xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision 1cf9b2375b21bbd252d6a780c47a40d91538aeab)
1*1cf9b237SStefano Zampini #include <../src/mat/impls/aij/seq/aij.h>
2ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddc.h>
3ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddcprivate.h>
4674ae819SStefano Zampini #include <petscblaslapack.h>
5674ae819SStefano Zampini 
6906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMultTranspose_Private(Mat A, Vec x, Vec y);
7906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMult_Private(Mat A, Vec x, Vec y);
8906d46d4SStefano Zampini 
9*1cf9b237SStefano Zampini /* TODO: add reuse flag */
10*1cf9b237SStefano Zampini #undef __FUNCT__
11*1cf9b237SStefano Zampini #define __FUNCT__ "MatSeqAIJCompress"
12*1cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
13*1cf9b237SStefano Zampini {
14*1cf9b237SStefano Zampini   Mat            Bt;
15*1cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
16*1cf9b237SStefano Zampini   const PetscInt *ii,*ij;
17*1cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
18*1cf9b237SStefano Zampini   PetscBool      flg_row;
19*1cf9b237SStefano Zampini   PetscErrorCode ierr;
20*1cf9b237SStefano Zampini 
21*1cf9b237SStefano Zampini   PetscFunctionBegin;
22*1cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
23*1cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
24*1cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
25*1cf9b237SStefano Zampini   nnz = n;
26*1cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
27*1cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
28*1cf9b237SStefano Zampini   }
29*1cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
30*1cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
31*1cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
32*1cf9b237SStefano Zampini   nnz = 0;
33*1cf9b237SStefano Zampini   bii[0] = 0;
34*1cf9b237SStefano Zampini   for (i=0;i<n;i++) {
35*1cf9b237SStefano Zampini     PetscInt j;
36*1cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
37*1cf9b237SStefano Zampini       PetscScalar entry = a[j];
38*1cf9b237SStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || ij[j] == i) {
39*1cf9b237SStefano Zampini         bij[nnz] = ij[j];
40*1cf9b237SStefano Zampini         bdata[nnz] = entry;
41*1cf9b237SStefano Zampini         nnz++;
42*1cf9b237SStefano Zampini       }
43*1cf9b237SStefano Zampini     }
44*1cf9b237SStefano Zampini     bii[i+1] = nnz;
45*1cf9b237SStefano Zampini   }
46*1cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
47*1cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
48*1cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
49*1cf9b237SStefano Zampini   {
50*1cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
51*1cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
52*1cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
53*1cf9b237SStefano Zampini   }
54*1cf9b237SStefano Zampini   *B = Bt;
55*1cf9b237SStefano Zampini   PetscFunctionReturn(0);
56*1cf9b237SStefano Zampini }
57*1cf9b237SStefano Zampini 
58674ae819SStefano Zampini #undef __FUNCT__
594f1b2e48SStefano Zampini #define __FUNCT__ "MatDetectDisconnectedComponents"
604f1b2e48SStefano Zampini PetscErrorCode MatDetectDisconnectedComponents(Mat A, PetscBool filter, PetscInt *ncc, IS* cc[])
614f1b2e48SStefano Zampini {
624f1b2e48SStefano Zampini   Mat                    B;
634f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
644f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
654f1b2e48SStefano Zampini   PCBDDCGraph            graph;
664f1b2e48SStefano Zampini   PetscInt               i,n;
674f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
684f1b2e48SStefano Zampini   PetscInt               *xadj_filtered,*adjncy_filtered;
694f1b2e48SStefano Zampini   PetscBool              flg_row,isseqaij;
704f1b2e48SStefano Zampini   PetscErrorCode         ierr;
714f1b2e48SStefano Zampini 
724f1b2e48SStefano Zampini   PetscFunctionBegin;
734f1b2e48SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
744f1b2e48SStefano Zampini   if (!isseqaij && filter) {
75*1cf9b237SStefano Zampini     PetscBool isseqdense;
76*1cf9b237SStefano Zampini 
77*1cf9b237SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
78*1cf9b237SStefano Zampini     if (!isseqdense) {
794f1b2e48SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
80*1cf9b237SStefano Zampini     } else { /* TODO: rectangular case and LDA */
81*1cf9b237SStefano Zampini       PetscScalar *array;
82*1cf9b237SStefano Zampini       PetscReal   chop=1.e-6;
83*1cf9b237SStefano Zampini 
84*1cf9b237SStefano Zampini       ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
85*1cf9b237SStefano Zampini       ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
86*1cf9b237SStefano Zampini       ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
87*1cf9b237SStefano Zampini       for (i=0;i<n;i++) {
88*1cf9b237SStefano Zampini         PetscInt j;
89*1cf9b237SStefano Zampini         for (j=i+1;j<n;j++) {
90*1cf9b237SStefano Zampini           PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
91*1cf9b237SStefano Zampini           if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
92*1cf9b237SStefano Zampini           if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
93*1cf9b237SStefano Zampini         }
94*1cf9b237SStefano Zampini       }
95*1cf9b237SStefano Zampini       ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
96*1cf9b237SStefano Zampini       ierr = MatConvert(B,MATSEQAIJ,MAT_REUSE_MATRIX,&B);CHKERRQ(ierr);
97*1cf9b237SStefano Zampini     }
984f1b2e48SStefano Zampini   } else {
994f1b2e48SStefano Zampini     B = A;
1004f1b2e48SStefano Zampini   }
1014f1b2e48SStefano Zampini   ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
1024f1b2e48SStefano Zampini 
1034f1b2e48SStefano Zampini   /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
1044f1b2e48SStefano Zampini   if (filter) {
1054f1b2e48SStefano Zampini     PetscScalar *data;
1064f1b2e48SStefano Zampini     PetscInt    j,cum;
1074f1b2e48SStefano Zampini 
1084f1b2e48SStefano Zampini     ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
1094f1b2e48SStefano Zampini     ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
1104f1b2e48SStefano Zampini     cum = 0;
1114f1b2e48SStefano Zampini     for (i=0;i<n;i++) {
1124f1b2e48SStefano Zampini       PetscInt t;
1134f1b2e48SStefano Zampini 
1144f1b2e48SStefano Zampini       for (j=xadj[i];j<xadj[i+1];j++) {
1154f1b2e48SStefano Zampini         if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
1164f1b2e48SStefano Zampini           continue;
1174f1b2e48SStefano Zampini         }
1184f1b2e48SStefano Zampini         adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
1194f1b2e48SStefano Zampini       }
1204f1b2e48SStefano Zampini       t = xadj_filtered[i];
1214f1b2e48SStefano Zampini       xadj_filtered[i] = cum;
1224f1b2e48SStefano Zampini       cum += t;
1234f1b2e48SStefano Zampini     }
1244f1b2e48SStefano Zampini     ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
1254f1b2e48SStefano Zampini   } else {
1264f1b2e48SStefano Zampini     xadj_filtered = NULL;
1274f1b2e48SStefano Zampini     adjncy_filtered = NULL;
1284f1b2e48SStefano Zampini   }
1294f1b2e48SStefano Zampini 
1304f1b2e48SStefano Zampini   /* compute local connected components using PCBDDCGraph */
1314f1b2e48SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
1324f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
1334f1b2e48SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
1344f1b2e48SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
1354f1b2e48SStefano Zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n);CHKERRQ(ierr);
1364f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
1374f1b2e48SStefano Zampini   if (xadj_filtered) {
1384f1b2e48SStefano Zampini     graph->xadj = xadj_filtered;
1394f1b2e48SStefano Zampini     graph->adjncy = adjncy_filtered;
1404f1b2e48SStefano Zampini   } else {
1414f1b2e48SStefano Zampini     graph->xadj = xadj;
1424f1b2e48SStefano Zampini     graph->adjncy = adjncy;
1434f1b2e48SStefano Zampini   }
1444f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
1454f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
1464f1b2e48SStefano Zampini 
1474f1b2e48SStefano Zampini   /* partial clean up */
1484f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
1494f1b2e48SStefano Zampini   ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
150*1cf9b237SStefano Zampini   if (A != B) {
1514f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
1524f1b2e48SStefano Zampini   }
1534f1b2e48SStefano Zampini 
1544f1b2e48SStefano Zampini   /* get back data */
155*1cf9b237SStefano Zampini   if (ncc) *ncc = graph->ncc;
156*1cf9b237SStefano Zampini   if (cc) {
1574f1b2e48SStefano Zampini     ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
1584f1b2e48SStefano Zampini     for (i=0;i<graph->ncc;i++) {
1594f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,graph->cptr[i+1]-graph->cptr[i],graph->queue+graph->cptr[i],PETSC_COPY_VALUES,&cc_n[i]);CHKERRQ(ierr);
1604f1b2e48SStefano Zampini     }
1614f1b2e48SStefano Zampini     *cc = cc_n;
162*1cf9b237SStefano Zampini   }
1634f1b2e48SStefano Zampini   /* clean up graph */
1644f1b2e48SStefano Zampini   graph->xadj = 0;
1654f1b2e48SStefano Zampini   graph->adjncy = 0;
1664f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
1674f1b2e48SStefano Zampini   PetscFunctionReturn(0);
1684f1b2e48SStefano Zampini }
1694f1b2e48SStefano Zampini 
1704f1b2e48SStefano Zampini #undef __FUNCT__
1715408967cSStefano Zampini #define __FUNCT__ "PCBDDCBenignCheck"
1725408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
1735408967cSStefano Zampini {
1745408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
1755408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
176dee84bffSStefano Zampini   IS             dirIS = NULL;
1774f1b2e48SStefano Zampini   PetscInt       i;
1785408967cSStefano Zampini   PetscErrorCode ierr;
1795408967cSStefano Zampini 
1805408967cSStefano Zampini   PetscFunctionBegin;
181dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
1825408967cSStefano Zampini   if (zerodiag) {
1835408967cSStefano Zampini     Mat            A;
1845408967cSStefano Zampini     Vec            vec3_N;
1855408967cSStefano Zampini     PetscScalar    *vals;
1865408967cSStefano Zampini     const PetscInt *idxs;
1874f1b2e48SStefano Zampini     PetscInt       nz;
1885408967cSStefano Zampini 
1895408967cSStefano Zampini     /* p0 */
1905408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
1915408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
1925408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
1935408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
1944f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
1955408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1965408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
1975408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
1985408967cSStefano Zampini     /* v_I */
1995408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
2005408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
2015408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
2025408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
2035408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
2045408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
2055408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
2065408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
2075408967cSStefano Zampini     if (dirIS) {
2085408967cSStefano Zampini       PetscInt n;
2095408967cSStefano Zampini 
2105408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
2115408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
2125408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
2135408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
2145408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
2155408967cSStefano Zampini     }
2165408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
2175408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
2185408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
2195408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
2205408967cSStefano Zampini     ierr = MatISGetLocalMat(pc->mat,&A);CHKERRQ(ierr);
2215408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
2225408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
2234f1b2e48SStefano Zampini     if (PetscAbsScalar(vals[0]) > PETSC_SMALL) {
2245408967cSStefano 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]));
2255408967cSStefano Zampini     }
2265408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
2275408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
2285408967cSStefano Zampini   }
229dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
2305408967cSStefano Zampini 
2315408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
2325408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
2334f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
2345408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
2354f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
2365408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
2374f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
2384f1b2e48SStefano Zampini     if ((PetscInt)PetscRealPart(pcbddc->benign_p0[i]) != -PetscGlobalRank-i) {
2394f1b2e48SStefano Zampini       SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error testing PCBDDCBenignGetOrSetP0! Found %1.4e at %d instead of %1.4e\n",pcbddc->benign_p0[i],i,-PetscGlobalRank-i);CHKERRQ(ierr);
2404f1b2e48SStefano Zampini     }
2415408967cSStefano Zampini   }
2425408967cSStefano Zampini   PetscFunctionReturn(0);
2435408967cSStefano Zampini }
2445408967cSStefano Zampini 
2455408967cSStefano Zampini #undef __FUNCT__
246339f8db1SStefano Zampini #define __FUNCT__ "PCBDDCBenignDetectSaddlePoint"
247339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
248339f8db1SStefano Zampini {
249339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2504f1b2e48SStefano Zampini   IS             pressures,zerodiag,*zerodiag_subs;
251b0f5fe93SStefano Zampini   PetscInt       nz,n;
2524f1b2e48SStefano Zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag;
253339f8db1SStefano Zampini   PetscErrorCode ierr;
254339f8db1SStefano Zampini 
255339f8db1SStefano Zampini   PetscFunctionBegin;
256339f8db1SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
257339f8db1SStefano Zampini   ierr = PetscObjectReference((PetscObject)pcbddc->local_mat);CHKERRQ(ierr);
258339f8db1SStefano Zampini   pcbddc->benign_original_mat = pcbddc->local_mat;
2594f1b2e48SStefano Zampini   /* if a local info on dofs is present, assumes the last field is represented by "pressures"
2604f1b2e48SStefano Zampini      otherwise, it uses only zerodiagonal dofs (ok if the pressure block is all zero; it could fail if it is not)
2614f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
2624f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
2634f1b2e48SStefano Zampini      since the local Schur complements are SPD
2644f1b2e48SStefano Zampini   */
2654f1b2e48SStefano Zampini   has_null_pressures = PETSC_TRUE;
2664f1b2e48SStefano Zampini   have_null = PETSC_TRUE;
26740fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
2684f1b2e48SStefano Zampini     PetscInt npl,*idxs,p = pcbddc->n_ISForDofsLocal-1;
2694f1b2e48SStefano Zampini 
2704f1b2e48SStefano Zampini     /* Dofs splitting for BDDC cannot have PETSC_COMM_SELF, so create a sequential IS */
2714f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[p],&npl);CHKERRQ(ierr);
2724f1b2e48SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
2734f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,npl,idxs,PETSC_COPY_VALUES,&pressures);CHKERRQ(ierr);
274ba14f8e3SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
27540fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
27640fa8d13SStefano Zampini     if (!sorted) {
27740fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
27840fa8d13SStefano Zampini     }
27940fa8d13SStefano Zampini   } else {
28040fa8d13SStefano Zampini     pressures = NULL;
28140fa8d13SStefano Zampini   }
2824f1b2e48SStefano Zampini   ierr = MatGetLocalSize(pcbddc->benign_original_mat,&n,NULL);CHKERRQ(ierr);
2834f1b2e48SStefano Zampini   /* TODO: add check for shared dofs and raise error */
284339f8db1SStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->benign_original_mat,&zerodiag);CHKERRQ(ierr);
285339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
286339f8db1SStefano Zampini   if (!sorted) {
287339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
288339f8db1SStefano Zampini   }
289339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
2904f1b2e48SStefano Zampini   if (!nz) {
2914f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
2924f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
29340fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
29440fa8d13SStefano Zampini   }
2954f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
2964f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
2974f1b2e48SStefano Zampini   zerodiag_subs = NULL;
2984f1b2e48SStefano Zampini   pcbddc->benign_n = 0;
2994f1b2e48SStefano Zampini   if (has_null_pressures) {
3004f1b2e48SStefano Zampini     IS       *subs;
3014f1b2e48SStefano Zampini     PetscInt nsubs,i;
3024f1b2e48SStefano Zampini 
3034f1b2e48SStefano Zampini     subs = pcbddc->local_subs;
3044f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
3054f1b2e48SStefano Zampini     if (nsubs > 1) {
3064f1b2e48SStefano Zampini       ierr = PetscCalloc1(nsubs,&zerodiag_subs);CHKERRQ(ierr);
3074f1b2e48SStefano Zampini       for (i=0;i<nsubs;i++) {
3084f1b2e48SStefano Zampini         ISLocalToGlobalMapping l2g;
3094f1b2e48SStefano Zampini         IS                     t_zerodiag_subs;
3104f1b2e48SStefano Zampini         PetscInt               nl;
3114f1b2e48SStefano Zampini 
3124f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
3134f1b2e48SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,zerodiag,&t_zerodiag_subs);CHKERRQ(ierr);
3144f1b2e48SStefano Zampini         ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
3154f1b2e48SStefano Zampini         if (nl) {
3164f1b2e48SStefano Zampini           PetscBool valid = PETSC_TRUE;
3174f1b2e48SStefano Zampini 
3184f1b2e48SStefano Zampini           if (pressures) {
3194f1b2e48SStefano Zampini             IS t_pressure_subs;
3204f1b2e48SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
3214f1b2e48SStefano Zampini             ierr = ISEqual(t_pressure_subs,t_zerodiag_subs,&valid);CHKERRQ(ierr);
3224f1b2e48SStefano Zampini             ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
3234f1b2e48SStefano Zampini           }
3244f1b2e48SStefano Zampini           if (valid) {
3254f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[pcbddc->benign_n]);CHKERRQ(ierr);
3264f1b2e48SStefano Zampini             pcbddc->benign_n++;
3274f1b2e48SStefano Zampini           } else {
3284f1b2e48SStefano Zampini             recompute_zerodiag = PETSC_TRUE;
3294f1b2e48SStefano Zampini           }
3304f1b2e48SStefano Zampini         }
3314f1b2e48SStefano Zampini         ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
3324f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
3334f1b2e48SStefano Zampini       }
3344f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
3354f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
3364f1b2e48SStefano Zampini       if (pressures) {
3374f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
3384f1b2e48SStefano Zampini       }
3394f1b2e48SStefano Zampini       if (valid) {
3404f1b2e48SStefano Zampini         pcbddc->benign_n = 1;
3414f1b2e48SStefano Zampini         ierr = PetscCalloc1(1,&zerodiag_subs);CHKERRQ(ierr);
3424f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
3434f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
3444f1b2e48SStefano Zampini       }
3454f1b2e48SStefano Zampini     }
3464f1b2e48SStefano Zampini   }
3474f1b2e48SStefano Zampini 
3484f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
3494f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
3504f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
3514f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
3524f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
3534f1b2e48SStefano Zampini   }
3544f1b2e48SStefano Zampini 
3554f1b2e48SStefano Zampini   /* final check for null pressures */
3564f1b2e48SStefano Zampini   if (zerodiag && pressures) {
3574f1b2e48SStefano Zampini     PetscInt nz,np;
3584f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
3594f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
3604f1b2e48SStefano Zampini     if (nz != np) have_null = PETSC_FALSE;
3614f1b2e48SStefano Zampini   }
3624f1b2e48SStefano Zampini 
3634f1b2e48SStefano Zampini   if (recompute_zerodiag) {
3644f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
3654f1b2e48SStefano Zampini     if (pcbddc->benign_n == 1) {
3664f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
3674f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
3684f1b2e48SStefano Zampini     } else {
3694f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
3704f1b2e48SStefano Zampini 
3714f1b2e48SStefano Zampini       nzn = 0;
3724f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
3734f1b2e48SStefano Zampini         PetscInt ns;
3744f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
3754f1b2e48SStefano Zampini         nzn += ns;
3764f1b2e48SStefano Zampini       }
3774f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
3784f1b2e48SStefano Zampini       nzn = 0;
3794f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
3804f1b2e48SStefano Zampini         PetscInt ns,*idxs;
3814f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
3824f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
3834f1b2e48SStefano Zampini         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
3844f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
3854f1b2e48SStefano Zampini         nzn += ns;
3864f1b2e48SStefano Zampini       }
3874f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
3884f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
3894f1b2e48SStefano Zampini     }
3904f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
3914f1b2e48SStefano Zampini   }
3924f1b2e48SStefano Zampini 
3934f1b2e48SStefano Zampini   if (has_null_pressures) {
3944f1b2e48SStefano Zampini     IS             zerodiagc;
3954f1b2e48SStefano Zampini     const PetscInt *idxs,*idxsc;
3964f1b2e48SStefano Zampini     PetscInt       i,s,*nnz;
397*1cf9b237SStefano Zampini     Mat            M;
3984f1b2e48SStefano Zampini 
3994f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
400339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
401339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
402339f8db1SStefano Zampini     /* local change of basis for pressures */
403339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
404339f8db1SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->benign_original_mat),&pcbddc->benign_change);CHKERRQ(ierr);
405339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
406339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
407339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
4084f1b2e48SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities plus pressure dofs for non-singular subdomains */
4094f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
4104f1b2e48SStefano Zampini       PetscInt nzs,j;
4114f1b2e48SStefano Zampini 
4124f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[i],&nzs);CHKERRQ(ierr);
4134f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
4144f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
4154f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
4164f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
4174f1b2e48SStefano Zampini     }
418339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
419339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
420339f8db1SStefano Zampini     /* set identity on velocities */
421339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
422339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
423339f8db1SStefano Zampini     }
4244f1b2e48SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
4254f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
4264f1b2e48SStefano Zampini     ierr = PetscMalloc3(pcbddc->benign_n,&pcbddc->benign_p0_lidx,pcbddc->benign_n,&pcbddc->benign_p0_gidx,pcbddc->benign_n,&pcbddc->benign_p0);CHKERRQ(ierr);
427339f8db1SStefano Zampini     /* set change on pressures */
4284f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
4294f1b2e48SStefano Zampini       PetscScalar *array;
4304f1b2e48SStefano Zampini       PetscInt    nzs;
4314f1b2e48SStefano Zampini 
4324f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[s],&nzs);CHKERRQ(ierr);
4334f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
4344f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
435339f8db1SStefano Zampini         PetscScalar vals[2];
436339f8db1SStefano Zampini         PetscInt    cols[2];
437339f8db1SStefano Zampini 
438339f8db1SStefano Zampini         cols[0] = idxs[i];
4394f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
440339f8db1SStefano Zampini         vals[0] = 1.;
441b0f5fe93SStefano Zampini         vals[1] = 1.;
4424f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
443339f8db1SStefano Zampini       }
4444f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
4454f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
4464f1b2e48SStefano Zampini       array[nzs-1] = 1.;
4474f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
4484f1b2e48SStefano Zampini       /* store local idxs for p0 */
4494f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
4504f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
4514f1b2e48SStefano Zampini       ierr = ISDestroy(&zerodiag_subs[s]);CHKERRQ(ierr);
452339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
4534f1b2e48SStefano Zampini     }
454339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
455339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
456339f8db1SStefano Zampini     /* TODO: need optimization? */
457339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
458*1cf9b237SStefano Zampini     ierr = MatPtAP(pcbddc->benign_original_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
459*1cf9b237SStefano Zampini     ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
460*1cf9b237SStefano Zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
4614f1b2e48SStefano Zampini     /* store global idxs for p0 */
4624f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
463339f8db1SStefano Zampini   }
4644f1b2e48SStefano Zampini   ierr = PetscFree(zerodiag_subs);CHKERRQ(ierr);
4654f1b2e48SStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
466b0f5fe93SStefano Zampini 
467b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
468b0f5fe93SStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
469339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
470339f8db1SStefano Zampini   PetscFunctionReturn(0);
471339f8db1SStefano Zampini }
472339f8db1SStefano Zampini 
473339f8db1SStefano Zampini #undef __FUNCT__
474015636ebSStefano Zampini #define __FUNCT__ "PCBDDCBenignGetOrSetP0"
475015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
476efc2fbd9SStefano Zampini {
477efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
478efc2fbd9SStefano Zampini   PetscErrorCode ierr;
479efc2fbd9SStefano Zampini 
480efc2fbd9SStefano Zampini   PetscFunctionBegin;
481efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
482efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
4834f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
484efc2fbd9SStefano Zampini   }
485015636ebSStefano Zampini   if (get) { /* use SF to get values */
486efc2fbd9SStefano Zampini     PetscScalar *array;
487efc2fbd9SStefano Zampini 
488efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
4894f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
4904f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
491efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
4924f1b2e48SStefano Zampini   } else { /* use VecSetValues (not scalable, I should try to find a better solution (defining a new MPI_OP for reduction) */
4934f1b2e48SStefano Zampini     ierr = VecSetValues(v,pcbddc->benign_n,pcbddc->benign_p0_gidx,pcbddc->benign_p0,INSERT_VALUES);CHKERRQ(ierr);
494efc2fbd9SStefano Zampini     ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
495efc2fbd9SStefano Zampini     ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
496efc2fbd9SStefano Zampini   }
497efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
498efc2fbd9SStefano Zampini }
499efc2fbd9SStefano Zampini 
500efc2fbd9SStefano Zampini #undef __FUNCT__
501c263805aSStefano Zampini #define __FUNCT__ "PCBDDCBenignPopOrPushB0"
502c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
503c263805aSStefano Zampini {
504c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
505c263805aSStefano Zampini   PetscErrorCode ierr;
506c263805aSStefano Zampini 
507c263805aSStefano Zampini   PetscFunctionBegin;
508c263805aSStefano Zampini   /* TODO: add error checking
509c263805aSStefano Zampini     - avoid nested pop (or push) calls.
510c263805aSStefano Zampini     - cannot push before pop.
5111c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
512c263805aSStefano Zampini   */
5134f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
514efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
515efc2fbd9SStefano Zampini   }
516c263805aSStefano Zampini   if (pop) {
5174f1b2e48SStefano Zampini     IS       is_p0;
5184f1b2e48SStefano Zampini     MatReuse reuse;
519c263805aSStefano Zampini 
520c263805aSStefano Zampini     /* extract B_0 */
5214f1b2e48SStefano Zampini     reuse = MAT_INITIAL_MATRIX;
5224f1b2e48SStefano Zampini     if (pcbddc->benign_B0) {
5234f1b2e48SStefano Zampini       reuse = MAT_REUSE_MATRIX;
5244f1b2e48SStefano Zampini     }
5254f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
5264f1b2e48SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
527c263805aSStefano Zampini     /* remove rows and cols from local problem */
528c263805aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
5294f1b2e48SStefano Zampini     ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
5304f1b2e48SStefano Zampini     ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
531c263805aSStefano Zampini   } else { /* push */
5324f1b2e48SStefano Zampini     PetscInt i;
5334f1b2e48SStefano Zampini 
5344f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
5354f1b2e48SStefano Zampini       PetscScalar *B0_vals;
5364f1b2e48SStefano Zampini       PetscInt    *B0_cols,B0_ncol;
5374f1b2e48SStefano Zampini 
5384f1b2e48SStefano Zampini       ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
5394f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
5404f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+1,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
5414f1b2e48SStefano Zampini       ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
5424f1b2e48SStefano Zampini       ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
5434f1b2e48SStefano Zampini     }
544c263805aSStefano Zampini     ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
545c263805aSStefano Zampini     ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
546c263805aSStefano Zampini   }
547c263805aSStefano Zampini   PetscFunctionReturn(0);
548c263805aSStefano Zampini }
549c263805aSStefano Zampini 
550c263805aSStefano Zampini #undef __FUNCT__
551b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
55208122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
553b1b3d7a2SStefano Zampini {
554b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
55508122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
55608122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
55708122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
55808122e43SStefano Zampini   PetscScalar     *work,lwork;
55908122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
56008122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
56108122e43SStefano Zampini   PetscReal       *eigs,thresh;
5621b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
563f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
56408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
56508122e43SStefano Zampini   PetscReal       *rwork;
56608122e43SStefano Zampini #endif
567b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
568b1b3d7a2SStefano Zampini 
569b1b3d7a2SStefano Zampini   PetscFunctionBegin;
57008122e43SStefano Zampini   if (!sub_schurs->use_mumps) {
57108122e43SStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS");
57208122e43SStefano Zampini   }
57308122e43SStefano Zampini 
57406a4e24aSStefano Zampini   if (sub_schurs->n_subs && (!sub_schurs->is_hermitian || !sub_schurs->is_posdef)) {
57506a4e24aSStefano 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);
57606a4e24aSStefano Zampini   }
57706a4e24aSStefano Zampini 
578fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
579fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
580fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
581fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
582fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
583fd14bc51SStefano Zampini   }
584fd14bc51SStefano Zampini 
585e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
586e496cd5dSStefano 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);
587e496cd5dSStefano Zampini   }
588e496cd5dSStefano Zampini 
58908122e43SStefano Zampini   /* max size of subsets */
59008122e43SStefano Zampini   mss = 0;
59108122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
59208122e43SStefano Zampini     PetscInt subset_size;
593862806e4SStefano Zampini 
59408122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
59508122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
59608122e43SStefano Zampini   }
59708122e43SStefano Zampini 
59808122e43SStefano Zampini   /* min/max and threshold */
59908122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
600f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
60108122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
602f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
603f6f667cfSStefano Zampini   if (nmin) {
604f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
605f6f667cfSStefano Zampini   }
60608122e43SStefano Zampini 
60708122e43SStefano Zampini   /* allocate lapack workspace */
60808122e43SStefano Zampini   cum = cum2 = 0;
60908122e43SStefano Zampini   maxneigs = 0;
61008122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
61108122e43SStefano Zampini     PetscInt n,subset_size;
612f6f667cfSStefano Zampini 
61308122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
61408122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
6159162d606SStefano Zampini     cum += subset_size;
6169162d606SStefano Zampini     cum2 += subset_size*n;
61708122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
61808122e43SStefano Zampini   }
61908122e43SStefano Zampini   if (mss) {
6209ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
62108122e43SStefano Zampini       PetscBLASInt B_itype = 1;
62208122e43SStefano Zampini       PetscBLASInt B_N = mss;
6234c6709b3SStefano Zampini       PetscReal    zero = 0.0;
6244c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
62508122e43SStefano Zampini 
62608122e43SStefano Zampini       B_lwork = -1;
62708122e43SStefano Zampini       S = NULL;
62808122e43SStefano Zampini       St = NULL;
629a58a30b4SStefano Zampini       eigs = NULL;
630a58a30b4SStefano Zampini       eigv = NULL;
631a58a30b4SStefano Zampini       B_iwork = NULL;
632a58a30b4SStefano Zampini       B_ifail = NULL;
633d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
634d1710679SStefano Zampini       rwork = NULL;
635d1710679SStefano Zampini #endif
6368bec7fa6SStefano Zampini       thresh = 1.0;
63708122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
63808122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
63908122e43SStefano 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));
64008122e43SStefano Zampini #else
64108122e43SStefano 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));
64208122e43SStefano Zampini #endif
64308122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
64408122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
64508122e43SStefano Zampini     } else {
64608122e43SStefano Zampini         /* TODO */
64708122e43SStefano Zampini     }
64808122e43SStefano Zampini   } else {
64908122e43SStefano Zampini     lwork = 0;
65008122e43SStefano Zampini   }
65108122e43SStefano Zampini 
65208122e43SStefano Zampini   nv = 0;
653d62866d3SStefano 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) */
654d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
65508122e43SStefano Zampini   }
6564c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
657f6f667cfSStefano Zampini   if (allocated_S_St) {
658f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
659f6f667cfSStefano Zampini   }
660f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
66108122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
66208122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
66308122e43SStefano Zampini #endif
6649162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
6659162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
6669162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
66708122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
6689162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
66908122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
67008122e43SStefano Zampini 
67108122e43SStefano Zampini   maxneigs = 0;
67208122e43SStefano Zampini   cum = cum2 = cumarray = 0;
6739162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
6749162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
675d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
67608122e43SStefano Zampini     const PetscInt *idxs;
67708122e43SStefano Zampini 
678d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
67908122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
68008122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
68108122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
68208122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
6839162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
6849162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
68508122e43SStefano Zampini     }
68608122e43SStefano Zampini     cum2 = cum;
687d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
68808122e43SStefano Zampini   }
68908122e43SStefano Zampini 
69008122e43SStefano Zampini   if (mss) { /* multilevel */
69108122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
69208122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
69308122e43SStefano Zampini   }
69408122e43SStefano Zampini 
69508122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
69608122e43SStefano Zampini 
69708122e43SStefano Zampini     const PetscInt *idxs;
698f6f667cfSStefano Zampini     PetscReal      infty = PETSC_MAX_REAL;
699862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
70008122e43SStefano Zampini     PetscBLASInt   B_N;
701aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
70208122e43SStefano Zampini 
703862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
704f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
705f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
7069ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
707aff50787SStefano Zampini         PetscInt j,k;
708aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
709aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
710aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
71108122e43SStefano Zampini         }
71208122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
713aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
714aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
715aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
716aff50787SStefano Zampini           }
71708122e43SStefano Zampini         }
71808122e43SStefano Zampini       } else {
71908122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
72008122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
72108122e43SStefano Zampini       }
7228bec7fa6SStefano Zampini     } else {
723f6f667cfSStefano Zampini       S = Sarray + cumarray;
724f6f667cfSStefano Zampini       St = Starray + cumarray;
7258bec7fa6SStefano Zampini     }
72608122e43SStefano Zampini 
727f6f667cfSStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
728aff50787SStefano Zampini     /* see if we can save some work */
729aff50787SStefano Zampini     if (sub_schurs->n_subs == 1) {
730aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
731aff50787SStefano Zampini     }
732aff50787SStefano Zampini 
733aff50787SStefano Zampini     if (same_data) { /* there's no need of constraints here, deluxe scaling is enough */
734aff50787SStefano Zampini       B_neigs = 0;
735aff50787SStefano Zampini     } else {
736aff50787SStefano Zampini       /* Threshold: this is an heuristic for edges */
737f6f667cfSStefano Zampini       thresh = pcbddc->mat_graph->count[idxs[0]]*pcbddc->adaptive_threshold;
738*1cf9b237SStefano Zampini       if (nmin) {
739*1cf9b237SStefano Zampini         Mat SM,StM;
740*1cf9b237SStefano Zampini         PetscInt j,k,nccs,nccst;
741*1cf9b237SStefano Zampini 
742*1cf9b237SStefano Zampini         for (j=0;j<subset_size;j++) {
743*1cf9b237SStefano Zampini           for (k=j;k<subset_size;k++) {
744*1cf9b237SStefano Zampini             S [k*subset_size+j] = S [j*subset_size+k];
745*1cf9b237SStefano Zampini             St[k*subset_size+j] = St[j*subset_size+k];
746*1cf9b237SStefano Zampini           }
747*1cf9b237SStefano Zampini         }
748*1cf9b237SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,subset_size,S,&SM);CHKERRQ(ierr);
749*1cf9b237SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,subset_size,St,&StM);CHKERRQ(ierr);
750*1cf9b237SStefano Zampini         ierr = MatDetectDisconnectedComponents(SM,PETSC_TRUE,&nccs,NULL);CHKERRQ(ierr);
751*1cf9b237SStefano Zampini         ierr = MatDetectDisconnectedComponents(StM,PETSC_TRUE,&nccst,NULL);CHKERRQ(ierr);
752*1cf9b237SStefano Zampini         if (nccs != 1 || nccst != 1) {
753*1cf9b237SStefano Zampini           PetscPrintf(PETSC_COMM_SELF,"[%d] Found disc %d %d (size %d)\n",PetscGlobalRank,nccs,nccst,subset_size);
754*1cf9b237SStefano Zampini         }
755*1cf9b237SStefano Zampini         ierr = MatDestroy(&SM);CHKERRQ(ierr);
756*1cf9b237SStefano Zampini         ierr = MatDestroy(&StM);CHKERRQ(ierr);
757*1cf9b237SStefano Zampini       }
758f6f667cfSStefano Zampini 
7599ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
76008122e43SStefano Zampini         PetscBLASInt B_itype = 1;
761f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
7624c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
7639552c7c7SStefano Zampini         PetscInt     nmin_s;
76408122e43SStefano Zampini 
765fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
7668bec7fa6SStefano 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]]);
767fd14bc51SStefano Zampini         }
768d16cbb6bSStefano Zampini 
76908122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
770d16cbb6bSStefano Zampini         if (thresh > 1.+PETSC_SMALL) {
771d16cbb6bSStefano Zampini 
772d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
77308122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
774f6f667cfSStefano 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));
77508122e43SStefano Zampini #else
776f6f667cfSStefano 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));
77708122e43SStefano Zampini #endif
778d16cbb6bSStefano Zampini         } else {
779d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
780d16cbb6bSStefano Zampini           B_IL = 1;
781d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
782d16cbb6bSStefano 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));
783d16cbb6bSStefano Zampini #else
784d16cbb6bSStefano 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));
785d16cbb6bSStefano Zampini #endif
786d16cbb6bSStefano Zampini         }
78708122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
78808122e43SStefano Zampini         if (B_ierr) {
78908122e43SStefano Zampini           if (B_ierr < 0 ) {
79008122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
79108122e43SStefano Zampini           } else if (B_ierr <= B_N) {
79208122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
79308122e43SStefano Zampini           } else {
7949552c7c7SStefano 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);
79508122e43SStefano Zampini           }
79608122e43SStefano Zampini         }
79708122e43SStefano Zampini 
79808122e43SStefano Zampini         if (B_neigs > nmax) {
799fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
800fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
801fd14bc51SStefano Zampini           }
802f6f667cfSStefano Zampini           eigs_start = B_neigs -nmax;
80308122e43SStefano Zampini           B_neigs = nmax;
80408122e43SStefano Zampini         }
80508122e43SStefano Zampini 
8069552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
8079552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
80808122e43SStefano Zampini           PetscBLASInt B_neigs2;
80908122e43SStefano Zampini 
810f6f667cfSStefano Zampini           B_IU = B_N - B_neigs;
811f6f667cfSStefano Zampini           B_IL = B_N - nmin_s + 1;
812fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
813fd14bc51SStefano 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);
814fd14bc51SStefano Zampini           }
8159ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
81608122e43SStefano Zampini             PetscInt j;
81708122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
81808122e43SStefano Zampini               ierr = PetscMemcpy(S+j*(subset_size+1),Sarray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
81908122e43SStefano Zampini             }
82008122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
82108122e43SStefano Zampini               ierr = PetscMemcpy(St+j*(subset_size+1),Starray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
82208122e43SStefano Zampini             }
82308122e43SStefano Zampini           } else {
82408122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
82508122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
82608122e43SStefano Zampini           }
82708122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
82808122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
829f6f667cfSStefano 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));
83008122e43SStefano Zampini #else
831f6f667cfSStefano 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));
83208122e43SStefano Zampini #endif
83308122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
83408122e43SStefano Zampini           B_neigs += B_neigs2;
83508122e43SStefano Zampini         }
83608122e43SStefano Zampini         if (B_ierr) {
83708122e43SStefano Zampini           if (B_ierr < 0 ) {
83808122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
83908122e43SStefano Zampini           } else if (B_ierr <= B_N) {
84008122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
84108122e43SStefano Zampini           } else {
8429552c7c7SStefano 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);
84308122e43SStefano Zampini           }
84408122e43SStefano Zampini         }
845fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
846ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
84708122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
84808122e43SStefano Zampini             if (eigs[j] == 0.0) {
849ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
85008122e43SStefano Zampini             } else {
851ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
852fd14bc51SStefano Zampini             }
85308122e43SStefano Zampini           }
85408122e43SStefano Zampini         }
85508122e43SStefano Zampini       } else {
85608122e43SStefano Zampini           /* TODO */
85708122e43SStefano Zampini       }
858aff50787SStefano Zampini     }
8598bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
8608bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
8619162d606SStefano Zampini     if (B_neigs) {
8629162d606SStefano 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);
863fd14bc51SStefano Zampini 
864fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
8659552c7c7SStefano Zampini         PetscInt ii;
8669552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
867ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
8689552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
869ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
870ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
871ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
872ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
873ac47001eSStefano Zampini #else
874ac47001eSStefano 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);
875ac47001eSStefano Zampini #endif
8769552c7c7SStefano Zampini           }
8779552c7c7SStefano Zampini         }
878fd14bc51SStefano Zampini       }
87908122e43SStefano Zampini #if 0
8809162d606SStefano Zampini       for (j=0;j<B_neigs;j++) {
88108122e43SStefano Zampini         PetscBLASInt Blas_N,Blas_one = 1.0;
88208122e43SStefano Zampini         PetscScalar norm;
88308122e43SStefano Zampini         ierr = PetscBLASIntCast(subset_size,&Blas_N);CHKERRQ(ierr);
8849162d606SStefano Zampini         PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,
8859162d606SStefano Zampini                                                    &Blas_one,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,&Blas_one));
88608122e43SStefano Zampini         if (pcbddc->adaptive_constraints_data[cum2] > 0.0) {
88708122e43SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
88808122e43SStefano Zampini         } else {
88908122e43SStefano Zampini           norm = -1.0/PetscSqrtReal(PetscRealPart(norm));
89008122e43SStefano Zampini         }
8919162d606SStefano Zampini         PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,&Blas_one));
892b1b3d7a2SStefano Zampini       }
893b1b3d7a2SStefano Zampini #endif
8949162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
8959162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
8969162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
8979162d606SStefano Zampini       cum++;
89808122e43SStefano Zampini     }
89908122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
90008122e43SStefano Zampini     /* shift for next computation */
90108122e43SStefano Zampini     cumarray += subset_size*subset_size;
90208122e43SStefano Zampini   }
903fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
904fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
905fd14bc51SStefano Zampini   }
90608122e43SStefano Zampini 
90708122e43SStefano Zampini   if (mss) {
90808122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
90908122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
910f6f667cfSStefano Zampini     /* destroy matrices (junk) */
911f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
912f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
91308122e43SStefano Zampini   }
914f6f667cfSStefano Zampini   if (allocated_S_St) {
915f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
916f6f667cfSStefano Zampini   }
917f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
91808122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
91908122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
92008122e43SStefano Zampini #endif
92108122e43SStefano Zampini   if (pcbddc->dbg_flag) {
9221b968477SStefano Zampini     PetscInt maxneigs_r;
92308122e43SStefano Zampini     ierr = MPI_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
9249b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
92508122e43SStefano Zampini   }
92608122e43SStefano Zampini   PetscFunctionReturn(0);
92708122e43SStefano Zampini }
928b1b3d7a2SStefano Zampini 
929674ae819SStefano Zampini #undef __FUNCT__
930c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
931c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
932c8587f34SStefano Zampini {
933c8587f34SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
9348629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
935c8587f34SStefano Zampini   PetscErrorCode ierr;
936c8587f34SStefano Zampini 
937c8587f34SStefano Zampini   PetscFunctionBegin;
938f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
9395e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
940c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
941c8587f34SStefano Zampini 
942684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
9430fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
944684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
945c8587f34SStefano Zampini 
946c8587f34SStefano Zampini   /* Change global null space passed in by the user if change of basis has been requested */
947b9b85e73SStefano Zampini   if (pcbddc->NullSpace && pcbddc->ChangeOfBasisMatrix) {
948c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAdaptGlobal(pc);CHKERRQ(ierr);
949c8587f34SStefano Zampini   }
950c8587f34SStefano Zampini 
9518629588bSStefano Zampini   /*
9528629588bSStefano Zampini      Setup local correction and local part of coarse basis.
9538629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
9548629588bSStefano Zampini   */
95547f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
9568629588bSStefano Zampini 
9578629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
9588629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
9598629588bSStefano Zampini 
9608629588bSStefano Zampini   /* free */
9618629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
962c8587f34SStefano Zampini   PetscFunctionReturn(0);
963c8587f34SStefano Zampini }
964c8587f34SStefano Zampini 
965c8587f34SStefano Zampini #undef __FUNCT__
966674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
967674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
968674ae819SStefano Zampini {
969674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
970674ae819SStefano Zampini   PetscErrorCode ierr;
971674ae819SStefano Zampini 
972674ae819SStefano Zampini   PetscFunctionBegin;
973674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
974674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
975674ae819SStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
976674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
977785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
978674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
979f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
980f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
981785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
98263602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
98363602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
984674ae819SStefano Zampini   PetscFunctionReturn(0);
985674ae819SStefano Zampini }
986674ae819SStefano Zampini 
987674ae819SStefano Zampini #undef __FUNCT__
988674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
989674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
990674ae819SStefano Zampini {
991674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
9924f1b2e48SStefano Zampini   PetscInt       i;
993674ae819SStefano Zampini   PetscErrorCode ierr;
994674ae819SStefano Zampini 
995674ae819SStefano Zampini   PetscFunctionBegin;
996b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
997674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
998674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
999674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
10004f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
10014f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
10024f1b2e48SStefano Zampini   }
10034f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
1004b96c3477SStefano Zampini   ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
1005674ae819SStefano Zampini   PetscFunctionReturn(0);
1006674ae819SStefano Zampini }
1007674ae819SStefano Zampini 
1008674ae819SStefano Zampini #undef __FUNCT__
1009674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
1010674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
1011674ae819SStefano Zampini {
1012674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
101306656605SStefano Zampini   PetscScalar    *array;
1014674ae819SStefano Zampini   PetscErrorCode ierr;
1015674ae819SStefano Zampini 
1016674ae819SStefano Zampini   PetscFunctionBegin;
1017674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
101858da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
101906656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
102006656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
102158da7f69SStefano Zampini   }
1022674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1023674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
102415aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
102515aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
1026674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
1027674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
1028674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
102906656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
1030674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
1031674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
10328ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
1033674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
1034674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
1035674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
1036f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
1037f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
1038f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
1039f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
1040727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
10410e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
1042f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
104370cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
10446e683305SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
104581d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
10460369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
10478b9f24d4SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
10484f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
10494f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
10508b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
10514f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
1052674ae819SStefano Zampini   PetscFunctionReturn(0);
1053674ae819SStefano Zampini }
1054674ae819SStefano Zampini 
1055674ae819SStefano Zampini #undef __FUNCT__
1056f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
1057f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
10586bfb1811SStefano Zampini {
10596bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
10606bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
10616bfb1811SStefano Zampini   VecType        impVecType;
10624f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
10636bfb1811SStefano Zampini   PetscErrorCode ierr;
10646bfb1811SStefano Zampini 
10656bfb1811SStefano Zampini   PetscFunctionBegin;
1066f4ddd8eeSStefano Zampini   if (!pcbddc->ConstraintMatrix) {
1067019a44ceSStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
1068f4ddd8eeSStefano Zampini   }
1069e7b262bdSStefano Zampini   /* get sizes */
10704f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
1071b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
10726bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
1073e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
1074e7b262bdSStefano Zampini   /* R nodes */
1075e7b262bdSStefano Zampini   old_size = -1;
1076e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
1077e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
1078e7b262bdSStefano Zampini   }
1079e7b262bdSStefano Zampini   if (n_R != old_size) {
1080e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
1081e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
10826bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
10836bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
10846bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
10856bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
1086e7b262bdSStefano Zampini   }
1087e7b262bdSStefano Zampini   /* local primal dofs */
1088e7b262bdSStefano Zampini   old_size = -1;
1089e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
1090e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
1091e7b262bdSStefano Zampini   }
1092e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
1093e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
109483b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
1095e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
10966bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
1097e7b262bdSStefano Zampini   }
1098e7b262bdSStefano Zampini   /* local explicit constraints */
1099e7b262bdSStefano Zampini   old_size = -1;
1100e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
1101e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
1102e7b262bdSStefano Zampini   }
1103e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
1104e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
110583b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
110683b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
110783b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
110883b7ccabSStefano Zampini   }
11096bfb1811SStefano Zampini   PetscFunctionReturn(0);
11106bfb1811SStefano Zampini }
11116bfb1811SStefano Zampini 
11126bfb1811SStefano Zampini #undef __FUNCT__
111347f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
111447f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
111588ebb749SStefano Zampini {
111625084f0cSStefano Zampini   PetscErrorCode  ierr;
111725084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
111888ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
111988ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1120d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
112125084f0cSStefano Zampini   /* submatrices of local problem */
112280677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
1123019a44ceSStefano Zampini   /* submatrices of benign trick */
1124d16cbb6bSStefano Zampini   Mat             B0_V = NULL;
112506656605SStefano Zampini   /* submatrices of local coarse problem */
112606656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
112725084f0cSStefano Zampini   /* working matrices */
112806656605SStefano Zampini   Mat             C_CR;
112925084f0cSStefano Zampini   /* additional working stuff */
113006656605SStefano Zampini   PC              pc_R;
11314f1b2e48SStefano Zampini   Mat             F;
113206656605SStefano Zampini   PetscBool       isLU,isCHOL,isILU;
113306656605SStefano Zampini 
113425084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
113506656605SStefano Zampini   PetscScalar     *work;
113606656605SStefano Zampini   PetscInt        *idx_V_B;
11374f1b2e48SStefano Zampini   PetscInt        n,n_vertices,n_constraints,*p0_lidx_I;
113806656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
1139b9d89cd5SStefano Zampini   PetscBool       unsymmetric_check;
114045a1bb75SStefano Zampini   /* matrix type (vector type propagated downstream from vec1_C and local matrix type) */
114188ebb749SStefano Zampini   MatType         impMatType;
114225084f0cSStefano Zampini   /* some shortcuts to scalars */
114306656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
114488ebb749SStefano Zampini 
114588ebb749SStefano Zampini   PetscFunctionBegin;
1146b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
11474f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
114888ebb749SStefano Zampini   /* Set Non-overlapping dimensions */
1149b371cd4fSStefano Zampini   n_B = pcis->n_B;
1150b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
115188ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
115288ebb749SStefano Zampini 
115388ebb749SStefano Zampini   /* Set types for local objects needed by BDDC precondtioner */
115488ebb749SStefano Zampini   impMatType = MATSEQDENSE;
115588ebb749SStefano Zampini 
115688ebb749SStefano Zampini   /* vertices in boundary numbering */
1157785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
11580e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
115988ebb749SStefano Zampini   if (i != n_vertices) {
116022d5777bSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %d != %d\n",n_vertices,i);
116188ebb749SStefano Zampini   }
116288ebb749SStefano Zampini 
116306656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
1164019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
116506656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
116606656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
116706656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
116806656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
116906656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
117006656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
117106656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
117206656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
117306656605SStefano Zampini 
117406656605SStefano Zampini   unsymmetric_check = PETSC_FALSE;
117506656605SStefano Zampini   /* allocate workspace */
117606656605SStefano Zampini   n = 0;
117706656605SStefano Zampini   if (n_constraints) {
117806656605SStefano Zampini     n += n_R*n_constraints;
117906656605SStefano Zampini   }
118006656605SStefano Zampini   if (n_vertices) {
118106656605SStefano Zampini     n = PetscMax(2*n_R*n_vertices,n);
118280677318SStefano Zampini     n = PetscMax((n_R+n_B)*n_vertices,n);
118306656605SStefano Zampini   }
11843301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
118506656605SStefano Zampini     n = PetscMax(2*n_R*pcbddc->local_primal_size,n);
118606656605SStefano Zampini     unsymmetric_check = PETSC_TRUE;
118706656605SStefano Zampini   }
118806656605SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
118906656605SStefano Zampini 
119006656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
119106656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
119206656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
119306656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
119406656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
119506656605SStefano Zampini   if (isLU || isILU || isCHOL) {
119606656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
1197d62866d3SStefano Zampini   } else if (sub_schurs->reuse_mumps) {
1198d62866d3SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
1199d62866d3SStefano Zampini     MatFactorType type;
1200d62866d3SStefano Zampini 
12016816873aSStefano Zampini     F = reuse_mumps->F;
12026816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
1203d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
120406656605SStefano Zampini   } else {
120506656605SStefano Zampini     F = NULL;
120606656605SStefano Zampini   }
120706656605SStefano Zampini 
120888ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
120988ebb749SStefano Zampini   if (n_constraints) {
121006656605SStefano Zampini     Mat         M1,M2,M3;
121180677318SStefano Zampini     Mat         auxmat;
121206656605SStefano Zampini     IS          is_aux;
121380677318SStefano Zampini     PetscScalar *array,*array2;
121406656605SStefano Zampini 
1215f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
121680677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
121788ebb749SStefano Zampini 
121825084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
121925084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
12208ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
122180677318SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&auxmat);CHKERRQ(ierr);
122288ebb749SStefano Zampini 
122380677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
122480677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
122506656605SStefano Zampini     ierr = PetscMemzero(work,n_R*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
122688ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
122706656605SStefano Zampini       const PetscScalar *row_cmat_values;
122806656605SStefano Zampini       const PetscInt    *row_cmat_indices;
122906656605SStefano Zampini       PetscInt          size_of_constraint,j;
123088ebb749SStefano Zampini 
123106656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
123206656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
123306656605SStefano Zampini         work[row_cmat_indices[j]+i*n_R] = -row_cmat_values[j];
123406656605SStefano Zampini       }
123506656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
123606656605SStefano Zampini     }
123780677318SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
123806656605SStefano Zampini     if (F) {
123906656605SStefano Zampini       Mat B;
124006656605SStefano Zampini 
124106656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
124280677318SStefano Zampini       ierr = MatMatSolve(F,B,local_auxmat2_R);CHKERRQ(ierr);
124306656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
124406656605SStefano Zampini     } else {
124580677318SStefano Zampini       PetscScalar *marr;
124680677318SStefano Zampini 
124780677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
124806656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
124906656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
125080677318SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*n_R);CHKERRQ(ierr);
125106656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
125206656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
125306656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
125406656605SStefano Zampini       }
125580677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
125606656605SStefano Zampini     }
125780677318SStefano Zampini     if (!pcbddc->switch_static) {
125880677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
125980677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
126080677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
126180677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
126280677318SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*n_R);CHKERRQ(ierr);
126380677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
126480677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
126580677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
126680677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
126780677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
126880677318SStefano Zampini       }
126980677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
127080677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
127180677318SStefano Zampini       ierr = MatMatMult(auxmat,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
127280677318SStefano Zampini     } else {
127380677318SStefano Zampini       ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
127480677318SStefano Zampini       pcbddc->local_auxmat2 = local_auxmat2_R;
127525084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
127680677318SStefano Zampini     }
127780677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
127880677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
127980677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
128006656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
128106656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
128280677318SStefano Zampini     if (isCHOL) {
128380677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
128480677318SStefano Zampini     } else {
128525084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
128680677318SStefano Zampini     }
128780677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,one);CHKERRQ(ierr);
128806656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
128925084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
129025084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
129125084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
129280677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
129380677318SStefano Zampini     ierr = MatMatMult(M1,auxmat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
129480677318SStefano Zampini     ierr = MatDestroy(&auxmat);CHKERRQ(ierr);
129506656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
129606656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
1297f4ddd8eeSStefano Zampini   }
129888ebb749SStefano Zampini   /* Get submatrices from subdomain matrix */
12994f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
1300d16cbb6bSStefano Zampini     IS        dummy;
1301d16cbb6bSStefano Zampini     Mat       B0_R;
1302d16cbb6bSStefano Zampini     PetscReal norm;
1303d16cbb6bSStefano Zampini 
13044f1b2e48SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
13054f1b2e48SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&B0_R);CHKERRQ(ierr);
1306d16cbb6bSStefano Zampini     ierr = MatNorm(B0_R,NORM_INFINITY,&norm);CHKERRQ(ierr);
1307d16cbb6bSStefano Zampini     if (norm > PETSC_SMALL) {
1308d16cbb6bSStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! ||B0_R|| = %f (should be numerically 0.)",norm);
1309d16cbb6bSStefano Zampini     }
1310d16cbb6bSStefano Zampini     ierr = MatDestroy(&B0_R);CHKERRQ(ierr);
1311d16cbb6bSStefano Zampini     ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1312d16cbb6bSStefano Zampini   }
1313d16cbb6bSStefano Zampini 
131488ebb749SStefano Zampini   if (n_vertices) {
131506656605SStefano Zampini     IS is_aux;
13163a50541eSStefano Zampini 
13176816873aSStefano Zampini     if (sub_schurs->reuse_mumps) { /* is_R_local is not sorted, ISComplement doesn't like it */
13186816873aSStefano Zampini       IS tis;
13196816873aSStefano Zampini 
13206816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
13216816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
13226816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
13236816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
13246816873aSStefano Zampini     } else {
13253a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
13266816873aSStefano Zampini     }
13279577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
13289577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
132904708bb6SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
13304f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
1331019a44ceSStefano Zampini       IS dummy;
1332019a44ceSStefano Zampini 
13334f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
13344f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,is_aux,MAT_INITIAL_MATRIX,&B0_V);CHKERRQ(ierr);
1335019a44ceSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1336019a44ceSStefano Zampini     }
133725084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
133888ebb749SStefano Zampini   }
133988ebb749SStefano Zampini 
134088ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
1341f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
134206656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
134306656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
134406656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
134506656605SStefano Zampini     }
1346f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
134706656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
134806656605SStefano Zampini       PetscScalar *marray;
134906656605SStefano Zampini 
135006656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
135106656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
1352f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1353f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
1354f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
1355f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
1356f4ddd8eeSStefano Zampini     }
1357f4ddd8eeSStefano Zampini   }
135806656605SStefano Zampini 
1359f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
136006656605SStefano Zampini     PetscScalar *marray;
136188ebb749SStefano Zampini 
136206656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
13638eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
136406656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
136588ebb749SStefano Zampini     }
13663301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
136706656605SStefano Zampini       n *= 2;
136888ebb749SStefano Zampini     }
136906656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
137006656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
137106656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
13728eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
137306656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
137406656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
137588ebb749SStefano Zampini     }
13763301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
137706656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
13788eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
137906656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
138006656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
138188ebb749SStefano Zampini       }
138288ebb749SStefano Zampini     } else {
1383c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
1384c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
13851b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
1386c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
1387c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
1388c0553b1fSStefano Zampini       }
138988ebb749SStefano Zampini     }
139006656605SStefano Zampini   }
1391019a44ceSStefano Zampini 
139206656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
13934f1b2e48SStefano Zampini   p0_lidx_I = NULL;
13944f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
1395d12edf2fSStefano Zampini     const PetscInt *idxs;
1396d12edf2fSStefano Zampini 
1397d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
13984f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
13994f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
14004f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
14014f1b2e48SStefano Zampini     }
1402d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
1403d12edf2fSStefano Zampini   }
1404d16cbb6bSStefano Zampini 
140506656605SStefano Zampini   /* vertices */
140606656605SStefano Zampini   if (n_vertices) {
140716f15bc4SStefano Zampini 
140804708bb6SStefano Zampini     ierr = MatConvert(A_VV,impMatType,MAT_REUSE_MATRIX,&A_VV);CHKERRQ(ierr);
140904708bb6SStefano Zampini 
141016f15bc4SStefano Zampini     if (n_R) {
141106656605SStefano Zampini       Mat          A_RRmA_RV,S_VVt; /* S_VVt with LDA=N */
141206656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
141316f15bc4SStefano Zampini       PetscScalar  *x,*y;
141404708bb6SStefano Zampini       PetscBool    isseqaij;
141506656605SStefano Zampini 
141621eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
141706656605SStefano Zampini       ierr = MatConvert(A_RV,impMatType,MAT_REUSE_MATRIX,&A_RV);CHKERRQ(ierr);
141804708bb6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
14196816873aSStefano Zampini       if (F) { /* TODO could be optimized for symmetric problems */
142006656605SStefano Zampini         ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
142106656605SStefano Zampini       } else {
142206656605SStefano Zampini         ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
142306656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
142406656605SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*n_R);CHKERRQ(ierr);
142506656605SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
142606656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
142706656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
142806656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
142906656605SStefano Zampini         }
143006656605SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
143106656605SStefano Zampini       }
143280677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
143306656605SStefano Zampini       /* S_VV and S_CV are the subdomain contribution to coarse matrix. WARNING -> column major ordering */
143406656605SStefano Zampini       if (n_constraints) {
143506656605SStefano Zampini         Mat B;
143680677318SStefano Zampini 
1437b3d85658SStefano Zampini         ierr = PetscMemzero(work+n_R*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
143880677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
143980677318SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
144080677318SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+n_R*n_vertices+i*n_B);CHKERRQ(ierr);
144180677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
144280677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
144380677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
144480677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
144580677318SStefano Zampini         }
144680677318SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+n_R*n_vertices,&B);CHKERRQ(ierr);
144780677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
144880677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
144906656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work+n_R*n_vertices,&B);CHKERRQ(ierr);
145080677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
145106656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
145206656605SStefano Zampini         ierr = PetscBLASIntCast(n_R*n_vertices,&B_N);CHKERRQ(ierr);
145306656605SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+n_R*n_vertices,&B_one,work,&B_one));
145406656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
145506656605SStefano Zampini       }
145604708bb6SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
145704708bb6SStefano Zampini       if (!isseqaij) { /* MatMatMult with SEQ(S)BAIJ below will raise an error */
145804708bb6SStefano Zampini         ierr = MatConvert(A_VR,MATSEQAIJ,MAT_REUSE_MATRIX,&A_VR);CHKERRQ(ierr);
145904708bb6SStefano Zampini       }
146006656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
146180677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
146206656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
146306656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
146406656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
146506656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
146606656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
146706656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
146806656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
1469d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
1470019a44ceSStefano Zampini     } else {
1471d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
1472d16cbb6bSStefano Zampini     }
14734f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
1474019a44ceSStefano Zampini       const PetscScalar *vals;
1475019a44ceSStefano Zampini       const PetscInt    *idxs;
14764f1b2e48SStefano Zampini       PetscInt          n,j,primal_idx;
1477019a44ceSStefano Zampini 
14784f1b2e48SStefano Zampini       ierr = MatGetRow(B0_V,i,&n,&idxs,&vals);CHKERRQ(ierr);
14794f1b2e48SStefano Zampini       primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + i;
1480d16cbb6bSStefano Zampini       for (j=0;j<n;j++) {
14814f1b2e48SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+idxs[j]] = vals[j];
14824f1b2e48SStefano Zampini         coarse_submat_vals[idxs[j]*pcbddc->local_primal_size+primal_idx] = vals[j];
1483019a44ceSStefano Zampini       }
14844f1b2e48SStefano Zampini       ierr = MatRestoreRow(B0_V,i,&n,&idxs,&vals);CHKERRQ(ierr);
148516f15bc4SStefano Zampini     }
148621eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
1487d16cbb6bSStefano Zampini 
148806656605SStefano Zampini     /* coarse basis functions */
148906656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
149016f15bc4SStefano Zampini       PetscScalar *y;
149116f15bc4SStefano Zampini 
149206656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*i);CHKERRQ(ierr);
149306656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
149406656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
149506656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
149606656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
149706656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
149806656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
149906656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
150006656605SStefano Zampini 
150106656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
15024f1b2e48SStefano Zampini         PetscInt j;
15034f1b2e48SStefano Zampini 
150406656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
150506656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
150606656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
150706656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
150806656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
15094f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
151006656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
151106656605SStefano Zampini       }
151206656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
151306656605SStefano Zampini     }
151404708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
151504708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
151606656605SStefano Zampini   }
151706656605SStefano Zampini 
151806656605SStefano Zampini   if (n_constraints) {
151906656605SStefano Zampini     Mat B;
152006656605SStefano Zampini 
152106656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
152206656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
152380677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
152406656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
152506656605SStefano Zampini     if (n_vertices) {
152680677318SStefano Zampini       if (isCHOL) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
152780677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
152880677318SStefano Zampini       } else {
152980677318SStefano Zampini         Mat S_VCt;
153080677318SStefano Zampini 
153180677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
153280677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
153380677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
153480677318SStefano Zampini       }
153506656605SStefano Zampini     }
153606656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
153706656605SStefano Zampini     /* coarse basis functions */
153806656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
153906656605SStefano Zampini       PetscScalar *y;
154006656605SStefano Zampini 
154106656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*i);CHKERRQ(ierr);
154206656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
154306656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
154406656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
154506656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
154606656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
154706656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
154806656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
15494f1b2e48SStefano Zampini         PetscInt j;
15504f1b2e48SStefano Zampini 
155106656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
155206656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
155306656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
155406656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
155506656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
15564f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
155706656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
155806656605SStefano Zampini       }
155906656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
156006656605SStefano Zampini     }
156106656605SStefano Zampini   }
156280677318SStefano Zampini   if (n_constraints) {
156380677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
156480677318SStefano Zampini   }
15654f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
1566019a44ceSStefano Zampini   ierr = MatDestroy(&B0_V);CHKERRQ(ierr);
1567019a44ceSStefano Zampini 
156806656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
15693301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
157006656605SStefano Zampini 
157106656605SStefano Zampini     if (n_constraints) {
157216f15bc4SStefano Zampini       Mat S_CCT,B_C;
157306656605SStefano Zampini 
157480677318SStefano Zampini       /* this is a lazy thing */
157580677318SStefano Zampini       ierr = MatConvert(C_CR,impMatType,MAT_REUSE_MATRIX,&C_CR);CHKERRQ(ierr);
157606656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work+n_vertices*n_R,&B_C);CHKERRQ(ierr);
157706656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
157806656605SStefano Zampini       ierr = MatTransposeMatMult(C_CR,S_CCT,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
157916f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
158006656605SStefano Zampini       if (n_vertices) {
158116f15bc4SStefano Zampini         Mat B_V,S_VCT;
158206656605SStefano Zampini 
158306656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&B_V);CHKERRQ(ierr);
158406656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
158506656605SStefano Zampini         ierr = MatTransposeMatMult(C_CR,S_VCT,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
158606656605SStefano Zampini         ierr = MatDestroy(&B_V);CHKERRQ(ierr);
158716f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
158806656605SStefano Zampini       }
158906656605SStefano Zampini       ierr = MatDestroy(&B_C);CHKERRQ(ierr);
159080677318SStefano Zampini     } else { /* if there are no constraints, reset work */
159180677318SStefano Zampini       ierr = PetscMemzero(work,n_R*pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
159206656605SStefano Zampini     }
159316f15bc4SStefano Zampini     if (n_vertices && n_R) {
159406656605SStefano Zampini       Mat          A_VRT;
159580677318SStefano Zampini       PetscScalar  *marray;
159606656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
159706656605SStefano Zampini 
159880677318SStefano Zampini       ierr = MatTranspose(A_VR,MAT_INITIAL_MATRIX,&A_VRT);CHKERRQ(ierr);
159980677318SStefano Zampini       ierr = MatConvert(A_VRT,impMatType,MAT_REUSE_MATRIX,&A_VRT);CHKERRQ(ierr);
160080677318SStefano Zampini       ierr = MatDenseGetArray(A_VRT,&marray);CHKERRQ(ierr);
160106656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_R,&B_N);CHKERRQ(ierr);
160280677318SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&m_one,marray,&B_one,work,&B_one));
160380677318SStefano Zampini       ierr = MatDenseRestoreArray(A_VRT,&marray);CHKERRQ(ierr);
160416f15bc4SStefano Zampini       ierr = MatDestroy(&A_VRT);CHKERRQ(ierr);
160506656605SStefano Zampini     }
160606656605SStefano Zampini 
160706656605SStefano Zampini     if (F) { /* currently there's no support for MatTransposeMatSolve(F,B,X) */
160806656605SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
160906656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
161006656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+(i+pcbddc->local_primal_size)*n_R);CHKERRQ(ierr);
161106656605SStefano Zampini         ierr = MatSolveTranspose(F,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
161206656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
161306656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
161406656605SStefano Zampini       }
161506656605SStefano Zampini     } else {
161606656605SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
161706656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
161806656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+(i+pcbddc->local_primal_size)*n_R);CHKERRQ(ierr);
161906656605SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
162006656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
162106656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
162206656605SStefano Zampini       }
162306656605SStefano Zampini     }
162406656605SStefano Zampini     /* coarse basis functions */
162506656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
162606656605SStefano Zampini       PetscScalar *y;
162706656605SStefano Zampini 
162806656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*(i+pcbddc->local_primal_size));CHKERRQ(ierr);
162906656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
163006656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
163106656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
163206656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
163306656605SStefano Zampini       if (i<n_vertices) {
163406656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
163506656605SStefano Zampini       }
163606656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
163706656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
163806656605SStefano Zampini 
163906656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
164006656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
164106656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
164206656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
164306656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
164406656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
164506656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
164606656605SStefano Zampini       }
164706656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
164806656605SStefano Zampini     }
164906656605SStefano Zampini   }
1650d62866d3SStefano Zampini   /* free memory */
165188ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
165206656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
165306656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
165406656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
165506656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
1656d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
1657d62866d3SStefano Zampini   if (n_vertices) {
1658d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
1659d62866d3SStefano Zampini   }
1660d62866d3SStefano Zampini   if (n_constraints) {
1661d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
1662d62866d3SStefano Zampini   }
166388ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
166488ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
166588ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
1666d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
166788ebb749SStefano Zampini     Mat         coarse_sub_mat;
166825084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
166988ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
167088ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
167188ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
16728bec7fa6SStefano Zampini     Mat         C_B,CPHI;
16738bec7fa6SStefano Zampini     IS          is_dummy;
16748bec7fa6SStefano Zampini     Vec         mones;
167588ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
167688ebb749SStefano Zampini     PetscReal   real_value;
167788ebb749SStefano Zampini 
167888ebb749SStefano Zampini     ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
167988ebb749SStefano Zampini     ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
168088ebb749SStefano Zampini     ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
168188ebb749SStefano Zampini     ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
168288ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
168388ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
1684c0553b1fSStefano Zampini     if (unsymmetric_check) {
168588ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
168688ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
168788ebb749SStefano Zampini     }
168888ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
168988ebb749SStefano Zampini 
169025084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
16913301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
169225084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1693c0553b1fSStefano Zampini     if (unsymmetric_check) {
169488ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
169588ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
169688ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
169788ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
169888ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
169988ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
170088ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
170188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
170288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
170388ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
170488ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
170588ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
170688ebb749SStefano Zampini     } else {
170788ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
170888ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
170988ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
171088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
171188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
171288ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
171388ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
171488ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
171588ebb749SStefano Zampini     }
171688ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
171788ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
171888ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
171988ebb749SStefano Zampini     ierr = MatConvert(TM1,MATSEQDENSE,MAT_REUSE_MATRIX,&TM1);CHKERRQ(ierr);
17204f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
1721d12edf2fSStefano Zampini       Mat         B0_I,B0_B,B0_BPHI,B0_IPHI;
1722d12edf2fSStefano Zampini       PetscScalar *data,*data2;
17234f1b2e48SStefano Zampini       PetscInt    j;
1724d12edf2fSStefano Zampini 
17254f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
17264f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);
17274f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_I_local,MAT_INITIAL_MATRIX,&B0_I);
1728d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
1729d12edf2fSStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_REUSE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
1730d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
1731d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
17324f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
17334f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
1734d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
17354f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
17364f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
17374f1b2e48SStefano Zampini         }
1738d12edf2fSStefano Zampini       }
1739d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
1740d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
1741d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
1742d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
1743d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
1744d12edf2fSStefano Zampini       ierr = MatMatMult(B0_I,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&B0_IPHI);CHKERRQ(ierr);
1745d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_I);CHKERRQ(ierr);
1746d12edf2fSStefano Zampini       ierr = MatNorm(B0_IPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
1747d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_IPHI);CHKERRQ(ierr);
1748d12edf2fSStefano Zampini     }
1749d12edf2fSStefano Zampini #if 0
1750d12edf2fSStefano Zampini   {
1751d12edf2fSStefano Zampini     PetscViewer viewer;
1752d12edf2fSStefano Zampini     char filename[256];
1753d12edf2fSStefano Zampini     sprintf(filename,"proj_local_coarse_mat%d.m",PetscGlobalRank);
1754d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
1755d12edf2fSStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1756d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
1757d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1758d12edf2fSStefano Zampini   }
1759d12edf2fSStefano Zampini #endif
176081d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
17618bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
17620fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
176306656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
17648bec7fa6SStefano Zampini 
17658bec7fa6SStefano Zampini     /* check constraints */
17664f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
17678bec7fa6SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&is_dummy);CHKERRQ(ierr);
17688bec7fa6SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);
17698bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
17708bec7fa6SStefano Zampini       ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
17718bec7fa6SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
17728bec7fa6SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
17738bec7fa6SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
1774bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
1775c0553b1fSStefano Zampini       if (unsymmetric_check) {
1776bdae7319SStefano Zampini         ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
1777bdae7319SStefano Zampini         ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
1778bdae7319SStefano Zampini         ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
1779bdae7319SStefano Zampini         ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
1780bdae7319SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
178188ebb749SStefano Zampini       }
17828bec7fa6SStefano Zampini       ierr = MatDestroy(&C_B);CHKERRQ(ierr);
17838bec7fa6SStefano Zampini       ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
17848bec7fa6SStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
17858bec7fa6SStefano Zampini       ierr = VecDestroy(&mones);CHKERRQ(ierr);
1786d12edf2fSStefano Zampini     }
178725084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
178888ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
178988ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
179088ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
179188ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
179288ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
179388ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
179488ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
179588ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
179688ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
179788ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
1798c0553b1fSStefano Zampini     if (unsymmetric_check) {
179988ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
180088ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
180188ebb749SStefano Zampini     }
180288ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
180388ebb749SStefano Zampini   }
18048629588bSStefano Zampini   /* get back data */
18058629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
180688ebb749SStefano Zampini   PetscFunctionReturn(0);
180788ebb749SStefano Zampini }
180888ebb749SStefano Zampini 
180988ebb749SStefano Zampini #undef __FUNCT__
1810d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
1811d648f858SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
1812aa0d41d4SStefano Zampini {
1813d65f70fdSStefano Zampini   Mat            *work_mat;
1814d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
1815d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
1816d65f70fdSStefano Zampini   PetscInt       rsize,*idxs_perm_r,csize,*idxs_perm_c;
1817aa0d41d4SStefano Zampini   PetscErrorCode ierr;
1818aa0d41d4SStefano Zampini 
1819aa0d41d4SStefano Zampini   PetscFunctionBegin;
1820d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
1821d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
1822d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
1823d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
1824aa0d41d4SStefano Zampini 
1825d65f70fdSStefano Zampini   if (!rsorted) {
1826906d46d4SStefano Zampini     const PetscInt *idxs;
1827906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
1828aa0d41d4SStefano Zampini 
1829d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
1830d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
1831d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
1832d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
1833aa0d41d4SStefano Zampini     }
1834d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
1835d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
1836d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
1837d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
1838aa0d41d4SStefano Zampini     }
1839d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
1840d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
1841d65f70fdSStefano Zampini   } else {
1842d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
1843d65f70fdSStefano Zampini     isrow_s = isrow;
1844aa0d41d4SStefano Zampini   }
1845906d46d4SStefano Zampini 
1846d65f70fdSStefano Zampini   if (!csorted) {
1847d65f70fdSStefano Zampini     if (isrow == iscol) {
1848d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
1849d65f70fdSStefano Zampini       iscol_s = isrow_s;
1850d65f70fdSStefano Zampini     } else {
1851d65f70fdSStefano Zampini       const PetscInt *idxs;
1852d65f70fdSStefano Zampini       PetscInt *idxs_sorted,i;
1853906d46d4SStefano Zampini 
1854d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
1855d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
1856d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
1857d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
1858d65f70fdSStefano Zampini       }
1859d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
1860d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
1861d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
1862d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
1863d65f70fdSStefano Zampini       }
1864d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
1865d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
1866d65f70fdSStefano Zampini     }
1867d65f70fdSStefano Zampini   } else {
1868d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
1869d65f70fdSStefano Zampini     iscol_s = iscol;
1870d65f70fdSStefano Zampini   }
1871d65f70fdSStefano Zampini 
1872d648f858SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
1873d65f70fdSStefano Zampini 
1874d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
1875906d46d4SStefano Zampini     Mat      new_mat;
1876d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
1877906d46d4SStefano Zampini 
1878d65f70fdSStefano Zampini     if (!rsorted) {
1879d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
1880d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
1881d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
1882d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
1883906d46d4SStefano Zampini       }
1884d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
1885d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
1886d65f70fdSStefano Zampini     } else {
1887d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
1888906d46d4SStefano Zampini     }
1889d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
1890d65f70fdSStefano Zampini 
1891d65f70fdSStefano Zampini     if (!csorted) {
1892d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
1893d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
1894d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
1895d65f70fdSStefano Zampini       } else {
1896d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
1897d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
1898d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
1899d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
1900d65f70fdSStefano Zampini         }
1901d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
1902d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
1903d65f70fdSStefano Zampini       }
1904d65f70fdSStefano Zampini     } else {
1905d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
1906d65f70fdSStefano Zampini     }
1907d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
1908d65f70fdSStefano Zampini 
1909d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
1910d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
1911d65f70fdSStefano Zampini     work_mat[0] = new_mat;
1912d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
1913d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
1914d65f70fdSStefano Zampini   }
1915d65f70fdSStefano Zampini 
1916d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
1917d65f70fdSStefano Zampini   *B = work_mat[0];
1918d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
1919d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
1920d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
1921d65f70fdSStefano Zampini   PetscFunctionReturn(0);
1922d65f70fdSStefano Zampini }
1923d65f70fdSStefano Zampini 
1924d65f70fdSStefano Zampini #undef __FUNCT__
19255e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
19265e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
1927aa0d41d4SStefano Zampini {
1928aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
19295e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
1930d65f70fdSStefano Zampini   Mat            new_mat;
19315e8657edSStefano Zampini   IS             is_local,is_global;
1932d65f70fdSStefano Zampini   PetscInt       local_size;
1933d65f70fdSStefano Zampini   PetscBool      isseqaij;
1934aa0d41d4SStefano Zampini   PetscErrorCode ierr;
1935aa0d41d4SStefano Zampini 
1936aa0d41d4SStefano Zampini   PetscFunctionBegin;
1937aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
19385e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
19395e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
1940b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
1941aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
1942d648f858SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
1943aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
1944906d46d4SStefano Zampini 
1945906d46d4SStefano Zampini   /* check */
1946906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
1947906d46d4SStefano Zampini     Vec       x,x_change;
1948906d46d4SStefano Zampini     PetscReal error;
1949906d46d4SStefano Zampini 
19505e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
1951906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
19525e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
1953e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1954e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1955d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
1956e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1957e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1958906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
1959906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
1960906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1961906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
1962906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
1963906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
1964906d46d4SStefano Zampini   }
1965906d46d4SStefano Zampini 
196622d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
19679b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
196822d5777bSStefano Zampini   if (isseqaij) {
1969*1cf9b237SStefano Zampini     Mat M;
1970*1cf9b237SStefano Zampini 
1971*1cf9b237SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
1972*1cf9b237SStefano Zampini     ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
1973*1cf9b237SStefano Zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
1974aa0d41d4SStefano Zampini   } else {
1975*1cf9b237SStefano Zampini     Mat work_mat,M;
1976*1cf9b237SStefano Zampini 
1977aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
1978*1cf9b237SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
1979*1cf9b237SStefano Zampini     ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
1980*1cf9b237SStefano Zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
1981aa0d41d4SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
1982aa0d41d4SStefano Zampini   }
19833301b35fSStefano Zampini   if (matis->A->symmetric_set) {
19843301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
1985e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
19863301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
1987e496cd5dSStefano Zampini #endif
19883301b35fSStefano Zampini   }
198945a1bb75SStefano Zampini   /*
199045a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1991d65f70fdSStefano Zampini   ierr = MatView(new_mat,(PetscViewer)0);CHKERRQ(ierr);
199245a1bb75SStefano Zampini   */
1993d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
1994aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
1995aa0d41d4SStefano Zampini }
1996aa0d41d4SStefano Zampini 
1997aa0d41d4SStefano Zampini #undef __FUNCT__
1998a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
19998ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
2000a64d13efSStefano Zampini {
2001a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
2002a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
2003d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
200453892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
20053a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
20063a50541eSStefano Zampini   PetscInt        vbs,bs;
20076816873aSStefano Zampini   PetscBT         bitmask=NULL;
2008a64d13efSStefano Zampini   PetscErrorCode  ierr;
2009a64d13efSStefano Zampini 
2010a64d13efSStefano Zampini   PetscFunctionBegin;
2011b23d619eSStefano Zampini   /*
2012b23d619eSStefano Zampini     No need to setup local scatters if
2013b23d619eSStefano Zampini       - primal space is unchanged
2014b23d619eSStefano Zampini         AND
2015b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
2016b23d619eSStefano Zampini         AND
2017b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
2018b23d619eSStefano Zampini   */
2019b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
2020f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
2021f4ddd8eeSStefano Zampini   }
2022f4ddd8eeSStefano Zampini   /* destroy old objects */
2023f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
2024f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
2025f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
2026a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
2027b371cd4fSStefano Zampini   n_B = pcis->n_B;
2028b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
2029b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
20303a50541eSStefano Zampini 
2031a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
20326816873aSStefano Zampini 
203353892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
20346816873aSStefano Zampini   if (!sub_schurs->reuse_mumps) {
2035854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
2036a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
2037a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
20380e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
2039a64d13efSStefano Zampini     }
2040a64d13efSStefano Zampini 
2041a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
20424641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
20436816873aSStefano Zampini         idx_R_local[n_R++] = i;
2044a64d13efSStefano Zampini       }
2045a64d13efSStefano Zampini     }
204653892102SStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing MUMPS Schur solver */
20476816873aSStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
20486816873aSStefano Zampini 
204953892102SStefano Zampini     ierr = ISGetIndices(reuse_mumps->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
205053892102SStefano Zampini     ierr = ISGetLocalSize(reuse_mumps->is_R,&n_R);CHKERRQ(ierr);
20516816873aSStefano Zampini   }
20523a50541eSStefano Zampini 
20533a50541eSStefano Zampini   /* Block code */
20543a50541eSStefano Zampini   vbs = 1;
20553a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
20563a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
20573a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
20583a50541eSStefano Zampini     PetscInt  *vary;
2059d3df7717SStefano Zampini     if (!sub_schurs->reuse_mumps) {
2060785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
20613a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
2062d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
2063d3df7717SStefano 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 */
20640e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
2065d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
20663a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
20673a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
20683a50541eSStefano Zampini           break;
20693a50541eSStefano Zampini         }
20703a50541eSStefano Zampini       }
2071d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
2072d3df7717SStefano Zampini     } else {
2073d3df7717SStefano Zampini       /* Verify directly the R set */
2074d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
2075d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
2076d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
2077d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
2078d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
2079d3df7717SStefano Zampini             break;
2080d3df7717SStefano Zampini           }
2081d3df7717SStefano Zampini         }
2082d3df7717SStefano Zampini       }
2083d3df7717SStefano Zampini     }
20843a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
20853a50541eSStefano Zampini       vbs = bs;
20863a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
20873a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
20883a50541eSStefano Zampini       }
20893a50541eSStefano Zampini     }
20903a50541eSStefano Zampini   }
20913a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
209253892102SStefano Zampini   if (sub_schurs->reuse_mumps) {
209353892102SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
209453892102SStefano Zampini 
209553892102SStefano Zampini     ierr = ISRestoreIndices(reuse_mumps->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
209653892102SStefano Zampini     ierr = ISDestroy(&reuse_mumps->is_R);CHKERRQ(ierr);
209753892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
209853892102SStefano Zampini     reuse_mumps->is_R = pcbddc->is_R_local;
209953892102SStefano Zampini   } else {
21003a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
210153892102SStefano Zampini   }
2102a64d13efSStefano Zampini 
2103a64d13efSStefano Zampini   /* print some info if requested */
2104a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
2105a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2106a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
21070fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
2108a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
2109a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
21104f1b2e48SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"r_size = %d, v_size = %d, constraints = %d, local_primal_size = %d\n",n_R,n_vertices,pcbddc->local_primal_size-n_vertices-pcbddc->benign_n,pcbddc->local_primal_size);CHKERRQ(ierr);
2111a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2112a64d13efSStefano Zampini   }
2113a64d13efSStefano Zampini 
2114a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
21156816873aSStefano Zampini   if (!sub_schurs->reuse_mumps) {
21166816873aSStefano Zampini     IS       is_aux1,is_aux2;
21176816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
21186816873aSStefano Zampini 
21193a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2120854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
2121854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
2122a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
21234641a718SStefano Zampini     for (i=0; i<n_D; i++) {
21244641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
21254641a718SStefano Zampini     }
2126a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2127a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
21284641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
21294641a718SStefano Zampini         aux_array1[j++] = i;
2130a64d13efSStefano Zampini       }
2131a64d13efSStefano Zampini     }
2132a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
2133a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2134a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
21354641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
21364641a718SStefano Zampini         aux_array2[j++] = i;
2137a64d13efSStefano Zampini       }
2138a64d13efSStefano Zampini     }
2139a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2140a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
2141a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
2142a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
2143a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
2144a64d13efSStefano Zampini 
21458eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
2146785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
2147a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
21484641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
21494641a718SStefano Zampini           aux_array1[j++] = i;
2150a64d13efSStefano Zampini         }
2151a64d13efSStefano Zampini       }
2152a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
2153a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
2154a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
2155a64d13efSStefano Zampini     }
21564641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
21573a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2158d62866d3SStefano Zampini   } else {
215953892102SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
21606816873aSStefano Zampini     IS               tis;
21616816873aSStefano Zampini     PetscInt         schur_size;
21626816873aSStefano Zampini 
216353892102SStefano Zampini     ierr = ISGetLocalSize(reuse_mumps->is_B,&schur_size);CHKERRQ(ierr);
21646816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
216553892102SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_mumps->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
21666816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
21676816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
21686816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
21696816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
21706816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
2171d62866d3SStefano Zampini     }
2172d62866d3SStefano Zampini   }
2173a64d13efSStefano Zampini   PetscFunctionReturn(0);
2174a64d13efSStefano Zampini }
2175a64d13efSStefano Zampini 
2176304d26faSStefano Zampini 
2177304d26faSStefano Zampini #undef __FUNCT__
2178304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
2179684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
2180304d26faSStefano Zampini {
2181304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2182304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
2183304d26faSStefano Zampini   PC             pc_temp;
2184304d26faSStefano Zampini   Mat            A_RR;
2185f4ddd8eeSStefano Zampini   MatReuse       reuse;
2186304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
2187304d26faSStefano Zampini   PetscReal      value;
218804708bb6SStefano Zampini   PetscInt       n_D,n_R;
21899577ea80SStefano Zampini   PetscBool      use_exact,use_exact_reduced,issbaij;
2190304d26faSStefano Zampini   PetscErrorCode ierr;
2191e604994aSStefano Zampini   /* prefixes stuff */
2192312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
2193e604994aSStefano Zampini   size_t         len;
2194304d26faSStefano Zampini 
2195304d26faSStefano Zampini   PetscFunctionBegin;
2196304d26faSStefano Zampini 
2197e604994aSStefano Zampini   /* compute prefixes */
2198e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
2199e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
2200e604994aSStefano Zampini   if (!pcbddc->current_level) {
2201e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
2202e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
2203e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
2204e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
2205e604994aSStefano Zampini   } else {
2206e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
2207312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
2208e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
2209e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
2210312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
2211312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
221234d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
221334d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
2214e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
2215e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
2216e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
2217e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
2218e604994aSStefano Zampini   }
2219e604994aSStefano Zampini 
2220304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
2221684f6988SStefano Zampini   if (dirichlet) {
2222d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
22233301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
22243301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
2225964fefecSStefano Zampini     }
2226ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
2227964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
2228304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
2229304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
2230304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
2231304d26faSStefano Zampini       /* default */
2232304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
2233e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
22349577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
2235304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
22369577ea80SStefano Zampini       if (issbaij) {
22379577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
22389577ea80SStefano Zampini       } else {
2239304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
22409577ea80SStefano Zampini       }
2241304d26faSStefano Zampini       /* Allow user's customization */
2242304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
2243304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
2244304d26faSStefano Zampini     }
2245d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
2246d62866d3SStefano Zampini     if (sub_schurs->reuse_mumps) {
2247d62866d3SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2248d62866d3SStefano Zampini 
2249d62866d3SStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_mumps->interior_solver);CHKERRQ(ierr);
2250d5574798SStefano Zampini     }
2251304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
2252304d26faSStefano Zampini     if (!n_D) {
2253304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
2254304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
2255304d26faSStefano Zampini     }
2256304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
2257304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
2258304d26faSStefano Zampini     /* set ksp_D into pcis data */
2259304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
2260304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
2261304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
2262684f6988SStefano Zampini   }
2263304d26faSStefano Zampini 
2264304d26faSStefano Zampini   /* NEUMANN PROBLEM */
2265684f6988SStefano Zampini   A_RR = 0;
2266684f6988SStefano Zampini   if (neumann) {
2267d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
226804708bb6SStefano Zampini     PetscInt        ibs,mbs;
226904708bb6SStefano Zampini     PetscBool       issbaij;
227004708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
2271f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
22728ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
2273f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
2274f4ddd8eeSStefano Zampini       PetscInt nn_R;
227581d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
2276f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
2277f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
2278f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
2279f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
2280f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2281f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
2282f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
2283727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
2284f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2285f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
2286f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
2287f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
2288f4ddd8eeSStefano Zampini         }
2289f4ddd8eeSStefano Zampini       }
2290f4ddd8eeSStefano Zampini       /* last check */
2291d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
2292f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2293f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
2294f4ddd8eeSStefano Zampini       }
2295f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
2296f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
2297f4ddd8eeSStefano Zampini     }
2298f4ddd8eeSStefano Zampini     /* extract A_RR */
2299af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
2300af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
230104708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
230204708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
230304708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
230404708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
230504708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
2306af732b37SStefano Zampini       } else {
230704708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
23086816873aSStefano Zampini       }
230904708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
231004708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
231104708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
231204708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
231304708bb6SStefano Zampini       } else {
231404708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
231504708bb6SStefano Zampini       }
231604708bb6SStefano Zampini     }
231704708bb6SStefano Zampini     if (!sub_schurs->reuse_mumps) {
2318f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
23193301b35fSStefano Zampini       if (pcbddc->local_mat->symmetric_set) {
23203301b35fSStefano Zampini         ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
23216816873aSStefano Zampini       }
23226816873aSStefano Zampini     } else {
23236816873aSStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
23246816873aSStefano Zampini 
23256816873aSStefano Zampini       ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
23266816873aSStefano Zampini       ierr = PCGetOperators(reuse_mumps->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
23276816873aSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
2328af732b37SStefano Zampini     }
2329f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
2330304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
2331304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
2332304d26faSStefano Zampini       /* default */
2333304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
2334e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
2335304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
23369577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
23379577ea80SStefano Zampini       if (issbaij) {
23389577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
23399577ea80SStefano Zampini       } else {
2340304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
23419577ea80SStefano Zampini       }
2342304d26faSStefano Zampini       /* Allow user's customization */
2343304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
2344304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
2345304d26faSStefano Zampini     }
2346d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
2347304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
2348304d26faSStefano Zampini     if (!n_R) {
2349304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
2350304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
2351304d26faSStefano Zampini     }
2352d62866d3SStefano Zampini     /* Reuse MUMPS solver if it is present */
2353d62866d3SStefano Zampini     if (sub_schurs->reuse_mumps) {
2354d62866d3SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2355d62866d3SStefano Zampini 
2356d62866d3SStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_mumps->correction_solver);CHKERRQ(ierr);
2357d62866d3SStefano Zampini     }
2358304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
2359304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
2360684f6988SStefano Zampini   }
23616816873aSStefano Zampini   /* free Neumann problem's matrix */
23626816873aSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2363304d26faSStefano Zampini 
2364304d26faSStefano Zampini   /* check Dirichlet and Neumann solvers and adapt them if a nullspace correction is needed */
23650fccc4e9SStefano Zampini   if (pcbddc->NullSpace || pcbddc->dbg_flag) {
2366684f6988SStefano Zampini     if (pcbddc->dbg_flag) {
2367684f6988SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2368684f6988SStefano Zampini       ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
2369684f6988SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2370684f6988SStefano Zampini     }
2371684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
23720fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
23730fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
23740fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
23750fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
23760fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
2377304d26faSStefano Zampini       /* need to be adapted? */
2378b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
2379b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2380b8ffe317SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,use_exact_reduced);CHKERRQ(ierr);
2381304d26faSStefano Zampini       /* print info */
2382304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
2383e604994aSStefano 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);
2384304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2385304d26faSStefano Zampini       }
2386b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced && !pcbddc->switch_static) {
2387298c0119SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcis->is_I_local);CHKERRQ(ierr);
2388304d26faSStefano Zampini       }
2389684f6988SStefano Zampini     }
2390684f6988SStefano Zampini     if (neumann) { /* Neumann */
23916816873aSStefano Zampini       ierr = KSPGetOperators(pcbddc->ksp_R,&A_RR,NULL);CHKERRQ(ierr);
23920fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
23930fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
23940fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
23950fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
23960fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
2397304d26faSStefano Zampini       /* need to be adapted? */
2398b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
2399b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2400304d26faSStefano Zampini       /* print info */
2401304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
2402e604994aSStefano 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);
2403304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2404304d26faSStefano Zampini       }
2405b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced) { /* is it the right logic? */
2406298c0119SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->is_R_local);CHKERRQ(ierr);
2407304d26faSStefano Zampini       }
24080fccc4e9SStefano Zampini     }
2409684f6988SStefano Zampini   }
2410304d26faSStefano Zampini   PetscFunctionReturn(0);
2411304d26faSStefano Zampini }
2412304d26faSStefano Zampini 
2413304d26faSStefano Zampini #undef __FUNCT__
2414ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
241580677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
2416674ae819SStefano Zampini {
2417674ae819SStefano Zampini   PetscErrorCode  ierr;
2418674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
2419be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
2420674ae819SStefano Zampini 
2421674ae819SStefano Zampini   PetscFunctionBegin;
2422be83ff47SStefano Zampini   if (!sub_schurs->reuse_mumps) {
242380677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
242420c7b377SStefano Zampini   }
242580677318SStefano Zampini   if (!pcbddc->switch_static) {
242680677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
242780677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
242880677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
242920c7b377SStefano Zampini     }
2430be83ff47SStefano Zampini     if (!sub_schurs->reuse_mumps) {
243180677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
243280677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
243320c7b377SStefano Zampini     } else {
2434be83ff47SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2435be83ff47SStefano Zampini 
243653892102SStefano Zampini       ierr = VecScatterBegin(reuse_mumps->correction_scatter_B,inout_B,reuse_mumps->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
243753892102SStefano Zampini       ierr = VecScatterEnd(reuse_mumps->correction_scatter_B,inout_B,reuse_mumps->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
243820c7b377SStefano Zampini     }
2439be83ff47SStefano Zampini   } else {
244080677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
244180677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
244280677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
244380677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
244480677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
244580677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
244680677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
244780677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
244880677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2449674ae819SStefano Zampini     }
2450674ae819SStefano Zampini   }
2451be83ff47SStefano Zampini   if (!sub_schurs->reuse_mumps) {
245280677318SStefano Zampini     if (applytranspose) {
245380677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
245480677318SStefano Zampini     } else {
245580677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
245680677318SStefano Zampini     }
245753892102SStefano Zampini #if defined(PETSC_HAVE_MUMPS)
2458be83ff47SStefano Zampini   } else {
2459be83ff47SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2460be83ff47SStefano Zampini 
2461be83ff47SStefano Zampini     if (applytranspose) {
246253892102SStefano Zampini       ierr = MatMumpsSolveSchurComplementTranspose(reuse_mumps->F,reuse_mumps->rhs_B,reuse_mumps->sol_B);CHKERRQ(ierr);
2463be83ff47SStefano Zampini     } else {
246453892102SStefano Zampini       ierr = MatMumpsSolveSchurComplement(reuse_mumps->F,reuse_mumps->rhs_B,reuse_mumps->sol_B);CHKERRQ(ierr);
2465be83ff47SStefano Zampini     }
246653892102SStefano Zampini #endif
2467be83ff47SStefano Zampini   }
246880677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
246980677318SStefano Zampini   if (!pcbddc->switch_static) {
2470be83ff47SStefano Zampini     if (!sub_schurs->reuse_mumps) {
247180677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
247280677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2473be83ff47SStefano Zampini     } else {
2474be83ff47SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2475be83ff47SStefano Zampini 
247653892102SStefano Zampini       ierr = VecScatterBegin(reuse_mumps->correction_scatter_B,reuse_mumps->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
247753892102SStefano Zampini       ierr = VecScatterEnd(reuse_mumps->correction_scatter_B,reuse_mumps->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2478be83ff47SStefano Zampini     }
247980677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
248080677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
248180677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
248280677318SStefano Zampini     }
248380677318SStefano Zampini   } else {
248480677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
248580677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
248680677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
248780677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
248880677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
248980677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
249080677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
249180677318SStefano Zampini     }
249280677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
249380677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
249480677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
249580677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2496674ae819SStefano Zampini   }
2497674ae819SStefano Zampini   PetscFunctionReturn(0);
2498674ae819SStefano Zampini }
2499674ae819SStefano Zampini 
2500dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
2501674ae819SStefano Zampini #undef __FUNCT__
2502674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
2503dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
2504674ae819SStefano Zampini {
2505674ae819SStefano Zampini   PetscErrorCode ierr;
2506674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
2507674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
2508674ae819SStefano Zampini   const PetscScalar zero = 0.0;
2509674ae819SStefano Zampini 
2510674ae819SStefano Zampini   PetscFunctionBegin;
2511dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
2512dc359a40SStefano Zampini   if (applytranspose) {
2513674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
25148eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
2515dc359a40SStefano Zampini   } else {
2516674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
2517674ae819SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
251815aaf578SStefano Zampini   }
2519efc2fbd9SStefano Zampini 
2520efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
25214f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
2522efc2fbd9SStefano Zampini     PetscScalar *array;
25234f1b2e48SStefano Zampini     PetscInt    j;
2524efc2fbd9SStefano Zampini 
2525efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
25264f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
2527efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2528efc2fbd9SStefano Zampini   }
2529efc2fbd9SStefano Zampini 
253012edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
253112edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
253212edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
253312edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
253412edc857SStefano Zampini 
25359f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
253612edc857SStefano Zampini   /* TODO remove null space when doing multilevel */
253712edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
253851694757SStefano Zampini     Mat coarse_mat;
2539964fefecSStefano Zampini     Vec rhs,sol;
254051694757SStefano Zampini     MatNullSpace nullsp;
2541964fefecSStefano Zampini 
2542964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
2543964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
254451694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
254551694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
254651694757SStefano Zampini     if (nullsp) {
254751694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
254851694757SStefano Zampini     }
254912edc857SStefano Zampini     if (applytranspose) {
2550964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
255112edc857SStefano Zampini     } else {
2552964fefecSStefano Zampini       ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
255312edc857SStefano Zampini     }
255451694757SStefano Zampini     if (nullsp) {
255551694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
255651694757SStefano Zampini     }
255712edc857SStefano Zampini   }
2558674ae819SStefano Zampini 
2559674ae819SStefano Zampini   /* Local solution on R nodes */
256080677318SStefano Zampini   if (pcis->n) { /* in/out pcbddc->vec1_B,pcbddc->vec1_D */
256180677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
25629f00e9b4SStefano Zampini   }
2563674ae819SStefano Zampini 
25649f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
25659f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
256612edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2567674ae819SStefano Zampini 
2568674ae819SStefano Zampini   /* Sum contributions from two levels */
2569dc359a40SStefano Zampini   if (applytranspose) {
2570dc359a40SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
2571dc359a40SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
2572dc359a40SStefano Zampini   } else {
2573674ae819SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
25748eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
2575dc359a40SStefano Zampini   }
2576efc2fbd9SStefano Zampini   /* store p0 */
25774f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
2578efc2fbd9SStefano Zampini     PetscScalar *array;
25794f1b2e48SStefano Zampini     PetscInt    j;
2580efc2fbd9SStefano Zampini 
2581efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
25824f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
2583efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2584efc2fbd9SStefano Zampini   }
2585674ae819SStefano Zampini   PetscFunctionReturn(0);
2586674ae819SStefano Zampini }
2587674ae819SStefano Zampini 
2588674ae819SStefano Zampini #undef __FUNCT__
2589674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
259012edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
2591674ae819SStefano Zampini {
2592674ae819SStefano Zampini   PetscErrorCode ierr;
2593674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
259458da7f69SStefano Zampini   PetscScalar    *array;
259512edc857SStefano Zampini   Vec            from,to;
2596674ae819SStefano Zampini 
2597674ae819SStefano Zampini   PetscFunctionBegin;
259812edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
259912edc857SStefano Zampini     from = pcbddc->coarse_vec;
260012edc857SStefano Zampini     to = pcbddc->vec1_P;
260112edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
260212edc857SStefano Zampini       Vec tvec;
260358da7f69SStefano Zampini 
260458da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
260558da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
260612edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
260758da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
260858da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
260958da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
261012edc857SStefano Zampini     }
261112edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
261212edc857SStefano Zampini     from = pcbddc->vec1_P;
261312edc857SStefano Zampini     to = pcbddc->coarse_vec;
261412edc857SStefano Zampini   }
261512edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
2616674ae819SStefano Zampini   PetscFunctionReturn(0);
2617674ae819SStefano Zampini }
2618674ae819SStefano Zampini 
2619674ae819SStefano Zampini #undef __FUNCT__
2620674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
262112edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
2622674ae819SStefano Zampini {
2623674ae819SStefano Zampini   PetscErrorCode ierr;
2624674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
262558da7f69SStefano Zampini   PetscScalar    *array;
262612edc857SStefano Zampini   Vec            from,to;
2627674ae819SStefano Zampini 
2628674ae819SStefano Zampini   PetscFunctionBegin;
262912edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
263012edc857SStefano Zampini     from = pcbddc->coarse_vec;
263112edc857SStefano Zampini     to = pcbddc->vec1_P;
263212edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
263312edc857SStefano Zampini     from = pcbddc->vec1_P;
263412edc857SStefano Zampini     to = pcbddc->coarse_vec;
263512edc857SStefano Zampini   }
263612edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
263712edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
263812edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
263912edc857SStefano Zampini       Vec tvec;
264058da7f69SStefano Zampini 
264112edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
264258da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
264358da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
264458da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
264558da7f69SStefano Zampini     }
264658da7f69SStefano Zampini   } else {
264758da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
264858da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
264912edc857SStefano Zampini     }
265012edc857SStefano Zampini   }
2651674ae819SStefano Zampini   PetscFunctionReturn(0);
2652674ae819SStefano Zampini }
2653674ae819SStefano Zampini 
2654984c4197SStefano Zampini /* uncomment for testing purposes */
2655984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
2656674ae819SStefano Zampini #undef __FUNCT__
2657674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
2658674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
2659674ae819SStefano Zampini {
2660674ae819SStefano Zampini   PetscErrorCode    ierr;
2661674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
2662674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
2663674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
2664984c4197SStefano Zampini   /* one and zero */
2665984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
2666984c4197SStefano Zampini   /* space to store constraints and their local indices */
26679162d606SStefano Zampini   PetscScalar       *constraints_data;
26689162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
26699162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
26709162d606SStefano Zampini   PetscInt          *constraints_n;
2671984c4197SStefano Zampini   /* iterators */
2672b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
2673984c4197SStefano Zampini   /* BLAS integers */
2674e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
2675e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
2676c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
2677727cdba6SStefano Zampini   /* reuse */
26780e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
26790e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
2680984c4197SStefano Zampini   /* change of basis */
2681b3d85658SStefano Zampini   PetscBool         qr_needed;
26829162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
2683984c4197SStefano Zampini   /* auxiliary stuff */
268464efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
26858a0068c3SStefano Zampini   PetscInt          ncc;
2686984c4197SStefano Zampini   /* some quantities */
268745a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
2688a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
2689984c4197SStefano Zampini 
2690674ae819SStefano Zampini   PetscFunctionBegin;
26918e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
26928e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
26938e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
2694088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
2695088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
26960e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
26970e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
26980e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
26990e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
27000e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
2701088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
2702cf5a6209SStefano Zampini 
2703cf5a6209SStefano Zampini   /* print some info */
2704cf5a6209SStefano Zampini   if (pcbddc->dbg_flag) {
2705cf5a6209SStefano Zampini     IS       vertices;
2706cf5a6209SStefano Zampini     PetscInt nv,nedges,nfaces;
2707cf5a6209SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
2708cf5a6209SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
2709cf5a6209SStefano Zampini     ierr = ISDestroy(&vertices);CHKERRQ(ierr);
2710cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
2711cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2712cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
2713fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
2714fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
2715cf5a6209SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2716cf5a6209SStefano Zampini   }
2717cf5a6209SStefano Zampini 
2718cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
27199162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
2720cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
2721cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
2722cf5a6209SStefano Zampini     Vec          *localnearnullsp;
2723cf5a6209SStefano Zampini     PetscScalar  *array;
2724cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
2725cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
2726674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
2727b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
2728674ae819SStefano Zampini     PetscScalar  *work;
2729674ae819SStefano Zampini     PetscReal    *singular_vals;
2730674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2731674ae819SStefano Zampini     PetscReal    *rwork;
2732674ae819SStefano Zampini #endif
2733674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2734674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
2735674ae819SStefano Zampini #else
2736964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
2737964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
2738674ae819SStefano Zampini #endif
2739674ae819SStefano Zampini 
2740674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
2741d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
2742d06fc5fdSStefano Zampini     /* free unneeded index sets */
2743d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
2744d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
2745674ae819SStefano Zampini     }
2746d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
2747d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
2748d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
2749d06fc5fdSStefano Zampini       }
2750d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
2751d06fc5fdSStefano Zampini       n_ISForEdges = 0;
2752d06fc5fdSStefano Zampini     }
2753d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
2754d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
2755d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
2756d06fc5fdSStefano Zampini       }
2757d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
2758d06fc5fdSStefano Zampini       n_ISForFaces = 0;
2759d06fc5fdSStefano Zampini     }
276070022509SStefano Zampini 
276170022509SStefano Zampini #if defined(PETSC_USE_DEBUG)
276270022509SStefano Zampini     /* HACK: when solving singular problems not using vertices, a change of basis is mandatory.
276370022509SStefano Zampini        Also use_change_of_basis should be consistent among processors */
276470022509SStefano Zampini     if (pcbddc->NullSpace) {
276570022509SStefano Zampini       PetscBool tbool[2],gbool[2];
276670022509SStefano Zampini 
276770022509SStefano Zampini       if (!ISForVertices && !pcbddc->user_ChangeOfBasisMatrix) {
2768b8ffe317SStefano Zampini         pcbddc->use_change_of_basis = PETSC_TRUE;
2769d06fc5fdSStefano Zampini         if (!ISForEdges) {
2770d06fc5fdSStefano Zampini           pcbddc->use_change_on_faces = PETSC_TRUE;
2771d06fc5fdSStefano Zampini         }
2772b8ffe317SStefano Zampini       }
2773d06fc5fdSStefano Zampini       tbool[0] = pcbddc->use_change_of_basis;
2774d06fc5fdSStefano Zampini       tbool[1] = pcbddc->use_change_on_faces;
2775d06fc5fdSStefano Zampini       ierr = MPI_Allreduce(tbool,gbool,2,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2776d06fc5fdSStefano Zampini       pcbddc->use_change_of_basis = gbool[0];
2777d06fc5fdSStefano Zampini       pcbddc->use_change_on_faces = gbool[1];
277898a51de6SStefano Zampini     }
277970022509SStefano Zampini #endif
278008122e43SStefano Zampini 
2781674ae819SStefano Zampini     /* check if near null space is attached to global mat */
2782674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
2783674ae819SStefano Zampini     if (nearnullsp) {
2784674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
2785f4ddd8eeSStefano Zampini       /* remove any stored info */
2786f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
2787f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
2788f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
2789f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
2790f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
2791473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
2792f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
2793f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
2794f4ddd8eeSStefano Zampini       }
2795984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
2796984c4197SStefano Zampini       nnsp_size = 0;
2797674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
2798674ae819SStefano Zampini     }
2799984c4197SStefano Zampini     /* get max number of constraints on a single cc */
2800984c4197SStefano Zampini     max_constraints = nnsp_size;
2801984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
2802984c4197SStefano Zampini 
2803674ae819SStefano Zampini     /*
2804674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
28059162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
28069162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
28079162d606SStefano Zampini          There can be multiple constraints per connected component
2808674ae819SStefano Zampini                                                                                                                                                            */
2809674ae819SStefano Zampini     n_vertices = 0;
2810674ae819SStefano Zampini     if (ISForVertices) {
2811674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
2812674ae819SStefano Zampini     }
28139162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
28149162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
28159162d606SStefano Zampini 
28169162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
28179162d606SStefano Zampini     total_counts *= max_constraints;
2818674ae819SStefano Zampini     total_counts += n_vertices;
28194641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
28209162d606SStefano Zampini 
2821674ae819SStefano Zampini     total_counts = 0;
2822674ae819SStefano Zampini     max_size_of_constraint = 0;
2823674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
28249162d606SStefano Zampini       IS used_is;
2825674ae819SStefano Zampini       if (i<n_ISForEdges) {
28269162d606SStefano Zampini         used_is = ISForEdges[i];
2827674ae819SStefano Zampini       } else {
28289162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
2829674ae819SStefano Zampini       }
28309162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
2831674ae819SStefano Zampini       total_counts += j;
2832674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
2833674ae819SStefano Zampini     }
28349162d606SStefano 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);
28359162d606SStefano Zampini 
2836984c4197SStefano Zampini     /* get local part of global near null space vectors */
2837785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
2838984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
2839984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
2840e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2841e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2842984c4197SStefano Zampini     }
2843674ae819SStefano Zampini 
2844242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
2845242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
2846a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
2847242a89d7SStefano Zampini 
2848984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
2849a773dcb8SStefano Zampini     if (!skip_lapack) {
2850674ae819SStefano Zampini       PetscScalar temp_work;
2851911cabfeSStefano Zampini 
2852674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2853984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
2854785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
2855785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
2856785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
2857674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2858785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
2859674ae819SStefano Zampini #endif
2860674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
2861c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
2862c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
2863674ae819SStefano Zampini       lwork = -1;
2864674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2865674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
2866c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
2867674ae819SStefano Zampini #else
2868c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
2869674ae819SStefano Zampini #endif
2870674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
2871984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
2872674ae819SStefano Zampini #else /* on missing GESVD */
2873674ae819SStefano Zampini       /* SVD */
2874674ae819SStefano Zampini       PetscInt max_n,min_n;
2875674ae819SStefano Zampini       max_n = max_size_of_constraint;
2876984c4197SStefano Zampini       min_n = max_constraints;
2877984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
2878674ae819SStefano Zampini         min_n = max_size_of_constraint;
2879984c4197SStefano Zampini         max_n = max_constraints;
2880674ae819SStefano Zampini       }
2881785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
2882674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2883785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
2884674ae819SStefano Zampini #endif
2885674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
2886674ae819SStefano Zampini       lwork = -1;
2887e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
2888e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
2889b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
2890674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2891674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
28929162d606SStefano 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));
2893674ae819SStefano Zampini #else
28949162d606SStefano 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));
2895674ae819SStefano Zampini #endif
2896674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
2897984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
2898984c4197SStefano Zampini #endif /* on missing GESVD */
2899674ae819SStefano Zampini       /* Allocate optimal workspace */
2900674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
2901854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
2902674ae819SStefano Zampini     }
2903674ae819SStefano Zampini     /* Now we can loop on constraining sets */
2904674ae819SStefano Zampini     total_counts = 0;
29059162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
29069162d606SStefano Zampini     constraints_data_ptr[0] = 0;
2907674ae819SStefano Zampini     /* vertices */
29089162d606SStefano Zampini     if (n_vertices) {
2909674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
29109162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
2911674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
29129162d606SStefano Zampini         constraints_n[total_counts] = 1;
29139162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
29149162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
29159162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
2916674ae819SStefano Zampini         total_counts++;
2917674ae819SStefano Zampini       }
2918674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2919674ae819SStefano Zampini       n_vertices = total_counts;
2920674ae819SStefano Zampini     }
2921984c4197SStefano Zampini 
2922674ae819SStefano Zampini     /* edges and faces */
29239162d606SStefano Zampini     total_counts_cc = total_counts;
2924911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
29259162d606SStefano Zampini       IS        used_is;
29269162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
29279162d606SStefano Zampini 
2928911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
29299162d606SStefano Zampini         used_is = ISForEdges[ncc];
2930984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
2931674ae819SStefano Zampini       } else {
29329162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
2933984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
2934674ae819SStefano Zampini       }
2935674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
29369162d606SStefano Zampini 
29379162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
29389162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2939984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
2940984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
2941674ae819SStefano Zampini       if (nnsp_has_cnst) {
29425b08dc53SStefano Zampini         PetscScalar quad_value;
29439162d606SStefano Zampini 
29449162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
29459162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
29469162d606SStefano Zampini 
2947a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
2948674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
2949a773dcb8SStefano Zampini         } else {
2950a773dcb8SStefano Zampini           quad_value = 1.0;
2951a773dcb8SStefano Zampini         }
2952674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
29539162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
2954674ae819SStefano Zampini         }
29559162d606SStefano Zampini         temp_constraints++;
2956674ae819SStefano Zampini         total_counts++;
2957674ae819SStefano Zampini       }
2958674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
2959984c4197SStefano Zampini         PetscReal real_value;
29609162d606SStefano Zampini         PetscScalar *ptr_to_data;
29619162d606SStefano Zampini 
2962984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
29639162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
2964674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
29659162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
2966674ae819SStefano Zampini         }
2967984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
2968984c4197SStefano Zampini         /* check if array is null on the connected component */
2969e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
29709162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
29715b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
2972674ae819SStefano Zampini           temp_constraints++;
2973674ae819SStefano Zampini           total_counts++;
29749162d606SStefano Zampini           if (!idxs_copied) {
29759162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
29769162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
2977674ae819SStefano Zampini           }
2978674ae819SStefano Zampini         }
29799162d606SStefano Zampini       }
29809162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
298145a1bb75SStefano Zampini       valid_constraints = temp_constraints;
2982eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
2983a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
29849162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
29859162d606SStefano Zampini 
29869162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
2987a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
29889162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
2989a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
29909162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
2991a773dcb8SStefano Zampini         } else { /* perform SVD */
2992984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
29939162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
2994674ae819SStefano Zampini 
2995674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2996984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
2997984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
2998984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
2999984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
3000984c4197SStefano Zampini                 from that computed using LAPACKgesvd
3001984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
3002984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
3003984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
3004674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
3005e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3006984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3007674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
3008674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
30099162d606SStefano 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));
3010674ae819SStefano Zampini             }
3011674ae819SStefano Zampini           }
3012e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
3013e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3014e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
3015674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
3016c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
3017674ae819SStefano Zampini #else
3018c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
3019674ae819SStefano Zampini #endif
3020674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3021984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
3022984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
3023674ae819SStefano Zampini           j = 0;
3024984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
3025674ae819SStefano Zampini           total_counts = total_counts-j;
302645a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
3027e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
3028c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3029c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3030c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
3031c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3032c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
3033c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
3034674ae819SStefano Zampini           if (j<temp_constraints) {
3035984c4197SStefano Zampini             PetscInt ii;
3036984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
3037674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
30389162d606SStefano 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));
3039674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
3040984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
3041674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
30429162d606SStefano 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];
3043674ae819SStefano Zampini               }
3044674ae819SStefano Zampini             }
3045674ae819SStefano Zampini           }
3046674ae819SStefano Zampini #else  /* on missing GESVD */
3047e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3048e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3049b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3050674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3051674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
30529162d606SStefano 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));
3053674ae819SStefano Zampini #else
30549162d606SStefano 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));
3055674ae819SStefano Zampini #endif
3056984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
3057674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3058984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
3059e310c8b4SStefano Zampini           k = temp_constraints;
3060e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
3061674ae819SStefano Zampini           j = 0;
3062e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
306345a1bb75SStefano Zampini           valid_constraints = k-j;
3064911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
3065984c4197SStefano Zampini #endif /* on missing GESVD */
3066674ae819SStefano Zampini         }
3067a773dcb8SStefano Zampini       }
30689162d606SStefano Zampini       /* update pointers information */
30699162d606SStefano Zampini       if (valid_constraints) {
30709162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
30719162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
30729162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
30739162d606SStefano Zampini         /* set change_of_basis flag */
307445a1bb75SStefano Zampini         if (boolforchange) {
3075b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
30769162d606SStefano Zampini         }
3077b3d85658SStefano Zampini         total_counts_cc++;
307845a1bb75SStefano Zampini       }
307945a1bb75SStefano Zampini     }
3080984c4197SStefano Zampini     /* free workspace */
30818f1c130eSStefano Zampini     if (!skip_lapack) {
3082984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
3083984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3084984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
3085984c4197SStefano Zampini #endif
3086984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
3087984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3088984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
3089984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
3090984c4197SStefano Zampini #endif
3091984c4197SStefano Zampini     }
3092984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
3093984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
3094984c4197SStefano Zampini     }
3095984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
3096cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
3097cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
3098cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
3099cf5a6209SStefano Zampini     }
3100cf5a6209SStefano Zampini     if (n_ISForFaces) {
3101cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
3102cf5a6209SStefano Zampini     }
3103cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
3104cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
3105cf5a6209SStefano Zampini     }
3106cf5a6209SStefano Zampini     if (n_ISForEdges) {
3107cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
3108cf5a6209SStefano Zampini     }
3109cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
311008122e43SStefano Zampini   } else {
311108122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
3112984c4197SStefano Zampini 
311308122e43SStefano Zampini     total_counts = 0;
311408122e43SStefano Zampini     n_vertices = 0;
3115d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
3116d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
311708122e43SStefano Zampini     }
311808122e43SStefano Zampini     max_constraints = 0;
31199162d606SStefano Zampini     total_counts_cc = 0;
312008122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
312108122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
31229162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
312308122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
312408122e43SStefano Zampini     }
31259162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
31269162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
31279162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
31289162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
312974d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
31309162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
31319162d606SStefano Zampini     total_counts_cc = 0;
31329162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
31339162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
31349162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
313508122e43SStefano Zampini       }
313608122e43SStefano Zampini     }
31379162d606SStefano Zampini #if 0
31389162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
31399162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
31409162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
31419162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
31429162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
31439162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
31449162d606SStefano Zampini       }
31459162d606SStefano Zampini       printf("\n");
31469162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
31479162d606SStefano Zampini     }
31481b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
31498bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
31501b968477SStefano Zampini     }
31511b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
31528bec7fa6SStefano 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]);
31531b968477SStefano Zampini     }
315408122e43SStefano Zampini #endif
315508122e43SStefano Zampini 
31568bec7fa6SStefano Zampini     max_size_of_constraint = 0;
31579162d606SStefano 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]);
31589162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
315908122e43SStefano Zampini     /* Change of basis */
3160b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
316108122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
316208122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
316308122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
3164b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
316508122e43SStefano Zampini         }
316608122e43SStefano Zampini       }
316708122e43SStefano Zampini     }
316808122e43SStefano Zampini   }
3169984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
31704f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
317108122e43SStefano Zampini 
31729162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
31739162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
31749162d606SStefano Zampini   if (i != constraints_idxs_ptr[total_counts_cc]) {
31759162d606SStefano 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);
317608122e43SStefano Zampini   }
3177674ae819SStefano Zampini 
3178674ae819SStefano Zampini   /* Create constraint matrix */
3179674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
318016f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
3181984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
3182984c4197SStefano Zampini 
3183984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
3184a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
3185a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
318674d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
3187984c4197SStefano Zampini   total_primal_vertices=0;
3188b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
31899162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
31909162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
3191984c4197SStefano Zampini     if (size_of_constraint == 1) {
31929162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
3193b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
319464efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
31959162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
31969162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
3197a717540cSStefano Zampini       }
3198b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
319974d5cdf7SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single || pcbddc->faster_deluxe) {
3200a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
3201a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
3202a717540cSStefano Zampini       }
3203fa434743SStefano Zampini     } else {
3204b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
3205fa434743SStefano Zampini     }
3206a717540cSStefano Zampini   }
3207b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
3208b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
3209674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
321070022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
3211b3d85658SStefano Zampini 
32124f1b2e48SStefano Zampini   ierr = PetscMalloc2(pcbddc->local_primal_size_cc+pcbddc->benign_n,&pcbddc->local_primal_ref_node,pcbddc->local_primal_size_cc+pcbddc->benign_n,&pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
32130e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
32140e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
3215984c4197SStefano Zampini 
3216984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
321774d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
3218785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
3219984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
322074d5cdf7SStefano Zampini 
3221984c4197SStefano Zampini   j = total_primal_vertices;
322274d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
3223b3d85658SStefano Zampini   cum = total_primal_vertices;
32249162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
32254641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
3226b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
3227b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
3228b3d85658SStefano Zampini       cum++;
32299162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
323074d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
323174d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
323274d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
323374d5cdf7SStefano Zampini       }
32349162d606SStefano Zampini       j += constraints_n[i];
3235674ae819SStefano Zampini     }
3236674ae819SStefano Zampini   }
3237674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
3238674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
3239088faed8SStefano Zampini 
3240674ae819SStefano Zampini   /* set values in constraint matrix */
3241984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
32420e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
3243674ae819SStefano Zampini   }
3244984c4197SStefano Zampini   total_counts = total_primal_vertices;
32459162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
32464641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
32479162d606SStefano Zampini       PetscInt *cols;
32489162d606SStefano Zampini 
32499162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
32509162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
32519162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
32529162d606SStefano Zampini         PetscInt    row = total_counts+k;
32539162d606SStefano Zampini         PetscScalar *vals;
32549162d606SStefano Zampini 
32559162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
32569162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
32579162d606SStefano Zampini       }
32589162d606SStefano Zampini       total_counts += constraints_n[i];
3259674ae819SStefano Zampini     }
3260674ae819SStefano Zampini   }
3261674ae819SStefano Zampini   /* assembling */
3262674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3263674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3264088faed8SStefano Zampini 
3265984c4197SStefano Zampini   /*
326645a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
3267984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
3268984c4197SStefano Zampini   */
3269674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
3270674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
3271026de310SStefano Zampini     /* dual and primal dofs on a single cc */
3272984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
3273984c4197SStefano Zampini     /* working stuff for GEQRF */
327481d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
3275984c4197SStefano Zampini     PetscBLASInt lqr_work;
3276984c4197SStefano Zampini     /* working stuff for UNGQR */
3277984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
3278984c4197SStefano Zampini     PetscBLASInt lgqr_work;
3279984c4197SStefano Zampini     /* working stuff for TRTRS */
3280984c4197SStefano Zampini     PetscScalar  *trs_rhs;
32813f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
3282984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
3283984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
3284984c4197SStefano Zampini     PetscScalar  *start_vals;
3285984c4197SStefano Zampini     /* working stuff for values insertion */
32864641a718SStefano Zampini     PetscBT      is_primal;
328764efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
3288906d46d4SStefano Zampini     /* matrix sizes */
3289906d46d4SStefano Zampini     PetscInt     global_size,local_size;
3290906d46d4SStefano Zampini     /* temporary change of basis */
3291906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
3292cf5a6209SStefano Zampini     /* extra space for debugging */
3293cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
3294984c4197SStefano Zampini 
3295906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
3296906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
329716f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
3298bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
3299906d46d4SStefano Zampini     /* nonzeros for local mat */
3300bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
3301bbb9e6c6SStefano Zampini     for (i=0;i<pcis->n;i++) nnz[i]=1;
33029162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
3303a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
33049162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
3305a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
33069162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
3307a717540cSStefano Zampini         } else {
33089162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
33099162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
3310a717540cSStefano Zampini         }
3311a717540cSStefano Zampini       }
3312a717540cSStefano Zampini     }
3313906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
3314bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
3315a717540cSStefano Zampini     /* Set initial identity in the matrix */
3316bbb9e6c6SStefano Zampini     for (i=0;i<pcis->n;i++) {
3317906d46d4SStefano Zampini       ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
3318a717540cSStefano Zampini     }
3319a717540cSStefano Zampini 
3320a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
3321a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3322a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
3323a717540cSStefano Zampini     }
3324a717540cSStefano Zampini 
3325a717540cSStefano Zampini 
3326a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
3327a717540cSStefano Zampini     /*
3328a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
3329a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
3330a717540cSStefano Zampini 
3331a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
3332a717540cSStefano Zampini 
3333a6b551f4SStefano 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)
3334a6b551f4SStefano Zampini 
3335a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
3336a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
3337a717540cSStefano Zampini             |              ...                        |
3338a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
3339a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
3340a717540cSStefano Zampini 
3341a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
3342a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
3343a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
3344a6b551f4SStefano Zampini 
3345a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
3346a717540cSStefano Zampini     */
3347a717540cSStefano Zampini     if (qr_needed) {
3348984c4197SStefano Zampini       /* space to store Q */
3349854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
3350984c4197SStefano Zampini       /* first we issue queries for optimal work */
33513f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
33523f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
33533f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3354984c4197SStefano Zampini       lqr_work = -1;
33553f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
3356984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
3357984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
3358785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
3359984c4197SStefano Zampini       lgqr_work = -1;
33603f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
33613f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
33623f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
33633f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
33643f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
33653f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
3366984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
3367984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
3368785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
3369984c4197SStefano Zampini       /* array to store scaling factors for reflectors */
3370785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
3371984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
3372785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
3373a717540cSStefano Zampini       /* allocating workspace for check */
3374a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
3375cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
3376a717540cSStefano Zampini       }
3377a717540cSStefano Zampini     }
3378984c4197SStefano Zampini     /* array to store whether a node is primal or not */
33794641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
3380473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
33810e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
338239e2fb2aSStefano Zampini     if (i != total_primal_vertices) {
338339e2fb2aSStefano Zampini       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %d != %d\n",total_primal_vertices,i);
33844641a718SStefano Zampini     }
338539e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
338639e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
338739e2fb2aSStefano Zampini     }
338839e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
3389984c4197SStefano Zampini 
3390a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
33919162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
33929162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
33934641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
3394984c4197SStefano Zampini         /* get constraint info */
33959162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
3396984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
3397984c4197SStefano Zampini 
3398984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
33999162d606SStefano 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);
3400674ae819SStefano Zampini         }
3401984c4197SStefano Zampini 
3402fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
3403a717540cSStefano Zampini 
3404a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
3405a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
34069162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3407a717540cSStefano Zampini           }
3408984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
34099162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3410984c4197SStefano Zampini 
3411984c4197SStefano Zampini           /* compute QR decomposition of constraints */
34123f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
34133f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
34143f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3415674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
34163f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
3417984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
3418674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3419984c4197SStefano Zampini 
3420984c4197SStefano Zampini           /* explictly compute R^-T */
3421984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
3422984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
34233f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
34243f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
34253f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
34263f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
3427984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
34283f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
3429984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
3430984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3431984c4197SStefano Zampini 
3432a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
34333f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
34343f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
34353f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
34363f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3437984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
34383f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
3439984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
3440984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3441984c4197SStefano Zampini 
3442984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
3443984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
3444984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
34453f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
34463f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
34473f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
34483f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
34493f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
34503f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
3451984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
34529162d606SStefano 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));
3453984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
34549162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3455984c4197SStefano Zampini 
3456984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
34579162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
3458984c4197SStefano Zampini           /* insert cols for primal dofs */
3459984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
3460984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
34619162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
3462906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
3463984c4197SStefano Zampini           }
3464984c4197SStefano Zampini           /* insert cols for dual dofs */
3465984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
34669162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
3467984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
34689162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
3469906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
3470984c4197SStefano Zampini               j++;
3471674ae819SStefano Zampini             }
3472674ae819SStefano Zampini           }
3473984c4197SStefano Zampini 
3474984c4197SStefano Zampini           /* check change of basis */
3475984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
3476984c4197SStefano Zampini             PetscInt   ii,jj;
3477984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
3478c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
3479c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3480c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
3481c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3482c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
3483c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
3484984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3485cf5a6209SStefano 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));
3486984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
3487984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
3488984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
3489cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
3490cf5a6209SStefano 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;
3491674ae819SStefano Zampini               }
3492674ae819SStefano Zampini             }
3493984c4197SStefano Zampini             if (!valid_qr) {
349422d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
3495984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
3496984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
3497cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
3498cf5a6209SStefano 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]));
3499674ae819SStefano Zampini                   }
3500cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
3501cf5a6209SStefano 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]));
3502984c4197SStefano Zampini                   }
3503984c4197SStefano Zampini                 }
3504984c4197SStefano Zampini               }
3505674ae819SStefano Zampini             } else {
350622d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
3507674ae819SStefano Zampini             }
3508674ae819SStefano Zampini           }
3509a717540cSStefano Zampini         } else { /* simple transformation block */
3510a717540cSStefano Zampini           PetscInt    row,col;
3511a6b551f4SStefano Zampini           PetscScalar val,norm;
3512a6b551f4SStefano Zampini 
3513a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
35149162d606SStefano 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));
3515a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
35169162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
35179162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
3518bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
35199162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
3520906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
35219162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
3522a717540cSStefano Zampini             } else {
3523a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
35249162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
3525a717540cSStefano Zampini                 if (row != col) {
35269162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
3527a717540cSStefano Zampini                 } else {
35289162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
3529a717540cSStefano Zampini                 }
3530906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
3531a717540cSStefano Zampini               }
3532a717540cSStefano Zampini             }
3533a717540cSStefano Zampini           }
353498a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
353522d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
3536a717540cSStefano Zampini           }
3537674ae819SStefano Zampini         }
3538984c4197SStefano Zampini       } else {
3539984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
35409162d606SStefano 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);
3541674ae819SStefano Zampini         }
3542674ae819SStefano Zampini       }
3543674ae819SStefano Zampini     }
3544a717540cSStefano Zampini 
3545a717540cSStefano Zampini     /* free workspace */
3546a717540cSStefano Zampini     if (qr_needed) {
3547984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
3548cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
3549984c4197SStefano Zampini       }
3550984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
3551984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
3552984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
3553984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
3554984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
3555674ae819SStefano Zampini     }
3556a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
3557906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3558906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3559906d46d4SStefano Zampini 
3560906d46d4SStefano Zampini     /* assembling of global change of variable */
3561bbb9e6c6SStefano Zampini     {
3562bbb9e6c6SStefano Zampini       Mat      tmat;
356316f15bc4SStefano Zampini       PetscInt bs;
356416f15bc4SStefano Zampini 
3565906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
3566906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
3567bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
3568bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
3569bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3570bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
357116f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
357216f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
3573906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
3574bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
3575bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3576bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
3577bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
3578bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
3579e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3580e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3581bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
3582bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
3583906d46d4SStefano Zampini     }
3584906d46d4SStefano Zampini     /* check */
3585906d46d4SStefano Zampini     if (pcbddc->dbg_flag) {
3586906d46d4SStefano Zampini       PetscReal error;
3587906d46d4SStefano Zampini       Vec       x,x_change;
3588906d46d4SStefano Zampini 
3589906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
3590906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
3591906d46d4SStefano Zampini       ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
3592906d46d4SStefano Zampini       ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
3593e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3594e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3595bbb9e6c6SStefano Zampini       ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
3596e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3597e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3598906d46d4SStefano Zampini       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
3599906d46d4SStefano Zampini       ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
3600906d46d4SStefano Zampini       ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
3601906d46d4SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3602bbb9e6c6SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
3603906d46d4SStefano Zampini       ierr = VecDestroy(&x);CHKERRQ(ierr);
3604906d46d4SStefano Zampini       ierr = VecDestroy(&x_change);CHKERRQ(ierr);
3605906d46d4SStefano Zampini     }
3606b96c3477SStefano Zampini 
3607b96c3477SStefano Zampini     /* adapt sub_schurs computed (if any) */
3608b96c3477SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
3609b96c3477SStefano Zampini       PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
3610b96c3477SStefano Zampini       if (sub_schurs->S_Ej_all) {
3611ac632422SStefano Zampini         Mat                    S_new,tmat;
3612b087196eSStefano Zampini         ISLocalToGlobalMapping NtoSall;
3613b087196eSStefano Zampini         IS                     is_all_N,is_V,is_V_Sall;
3614b087196eSStefano Zampini         const PetscScalar      *array;
3615b087196eSStefano Zampini         const PetscInt         *idxs_V,*idxs_all;
3616b087196eSStefano Zampini         PetscInt               i,n_V;
3617bbb9e6c6SStefano Zampini 
3618bbb9e6c6SStefano Zampini         ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
36196816873aSStefano Zampini         ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
3620b087196eSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
3621b087196eSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
3622b087196eSStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
3623b087196eSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
3624bbb9e6c6SStefano Zampini         ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
3625b087196eSStefano Zampini         ierr = ISDestroy(&is_V);CHKERRQ(ierr);
3626ac632422SStefano Zampini         ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
3627b96c3477SStefano Zampini         ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
3628ac632422SStefano Zampini         ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
3629b087196eSStefano Zampini         ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
3630b087196eSStefano Zampini         ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
3631b087196eSStefano Zampini         ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
3632b087196eSStefano Zampini         ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
3633b087196eSStefano Zampini         ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
3634b087196eSStefano Zampini         for (i=0;i<n_V;i++) {
3635b087196eSStefano Zampini           PetscScalar val;
3636b087196eSStefano Zampini           PetscInt    idx;
3637b087196eSStefano Zampini 
3638b087196eSStefano Zampini           idx = idxs_V[i];
3639b087196eSStefano Zampini           val = array[idxs_all[idxs_V[i]]];
3640b087196eSStefano Zampini           ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
3641b087196eSStefano Zampini         }
3642b087196eSStefano Zampini         ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3643b087196eSStefano Zampini         ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3644ac632422SStefano Zampini         sub_schurs->S_Ej_all = S_new;
3645ac632422SStefano Zampini         ierr = MatDestroy(&S_new);CHKERRQ(ierr);
3646ac632422SStefano Zampini         if (sub_schurs->sum_S_Ej_all) {
3647ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
3648b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
3649ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
3650b087196eSStefano Zampini           ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
3651ac632422SStefano Zampini           sub_schurs->sum_S_Ej_all = S_new;
3652ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
3653ac632422SStefano Zampini         }
3654b087196eSStefano Zampini         ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
3655b087196eSStefano Zampini         ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
3656b087196eSStefano Zampini         ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
3657b96c3477SStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
3658b087196eSStefano Zampini         ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
3659b96c3477SStefano Zampini       }
3660b96c3477SStefano Zampini     }
3661906d46d4SStefano Zampini     ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
3662906d46d4SStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix) {
3663b9b85e73SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3664b9b85e73SStefano Zampini     pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
3665b9b85e73SStefano Zampini   }
3666906d46d4SStefano Zampini 
3667906d46d4SStefano Zampini   /* set up change of basis context */
3668906d46d4SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
3669906d46d4SStefano Zampini     PCBDDCChange_ctx change_ctx;
3670906d46d4SStefano Zampini 
3671906d46d4SStefano Zampini     if (!pcbddc->new_global_mat) {
3672906d46d4SStefano Zampini       PetscInt global_size,local_size;
3673906d46d4SStefano Zampini 
3674906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
3675906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
3676906d46d4SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->new_global_mat);CHKERRQ(ierr);
3677906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->new_global_mat,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
3678906d46d4SStefano Zampini       ierr = MatSetType(pcbddc->new_global_mat,MATSHELL);CHKERRQ(ierr);
3679906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT,(void (*)(void))PCBDDCMatMult_Private);CHKERRQ(ierr);
3680906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCMatMultTranspose_Private);CHKERRQ(ierr);
3681906d46d4SStefano Zampini       ierr = PetscNew(&change_ctx);CHKERRQ(ierr);
3682906d46d4SStefano Zampini       ierr = MatShellSetContext(pcbddc->new_global_mat,change_ctx);CHKERRQ(ierr);
3683906d46d4SStefano Zampini     } else {
3684906d46d4SStefano Zampini       ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
3685906d46d4SStefano Zampini       ierr = MatDestroy(&change_ctx->global_change);CHKERRQ(ierr);
3686906d46d4SStefano Zampini       ierr = VecDestroyVecs(2,&change_ctx->work);CHKERRQ(ierr);
3687906d46d4SStefano Zampini     }
3688906d46d4SStefano Zampini     if (!pcbddc->user_ChangeOfBasisMatrix) {
3689906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3690906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->ChangeOfBasisMatrix;
3691906d46d4SStefano Zampini     } else {
3692906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3693906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->user_ChangeOfBasisMatrix;
3694906d46d4SStefano Zampini     }
3695906d46d4SStefano Zampini     ierr = VecDuplicateVecs(pcis->vec1_global,2,&change_ctx->work);CHKERRQ(ierr);
3696906d46d4SStefano Zampini     ierr = MatSetUp(pcbddc->new_global_mat);CHKERRQ(ierr);
3697906d46d4SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3698906d46d4SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3699b9b85e73SStefano Zampini   }
3700a717540cSStefano Zampini 
37014f1b2e48SStefano Zampini   /* add pressure dofs to set of primal nodes for numbering purposes */
37024f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
37034f1b2e48SStefano Zampini     pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
37044f1b2e48SStefano Zampini     pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
3705019a44ceSStefano Zampini     pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
3706019a44ceSStefano Zampini     pcbddc->local_primal_size_cc++;
3707019a44ceSStefano Zampini     pcbddc->local_primal_size++;
3708019a44ceSStefano Zampini   }
3709019a44ceSStefano Zampini 
3710019a44ceSStefano Zampini   /* check if a new primal space has been introduced (also take into account benign trick) */
3711727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_TRUE;
3712727cdba6SStefano Zampini   if (olocal_primal_size == pcbddc->local_primal_size) {
3713aff50787SStefano 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);
3714c1c8e736SStefano Zampini     pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
37150e6343abSStefano Zampini     if (!pcbddc->new_primal_space_local) {
3716aff50787SStefano 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);
3717727cdba6SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
3718727cdba6SStefano Zampini     }
37190e6343abSStefano Zampini   }
37200e6343abSStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
3721727cdba6SStefano Zampini   /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
3722727cdba6SStefano Zampini   ierr = MPI_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
3723727cdba6SStefano Zampini 
3724a717540cSStefano Zampini   /* flush dbg viewer */
3725b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
3726b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3727b8ffe317SStefano Zampini   }
3728a717540cSStefano Zampini 
3729e310c8b4SStefano Zampini   /* free workspace */
3730a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
37314641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
373208122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
37339162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
37349162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
373508122e43SStefano Zampini   } else {
37369162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
37379162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
37389162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
373908122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
374008122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
37419162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
37429162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
374308122e43SStefano Zampini   }
3744674ae819SStefano Zampini   PetscFunctionReturn(0);
3745674ae819SStefano Zampini }
3746674ae819SStefano Zampini 
3747674ae819SStefano Zampini #undef __FUNCT__
3748674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
3749674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
3750674ae819SStefano Zampini {
3751674ae819SStefano Zampini   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
3752674ae819SStefano Zampini   PC_IS       *pcis = (PC_IS*)pc->data;
3753674ae819SStefano Zampini   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
37547fb0e2dbSStefano Zampini   PetscInt    ierr,i,vertex_size,N;
3755674ae819SStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
3756674ae819SStefano Zampini 
3757674ae819SStefano Zampini   PetscFunctionBegin;
37588e61c736SStefano Zampini   /* Reset previously computed graph */
37598e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
3760674ae819SStefano Zampini   /* Init local Graph struct */
37617fb0e2dbSStefano Zampini   ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
37623bbff08aSStefano Zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,pcis->mapping,N);CHKERRQ(ierr);
3763674ae819SStefano Zampini 
3764575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
37655099eff2SStefano Zampini   if (pcbddc->mat_graph->nvtxs_csr && pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) {
37665099eff2SStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid size of local CSR graph! Found %d, expected %d\n",pcbddc->mat_graph->nvtxs_csr,pcbddc->mat_graph->nvtxs);
3767575ad6abSStefano Zampini   }
37689577ea80SStefano Zampini 
3769674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
37704d379d7bSStefano Zampini   if (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) {
37714d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
37724d379d7bSStefano Zampini     PetscInt  nvtxs;
3773e496cd5dSStefano Zampini     PetscBool flg_row=PETSC_FALSE;
3774674ae819SStefano Zampini 
37754d379d7bSStefano Zampini     if (pcbddc->use_local_adj) {
37762fffb893SStefano Zampini 
37772fffb893SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
37782fffb893SStefano Zampini       if (flg_row) {
37794d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
3780b96c3477SStefano Zampini         pcbddc->computed_rowadj = PETSC_TRUE;
37812fffb893SStefano Zampini       }
37822fffb893SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
37839b28b941SStefano 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 */
37844d379d7bSStefano Zampini       IS                     is_dummy;
37854d379d7bSStefano Zampini       ISLocalToGlobalMapping l2gmap_dummy;
37864d379d7bSStefano Zampini       PetscInt               j,sum;
37874d379d7bSStefano Zampini       PetscInt               *cxadj,*cadjncy;
37884d379d7bSStefano Zampini       const PetscInt         *idxs;
37894d379d7bSStefano Zampini       PCBDDCGraph            graph;
37904d379d7bSStefano Zampini       PetscBT                is_on_boundary;
37914d379d7bSStefano Zampini 
37924d379d7bSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcis->n,0,1,&is_dummy);CHKERRQ(ierr);
37934d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
37944d379d7bSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
37954d379d7bSStefano Zampini       ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
37967fb0e2dbSStefano Zampini       ierr = PCBDDCGraphInit(graph,l2gmap_dummy,pcis->n);CHKERRQ(ierr);
37974d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
3798e496cd5dSStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
3799e496cd5dSStefano Zampini       if (flg_row) {
38004d379d7bSStefano Zampini         graph->xadj = xadj;
38014d379d7bSStefano Zampini         graph->adjncy = adjncy;
3802e496cd5dSStefano Zampini       }
38034d379d7bSStefano Zampini       ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
38044d379d7bSStefano Zampini       ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
3805e496cd5dSStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
38064d379d7bSStefano Zampini 
38074d379d7bSStefano Zampini       if (pcbddc->dbg_flag) {
38089b28b941SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] Found %d subdomains (local size %d)\n",PetscGlobalRank,graph->ncc,pcis->n);CHKERRQ(ierr);
38094d379d7bSStefano Zampini         for (i=0;i<graph->ncc;i++) {
38104d379d7bSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] %d cc size %d\n",PetscGlobalRank,i,graph->cptr[i+1]-graph->cptr[i]);CHKERRQ(ierr);
38114d379d7bSStefano Zampini         }
38124d379d7bSStefano Zampini       }
38134d379d7bSStefano Zampini 
3814e496cd5dSStefano Zampini       ierr = PetscBTCreate(pcis->n,&is_on_boundary);CHKERRQ(ierr);
38154d379d7bSStefano Zampini       ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
38164d379d7bSStefano Zampini       for (i=0;i<pcis->n_B;i++) {
38174d379d7bSStefano Zampini         ierr = PetscBTSet(is_on_boundary,idxs[i]);CHKERRQ(ierr);
38184d379d7bSStefano Zampini       }
38194d379d7bSStefano Zampini       ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
38204d379d7bSStefano Zampini 
3821e496cd5dSStefano Zampini       ierr = PetscCalloc1(pcis->n+1,&cxadj);CHKERRQ(ierr);
38224d379d7bSStefano Zampini       sum = 0;
38234d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
38244d379d7bSStefano Zampini         PetscInt sizecc = 0;
38254d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
38264d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
38274d379d7bSStefano Zampini             sizecc++;
38284d379d7bSStefano Zampini           }
38294d379d7bSStefano Zampini         }
38304d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
38314d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
38324d379d7bSStefano Zampini             cxadj[graph->queue[j]] = sizecc;
38334d379d7bSStefano Zampini           }
38344d379d7bSStefano Zampini         }
38354d379d7bSStefano Zampini         sum += sizecc*sizecc;
38364d379d7bSStefano Zampini       }
38374d379d7bSStefano Zampini       ierr = PetscMalloc1(sum,&cadjncy);CHKERRQ(ierr);
38384d379d7bSStefano Zampini       sum = 0;
3839e496cd5dSStefano Zampini       for (i=0;i<pcis->n;i++) {
38404d379d7bSStefano Zampini         PetscInt temp = cxadj[i];
38414d379d7bSStefano Zampini         cxadj[i] = sum;
38424d379d7bSStefano Zampini         sum += temp;
38434d379d7bSStefano Zampini       }
3844e496cd5dSStefano Zampini       cxadj[pcis->n] = sum;
38454d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
38464d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
38474d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
38484d379d7bSStefano Zampini             PetscInt k,sizecc = 0;
38494d379d7bSStefano Zampini             for (k=graph->cptr[i];k<graph->cptr[i+1];k++) {
38504d379d7bSStefano Zampini               if (PetscBTLookup(is_on_boundary,graph->queue[k])) {
38514d379d7bSStefano Zampini                 cadjncy[cxadj[graph->queue[j]]+sizecc]=graph->queue[k];
38524d379d7bSStefano Zampini                 sizecc++;
38534d379d7bSStefano Zampini               }
38544d379d7bSStefano Zampini             }
38554d379d7bSStefano Zampini           }
38564d379d7bSStefano Zampini         }
38574d379d7bSStefano Zampini       }
38589b28b941SStefano Zampini       if (sum) {
3859e496cd5dSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,pcis->n,cxadj,cadjncy,PETSC_OWN_POINTER);CHKERRQ(ierr);
38604d379d7bSStefano Zampini       } else {
38614d379d7bSStefano Zampini         ierr = PetscFree(cxadj);CHKERRQ(ierr);
38624d379d7bSStefano Zampini         ierr = PetscFree(cadjncy);CHKERRQ(ierr);
38634d379d7bSStefano Zampini       }
38644d379d7bSStefano Zampini       graph->xadj = 0;
38654d379d7bSStefano Zampini       graph->adjncy = 0;
38664d379d7bSStefano Zampini       ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
38674d379d7bSStefano Zampini       ierr = PetscBTDestroy(&is_on_boundary);CHKERRQ(ierr);
38684d379d7bSStefano Zampini     }
3869674ae819SStefano Zampini   }
38709b28b941SStefano Zampini   if (pcbddc->dbg_flag) {
38719b28b941SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3872674ae819SStefano Zampini   }
3873674ae819SStefano Zampini 
387463602bcaSStefano Zampini   /* Set default dofs' splitting if no information has been provided by the user with PCBDDCSetDofsSplitting or PCBDDCSetDofsSplittingLocal */
3875674ae819SStefano Zampini   vertex_size = 1;
387663602bcaSStefano Zampini   if (pcbddc->user_provided_isfordofs) {
387763602bcaSStefano Zampini     if (pcbddc->n_ISForDofs) { /* need to convert from global to local and remove references to global dofs splitting */
387895ecbf38SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
387963602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
3880e176bc59SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
388163602bcaSStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
3882674ae819SStefano Zampini       }
388363602bcaSStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
388463602bcaSStefano Zampini       pcbddc->n_ISForDofs = 0;
388563602bcaSStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
3886674ae819SStefano Zampini     }
388763602bcaSStefano Zampini     /* mat block size as vertex size (used for elasticity with rigid body modes as nearnullspace) */
3888674ae819SStefano Zampini     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
388963602bcaSStefano Zampini   } else {
389063602bcaSStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering */
389163602bcaSStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->n_ISForDofsLocal);CHKERRQ(ierr);
3892854ce69bSBarry Smith       ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
389363602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
389463602bcaSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),pcis->n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
389563602bcaSStefano Zampini       }
389663602bcaSStefano Zampini     }
3897674ae819SStefano Zampini   }
3898674ae819SStefano Zampini 
3899674ae819SStefano Zampini   /* Setup of Graph */
3900785d1243SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) { /* need to convert from global to local */
3901e176bc59SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
3902785d1243SStefano Zampini   }
3903785d1243SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) { /* need to convert from global to local */
3904e176bc59SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
3905785d1243SStefano Zampini   }
3906302440fdSBarry Smith   ierr = PCBDDCGraphSetUp(pcbddc->mat_graph,vertex_size,pcbddc->NeumannBoundariesLocal,pcbddc->DirichletBoundariesLocal,pcbddc->n_ISForDofsLocal,pcbddc->ISForDofsLocal,pcbddc->user_primal_vertices);CHKERRQ(ierr);
3907674ae819SStefano Zampini 
39084f1b2e48SStefano Zampini   /* attach info on disconnected subdomains if present */
39094f1b2e48SStefano Zampini   if (pcbddc->n_local_subs) {
39104f1b2e48SStefano Zampini     PetscInt *local_subs;
39114f1b2e48SStefano Zampini 
39124f1b2e48SStefano Zampini     ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
39134f1b2e48SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
39144f1b2e48SStefano Zampini       const PetscInt *idxs;
39154f1b2e48SStefano Zampini       PetscInt       nl,j;
39164f1b2e48SStefano Zampini 
39174f1b2e48SStefano Zampini       ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
39184f1b2e48SStefano Zampini       ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
39194f1b2e48SStefano Zampini       for (j=0;j<nl;j++) {
39204f1b2e48SStefano Zampini         local_subs[idxs[j]] = i;
39214f1b2e48SStefano Zampini       }
39224f1b2e48SStefano Zampini       ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
39234f1b2e48SStefano Zampini     }
39244f1b2e48SStefano Zampini     pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
39254f1b2e48SStefano Zampini     pcbddc->mat_graph->local_subs = local_subs;
39264f1b2e48SStefano Zampini   }
39274f1b2e48SStefano Zampini 
3928674ae819SStefano Zampini   /* Graph's connected components analysis */
3929674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
3930674ae819SStefano Zampini 
3931674ae819SStefano Zampini   /* print some info to stdout */
3932674ae819SStefano Zampini   if (pcbddc->dbg_flag) {
3933302440fdSBarry Smith     ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,viewer);CHKERRQ(ierr);
3934674ae819SStefano Zampini   }
3935fb180af4SStefano Zampini 
3936fb180af4SStefano Zampini   /* mark topography has done */
3937fb180af4SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
3938674ae819SStefano Zampini   PetscFunctionReturn(0);
3939674ae819SStefano Zampini }
3940674ae819SStefano Zampini 
3941dc456d91SStefano Zampini /* given an index sets possibly with holes, renumbers the indexes removing the holes */
3942674ae819SStefano Zampini #undef __FUNCT__
3943674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSubsetNumbering"
3944dc456d91SStefano Zampini PetscErrorCode PCBDDCSubsetNumbering(IS subset, IS subset_mult, PetscInt *N_n, IS *subset_n)
3945674ae819SStefano Zampini {
3946dc456d91SStefano Zampini   PetscSF        sf;
3947dc456d91SStefano Zampini   PetscLayout    map;
3948dc456d91SStefano Zampini   const PetscInt *idxs;
3949dc456d91SStefano Zampini   PetscInt       *leaf_data,*root_data,*gidxs;
3950dc456d91SStefano Zampini   PetscInt       N,n,i,lbounds[2],gbounds[2],Nl;
3951dc456d91SStefano Zampini   PetscInt       n_n,nlocals,start,first_index;
3952dc456d91SStefano Zampini   PetscMPIInt    commsize;
3953674ae819SStefano Zampini   PetscBool      first_found;
3954674ae819SStefano Zampini   PetscErrorCode ierr;
3955674ae819SStefano Zampini 
3956674ae819SStefano Zampini   PetscFunctionBegin;
3957dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset,&n);CHKERRQ(ierr);
3958dc456d91SStefano Zampini   if (subset_mult) {
3959dc456d91SStefano Zampini     PetscCheckSameComm(subset,1,subset_mult,2);
3960dc456d91SStefano Zampini     ierr = ISGetLocalSize(subset,&i);CHKERRQ(ierr);
3961dc456d91SStefano Zampini     if (i != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local subset and multiplicity sizes don't match! %d != %d",n,i);
3962674ae819SStefano Zampini   }
3963dc456d91SStefano Zampini   /* create workspace layout for computing global indices of subset */
3964dc456d91SStefano Zampini   ierr = ISGetIndices(subset,&idxs);CHKERRQ(ierr);
3965dc456d91SStefano Zampini   lbounds[0] = lbounds[1] = 0;
3966dc456d91SStefano Zampini   for (i=0;i<n;i++) {
3967dc456d91SStefano Zampini     if (idxs[i] < lbounds[0]) lbounds[0] = idxs[i];
3968dc456d91SStefano Zampini     else if (idxs[i] > lbounds[1]) lbounds[1] = idxs[i];
3969674ae819SStefano Zampini   }
3970dc456d91SStefano Zampini   lbounds[0] = -lbounds[0];
3971dc456d91SStefano Zampini   ierr = MPI_Allreduce(lbounds,gbounds,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
3972dc456d91SStefano Zampini   gbounds[0] = -gbounds[0];
3973dc456d91SStefano Zampini   N = gbounds[1] - gbounds[0] + 1;
3974dc456d91SStefano Zampini   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)subset),&map);CHKERRQ(ierr);
3975dc456d91SStefano Zampini   ierr = PetscLayoutSetBlockSize(map,1);CHKERRQ(ierr);
3976dc456d91SStefano Zampini   ierr = PetscLayoutSetSize(map,N);CHKERRQ(ierr);
3977dc456d91SStefano Zampini   ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
3978dc456d91SStefano Zampini   ierr = PetscLayoutGetLocalSize(map,&Nl);CHKERRQ(ierr);
3979dc456d91SStefano Zampini 
3980dc456d91SStefano Zampini   /* create sf : leaf_data == multiplicity of indexes, root data == global index in layout */
3981dc456d91SStefano Zampini   ierr = PetscMalloc2(n,&leaf_data,Nl,&root_data);CHKERRQ(ierr);
3982dc456d91SStefano Zampini   if (subset_mult) {
3983dc456d91SStefano Zampini     const PetscInt* idxs_mult;
3984dc456d91SStefano Zampini 
3985dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
3986dc456d91SStefano Zampini     ierr = PetscMemcpy(leaf_data,idxs_mult,n*sizeof(PetscInt));CHKERRQ(ierr);
3987dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
3988674ae819SStefano Zampini   } else {
3989dc456d91SStefano Zampini     for (i=0;i<n;i++) leaf_data[i] = 1;
3990674ae819SStefano Zampini   }
3991dc456d91SStefano Zampini   /* local size of new subset */
3992dc456d91SStefano Zampini   n_n = 0;
3993dc456d91SStefano Zampini   for (i=0;i<n;i++) n_n += leaf_data[i];
3994dc456d91SStefano Zampini 
3995dc456d91SStefano Zampini   /* global indexes in layout */
3996dc456d91SStefano Zampini   ierr = PetscMalloc1(n_n,&gidxs);CHKERRQ(ierr); /* allocating possibly extra space in gidxs which will be used later */
3997dc456d91SStefano Zampini   for (i=0;i<n;i++) gidxs[i] = idxs[i] - gbounds[0];
3998dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset,&idxs);CHKERRQ(ierr);
3999dc456d91SStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)subset),&sf);CHKERRQ(ierr);
4000dc456d91SStefano Zampini   ierr = PetscSFSetGraphLayout(sf,map,n,NULL,PETSC_COPY_VALUES,gidxs);CHKERRQ(ierr);
4001dc456d91SStefano Zampini   ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr);
4002dc456d91SStefano Zampini 
4003dc456d91SStefano Zampini   /* reduce from leaves to roots */
4004dc456d91SStefano Zampini   ierr = PetscMemzero(root_data,Nl*sizeof(PetscInt));CHKERRQ(ierr);
400564a8e5bcSStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
400664a8e5bcSStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
4007dc456d91SStefano Zampini 
4008dc456d91SStefano Zampini   /* count indexes in local part of layout */
4009674ae819SStefano Zampini   nlocals = 0;
4010674ae819SStefano Zampini   first_index = -1;
4011674ae819SStefano Zampini   first_found = PETSC_FALSE;
4012dc456d91SStefano Zampini   for (i=0;i<Nl;i++) {
4013dc456d91SStefano Zampini     if (!first_found && root_data[i]) {
4014674ae819SStefano Zampini       first_found = PETSC_TRUE;
4015674ae819SStefano Zampini       first_index = i;
4016674ae819SStefano Zampini     }
4017dc456d91SStefano Zampini     nlocals += root_data[i];
4018674ae819SStefano Zampini   }
4019dc456d91SStefano Zampini 
4020dc456d91SStefano Zampini   /* cumulative of number of indexes and size of subset without holes */
40215fa240b1SStefano Zampini #if defined(PETSC_HAVE_MPI_EXSCAN)
4022dc456d91SStefano Zampini   start = 0;
402364a8e5bcSStefano Zampini   ierr = MPI_Exscan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
40245fa240b1SStefano Zampini #else
402564a8e5bcSStefano Zampini   ierr = MPI_Scan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
40265fa240b1SStefano Zampini   start = start-nlocals;
40275fa240b1SStefano Zampini #endif
40285fa240b1SStefano Zampini 
4029dc456d91SStefano Zampini   if (N_n) { /* compute total size of new subset if requested */
4030dc456d91SStefano Zampini     *N_n = start + nlocals;
4031dc456d91SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)subset),&commsize);CHKERRQ(ierr);
4032dc456d91SStefano Zampini     ierr = MPI_Bcast(N_n,1,MPIU_INT,commsize-1,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
4033674ae819SStefano Zampini   }
40345fa240b1SStefano Zampini 
40355fa240b1SStefano Zampini   /* adapt root data with cumulative */
4036674ae819SStefano Zampini   if (first_found) {
4037dc456d91SStefano Zampini     PetscInt old_index;
4038dc456d91SStefano Zampini 
4039dc456d91SStefano Zampini     root_data[first_index] += start;
4040674ae819SStefano Zampini     old_index = first_index;
4041dc456d91SStefano Zampini     for (i=first_index+1;i<Nl;i++) {
4042dc456d91SStefano Zampini       if (root_data[i]) {
4043dc456d91SStefano Zampini         root_data[i] += root_data[old_index];
4044674ae819SStefano Zampini         old_index = i;
4045674ae819SStefano Zampini       }
4046674ae819SStefano Zampini     }
4047674ae819SStefano Zampini   }
4048dc456d91SStefano Zampini 
4049dc456d91SStefano Zampini   /* from roots to leaves */
4050dc456d91SStefano Zampini   ierr = PetscSFBcastBegin(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
4051dc456d91SStefano Zampini   ierr = PetscSFBcastEnd(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
4052dc456d91SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
4053dc456d91SStefano Zampini 
4054dc456d91SStefano Zampini   /* create new IS with global indexes without holes */
4055dc456d91SStefano Zampini   if (subset_mult) {
4056dc456d91SStefano Zampini     const PetscInt* idxs_mult;
4057dc456d91SStefano Zampini     PetscInt        cum;
4058dc456d91SStefano Zampini 
4059dc456d91SStefano Zampini     cum = 0;
4060dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4061dc456d91SStefano Zampini     for (i=0;i<n;i++) {
4062dc456d91SStefano Zampini       PetscInt j;
4063dc456d91SStefano Zampini       for (j=0;j<idxs_mult[i];j++) gidxs[cum++] = leaf_data[i] - idxs_mult[i] + j;
4064674ae819SStefano Zampini     }
4065dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4066674ae819SStefano Zampini   } else {
4067dc456d91SStefano Zampini     for (i=0;i<n;i++) {
4068dc456d91SStefano Zampini       gidxs[i] = leaf_data[i]-1;
4069674ae819SStefano Zampini     }
4070674ae819SStefano Zampini   }
4071dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)subset),n_n,gidxs,PETSC_OWN_POINTER,subset_n);CHKERRQ(ierr);
4072dc456d91SStefano Zampini   ierr = PetscFree2(leaf_data,root_data);CHKERRQ(ierr);
4073674ae819SStefano Zampini   PetscFunctionReturn(0);
4074674ae819SStefano Zampini }
40759a7d3425SStefano Zampini 
40769a7d3425SStefano Zampini #undef __FUNCT__
40779a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
40789a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
40799a7d3425SStefano Zampini {
40809a7d3425SStefano Zampini   PetscInt       i,j;
40819a7d3425SStefano Zampini   PetscScalar    *alphas;
40829a7d3425SStefano Zampini   PetscErrorCode ierr;
40839a7d3425SStefano Zampini 
40849a7d3425SStefano Zampini   PetscFunctionBegin;
40859a7d3425SStefano Zampini   /* this implements stabilized Gram-Schmidt */
4086785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
40879a7d3425SStefano Zampini   for (i=0;i<n;i++) {
40889a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
40899a7d3425SStefano Zampini     if (i<n) { ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],&alphas[i+1]);CHKERRQ(ierr); }
40909a7d3425SStefano Zampini     for (j=i+1;j<n;j++) { ierr = VecAXPY(vecs[j],PetscConj(-alphas[j]),vecs[i]);CHKERRQ(ierr); }
40919a7d3425SStefano Zampini   }
40929a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
40939a7d3425SStefano Zampini   PetscFunctionReturn(0);
40949a7d3425SStefano Zampini }
40959a7d3425SStefano Zampini 
4096e7931f94SStefano Zampini #undef __FUNCT__
409770cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
4098b0c7d250SStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt n_subdomains, PetscInt redprocs, IS* is_sends)
4099e7931f94SStefano Zampini {
410052e5ac9dSStefano Zampini   IS             ranks_send_to;
4101e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
4102e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
410352e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
410452e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
41053837a79fSStefano Zampini   PetscInt       i,local_size,threshold=0;
41062b510759SStefano Zampini   PetscBool      use_vwgt=PETSC_FALSE,use_square=PETSC_FALSE;
4107e7931f94SStefano Zampini   PetscSubcomm   subcomm;
410852e5ac9dSStefano Zampini   PetscErrorCode ierr;
4109a57a6d2fSStefano Zampini 
4110e7931f94SStefano Zampini   PetscFunctionBegin;
41112b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_square",&use_square,NULL);CHKERRQ(ierr);
41122b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
41132b510759SStefano Zampini   ierr = PetscOptionsGetInt(NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
4114e7931f94SStefano Zampini 
4115e7931f94SStefano Zampini   /* Get info on mapping */
41163bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&local_size);CHKERRQ(ierr);
41173bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
4118e7931f94SStefano Zampini 
4119e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
4120785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
4121e7931f94SStefano Zampini   xadj[0] = 0;
4122e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
4123785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
4124785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
4125e7931f94SStefano Zampini 
41262b510759SStefano Zampini   if (threshold) {
4127d023bfaeSStefano Zampini     PetscInt xadj_count = 0;
41282b510759SStefano Zampini     for (i=1;i<n_neighs;i++) {
4129d023bfaeSStefano Zampini       if (n_shared[i] > threshold) {
4130d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
4131d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
4132d023bfaeSStefano Zampini         xadj_count++;
4133e7931f94SStefano Zampini       }
4134e7931f94SStefano Zampini     }
4135d023bfaeSStefano Zampini     xadj[1] = xadj_count;
4136c8587f34SStefano Zampini   } else {
4137e7931f94SStefano Zampini     if (xadj[1]) {
4138e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy,&neighs[1],xadj[1]*sizeof(*adjncy));CHKERRQ(ierr);
4139e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy_wgt,&n_shared[1],xadj[1]*sizeof(*adjncy_wgt));CHKERRQ(ierr);
4140c8587f34SStefano Zampini     }
4141e7931f94SStefano Zampini   }
41423bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
4143e7931f94SStefano Zampini   if (use_square) {
4144e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
4145e7931f94SStefano Zampini       adjncy_wgt[i] = adjncy_wgt[i]*adjncy_wgt[i];
4146e7931f94SStefano Zampini     }
4147e7931f94SStefano Zampini   }
4148e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
4149e7931f94SStefano Zampini 
41503837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
4151e7931f94SStefano Zampini 
4152e7931f94SStefano Zampini   /*
4153e7931f94SStefano Zampini     Restrict work on active processes only.
4154e7931f94SStefano Zampini   */
4155e7931f94SStefano Zampini   ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&subcomm);CHKERRQ(ierr);
4156e7931f94SStefano Zampini   ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
4157e7931f94SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
41582b510759SStefano Zampini   ierr = PetscMPIIntCast(!local_size,&color);CHKERRQ(ierr);
4159d3531aaaSJed Brown   ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
4160e7931f94SStefano Zampini   if (color) {
4161e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
4162e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
4163e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
4164c8587f34SStefano Zampini   } else {
416552e5ac9dSStefano Zampini     Mat             subdomain_adj;
416652e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
416752e5ac9dSStefano Zampini     MatPartitioning partitioner;
416852e5ac9dSStefano Zampini     PetscInt        prank,rstart=0,rend=0;
416952e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
4170b0c7d250SStefano Zampini     PetscBool       aggregate;
4171b0c7d250SStefano Zampini 
4172306c2d5bSBarry Smith     ierr = MPI_Comm_size(PetscSubcommChild(subcomm),&size);CHKERRQ(ierr);
4173785e854fSJed Brown     ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
4174e7931f94SStefano Zampini     prank = rank;
4175306c2d5bSBarry Smith     ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,PetscSubcommChild(subcomm));CHKERRQ(ierr);
41768002ef2cSStefano Zampini     /*
4177e7931f94SStefano Zampini     for (i=0;i<size;i++) {
4178e7931f94SStefano Zampini       PetscPrintf(subcomm->comm,"oldranks[%d] = %d\n",i,oldranks[i]);
4179c8587f34SStefano Zampini     }
41808002ef2cSStefano Zampini     */
4181e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
4182e7931f94SStefano Zampini       ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
4183c8587f34SStefano Zampini     }
4184e7931f94SStefano Zampini     ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
4185b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
4186b0c7d250SStefano Zampini     if (aggregate) {
4187b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
4188b0c7d250SStefano Zampini       PetscMPIInt nrank;
4189b0c7d250SStefano Zampini       PetscScalar *vals;
4190b0c7d250SStefano Zampini 
4191b0c7d250SStefano Zampini       ierr = MPI_Comm_rank(PetscSubcommChild(subcomm),&nrank);CHKERRQ(ierr);
4192b0c7d250SStefano Zampini       lrows = 0;
4193b0c7d250SStefano Zampini       if (nrank<redprocs) {
4194b0c7d250SStefano Zampini         lrows = size/redprocs;
4195b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
4196b0c7d250SStefano Zampini       }
41975fa240b1SStefano Zampini       ierr = MatCreateAIJ(PetscSubcommChild(subcomm),lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
4198b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
4199b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
4200b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
4201b0c7d250SStefano Zampini       row = nrank;
4202b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
4203b0c7d250SStefano Zampini       cols = adjncy;
4204b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
4205b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
4206b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
4207b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4208b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
420952e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
421052e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
421152e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
4212b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
4213b0c7d250SStefano Zampini     } else {
4214306c2d5bSBarry Smith       ierr = MatCreateMPIAdj(PetscSubcommChild(subcomm),1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
4215b0c7d250SStefano Zampini     }
421622b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
4217e7931f94SStefano Zampini 
4218e7931f94SStefano Zampini     /* Partition */
4219306c2d5bSBarry Smith     ierr = MatPartitioningCreate(PetscSubcommChild(subcomm),&partitioner);CHKERRQ(ierr);
4220e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
4221e7931f94SStefano Zampini     if (use_vwgt) {
42223837a79fSStefano Zampini       ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
4223e7931f94SStefano Zampini       v_wgt[0] = local_size;
4224e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
4225c8587f34SStefano Zampini     }
422628143c3dSStefano Zampini     n_subdomains = PetscMin((PetscInt)size,n_subdomains);
422728143c3dSStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,n_subdomains);CHKERRQ(ierr);
4228e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
4229e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
423022b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
4231e7931f94SStefano Zampini 
423252e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
423352e5ac9dSStefano Zampini     ierr = PCBDDCSubsetNumbering(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
423452e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
423552e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4236b0c7d250SStefano Zampini     if (!redprocs) {
4237b0c7d250SStefano Zampini       ranks_send_to_idx[0] = oldranks[is_indices[0]];
423828143c3dSStefano Zampini     } else {
4239b0c7d250SStefano Zampini       PetscInt    idxs[1];
4240b0c7d250SStefano Zampini       PetscMPIInt tag;
4241b0c7d250SStefano Zampini       MPI_Request *reqs;
4242b0c7d250SStefano Zampini 
4243b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
4244b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
4245b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
4246b0c7d250SStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,PetscSubcommChild(subcomm),&reqs[i-rstart]);CHKERRQ(ierr);
424728143c3dSStefano Zampini       }
4248b0c7d250SStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,PetscSubcommChild(subcomm),MPI_STATUS_IGNORE);CHKERRQ(ierr);
4249b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4250b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
4251b0c7d250SStefano Zampini       ranks_send_to_idx[0] = oldranks[idxs[0]];
4252e7931f94SStefano Zampini     }
425352e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4254e7931f94SStefano Zampini     /* clean up */
4255e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
425652e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
4257e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
4258e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
4259e7931f94SStefano Zampini   }
4260e7931f94SStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
4261e7931f94SStefano Zampini 
4262e7931f94SStefano Zampini   /* assemble parallel IS for sends */
4263e7931f94SStefano Zampini   i = 1;
4264e7931f94SStefano Zampini   if (color) i=0;
4265e7931f94SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,&ranks_send_to);CHKERRQ(ierr);
4266e7931f94SStefano Zampini   /* get back IS */
4267e7931f94SStefano Zampini   *is_sends = ranks_send_to;
4268e7931f94SStefano Zampini   PetscFunctionReturn(0);
4269e7931f94SStefano Zampini }
4270e7931f94SStefano Zampini 
4271e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
4272e7931f94SStefano Zampini 
4273e7931f94SStefano Zampini #undef __FUNCT__
4274e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
427553a05cb3SStefano 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[])
4276e7931f94SStefano Zampini {
427770cf5478SStefano Zampini   Mat                    local_mat;
4278e7931f94SStefano Zampini   IS                     is_sends_internal;
42799d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
428028143c3dSStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals;
42819d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
4282e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
4283e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
4284e7931f94SStefano Zampini   const PetscInt*        is_indices;
4285e7931f94SStefano Zampini   MatType                new_local_type;
4286e7931f94SStefano Zampini   /* buffers */
4287e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
428828143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
42899d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
4290e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
4291e7931f94SStefano Zampini   /* MPI */
429228143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
429328143c3dSStefano Zampini   PetscSubcomm           subcomm;
4294e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
429528143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
429628143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
429728143c3dSStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,source_dest;
429828143c3dSStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals;
429928143c3dSStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals;
4300e7931f94SStefano Zampini   PetscErrorCode         ierr;
4301e7931f94SStefano Zampini 
4302e7931f94SStefano Zampini   PetscFunctionBegin;
430328143c3dSStefano Zampini   /* TODO: add missing checks */
430428143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
430528143c3dSStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
430628143c3dSStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,5);
430728143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,7);
4308e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
430928143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
4310e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
4311e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
4312e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
4313e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
4314e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
431528143c3dSStefano Zampini   if (reuse == MAT_REUSE_MATRIX && *mat_n) {
431670cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
431770cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
431828143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
431970cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
432070cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
432170cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
432270cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
432370cf5478SStefano Zampini   }
4324e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
4325e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
4326e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
4327e7931f94SStefano Zampini   if (!is_sends) {
432828143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
4329b0c7d250SStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,n_subdomains,0,&is_sends_internal);CHKERRQ(ierr);
4330c8587f34SStefano Zampini   } else {
4331e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
4332e7931f94SStefano Zampini     is_sends_internal = is_sends;
4333c8587f34SStefano Zampini   }
4334e7931f94SStefano Zampini 
4335e7931f94SStefano Zampini   /* get comm */
4336a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
4337e7931f94SStefano Zampini 
4338e7931f94SStefano Zampini   /* compute number of sends */
4339e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
4340e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
4341e7931f94SStefano Zampini 
4342e7931f94SStefano Zampini   /* compute number of receives */
4343e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
4344785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
4345e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
4346e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
4347e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
4348e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
4349e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
4350e7931f94SStefano Zampini 
435128143c3dSStefano Zampini   /* restrict comm if requested */
435228143c3dSStefano Zampini   subcomm = 0;
435328143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
435428143c3dSStefano Zampini   if (restrict_comm) {
4355779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
4356779c1cceSStefano Zampini 
435728143c3dSStefano Zampini     color = 0;
435853a05cb3SStefano Zampini     if (restrict_full) {
435953a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
436053a05cb3SStefano Zampini     } else {
436153a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
436253a05cb3SStefano Zampini     }
436328143c3dSStefano Zampini     ierr = MPI_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
436428143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
436528143c3dSStefano Zampini     /* check if reuse has been requested */
436628143c3dSStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
436728143c3dSStefano Zampini       if (*mat_n) {
436828143c3dSStefano Zampini         PetscMPIInt subcommsize2;
436928143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
437028143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
437128143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
437228143c3dSStefano Zampini       } else {
437328143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
437428143c3dSStefano Zampini       }
437528143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
4376779c1cceSStefano Zampini       PetscMPIInt rank;
4377779c1cceSStefano Zampini 
4378779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
437928143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
438028143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
438128143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
4382306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
438328143c3dSStefano Zampini     }
438428143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
438528143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
438628143c3dSStefano Zampini   } else {
438728143c3dSStefano Zampini     comm_n = comm;
438828143c3dSStefano Zampini   }
438928143c3dSStefano Zampini 
4390e7931f94SStefano Zampini   /* prepare send/receive buffers */
4391785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
4392e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
4393785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
4394e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
439528143c3dSStefano Zampini   if (nis) {
4396854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
439728143c3dSStefano Zampini   }
4398e7931f94SStefano Zampini 
439928143c3dSStefano Zampini   /* Get data from local matrices */
4400e7931f94SStefano Zampini   if (!isdense) {
4401a26c9d0eSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
4402e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
4403e7931f94SStefano Zampini     /*
4404e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
4405e7931f94SStefano Zampini        send_buffer_idxs should contain:
4406e7931f94SStefano Zampini        - MatType_PRIVATE type
4407e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
4408e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
4409e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
4410e7931f94SStefano Zampini     */
4411e7931f94SStefano Zampini   } else {
4412e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
44133bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
4414854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
4415e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
4416e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
44173bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
4418e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
44193bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
4420e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
4421e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
4422e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
4423e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
4424c8587f34SStefano Zampini     }
4425c8587f34SStefano Zampini   }
4426e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
442728143c3dSStefano Zampini   /* additional is (if any) */
442828143c3dSStefano Zampini   if (nis) {
442928143c3dSStefano Zampini     PetscMPIInt psum;
443028143c3dSStefano Zampini     PetscInt j;
443128143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
443228143c3dSStefano Zampini       PetscInt plen;
443328143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
443428143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
443528143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
443628143c3dSStefano Zampini     }
4437854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
443828143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
443928143c3dSStefano Zampini       PetscInt plen;
444028143c3dSStefano Zampini       const PetscInt *is_array_idxs;
444128143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
444228143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
444328143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
444428143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
444528143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
444628143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
444728143c3dSStefano Zampini     }
444828143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
444928143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
445028143c3dSStefano Zampini     }
445128143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
445228143c3dSStefano Zampini   }
445328143c3dSStefano Zampini 
4454e7931f94SStefano Zampini   buf_size_idxs = 0;
4455e7931f94SStefano Zampini   buf_size_vals = 0;
445628143c3dSStefano Zampini   buf_size_idxs_is = 0;
4457e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4458e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
4459e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
446028143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
4461e7931f94SStefano Zampini   }
4462785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
4463785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
446495ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
4465e7931f94SStefano Zampini 
4466e7931f94SStefano Zampini   /* get new tags for clean communications */
4467e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
4468e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
446928143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
4470e7931f94SStefano Zampini 
4471e7931f94SStefano Zampini   /* allocate for requests */
4472785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
4473785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
447495ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
4475785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
4476785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
447795ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
4478e7931f94SStefano Zampini 
4479e7931f94SStefano Zampini   /* communications */
4480e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
4481e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
448228143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
4483e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4484e7931f94SStefano Zampini     source_dest = onodes[i];
4485e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
4486e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
4487e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4488e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
448928143c3dSStefano Zampini     if (nis) {
449028143c3dSStefano 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);
449128143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
449228143c3dSStefano Zampini     }
4493e7931f94SStefano Zampini   }
4494e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
4495e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
4496e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
4497e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
449828143c3dSStefano Zampini     if (nis) {
449928143c3dSStefano 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);
450028143c3dSStefano Zampini     }
4501e7931f94SStefano Zampini   }
4502e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
4503e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
4504e7931f94SStefano Zampini 
4505e7931f94SStefano Zampini   /* assemble new l2g map */
4506e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4507e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
45089d30be91SStefano Zampini   new_local_rows = 0;
4509e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
45109d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
4511e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4512e7931f94SStefano Zampini   }
45139d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
4514e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
45159d30be91SStefano Zampini   new_local_rows = 0;
4516e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
45179d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
45189d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
4519e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4520e7931f94SStefano Zampini   }
45219d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
45229d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
4523e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
4524e7931f94SStefano Zampini 
4525e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
4526e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
4527e7931f94SStefano 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) */
4528e7931f94SStefano Zampini   if (n_recvs) {
452928143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
4530e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
4531e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
4532e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
4533e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
4534e7931f94SStefano Zampini         break;
4535e7931f94SStefano Zampini       }
4536e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
4537e7931f94SStefano Zampini     }
4538e7931f94SStefano Zampini     switch (new_local_type_private) {
453928143c3dSStefano Zampini       case MATDENSE_PRIVATE:
454028143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
4541e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
4542e7931f94SStefano Zampini           bs = 1;
454328143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
454428143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
454528143c3dSStefano Zampini           bs = 1;
454628143c3dSStefano Zampini         }
4547e7931f94SStefano Zampini         break;
4548e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
4549e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
4550e7931f94SStefano Zampini         bs = 1;
4551e7931f94SStefano Zampini         break;
4552e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
4553e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
4554e7931f94SStefano Zampini         break;
4555e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
4556e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
4557e7931f94SStefano Zampini         break;
4558e7931f94SStefano Zampini       default:
45599d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
4560e7931f94SStefano Zampini         break;
4561e7931f94SStefano Zampini     }
456228143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
456328143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
456428143c3dSStefano Zampini     bs = 1;
4565e7931f94SStefano Zampini   }
4566e7931f94SStefano Zampini 
456770cf5478SStefano Zampini   /* create MATIS object if needed */
456870cf5478SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
4569e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
4570e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
457170cf5478SStefano Zampini   } else {
457270cf5478SStefano Zampini     /* it also destroys the local matrices */
457370cf5478SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
457470cf5478SStefano Zampini   }
457570cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
4576e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
45779d30be91SStefano Zampini 
45789d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
45799d30be91SStefano Zampini 
45809d30be91SStefano Zampini   /* Global to local map of received indices */
45819d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
45829d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
45839d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
45849d30be91SStefano Zampini 
45859d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
45869d30be91SStefano Zampini   buf_size_idxs = 0;
45879d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
45889d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
45899d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
45909d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
45919d30be91SStefano Zampini   }
45929d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
45939d30be91SStefano Zampini 
45949d30be91SStefano Zampini   /* set preallocation */
45959d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
45969d30be91SStefano Zampini   if (!newisdense) {
45979d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
45989d30be91SStefano Zampini 
45999d30be91SStefano Zampini     ptr_vals = recv_buffer_vals;
46009d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
46019d30be91SStefano Zampini     if (n_recvs) {
46029d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
46039d30be91SStefano Zampini     }
46049d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
46059d30be91SStefano Zampini       PetscInt j;
46069d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
46079d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
46089d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
46099d30be91SStefano Zampini         }
46109d30be91SStefano Zampini       } else {
46119d30be91SStefano Zampini         /* TODO */
46129d30be91SStefano Zampini       }
46139d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
46149d30be91SStefano Zampini     }
46159d30be91SStefano Zampini     if (new_local_nnz) {
46169d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
46179d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
46189d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
46199d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
46209d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
46219d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
46229d30be91SStefano Zampini     } else {
46239d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
46249d30be91SStefano Zampini     }
46259d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
46269d30be91SStefano Zampini   } else {
46279d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
46289d30be91SStefano Zampini   }
4629e7931f94SStefano Zampini 
4630e7931f94SStefano Zampini   /* set values */
4631e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
46329d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
4633e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4634e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
4635e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
46369d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
4637e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
4638e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
4639e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
464028143c3dSStefano Zampini     } else {
464128143c3dSStefano Zampini       /* TODO */
4642e7931f94SStefano Zampini     }
4643e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4644e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
4645e7931f94SStefano Zampini   }
4646e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4647e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
464870cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
464970cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
46509d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
46519d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
4652e7931f94SStefano Zampini 
4653dfd14d43SStefano Zampini #if 0
465428143c3dSStefano Zampini   if (!restrict_comm) { /* check */
4655e7931f94SStefano Zampini     Vec       lvec,rvec;
4656e7931f94SStefano Zampini     PetscReal infty_error;
4657e7931f94SStefano Zampini 
46582a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
4659e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
4660e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
4661e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
466270cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
4663e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
4664e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
4665e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
4666e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
4667e7931f94SStefano Zampini   }
466828143c3dSStefano Zampini #endif
4669e7931f94SStefano Zampini 
467028143c3dSStefano Zampini   /* assemble new additional is (if any) */
467128143c3dSStefano Zampini   if (nis) {
467228143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
467328143c3dSStefano Zampini 
467428143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4675854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
467628143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
467728143c3dSStefano Zampini     psum = 0;
467828143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
467928143c3dSStefano Zampini       for (j=0;j<nis;j++) {
468028143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
468128143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
468228143c3dSStefano Zampini         psum += plen;
468328143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
468428143c3dSStefano Zampini       }
468528143c3dSStefano Zampini     }
4686854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
4687854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
468828143c3dSStefano Zampini     for (i=1;i<nis;i++) {
468928143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
469028143c3dSStefano Zampini     }
469128143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
469228143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
469328143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
469428143c3dSStefano Zampini       for (j=0;j<nis;j++) {
469528143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
469628143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
469728143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
469828143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
469928143c3dSStefano Zampini       }
470028143c3dSStefano Zampini     }
470128143c3dSStefano Zampini     for (i=0;i<nis;i++) {
470228143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
470328143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
470428143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
470528143c3dSStefano Zampini     }
470628143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
470728143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
470828143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
470928143c3dSStefano Zampini   }
4710e7931f94SStefano Zampini   /* free workspace */
471128143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
4712e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4713e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
4714e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4715e7931f94SStefano Zampini   if (isdense) {
4716e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
4717e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
4718e7931f94SStefano Zampini   } else {
4719e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
4720e7931f94SStefano Zampini   }
472128143c3dSStefano Zampini   if (nis) {
472228143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
472328143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
472428143c3dSStefano Zampini   }
4725e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
4726e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
472728143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
4728e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
4729e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
473028143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
4731e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
4732e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
4733e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
4734e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
4735e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
473628143c3dSStefano Zampini   if (nis) {
473728143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
473828143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
473928143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
474028143c3dSStefano Zampini   }
474128143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
474228143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
474328143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
474428143c3dSStefano Zampini     for (i=0;i<nis;i++) {
474528143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
474628143c3dSStefano Zampini     }
474753a05cb3SStefano Zampini     *mat_n = NULL;
474828143c3dSStefano Zampini   }
4749e7931f94SStefano Zampini   PetscFunctionReturn(0);
4750e7931f94SStefano Zampini }
4751a57a6d2fSStefano Zampini 
475212edc857SStefano Zampini /* temporary hack into ksp private data structure */
4753af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
475412edc857SStefano Zampini 
4755c8587f34SStefano Zampini #undef __FUNCT__
4756c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
4757c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
4758c8587f34SStefano Zampini {
4759c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
4760c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
476120a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
47629881197aSStefano Zampini   MatNullSpace           CoarseNullSpace=NULL;
476320a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
47646e683305SStefano Zampini   IS                     coarse_is,*isarray;
47656e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
47666e683305SStefano Zampini   PetscInt               nis,nisdofs,nisneu;
4767f9eb5b7dSStefano Zampini   PC                     pc_temp;
4768c8587f34SStefano Zampini   PCType                 coarse_pc_type;
4769c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
4770f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
47714f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
47726e683305SStefano Zampini   Mat                    t_coarse_mat_is;
47736e683305SStefano Zampini   PetscInt               void_procs,ncoarse_ml,ncoarse_ds,ncoarse;
47746e683305SStefano Zampini   PetscMPIInt            all_procs;
477574e2c79eSStefano Zampini   PetscBool              csin_ml,csin_ds,csin,csin_type_simple,redist;
477668457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
477722bc73bbSStefano Zampini   PetscScalar            *array;
47789881197aSStefano Zampini   PetscErrorCode         ierr;
4779fdc09c96SStefano Zampini 
4780c8587f34SStefano Zampini   PetscFunctionBegin;
4781c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
478268457ee5SStefano 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 */
4783fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
47845a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
4785fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
4786f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
4787f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
4788f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
4789fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
479051bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
479151bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
4792dc4bcba2SStefano Zampini         PC        pc;
4793dc4bcba2SStefano Zampini         PetscBool isbddc;
4794dc4bcba2SStefano Zampini 
4795dc4bcba2SStefano Zampini         /* temporary workaround since PCBDDC does not have a reset method so far */
4796dc4bcba2SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
4797dc4bcba2SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
4798dc4bcba2SStefano Zampini         if (isbddc) {
4799dc4bcba2SStefano Zampini           ierr = PCDestroy(&pc);CHKERRQ(ierr);
4800dc4bcba2SStefano Zampini         }
4801727cdba6SStefano Zampini         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
4802fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
4803fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
4804fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
4805f4ddd8eeSStefano Zampini       }
4806fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
4807fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
4808f4ddd8eeSStefano Zampini     }
480970cf5478SStefano Zampini     /* reset any subassembling information */
481070cf5478SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
48116e683305SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
48126e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
4813fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
4814f4ddd8eeSStefano Zampini   }
4815c8587f34SStefano Zampini 
48166e683305SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
48172b510759SStefano Zampini   im_active = !!(pcis->n);
48182b510759SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
48196e683305SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&all_procs);CHKERRQ(ierr);
48206e683305SStefano Zampini   void_procs = all_procs-active_procs;
48216e683305SStefano Zampini   csin_type_simple = PETSC_TRUE;
482274e2c79eSStefano Zampini   redist = PETSC_FALSE;
482322bc73bbSStefano Zampini   if (pcbddc->current_level && void_procs) {
48246e683305SStefano Zampini     csin_ml = PETSC_TRUE;
48256e683305SStefano Zampini     ncoarse_ml = void_procs;
4826779c1cceSStefano Zampini     /* it has no sense to redistribute on a set of processors larger than the number of active processes */
4827779c1cceSStefano Zampini     if (pcbddc->redistribute_coarse > 0 && pcbddc->redistribute_coarse < active_procs) {
48286e683305SStefano Zampini       csin_ds = PETSC_TRUE;
482918a45a71SStefano Zampini       ncoarse_ds = pcbddc->redistribute_coarse;
483018a45a71SStefano Zampini       redist = PETSC_TRUE;
483118a45a71SStefano Zampini     } else {
48326e683305SStefano Zampini       csin_ds = PETSC_TRUE;
4833779c1cceSStefano Zampini       ncoarse_ds = active_procs;
4834779c1cceSStefano Zampini       redist = PETSC_TRUE;
483518a45a71SStefano Zampini     }
48366e683305SStefano Zampini   } else {
48376e683305SStefano Zampini     csin_ml = PETSC_FALSE;
48386e683305SStefano Zampini     ncoarse_ml = all_procs;
48396e683305SStefano Zampini     if (void_procs) {
48406e683305SStefano Zampini       csin_ds = PETSC_TRUE;
48416e683305SStefano Zampini       ncoarse_ds = void_procs;
48426e683305SStefano Zampini       csin_type_simple = PETSC_FALSE;
48436e683305SStefano Zampini     } else {
4844779c1cceSStefano Zampini       if (pcbddc->redistribute_coarse > 0 && pcbddc->redistribute_coarse < all_procs) {
484574e2c79eSStefano Zampini         csin_ds = PETSC_TRUE;
484674e2c79eSStefano Zampini         ncoarse_ds = pcbddc->redistribute_coarse;
484774e2c79eSStefano Zampini         redist = PETSC_TRUE;
484874e2c79eSStefano Zampini       } else {
48496e683305SStefano Zampini         csin_ds = PETSC_FALSE;
48506e683305SStefano Zampini         ncoarse_ds = all_procs;
48516e683305SStefano Zampini       }
48526e683305SStefano Zampini     }
485374e2c79eSStefano Zampini   }
48546e683305SStefano Zampini 
48556e683305SStefano Zampini   /*
48566e683305SStefano Zampini     test if we can go multilevel: three conditions must be satisfied:
48576e683305SStefano Zampini     - we have not exceeded the number of levels requested
48586e683305SStefano Zampini     - we can actually subassemble the active processes
48596e683305SStefano Zampini     - we can find a suitable number of MPI processes where we can place the subassembled problem
48606e683305SStefano Zampini   */
48616e683305SStefano Zampini   multilevel_allowed = PETSC_FALSE;
48626e683305SStefano Zampini   multilevel_requested = PETSC_FALSE;
48636e683305SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
48646e683305SStefano Zampini     multilevel_requested = PETSC_TRUE;
48656e683305SStefano Zampini     if (active_procs/pcbddc->coarsening_ratio < 2 || ncoarse_ml/pcbddc->coarsening_ratio < 2) {
4866f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_FALSE;
48672b510759SStefano Zampini     } else {
4868f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_TRUE;
4869c8587f34SStefano Zampini     }
4870c8587f34SStefano Zampini   }
48716e683305SStefano Zampini   /* determine number of process partecipating to coarse solver */
48726e683305SStefano Zampini   if (multilevel_allowed) {
48736e683305SStefano Zampini     ncoarse = ncoarse_ml;
48746e683305SStefano Zampini     csin = csin_ml;
487558da7f69SStefano Zampini     redist = PETSC_FALSE;
48766e683305SStefano Zampini   } else {
48776e683305SStefano Zampini     ncoarse = ncoarse_ds;
48786e683305SStefano Zampini     csin = csin_ds;
48796e683305SStefano Zampini   }
4880e7931f94SStefano Zampini 
4881abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
4882abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
4883abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
4884abbbba34SStefano Zampini 
4885abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
488622bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
488722bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
488822bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
488922bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
4890b1ecc7b1SStefano Zampini #if 0
4891b9b85e73SStefano Zampini   {
4892b9b85e73SStefano Zampini     PetscViewer viewer;
4893b9b85e73SStefano Zampini     char filename[256];
4894b1ecc7b1SStefano Zampini     sprintf(filename,"local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
4895b9b85e73SStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
4896b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4897b9b85e73SStefano Zampini     ierr = MatView(coarse_submat_dense,viewer);CHKERRQ(ierr);
4898b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4899b9b85e73SStefano Zampini   }
4900b9b85e73SStefano Zampini #endif
4901e176bc59SStefano 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);
49026e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
49036e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
49046e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4905abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
4906abbbba34SStefano Zampini 
49076e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
49086e683305SStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal) ) { /* protects from unneded computations */
49096e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
49106e683305SStefano Zampini     const PetscInt         *idxs;
49116e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
49126e683305SStefano Zampini 
49136e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
49140be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
49156e683305SStefano Zampini     /* allocate space for temporary storage */
4916854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
4917854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
49186e683305SStefano Zampini     /* allocate for IS array */
49196e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
49206e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
49216e683305SStefano Zampini     nis = nisdofs + nisneu;
4922854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
49236e683305SStefano Zampini     /* dofs splitting */
49246e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
49256e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
49266e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
49276e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
49286e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
49296e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
49306e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
49316e683305SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pcbddc->ISForDofsLocal[i]),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
49326e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
49336e683305SStefano Zampini     }
49346e683305SStefano Zampini     /* neumann boundaries */
49356e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
49366e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
49376e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
49386e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
49396e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
49406e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
49416e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
49426e683305SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pcbddc->NeumannBoundariesLocal),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
49436e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
49446e683305SStefano Zampini     }
49456e683305SStefano Zampini     /* free memory */
49466e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
49476e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
49486e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
49496e683305SStefano Zampini   } else {
49506e683305SStefano Zampini     nis = 0;
49516e683305SStefano Zampini     nisdofs = 0;
49526e683305SStefano Zampini     nisneu = 0;
49536e683305SStefano Zampini     isarray = NULL;
49546e683305SStefano Zampini   }
49556e683305SStefano Zampini   /* destroy no longer needed map */
49566e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
49576e683305SStefano Zampini 
49586e683305SStefano Zampini   /* restrict on coarse candidates (if needed) */
49596e683305SStefano Zampini   coarse_mat_is = NULL;
49606e683305SStefano Zampini   if (csin) {
49616e683305SStefano Zampini     if (!pcbddc->coarse_subassembling_init ) { /* creates subassembling init pattern if not present */
496274e2c79eSStefano Zampini       if (redist) {
496374e2c79eSStefano Zampini         PetscMPIInt rank;
4964779c1cceSStefano Zampini         PetscInt    spc,n_spc_p1,dest[1],destsize;
496574e2c79eSStefano Zampini 
496674e2c79eSStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
496758da7f69SStefano Zampini         spc = active_procs/ncoarse;
496858da7f69SStefano Zampini         n_spc_p1 = active_procs%ncoarse;
4969779c1cceSStefano Zampini         if (im_active) {
4970779c1cceSStefano Zampini           destsize = 1;
497174e2c79eSStefano Zampini           if (rank > n_spc_p1*(spc+1)-1) {
497274e2c79eSStefano Zampini             dest[0] = n_spc_p1+(rank-(n_spc_p1*(spc+1)))/spc;
497374e2c79eSStefano Zampini           } else {
497474e2c79eSStefano Zampini             dest[0] = rank/(spc+1);
497574e2c79eSStefano Zampini           }
497674e2c79eSStefano Zampini         } else {
4977779c1cceSStefano Zampini           destsize = 0;
49786e683305SStefano Zampini         }
4979779c1cceSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),destsize,dest,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
4980779c1cceSStefano Zampini       } else if (csin_type_simple) {
49816e683305SStefano Zampini         PetscMPIInt rank;
49826e683305SStefano Zampini         PetscInt    issize,isidx;
4983779c1cceSStefano Zampini 
49846e683305SStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
49856e683305SStefano Zampini         if (im_active) {
49866e683305SStefano Zampini           issize = 1;
49876e683305SStefano Zampini           isidx = (PetscInt)rank;
49886e683305SStefano Zampini         } else {
49896e683305SStefano Zampini           issize = 0;
49906e683305SStefano Zampini           isidx = -1;
49916e683305SStefano Zampini         }
49926e683305SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),issize,&isidx,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
4993779c1cceSStefano Zampini       } else { /* get a suitable subassembling pattern from MATIS code */
4994b0c7d250SStefano Zampini         ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
49956e683305SStefano Zampini       }
4996779c1cceSStefano Zampini 
4997779c1cceSStefano Zampini       /* we need to shift on coarse candidates either if we are not redistributing or we are redistributing and we have enough void processes */
4998779c1cceSStefano Zampini       if (!redist || ncoarse <= void_procs) {
4999779c1cceSStefano Zampini         PetscInt ncoarse_cand,tissize,*nisindices;
5000779c1cceSStefano Zampini         PetscInt *coarse_candidates;
5001779c1cceSStefano Zampini         const PetscInt* tisindices;
5002779c1cceSStefano Zampini 
5003779c1cceSStefano Zampini         /* get coarse candidates' ranks in pc communicator */
5004779c1cceSStefano Zampini         ierr = PetscMalloc1(all_procs,&coarse_candidates);CHKERRQ(ierr);
5005779c1cceSStefano Zampini         ierr = MPI_Allgather(&im_active,1,MPIU_INT,coarse_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
5006779c1cceSStefano Zampini         for (i=0,ncoarse_cand=0;i<all_procs;i++) {
5007779c1cceSStefano Zampini           if (!coarse_candidates[i]) {
5008779c1cceSStefano Zampini             coarse_candidates[ncoarse_cand++]=i;
5009779c1cceSStefano Zampini           }
5010779c1cceSStefano Zampini         }
5011779c1cceSStefano Zampini         if (ncoarse_cand < ncoarse) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen! %d < %d",ncoarse_cand,ncoarse);
5012779c1cceSStefano Zampini 
5013779c1cceSStefano Zampini 
50146e683305SStefano Zampini         if (pcbddc->dbg_flag) {
50156e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
50166e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init (before shift)\n");CHKERRQ(ierr);
50176e683305SStefano Zampini           ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
50186e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse candidates\n");CHKERRQ(ierr);
5019779c1cceSStefano Zampini           for (i=0;i<ncoarse_cand;i++) {
50206e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"%d ",coarse_candidates[i]);CHKERRQ(ierr);
50216e683305SStefano Zampini           }
50226e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"\n");CHKERRQ(ierr);
50236e683305SStefano Zampini           ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
50246e683305SStefano Zampini         }
50256e683305SStefano Zampini         /* shift the pattern on coarse candidates */
50266e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->coarse_subassembling_init,&tissize);CHKERRQ(ierr);
50276e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
5028854ce69bSBarry Smith         ierr = PetscMalloc1(tissize,&nisindices);CHKERRQ(ierr);
50296e683305SStefano Zampini         for (i=0;i<tissize;i++) nisindices[i] = coarse_candidates[tisindices[i]];
50306e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
50316e683305SStefano Zampini         ierr = ISGeneralSetIndices(pcbddc->coarse_subassembling_init,tissize,nisindices,PETSC_OWN_POINTER);CHKERRQ(ierr);
50326e683305SStefano Zampini         ierr = PetscFree(coarse_candidates);CHKERRQ(ierr);
50336e683305SStefano Zampini       }
50346e683305SStefano Zampini       if (pcbddc->dbg_flag) {
50356e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
50366e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init\n");CHKERRQ(ierr);
50376e683305SStefano Zampini         ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
50386e683305SStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
50396e683305SStefano Zampini       }
5040779c1cceSStefano Zampini     }
50416e683305SStefano Zampini     /* get temporary coarse mat in IS format restricted on coarse procs (plus additional index sets of isarray) */
504253a05cb3SStefano Zampini     if (multilevel_allowed) { /* we need to keep tracking of void processes for future placements */
504353a05cb3SStefano 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);
504453a05cb3SStefano Zampini     } else { /* this is the last level, so use just receiving processes in subcomm */
504553a05cb3SStefano 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);
504653a05cb3SStefano Zampini     }
50476e683305SStefano Zampini   } else {
50486e683305SStefano Zampini     if (pcbddc->dbg_flag) {
50496e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
50506e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init not needed\n");CHKERRQ(ierr);
50516e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
50526e683305SStefano Zampini     }
50536e683305SStefano Zampini     ierr = PetscObjectReference((PetscObject)t_coarse_mat_is);CHKERRQ(ierr);
50546e683305SStefano Zampini     coarse_mat_is = t_coarse_mat_is;
50556e683305SStefano Zampini   }
50566e683305SStefano Zampini 
50576e683305SStefano Zampini   /* create local to global scatters for coarse problem */
505868457ee5SStefano Zampini   if (compute_vecs) {
50596e683305SStefano Zampini     PetscInt lrows;
50606e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
50616e683305SStefano Zampini     if (coarse_mat_is) {
50626e683305SStefano Zampini       ierr = MatGetLocalSize(coarse_mat_is,&lrows,NULL);CHKERRQ(ierr);
50636e683305SStefano Zampini     } else {
50646e683305SStefano Zampini       lrows = 0;
50656e683305SStefano Zampini     }
50666e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
50676e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
50686e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
50696e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
50706e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
50716e683305SStefano Zampini   }
50726e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
50736e683305SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
5074c8587f34SStefano Zampini 
5075f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
5076f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
5077f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
5078f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
5079f9eb5b7dSStefano Zampini   } else {
5080f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
5081f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
5082c8587f34SStefano Zampini   }
5083c8587f34SStefano Zampini 
50846e683305SStefano Zampini   /* print some info if requested */
50856e683305SStefano Zampini   if (pcbddc->dbg_flag) {
50866e683305SStefano Zampini     if (!multilevel_allowed) {
50876e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
50886e683305SStefano Zampini       if (multilevel_requested) {
50896e683305SStefano 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);
50906e683305SStefano Zampini       } else if (pcbddc->max_levels) {
50916e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
50926e683305SStefano Zampini       }
50936e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
50946e683305SStefano Zampini     }
50956e683305SStefano Zampini   }
50966e683305SStefano Zampini 
5097f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
50986e683305SStefano Zampini   if (coarse_mat_is) {
50996e683305SStefano Zampini     MatReuse coarse_mat_reuse;
51006a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
51016e683305SStefano Zampini     if (pcbddc->dbg_flag) {
51026e683305SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat_is));
51036e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
51046e683305SStefano Zampini     }
5105f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
5106312be037SStefano Zampini       char prefix[256],str_level[16];
5107e604994aSStefano Zampini       size_t len;
51086e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat_is),&pcbddc->coarse_ksp);CHKERRQ(ierr);
5109422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
5110c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
5111f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
51125f76c7aeSStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat_is,coarse_mat_is);CHKERRQ(ierr);
5113c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
51146e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
5115c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
5116c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
5117e604994aSStefano Zampini       /* prefix */
5118e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
5119e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
5120e604994aSStefano Zampini       if (!pcbddc->current_level) {
5121e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
5122e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
5123c8587f34SStefano Zampini       } else {
5124e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
5125312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
5126312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
512734d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
5128312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
5129e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
5130e604994aSStefano Zampini       }
5131e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
51323e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
51333e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
51343e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
51353e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
5136f9eb5b7dSStefano Zampini       /* allow user customization */
5137f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
51383e3c6dadSStefano Zampini     }
51393e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
514051bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
51413e3c6dadSStefano Zampini     if (nisdofs) {
51423e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
51433e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
51443e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
51453e3c6dadSStefano Zampini       }
51463e3c6dadSStefano Zampini     }
51473e3c6dadSStefano Zampini     if (nisneu) {
51483e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
51493e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
5150312be037SStefano Zampini     }
5151f9eb5b7dSStefano Zampini 
5152f9eb5b7dSStefano Zampini     /* get some info after set from options */
5153f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
5154f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
51554f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
51566e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
5157f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
5158f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
5159f9eb5b7dSStefano Zampini     }
516039f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
51614f3a063dSStefano Zampini     if (isredundant) {
51624f3a063dSStefano Zampini       KSP inner_ksp;
51634f3a063dSStefano Zampini       PC  inner_pc;
51644f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
51654f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
51664f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
51674f3a063dSStefano Zampini     }
5168f9eb5b7dSStefano Zampini 
5169f9eb5b7dSStefano Zampini     /* assemble coarse matrix */
5170fa7f1dd8SStefano Zampini     if (coarse_reuse) {
517181d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
5172fa7f1dd8SStefano Zampini       ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
51736e683305SStefano Zampini       coarse_mat_reuse = MAT_REUSE_MATRIX;
5174fa7f1dd8SStefano Zampini     } else {
51756e683305SStefano Zampini       coarse_mat_reuse = MAT_INITIAL_MATRIX;
5176fa7f1dd8SStefano Zampini     }
5177c8587f34SStefano Zampini     if (isbddc || isnn) {
517822bc73bbSStefano Zampini       if (pcbddc->coarsening_ratio > 1) {
517970cf5478SStefano Zampini         if (!pcbddc->coarse_subassembling) { /* subassembling info is not present */
5180b0c7d250SStefano Zampini           ierr = MatISGetSubassemblingPattern(coarse_mat_is,active_procs/pcbddc->coarsening_ratio,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
518122b6e8a2SStefano Zampini           if (pcbddc->dbg_flag) {
51826e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
51836e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"Subassembling pattern\n");CHKERRQ(ierr);
51846e683305SStefano Zampini             ierr = ISView(pcbddc->coarse_subassembling,dbg_viewer);CHKERRQ(ierr);
51856e683305SStefano Zampini             ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
518622b6e8a2SStefano Zampini           }
518770cf5478SStefano Zampini         }
518853a05cb3SStefano Zampini         ierr = MatISSubassemble(coarse_mat_is,pcbddc->coarse_subassembling,0,PETSC_FALSE,PETSC_FALSE,coarse_mat_reuse,&coarse_mat,0,NULL);CHKERRQ(ierr);
518970cf5478SStefano Zampini       } else {
519022bc73bbSStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
519122bc73bbSStefano Zampini         coarse_mat = coarse_mat_is;
519222bc73bbSStefano Zampini       }
519322bc73bbSStefano Zampini     } else {
51942e1e5fa4SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
5195c8587f34SStefano Zampini     }
5196c8587f34SStefano Zampini     ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
5197c8587f34SStefano Zampini 
51983301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
51995a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
52003301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
52013301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
52023301b35fSStefano Zampini     }
52033301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
52043301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
52053301b35fSStefano Zampini     }
52063301b35fSStefano Zampini     if (pc->pmat->spd_set) {
52073301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
52083301b35fSStefano Zampini     }
52096e683305SStefano Zampini     /* set operators */
52105f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
52116e683305SStefano Zampini     if (pcbddc->dbg_flag) {
52126e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
52136e683305SStefano Zampini     }
52146e683305SStefano Zampini   } else { /* processes non partecipating to coarse solver (if any) */
52156e683305SStefano Zampini     coarse_mat = 0;
52166e683305SStefano Zampini   }
52176e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
5218b1ecc7b1SStefano Zampini #if 0
5219b9b85e73SStefano Zampini   {
5220b9b85e73SStefano Zampini     PetscViewer viewer;
5221b9b85e73SStefano Zampini     char filename[256];
5222b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
5223b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
5224b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
5225b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
5226b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
5227b9b85e73SStefano Zampini   }
5228b9b85e73SStefano Zampini #endif
5229c8587f34SStefano Zampini 
5230c8587f34SStefano Zampini   /* Compute coarse null space (special handling by BDDC only) */
5231298c0119SStefano Zampini #if 0
5232c8587f34SStefano Zampini   if (pcbddc->NullSpace) {
5233c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,coarse_mat,&CoarseNullSpace);CHKERRQ(ierr);
523498a51de6SStefano Zampini   }
5235298c0119SStefano Zampini #endif
5236b0f5fe93SStefano Zampini   /* hack */
523798a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
523898a51de6SStefano Zampini     Vec crhs,csol;
523904708bb6SStefano Zampini 
5240f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
5241f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
5242f347579bSStefano Zampini     if (!csol) {
52432a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
5244f9eb5b7dSStefano Zampini     }
5245f347579bSStefano Zampini     if (!crhs) {
52462a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
5247f347579bSStefano Zampini     }
5248b0f5fe93SStefano Zampini   }
5249b0f5fe93SStefano Zampini 
5250b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
5251b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
5252b0f5fe93SStefano Zampini 
5253b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
52544f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
52554f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
52564f1b2e48SStefano Zampini     }
5257b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
5258b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
5259b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5260b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5261b0f5fe93SStefano Zampini     if (coarse_mat) {
5262b0f5fe93SStefano Zampini       Vec         nullv;
5263b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
5264b0f5fe93SStefano Zampini       PetscInt    nl;
5265b0f5fe93SStefano Zampini 
5266b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
5267b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
5268b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
5269b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
5270b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
5271b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
5272b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
5273b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
5274b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
5275b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
5276b0f5fe93SStefano Zampini     }
5277b0f5fe93SStefano Zampini   }
5278b0f5fe93SStefano Zampini 
5279b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
5280b0f5fe93SStefano Zampini     PetscBool ispreonly;
5281b0f5fe93SStefano Zampini 
5282b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
5283b0f5fe93SStefano Zampini       PetscBool isnull;
5284b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
5285b0f5fe93SStefano Zampini       if (isnull) {
5286b0f5fe93SStefano Zampini         if (isbddc) {
5287b0f5fe93SStefano Zampini           ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
5288b0f5fe93SStefano Zampini         } else {
5289b0f5fe93SStefano Zampini           ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
5290b0f5fe93SStefano Zampini         }
5291b0f5fe93SStefano Zampini       } else {
5292b0f5fe93SStefano Zampini         ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
5293b0f5fe93SStefano Zampini       }
5294b0f5fe93SStefano Zampini     }
5295b0f5fe93SStefano Zampini     /* setup coarse ksp */
5296b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
5297cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
5298cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
52996e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
5300c8587f34SStefano Zampini       KSP       check_ksp;
53012b510759SStefano Zampini       KSPType   check_ksp_type;
5302c8587f34SStefano Zampini       PC        check_pc;
53036e683305SStefano Zampini       Vec       check_vec,coarse_vec;
53046a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
53052b510759SStefano Zampini       PetscInt  its;
53066e683305SStefano Zampini       PetscBool compute_eigs;
53076e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
53086e683305SStefano Zampini       PetscInt  neigs;
53098e185a42SStefano Zampini       const char *prefix;
5310c8587f34SStefano Zampini 
53112b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
53126e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
5313422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
531423ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
5315f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
53162b510759SStefano Zampini       if (ispreonly) {
53172b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
53186e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
53192b510759SStefano Zampini       } else {
5320cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
53216e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
5322c8587f34SStefano Zampini       }
5323c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
53246e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
53256e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
53266e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
5327a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
5328a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
5329a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
5330a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
5331c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
5332c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
5333c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
5334c8587f34SStefano Zampini       /* create random vec */
53356e683305SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&coarse_vec);CHKERRQ(ierr);
53366e683305SStefano Zampini       ierr = VecDuplicate(coarse_vec,&check_vec);CHKERRQ(ierr);
5337c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
5338c8587f34SStefano Zampini       if (CoarseNullSpace) {
5339c8587f34SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
5340c8587f34SStefano Zampini       }
53416e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
5342c8587f34SStefano Zampini       /* solve coarse problem */
53436e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
5344c8587f34SStefano Zampini       if (CoarseNullSpace) {
53456e683305SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,coarse_vec);CHKERRQ(ierr);
5346c8587f34SStefano Zampini       }
5347cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
53486e683305SStefano Zampini       if (compute_eigs) {
5349854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
5350854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
53516e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
53526e683305SStefano Zampini         lambda_max = eigs_r[neigs-1];
53536e683305SStefano Zampini         lambda_min = eigs_r[0];
53546e683305SStefano Zampini         if (pcbddc->use_coarse_estimates) {
53556e683305SStefano Zampini           if (lambda_max>lambda_min) {
5356cbcc2c2aSStefano Zampini             ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max,lambda_min);CHKERRQ(ierr);
5357cbcc2c2aSStefano Zampini             ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
5358cbcc2c2aSStefano Zampini           }
5359c8587f34SStefano Zampini         }
5360c8587f34SStefano Zampini       }
5361cbcc2c2aSStefano Zampini 
5362c8587f34SStefano Zampini       /* check coarse problem residual error */
53636e683305SStefano Zampini       if (pcbddc->dbg_flag) {
53646e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
53656e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
53666e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
5367c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
53686e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
53696e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
5370c8587f34SStefano Zampini         ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
5371779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
53726e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
53736e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
53746e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
53756e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
5376b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
5377b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
5378b0f5fe93SStefano Zampini         }
53796e683305SStefano Zampini         if (compute_eigs) {
53806e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
5381deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
5382c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
53836e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
53846e683305SStefano 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);
53856e683305SStefano Zampini           for (i=0;i<neigs;i++) {
53866e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
5387c8587f34SStefano Zampini           }
53886e683305SStefano Zampini         }
53896e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
53906e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
53916e683305SStefano Zampini       }
5392c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
53936e683305SStefano Zampini       if (compute_eigs) {
53946e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
53956e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
5396c8587f34SStefano Zampini       }
53976e683305SStefano Zampini     }
53986e683305SStefano Zampini   }
5399cbcc2c2aSStefano Zampini   /* print additional info */
5400cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
54016e683305SStefano Zampini     /* waits until all processes reaches this point */
54026e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
5403cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
5404cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5405cbcc2c2aSStefano Zampini   }
5406cbcc2c2aSStefano Zampini 
54072b510759SStefano Zampini   /* free memory */
5408c8587f34SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
5409fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
5410c8587f34SStefano Zampini   PetscFunctionReturn(0);
5411c8587f34SStefano Zampini }
5412674ae819SStefano Zampini 
5413f34684f1SStefano Zampini #undef __FUNCT__
5414f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
5415f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
5416f34684f1SStefano Zampini {
5417f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
5418f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
5419f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
5420dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
5421dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
542273be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
5423dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
5424f34684f1SStefano Zampini   PetscErrorCode ierr;
5425f34684f1SStefano Zampini 
5426f34684f1SStefano Zampini   PetscFunctionBegin;
5427f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
54280e6343abSStefano Zampini   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) {
54290e6343abSStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
5430727cdba6SStefano Zampini   }
5431dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
54323bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
5433dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
5434dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
5435dc456d91SStefano Zampini   ierr = PCBDDCSubsetNumbering(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
5436dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
5437dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
5438dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
54390e6343abSStefano Zampini   if (local_size != pcbddc->local_primal_size) {
54400e6343abSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid number of local primal indices computed %d != %d",local_size,pcbddc->local_primal_size);
54410e6343abSStefano Zampini   }
5442dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
5443dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
5444dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
5445dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
5446dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
5447f34684f1SStefano Zampini 
5448f34684f1SStefano Zampini   /* check numbering */
5449f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
5450019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
5451dc456d91SStefano Zampini     PetscInt    i;
5452b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
5453f34684f1SStefano Zampini 
5454f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5455f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5456f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
54570fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
5458019a44ceSStefano Zampini     /* counter */
5459019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5460019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
5461019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5462019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5463019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5464019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5465019a44ceSStefano Zampini 
5466f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
5467f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
5468727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
5469f34684f1SStefano Zampini     }
5470f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
5471f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
5472f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5473e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5474e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5475e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5476e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5477f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5478019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
5479f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
5480019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
548175c01103SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]);
548275c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
5483b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
5484019a44ceSStefano 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);
5485f34684f1SStefano Zampini       }
5486f34684f1SStefano Zampini     }
5487019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
5488b9b85e73SStefano Zampini     ierr = MPI_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
5489f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5490f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
5491f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
5492f34684f1SStefano Zampini     }
5493f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5494f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5495e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5496e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5497f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
5498f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
5499b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
5500ca8b9ea9SStefano Zampini       PetscInt *gidxs;
5501ca8b9ea9SStefano Zampini 
5502ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
55033bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
5504f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
5505f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5506f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
5507f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
55084bc2dc4bSStefano 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);
5509f34684f1SStefano Zampini       }
5510f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5511ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
5512f34684f1SStefano Zampini     }
5513f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5514302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
5515f34684f1SStefano Zampini   }
55168bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
5517f34684f1SStefano Zampini   /* get back data */
5518f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
5519f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
5520674ae819SStefano Zampini   PetscFunctionReturn(0);
5521674ae819SStefano Zampini }
5522674ae819SStefano Zampini 
5523e456f2a8SStefano Zampini #undef __FUNCT__
5524e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
5525a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
5526e456f2a8SStefano Zampini {
5527e456f2a8SStefano Zampini   IS             localis_t;
5528a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
5529e456f2a8SStefano Zampini   PetscScalar    *vals;
5530e456f2a8SStefano Zampini   PetscErrorCode ierr;
5531e456f2a8SStefano Zampini 
5532e456f2a8SStefano Zampini   PetscFunctionBegin;
5533a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
5534e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
5535854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
5536e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
5537e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
5538a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
5539a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
55401035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
5541a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
55421035eff8SStefano Zampini   }
5543a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
5544e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
5545e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
5546a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
5547a7dc3881SStefano Zampini   /* now compute set in local ordering */
5548a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5549a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5550a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
5551a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
5552a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
5553ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
5554e456f2a8SStefano Zampini       lsize++;
5555e456f2a8SStefano Zampini     }
5556e456f2a8SStefano Zampini   }
5557854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
5558a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
5559ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
5560e456f2a8SStefano Zampini       idxs[lsize++] = i;
5561e456f2a8SStefano Zampini     }
5562e456f2a8SStefano Zampini   }
5563a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
5564a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
5565e456f2a8SStefano Zampini   *localis = localis_t;
5566e456f2a8SStefano Zampini   PetscFunctionReturn(0);
5567e456f2a8SStefano Zampini }
5568906d46d4SStefano Zampini 
5569906d46d4SStefano Zampini /* the next two functions will be called in KSPMatMult if a change of basis has been requested */
5570906d46d4SStefano Zampini #undef __FUNCT__
5571906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMult_Private"
5572906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMult_Private(Mat A, Vec x, Vec y)
5573906d46d4SStefano Zampini {
5574906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
5575906d46d4SStefano Zampini   PetscErrorCode   ierr;
5576906d46d4SStefano Zampini 
5577906d46d4SStefano Zampini   PetscFunctionBegin;
5578906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
5579906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
5580906d46d4SStefano Zampini   ierr = MatMult(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
5581906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
5582906d46d4SStefano Zampini   PetscFunctionReturn(0);
5583906d46d4SStefano Zampini }
5584906d46d4SStefano Zampini 
5585906d46d4SStefano Zampini #undef __FUNCT__
5586906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMultTranspose_Private"
5587906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMultTranspose_Private(Mat A, Vec x, Vec y)
5588906d46d4SStefano Zampini {
5589906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
5590906d46d4SStefano Zampini   PetscErrorCode   ierr;
5591906d46d4SStefano Zampini 
5592906d46d4SStefano Zampini   PetscFunctionBegin;
5593906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
5594906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
5595906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
5596906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
5597906d46d4SStefano Zampini   PetscFunctionReturn(0);
5598906d46d4SStefano Zampini }
5599b96c3477SStefano Zampini 
5600b96c3477SStefano Zampini #undef __FUNCT__
5601b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
560208122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
5603b96c3477SStefano Zampini {
5604a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
5605b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
5606b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
5607a64f4aa4SStefano Zampini   Mat                 S_j;
5608b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
5609b96c3477SStefano Zampini   PetscBool           free_used_adj;
5610b96c3477SStefano Zampini   PetscErrorCode      ierr;
5611b96c3477SStefano Zampini 
5612b96c3477SStefano Zampini   PetscFunctionBegin;
5613b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
5614b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
561508122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
5616b96c3477SStefano Zampini     used_xadj = NULL;
5617b96c3477SStefano Zampini     used_adjncy = NULL;
5618b96c3477SStefano Zampini   } else {
561908122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
562008122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
562108122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
562208122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
5623b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
5624b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
5625b96c3477SStefano Zampini     } else {
56262fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
5627b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
5628b96c3477SStefano Zampini       PetscInt       nvtxs;
5629b96c3477SStefano Zampini 
56302fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
56312fffb893SStefano Zampini       if (flg_row) {
5632b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
5633b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
5634b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
5635b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
56362fffb893SStefano Zampini       } else {
56372fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
56382fffb893SStefano Zampini         used_xadj = NULL;
56392fffb893SStefano Zampini         used_adjncy = NULL;
56402fffb893SStefano Zampini       }
56412fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
5642b96c3477SStefano Zampini     }
5643b96c3477SStefano Zampini   }
5644d5574798SStefano Zampini 
5645d5574798SStefano Zampini   /* setup sub_schurs data */
5646a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
5647a64f4aa4SStefano Zampini   if (!sub_schurs->use_mumps) {
5648a64f4aa4SStefano Zampini     /* pcbddc->ksp_D up to date only if not using MUMPS */
5649a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
565006a4e24aSStefano 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);
5651a64f4aa4SStefano Zampini   } else {
56526816873aSStefano Zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
565304708bb6SStefano Zampini     PetscBool isseqaij;
56545feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
56555feab87aSStefano Zampini       PetscInt n_vertices;
56565feab87aSStefano Zampini 
56575feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
56582034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
56595feab87aSStefano Zampini     }
566004708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
566104708bb6SStefano Zampini     if (!isseqaij) {
566204708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
566304708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
566404708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
566504708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
566604708bb6SStefano Zampini       } else {
566704708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
566804708bb6SStefano Zampini       }
566904708bb6SStefano Zampini     }
567006a4e24aSStefano 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);
5671a64f4aa4SStefano Zampini   }
5672a64f4aa4SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
5673b96c3477SStefano Zampini 
5674b96c3477SStefano Zampini   /* free adjacency */
5675b96c3477SStefano Zampini   if (free_used_adj) {
5676b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
5677b96c3477SStefano Zampini   }
5678b96c3477SStefano Zampini   PetscFunctionReturn(0);
5679b96c3477SStefano Zampini }
5680b96c3477SStefano Zampini 
5681b96c3477SStefano Zampini #undef __FUNCT__
5682b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
568308122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
5684b96c3477SStefano Zampini {
5685b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
5686b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
5687b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
5688b96c3477SStefano Zampini   PCBDDCGraph         graph;
5689b96c3477SStefano Zampini   PetscErrorCode      ierr;
5690b96c3477SStefano Zampini 
5691b96c3477SStefano Zampini   PetscFunctionBegin;
5692b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
569308122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
56943301b35fSStefano Zampini     IS       verticesIS,verticescomm;
56953301b35fSStefano Zampini     PetscInt vsize,*idxs;
5696b96c3477SStefano Zampini 
5697b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
56983301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
56993301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
57003301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
57013301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
57023301b35fSStefano Zampini     ierr = ISDestroy(&verticesIS);CHKERRQ(ierr);
5703b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
57047fb0e2dbSStefano Zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global);CHKERRQ(ierr);
57053301b35fSStefano Zampini     ierr = PCBDDCGraphSetUp(graph,0,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
57063301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
5707b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
5708b96c3477SStefano Zampini /*
5709b96c3477SStefano Zampini     if (pcbddc->dbg_flag) {
5710b96c3477SStefano Zampini       ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
5711b96c3477SStefano Zampini     }
5712b96c3477SStefano Zampini */
5713b96c3477SStefano Zampini   } else {
5714b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
5715b96c3477SStefano Zampini   }
5716b96c3477SStefano Zampini 
5717b96c3477SStefano Zampini   /* sub_schurs init */
5718a64f4aa4SStefano Zampini   ierr = PCBDDCSubSchursInit(sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap);CHKERRQ(ierr);
5719a64f4aa4SStefano Zampini 
5720b96c3477SStefano Zampini   /* free graph struct */
572108122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
5722b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
5723b96c3477SStefano Zampini   }
5724b96c3477SStefano Zampini   PetscFunctionReturn(0);
5725b96c3477SStefano Zampini }
5726fa34dd3eSStefano Zampini 
5727fa34dd3eSStefano Zampini #undef __FUNCT__
5728fa34dd3eSStefano Zampini #define __FUNCT__ "PCBDDCCheckOperator"
5729fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
5730fa34dd3eSStefano Zampini {
5731fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
5732fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
5733fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
5734fa34dd3eSStefano Zampini 
5735fa34dd3eSStefano Zampini   PetscFunctionBegin;
5736fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
5737fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
57384f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
5739fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
57404f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
574175c01103SStefano Zampini     PetscReal      norm;
5742fa34dd3eSStefano Zampini     PetscInt       i;
5743fa34dd3eSStefano Zampini 
5744fa34dd3eSStefano Zampini     /* B0 and B0_B */
5745fa34dd3eSStefano Zampini     if (zerodiag) {
5746fa34dd3eSStefano Zampini       IS       dummy;
5747fa34dd3eSStefano Zampini 
57484f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
57494f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
5750fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
5751fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
5752fa34dd3eSStefano Zampini     }
5753fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
5754fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
5755fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
5756fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5757fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5758fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5759fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5760fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
5761fa34dd3eSStefano Zampini     /* S_j */
5762fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
5763fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
5764fa34dd3eSStefano Zampini 
5765fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
5766fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
5767fa34dd3eSStefano Zampini     /* continuous in primal space */
5768fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
5769fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5770fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5771fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
57724f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
57734f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
5774fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
5775fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5776fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
5777fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
5778fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5779fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5780fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
5781fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
5782fa34dd3eSStefano Zampini 
5783fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
5784fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
5785fa34dd3eSStefano Zampini     /* local with Schur */
5786fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
5787fa34dd3eSStefano Zampini     if (zerodiag) {
5788fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
57894f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
5790fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
5791fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
5792fa34dd3eSStefano Zampini     }
5793fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
5794fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5795fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5796fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5797fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
5798fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
5799fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
5800fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5801fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
5802fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5803fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5804fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5805fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5806fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5807fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
5808fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
5809fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
5810fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5811fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
5812fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
5813fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5814fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5815fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
5816fa34dd3eSStefano Zampini     if (zerodiag) {
5817fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
5818fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
58194f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
5820fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
5821fa34dd3eSStefano Zampini     }
5822fa34dd3eSStefano Zampini     /* BDDC */
5823fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
5824fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
5825fa34dd3eSStefano Zampini 
5826fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
5827fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
5828fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
5829fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
58304f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
58314f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
5832fa34dd3eSStefano Zampini     }
58334f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
5834fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
5835fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
5836fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
5837fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
5838fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
5839fa34dd3eSStefano Zampini   }
5840fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
5841fa34dd3eSStefano Zampini }
5842