xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision 30368db7a196d34abcffce59efe277e055a7d266)
11cf9b237SStefano Zampini #include <../src/mat/impls/aij/seq/aij.h>
2ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddc.h>
3ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddcprivate.h>
4674ae819SStefano Zampini #include <petscblaslapack.h>
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 
91cf9b237SStefano Zampini /* TODO: add reuse flag */
101cf9b237SStefano Zampini #undef __FUNCT__
111cf9b237SStefano Zampini #define __FUNCT__ "MatSeqAIJCompress"
121cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
131cf9b237SStefano Zampini {
141cf9b237SStefano Zampini   Mat            Bt;
151cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
161cf9b237SStefano Zampini   const PetscInt *ii,*ij;
171cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
181cf9b237SStefano Zampini   PetscBool      flg_row;
191cf9b237SStefano Zampini   PetscErrorCode ierr;
201cf9b237SStefano Zampini 
211cf9b237SStefano Zampini   PetscFunctionBegin;
221cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
231cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
241cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
251cf9b237SStefano Zampini   nnz = n;
261cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
271cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
281cf9b237SStefano Zampini   }
291cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
301cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
311cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
321cf9b237SStefano Zampini   nnz = 0;
331cf9b237SStefano Zampini   bii[0] = 0;
341cf9b237SStefano Zampini   for (i=0;i<n;i++) {
351cf9b237SStefano Zampini     PetscInt j;
361cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
371cf9b237SStefano Zampini       PetscScalar entry = a[j];
381cf9b237SStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || ij[j] == i) {
391cf9b237SStefano Zampini         bij[nnz] = ij[j];
401cf9b237SStefano Zampini         bdata[nnz] = entry;
411cf9b237SStefano Zampini         nnz++;
421cf9b237SStefano Zampini       }
431cf9b237SStefano Zampini     }
441cf9b237SStefano Zampini     bii[i+1] = nnz;
451cf9b237SStefano Zampini   }
461cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
471cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
481cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
491cf9b237SStefano Zampini   {
501cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
511cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
521cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
531cf9b237SStefano Zampini   }
541cf9b237SStefano Zampini   *B = Bt;
551cf9b237SStefano Zampini   PetscFunctionReturn(0);
561cf9b237SStefano Zampini }
571cf9b237SStefano 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) {
751cf9b237SStefano Zampini     PetscBool isseqdense;
761cf9b237SStefano Zampini 
771cf9b237SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
781cf9b237SStefano Zampini     if (!isseqdense) {
794f1b2e48SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
801cf9b237SStefano Zampini     } else { /* TODO: rectangular case and LDA */
811cf9b237SStefano Zampini       PetscScalar *array;
821cf9b237SStefano Zampini       PetscReal   chop=1.e-6;
831cf9b237SStefano Zampini 
841cf9b237SStefano Zampini       ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
851cf9b237SStefano Zampini       ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
861cf9b237SStefano Zampini       ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
871cf9b237SStefano Zampini       for (i=0;i<n;i++) {
881cf9b237SStefano Zampini         PetscInt j;
891cf9b237SStefano Zampini         for (j=i+1;j<n;j++) {
901cf9b237SStefano Zampini           PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
911cf9b237SStefano Zampini           if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
921cf9b237SStefano Zampini           if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
931cf9b237SStefano Zampini         }
941cf9b237SStefano Zampini       }
951cf9b237SStefano Zampini       ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
961cf9b237SStefano Zampini       ierr = MatConvert(B,MATSEQAIJ,MAT_REUSE_MATRIX,&B);CHKERRQ(ierr);
971cf9b237SStefano 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);
1501cf9b237SStefano Zampini   if (A != B) {
1514f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
1524f1b2e48SStefano Zampini   }
1534f1b2e48SStefano Zampini 
1544f1b2e48SStefano Zampini   /* get back data */
1551cf9b237SStefano Zampini   if (ncc) *ncc = graph->ncc;
1561cf9b237SStefano 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;
1621cf9b237SStefano 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;
2569f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
2579f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
258339f8db1SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
259339f8db1SStefano Zampini   ierr = PetscObjectReference((PetscObject)pcbddc->local_mat);CHKERRQ(ierr);
260339f8db1SStefano Zampini   pcbddc->benign_original_mat = pcbddc->local_mat;
2614f1b2e48SStefano Zampini   /* if a local info on dofs is present, assumes the last field is represented by "pressures"
2624f1b2e48SStefano Zampini      otherwise, it uses only zerodiagonal dofs (ok if the pressure block is all zero; it could fail if it is not)
2634f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
2644f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
2654f1b2e48SStefano Zampini      since the local Schur complements are SPD
2664f1b2e48SStefano Zampini   */
2674f1b2e48SStefano Zampini   has_null_pressures = PETSC_TRUE;
2684f1b2e48SStefano Zampini   have_null = PETSC_TRUE;
26940fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
2704f1b2e48SStefano Zampini     PetscInt npl,*idxs,p = pcbddc->n_ISForDofsLocal-1;
2714f1b2e48SStefano Zampini 
2724f1b2e48SStefano Zampini     /* Dofs splitting for BDDC cannot have PETSC_COMM_SELF, so create a sequential IS */
2734f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[p],&npl);CHKERRQ(ierr);
2744f1b2e48SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
2754f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,npl,idxs,PETSC_COPY_VALUES,&pressures);CHKERRQ(ierr);
276ba14f8e3SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
27740fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
27840fa8d13SStefano Zampini     if (!sorted) {
27940fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
28040fa8d13SStefano Zampini     }
28140fa8d13SStefano Zampini   } else {
28240fa8d13SStefano Zampini     pressures = NULL;
28340fa8d13SStefano Zampini   }
2844f1b2e48SStefano Zampini   ierr = MatGetLocalSize(pcbddc->benign_original_mat,&n,NULL);CHKERRQ(ierr);
2854f1b2e48SStefano Zampini   /* TODO: add check for shared dofs and raise error */
286339f8db1SStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->benign_original_mat,&zerodiag);CHKERRQ(ierr);
287339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
288339f8db1SStefano Zampini   if (!sorted) {
289339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
290339f8db1SStefano Zampini   }
291339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
2924f1b2e48SStefano Zampini   if (!nz) {
2934f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
2944f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
29540fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
29640fa8d13SStefano Zampini   }
2974f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
2984f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
2994f1b2e48SStefano Zampini   zerodiag_subs = NULL;
3004f1b2e48SStefano Zampini   pcbddc->benign_n = 0;
3014f1b2e48SStefano Zampini   if (has_null_pressures) {
3024f1b2e48SStefano Zampini     IS       *subs;
3034f1b2e48SStefano Zampini     PetscInt nsubs,i;
3044f1b2e48SStefano Zampini 
3054f1b2e48SStefano Zampini     subs = pcbddc->local_subs;
3064f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
3074f1b2e48SStefano Zampini     if (nsubs > 1) {
3084f1b2e48SStefano Zampini       ierr = PetscCalloc1(nsubs,&zerodiag_subs);CHKERRQ(ierr);
3094f1b2e48SStefano Zampini       for (i=0;i<nsubs;i++) {
3104f1b2e48SStefano Zampini         ISLocalToGlobalMapping l2g;
3114f1b2e48SStefano Zampini         IS                     t_zerodiag_subs;
3124f1b2e48SStefano Zampini         PetscInt               nl;
3134f1b2e48SStefano Zampini 
3144f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
3154f1b2e48SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,zerodiag,&t_zerodiag_subs);CHKERRQ(ierr);
3164f1b2e48SStefano Zampini         ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
3174f1b2e48SStefano Zampini         if (nl) {
3184f1b2e48SStefano Zampini           PetscBool valid = PETSC_TRUE;
3194f1b2e48SStefano Zampini 
3204f1b2e48SStefano Zampini           if (pressures) {
3214f1b2e48SStefano Zampini             IS t_pressure_subs;
3224f1b2e48SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
3234f1b2e48SStefano Zampini             ierr = ISEqual(t_pressure_subs,t_zerodiag_subs,&valid);CHKERRQ(ierr);
3244f1b2e48SStefano Zampini             ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
3254f1b2e48SStefano Zampini           }
3264f1b2e48SStefano Zampini           if (valid) {
3274f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[pcbddc->benign_n]);CHKERRQ(ierr);
3284f1b2e48SStefano Zampini             pcbddc->benign_n++;
3294f1b2e48SStefano Zampini           } else {
3304f1b2e48SStefano Zampini             recompute_zerodiag = PETSC_TRUE;
3314f1b2e48SStefano Zampini           }
3324f1b2e48SStefano Zampini         }
3334f1b2e48SStefano Zampini         ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
3344f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
3354f1b2e48SStefano Zampini       }
3364f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
3374f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
3384f1b2e48SStefano Zampini       if (pressures) {
3394f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
3404f1b2e48SStefano Zampini       }
3414f1b2e48SStefano Zampini       if (valid) {
3424f1b2e48SStefano Zampini         pcbddc->benign_n = 1;
3434f1b2e48SStefano Zampini         ierr = PetscCalloc1(1,&zerodiag_subs);CHKERRQ(ierr);
3444f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
3454f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
3464f1b2e48SStefano Zampini       }
3474f1b2e48SStefano Zampini     }
3484f1b2e48SStefano Zampini   }
3494f1b2e48SStefano Zampini 
3504f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
3514f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
3524f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
3534f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
3544f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
3554f1b2e48SStefano Zampini   }
3564f1b2e48SStefano Zampini 
3574f1b2e48SStefano Zampini   /* final check for null pressures */
3584f1b2e48SStefano Zampini   if (zerodiag && pressures) {
3594f1b2e48SStefano Zampini     PetscInt nz,np;
3604f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
3614f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
3624f1b2e48SStefano Zampini     if (nz != np) have_null = PETSC_FALSE;
3634f1b2e48SStefano Zampini   }
3644f1b2e48SStefano Zampini 
3654f1b2e48SStefano Zampini   if (recompute_zerodiag) {
3664f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
3674f1b2e48SStefano Zampini     if (pcbddc->benign_n == 1) {
3684f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
3694f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
3704f1b2e48SStefano Zampini     } else {
3714f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
3724f1b2e48SStefano Zampini 
3734f1b2e48SStefano Zampini       nzn = 0;
3744f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
3754f1b2e48SStefano Zampini         PetscInt ns;
3764f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
3774f1b2e48SStefano Zampini         nzn += ns;
3784f1b2e48SStefano Zampini       }
3794f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
3804f1b2e48SStefano Zampini       nzn = 0;
3814f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
3824f1b2e48SStefano Zampini         PetscInt ns,*idxs;
3834f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
3844f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
3854f1b2e48SStefano Zampini         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
3864f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
3874f1b2e48SStefano Zampini         nzn += ns;
3884f1b2e48SStefano Zampini       }
3894f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
3904f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
3914f1b2e48SStefano Zampini     }
3924f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
3934f1b2e48SStefano Zampini   }
3944f1b2e48SStefano Zampini 
3954f1b2e48SStefano Zampini   if (has_null_pressures) {
3964f1b2e48SStefano Zampini     IS             zerodiagc;
3974f1b2e48SStefano Zampini     const PetscInt *idxs,*idxsc;
3984f1b2e48SStefano Zampini     PetscInt       i,s,*nnz;
3991cf9b237SStefano Zampini     Mat            M;
4004f1b2e48SStefano Zampini 
4014f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
402339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
403339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
404339f8db1SStefano Zampini     /* local change of basis for pressures */
405339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
406339f8db1SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->benign_original_mat),&pcbddc->benign_change);CHKERRQ(ierr);
407339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
408339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
409339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
4104f1b2e48SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities plus pressure dofs for non-singular subdomains */
4114f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
4124f1b2e48SStefano Zampini       PetscInt nzs,j;
4134f1b2e48SStefano Zampini 
4144f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[i],&nzs);CHKERRQ(ierr);
4154f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
4164f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
4174f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
4184f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
4194f1b2e48SStefano Zampini     }
420339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
421339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
422339f8db1SStefano Zampini     /* set identity on velocities */
423339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
424339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
425339f8db1SStefano Zampini     }
4264f1b2e48SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
4274f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
4289f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
4294f1b2e48SStefano 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);
430339f8db1SStefano Zampini     /* set change on pressures */
4314f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
4324f1b2e48SStefano Zampini       PetscScalar *array;
4334f1b2e48SStefano Zampini       PetscInt    nzs;
4344f1b2e48SStefano Zampini 
4354f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[s],&nzs);CHKERRQ(ierr);
4364f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
4374f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
438339f8db1SStefano Zampini         PetscScalar vals[2];
439339f8db1SStefano Zampini         PetscInt    cols[2];
440339f8db1SStefano Zampini 
441339f8db1SStefano Zampini         cols[0] = idxs[i];
4424f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
443339f8db1SStefano Zampini         vals[0] = 1.;
444b0f5fe93SStefano Zampini         vals[1] = 1.;
4454f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
446339f8db1SStefano Zampini       }
4474f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
4484f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
4494f1b2e48SStefano Zampini       array[nzs-1] = 1.;
4504f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
4514f1b2e48SStefano Zampini       /* store local idxs for p0 */
4524f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
4534f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
4544f1b2e48SStefano Zampini       ierr = ISDestroy(&zerodiag_subs[s]);CHKERRQ(ierr);
455339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
4564f1b2e48SStefano Zampini     }
457339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
458339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
459339f8db1SStefano Zampini     /* TODO: need optimization? */
460339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
4611cf9b237SStefano Zampini     ierr = MatPtAP(pcbddc->benign_original_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
4621cf9b237SStefano Zampini     ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
4631cf9b237SStefano Zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
4644f1b2e48SStefano Zampini     /* store global idxs for p0 */
4654f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
466339f8db1SStefano Zampini   }
4674f1b2e48SStefano Zampini   ierr = PetscFree(zerodiag_subs);CHKERRQ(ierr);
4684f1b2e48SStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
469b0f5fe93SStefano Zampini 
470b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
471b0f5fe93SStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
472339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
473339f8db1SStefano Zampini   PetscFunctionReturn(0);
474339f8db1SStefano Zampini }
475339f8db1SStefano Zampini 
476339f8db1SStefano Zampini #undef __FUNCT__
477015636ebSStefano Zampini #define __FUNCT__ "PCBDDCBenignGetOrSetP0"
478015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
479efc2fbd9SStefano Zampini {
480efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
481efc2fbd9SStefano Zampini   PetscErrorCode ierr;
482efc2fbd9SStefano Zampini 
483efc2fbd9SStefano Zampini   PetscFunctionBegin;
484efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
485efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
4864f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
487efc2fbd9SStefano Zampini   }
488015636ebSStefano Zampini   if (get) { /* use SF to get values */
489efc2fbd9SStefano Zampini     PetscScalar *array;
490efc2fbd9SStefano Zampini 
491efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
4924f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
4934f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
494efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
4954f1b2e48SStefano Zampini   } else { /* use VecSetValues (not scalable, I should try to find a better solution (defining a new MPI_OP for reduction) */
4964f1b2e48SStefano Zampini     ierr = VecSetValues(v,pcbddc->benign_n,pcbddc->benign_p0_gidx,pcbddc->benign_p0,INSERT_VALUES);CHKERRQ(ierr);
497efc2fbd9SStefano Zampini     ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
498efc2fbd9SStefano Zampini     ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
499efc2fbd9SStefano Zampini   }
500efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
501efc2fbd9SStefano Zampini }
502efc2fbd9SStefano Zampini 
503efc2fbd9SStefano Zampini #undef __FUNCT__
504c263805aSStefano Zampini #define __FUNCT__ "PCBDDCBenignPopOrPushB0"
505c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
506c263805aSStefano Zampini {
507c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
508c263805aSStefano Zampini   PetscErrorCode ierr;
509c263805aSStefano Zampini 
510c263805aSStefano Zampini   PetscFunctionBegin;
511c263805aSStefano Zampini   /* TODO: add error checking
512c263805aSStefano Zampini     - avoid nested pop (or push) calls.
513c263805aSStefano Zampini     - cannot push before pop.
5141c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
515c263805aSStefano Zampini   */
5164f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
517efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
518efc2fbd9SStefano Zampini   }
519c263805aSStefano Zampini   if (pop) {
5204f1b2e48SStefano Zampini     IS       is_p0;
5214f1b2e48SStefano Zampini     MatReuse reuse;
522c263805aSStefano Zampini 
523c263805aSStefano Zampini     /* extract B_0 */
5244f1b2e48SStefano Zampini     reuse = MAT_INITIAL_MATRIX;
5254f1b2e48SStefano Zampini     if (pcbddc->benign_B0) {
5264f1b2e48SStefano Zampini       reuse = MAT_REUSE_MATRIX;
5274f1b2e48SStefano Zampini     }
5284f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
5294f1b2e48SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
530c263805aSStefano Zampini     /* remove rows and cols from local problem */
531c263805aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
5324f1b2e48SStefano Zampini     ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
5334f1b2e48SStefano Zampini     ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
534c263805aSStefano Zampini   } else { /* push */
5354f1b2e48SStefano Zampini     PetscInt i;
5364f1b2e48SStefano Zampini 
5374f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
5384f1b2e48SStefano Zampini       PetscScalar *B0_vals;
5394f1b2e48SStefano Zampini       PetscInt    *B0_cols,B0_ncol;
5404f1b2e48SStefano Zampini 
5414f1b2e48SStefano Zampini       ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
5424f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
5434f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+1,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
5444f1b2e48SStefano Zampini       ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
5454f1b2e48SStefano Zampini       ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
5464f1b2e48SStefano Zampini     }
547c263805aSStefano Zampini     ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
548c263805aSStefano Zampini     ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
549c263805aSStefano Zampini   }
550c263805aSStefano Zampini   PetscFunctionReturn(0);
551c263805aSStefano Zampini }
552c263805aSStefano Zampini 
553c263805aSStefano Zampini #undef __FUNCT__
554b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
55508122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
556b1b3d7a2SStefano Zampini {
557b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
55808122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
55908122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
56008122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
56108122e43SStefano Zampini   PetscScalar     *work,lwork;
56208122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
56308122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
56408122e43SStefano Zampini   PetscReal       *eigs,thresh;
5651b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
566f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
56708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
56808122e43SStefano Zampini   PetscReal       *rwork;
56908122e43SStefano Zampini #endif
570b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
571b1b3d7a2SStefano Zampini 
572b1b3d7a2SStefano Zampini   PetscFunctionBegin;
57308122e43SStefano Zampini   if (!sub_schurs->use_mumps) {
57408122e43SStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS");
57508122e43SStefano Zampini   }
57608122e43SStefano Zampini 
57706a4e24aSStefano Zampini   if (sub_schurs->n_subs && (!sub_schurs->is_hermitian || !sub_schurs->is_posdef)) {
57806a4e24aSStefano 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);
57906a4e24aSStefano Zampini   }
58006a4e24aSStefano Zampini 
581fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
582fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
583fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
584fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
585fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
586fd14bc51SStefano Zampini   }
587fd14bc51SStefano Zampini 
588e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
589e496cd5dSStefano 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);
590e496cd5dSStefano Zampini   }
591e496cd5dSStefano Zampini 
59208122e43SStefano Zampini   /* max size of subsets */
59308122e43SStefano Zampini   mss = 0;
59408122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
59508122e43SStefano Zampini     PetscInt subset_size;
596862806e4SStefano Zampini 
59708122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
59808122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
59908122e43SStefano Zampini   }
60008122e43SStefano Zampini 
60108122e43SStefano Zampini   /* min/max and threshold */
60208122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
603f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
60408122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
605f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
606f6f667cfSStefano Zampini   if (nmin) {
607f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
608f6f667cfSStefano Zampini   }
60908122e43SStefano Zampini 
61008122e43SStefano Zampini   /* allocate lapack workspace */
61108122e43SStefano Zampini   cum = cum2 = 0;
61208122e43SStefano Zampini   maxneigs = 0;
61308122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
61408122e43SStefano Zampini     PetscInt n,subset_size;
615f6f667cfSStefano Zampini 
61608122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
61708122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
6189162d606SStefano Zampini     cum += subset_size;
6199162d606SStefano Zampini     cum2 += subset_size*n;
62008122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
62108122e43SStefano Zampini   }
62208122e43SStefano Zampini   if (mss) {
6239ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
62408122e43SStefano Zampini       PetscBLASInt B_itype = 1;
62508122e43SStefano Zampini       PetscBLASInt B_N = mss;
6264c6709b3SStefano Zampini       PetscReal    zero = 0.0;
6274c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
62808122e43SStefano Zampini 
62908122e43SStefano Zampini       B_lwork = -1;
63008122e43SStefano Zampini       S = NULL;
63108122e43SStefano Zampini       St = NULL;
632a58a30b4SStefano Zampini       eigs = NULL;
633a58a30b4SStefano Zampini       eigv = NULL;
634a58a30b4SStefano Zampini       B_iwork = NULL;
635a58a30b4SStefano Zampini       B_ifail = NULL;
636d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
637d1710679SStefano Zampini       rwork = NULL;
638d1710679SStefano Zampini #endif
6398bec7fa6SStefano Zampini       thresh = 1.0;
64008122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
64108122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
64208122e43SStefano 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));
64308122e43SStefano Zampini #else
64408122e43SStefano 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));
64508122e43SStefano Zampini #endif
64608122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
64708122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
64808122e43SStefano Zampini     } else {
64908122e43SStefano Zampini         /* TODO */
65008122e43SStefano Zampini     }
65108122e43SStefano Zampini   } else {
65208122e43SStefano Zampini     lwork = 0;
65308122e43SStefano Zampini   }
65408122e43SStefano Zampini 
65508122e43SStefano Zampini   nv = 0;
656d62866d3SStefano 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) */
657d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
65808122e43SStefano Zampini   }
6594c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
660f6f667cfSStefano Zampini   if (allocated_S_St) {
661f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
662f6f667cfSStefano Zampini   }
663f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
66408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
66508122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
66608122e43SStefano Zampini #endif
6679162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
6689162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
6699162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
67008122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
6719162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
67208122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
67308122e43SStefano Zampini 
67408122e43SStefano Zampini   maxneigs = 0;
67508122e43SStefano Zampini   cum = cum2 = cumarray = 0;
6769162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
6779162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
678d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
67908122e43SStefano Zampini     const PetscInt *idxs;
68008122e43SStefano Zampini 
681d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
68208122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
68308122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
68408122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
68508122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
6869162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
6879162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
68808122e43SStefano Zampini     }
68908122e43SStefano Zampini     cum2 = cum;
690d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
69108122e43SStefano Zampini   }
69208122e43SStefano Zampini 
69308122e43SStefano Zampini   if (mss) { /* multilevel */
69408122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
69508122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
69608122e43SStefano Zampini   }
69708122e43SStefano Zampini 
69808122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
69908122e43SStefano Zampini 
70008122e43SStefano Zampini     const PetscInt *idxs;
701f6f667cfSStefano Zampini     PetscReal      infty = PETSC_MAX_REAL;
702862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
70308122e43SStefano Zampini     PetscBLASInt   B_N;
704aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
70508122e43SStefano Zampini 
706862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
707f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
708f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
7099ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
710aff50787SStefano Zampini         PetscInt j,k;
711aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
712aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
713aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
71408122e43SStefano Zampini         }
71508122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
716aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
717aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
718aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
719aff50787SStefano Zampini           }
72008122e43SStefano Zampini         }
72108122e43SStefano Zampini       } else {
72208122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
72308122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
72408122e43SStefano Zampini       }
7258bec7fa6SStefano Zampini     } else {
726f6f667cfSStefano Zampini       S = Sarray + cumarray;
727f6f667cfSStefano Zampini       St = Starray + cumarray;
7288bec7fa6SStefano Zampini     }
72908122e43SStefano Zampini 
730f6f667cfSStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
731aff50787SStefano Zampini     /* see if we can save some work */
732aff50787SStefano Zampini     if (sub_schurs->n_subs == 1) {
733aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
734aff50787SStefano Zampini     }
735aff50787SStefano Zampini 
736aff50787SStefano Zampini     if (same_data) { /* there's no need of constraints here, deluxe scaling is enough */
737aff50787SStefano Zampini       B_neigs = 0;
738aff50787SStefano Zampini     } else {
739aff50787SStefano Zampini       /* Threshold: this is an heuristic for edges */
740f6f667cfSStefano Zampini       thresh = pcbddc->mat_graph->count[idxs[0]]*pcbddc->adaptive_threshold;
7411cf9b237SStefano Zampini       if (nmin) {
7421cf9b237SStefano Zampini         Mat SM,StM;
7431cf9b237SStefano Zampini         PetscInt j,k,nccs,nccst;
7441cf9b237SStefano Zampini 
7451cf9b237SStefano Zampini         for (j=0;j<subset_size;j++) {
7461cf9b237SStefano Zampini           for (k=j;k<subset_size;k++) {
7471cf9b237SStefano Zampini             S [k*subset_size+j] = S [j*subset_size+k];
7481cf9b237SStefano Zampini             St[k*subset_size+j] = St[j*subset_size+k];
7491cf9b237SStefano Zampini           }
7501cf9b237SStefano Zampini         }
7511cf9b237SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,subset_size,S,&SM);CHKERRQ(ierr);
7521cf9b237SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,subset_size,St,&StM);CHKERRQ(ierr);
7531cf9b237SStefano Zampini         ierr = MatDetectDisconnectedComponents(SM,PETSC_TRUE,&nccs,NULL);CHKERRQ(ierr);
7541cf9b237SStefano Zampini         ierr = MatDetectDisconnectedComponents(StM,PETSC_TRUE,&nccst,NULL);CHKERRQ(ierr);
7551cf9b237SStefano Zampini         if (nccs != 1 || nccst != 1) {
7561cf9b237SStefano Zampini           PetscPrintf(PETSC_COMM_SELF,"[%d] Found disc %d %d (size %d)\n",PetscGlobalRank,nccs,nccst,subset_size);
7571cf9b237SStefano Zampini         }
7581cf9b237SStefano Zampini         ierr = MatDestroy(&SM);CHKERRQ(ierr);
7591cf9b237SStefano Zampini         ierr = MatDestroy(&StM);CHKERRQ(ierr);
7601cf9b237SStefano Zampini       }
761f6f667cfSStefano Zampini 
7629ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
76308122e43SStefano Zampini         PetscBLASInt B_itype = 1;
764f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
7654c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
7669552c7c7SStefano Zampini         PetscInt     nmin_s;
76708122e43SStefano Zampini 
768fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
7698bec7fa6SStefano 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]]);
770fd14bc51SStefano Zampini         }
771d16cbb6bSStefano Zampini 
77208122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
773d16cbb6bSStefano Zampini         if (thresh > 1.+PETSC_SMALL) {
774d16cbb6bSStefano Zampini 
775d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
77608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
777f6f667cfSStefano 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));
77808122e43SStefano Zampini #else
779f6f667cfSStefano 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));
78008122e43SStefano Zampini #endif
781d16cbb6bSStefano Zampini         } else {
782d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
783d16cbb6bSStefano Zampini           B_IL = 1;
784d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
785d16cbb6bSStefano 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));
786d16cbb6bSStefano Zampini #else
787d16cbb6bSStefano 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));
788d16cbb6bSStefano Zampini #endif
789d16cbb6bSStefano Zampini         }
79008122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
79108122e43SStefano Zampini         if (B_ierr) {
79208122e43SStefano Zampini           if (B_ierr < 0 ) {
79308122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
79408122e43SStefano Zampini           } else if (B_ierr <= B_N) {
79508122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
79608122e43SStefano Zampini           } else {
7979552c7c7SStefano 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);
79808122e43SStefano Zampini           }
79908122e43SStefano Zampini         }
80008122e43SStefano Zampini 
80108122e43SStefano Zampini         if (B_neigs > nmax) {
802fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
803fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
804fd14bc51SStefano Zampini           }
805f6f667cfSStefano Zampini           eigs_start = B_neigs -nmax;
80608122e43SStefano Zampini           B_neigs = nmax;
80708122e43SStefano Zampini         }
80808122e43SStefano Zampini 
8099552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
8109552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
81108122e43SStefano Zampini           PetscBLASInt B_neigs2;
81208122e43SStefano Zampini 
813f6f667cfSStefano Zampini           B_IU = B_N - B_neigs;
814f6f667cfSStefano Zampini           B_IL = B_N - nmin_s + 1;
815fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
816fd14bc51SStefano 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);
817fd14bc51SStefano Zampini           }
8189ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
81908122e43SStefano Zampini             PetscInt j;
82008122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
82108122e43SStefano Zampini               ierr = PetscMemcpy(S+j*(subset_size+1),Sarray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
82208122e43SStefano Zampini             }
82308122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
82408122e43SStefano Zampini               ierr = PetscMemcpy(St+j*(subset_size+1),Starray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
82508122e43SStefano Zampini             }
82608122e43SStefano Zampini           } else {
82708122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
82808122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
82908122e43SStefano Zampini           }
83008122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
83108122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
832f6f667cfSStefano 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));
83308122e43SStefano Zampini #else
834f6f667cfSStefano 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));
83508122e43SStefano Zampini #endif
83608122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
83708122e43SStefano Zampini           B_neigs += B_neigs2;
83808122e43SStefano Zampini         }
83908122e43SStefano Zampini         if (B_ierr) {
84008122e43SStefano Zampini           if (B_ierr < 0 ) {
84108122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
84208122e43SStefano Zampini           } else if (B_ierr <= B_N) {
84308122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
84408122e43SStefano Zampini           } else {
8459552c7c7SStefano 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);
84608122e43SStefano Zampini           }
84708122e43SStefano Zampini         }
848fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
849ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
85008122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
85108122e43SStefano Zampini             if (eigs[j] == 0.0) {
852ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
85308122e43SStefano Zampini             } else {
854ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
855fd14bc51SStefano Zampini             }
85608122e43SStefano Zampini           }
85708122e43SStefano Zampini         }
85808122e43SStefano Zampini       } else {
85908122e43SStefano Zampini           /* TODO */
86008122e43SStefano Zampini       }
861aff50787SStefano Zampini     }
8628bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
8638bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
8649162d606SStefano Zampini     if (B_neigs) {
8659162d606SStefano 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);
866fd14bc51SStefano Zampini 
867fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
8689552c7c7SStefano Zampini         PetscInt ii;
8699552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
870ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
8719552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
872ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
873ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
874ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
875ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
876ac47001eSStefano Zampini #else
877ac47001eSStefano 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);
878ac47001eSStefano Zampini #endif
8799552c7c7SStefano Zampini           }
8809552c7c7SStefano Zampini         }
881fd14bc51SStefano Zampini       }
88208122e43SStefano Zampini #if 0
8839162d606SStefano Zampini       for (j=0;j<B_neigs;j++) {
88408122e43SStefano Zampini         PetscBLASInt Blas_N,Blas_one = 1.0;
88508122e43SStefano Zampini         PetscScalar norm;
88608122e43SStefano Zampini         ierr = PetscBLASIntCast(subset_size,&Blas_N);CHKERRQ(ierr);
8879162d606SStefano Zampini         PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,
8889162d606SStefano Zampini                                                    &Blas_one,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,&Blas_one));
88908122e43SStefano Zampini         if (pcbddc->adaptive_constraints_data[cum2] > 0.0) {
89008122e43SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
89108122e43SStefano Zampini         } else {
89208122e43SStefano Zampini           norm = -1.0/PetscSqrtReal(PetscRealPart(norm));
89308122e43SStefano Zampini         }
8949162d606SStefano Zampini         PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,&Blas_one));
895b1b3d7a2SStefano Zampini       }
896b1b3d7a2SStefano Zampini #endif
8979162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
8989162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
8999162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
9009162d606SStefano Zampini       cum++;
90108122e43SStefano Zampini     }
90208122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
90308122e43SStefano Zampini     /* shift for next computation */
90408122e43SStefano Zampini     cumarray += subset_size*subset_size;
90508122e43SStefano Zampini   }
906fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
907fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
908fd14bc51SStefano Zampini   }
90908122e43SStefano Zampini 
91008122e43SStefano Zampini   if (mss) {
91108122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
91208122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
913f6f667cfSStefano Zampini     /* destroy matrices (junk) */
914f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
915f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
91608122e43SStefano Zampini   }
917f6f667cfSStefano Zampini   if (allocated_S_St) {
918f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
919f6f667cfSStefano Zampini   }
920f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
92108122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
92208122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
92308122e43SStefano Zampini #endif
92408122e43SStefano Zampini   if (pcbddc->dbg_flag) {
9251b968477SStefano Zampini     PetscInt maxneigs_r;
92608122e43SStefano Zampini     ierr = MPI_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
9279b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
92808122e43SStefano Zampini   }
92908122e43SStefano Zampini   PetscFunctionReturn(0);
93008122e43SStefano Zampini }
931b1b3d7a2SStefano Zampini 
932674ae819SStefano Zampini #undef __FUNCT__
933c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
934c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
935c8587f34SStefano Zampini {
936c8587f34SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
9378629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
938c8587f34SStefano Zampini   PetscErrorCode ierr;
939c8587f34SStefano Zampini 
940c8587f34SStefano Zampini   PetscFunctionBegin;
941f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
9425e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
943c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
944c8587f34SStefano Zampini 
945684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
9460fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
947684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
948c8587f34SStefano Zampini 
949c8587f34SStefano Zampini   /* Change global null space passed in by the user if change of basis has been requested */
950b9b85e73SStefano Zampini   if (pcbddc->NullSpace && pcbddc->ChangeOfBasisMatrix) {
951c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAdaptGlobal(pc);CHKERRQ(ierr);
952c8587f34SStefano Zampini   }
953c8587f34SStefano Zampini 
9548629588bSStefano Zampini   /*
9558629588bSStefano Zampini      Setup local correction and local part of coarse basis.
9568629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
9578629588bSStefano Zampini   */
95847f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
9598629588bSStefano Zampini 
9608629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
9618629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
9628629588bSStefano Zampini 
9638629588bSStefano Zampini   /* free */
9648629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
965c8587f34SStefano Zampini   PetscFunctionReturn(0);
966c8587f34SStefano Zampini }
967c8587f34SStefano Zampini 
968c8587f34SStefano Zampini #undef __FUNCT__
969674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
970674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
971674ae819SStefano Zampini {
972674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
973674ae819SStefano Zampini   PetscErrorCode ierr;
974674ae819SStefano Zampini 
975674ae819SStefano Zampini   PetscFunctionBegin;
976674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
977674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
978*30368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
979674ae819SStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
980674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
981785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
982674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
983f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
984f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
985785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
98663602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
98763602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
988674ae819SStefano Zampini   PetscFunctionReturn(0);
989674ae819SStefano Zampini }
990674ae819SStefano Zampini 
991674ae819SStefano Zampini #undef __FUNCT__
992674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
993674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
994674ae819SStefano Zampini {
995674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
9964f1b2e48SStefano Zampini   PetscInt       i;
997674ae819SStefano Zampini   PetscErrorCode ierr;
998674ae819SStefano Zampini 
999674ae819SStefano Zampini   PetscFunctionBegin;
1000b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
1001674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
1002674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
1003674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
10044f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
10054f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
10064f1b2e48SStefano Zampini   }
10074f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
1008b96c3477SStefano Zampini   ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
1009674ae819SStefano Zampini   PetscFunctionReturn(0);
1010674ae819SStefano Zampini }
1011674ae819SStefano Zampini 
1012674ae819SStefano Zampini #undef __FUNCT__
1013674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
1014674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
1015674ae819SStefano Zampini {
1016674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
101706656605SStefano Zampini   PetscScalar    *array;
1018674ae819SStefano Zampini   PetscErrorCode ierr;
1019674ae819SStefano Zampini 
1020674ae819SStefano Zampini   PetscFunctionBegin;
1021674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
102258da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
102306656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
102406656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
102558da7f69SStefano Zampini   }
1026674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1027674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
102815aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
102915aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
1030674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
1031674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
1032674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
103306656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
1034674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
1035674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
10368ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
1037674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
1038674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
1039674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
1040f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
1041f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
1042f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
1043f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
1044727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
10450e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
1046f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
104770cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
10486e683305SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
104981d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
10500369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
10518b9f24d4SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
10524f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
10534f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
10548b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
10554f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
1056674ae819SStefano Zampini   PetscFunctionReturn(0);
1057674ae819SStefano Zampini }
1058674ae819SStefano Zampini 
1059674ae819SStefano Zampini #undef __FUNCT__
1060f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
1061f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
10626bfb1811SStefano Zampini {
10636bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
10646bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
10656bfb1811SStefano Zampini   VecType        impVecType;
10664f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
10676bfb1811SStefano Zampini   PetscErrorCode ierr;
10686bfb1811SStefano Zampini 
10696bfb1811SStefano Zampini   PetscFunctionBegin;
1070f4ddd8eeSStefano Zampini   if (!pcbddc->ConstraintMatrix) {
1071019a44ceSStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
1072f4ddd8eeSStefano Zampini   }
1073e7b262bdSStefano Zampini   /* get sizes */
10744f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
1075b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
10766bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
1077e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
1078e7b262bdSStefano Zampini   /* R nodes */
1079e7b262bdSStefano Zampini   old_size = -1;
1080e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
1081e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
1082e7b262bdSStefano Zampini   }
1083e7b262bdSStefano Zampini   if (n_R != old_size) {
1084e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
1085e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
10866bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
10876bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
10886bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
10896bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
1090e7b262bdSStefano Zampini   }
1091e7b262bdSStefano Zampini   /* local primal dofs */
1092e7b262bdSStefano Zampini   old_size = -1;
1093e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
1094e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
1095e7b262bdSStefano Zampini   }
1096e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
1097e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
109883b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
1099e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
11006bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
1101e7b262bdSStefano Zampini   }
1102e7b262bdSStefano Zampini   /* local explicit constraints */
1103e7b262bdSStefano Zampini   old_size = -1;
1104e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
1105e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
1106e7b262bdSStefano Zampini   }
1107e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
1108e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
110983b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
111083b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
111183b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
111283b7ccabSStefano Zampini   }
11136bfb1811SStefano Zampini   PetscFunctionReturn(0);
11146bfb1811SStefano Zampini }
11156bfb1811SStefano Zampini 
11166bfb1811SStefano Zampini #undef __FUNCT__
111747f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
111847f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
111988ebb749SStefano Zampini {
112025084f0cSStefano Zampini   PetscErrorCode  ierr;
112125084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
112288ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
112388ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1124d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
112525084f0cSStefano Zampini   /* submatrices of local problem */
112680677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
1127019a44ceSStefano Zampini   /* submatrices of benign trick */
1128d16cbb6bSStefano Zampini   Mat             B0_V = NULL;
112906656605SStefano Zampini   /* submatrices of local coarse problem */
113006656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
113125084f0cSStefano Zampini   /* working matrices */
113206656605SStefano Zampini   Mat             C_CR;
113325084f0cSStefano Zampini   /* additional working stuff */
113406656605SStefano Zampini   PC              pc_R;
11354f1b2e48SStefano Zampini   Mat             F;
113606656605SStefano Zampini   PetscBool       isLU,isCHOL,isILU;
113706656605SStefano Zampini 
113825084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
113906656605SStefano Zampini   PetscScalar     *work;
114006656605SStefano Zampini   PetscInt        *idx_V_B;
11414f1b2e48SStefano Zampini   PetscInt        n,n_vertices,n_constraints,*p0_lidx_I;
114206656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
1143b9d89cd5SStefano Zampini   PetscBool       unsymmetric_check;
114445a1bb75SStefano Zampini   /* matrix type (vector type propagated downstream from vec1_C and local matrix type) */
114588ebb749SStefano Zampini   MatType         impMatType;
114625084f0cSStefano Zampini   /* some shortcuts to scalars */
114706656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
114888ebb749SStefano Zampini 
114988ebb749SStefano Zampini   PetscFunctionBegin;
1150b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
11514f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
115288ebb749SStefano Zampini   /* Set Non-overlapping dimensions */
1153b371cd4fSStefano Zampini   n_B = pcis->n_B;
1154b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
115588ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
115688ebb749SStefano Zampini 
115788ebb749SStefano Zampini   /* Set types for local objects needed by BDDC precondtioner */
115888ebb749SStefano Zampini   impMatType = MATSEQDENSE;
115988ebb749SStefano Zampini 
116088ebb749SStefano Zampini   /* vertices in boundary numbering */
1161785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
11620e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
116388ebb749SStefano Zampini   if (i != n_vertices) {
116422d5777bSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %d != %d\n",n_vertices,i);
116588ebb749SStefano Zampini   }
116688ebb749SStefano Zampini 
116706656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
1168019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
116906656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
117006656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
117106656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
117206656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
117306656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
117406656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
117506656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
117606656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
117706656605SStefano Zampini 
117806656605SStefano Zampini   unsymmetric_check = PETSC_FALSE;
117906656605SStefano Zampini   /* allocate workspace */
118006656605SStefano Zampini   n = 0;
118106656605SStefano Zampini   if (n_constraints) {
118206656605SStefano Zampini     n += n_R*n_constraints;
118306656605SStefano Zampini   }
118406656605SStefano Zampini   if (n_vertices) {
118506656605SStefano Zampini     n = PetscMax(2*n_R*n_vertices,n);
118680677318SStefano Zampini     n = PetscMax((n_R+n_B)*n_vertices,n);
118706656605SStefano Zampini   }
11883301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
118906656605SStefano Zampini     n = PetscMax(2*n_R*pcbddc->local_primal_size,n);
119006656605SStefano Zampini     unsymmetric_check = PETSC_TRUE;
119106656605SStefano Zampini   }
119206656605SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
119306656605SStefano Zampini 
119406656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
119506656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
119606656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
119706656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
119806656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
119906656605SStefano Zampini   if (isLU || isILU || isCHOL) {
120006656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
1201d62866d3SStefano Zampini   } else if (sub_schurs->reuse_mumps) {
1202d62866d3SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
1203d62866d3SStefano Zampini     MatFactorType type;
1204d62866d3SStefano Zampini 
12056816873aSStefano Zampini     F = reuse_mumps->F;
12066816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
1207d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
120806656605SStefano Zampini   } else {
120906656605SStefano Zampini     F = NULL;
121006656605SStefano Zampini   }
121106656605SStefano Zampini 
121288ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
121388ebb749SStefano Zampini   if (n_constraints) {
121406656605SStefano Zampini     Mat         M1,M2,M3;
121580677318SStefano Zampini     Mat         auxmat;
121606656605SStefano Zampini     IS          is_aux;
121780677318SStefano Zampini     PetscScalar *array,*array2;
121806656605SStefano Zampini 
1219f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
122080677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
122188ebb749SStefano Zampini 
122225084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
122325084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
12248ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
122580677318SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&auxmat);CHKERRQ(ierr);
122688ebb749SStefano Zampini 
122780677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
122880677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
122906656605SStefano Zampini     ierr = PetscMemzero(work,n_R*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
123088ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
123106656605SStefano Zampini       const PetscScalar *row_cmat_values;
123206656605SStefano Zampini       const PetscInt    *row_cmat_indices;
123306656605SStefano Zampini       PetscInt          size_of_constraint,j;
123488ebb749SStefano Zampini 
123506656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
123606656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
123706656605SStefano Zampini         work[row_cmat_indices[j]+i*n_R] = -row_cmat_values[j];
123806656605SStefano Zampini       }
123906656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
124006656605SStefano Zampini     }
124180677318SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
124206656605SStefano Zampini     if (F) {
124306656605SStefano Zampini       Mat B;
124406656605SStefano Zampini 
124506656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
124680677318SStefano Zampini       ierr = MatMatSolve(F,B,local_auxmat2_R);CHKERRQ(ierr);
124706656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
124806656605SStefano Zampini     } else {
124980677318SStefano Zampini       PetscScalar *marr;
125080677318SStefano Zampini 
125180677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
125206656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
125306656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
125480677318SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*n_R);CHKERRQ(ierr);
125506656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
125606656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
125706656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
125806656605SStefano Zampini       }
125980677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
126006656605SStefano Zampini     }
126180677318SStefano Zampini     if (!pcbddc->switch_static) {
126280677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
126380677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
126480677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
126580677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
126680677318SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*n_R);CHKERRQ(ierr);
126780677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
126880677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
126980677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
127080677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
127180677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
127280677318SStefano Zampini       }
127380677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
127480677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
127580677318SStefano Zampini       ierr = MatMatMult(auxmat,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
127680677318SStefano Zampini     } else {
127780677318SStefano Zampini       ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
127880677318SStefano Zampini       pcbddc->local_auxmat2 = local_auxmat2_R;
127925084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
128080677318SStefano Zampini     }
128180677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
128280677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
128380677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
128406656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
128506656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
128680677318SStefano Zampini     if (isCHOL) {
128780677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
128880677318SStefano Zampini     } else {
128925084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
129080677318SStefano Zampini     }
129180677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,one);CHKERRQ(ierr);
129206656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
129325084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
129425084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
129525084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
129680677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
129780677318SStefano Zampini     ierr = MatMatMult(M1,auxmat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
129880677318SStefano Zampini     ierr = MatDestroy(&auxmat);CHKERRQ(ierr);
129906656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
130006656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
1301f4ddd8eeSStefano Zampini   }
130288ebb749SStefano Zampini   /* Get submatrices from subdomain matrix */
13034f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
1304d16cbb6bSStefano Zampini     IS        dummy;
1305d16cbb6bSStefano Zampini     Mat       B0_R;
1306d16cbb6bSStefano Zampini     PetscReal norm;
1307d16cbb6bSStefano Zampini 
13084f1b2e48SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
13094f1b2e48SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&B0_R);CHKERRQ(ierr);
1310d16cbb6bSStefano Zampini     ierr = MatNorm(B0_R,NORM_INFINITY,&norm);CHKERRQ(ierr);
1311d16cbb6bSStefano Zampini     if (norm > PETSC_SMALL) {
1312d16cbb6bSStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! ||B0_R|| = %f (should be numerically 0.)",norm);
1313d16cbb6bSStefano Zampini     }
1314d16cbb6bSStefano Zampini     ierr = MatDestroy(&B0_R);CHKERRQ(ierr);
1315d16cbb6bSStefano Zampini     ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1316d16cbb6bSStefano Zampini   }
1317d16cbb6bSStefano Zampini 
131888ebb749SStefano Zampini   if (n_vertices) {
131906656605SStefano Zampini     IS is_aux;
13203a50541eSStefano Zampini 
13216816873aSStefano Zampini     if (sub_schurs->reuse_mumps) { /* is_R_local is not sorted, ISComplement doesn't like it */
13226816873aSStefano Zampini       IS tis;
13236816873aSStefano Zampini 
13246816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
13256816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
13266816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
13276816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
13286816873aSStefano Zampini     } else {
13293a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
13306816873aSStefano Zampini     }
13319577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
13329577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
133304708bb6SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
13344f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
1335019a44ceSStefano Zampini       IS dummy;
1336019a44ceSStefano Zampini 
13374f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
13384f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,is_aux,MAT_INITIAL_MATRIX,&B0_V);CHKERRQ(ierr);
1339019a44ceSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1340019a44ceSStefano Zampini     }
134125084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
134288ebb749SStefano Zampini   }
134388ebb749SStefano Zampini 
134488ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
1345f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
134606656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
134706656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
134806656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
134906656605SStefano Zampini     }
1350f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
135106656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
135206656605SStefano Zampini       PetscScalar *marray;
135306656605SStefano Zampini 
135406656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
135506656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
1356f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1357f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
1358f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
1359f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
1360f4ddd8eeSStefano Zampini     }
1361f4ddd8eeSStefano Zampini   }
136206656605SStefano Zampini 
1363f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
136406656605SStefano Zampini     PetscScalar *marray;
136588ebb749SStefano Zampini 
136606656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
13678eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
136806656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
136988ebb749SStefano Zampini     }
13703301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
137106656605SStefano Zampini       n *= 2;
137288ebb749SStefano Zampini     }
137306656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
137406656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
137506656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
13768eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
137706656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
137806656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
137988ebb749SStefano Zampini     }
13803301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
138106656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
13828eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
138306656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
138406656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
138588ebb749SStefano Zampini       }
138688ebb749SStefano Zampini     } else {
1387c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
1388c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
13891b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
1390c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
1391c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
1392c0553b1fSStefano Zampini       }
139388ebb749SStefano Zampini     }
139406656605SStefano Zampini   }
1395019a44ceSStefano Zampini 
139606656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
13974f1b2e48SStefano Zampini   p0_lidx_I = NULL;
13984f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
1399d12edf2fSStefano Zampini     const PetscInt *idxs;
1400d12edf2fSStefano Zampini 
1401d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
14024f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
14034f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
14044f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
14054f1b2e48SStefano Zampini     }
1406d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
1407d12edf2fSStefano Zampini   }
1408d16cbb6bSStefano Zampini 
140906656605SStefano Zampini   /* vertices */
141006656605SStefano Zampini   if (n_vertices) {
141116f15bc4SStefano Zampini 
141204708bb6SStefano Zampini     ierr = MatConvert(A_VV,impMatType,MAT_REUSE_MATRIX,&A_VV);CHKERRQ(ierr);
141304708bb6SStefano Zampini 
141416f15bc4SStefano Zampini     if (n_R) {
141506656605SStefano Zampini       Mat          A_RRmA_RV,S_VVt; /* S_VVt with LDA=N */
141606656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
141716f15bc4SStefano Zampini       PetscScalar  *x,*y;
141804708bb6SStefano Zampini       PetscBool    isseqaij;
141906656605SStefano Zampini 
142021eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
142106656605SStefano Zampini       ierr = MatConvert(A_RV,impMatType,MAT_REUSE_MATRIX,&A_RV);CHKERRQ(ierr);
142204708bb6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
14236816873aSStefano Zampini       if (F) { /* TODO could be optimized for symmetric problems */
142406656605SStefano Zampini         ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
142506656605SStefano Zampini       } else {
142606656605SStefano Zampini         ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
142706656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
142806656605SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*n_R);CHKERRQ(ierr);
142906656605SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
143006656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
143106656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
143206656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
143306656605SStefano Zampini         }
143406656605SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
143506656605SStefano Zampini       }
143680677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
143706656605SStefano Zampini       /* S_VV and S_CV are the subdomain contribution to coarse matrix. WARNING -> column major ordering */
143806656605SStefano Zampini       if (n_constraints) {
143906656605SStefano Zampini         Mat B;
144080677318SStefano Zampini 
1441b3d85658SStefano Zampini         ierr = PetscMemzero(work+n_R*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
144280677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
144380677318SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
144480677318SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+n_R*n_vertices+i*n_B);CHKERRQ(ierr);
144580677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
144680677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
144780677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
144880677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
144980677318SStefano Zampini         }
145080677318SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+n_R*n_vertices,&B);CHKERRQ(ierr);
145180677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
145280677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
145306656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work+n_R*n_vertices,&B);CHKERRQ(ierr);
145480677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
145506656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
145606656605SStefano Zampini         ierr = PetscBLASIntCast(n_R*n_vertices,&B_N);CHKERRQ(ierr);
145706656605SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+n_R*n_vertices,&B_one,work,&B_one));
145806656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
145906656605SStefano Zampini       }
146004708bb6SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
146104708bb6SStefano Zampini       if (!isseqaij) { /* MatMatMult with SEQ(S)BAIJ below will raise an error */
146204708bb6SStefano Zampini         ierr = MatConvert(A_VR,MATSEQAIJ,MAT_REUSE_MATRIX,&A_VR);CHKERRQ(ierr);
146304708bb6SStefano Zampini       }
146406656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
146580677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
146606656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
146706656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
146806656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
146906656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
147006656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
147106656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
147206656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
1473d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
1474019a44ceSStefano Zampini     } else {
1475d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
1476d16cbb6bSStefano Zampini     }
14774f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
1478019a44ceSStefano Zampini       const PetscScalar *vals;
1479019a44ceSStefano Zampini       const PetscInt    *idxs;
14804f1b2e48SStefano Zampini       PetscInt          n,j,primal_idx;
1481019a44ceSStefano Zampini 
14824f1b2e48SStefano Zampini       ierr = MatGetRow(B0_V,i,&n,&idxs,&vals);CHKERRQ(ierr);
14834f1b2e48SStefano Zampini       primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + i;
1484d16cbb6bSStefano Zampini       for (j=0;j<n;j++) {
14854f1b2e48SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+idxs[j]] = vals[j];
14864f1b2e48SStefano Zampini         coarse_submat_vals[idxs[j]*pcbddc->local_primal_size+primal_idx] = vals[j];
1487019a44ceSStefano Zampini       }
14884f1b2e48SStefano Zampini       ierr = MatRestoreRow(B0_V,i,&n,&idxs,&vals);CHKERRQ(ierr);
148916f15bc4SStefano Zampini     }
149021eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
1491d16cbb6bSStefano Zampini 
149206656605SStefano Zampini     /* coarse basis functions */
149306656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
149416f15bc4SStefano Zampini       PetscScalar *y;
149516f15bc4SStefano Zampini 
149606656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*i);CHKERRQ(ierr);
149706656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
149806656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
149906656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
150006656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
150106656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
150206656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
150306656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
150406656605SStefano Zampini 
150506656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
15064f1b2e48SStefano Zampini         PetscInt j;
15074f1b2e48SStefano Zampini 
150806656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
150906656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
151006656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
151106656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
151206656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
15134f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
151406656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
151506656605SStefano Zampini       }
151606656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
151706656605SStefano Zampini     }
151804708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
151904708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
152006656605SStefano Zampini   }
152106656605SStefano Zampini 
152206656605SStefano Zampini   if (n_constraints) {
152306656605SStefano Zampini     Mat B;
152406656605SStefano Zampini 
152506656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
152606656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
152780677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
152806656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
152906656605SStefano Zampini     if (n_vertices) {
153080677318SStefano Zampini       if (isCHOL) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
153180677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
153280677318SStefano Zampini       } else {
153380677318SStefano Zampini         Mat S_VCt;
153480677318SStefano Zampini 
153580677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
153680677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
153780677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
153880677318SStefano Zampini       }
153906656605SStefano Zampini     }
154006656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
154106656605SStefano Zampini     /* coarse basis functions */
154206656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
154306656605SStefano Zampini       PetscScalar *y;
154406656605SStefano Zampini 
154506656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*i);CHKERRQ(ierr);
154606656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
154706656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
154806656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
154906656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
155006656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
155106656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
155206656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
15534f1b2e48SStefano Zampini         PetscInt j;
15544f1b2e48SStefano Zampini 
155506656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
155606656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
155706656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
155806656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
155906656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
15604f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
156106656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
156206656605SStefano Zampini       }
156306656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
156406656605SStefano Zampini     }
156506656605SStefano Zampini   }
156680677318SStefano Zampini   if (n_constraints) {
156780677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
156880677318SStefano Zampini   }
15694f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
1570019a44ceSStefano Zampini   ierr = MatDestroy(&B0_V);CHKERRQ(ierr);
1571019a44ceSStefano Zampini 
157206656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
15733301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
157406656605SStefano Zampini 
157506656605SStefano Zampini     if (n_constraints) {
157616f15bc4SStefano Zampini       Mat S_CCT,B_C;
157706656605SStefano Zampini 
157880677318SStefano Zampini       /* this is a lazy thing */
157980677318SStefano Zampini       ierr = MatConvert(C_CR,impMatType,MAT_REUSE_MATRIX,&C_CR);CHKERRQ(ierr);
158006656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work+n_vertices*n_R,&B_C);CHKERRQ(ierr);
158106656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
158206656605SStefano Zampini       ierr = MatTransposeMatMult(C_CR,S_CCT,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
158316f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
158406656605SStefano Zampini       if (n_vertices) {
158516f15bc4SStefano Zampini         Mat B_V,S_VCT;
158606656605SStefano Zampini 
158706656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&B_V);CHKERRQ(ierr);
158806656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
158906656605SStefano Zampini         ierr = MatTransposeMatMult(C_CR,S_VCT,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
159006656605SStefano Zampini         ierr = MatDestroy(&B_V);CHKERRQ(ierr);
159116f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
159206656605SStefano Zampini       }
159306656605SStefano Zampini       ierr = MatDestroy(&B_C);CHKERRQ(ierr);
159480677318SStefano Zampini     } else { /* if there are no constraints, reset work */
159580677318SStefano Zampini       ierr = PetscMemzero(work,n_R*pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
159606656605SStefano Zampini     }
159716f15bc4SStefano Zampini     if (n_vertices && n_R) {
159806656605SStefano Zampini       Mat          A_VRT;
159980677318SStefano Zampini       PetscScalar  *marray;
160006656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
160106656605SStefano Zampini 
160280677318SStefano Zampini       ierr = MatTranspose(A_VR,MAT_INITIAL_MATRIX,&A_VRT);CHKERRQ(ierr);
160380677318SStefano Zampini       ierr = MatConvert(A_VRT,impMatType,MAT_REUSE_MATRIX,&A_VRT);CHKERRQ(ierr);
160480677318SStefano Zampini       ierr = MatDenseGetArray(A_VRT,&marray);CHKERRQ(ierr);
160506656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_R,&B_N);CHKERRQ(ierr);
160680677318SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&m_one,marray,&B_one,work,&B_one));
160780677318SStefano Zampini       ierr = MatDenseRestoreArray(A_VRT,&marray);CHKERRQ(ierr);
160816f15bc4SStefano Zampini       ierr = MatDestroy(&A_VRT);CHKERRQ(ierr);
160906656605SStefano Zampini     }
161006656605SStefano Zampini 
161106656605SStefano Zampini     if (F) { /* currently there's no support for MatTransposeMatSolve(F,B,X) */
161206656605SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
161306656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
161406656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+(i+pcbddc->local_primal_size)*n_R);CHKERRQ(ierr);
161506656605SStefano Zampini         ierr = MatSolveTranspose(F,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
161606656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
161706656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
161806656605SStefano Zampini       }
161906656605SStefano Zampini     } else {
162006656605SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
162106656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
162206656605SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+(i+pcbddc->local_primal_size)*n_R);CHKERRQ(ierr);
162306656605SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
162406656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
162506656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
162606656605SStefano Zampini       }
162706656605SStefano Zampini     }
162806656605SStefano Zampini     /* coarse basis functions */
162906656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
163006656605SStefano Zampini       PetscScalar *y;
163106656605SStefano Zampini 
163206656605SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+n_R*(i+pcbddc->local_primal_size));CHKERRQ(ierr);
163306656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
163406656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
163506656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
163606656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
163706656605SStefano Zampini       if (i<n_vertices) {
163806656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
163906656605SStefano Zampini       }
164006656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
164106656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
164206656605SStefano Zampini 
164306656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
164406656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
164506656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
164606656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
164706656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
164806656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
164906656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
165006656605SStefano Zampini       }
165106656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
165206656605SStefano Zampini     }
165306656605SStefano Zampini   }
1654d62866d3SStefano Zampini   /* free memory */
165588ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
165606656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
165706656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
165806656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
165906656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
1660d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
1661d62866d3SStefano Zampini   if (n_vertices) {
1662d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
1663d62866d3SStefano Zampini   }
1664d62866d3SStefano Zampini   if (n_constraints) {
1665d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
1666d62866d3SStefano Zampini   }
166788ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
166888ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
166988ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
1670d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
167188ebb749SStefano Zampini     Mat         coarse_sub_mat;
167225084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
167388ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
167488ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
167588ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
16768bec7fa6SStefano Zampini     Mat         C_B,CPHI;
16778bec7fa6SStefano Zampini     IS          is_dummy;
16788bec7fa6SStefano Zampini     Vec         mones;
167988ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
168088ebb749SStefano Zampini     PetscReal   real_value;
168188ebb749SStefano Zampini 
168288ebb749SStefano Zampini     ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
168388ebb749SStefano Zampini     ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
168488ebb749SStefano Zampini     ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
168588ebb749SStefano Zampini     ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
168688ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
168788ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
1688c0553b1fSStefano Zampini     if (unsymmetric_check) {
168988ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
169088ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
169188ebb749SStefano Zampini     }
169288ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
169388ebb749SStefano Zampini 
169425084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
16953301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
169625084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1697c0553b1fSStefano Zampini     if (unsymmetric_check) {
169888ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
169988ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
170088ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
170188ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
170288ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
170388ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
170488ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
170588ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
170688ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
170788ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
170888ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
170988ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
171088ebb749SStefano Zampini     } else {
171188ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
171288ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
171388ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
171488ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
171588ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
171688ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
171788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
171888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
171988ebb749SStefano Zampini     }
172088ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
172188ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
172288ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
172388ebb749SStefano Zampini     ierr = MatConvert(TM1,MATSEQDENSE,MAT_REUSE_MATRIX,&TM1);CHKERRQ(ierr);
17244f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
1725d12edf2fSStefano Zampini       Mat         B0_I,B0_B,B0_BPHI,B0_IPHI;
1726d12edf2fSStefano Zampini       PetscScalar *data,*data2;
17274f1b2e48SStefano Zampini       PetscInt    j;
1728d12edf2fSStefano Zampini 
17294f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
17304f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);
17314f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_I_local,MAT_INITIAL_MATRIX,&B0_I);
1732d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
1733d12edf2fSStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_REUSE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
1734d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
1735d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
17364f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
17374f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
1738d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
17394f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
17404f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
17414f1b2e48SStefano Zampini         }
1742d12edf2fSStefano Zampini       }
1743d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
1744d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
1745d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
1746d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
1747d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
1748d12edf2fSStefano Zampini       ierr = MatMatMult(B0_I,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&B0_IPHI);CHKERRQ(ierr);
1749d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_I);CHKERRQ(ierr);
1750d12edf2fSStefano Zampini       ierr = MatNorm(B0_IPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
1751d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_IPHI);CHKERRQ(ierr);
1752d12edf2fSStefano Zampini     }
1753d12edf2fSStefano Zampini #if 0
1754d12edf2fSStefano Zampini   {
1755d12edf2fSStefano Zampini     PetscViewer viewer;
1756d12edf2fSStefano Zampini     char filename[256];
1757d12edf2fSStefano Zampini     sprintf(filename,"proj_local_coarse_mat%d.m",PetscGlobalRank);
1758d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
1759d12edf2fSStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1760d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
1761d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1762d12edf2fSStefano Zampini   }
1763d12edf2fSStefano Zampini #endif
176481d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
17658bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
17660fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
176706656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
17688bec7fa6SStefano Zampini 
17698bec7fa6SStefano Zampini     /* check constraints */
17704f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
17718bec7fa6SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&is_dummy);CHKERRQ(ierr);
17728bec7fa6SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);
17738bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
17748bec7fa6SStefano Zampini       ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
17758bec7fa6SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
17768bec7fa6SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
17778bec7fa6SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
1778bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
1779c0553b1fSStefano Zampini       if (unsymmetric_check) {
1780bdae7319SStefano Zampini         ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
1781bdae7319SStefano Zampini         ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
1782bdae7319SStefano Zampini         ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
1783bdae7319SStefano Zampini         ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
1784bdae7319SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
178588ebb749SStefano Zampini       }
17868bec7fa6SStefano Zampini       ierr = MatDestroy(&C_B);CHKERRQ(ierr);
17878bec7fa6SStefano Zampini       ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
17888bec7fa6SStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
17898bec7fa6SStefano Zampini       ierr = VecDestroy(&mones);CHKERRQ(ierr);
1790d12edf2fSStefano Zampini     }
179125084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
179288ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
179388ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
179488ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
179588ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
179688ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
179788ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
179888ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
179988ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
180088ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
180188ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
1802c0553b1fSStefano Zampini     if (unsymmetric_check) {
180388ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
180488ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
180588ebb749SStefano Zampini     }
180688ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
180788ebb749SStefano Zampini   }
18088629588bSStefano Zampini   /* get back data */
18098629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
181088ebb749SStefano Zampini   PetscFunctionReturn(0);
181188ebb749SStefano Zampini }
181288ebb749SStefano Zampini 
181388ebb749SStefano Zampini #undef __FUNCT__
1814d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
1815d648f858SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
1816aa0d41d4SStefano Zampini {
1817d65f70fdSStefano Zampini   Mat            *work_mat;
1818d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
1819d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
1820d65f70fdSStefano Zampini   PetscInt       rsize,*idxs_perm_r,csize,*idxs_perm_c;
1821aa0d41d4SStefano Zampini   PetscErrorCode ierr;
1822aa0d41d4SStefano Zampini 
1823aa0d41d4SStefano Zampini   PetscFunctionBegin;
1824d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
1825d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
1826d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
1827d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
1828aa0d41d4SStefano Zampini 
1829d65f70fdSStefano Zampini   if (!rsorted) {
1830906d46d4SStefano Zampini     const PetscInt *idxs;
1831906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
1832aa0d41d4SStefano Zampini 
1833d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
1834d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
1835d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
1836d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
1837aa0d41d4SStefano Zampini     }
1838d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
1839d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
1840d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
1841d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
1842aa0d41d4SStefano Zampini     }
1843d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
1844d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
1845d65f70fdSStefano Zampini   } else {
1846d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
1847d65f70fdSStefano Zampini     isrow_s = isrow;
1848aa0d41d4SStefano Zampini   }
1849906d46d4SStefano Zampini 
1850d65f70fdSStefano Zampini   if (!csorted) {
1851d65f70fdSStefano Zampini     if (isrow == iscol) {
1852d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
1853d65f70fdSStefano Zampini       iscol_s = isrow_s;
1854d65f70fdSStefano Zampini     } else {
1855d65f70fdSStefano Zampini       const PetscInt *idxs;
1856d65f70fdSStefano Zampini       PetscInt *idxs_sorted,i;
1857906d46d4SStefano Zampini 
1858d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
1859d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
1860d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
1861d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
1862d65f70fdSStefano Zampini       }
1863d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
1864d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
1865d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
1866d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
1867d65f70fdSStefano Zampini       }
1868d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
1869d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
1870d65f70fdSStefano Zampini     }
1871d65f70fdSStefano Zampini   } else {
1872d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
1873d65f70fdSStefano Zampini     iscol_s = iscol;
1874d65f70fdSStefano Zampini   }
1875d65f70fdSStefano Zampini 
1876d648f858SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
1877d65f70fdSStefano Zampini 
1878d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
1879906d46d4SStefano Zampini     Mat      new_mat;
1880d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
1881906d46d4SStefano Zampini 
1882d65f70fdSStefano Zampini     if (!rsorted) {
1883d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
1884d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
1885d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
1886d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
1887906d46d4SStefano Zampini       }
1888d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
1889d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
1890d65f70fdSStefano Zampini     } else {
1891d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
1892906d46d4SStefano Zampini     }
1893d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
1894d65f70fdSStefano Zampini 
1895d65f70fdSStefano Zampini     if (!csorted) {
1896d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
1897d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
1898d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
1899d65f70fdSStefano Zampini       } else {
1900d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
1901d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
1902d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
1903d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
1904d65f70fdSStefano Zampini         }
1905d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
1906d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
1907d65f70fdSStefano Zampini       }
1908d65f70fdSStefano Zampini     } else {
1909d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
1910d65f70fdSStefano Zampini     }
1911d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
1912d65f70fdSStefano Zampini 
1913d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
1914d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
1915d65f70fdSStefano Zampini     work_mat[0] = new_mat;
1916d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
1917d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
1918d65f70fdSStefano Zampini   }
1919d65f70fdSStefano Zampini 
1920d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
1921d65f70fdSStefano Zampini   *B = work_mat[0];
1922d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
1923d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
1924d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
1925d65f70fdSStefano Zampini   PetscFunctionReturn(0);
1926d65f70fdSStefano Zampini }
1927d65f70fdSStefano Zampini 
1928d65f70fdSStefano Zampini #undef __FUNCT__
19295e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
19305e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
1931aa0d41d4SStefano Zampini {
1932aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
19335e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
1934d65f70fdSStefano Zampini   Mat            new_mat;
19355e8657edSStefano Zampini   IS             is_local,is_global;
1936d65f70fdSStefano Zampini   PetscInt       local_size;
1937d65f70fdSStefano Zampini   PetscBool      isseqaij;
1938aa0d41d4SStefano Zampini   PetscErrorCode ierr;
1939aa0d41d4SStefano Zampini 
1940aa0d41d4SStefano Zampini   PetscFunctionBegin;
1941aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
19425e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
19435e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
1944b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
1945aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
1946d648f858SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
1947aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
1948906d46d4SStefano Zampini 
1949906d46d4SStefano Zampini   /* check */
1950906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
1951906d46d4SStefano Zampini     Vec       x,x_change;
1952906d46d4SStefano Zampini     PetscReal error;
1953906d46d4SStefano Zampini 
19545e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
1955906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
19565e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
1957e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1958e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1959d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
1960e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1961e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1962906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
1963906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
1964906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1965906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
1966906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
1967906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
1968906d46d4SStefano Zampini   }
1969906d46d4SStefano Zampini 
197022d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
19719b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
197222d5777bSStefano Zampini   if (isseqaij) {
19731cf9b237SStefano Zampini     Mat M;
19741cf9b237SStefano Zampini 
19751cf9b237SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
19761cf9b237SStefano Zampini     ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
19771cf9b237SStefano Zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
1978aa0d41d4SStefano Zampini   } else {
19791cf9b237SStefano Zampini     Mat work_mat,M;
19801cf9b237SStefano Zampini 
1981aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
19821cf9b237SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
19831cf9b237SStefano Zampini     ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
19841cf9b237SStefano Zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
1985aa0d41d4SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
1986aa0d41d4SStefano Zampini   }
19873301b35fSStefano Zampini   if (matis->A->symmetric_set) {
19883301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
1989e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
19903301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
1991e496cd5dSStefano Zampini #endif
19923301b35fSStefano Zampini   }
199345a1bb75SStefano Zampini   /*
199445a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1995d65f70fdSStefano Zampini   ierr = MatView(new_mat,(PetscViewer)0);CHKERRQ(ierr);
199645a1bb75SStefano Zampini   */
1997d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
1998aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
1999aa0d41d4SStefano Zampini }
2000aa0d41d4SStefano Zampini 
2001aa0d41d4SStefano Zampini #undef __FUNCT__
2002a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
20038ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
2004a64d13efSStefano Zampini {
2005a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
2006a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
2007d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
200853892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
20093a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
20103a50541eSStefano Zampini   PetscInt        vbs,bs;
20116816873aSStefano Zampini   PetscBT         bitmask=NULL;
2012a64d13efSStefano Zampini   PetscErrorCode  ierr;
2013a64d13efSStefano Zampini 
2014a64d13efSStefano Zampini   PetscFunctionBegin;
2015b23d619eSStefano Zampini   /*
2016b23d619eSStefano Zampini     No need to setup local scatters if
2017b23d619eSStefano Zampini       - primal space is unchanged
2018b23d619eSStefano Zampini         AND
2019b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
2020b23d619eSStefano Zampini         AND
2021b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
2022b23d619eSStefano Zampini   */
2023b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
2024f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
2025f4ddd8eeSStefano Zampini   }
2026f4ddd8eeSStefano Zampini   /* destroy old objects */
2027f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
2028f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
2029f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
2030a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
2031b371cd4fSStefano Zampini   n_B = pcis->n_B;
2032b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
2033b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
20343a50541eSStefano Zampini 
2035a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
20366816873aSStefano Zampini 
203753892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
20386816873aSStefano Zampini   if (!sub_schurs->reuse_mumps) {
2039854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
2040a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
2041a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
20420e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
2043a64d13efSStefano Zampini     }
2044a64d13efSStefano Zampini 
2045a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
20464641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
20476816873aSStefano Zampini         idx_R_local[n_R++] = i;
2048a64d13efSStefano Zampini       }
2049a64d13efSStefano Zampini     }
205053892102SStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing MUMPS Schur solver */
20516816873aSStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
20526816873aSStefano Zampini 
205353892102SStefano Zampini     ierr = ISGetIndices(reuse_mumps->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
205453892102SStefano Zampini     ierr = ISGetLocalSize(reuse_mumps->is_R,&n_R);CHKERRQ(ierr);
20556816873aSStefano Zampini   }
20563a50541eSStefano Zampini 
20573a50541eSStefano Zampini   /* Block code */
20583a50541eSStefano Zampini   vbs = 1;
20593a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
20603a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
20613a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
20623a50541eSStefano Zampini     PetscInt  *vary;
2063d3df7717SStefano Zampini     if (!sub_schurs->reuse_mumps) {
2064785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
20653a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
2066d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
2067d3df7717SStefano 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 */
20680e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
2069d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
20703a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
20713a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
20723a50541eSStefano Zampini           break;
20733a50541eSStefano Zampini         }
20743a50541eSStefano Zampini       }
2075d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
2076d3df7717SStefano Zampini     } else {
2077d3df7717SStefano Zampini       /* Verify directly the R set */
2078d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
2079d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
2080d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
2081d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
2082d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
2083d3df7717SStefano Zampini             break;
2084d3df7717SStefano Zampini           }
2085d3df7717SStefano Zampini         }
2086d3df7717SStefano Zampini       }
2087d3df7717SStefano Zampini     }
20883a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
20893a50541eSStefano Zampini       vbs = bs;
20903a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
20913a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
20923a50541eSStefano Zampini       }
20933a50541eSStefano Zampini     }
20943a50541eSStefano Zampini   }
20953a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
209653892102SStefano Zampini   if (sub_schurs->reuse_mumps) {
209753892102SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
209853892102SStefano Zampini 
209953892102SStefano Zampini     ierr = ISRestoreIndices(reuse_mumps->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
210053892102SStefano Zampini     ierr = ISDestroy(&reuse_mumps->is_R);CHKERRQ(ierr);
210153892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
210253892102SStefano Zampini     reuse_mumps->is_R = pcbddc->is_R_local;
210353892102SStefano Zampini   } else {
21043a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
210553892102SStefano Zampini   }
2106a64d13efSStefano Zampini 
2107a64d13efSStefano Zampini   /* print some info if requested */
2108a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
2109a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2110a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
21110fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
2112a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
2113a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
21144f1b2e48SStefano 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);
2115a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2116a64d13efSStefano Zampini   }
2117a64d13efSStefano Zampini 
2118a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
21196816873aSStefano Zampini   if (!sub_schurs->reuse_mumps) {
21206816873aSStefano Zampini     IS       is_aux1,is_aux2;
21216816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
21226816873aSStefano Zampini 
21233a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2124854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
2125854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
2126a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
21274641a718SStefano Zampini     for (i=0; i<n_D; i++) {
21284641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
21294641a718SStefano Zampini     }
2130a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2131a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
21324641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
21334641a718SStefano Zampini         aux_array1[j++] = i;
2134a64d13efSStefano Zampini       }
2135a64d13efSStefano Zampini     }
2136a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
2137a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2138a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
21394641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
21404641a718SStefano Zampini         aux_array2[j++] = i;
2141a64d13efSStefano Zampini       }
2142a64d13efSStefano Zampini     }
2143a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2144a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
2145a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
2146a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
2147a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
2148a64d13efSStefano Zampini 
21498eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
2150785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
2151a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
21524641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
21534641a718SStefano Zampini           aux_array1[j++] = i;
2154a64d13efSStefano Zampini         }
2155a64d13efSStefano Zampini       }
2156a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
2157a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
2158a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
2159a64d13efSStefano Zampini     }
21604641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
21613a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2162d62866d3SStefano Zampini   } else {
216353892102SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
21646816873aSStefano Zampini     IS               tis;
21656816873aSStefano Zampini     PetscInt         schur_size;
21666816873aSStefano Zampini 
216753892102SStefano Zampini     ierr = ISGetLocalSize(reuse_mumps->is_B,&schur_size);CHKERRQ(ierr);
21686816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
216953892102SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_mumps->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
21706816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
21716816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
21726816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
21736816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
21746816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
2175d62866d3SStefano Zampini     }
2176d62866d3SStefano Zampini   }
2177a64d13efSStefano Zampini   PetscFunctionReturn(0);
2178a64d13efSStefano Zampini }
2179a64d13efSStefano Zampini 
2180304d26faSStefano Zampini 
2181304d26faSStefano Zampini #undef __FUNCT__
2182304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
2183684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
2184304d26faSStefano Zampini {
2185304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2186304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
2187304d26faSStefano Zampini   PC             pc_temp;
2188304d26faSStefano Zampini   Mat            A_RR;
2189f4ddd8eeSStefano Zampini   MatReuse       reuse;
2190304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
2191304d26faSStefano Zampini   PetscReal      value;
219204708bb6SStefano Zampini   PetscInt       n_D,n_R;
21939577ea80SStefano Zampini   PetscBool      use_exact,use_exact_reduced,issbaij;
2194304d26faSStefano Zampini   PetscErrorCode ierr;
2195e604994aSStefano Zampini   /* prefixes stuff */
2196312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
2197e604994aSStefano Zampini   size_t         len;
2198304d26faSStefano Zampini 
2199304d26faSStefano Zampini   PetscFunctionBegin;
2200304d26faSStefano Zampini 
2201e604994aSStefano Zampini   /* compute prefixes */
2202e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
2203e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
2204e604994aSStefano Zampini   if (!pcbddc->current_level) {
2205e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
2206e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
2207e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
2208e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
2209e604994aSStefano Zampini   } else {
2210e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
2211312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
2212e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
2213e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
2214312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
2215312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
221634d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
221734d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
2218e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
2219e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
2220e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
2221e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
2222e604994aSStefano Zampini   }
2223e604994aSStefano Zampini 
2224304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
2225684f6988SStefano Zampini   if (dirichlet) {
2226d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
22273301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
22283301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
2229964fefecSStefano Zampini     }
2230ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
2231964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
2232304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
2233304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
2234304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
2235304d26faSStefano Zampini       /* default */
2236304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
2237e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
22389577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
2239304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
22409577ea80SStefano Zampini       if (issbaij) {
22419577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
22429577ea80SStefano Zampini       } else {
2243304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
22449577ea80SStefano Zampini       }
2245304d26faSStefano Zampini       /* Allow user's customization */
2246304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
2247304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
2248304d26faSStefano Zampini     }
2249d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
2250d62866d3SStefano Zampini     if (sub_schurs->reuse_mumps) {
2251d62866d3SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2252d62866d3SStefano Zampini 
2253d62866d3SStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_mumps->interior_solver);CHKERRQ(ierr);
2254d5574798SStefano Zampini     }
2255304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
2256304d26faSStefano Zampini     if (!n_D) {
2257304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
2258304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
2259304d26faSStefano Zampini     }
2260304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
2261304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
2262304d26faSStefano Zampini     /* set ksp_D into pcis data */
2263304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
2264304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
2265304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
2266684f6988SStefano Zampini   }
2267304d26faSStefano Zampini 
2268304d26faSStefano Zampini   /* NEUMANN PROBLEM */
2269684f6988SStefano Zampini   A_RR = 0;
2270684f6988SStefano Zampini   if (neumann) {
2271d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
227204708bb6SStefano Zampini     PetscInt        ibs,mbs;
227304708bb6SStefano Zampini     PetscBool       issbaij;
227404708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
2275f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
22768ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
2277f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
2278f4ddd8eeSStefano Zampini       PetscInt nn_R;
227981d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
2280f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
2281f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
2282f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
2283f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
2284f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2285f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
2286f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
2287727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
2288f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2289f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
2290f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
2291f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
2292f4ddd8eeSStefano Zampini         }
2293f4ddd8eeSStefano Zampini       }
2294f4ddd8eeSStefano Zampini       /* last check */
2295d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
2296f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2297f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
2298f4ddd8eeSStefano Zampini       }
2299f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
2300f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
2301f4ddd8eeSStefano Zampini     }
2302f4ddd8eeSStefano Zampini     /* extract A_RR */
2303af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
2304af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
230504708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
230604708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
230704708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
230804708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
230904708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
2310af732b37SStefano Zampini       } else {
231104708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
23126816873aSStefano Zampini       }
231304708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
231404708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
231504708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
231604708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
231704708bb6SStefano Zampini       } else {
231804708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
231904708bb6SStefano Zampini       }
232004708bb6SStefano Zampini     }
232104708bb6SStefano Zampini     if (!sub_schurs->reuse_mumps) {
2322f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
23233301b35fSStefano Zampini       if (pcbddc->local_mat->symmetric_set) {
23243301b35fSStefano Zampini         ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
23256816873aSStefano Zampini       }
23266816873aSStefano Zampini     } else {
23276816873aSStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
23286816873aSStefano Zampini 
23296816873aSStefano Zampini       ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
23306816873aSStefano Zampini       ierr = PCGetOperators(reuse_mumps->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
23316816873aSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
2332af732b37SStefano Zampini     }
2333f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
2334304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
2335304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
2336304d26faSStefano Zampini       /* default */
2337304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
2338e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
2339304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
23409577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
23419577ea80SStefano Zampini       if (issbaij) {
23429577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
23439577ea80SStefano Zampini       } else {
2344304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
23459577ea80SStefano Zampini       }
2346304d26faSStefano Zampini       /* Allow user's customization */
2347304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
2348304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
2349304d26faSStefano Zampini     }
2350d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
2351304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
2352304d26faSStefano Zampini     if (!n_R) {
2353304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
2354304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
2355304d26faSStefano Zampini     }
2356d62866d3SStefano Zampini     /* Reuse MUMPS solver if it is present */
2357d62866d3SStefano Zampini     if (sub_schurs->reuse_mumps) {
2358d62866d3SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2359d62866d3SStefano Zampini 
2360d62866d3SStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_mumps->correction_solver);CHKERRQ(ierr);
2361d62866d3SStefano Zampini     }
2362304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
2363304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
2364684f6988SStefano Zampini   }
23656816873aSStefano Zampini   /* free Neumann problem's matrix */
23666816873aSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2367304d26faSStefano Zampini 
2368304d26faSStefano Zampini   /* check Dirichlet and Neumann solvers and adapt them if a nullspace correction is needed */
23690fccc4e9SStefano Zampini   if (pcbddc->NullSpace || pcbddc->dbg_flag) {
2370684f6988SStefano Zampini     if (pcbddc->dbg_flag) {
2371684f6988SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2372684f6988SStefano Zampini       ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
2373684f6988SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2374684f6988SStefano Zampini     }
2375684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
23760fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
23770fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
23780fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
23790fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
23800fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
2381304d26faSStefano Zampini       /* need to be adapted? */
2382b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
2383b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2384b8ffe317SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,use_exact_reduced);CHKERRQ(ierr);
2385304d26faSStefano Zampini       /* print info */
2386304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
2387e604994aSStefano 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);
2388304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2389304d26faSStefano Zampini       }
2390b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced && !pcbddc->switch_static) {
2391298c0119SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcis->is_I_local);CHKERRQ(ierr);
2392304d26faSStefano Zampini       }
2393684f6988SStefano Zampini     }
2394684f6988SStefano Zampini     if (neumann) { /* Neumann */
23956816873aSStefano Zampini       ierr = KSPGetOperators(pcbddc->ksp_R,&A_RR,NULL);CHKERRQ(ierr);
23960fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
23970fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
23980fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
23990fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
24000fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
2401304d26faSStefano Zampini       /* need to be adapted? */
2402b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
2403b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2404304d26faSStefano Zampini       /* print info */
2405304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
2406e604994aSStefano 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);
2407304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2408304d26faSStefano Zampini       }
2409b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced) { /* is it the right logic? */
2410298c0119SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->is_R_local);CHKERRQ(ierr);
2411304d26faSStefano Zampini       }
24120fccc4e9SStefano Zampini     }
2413684f6988SStefano Zampini   }
2414304d26faSStefano Zampini   PetscFunctionReturn(0);
2415304d26faSStefano Zampini }
2416304d26faSStefano Zampini 
2417304d26faSStefano Zampini #undef __FUNCT__
2418ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
241980677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
2420674ae819SStefano Zampini {
2421674ae819SStefano Zampini   PetscErrorCode  ierr;
2422674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
2423be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
2424674ae819SStefano Zampini 
2425674ae819SStefano Zampini   PetscFunctionBegin;
2426be83ff47SStefano Zampini   if (!sub_schurs->reuse_mumps) {
242780677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
242820c7b377SStefano Zampini   }
242980677318SStefano Zampini   if (!pcbddc->switch_static) {
243080677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
243180677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
243280677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
243320c7b377SStefano Zampini     }
2434be83ff47SStefano Zampini     if (!sub_schurs->reuse_mumps) {
243580677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
243680677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
243720c7b377SStefano Zampini     } else {
2438be83ff47SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2439be83ff47SStefano Zampini 
244053892102SStefano Zampini       ierr = VecScatterBegin(reuse_mumps->correction_scatter_B,inout_B,reuse_mumps->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
244153892102SStefano Zampini       ierr = VecScatterEnd(reuse_mumps->correction_scatter_B,inout_B,reuse_mumps->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
244220c7b377SStefano Zampini     }
2443be83ff47SStefano Zampini   } else {
244480677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
244580677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
244680677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
244780677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
244880677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
244980677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
245080677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
245180677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
245280677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2453674ae819SStefano Zampini     }
2454674ae819SStefano Zampini   }
2455be83ff47SStefano Zampini   if (!sub_schurs->reuse_mumps) {
245680677318SStefano Zampini     if (applytranspose) {
245780677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
245880677318SStefano Zampini     } else {
245980677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
246080677318SStefano Zampini     }
246153892102SStefano Zampini #if defined(PETSC_HAVE_MUMPS)
2462be83ff47SStefano Zampini   } else {
2463be83ff47SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2464be83ff47SStefano Zampini 
2465be83ff47SStefano Zampini     if (applytranspose) {
246653892102SStefano Zampini       ierr = MatMumpsSolveSchurComplementTranspose(reuse_mumps->F,reuse_mumps->rhs_B,reuse_mumps->sol_B);CHKERRQ(ierr);
2467be83ff47SStefano Zampini     } else {
246853892102SStefano Zampini       ierr = MatMumpsSolveSchurComplement(reuse_mumps->F,reuse_mumps->rhs_B,reuse_mumps->sol_B);CHKERRQ(ierr);
2469be83ff47SStefano Zampini     }
247053892102SStefano Zampini #endif
2471be83ff47SStefano Zampini   }
247280677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
247380677318SStefano Zampini   if (!pcbddc->switch_static) {
2474be83ff47SStefano Zampini     if (!sub_schurs->reuse_mumps) {
247580677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
247680677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2477be83ff47SStefano Zampini     } else {
2478be83ff47SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2479be83ff47SStefano Zampini 
248053892102SStefano Zampini       ierr = VecScatterBegin(reuse_mumps->correction_scatter_B,reuse_mumps->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
248153892102SStefano Zampini       ierr = VecScatterEnd(reuse_mumps->correction_scatter_B,reuse_mumps->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2482be83ff47SStefano Zampini     }
248380677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
248480677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
248580677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
248680677318SStefano Zampini     }
248780677318SStefano Zampini   } else {
248880677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
248980677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
249080677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
249180677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
249280677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
249380677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
249480677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
249580677318SStefano Zampini     }
249680677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
249780677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
249880677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
249980677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2500674ae819SStefano Zampini   }
2501674ae819SStefano Zampini   PetscFunctionReturn(0);
2502674ae819SStefano Zampini }
2503674ae819SStefano Zampini 
2504dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
2505674ae819SStefano Zampini #undef __FUNCT__
2506674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
2507dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
2508674ae819SStefano Zampini {
2509674ae819SStefano Zampini   PetscErrorCode ierr;
2510674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
2511674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
2512674ae819SStefano Zampini   const PetscScalar zero = 0.0;
2513674ae819SStefano Zampini 
2514674ae819SStefano Zampini   PetscFunctionBegin;
2515dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
2516dc359a40SStefano Zampini   if (applytranspose) {
2517674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
25188eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
2519dc359a40SStefano Zampini   } else {
2520674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
2521674ae819SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
252215aaf578SStefano Zampini   }
2523efc2fbd9SStefano Zampini 
2524efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
25254f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
2526efc2fbd9SStefano Zampini     PetscScalar *array;
25274f1b2e48SStefano Zampini     PetscInt    j;
2528efc2fbd9SStefano Zampini 
2529efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
25304f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
2531efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2532efc2fbd9SStefano Zampini   }
2533efc2fbd9SStefano Zampini 
253412edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
253512edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
253612edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
253712edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
253812edc857SStefano Zampini 
25399f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
254012edc857SStefano Zampini   /* TODO remove null space when doing multilevel */
254112edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
254251694757SStefano Zampini     Mat coarse_mat;
2543964fefecSStefano Zampini     Vec rhs,sol;
254451694757SStefano Zampini     MatNullSpace nullsp;
2545964fefecSStefano Zampini 
2546964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
2547964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
254851694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
254951694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
255051694757SStefano Zampini     if (nullsp) {
255151694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
255251694757SStefano Zampini     }
255312edc857SStefano Zampini     if (applytranspose) {
2554964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
255512edc857SStefano Zampini     } else {
2556964fefecSStefano Zampini       ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
255712edc857SStefano Zampini     }
255851694757SStefano Zampini     if (nullsp) {
255951694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
256051694757SStefano Zampini     }
256112edc857SStefano Zampini   }
2562674ae819SStefano Zampini 
2563674ae819SStefano Zampini   /* Local solution on R nodes */
256480677318SStefano Zampini   if (pcis->n) { /* in/out pcbddc->vec1_B,pcbddc->vec1_D */
256580677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
25669f00e9b4SStefano Zampini   }
2567674ae819SStefano Zampini 
25689f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
25699f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
257012edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2571674ae819SStefano Zampini 
2572674ae819SStefano Zampini   /* Sum contributions from two levels */
2573dc359a40SStefano Zampini   if (applytranspose) {
2574dc359a40SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
2575dc359a40SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
2576dc359a40SStefano Zampini   } else {
2577674ae819SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
25788eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
2579dc359a40SStefano Zampini   }
2580efc2fbd9SStefano Zampini   /* store p0 */
25814f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
2582efc2fbd9SStefano Zampini     PetscScalar *array;
25834f1b2e48SStefano Zampini     PetscInt    j;
2584efc2fbd9SStefano Zampini 
2585efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
25864f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
2587efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2588efc2fbd9SStefano Zampini   }
2589674ae819SStefano Zampini   PetscFunctionReturn(0);
2590674ae819SStefano Zampini }
2591674ae819SStefano Zampini 
2592674ae819SStefano Zampini #undef __FUNCT__
2593674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
259412edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
2595674ae819SStefano Zampini {
2596674ae819SStefano Zampini   PetscErrorCode ierr;
2597674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
259858da7f69SStefano Zampini   PetscScalar    *array;
259912edc857SStefano Zampini   Vec            from,to;
2600674ae819SStefano Zampini 
2601674ae819SStefano Zampini   PetscFunctionBegin;
260212edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
260312edc857SStefano Zampini     from = pcbddc->coarse_vec;
260412edc857SStefano Zampini     to = pcbddc->vec1_P;
260512edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
260612edc857SStefano Zampini       Vec tvec;
260758da7f69SStefano Zampini 
260858da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
260958da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
261012edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
261158da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
261258da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
261358da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
261412edc857SStefano Zampini     }
261512edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
261612edc857SStefano Zampini     from = pcbddc->vec1_P;
261712edc857SStefano Zampini     to = pcbddc->coarse_vec;
261812edc857SStefano Zampini   }
261912edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
2620674ae819SStefano Zampini   PetscFunctionReturn(0);
2621674ae819SStefano Zampini }
2622674ae819SStefano Zampini 
2623674ae819SStefano Zampini #undef __FUNCT__
2624674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
262512edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
2626674ae819SStefano Zampini {
2627674ae819SStefano Zampini   PetscErrorCode ierr;
2628674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
262958da7f69SStefano Zampini   PetscScalar    *array;
263012edc857SStefano Zampini   Vec            from,to;
2631674ae819SStefano Zampini 
2632674ae819SStefano Zampini   PetscFunctionBegin;
263312edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
263412edc857SStefano Zampini     from = pcbddc->coarse_vec;
263512edc857SStefano Zampini     to = pcbddc->vec1_P;
263612edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
263712edc857SStefano Zampini     from = pcbddc->vec1_P;
263812edc857SStefano Zampini     to = pcbddc->coarse_vec;
263912edc857SStefano Zampini   }
264012edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
264112edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
264212edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
264312edc857SStefano Zampini       Vec tvec;
264458da7f69SStefano Zampini 
264512edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
264658da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
264758da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
264858da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
264958da7f69SStefano Zampini     }
265058da7f69SStefano Zampini   } else {
265158da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
265258da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
265312edc857SStefano Zampini     }
265412edc857SStefano Zampini   }
2655674ae819SStefano Zampini   PetscFunctionReturn(0);
2656674ae819SStefano Zampini }
2657674ae819SStefano Zampini 
2658984c4197SStefano Zampini /* uncomment for testing purposes */
2659984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
2660674ae819SStefano Zampini #undef __FUNCT__
2661674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
2662674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
2663674ae819SStefano Zampini {
2664674ae819SStefano Zampini   PetscErrorCode    ierr;
2665674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
2666674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
2667674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
2668984c4197SStefano Zampini   /* one and zero */
2669984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
2670984c4197SStefano Zampini   /* space to store constraints and their local indices */
26719162d606SStefano Zampini   PetscScalar       *constraints_data;
26729162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
26739162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
26749162d606SStefano Zampini   PetscInt          *constraints_n;
2675984c4197SStefano Zampini   /* iterators */
2676b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
2677984c4197SStefano Zampini   /* BLAS integers */
2678e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
2679e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
2680c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
2681727cdba6SStefano Zampini   /* reuse */
26820e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
26830e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
2684984c4197SStefano Zampini   /* change of basis */
2685b3d85658SStefano Zampini   PetscBool         qr_needed;
26869162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
2687984c4197SStefano Zampini   /* auxiliary stuff */
268864efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
26898a0068c3SStefano Zampini   PetscInt          ncc;
2690984c4197SStefano Zampini   /* some quantities */
269145a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
2692a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
2693984c4197SStefano Zampini 
2694674ae819SStefano Zampini   PetscFunctionBegin;
26958e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
26968e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
26978e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
2698088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
2699088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
27000e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
27010e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
27020e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
27030e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
27040e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
2705088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
2706cf5a6209SStefano Zampini 
2707cf5a6209SStefano Zampini   /* print some info */
2708cf5a6209SStefano Zampini   if (pcbddc->dbg_flag) {
2709cf5a6209SStefano Zampini     IS       vertices;
2710cf5a6209SStefano Zampini     PetscInt nv,nedges,nfaces;
2711cf5a6209SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
2712cf5a6209SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
2713cf5a6209SStefano Zampini     ierr = ISDestroy(&vertices);CHKERRQ(ierr);
2714cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
2715cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2716cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
2717fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
2718fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
2719cf5a6209SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2720cf5a6209SStefano Zampini   }
2721cf5a6209SStefano Zampini 
2722cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
27239162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
2724cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
2725cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
2726cf5a6209SStefano Zampini     Vec          *localnearnullsp;
2727cf5a6209SStefano Zampini     PetscScalar  *array;
2728cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
2729cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
2730674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
2731b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
2732674ae819SStefano Zampini     PetscScalar  *work;
2733674ae819SStefano Zampini     PetscReal    *singular_vals;
2734674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2735674ae819SStefano Zampini     PetscReal    *rwork;
2736674ae819SStefano Zampini #endif
2737674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2738674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
2739674ae819SStefano Zampini #else
2740964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
2741964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
2742674ae819SStefano Zampini #endif
2743674ae819SStefano Zampini 
2744674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
2745d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
2746d06fc5fdSStefano Zampini     /* free unneeded index sets */
2747d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
2748d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
2749674ae819SStefano Zampini     }
2750d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
2751d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
2752d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
2753d06fc5fdSStefano Zampini       }
2754d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
2755d06fc5fdSStefano Zampini       n_ISForEdges = 0;
2756d06fc5fdSStefano Zampini     }
2757d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
2758d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
2759d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
2760d06fc5fdSStefano Zampini       }
2761d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
2762d06fc5fdSStefano Zampini       n_ISForFaces = 0;
2763d06fc5fdSStefano Zampini     }
276470022509SStefano Zampini 
276570022509SStefano Zampini #if defined(PETSC_USE_DEBUG)
276670022509SStefano Zampini     /* HACK: when solving singular problems not using vertices, a change of basis is mandatory.
276770022509SStefano Zampini        Also use_change_of_basis should be consistent among processors */
276870022509SStefano Zampini     if (pcbddc->NullSpace) {
276970022509SStefano Zampini       PetscBool tbool[2],gbool[2];
277070022509SStefano Zampini 
277170022509SStefano Zampini       if (!ISForVertices && !pcbddc->user_ChangeOfBasisMatrix) {
2772b8ffe317SStefano Zampini         pcbddc->use_change_of_basis = PETSC_TRUE;
2773d06fc5fdSStefano Zampini         if (!ISForEdges) {
2774d06fc5fdSStefano Zampini           pcbddc->use_change_on_faces = PETSC_TRUE;
2775d06fc5fdSStefano Zampini         }
2776b8ffe317SStefano Zampini       }
2777d06fc5fdSStefano Zampini       tbool[0] = pcbddc->use_change_of_basis;
2778d06fc5fdSStefano Zampini       tbool[1] = pcbddc->use_change_on_faces;
2779d06fc5fdSStefano Zampini       ierr = MPI_Allreduce(tbool,gbool,2,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2780d06fc5fdSStefano Zampini       pcbddc->use_change_of_basis = gbool[0];
2781d06fc5fdSStefano Zampini       pcbddc->use_change_on_faces = gbool[1];
278298a51de6SStefano Zampini     }
278370022509SStefano Zampini #endif
278408122e43SStefano Zampini 
2785674ae819SStefano Zampini     /* check if near null space is attached to global mat */
2786674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
2787674ae819SStefano Zampini     if (nearnullsp) {
2788674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
2789f4ddd8eeSStefano Zampini       /* remove any stored info */
2790f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
2791f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
2792f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
2793f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
2794f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
2795473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
2796f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
2797f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
2798f4ddd8eeSStefano Zampini       }
2799984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
2800984c4197SStefano Zampini       nnsp_size = 0;
2801674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
2802674ae819SStefano Zampini     }
2803984c4197SStefano Zampini     /* get max number of constraints on a single cc */
2804984c4197SStefano Zampini     max_constraints = nnsp_size;
2805984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
2806984c4197SStefano Zampini 
2807674ae819SStefano Zampini     /*
2808674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
28099162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
28109162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
28119162d606SStefano Zampini          There can be multiple constraints per connected component
2812674ae819SStefano Zampini                                                                                                                                                            */
2813674ae819SStefano Zampini     n_vertices = 0;
2814674ae819SStefano Zampini     if (ISForVertices) {
2815674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
2816674ae819SStefano Zampini     }
28179162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
28189162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
28199162d606SStefano Zampini 
28209162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
28219162d606SStefano Zampini     total_counts *= max_constraints;
2822674ae819SStefano Zampini     total_counts += n_vertices;
28234641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
28249162d606SStefano Zampini 
2825674ae819SStefano Zampini     total_counts = 0;
2826674ae819SStefano Zampini     max_size_of_constraint = 0;
2827674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
28289162d606SStefano Zampini       IS used_is;
2829674ae819SStefano Zampini       if (i<n_ISForEdges) {
28309162d606SStefano Zampini         used_is = ISForEdges[i];
2831674ae819SStefano Zampini       } else {
28329162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
2833674ae819SStefano Zampini       }
28349162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
2835674ae819SStefano Zampini       total_counts += j;
2836674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
2837674ae819SStefano Zampini     }
28389162d606SStefano 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);
28399162d606SStefano Zampini 
2840984c4197SStefano Zampini     /* get local part of global near null space vectors */
2841785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
2842984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
2843984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
2844e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2845e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2846984c4197SStefano Zampini     }
2847674ae819SStefano Zampini 
2848242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
2849242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
2850a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
2851242a89d7SStefano Zampini 
2852984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
2853a773dcb8SStefano Zampini     if (!skip_lapack) {
2854674ae819SStefano Zampini       PetscScalar temp_work;
2855911cabfeSStefano Zampini 
2856674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2857984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
2858785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
2859785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
2860785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
2861674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2862785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
2863674ae819SStefano Zampini #endif
2864674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
2865c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
2866c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
2867674ae819SStefano Zampini       lwork = -1;
2868674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2869674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
2870c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
2871674ae819SStefano Zampini #else
2872c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
2873674ae819SStefano Zampini #endif
2874674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
2875984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
2876674ae819SStefano Zampini #else /* on missing GESVD */
2877674ae819SStefano Zampini       /* SVD */
2878674ae819SStefano Zampini       PetscInt max_n,min_n;
2879674ae819SStefano Zampini       max_n = max_size_of_constraint;
2880984c4197SStefano Zampini       min_n = max_constraints;
2881984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
2882674ae819SStefano Zampini         min_n = max_size_of_constraint;
2883984c4197SStefano Zampini         max_n = max_constraints;
2884674ae819SStefano Zampini       }
2885785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
2886674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2887785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
2888674ae819SStefano Zampini #endif
2889674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
2890674ae819SStefano Zampini       lwork = -1;
2891e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
2892e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
2893b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
2894674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2895674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
28969162d606SStefano 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));
2897674ae819SStefano Zampini #else
28989162d606SStefano 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));
2899674ae819SStefano Zampini #endif
2900674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
2901984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
2902984c4197SStefano Zampini #endif /* on missing GESVD */
2903674ae819SStefano Zampini       /* Allocate optimal workspace */
2904674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
2905854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
2906674ae819SStefano Zampini     }
2907674ae819SStefano Zampini     /* Now we can loop on constraining sets */
2908674ae819SStefano Zampini     total_counts = 0;
29099162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
29109162d606SStefano Zampini     constraints_data_ptr[0] = 0;
2911674ae819SStefano Zampini     /* vertices */
29129162d606SStefano Zampini     if (n_vertices) {
2913674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
29149162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
2915674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
29169162d606SStefano Zampini         constraints_n[total_counts] = 1;
29179162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
29189162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
29199162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
2920674ae819SStefano Zampini         total_counts++;
2921674ae819SStefano Zampini       }
2922674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2923674ae819SStefano Zampini       n_vertices = total_counts;
2924674ae819SStefano Zampini     }
2925984c4197SStefano Zampini 
2926674ae819SStefano Zampini     /* edges and faces */
29279162d606SStefano Zampini     total_counts_cc = total_counts;
2928911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
29299162d606SStefano Zampini       IS        used_is;
29309162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
29319162d606SStefano Zampini 
2932911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
29339162d606SStefano Zampini         used_is = ISForEdges[ncc];
2934984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
2935674ae819SStefano Zampini       } else {
29369162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
2937984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
2938674ae819SStefano Zampini       }
2939674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
29409162d606SStefano Zampini 
29419162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
29429162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2943984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
2944984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
2945674ae819SStefano Zampini       if (nnsp_has_cnst) {
29465b08dc53SStefano Zampini         PetscScalar quad_value;
29479162d606SStefano Zampini 
29489162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
29499162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
29509162d606SStefano Zampini 
2951a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
2952674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
2953a773dcb8SStefano Zampini         } else {
2954a773dcb8SStefano Zampini           quad_value = 1.0;
2955a773dcb8SStefano Zampini         }
2956674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
29579162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
2958674ae819SStefano Zampini         }
29599162d606SStefano Zampini         temp_constraints++;
2960674ae819SStefano Zampini         total_counts++;
2961674ae819SStefano Zampini       }
2962674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
2963984c4197SStefano Zampini         PetscReal real_value;
29649162d606SStefano Zampini         PetscScalar *ptr_to_data;
29659162d606SStefano Zampini 
2966984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
29679162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
2968674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
29699162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
2970674ae819SStefano Zampini         }
2971984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
2972984c4197SStefano Zampini         /* check if array is null on the connected component */
2973e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
29749162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
29755b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
2976674ae819SStefano Zampini           temp_constraints++;
2977674ae819SStefano Zampini           total_counts++;
29789162d606SStefano Zampini           if (!idxs_copied) {
29799162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
29809162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
2981674ae819SStefano Zampini           }
2982674ae819SStefano Zampini         }
29839162d606SStefano Zampini       }
29849162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
298545a1bb75SStefano Zampini       valid_constraints = temp_constraints;
2986eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
2987a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
29889162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
29899162d606SStefano Zampini 
29909162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
2991a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
29929162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
2993a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
29949162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
2995a773dcb8SStefano Zampini         } else { /* perform SVD */
2996984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
29979162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
2998674ae819SStefano Zampini 
2999674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3000984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
3001984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
3002984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
3003984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
3004984c4197SStefano Zampini                 from that computed using LAPACKgesvd
3005984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
3006984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
3007984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
3008674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
3009e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3010984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3011674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
3012674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
30139162d606SStefano 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));
3014674ae819SStefano Zampini             }
3015674ae819SStefano Zampini           }
3016e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
3017e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3018e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
3019674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
3020c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
3021674ae819SStefano Zampini #else
3022c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
3023674ae819SStefano Zampini #endif
3024674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3025984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
3026984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
3027674ae819SStefano Zampini           j = 0;
3028984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
3029674ae819SStefano Zampini           total_counts = total_counts-j;
303045a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
3031e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
3032c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3033c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3034c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
3035c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3036c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
3037c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
3038674ae819SStefano Zampini           if (j<temp_constraints) {
3039984c4197SStefano Zampini             PetscInt ii;
3040984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
3041674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
30429162d606SStefano 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));
3043674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
3044984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
3045674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
30469162d606SStefano 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];
3047674ae819SStefano Zampini               }
3048674ae819SStefano Zampini             }
3049674ae819SStefano Zampini           }
3050674ae819SStefano Zampini #else  /* on missing GESVD */
3051e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3052e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3053b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3054674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3055674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
30569162d606SStefano 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));
3057674ae819SStefano Zampini #else
30589162d606SStefano 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));
3059674ae819SStefano Zampini #endif
3060984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
3061674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3062984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
3063e310c8b4SStefano Zampini           k = temp_constraints;
3064e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
3065674ae819SStefano Zampini           j = 0;
3066e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
306745a1bb75SStefano Zampini           valid_constraints = k-j;
3068911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
3069984c4197SStefano Zampini #endif /* on missing GESVD */
3070674ae819SStefano Zampini         }
3071a773dcb8SStefano Zampini       }
30729162d606SStefano Zampini       /* update pointers information */
30739162d606SStefano Zampini       if (valid_constraints) {
30749162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
30759162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
30769162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
30779162d606SStefano Zampini         /* set change_of_basis flag */
307845a1bb75SStefano Zampini         if (boolforchange) {
3079b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
30809162d606SStefano Zampini         }
3081b3d85658SStefano Zampini         total_counts_cc++;
308245a1bb75SStefano Zampini       }
308345a1bb75SStefano Zampini     }
3084984c4197SStefano Zampini     /* free workspace */
30858f1c130eSStefano Zampini     if (!skip_lapack) {
3086984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
3087984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3088984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
3089984c4197SStefano Zampini #endif
3090984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
3091984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3092984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
3093984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
3094984c4197SStefano Zampini #endif
3095984c4197SStefano Zampini     }
3096984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
3097984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
3098984c4197SStefano Zampini     }
3099984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
3100cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
3101cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
3102cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
3103cf5a6209SStefano Zampini     }
3104cf5a6209SStefano Zampini     if (n_ISForFaces) {
3105cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
3106cf5a6209SStefano Zampini     }
3107cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
3108cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
3109cf5a6209SStefano Zampini     }
3110cf5a6209SStefano Zampini     if (n_ISForEdges) {
3111cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
3112cf5a6209SStefano Zampini     }
3113cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
311408122e43SStefano Zampini   } else {
311508122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
3116984c4197SStefano Zampini 
311708122e43SStefano Zampini     total_counts = 0;
311808122e43SStefano Zampini     n_vertices = 0;
3119d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
3120d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
312108122e43SStefano Zampini     }
312208122e43SStefano Zampini     max_constraints = 0;
31239162d606SStefano Zampini     total_counts_cc = 0;
312408122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
312508122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
31269162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
312708122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
312808122e43SStefano Zampini     }
31299162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
31309162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
31319162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
31329162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
313374d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
31349162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
31359162d606SStefano Zampini     total_counts_cc = 0;
31369162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
31379162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
31389162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
313908122e43SStefano Zampini       }
314008122e43SStefano Zampini     }
31419162d606SStefano Zampini #if 0
31429162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
31439162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
31449162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
31459162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
31469162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
31479162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
31489162d606SStefano Zampini       }
31499162d606SStefano Zampini       printf("\n");
31509162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
31519162d606SStefano Zampini     }
31521b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
31538bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
31541b968477SStefano Zampini     }
31551b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
31568bec7fa6SStefano 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]);
31571b968477SStefano Zampini     }
315808122e43SStefano Zampini #endif
315908122e43SStefano Zampini 
31608bec7fa6SStefano Zampini     max_size_of_constraint = 0;
31619162d606SStefano 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]);
31629162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
316308122e43SStefano Zampini     /* Change of basis */
3164b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
316508122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
316608122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
316708122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
3168b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
316908122e43SStefano Zampini         }
317008122e43SStefano Zampini       }
317108122e43SStefano Zampini     }
317208122e43SStefano Zampini   }
3173984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
31744f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
317508122e43SStefano Zampini 
31769162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
31779162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
31789162d606SStefano Zampini   if (i != constraints_idxs_ptr[total_counts_cc]) {
31799162d606SStefano 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);
318008122e43SStefano Zampini   }
3181674ae819SStefano Zampini 
3182674ae819SStefano Zampini   /* Create constraint matrix */
3183674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
318416f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
3185984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
3186984c4197SStefano Zampini 
3187984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
3188a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
3189a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
319074d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
3191984c4197SStefano Zampini   total_primal_vertices=0;
3192b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
31939162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
31949162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
3195984c4197SStefano Zampini     if (size_of_constraint == 1) {
31969162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
3197b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
319864efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
31999162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
32009162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
3201a717540cSStefano Zampini       }
3202b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
320374d5cdf7SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single || pcbddc->faster_deluxe) {
3204a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
3205a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
3206a717540cSStefano Zampini       }
3207fa434743SStefano Zampini     } else {
3208b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
3209fa434743SStefano Zampini     }
3210a717540cSStefano Zampini   }
3211b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
3212b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
3213674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
321470022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
3215b3d85658SStefano Zampini 
32164f1b2e48SStefano 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);
32170e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
32180e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
3219984c4197SStefano Zampini 
3220984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
322174d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
3222785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
3223984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
322474d5cdf7SStefano Zampini 
3225984c4197SStefano Zampini   j = total_primal_vertices;
322674d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
3227b3d85658SStefano Zampini   cum = total_primal_vertices;
32289162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
32294641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
3230b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
3231b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
3232b3d85658SStefano Zampini       cum++;
32339162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
323474d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
323574d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
323674d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
323774d5cdf7SStefano Zampini       }
32389162d606SStefano Zampini       j += constraints_n[i];
3239674ae819SStefano Zampini     }
3240674ae819SStefano Zampini   }
3241674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
3242674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
3243088faed8SStefano Zampini 
3244674ae819SStefano Zampini   /* set values in constraint matrix */
3245984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
32460e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
3247674ae819SStefano Zampini   }
3248984c4197SStefano Zampini   total_counts = total_primal_vertices;
32499162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
32504641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
32519162d606SStefano Zampini       PetscInt *cols;
32529162d606SStefano Zampini 
32539162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
32549162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
32559162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
32569162d606SStefano Zampini         PetscInt    row = total_counts+k;
32579162d606SStefano Zampini         PetscScalar *vals;
32589162d606SStefano Zampini 
32599162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
32609162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
32619162d606SStefano Zampini       }
32629162d606SStefano Zampini       total_counts += constraints_n[i];
3263674ae819SStefano Zampini     }
3264674ae819SStefano Zampini   }
3265674ae819SStefano Zampini   /* assembling */
3266674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3267674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3268088faed8SStefano Zampini 
3269984c4197SStefano Zampini   /*
327045a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
3271984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
3272984c4197SStefano Zampini   */
3273674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
3274674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
3275026de310SStefano Zampini     /* dual and primal dofs on a single cc */
3276984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
3277984c4197SStefano Zampini     /* working stuff for GEQRF */
327881d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
3279984c4197SStefano Zampini     PetscBLASInt lqr_work;
3280984c4197SStefano Zampini     /* working stuff for UNGQR */
3281984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
3282984c4197SStefano Zampini     PetscBLASInt lgqr_work;
3283984c4197SStefano Zampini     /* working stuff for TRTRS */
3284984c4197SStefano Zampini     PetscScalar  *trs_rhs;
32853f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
3286984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
3287984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
3288984c4197SStefano Zampini     PetscScalar  *start_vals;
3289984c4197SStefano Zampini     /* working stuff for values insertion */
32904641a718SStefano Zampini     PetscBT      is_primal;
329164efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
3292906d46d4SStefano Zampini     /* matrix sizes */
3293906d46d4SStefano Zampini     PetscInt     global_size,local_size;
3294906d46d4SStefano Zampini     /* temporary change of basis */
3295906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
3296cf5a6209SStefano Zampini     /* extra space for debugging */
3297cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
3298984c4197SStefano Zampini 
3299906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
3300906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
330116f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
3302bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
3303906d46d4SStefano Zampini     /* nonzeros for local mat */
3304bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
3305bbb9e6c6SStefano Zampini     for (i=0;i<pcis->n;i++) nnz[i]=1;
33069162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
3307a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
33089162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
3309a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
33109162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
3311a717540cSStefano Zampini         } else {
33129162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
33139162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
3314a717540cSStefano Zampini         }
3315a717540cSStefano Zampini       }
3316a717540cSStefano Zampini     }
3317906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
3318bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
3319a717540cSStefano Zampini     /* Set initial identity in the matrix */
3320bbb9e6c6SStefano Zampini     for (i=0;i<pcis->n;i++) {
3321906d46d4SStefano Zampini       ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
3322a717540cSStefano Zampini     }
3323a717540cSStefano Zampini 
3324a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
3325a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3326a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
3327a717540cSStefano Zampini     }
3328a717540cSStefano Zampini 
3329a717540cSStefano Zampini 
3330a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
3331a717540cSStefano Zampini     /*
3332a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
3333a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
3334a717540cSStefano Zampini 
3335a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
3336a717540cSStefano Zampini 
3337a6b551f4SStefano 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)
3338a6b551f4SStefano Zampini 
3339a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
3340a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
3341a717540cSStefano Zampini             |              ...                        |
3342a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
3343a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
3344a717540cSStefano Zampini 
3345a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
3346a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
3347a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
3348a6b551f4SStefano Zampini 
3349a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
3350a717540cSStefano Zampini     */
3351a717540cSStefano Zampini     if (qr_needed) {
3352984c4197SStefano Zampini       /* space to store Q */
3353854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
3354984c4197SStefano Zampini       /* first we issue queries for optimal work */
33553f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
33563f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
33573f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3358984c4197SStefano Zampini       lqr_work = -1;
33593f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
3360984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
3361984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
3362785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
3363984c4197SStefano Zampini       lgqr_work = -1;
33643f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
33653f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
33663f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
33673f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
33683f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
33693f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
3370984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
3371984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
3372785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
3373984c4197SStefano Zampini       /* array to store scaling factors for reflectors */
3374785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
3375984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
3376785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
3377a717540cSStefano Zampini       /* allocating workspace for check */
3378a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
3379cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
3380a717540cSStefano Zampini       }
3381a717540cSStefano Zampini     }
3382984c4197SStefano Zampini     /* array to store whether a node is primal or not */
33834641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
3384473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
33850e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
338639e2fb2aSStefano Zampini     if (i != total_primal_vertices) {
338739e2fb2aSStefano Zampini       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %d != %d\n",total_primal_vertices,i);
33884641a718SStefano Zampini     }
338939e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
339039e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
339139e2fb2aSStefano Zampini     }
339239e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
3393984c4197SStefano Zampini 
3394a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
33959162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
33969162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
33974641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
3398984c4197SStefano Zampini         /* get constraint info */
33999162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
3400984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
3401984c4197SStefano Zampini 
3402984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
34039162d606SStefano 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);
3404674ae819SStefano Zampini         }
3405984c4197SStefano Zampini 
3406fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
3407a717540cSStefano Zampini 
3408a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
3409a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
34109162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3411a717540cSStefano Zampini           }
3412984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
34139162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3414984c4197SStefano Zampini 
3415984c4197SStefano Zampini           /* compute QR decomposition of constraints */
34163f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
34173f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
34183f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3419674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
34203f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
3421984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
3422674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3423984c4197SStefano Zampini 
3424984c4197SStefano Zampini           /* explictly compute R^-T */
3425984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
3426984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
34273f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
34283f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
34293f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
34303f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
3431984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
34323f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
3433984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
3434984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3435984c4197SStefano Zampini 
3436a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
34373f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
34383f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
34393f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
34403f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3441984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
34423f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
3443984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
3444984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3445984c4197SStefano Zampini 
3446984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
3447984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
3448984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
34493f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
34503f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
34513f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
34523f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
34533f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
34543f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
3455984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
34569162d606SStefano 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));
3457984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
34589162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3459984c4197SStefano Zampini 
3460984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
34619162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
3462984c4197SStefano Zampini           /* insert cols for primal dofs */
3463984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
3464984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
34659162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
3466906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
3467984c4197SStefano Zampini           }
3468984c4197SStefano Zampini           /* insert cols for dual dofs */
3469984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
34709162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
3471984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
34729162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
3473906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
3474984c4197SStefano Zampini               j++;
3475674ae819SStefano Zampini             }
3476674ae819SStefano Zampini           }
3477984c4197SStefano Zampini 
3478984c4197SStefano Zampini           /* check change of basis */
3479984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
3480984c4197SStefano Zampini             PetscInt   ii,jj;
3481984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
3482c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
3483c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3484c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
3485c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3486c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
3487c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
3488984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3489cf5a6209SStefano 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));
3490984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
3491984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
3492984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
3493cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
3494cf5a6209SStefano 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;
3495674ae819SStefano Zampini               }
3496674ae819SStefano Zampini             }
3497984c4197SStefano Zampini             if (!valid_qr) {
349822d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
3499984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
3500984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
3501cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
3502cf5a6209SStefano 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]));
3503674ae819SStefano Zampini                   }
3504cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
3505cf5a6209SStefano 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]));
3506984c4197SStefano Zampini                   }
3507984c4197SStefano Zampini                 }
3508984c4197SStefano Zampini               }
3509674ae819SStefano Zampini             } else {
351022d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
3511674ae819SStefano Zampini             }
3512674ae819SStefano Zampini           }
3513a717540cSStefano Zampini         } else { /* simple transformation block */
3514a717540cSStefano Zampini           PetscInt    row,col;
3515a6b551f4SStefano Zampini           PetscScalar val,norm;
3516a6b551f4SStefano Zampini 
3517a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
35189162d606SStefano 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));
3519a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
35209162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
35219162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
3522bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
35239162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
3524906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
35259162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
3526a717540cSStefano Zampini             } else {
3527a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
35289162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
3529a717540cSStefano Zampini                 if (row != col) {
35309162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
3531a717540cSStefano Zampini                 } else {
35329162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
3533a717540cSStefano Zampini                 }
3534906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
3535a717540cSStefano Zampini               }
3536a717540cSStefano Zampini             }
3537a717540cSStefano Zampini           }
353898a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
353922d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
3540a717540cSStefano Zampini           }
3541674ae819SStefano Zampini         }
3542984c4197SStefano Zampini       } else {
3543984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
35449162d606SStefano 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);
3545674ae819SStefano Zampini         }
3546674ae819SStefano Zampini       }
3547674ae819SStefano Zampini     }
3548a717540cSStefano Zampini 
3549a717540cSStefano Zampini     /* free workspace */
3550a717540cSStefano Zampini     if (qr_needed) {
3551984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
3552cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
3553984c4197SStefano Zampini       }
3554984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
3555984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
3556984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
3557984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
3558984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
3559674ae819SStefano Zampini     }
3560a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
3561906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3562906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3563906d46d4SStefano Zampini 
3564906d46d4SStefano Zampini     /* assembling of global change of variable */
3565bbb9e6c6SStefano Zampini     {
3566bbb9e6c6SStefano Zampini       Mat      tmat;
356716f15bc4SStefano Zampini       PetscInt bs;
356816f15bc4SStefano Zampini 
3569906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
3570906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
3571bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
3572bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
3573bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3574bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
357516f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
357616f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
3577906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
3578bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
3579bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3580bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
3581bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
3582bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
3583e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3584e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3585bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
3586bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
3587906d46d4SStefano Zampini     }
3588906d46d4SStefano Zampini     /* check */
3589906d46d4SStefano Zampini     if (pcbddc->dbg_flag) {
3590906d46d4SStefano Zampini       PetscReal error;
3591906d46d4SStefano Zampini       Vec       x,x_change;
3592906d46d4SStefano Zampini 
3593906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
3594906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
3595906d46d4SStefano Zampini       ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
3596906d46d4SStefano Zampini       ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
3597e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3598e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3599bbb9e6c6SStefano Zampini       ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
3600e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3601e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3602906d46d4SStefano Zampini       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
3603906d46d4SStefano Zampini       ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
3604906d46d4SStefano Zampini       ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
3605906d46d4SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3606bbb9e6c6SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
3607906d46d4SStefano Zampini       ierr = VecDestroy(&x);CHKERRQ(ierr);
3608906d46d4SStefano Zampini       ierr = VecDestroy(&x_change);CHKERRQ(ierr);
3609906d46d4SStefano Zampini     }
3610b96c3477SStefano Zampini 
3611b96c3477SStefano Zampini     /* adapt sub_schurs computed (if any) */
3612b96c3477SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
3613b96c3477SStefano Zampini       PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
3614b96c3477SStefano Zampini       if (sub_schurs->S_Ej_all) {
3615ac632422SStefano Zampini         Mat                    S_new,tmat;
3616b087196eSStefano Zampini         ISLocalToGlobalMapping NtoSall;
3617b087196eSStefano Zampini         IS                     is_all_N,is_V,is_V_Sall;
3618b087196eSStefano Zampini         const PetscScalar      *array;
3619b087196eSStefano Zampini         const PetscInt         *idxs_V,*idxs_all;
3620b087196eSStefano Zampini         PetscInt               i,n_V;
3621bbb9e6c6SStefano Zampini 
3622bbb9e6c6SStefano Zampini         ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
36236816873aSStefano Zampini         ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
3624b087196eSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
3625b087196eSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
3626b087196eSStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
3627b087196eSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
3628bbb9e6c6SStefano Zampini         ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
3629b087196eSStefano Zampini         ierr = ISDestroy(&is_V);CHKERRQ(ierr);
3630ac632422SStefano Zampini         ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
3631b96c3477SStefano Zampini         ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
3632ac632422SStefano Zampini         ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
3633b087196eSStefano Zampini         ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
3634b087196eSStefano Zampini         ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
3635b087196eSStefano Zampini         ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
3636b087196eSStefano Zampini         ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
3637b087196eSStefano Zampini         ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
3638b087196eSStefano Zampini         for (i=0;i<n_V;i++) {
3639b087196eSStefano Zampini           PetscScalar val;
3640b087196eSStefano Zampini           PetscInt    idx;
3641b087196eSStefano Zampini 
3642b087196eSStefano Zampini           idx = idxs_V[i];
3643b087196eSStefano Zampini           val = array[idxs_all[idxs_V[i]]];
3644b087196eSStefano Zampini           ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
3645b087196eSStefano Zampini         }
3646b087196eSStefano Zampini         ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3647b087196eSStefano Zampini         ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3648ac632422SStefano Zampini         sub_schurs->S_Ej_all = S_new;
3649ac632422SStefano Zampini         ierr = MatDestroy(&S_new);CHKERRQ(ierr);
3650ac632422SStefano Zampini         if (sub_schurs->sum_S_Ej_all) {
3651ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
3652b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
3653ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
3654b087196eSStefano Zampini           ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
3655ac632422SStefano Zampini           sub_schurs->sum_S_Ej_all = S_new;
3656ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
3657ac632422SStefano Zampini         }
3658b087196eSStefano Zampini         ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
3659b087196eSStefano Zampini         ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
3660b087196eSStefano Zampini         ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
3661b96c3477SStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
3662b087196eSStefano Zampini         ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
3663b96c3477SStefano Zampini       }
3664b96c3477SStefano Zampini     }
3665906d46d4SStefano Zampini     ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
3666906d46d4SStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix) {
3667b9b85e73SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3668b9b85e73SStefano Zampini     pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
3669b9b85e73SStefano Zampini   }
3670906d46d4SStefano Zampini 
3671906d46d4SStefano Zampini   /* set up change of basis context */
3672906d46d4SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
3673906d46d4SStefano Zampini     PCBDDCChange_ctx change_ctx;
3674906d46d4SStefano Zampini 
3675906d46d4SStefano Zampini     if (!pcbddc->new_global_mat) {
3676906d46d4SStefano Zampini       PetscInt global_size,local_size;
3677906d46d4SStefano Zampini 
3678906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
3679906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
3680906d46d4SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->new_global_mat);CHKERRQ(ierr);
3681906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->new_global_mat,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
3682906d46d4SStefano Zampini       ierr = MatSetType(pcbddc->new_global_mat,MATSHELL);CHKERRQ(ierr);
3683906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT,(void (*)(void))PCBDDCMatMult_Private);CHKERRQ(ierr);
3684906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCMatMultTranspose_Private);CHKERRQ(ierr);
3685906d46d4SStefano Zampini       ierr = PetscNew(&change_ctx);CHKERRQ(ierr);
3686906d46d4SStefano Zampini       ierr = MatShellSetContext(pcbddc->new_global_mat,change_ctx);CHKERRQ(ierr);
3687906d46d4SStefano Zampini     } else {
3688906d46d4SStefano Zampini       ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
3689906d46d4SStefano Zampini       ierr = MatDestroy(&change_ctx->global_change);CHKERRQ(ierr);
3690906d46d4SStefano Zampini       ierr = VecDestroyVecs(2,&change_ctx->work);CHKERRQ(ierr);
3691906d46d4SStefano Zampini     }
3692906d46d4SStefano Zampini     if (!pcbddc->user_ChangeOfBasisMatrix) {
3693906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3694906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->ChangeOfBasisMatrix;
3695906d46d4SStefano Zampini     } else {
3696906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3697906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->user_ChangeOfBasisMatrix;
3698906d46d4SStefano Zampini     }
3699906d46d4SStefano Zampini     ierr = VecDuplicateVecs(pcis->vec1_global,2,&change_ctx->work);CHKERRQ(ierr);
3700906d46d4SStefano Zampini     ierr = MatSetUp(pcbddc->new_global_mat);CHKERRQ(ierr);
3701906d46d4SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3702906d46d4SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3703b9b85e73SStefano Zampini   }
3704a717540cSStefano Zampini 
37054f1b2e48SStefano Zampini   /* add pressure dofs to set of primal nodes for numbering purposes */
37064f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
37074f1b2e48SStefano Zampini     pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
37084f1b2e48SStefano Zampini     pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
3709019a44ceSStefano Zampini     pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
3710019a44ceSStefano Zampini     pcbddc->local_primal_size_cc++;
3711019a44ceSStefano Zampini     pcbddc->local_primal_size++;
3712019a44ceSStefano Zampini   }
3713019a44ceSStefano Zampini 
3714019a44ceSStefano Zampini   /* check if a new primal space has been introduced (also take into account benign trick) */
3715727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_TRUE;
3716727cdba6SStefano Zampini   if (olocal_primal_size == pcbddc->local_primal_size) {
37179f47a83aSStefano Zampini     ierr = PetscMemcmp(pcbddc->local_primal_ref_node,olocal_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt),&pcbddc->new_primal_space_local);CHKERRQ(ierr);
3718c1c8e736SStefano Zampini     pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
37190e6343abSStefano Zampini     if (!pcbddc->new_primal_space_local) {
37209f47a83aSStefano Zampini       ierr = PetscMemcmp(pcbddc->local_primal_ref_mult,olocal_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt),&pcbddc->new_primal_space_local);CHKERRQ(ierr);
3721727cdba6SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
3722727cdba6SStefano Zampini     }
37230e6343abSStefano Zampini   }
37240e6343abSStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
3725727cdba6SStefano Zampini   /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
3726727cdba6SStefano Zampini   ierr = MPI_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
3727727cdba6SStefano Zampini 
3728a717540cSStefano Zampini   /* flush dbg viewer */
3729b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
3730b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3731b8ffe317SStefano Zampini   }
3732a717540cSStefano Zampini 
3733e310c8b4SStefano Zampini   /* free workspace */
3734a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
37354641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
373608122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
37379162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
37389162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
373908122e43SStefano Zampini   } else {
37409162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
37419162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
37429162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
374308122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
374408122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
37459162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
37469162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
374708122e43SStefano Zampini   }
3748674ae819SStefano Zampini   PetscFunctionReturn(0);
3749674ae819SStefano Zampini }
3750674ae819SStefano Zampini 
3751674ae819SStefano Zampini #undef __FUNCT__
3752674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
3753674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
3754674ae819SStefano Zampini {
3755674ae819SStefano Zampini   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
3756674ae819SStefano Zampini   PC_IS       *pcis = (PC_IS*)pc->data;
3757674ae819SStefano Zampini   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
37587fb0e2dbSStefano Zampini   PetscInt    ierr,i,vertex_size,N;
3759674ae819SStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
3760674ae819SStefano Zampini 
3761674ae819SStefano Zampini   PetscFunctionBegin;
37628e61c736SStefano Zampini   /* Reset previously computed graph */
37638e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
3764674ae819SStefano Zampini   /* Init local Graph struct */
37657fb0e2dbSStefano Zampini   ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
37663bbff08aSStefano Zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,pcis->mapping,N);CHKERRQ(ierr);
3767674ae819SStefano Zampini 
3768575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
37695099eff2SStefano Zampini   if (pcbddc->mat_graph->nvtxs_csr && pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) {
37705099eff2SStefano 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);
3771575ad6abSStefano Zampini   }
37729577ea80SStefano Zampini 
3773674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
37744d379d7bSStefano Zampini   if (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) {
37754d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
37764d379d7bSStefano Zampini     PetscInt  nvtxs;
3777e496cd5dSStefano Zampini     PetscBool flg_row=PETSC_FALSE;
3778674ae819SStefano Zampini 
37794d379d7bSStefano Zampini     if (pcbddc->use_local_adj) {
37802fffb893SStefano Zampini 
37812fffb893SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
37822fffb893SStefano Zampini       if (flg_row) {
37834d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
3784b96c3477SStefano Zampini         pcbddc->computed_rowadj = PETSC_TRUE;
37852fffb893SStefano Zampini       }
37862fffb893SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
37879b28b941SStefano 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 */
37884d379d7bSStefano Zampini       IS                     is_dummy;
37894d379d7bSStefano Zampini       ISLocalToGlobalMapping l2gmap_dummy;
37904d379d7bSStefano Zampini       PetscInt               j,sum;
37914d379d7bSStefano Zampini       PetscInt               *cxadj,*cadjncy;
37924d379d7bSStefano Zampini       const PetscInt         *idxs;
37934d379d7bSStefano Zampini       PCBDDCGraph            graph;
37944d379d7bSStefano Zampini       PetscBT                is_on_boundary;
37954d379d7bSStefano Zampini 
37964d379d7bSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcis->n,0,1,&is_dummy);CHKERRQ(ierr);
37974d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
37984d379d7bSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
37994d379d7bSStefano Zampini       ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
38007fb0e2dbSStefano Zampini       ierr = PCBDDCGraphInit(graph,l2gmap_dummy,pcis->n);CHKERRQ(ierr);
38014d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
3802e496cd5dSStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
3803e496cd5dSStefano Zampini       if (flg_row) {
38044d379d7bSStefano Zampini         graph->xadj = xadj;
38054d379d7bSStefano Zampini         graph->adjncy = adjncy;
3806e496cd5dSStefano Zampini       }
38074d379d7bSStefano Zampini       ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
38084d379d7bSStefano Zampini       ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
3809e496cd5dSStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
38104d379d7bSStefano Zampini 
38114d379d7bSStefano Zampini       if (pcbddc->dbg_flag) {
38129b28b941SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] Found %d subdomains (local size %d)\n",PetscGlobalRank,graph->ncc,pcis->n);CHKERRQ(ierr);
38134d379d7bSStefano Zampini         for (i=0;i<graph->ncc;i++) {
38144d379d7bSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] %d cc size %d\n",PetscGlobalRank,i,graph->cptr[i+1]-graph->cptr[i]);CHKERRQ(ierr);
38154d379d7bSStefano Zampini         }
38164d379d7bSStefano Zampini       }
38174d379d7bSStefano Zampini 
3818e496cd5dSStefano Zampini       ierr = PetscBTCreate(pcis->n,&is_on_boundary);CHKERRQ(ierr);
38194d379d7bSStefano Zampini       ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
38204d379d7bSStefano Zampini       for (i=0;i<pcis->n_B;i++) {
38214d379d7bSStefano Zampini         ierr = PetscBTSet(is_on_boundary,idxs[i]);CHKERRQ(ierr);
38224d379d7bSStefano Zampini       }
38234d379d7bSStefano Zampini       ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
38244d379d7bSStefano Zampini 
3825e496cd5dSStefano Zampini       ierr = PetscCalloc1(pcis->n+1,&cxadj);CHKERRQ(ierr);
38264d379d7bSStefano Zampini       sum = 0;
38274d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
38284d379d7bSStefano Zampini         PetscInt sizecc = 0;
38294d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
38304d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
38314d379d7bSStefano Zampini             sizecc++;
38324d379d7bSStefano Zampini           }
38334d379d7bSStefano Zampini         }
38344d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
38354d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
38364d379d7bSStefano Zampini             cxadj[graph->queue[j]] = sizecc;
38374d379d7bSStefano Zampini           }
38384d379d7bSStefano Zampini         }
38394d379d7bSStefano Zampini         sum += sizecc*sizecc;
38404d379d7bSStefano Zampini       }
38414d379d7bSStefano Zampini       ierr = PetscMalloc1(sum,&cadjncy);CHKERRQ(ierr);
38424d379d7bSStefano Zampini       sum = 0;
3843e496cd5dSStefano Zampini       for (i=0;i<pcis->n;i++) {
38444d379d7bSStefano Zampini         PetscInt temp = cxadj[i];
38454d379d7bSStefano Zampini         cxadj[i] = sum;
38464d379d7bSStefano Zampini         sum += temp;
38474d379d7bSStefano Zampini       }
3848e496cd5dSStefano Zampini       cxadj[pcis->n] = sum;
38494d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
38504d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
38514d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
38524d379d7bSStefano Zampini             PetscInt k,sizecc = 0;
38534d379d7bSStefano Zampini             for (k=graph->cptr[i];k<graph->cptr[i+1];k++) {
38544d379d7bSStefano Zampini               if (PetscBTLookup(is_on_boundary,graph->queue[k])) {
38554d379d7bSStefano Zampini                 cadjncy[cxadj[graph->queue[j]]+sizecc]=graph->queue[k];
38564d379d7bSStefano Zampini                 sizecc++;
38574d379d7bSStefano Zampini               }
38584d379d7bSStefano Zampini             }
38594d379d7bSStefano Zampini           }
38604d379d7bSStefano Zampini         }
38614d379d7bSStefano Zampini       }
38629b28b941SStefano Zampini       if (sum) {
3863e496cd5dSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,pcis->n,cxadj,cadjncy,PETSC_OWN_POINTER);CHKERRQ(ierr);
38644d379d7bSStefano Zampini       } else {
38654d379d7bSStefano Zampini         ierr = PetscFree(cxadj);CHKERRQ(ierr);
38664d379d7bSStefano Zampini         ierr = PetscFree(cadjncy);CHKERRQ(ierr);
38674d379d7bSStefano Zampini       }
38684d379d7bSStefano Zampini       graph->xadj = 0;
38694d379d7bSStefano Zampini       graph->adjncy = 0;
38704d379d7bSStefano Zampini       ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
38714d379d7bSStefano Zampini       ierr = PetscBTDestroy(&is_on_boundary);CHKERRQ(ierr);
38724d379d7bSStefano Zampini     }
3873674ae819SStefano Zampini   }
38749b28b941SStefano Zampini   if (pcbddc->dbg_flag) {
38759b28b941SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3876674ae819SStefano Zampini   }
3877674ae819SStefano Zampini 
387863602bcaSStefano Zampini   /* Set default dofs' splitting if no information has been provided by the user with PCBDDCSetDofsSplitting or PCBDDCSetDofsSplittingLocal */
3879674ae819SStefano Zampini   vertex_size = 1;
388063602bcaSStefano Zampini   if (pcbddc->user_provided_isfordofs) {
388163602bcaSStefano Zampini     if (pcbddc->n_ISForDofs) { /* need to convert from global to local and remove references to global dofs splitting */
388295ecbf38SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
388363602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
3884e176bc59SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
388563602bcaSStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
3886674ae819SStefano Zampini       }
388763602bcaSStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
388863602bcaSStefano Zampini       pcbddc->n_ISForDofs = 0;
388963602bcaSStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
3890674ae819SStefano Zampini     }
389163602bcaSStefano Zampini     /* mat block size as vertex size (used for elasticity with rigid body modes as nearnullspace) */
3892674ae819SStefano Zampini     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
389363602bcaSStefano Zampini   } else {
389463602bcaSStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering */
389563602bcaSStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->n_ISForDofsLocal);CHKERRQ(ierr);
3896854ce69bSBarry Smith       ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
389763602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
389863602bcaSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),pcis->n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
389963602bcaSStefano Zampini       }
390063602bcaSStefano Zampini     }
3901674ae819SStefano Zampini   }
3902674ae819SStefano Zampini 
3903674ae819SStefano Zampini   /* Setup of Graph */
3904785d1243SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) { /* need to convert from global to local */
3905e176bc59SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
3906785d1243SStefano Zampini   }
3907785d1243SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) { /* need to convert from global to local */
3908e176bc59SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
3909785d1243SStefano Zampini   }
3910*30368db7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) { /* need to convert from global to local */
3911*30368db7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
3912*30368db7SStefano Zampini   }
3913*30368db7SStefano Zampini   ierr = PCBDDCGraphSetUp(pcbddc->mat_graph,vertex_size,pcbddc->NeumannBoundariesLocal,pcbddc->DirichletBoundariesLocal,pcbddc->n_ISForDofsLocal,pcbddc->ISForDofsLocal,pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
3914674ae819SStefano Zampini 
39154f1b2e48SStefano Zampini   /* attach info on disconnected subdomains if present */
39164f1b2e48SStefano Zampini   if (pcbddc->n_local_subs) {
39174f1b2e48SStefano Zampini     PetscInt *local_subs;
39184f1b2e48SStefano Zampini 
39194f1b2e48SStefano Zampini     ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
39204f1b2e48SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
39214f1b2e48SStefano Zampini       const PetscInt *idxs;
39224f1b2e48SStefano Zampini       PetscInt       nl,j;
39234f1b2e48SStefano Zampini 
39244f1b2e48SStefano Zampini       ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
39254f1b2e48SStefano Zampini       ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
39264f1b2e48SStefano Zampini       for (j=0;j<nl;j++) {
39274f1b2e48SStefano Zampini         local_subs[idxs[j]] = i;
39284f1b2e48SStefano Zampini       }
39294f1b2e48SStefano Zampini       ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
39304f1b2e48SStefano Zampini     }
39314f1b2e48SStefano Zampini     pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
39324f1b2e48SStefano Zampini     pcbddc->mat_graph->local_subs = local_subs;
39334f1b2e48SStefano Zampini   }
39344f1b2e48SStefano Zampini 
3935674ae819SStefano Zampini   /* Graph's connected components analysis */
3936674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
3937674ae819SStefano Zampini 
3938674ae819SStefano Zampini   /* print some info to stdout */
3939674ae819SStefano Zampini   if (pcbddc->dbg_flag) {
3940302440fdSBarry Smith     ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,viewer);CHKERRQ(ierr);
3941674ae819SStefano Zampini   }
3942fb180af4SStefano Zampini 
3943fb180af4SStefano Zampini   /* mark topography has done */
3944fb180af4SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
3945674ae819SStefano Zampini   PetscFunctionReturn(0);
3946674ae819SStefano Zampini }
3947674ae819SStefano Zampini 
3948dc456d91SStefano Zampini /* given an index sets possibly with holes, renumbers the indexes removing the holes */
3949674ae819SStefano Zampini #undef __FUNCT__
3950674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSubsetNumbering"
3951dc456d91SStefano Zampini PetscErrorCode PCBDDCSubsetNumbering(IS subset, IS subset_mult, PetscInt *N_n, IS *subset_n)
3952674ae819SStefano Zampini {
3953dc456d91SStefano Zampini   PetscSF        sf;
3954dc456d91SStefano Zampini   PetscLayout    map;
3955dc456d91SStefano Zampini   const PetscInt *idxs;
3956dc456d91SStefano Zampini   PetscInt       *leaf_data,*root_data,*gidxs;
3957dc456d91SStefano Zampini   PetscInt       N,n,i,lbounds[2],gbounds[2],Nl;
3958dc456d91SStefano Zampini   PetscInt       n_n,nlocals,start,first_index;
3959dc456d91SStefano Zampini   PetscMPIInt    commsize;
3960674ae819SStefano Zampini   PetscBool      first_found;
3961674ae819SStefano Zampini   PetscErrorCode ierr;
3962674ae819SStefano Zampini 
3963674ae819SStefano Zampini   PetscFunctionBegin;
3964dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset,&n);CHKERRQ(ierr);
3965dc456d91SStefano Zampini   if (subset_mult) {
3966dc456d91SStefano Zampini     PetscCheckSameComm(subset,1,subset_mult,2);
3967dc456d91SStefano Zampini     ierr = ISGetLocalSize(subset,&i);CHKERRQ(ierr);
3968dc456d91SStefano Zampini     if (i != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local subset and multiplicity sizes don't match! %d != %d",n,i);
3969674ae819SStefano Zampini   }
3970dc456d91SStefano Zampini   /* create workspace layout for computing global indices of subset */
3971dc456d91SStefano Zampini   ierr = ISGetIndices(subset,&idxs);CHKERRQ(ierr);
3972dc456d91SStefano Zampini   lbounds[0] = lbounds[1] = 0;
3973dc456d91SStefano Zampini   for (i=0;i<n;i++) {
3974dc456d91SStefano Zampini     if (idxs[i] < lbounds[0]) lbounds[0] = idxs[i];
3975dc456d91SStefano Zampini     else if (idxs[i] > lbounds[1]) lbounds[1] = idxs[i];
3976674ae819SStefano Zampini   }
3977dc456d91SStefano Zampini   lbounds[0] = -lbounds[0];
3978dc456d91SStefano Zampini   ierr = MPI_Allreduce(lbounds,gbounds,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
3979dc456d91SStefano Zampini   gbounds[0] = -gbounds[0];
3980dc456d91SStefano Zampini   N = gbounds[1] - gbounds[0] + 1;
3981dc456d91SStefano Zampini   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)subset),&map);CHKERRQ(ierr);
3982dc456d91SStefano Zampini   ierr = PetscLayoutSetBlockSize(map,1);CHKERRQ(ierr);
3983dc456d91SStefano Zampini   ierr = PetscLayoutSetSize(map,N);CHKERRQ(ierr);
3984dc456d91SStefano Zampini   ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
3985dc456d91SStefano Zampini   ierr = PetscLayoutGetLocalSize(map,&Nl);CHKERRQ(ierr);
3986dc456d91SStefano Zampini 
3987dc456d91SStefano Zampini   /* create sf : leaf_data == multiplicity of indexes, root data == global index in layout */
3988dc456d91SStefano Zampini   ierr = PetscMalloc2(n,&leaf_data,Nl,&root_data);CHKERRQ(ierr);
3989dc456d91SStefano Zampini   if (subset_mult) {
3990dc456d91SStefano Zampini     const PetscInt* idxs_mult;
3991dc456d91SStefano Zampini 
3992dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
3993dc456d91SStefano Zampini     ierr = PetscMemcpy(leaf_data,idxs_mult,n*sizeof(PetscInt));CHKERRQ(ierr);
3994dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
3995674ae819SStefano Zampini   } else {
3996dc456d91SStefano Zampini     for (i=0;i<n;i++) leaf_data[i] = 1;
3997674ae819SStefano Zampini   }
3998dc456d91SStefano Zampini   /* local size of new subset */
3999dc456d91SStefano Zampini   n_n = 0;
4000dc456d91SStefano Zampini   for (i=0;i<n;i++) n_n += leaf_data[i];
4001dc456d91SStefano Zampini 
4002dc456d91SStefano Zampini   /* global indexes in layout */
4003dc456d91SStefano Zampini   ierr = PetscMalloc1(n_n,&gidxs);CHKERRQ(ierr); /* allocating possibly extra space in gidxs which will be used later */
4004dc456d91SStefano Zampini   for (i=0;i<n;i++) gidxs[i] = idxs[i] - gbounds[0];
4005dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset,&idxs);CHKERRQ(ierr);
4006dc456d91SStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)subset),&sf);CHKERRQ(ierr);
4007dc456d91SStefano Zampini   ierr = PetscSFSetGraphLayout(sf,map,n,NULL,PETSC_COPY_VALUES,gidxs);CHKERRQ(ierr);
4008dc456d91SStefano Zampini   ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr);
4009dc456d91SStefano Zampini 
4010dc456d91SStefano Zampini   /* reduce from leaves to roots */
4011dc456d91SStefano Zampini   ierr = PetscMemzero(root_data,Nl*sizeof(PetscInt));CHKERRQ(ierr);
401264a8e5bcSStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
401364a8e5bcSStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
4014dc456d91SStefano Zampini 
4015dc456d91SStefano Zampini   /* count indexes in local part of layout */
4016674ae819SStefano Zampini   nlocals = 0;
4017674ae819SStefano Zampini   first_index = -1;
4018674ae819SStefano Zampini   first_found = PETSC_FALSE;
4019dc456d91SStefano Zampini   for (i=0;i<Nl;i++) {
4020dc456d91SStefano Zampini     if (!first_found && root_data[i]) {
4021674ae819SStefano Zampini       first_found = PETSC_TRUE;
4022674ae819SStefano Zampini       first_index = i;
4023674ae819SStefano Zampini     }
4024dc456d91SStefano Zampini     nlocals += root_data[i];
4025674ae819SStefano Zampini   }
4026dc456d91SStefano Zampini 
4027dc456d91SStefano Zampini   /* cumulative of number of indexes and size of subset without holes */
40285fa240b1SStefano Zampini #if defined(PETSC_HAVE_MPI_EXSCAN)
4029dc456d91SStefano Zampini   start = 0;
403064a8e5bcSStefano Zampini   ierr = MPI_Exscan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
40315fa240b1SStefano Zampini #else
403264a8e5bcSStefano Zampini   ierr = MPI_Scan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
40335fa240b1SStefano Zampini   start = start-nlocals;
40345fa240b1SStefano Zampini #endif
40355fa240b1SStefano Zampini 
4036dc456d91SStefano Zampini   if (N_n) { /* compute total size of new subset if requested */
4037dc456d91SStefano Zampini     *N_n = start + nlocals;
4038dc456d91SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)subset),&commsize);CHKERRQ(ierr);
4039dc456d91SStefano Zampini     ierr = MPI_Bcast(N_n,1,MPIU_INT,commsize-1,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
4040674ae819SStefano Zampini   }
40415fa240b1SStefano Zampini 
40425fa240b1SStefano Zampini   /* adapt root data with cumulative */
4043674ae819SStefano Zampini   if (first_found) {
4044dc456d91SStefano Zampini     PetscInt old_index;
4045dc456d91SStefano Zampini 
4046dc456d91SStefano Zampini     root_data[first_index] += start;
4047674ae819SStefano Zampini     old_index = first_index;
4048dc456d91SStefano Zampini     for (i=first_index+1;i<Nl;i++) {
4049dc456d91SStefano Zampini       if (root_data[i]) {
4050dc456d91SStefano Zampini         root_data[i] += root_data[old_index];
4051674ae819SStefano Zampini         old_index = i;
4052674ae819SStefano Zampini       }
4053674ae819SStefano Zampini     }
4054674ae819SStefano Zampini   }
4055dc456d91SStefano Zampini 
4056dc456d91SStefano Zampini   /* from roots to leaves */
4057dc456d91SStefano Zampini   ierr = PetscSFBcastBegin(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
4058dc456d91SStefano Zampini   ierr = PetscSFBcastEnd(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
4059dc456d91SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
4060dc456d91SStefano Zampini 
4061dc456d91SStefano Zampini   /* create new IS with global indexes without holes */
4062dc456d91SStefano Zampini   if (subset_mult) {
4063dc456d91SStefano Zampini     const PetscInt* idxs_mult;
4064dc456d91SStefano Zampini     PetscInt        cum;
4065dc456d91SStefano Zampini 
4066dc456d91SStefano Zampini     cum = 0;
4067dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4068dc456d91SStefano Zampini     for (i=0;i<n;i++) {
4069dc456d91SStefano Zampini       PetscInt j;
4070dc456d91SStefano Zampini       for (j=0;j<idxs_mult[i];j++) gidxs[cum++] = leaf_data[i] - idxs_mult[i] + j;
4071674ae819SStefano Zampini     }
4072dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4073674ae819SStefano Zampini   } else {
4074dc456d91SStefano Zampini     for (i=0;i<n;i++) {
4075dc456d91SStefano Zampini       gidxs[i] = leaf_data[i]-1;
4076674ae819SStefano Zampini     }
4077674ae819SStefano Zampini   }
4078dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)subset),n_n,gidxs,PETSC_OWN_POINTER,subset_n);CHKERRQ(ierr);
4079dc456d91SStefano Zampini   ierr = PetscFree2(leaf_data,root_data);CHKERRQ(ierr);
4080674ae819SStefano Zampini   PetscFunctionReturn(0);
4081674ae819SStefano Zampini }
40829a7d3425SStefano Zampini 
40839a7d3425SStefano Zampini #undef __FUNCT__
40849a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
40859a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
40869a7d3425SStefano Zampini {
40879a7d3425SStefano Zampini   PetscInt       i,j;
40889a7d3425SStefano Zampini   PetscScalar    *alphas;
40899a7d3425SStefano Zampini   PetscErrorCode ierr;
40909a7d3425SStefano Zampini 
40919a7d3425SStefano Zampini   PetscFunctionBegin;
40929a7d3425SStefano Zampini   /* this implements stabilized Gram-Schmidt */
4093785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
40949a7d3425SStefano Zampini   for (i=0;i<n;i++) {
40959a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
40969a7d3425SStefano Zampini     if (i<n) { ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],&alphas[i+1]);CHKERRQ(ierr); }
40979a7d3425SStefano Zampini     for (j=i+1;j<n;j++) { ierr = VecAXPY(vecs[j],PetscConj(-alphas[j]),vecs[i]);CHKERRQ(ierr); }
40989a7d3425SStefano Zampini   }
40999a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
41009a7d3425SStefano Zampini   PetscFunctionReturn(0);
41019a7d3425SStefano Zampini }
41029a7d3425SStefano Zampini 
4103e7931f94SStefano Zampini #undef __FUNCT__
410470cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
4105b0c7d250SStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt n_subdomains, PetscInt redprocs, IS* is_sends)
4106e7931f94SStefano Zampini {
410752e5ac9dSStefano Zampini   IS             ranks_send_to;
4108e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
4109e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
411052e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
411152e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
41123837a79fSStefano Zampini   PetscInt       i,local_size,threshold=0;
41132b510759SStefano Zampini   PetscBool      use_vwgt=PETSC_FALSE,use_square=PETSC_FALSE;
4114e7931f94SStefano Zampini   PetscSubcomm   subcomm;
411552e5ac9dSStefano Zampini   PetscErrorCode ierr;
4116a57a6d2fSStefano Zampini 
4117e7931f94SStefano Zampini   PetscFunctionBegin;
41182b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_square",&use_square,NULL);CHKERRQ(ierr);
41192b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
41202b510759SStefano Zampini   ierr = PetscOptionsGetInt(NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
4121e7931f94SStefano Zampini 
4122e7931f94SStefano Zampini   /* Get info on mapping */
41233bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&local_size);CHKERRQ(ierr);
41243bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
4125e7931f94SStefano Zampini 
4126e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
4127785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
4128e7931f94SStefano Zampini   xadj[0] = 0;
4129e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
4130785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
4131785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
4132e7931f94SStefano Zampini 
41332b510759SStefano Zampini   if (threshold) {
4134d023bfaeSStefano Zampini     PetscInt xadj_count = 0;
41352b510759SStefano Zampini     for (i=1;i<n_neighs;i++) {
4136d023bfaeSStefano Zampini       if (n_shared[i] > threshold) {
4137d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
4138d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
4139d023bfaeSStefano Zampini         xadj_count++;
4140e7931f94SStefano Zampini       }
4141e7931f94SStefano Zampini     }
4142d023bfaeSStefano Zampini     xadj[1] = xadj_count;
4143c8587f34SStefano Zampini   } else {
4144e7931f94SStefano Zampini     if (xadj[1]) {
4145e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy,&neighs[1],xadj[1]*sizeof(*adjncy));CHKERRQ(ierr);
4146e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy_wgt,&n_shared[1],xadj[1]*sizeof(*adjncy_wgt));CHKERRQ(ierr);
4147c8587f34SStefano Zampini     }
4148e7931f94SStefano Zampini   }
41493bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
4150e7931f94SStefano Zampini   if (use_square) {
4151e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
4152e7931f94SStefano Zampini       adjncy_wgt[i] = adjncy_wgt[i]*adjncy_wgt[i];
4153e7931f94SStefano Zampini     }
4154e7931f94SStefano Zampini   }
4155e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
4156e7931f94SStefano Zampini 
41573837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
4158e7931f94SStefano Zampini 
4159e7931f94SStefano Zampini   /*
4160e7931f94SStefano Zampini     Restrict work on active processes only.
4161e7931f94SStefano Zampini   */
4162e7931f94SStefano Zampini   ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&subcomm);CHKERRQ(ierr);
4163e7931f94SStefano Zampini   ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
4164e7931f94SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
41652b510759SStefano Zampini   ierr = PetscMPIIntCast(!local_size,&color);CHKERRQ(ierr);
4166d3531aaaSJed Brown   ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
4167e7931f94SStefano Zampini   if (color) {
4168e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
4169e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
4170e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
4171c8587f34SStefano Zampini   } else {
417252e5ac9dSStefano Zampini     Mat             subdomain_adj;
417352e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
417452e5ac9dSStefano Zampini     MatPartitioning partitioner;
417552e5ac9dSStefano Zampini     PetscInt        prank,rstart=0,rend=0;
417652e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
4177b0c7d250SStefano Zampini     PetscBool       aggregate;
4178b0c7d250SStefano Zampini 
4179306c2d5bSBarry Smith     ierr = MPI_Comm_size(PetscSubcommChild(subcomm),&size);CHKERRQ(ierr);
4180785e854fSJed Brown     ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
4181e7931f94SStefano Zampini     prank = rank;
4182306c2d5bSBarry Smith     ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,PetscSubcommChild(subcomm));CHKERRQ(ierr);
41838002ef2cSStefano Zampini     /*
4184e7931f94SStefano Zampini     for (i=0;i<size;i++) {
4185e7931f94SStefano Zampini       PetscPrintf(subcomm->comm,"oldranks[%d] = %d\n",i,oldranks[i]);
4186c8587f34SStefano Zampini     }
41878002ef2cSStefano Zampini     */
4188e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
4189e7931f94SStefano Zampini       ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
4190c8587f34SStefano Zampini     }
4191e7931f94SStefano Zampini     ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
4192b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
4193b0c7d250SStefano Zampini     if (aggregate) {
4194b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
4195b0c7d250SStefano Zampini       PetscMPIInt nrank;
4196b0c7d250SStefano Zampini       PetscScalar *vals;
4197b0c7d250SStefano Zampini 
4198b0c7d250SStefano Zampini       ierr = MPI_Comm_rank(PetscSubcommChild(subcomm),&nrank);CHKERRQ(ierr);
4199b0c7d250SStefano Zampini       lrows = 0;
4200b0c7d250SStefano Zampini       if (nrank<redprocs) {
4201b0c7d250SStefano Zampini         lrows = size/redprocs;
4202b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
4203b0c7d250SStefano Zampini       }
42045fa240b1SStefano Zampini       ierr = MatCreateAIJ(PetscSubcommChild(subcomm),lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
4205b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
4206b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
4207b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
4208b0c7d250SStefano Zampini       row = nrank;
4209b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
4210b0c7d250SStefano Zampini       cols = adjncy;
4211b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
4212b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
4213b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
4214b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4215b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
421652e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
421752e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
421852e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
4219b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
4220b0c7d250SStefano Zampini     } else {
4221306c2d5bSBarry Smith       ierr = MatCreateMPIAdj(PetscSubcommChild(subcomm),1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
4222b0c7d250SStefano Zampini     }
422322b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
4224e7931f94SStefano Zampini 
4225e7931f94SStefano Zampini     /* Partition */
4226306c2d5bSBarry Smith     ierr = MatPartitioningCreate(PetscSubcommChild(subcomm),&partitioner);CHKERRQ(ierr);
4227e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
4228e7931f94SStefano Zampini     if (use_vwgt) {
42293837a79fSStefano Zampini       ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
4230e7931f94SStefano Zampini       v_wgt[0] = local_size;
4231e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
4232c8587f34SStefano Zampini     }
423328143c3dSStefano Zampini     n_subdomains = PetscMin((PetscInt)size,n_subdomains);
423428143c3dSStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,n_subdomains);CHKERRQ(ierr);
4235e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
4236e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
423722b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
4238e7931f94SStefano Zampini 
423952e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
424052e5ac9dSStefano Zampini     ierr = PCBDDCSubsetNumbering(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
424152e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
424252e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4243b0c7d250SStefano Zampini     if (!redprocs) {
4244b0c7d250SStefano Zampini       ranks_send_to_idx[0] = oldranks[is_indices[0]];
424528143c3dSStefano Zampini     } else {
4246b0c7d250SStefano Zampini       PetscInt    idxs[1];
4247b0c7d250SStefano Zampini       PetscMPIInt tag;
4248b0c7d250SStefano Zampini       MPI_Request *reqs;
4249b0c7d250SStefano Zampini 
4250b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
4251b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
4252b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
4253b0c7d250SStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,PetscSubcommChild(subcomm),&reqs[i-rstart]);CHKERRQ(ierr);
425428143c3dSStefano Zampini       }
4255b0c7d250SStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,PetscSubcommChild(subcomm),MPI_STATUS_IGNORE);CHKERRQ(ierr);
4256b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4257b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
4258b0c7d250SStefano Zampini       ranks_send_to_idx[0] = oldranks[idxs[0]];
4259e7931f94SStefano Zampini     }
426052e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4261e7931f94SStefano Zampini     /* clean up */
4262e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
426352e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
4264e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
4265e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
4266e7931f94SStefano Zampini   }
4267e7931f94SStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
4268e7931f94SStefano Zampini 
4269e7931f94SStefano Zampini   /* assemble parallel IS for sends */
4270e7931f94SStefano Zampini   i = 1;
4271e7931f94SStefano Zampini   if (color) i=0;
4272e7931f94SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,&ranks_send_to);CHKERRQ(ierr);
4273e7931f94SStefano Zampini   /* get back IS */
4274e7931f94SStefano Zampini   *is_sends = ranks_send_to;
4275e7931f94SStefano Zampini   PetscFunctionReturn(0);
4276e7931f94SStefano Zampini }
4277e7931f94SStefano Zampini 
4278e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
4279e7931f94SStefano Zampini 
4280e7931f94SStefano Zampini #undef __FUNCT__
4281e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
428253a05cb3SStefano 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[])
4283e7931f94SStefano Zampini {
428470cf5478SStefano Zampini   Mat                    local_mat;
4285e7931f94SStefano Zampini   IS                     is_sends_internal;
42869d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
428728143c3dSStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals;
42889d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
4289e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
4290e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
4291e7931f94SStefano Zampini   const PetscInt*        is_indices;
4292e7931f94SStefano Zampini   MatType                new_local_type;
4293e7931f94SStefano Zampini   /* buffers */
4294e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
429528143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
42969d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
4297e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
4298e7931f94SStefano Zampini   /* MPI */
429928143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
430028143c3dSStefano Zampini   PetscSubcomm           subcomm;
4301e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
430228143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
430328143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
430428143c3dSStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,source_dest;
430528143c3dSStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals;
430628143c3dSStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals;
4307e7931f94SStefano Zampini   PetscErrorCode         ierr;
4308e7931f94SStefano Zampini 
4309e7931f94SStefano Zampini   PetscFunctionBegin;
431028143c3dSStefano Zampini   /* TODO: add missing checks */
431128143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
431228143c3dSStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
431328143c3dSStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,5);
431428143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,7);
4315e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
431628143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
4317e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
4318e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
4319e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
4320e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
4321e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
432228143c3dSStefano Zampini   if (reuse == MAT_REUSE_MATRIX && *mat_n) {
432370cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
432470cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
432528143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
432670cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
432770cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
432870cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
432970cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
433070cf5478SStefano Zampini   }
4331e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
4332e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
4333e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
4334e7931f94SStefano Zampini   if (!is_sends) {
433528143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
4336b0c7d250SStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,n_subdomains,0,&is_sends_internal);CHKERRQ(ierr);
4337c8587f34SStefano Zampini   } else {
4338e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
4339e7931f94SStefano Zampini     is_sends_internal = is_sends;
4340c8587f34SStefano Zampini   }
4341e7931f94SStefano Zampini 
4342e7931f94SStefano Zampini   /* get comm */
4343a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
4344e7931f94SStefano Zampini 
4345e7931f94SStefano Zampini   /* compute number of sends */
4346e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
4347e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
4348e7931f94SStefano Zampini 
4349e7931f94SStefano Zampini   /* compute number of receives */
4350e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
4351785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
4352e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
4353e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
4354e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
4355e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
4356e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
4357e7931f94SStefano Zampini 
435828143c3dSStefano Zampini   /* restrict comm if requested */
435928143c3dSStefano Zampini   subcomm = 0;
436028143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
436128143c3dSStefano Zampini   if (restrict_comm) {
4362779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
4363779c1cceSStefano Zampini 
436428143c3dSStefano Zampini     color = 0;
436553a05cb3SStefano Zampini     if (restrict_full) {
436653a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
436753a05cb3SStefano Zampini     } else {
436853a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
436953a05cb3SStefano Zampini     }
437028143c3dSStefano Zampini     ierr = MPI_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
437128143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
437228143c3dSStefano Zampini     /* check if reuse has been requested */
437328143c3dSStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
437428143c3dSStefano Zampini       if (*mat_n) {
437528143c3dSStefano Zampini         PetscMPIInt subcommsize2;
437628143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
437728143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
437828143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
437928143c3dSStefano Zampini       } else {
438028143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
438128143c3dSStefano Zampini       }
438228143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
4383779c1cceSStefano Zampini       PetscMPIInt rank;
4384779c1cceSStefano Zampini 
4385779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
438628143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
438728143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
438828143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
4389306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
439028143c3dSStefano Zampini     }
439128143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
439228143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
439328143c3dSStefano Zampini   } else {
439428143c3dSStefano Zampini     comm_n = comm;
439528143c3dSStefano Zampini   }
439628143c3dSStefano Zampini 
4397e7931f94SStefano Zampini   /* prepare send/receive buffers */
4398785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
4399e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
4400785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
4401e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
440228143c3dSStefano Zampini   if (nis) {
4403854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
440428143c3dSStefano Zampini   }
4405e7931f94SStefano Zampini 
440628143c3dSStefano Zampini   /* Get data from local matrices */
4407e7931f94SStefano Zampini   if (!isdense) {
4408a26c9d0eSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
4409e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
4410e7931f94SStefano Zampini     /*
4411e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
4412e7931f94SStefano Zampini        send_buffer_idxs should contain:
4413e7931f94SStefano Zampini        - MatType_PRIVATE type
4414e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
4415e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
4416e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
4417e7931f94SStefano Zampini     */
4418e7931f94SStefano Zampini   } else {
4419e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
44203bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
4421854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
4422e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
4423e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
44243bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
4425e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
44263bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
4427e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
4428e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
4429e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
4430e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
4431c8587f34SStefano Zampini     }
4432c8587f34SStefano Zampini   }
4433e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
443428143c3dSStefano Zampini   /* additional is (if any) */
443528143c3dSStefano Zampini   if (nis) {
443628143c3dSStefano Zampini     PetscMPIInt psum;
443728143c3dSStefano Zampini     PetscInt j;
443828143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
443928143c3dSStefano Zampini       PetscInt plen;
444028143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
444128143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
444228143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
444328143c3dSStefano Zampini     }
4444854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
444528143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
444628143c3dSStefano Zampini       PetscInt plen;
444728143c3dSStefano Zampini       const PetscInt *is_array_idxs;
444828143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
444928143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
445028143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
445128143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
445228143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
445328143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
445428143c3dSStefano Zampini     }
445528143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
445628143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
445728143c3dSStefano Zampini     }
445828143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
445928143c3dSStefano Zampini   }
446028143c3dSStefano Zampini 
4461e7931f94SStefano Zampini   buf_size_idxs = 0;
4462e7931f94SStefano Zampini   buf_size_vals = 0;
446328143c3dSStefano Zampini   buf_size_idxs_is = 0;
4464e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4465e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
4466e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
446728143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
4468e7931f94SStefano Zampini   }
4469785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
4470785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
447195ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
4472e7931f94SStefano Zampini 
4473e7931f94SStefano Zampini   /* get new tags for clean communications */
4474e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
4475e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
447628143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
4477e7931f94SStefano Zampini 
4478e7931f94SStefano Zampini   /* allocate for requests */
4479785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
4480785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
448195ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
4482785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
4483785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
448495ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
4485e7931f94SStefano Zampini 
4486e7931f94SStefano Zampini   /* communications */
4487e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
4488e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
448928143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
4490e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4491e7931f94SStefano Zampini     source_dest = onodes[i];
4492e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
4493e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
4494e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4495e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
449628143c3dSStefano Zampini     if (nis) {
449728143c3dSStefano 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);
449828143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
449928143c3dSStefano Zampini     }
4500e7931f94SStefano Zampini   }
4501e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
4502e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
4503e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
4504e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
450528143c3dSStefano Zampini     if (nis) {
450628143c3dSStefano 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);
450728143c3dSStefano Zampini     }
4508e7931f94SStefano Zampini   }
4509e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
4510e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
4511e7931f94SStefano Zampini 
4512e7931f94SStefano Zampini   /* assemble new l2g map */
4513e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);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     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
4518e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4519e7931f94SStefano Zampini   }
45209d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
4521e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
45229d30be91SStefano Zampini   new_local_rows = 0;
4523e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
45249d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
45259d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
4526e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4527e7931f94SStefano Zampini   }
45289d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
45299d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
4530e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
4531e7931f94SStefano Zampini 
4532e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
4533e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
4534e7931f94SStefano 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) */
4535e7931f94SStefano Zampini   if (n_recvs) {
453628143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
4537e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
4538e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
4539e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
4540e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
4541e7931f94SStefano Zampini         break;
4542e7931f94SStefano Zampini       }
4543e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
4544e7931f94SStefano Zampini     }
4545e7931f94SStefano Zampini     switch (new_local_type_private) {
454628143c3dSStefano Zampini       case MATDENSE_PRIVATE:
454728143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
4548e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
4549e7931f94SStefano Zampini           bs = 1;
455028143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
455128143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
455228143c3dSStefano Zampini           bs = 1;
455328143c3dSStefano Zampini         }
4554e7931f94SStefano Zampini         break;
4555e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
4556e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
4557e7931f94SStefano Zampini         bs = 1;
4558e7931f94SStefano Zampini         break;
4559e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
4560e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
4561e7931f94SStefano Zampini         break;
4562e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
4563e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
4564e7931f94SStefano Zampini         break;
4565e7931f94SStefano Zampini       default:
45669d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
4567e7931f94SStefano Zampini         break;
4568e7931f94SStefano Zampini     }
456928143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
457028143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
457128143c3dSStefano Zampini     bs = 1;
4572e7931f94SStefano Zampini   }
4573e7931f94SStefano Zampini 
457470cf5478SStefano Zampini   /* create MATIS object if needed */
457570cf5478SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
4576e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
4577e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
457870cf5478SStefano Zampini   } else {
457970cf5478SStefano Zampini     /* it also destroys the local matrices */
458070cf5478SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
458170cf5478SStefano Zampini   }
458270cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
4583e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
45849d30be91SStefano Zampini 
45859d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
45869d30be91SStefano Zampini 
45879d30be91SStefano Zampini   /* Global to local map of received indices */
45889d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
45899d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
45909d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
45919d30be91SStefano Zampini 
45929d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
45939d30be91SStefano Zampini   buf_size_idxs = 0;
45949d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
45959d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
45969d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
45979d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
45989d30be91SStefano Zampini   }
45999d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
46009d30be91SStefano Zampini 
46019d30be91SStefano Zampini   /* set preallocation */
46029d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
46039d30be91SStefano Zampini   if (!newisdense) {
46049d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
46059d30be91SStefano Zampini 
46069d30be91SStefano Zampini     ptr_vals = recv_buffer_vals;
46079d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
46089d30be91SStefano Zampini     if (n_recvs) {
46099d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
46109d30be91SStefano Zampini     }
46119d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
46129d30be91SStefano Zampini       PetscInt j;
46139d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
46149d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
46159d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
46169d30be91SStefano Zampini         }
46179d30be91SStefano Zampini       } else {
46189d30be91SStefano Zampini         /* TODO */
46199d30be91SStefano Zampini       }
46209d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
46219d30be91SStefano Zampini     }
46229d30be91SStefano Zampini     if (new_local_nnz) {
46239d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
46249d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
46259d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
46269d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
46279d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
46289d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
46299d30be91SStefano Zampini     } else {
46309d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
46319d30be91SStefano Zampini     }
46329d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
46339d30be91SStefano Zampini   } else {
46349d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
46359d30be91SStefano Zampini   }
4636e7931f94SStefano Zampini 
4637e7931f94SStefano Zampini   /* set values */
4638e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
46399d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
4640e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4641e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
4642e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
46439d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
4644e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
4645e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
4646e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
464728143c3dSStefano Zampini     } else {
464828143c3dSStefano Zampini       /* TODO */
4649e7931f94SStefano Zampini     }
4650e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4651e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
4652e7931f94SStefano Zampini   }
4653e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4654e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
465570cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
465670cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
46579d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
46589d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
4659e7931f94SStefano Zampini 
4660dfd14d43SStefano Zampini #if 0
466128143c3dSStefano Zampini   if (!restrict_comm) { /* check */
4662e7931f94SStefano Zampini     Vec       lvec,rvec;
4663e7931f94SStefano Zampini     PetscReal infty_error;
4664e7931f94SStefano Zampini 
46652a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
4666e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
4667e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
4668e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
466970cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
4670e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
4671e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
4672e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
4673e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
4674e7931f94SStefano Zampini   }
467528143c3dSStefano Zampini #endif
4676e7931f94SStefano Zampini 
467728143c3dSStefano Zampini   /* assemble new additional is (if any) */
467828143c3dSStefano Zampini   if (nis) {
467928143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
468028143c3dSStefano Zampini 
468128143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4682854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
468328143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
468428143c3dSStefano Zampini     psum = 0;
468528143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
468628143c3dSStefano Zampini       for (j=0;j<nis;j++) {
468728143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
468828143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
468928143c3dSStefano Zampini         psum += plen;
469028143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
469128143c3dSStefano Zampini       }
469228143c3dSStefano Zampini     }
4693854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
4694854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
469528143c3dSStefano Zampini     for (i=1;i<nis;i++) {
469628143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
469728143c3dSStefano Zampini     }
469828143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
469928143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
470028143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
470128143c3dSStefano Zampini       for (j=0;j<nis;j++) {
470228143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
470328143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
470428143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
470528143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
470628143c3dSStefano Zampini       }
470728143c3dSStefano Zampini     }
470828143c3dSStefano Zampini     for (i=0;i<nis;i++) {
470928143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
471028143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
471128143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
471228143c3dSStefano Zampini     }
471328143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
471428143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
471528143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
471628143c3dSStefano Zampini   }
4717e7931f94SStefano Zampini   /* free workspace */
471828143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
4719e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4720e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
4721e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4722e7931f94SStefano Zampini   if (isdense) {
4723e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
4724e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
4725e7931f94SStefano Zampini   } else {
4726e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
4727e7931f94SStefano Zampini   }
472828143c3dSStefano Zampini   if (nis) {
472928143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
473028143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
473128143c3dSStefano Zampini   }
4732e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
4733e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
473428143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
4735e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
4736e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
473728143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
4738e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
4739e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
4740e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
4741e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
4742e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
474328143c3dSStefano Zampini   if (nis) {
474428143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
474528143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
474628143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
474728143c3dSStefano Zampini   }
474828143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
474928143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
475028143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
475128143c3dSStefano Zampini     for (i=0;i<nis;i++) {
475228143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
475328143c3dSStefano Zampini     }
475453a05cb3SStefano Zampini     *mat_n = NULL;
475528143c3dSStefano Zampini   }
4756e7931f94SStefano Zampini   PetscFunctionReturn(0);
4757e7931f94SStefano Zampini }
4758a57a6d2fSStefano Zampini 
475912edc857SStefano Zampini /* temporary hack into ksp private data structure */
4760af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
476112edc857SStefano Zampini 
4762c8587f34SStefano Zampini #undef __FUNCT__
4763c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
4764c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
4765c8587f34SStefano Zampini {
4766c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
4767c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
476820a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
47699881197aSStefano Zampini   MatNullSpace           CoarseNullSpace=NULL;
477020a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
47716e683305SStefano Zampini   IS                     coarse_is,*isarray;
47726e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
4773*30368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
4774f9eb5b7dSStefano Zampini   PC                     pc_temp;
4775c8587f34SStefano Zampini   PCType                 coarse_pc_type;
4776c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
4777f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
47784f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
47796e683305SStefano Zampini   Mat                    t_coarse_mat_is;
47806e683305SStefano Zampini   PetscInt               void_procs,ncoarse_ml,ncoarse_ds,ncoarse;
47816e683305SStefano Zampini   PetscMPIInt            all_procs;
478274e2c79eSStefano Zampini   PetscBool              csin_ml,csin_ds,csin,csin_type_simple,redist;
478368457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
478422bc73bbSStefano Zampini   PetscScalar            *array;
47859881197aSStefano Zampini   PetscErrorCode         ierr;
4786fdc09c96SStefano Zampini 
4787c8587f34SStefano Zampini   PetscFunctionBegin;
4788c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
478968457ee5SStefano 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 */
4790fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
47915a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
4792fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
4793f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
4794f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
4795f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
4796fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
479751bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
479851bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
4799dc4bcba2SStefano Zampini         PC        pc;
4800dc4bcba2SStefano Zampini         PetscBool isbddc;
4801dc4bcba2SStefano Zampini 
4802dc4bcba2SStefano Zampini         /* temporary workaround since PCBDDC does not have a reset method so far */
4803dc4bcba2SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
4804dc4bcba2SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
4805dc4bcba2SStefano Zampini         if (isbddc) {
4806dc4bcba2SStefano Zampini           ierr = PCDestroy(&pc);CHKERRQ(ierr);
4807dc4bcba2SStefano Zampini         }
4808727cdba6SStefano Zampini         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
4809fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
4810fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
4811fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
4812f4ddd8eeSStefano Zampini       }
4813fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
4814fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
4815f4ddd8eeSStefano Zampini     }
481670cf5478SStefano Zampini     /* reset any subassembling information */
481770cf5478SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
48186e683305SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
48196e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
4820fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
4821f4ddd8eeSStefano Zampini   }
4822c8587f34SStefano Zampini 
48236e683305SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
48242b510759SStefano Zampini   im_active = !!(pcis->n);
48252b510759SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
48266e683305SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&all_procs);CHKERRQ(ierr);
48276e683305SStefano Zampini   void_procs = all_procs-active_procs;
48286e683305SStefano Zampini   csin_type_simple = PETSC_TRUE;
482974e2c79eSStefano Zampini   redist = PETSC_FALSE;
483022bc73bbSStefano Zampini   if (pcbddc->current_level && void_procs) {
48316e683305SStefano Zampini     csin_ml = PETSC_TRUE;
48326e683305SStefano Zampini     ncoarse_ml = void_procs;
4833779c1cceSStefano Zampini     /* it has no sense to redistribute on a set of processors larger than the number of active processes */
4834779c1cceSStefano Zampini     if (pcbddc->redistribute_coarse > 0 && pcbddc->redistribute_coarse < active_procs) {
48356e683305SStefano Zampini       csin_ds = PETSC_TRUE;
483618a45a71SStefano Zampini       ncoarse_ds = pcbddc->redistribute_coarse;
483718a45a71SStefano Zampini       redist = PETSC_TRUE;
483818a45a71SStefano Zampini     } else {
48396e683305SStefano Zampini       csin_ds = PETSC_TRUE;
4840779c1cceSStefano Zampini       ncoarse_ds = active_procs;
4841779c1cceSStefano Zampini       redist = PETSC_TRUE;
484218a45a71SStefano Zampini     }
48436e683305SStefano Zampini   } else {
48446e683305SStefano Zampini     csin_ml = PETSC_FALSE;
48456e683305SStefano Zampini     ncoarse_ml = all_procs;
48466e683305SStefano Zampini     if (void_procs) {
48476e683305SStefano Zampini       csin_ds = PETSC_TRUE;
48486e683305SStefano Zampini       ncoarse_ds = void_procs;
48496e683305SStefano Zampini       csin_type_simple = PETSC_FALSE;
48506e683305SStefano Zampini     } else {
4851779c1cceSStefano Zampini       if (pcbddc->redistribute_coarse > 0 && pcbddc->redistribute_coarse < all_procs) {
485274e2c79eSStefano Zampini         csin_ds = PETSC_TRUE;
485374e2c79eSStefano Zampini         ncoarse_ds = pcbddc->redistribute_coarse;
485474e2c79eSStefano Zampini         redist = PETSC_TRUE;
485574e2c79eSStefano Zampini       } else {
48566e683305SStefano Zampini         csin_ds = PETSC_FALSE;
48576e683305SStefano Zampini         ncoarse_ds = all_procs;
48586e683305SStefano Zampini       }
48596e683305SStefano Zampini     }
486074e2c79eSStefano Zampini   }
48616e683305SStefano Zampini 
48626e683305SStefano Zampini   /*
48636e683305SStefano Zampini     test if we can go multilevel: three conditions must be satisfied:
48646e683305SStefano Zampini     - we have not exceeded the number of levels requested
48656e683305SStefano Zampini     - we can actually subassemble the active processes
48666e683305SStefano Zampini     - we can find a suitable number of MPI processes where we can place the subassembled problem
48676e683305SStefano Zampini   */
48686e683305SStefano Zampini   multilevel_allowed = PETSC_FALSE;
48696e683305SStefano Zampini   multilevel_requested = PETSC_FALSE;
48706e683305SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
48716e683305SStefano Zampini     multilevel_requested = PETSC_TRUE;
48726e683305SStefano Zampini     if (active_procs/pcbddc->coarsening_ratio < 2 || ncoarse_ml/pcbddc->coarsening_ratio < 2) {
4873f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_FALSE;
48742b510759SStefano Zampini     } else {
4875f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_TRUE;
4876c8587f34SStefano Zampini     }
4877c8587f34SStefano Zampini   }
48786e683305SStefano Zampini   /* determine number of process partecipating to coarse solver */
48796e683305SStefano Zampini   if (multilevel_allowed) {
48806e683305SStefano Zampini     ncoarse = ncoarse_ml;
48816e683305SStefano Zampini     csin = csin_ml;
488258da7f69SStefano Zampini     redist = PETSC_FALSE;
48836e683305SStefano Zampini   } else {
48846e683305SStefano Zampini     ncoarse = ncoarse_ds;
48856e683305SStefano Zampini     csin = csin_ds;
48866e683305SStefano Zampini   }
4887e7931f94SStefano Zampini 
4888abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
4889abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
4890abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
4891abbbba34SStefano Zampini 
4892abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
489322bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
489422bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
489522bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
489622bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
4897b1ecc7b1SStefano Zampini #if 0
4898b9b85e73SStefano Zampini   {
4899b9b85e73SStefano Zampini     PetscViewer viewer;
4900b9b85e73SStefano Zampini     char filename[256];
4901b1ecc7b1SStefano Zampini     sprintf(filename,"local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
4902b9b85e73SStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
4903b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4904b9b85e73SStefano Zampini     ierr = MatView(coarse_submat_dense,viewer);CHKERRQ(ierr);
4905b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4906b9b85e73SStefano Zampini   }
4907b9b85e73SStefano Zampini #endif
4908e176bc59SStefano 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);
49096e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
49106e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
49116e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4912abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
4913abbbba34SStefano Zampini 
49146e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
4915*30368db7SStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal || (pcbddc->benign_saddle_point && pcbddc->user_primal_vertices_local))) { /* protects from unneded computations */
49166e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
49176e683305SStefano Zampini     const PetscInt         *idxs;
49186e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
49196e683305SStefano Zampini 
49206e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
49210be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
49226e683305SStefano Zampini     /* allocate space for temporary storage */
4923854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
4924854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
49256e683305SStefano Zampini     /* allocate for IS array */
49266e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
49276e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
4928*30368db7SStefano Zampini     nisvert = 0;
4929*30368db7SStefano Zampini     if (pcbddc->benign_saddle_point && pcbddc->user_primal_vertices_local) {
4930*30368db7SStefano Zampini       nisvert = 1;
4931*30368db7SStefano Zampini     }
4932*30368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
4933854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
49346e683305SStefano Zampini     /* dofs splitting */
49356e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
49366e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
49376e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
49386e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
49396e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
49406e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
49416e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
4942*30368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
49436e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
49446e683305SStefano Zampini     }
49456e683305SStefano Zampini     /* neumann boundaries */
49466e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
49476e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
49486e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
49496e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
49506e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
49516e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
49526e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
4953*30368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
49546e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
49556e683305SStefano Zampini     }
4956*30368db7SStefano Zampini     /* primal vertices (benign) */
4957*30368db7SStefano Zampini     if (pcbddc->benign_saddle_point && pcbddc->user_primal_vertices_local) {
4958*30368db7SStefano Zampini       ierr = ISGetLocalSize(pcbddc->user_primal_vertices_local,&tsize);CHKERRQ(ierr);
4959*30368db7SStefano Zampini       ierr = ISGetIndices(pcbddc->user_primal_vertices_local,&idxs);CHKERRQ(ierr);
4960*30368db7SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
4961*30368db7SStefano Zampini       ierr = ISRestoreIndices(pcbddc->user_primal_vertices_local,&idxs);CHKERRQ(ierr);
4962*30368db7SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
4963*30368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nis-1]);CHKERRQ(ierr);
4964*30368db7SStefano Zampini     }
49656e683305SStefano Zampini     /* free memory */
49666e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
49676e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
49686e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
49696e683305SStefano Zampini   } else {
49706e683305SStefano Zampini     nis = 0;
49716e683305SStefano Zampini     nisdofs = 0;
49726e683305SStefano Zampini     nisneu = 0;
4973*30368db7SStefano Zampini     nisvert = 0;
49746e683305SStefano Zampini     isarray = NULL;
49756e683305SStefano Zampini   }
49766e683305SStefano Zampini   /* destroy no longer needed map */
49776e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
49786e683305SStefano Zampini 
49796e683305SStefano Zampini   /* restrict on coarse candidates (if needed) */
49806e683305SStefano Zampini   coarse_mat_is = NULL;
49816e683305SStefano Zampini   if (csin) {
49826e683305SStefano Zampini     if (!pcbddc->coarse_subassembling_init ) { /* creates subassembling init pattern if not present */
498374e2c79eSStefano Zampini       if (redist) {
498474e2c79eSStefano Zampini         PetscMPIInt rank;
4985779c1cceSStefano Zampini         PetscInt    spc,n_spc_p1,dest[1],destsize;
498674e2c79eSStefano Zampini 
498774e2c79eSStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
498858da7f69SStefano Zampini         spc = active_procs/ncoarse;
498958da7f69SStefano Zampini         n_spc_p1 = active_procs%ncoarse;
4990779c1cceSStefano Zampini         if (im_active) {
4991779c1cceSStefano Zampini           destsize = 1;
499274e2c79eSStefano Zampini           if (rank > n_spc_p1*(spc+1)-1) {
499374e2c79eSStefano Zampini             dest[0] = n_spc_p1+(rank-(n_spc_p1*(spc+1)))/spc;
499474e2c79eSStefano Zampini           } else {
499574e2c79eSStefano Zampini             dest[0] = rank/(spc+1);
499674e2c79eSStefano Zampini           }
499774e2c79eSStefano Zampini         } else {
4998779c1cceSStefano Zampini           destsize = 0;
49996e683305SStefano Zampini         }
5000779c1cceSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),destsize,dest,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
5001779c1cceSStefano Zampini       } else if (csin_type_simple) {
50026e683305SStefano Zampini         PetscMPIInt rank;
50036e683305SStefano Zampini         PetscInt    issize,isidx;
5004779c1cceSStefano Zampini 
50056e683305SStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
50066e683305SStefano Zampini         if (im_active) {
50076e683305SStefano Zampini           issize = 1;
50086e683305SStefano Zampini           isidx = (PetscInt)rank;
50096e683305SStefano Zampini         } else {
50106e683305SStefano Zampini           issize = 0;
50116e683305SStefano Zampini           isidx = -1;
50126e683305SStefano Zampini         }
50136e683305SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),issize,&isidx,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
5014779c1cceSStefano Zampini       } else { /* get a suitable subassembling pattern from MATIS code */
5015b0c7d250SStefano Zampini         ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
50166e683305SStefano Zampini       }
5017779c1cceSStefano Zampini 
5018779c1cceSStefano Zampini       /* we need to shift on coarse candidates either if we are not redistributing or we are redistributing and we have enough void processes */
5019779c1cceSStefano Zampini       if (!redist || ncoarse <= void_procs) {
5020779c1cceSStefano Zampini         PetscInt ncoarse_cand,tissize,*nisindices;
5021779c1cceSStefano Zampini         PetscInt *coarse_candidates;
5022779c1cceSStefano Zampini         const PetscInt* tisindices;
5023779c1cceSStefano Zampini 
5024779c1cceSStefano Zampini         /* get coarse candidates' ranks in pc communicator */
5025779c1cceSStefano Zampini         ierr = PetscMalloc1(all_procs,&coarse_candidates);CHKERRQ(ierr);
5026779c1cceSStefano Zampini         ierr = MPI_Allgather(&im_active,1,MPIU_INT,coarse_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
5027779c1cceSStefano Zampini         for (i=0,ncoarse_cand=0;i<all_procs;i++) {
5028779c1cceSStefano Zampini           if (!coarse_candidates[i]) {
5029779c1cceSStefano Zampini             coarse_candidates[ncoarse_cand++]=i;
5030779c1cceSStefano Zampini           }
5031779c1cceSStefano Zampini         }
5032779c1cceSStefano Zampini         if (ncoarse_cand < ncoarse) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen! %d < %d",ncoarse_cand,ncoarse);
5033779c1cceSStefano Zampini 
5034779c1cceSStefano Zampini 
50356e683305SStefano Zampini         if (pcbddc->dbg_flag) {
50366e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
50376e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init (before shift)\n");CHKERRQ(ierr);
50386e683305SStefano Zampini           ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
50396e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse candidates\n");CHKERRQ(ierr);
5040779c1cceSStefano Zampini           for (i=0;i<ncoarse_cand;i++) {
50416e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"%d ",coarse_candidates[i]);CHKERRQ(ierr);
50426e683305SStefano Zampini           }
50436e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"\n");CHKERRQ(ierr);
50446e683305SStefano Zampini           ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
50456e683305SStefano Zampini         }
50466e683305SStefano Zampini         /* shift the pattern on coarse candidates */
50476e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->coarse_subassembling_init,&tissize);CHKERRQ(ierr);
50486e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
5049854ce69bSBarry Smith         ierr = PetscMalloc1(tissize,&nisindices);CHKERRQ(ierr);
50506e683305SStefano Zampini         for (i=0;i<tissize;i++) nisindices[i] = coarse_candidates[tisindices[i]];
50516e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
50526e683305SStefano Zampini         ierr = ISGeneralSetIndices(pcbddc->coarse_subassembling_init,tissize,nisindices,PETSC_OWN_POINTER);CHKERRQ(ierr);
50536e683305SStefano Zampini         ierr = PetscFree(coarse_candidates);CHKERRQ(ierr);
50546e683305SStefano Zampini       }
50556e683305SStefano Zampini       if (pcbddc->dbg_flag) {
50566e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
50576e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init\n");CHKERRQ(ierr);
50586e683305SStefano Zampini         ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
50596e683305SStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
50606e683305SStefano Zampini       }
5061779c1cceSStefano Zampini     }
50626e683305SStefano Zampini     /* get temporary coarse mat in IS format restricted on coarse procs (plus additional index sets of isarray) */
506353a05cb3SStefano Zampini     if (multilevel_allowed) { /* we need to keep tracking of void processes for future placements */
506453a05cb3SStefano 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);
506553a05cb3SStefano Zampini     } else { /* this is the last level, so use just receiving processes in subcomm */
506653a05cb3SStefano 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);
506753a05cb3SStefano Zampini     }
50686e683305SStefano Zampini   } else {
50696e683305SStefano Zampini     if (pcbddc->dbg_flag) {
50706e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
50716e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init not needed\n");CHKERRQ(ierr);
50726e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
50736e683305SStefano Zampini     }
50746e683305SStefano Zampini     ierr = PetscObjectReference((PetscObject)t_coarse_mat_is);CHKERRQ(ierr);
50756e683305SStefano Zampini     coarse_mat_is = t_coarse_mat_is;
50766e683305SStefano Zampini   }
50776e683305SStefano Zampini 
50786e683305SStefano Zampini   /* create local to global scatters for coarse problem */
507968457ee5SStefano Zampini   if (compute_vecs) {
50806e683305SStefano Zampini     PetscInt lrows;
50816e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
50826e683305SStefano Zampini     if (coarse_mat_is) {
50836e683305SStefano Zampini       ierr = MatGetLocalSize(coarse_mat_is,&lrows,NULL);CHKERRQ(ierr);
50846e683305SStefano Zampini     } else {
50856e683305SStefano Zampini       lrows = 0;
50866e683305SStefano Zampini     }
50876e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
50886e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
50896e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
50906e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
50916e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
50926e683305SStefano Zampini   }
50936e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
50946e683305SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
5095c8587f34SStefano Zampini 
5096f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
5097f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
5098f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
5099f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
5100f9eb5b7dSStefano Zampini   } else {
5101f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
5102f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
5103c8587f34SStefano Zampini   }
5104c8587f34SStefano Zampini 
51056e683305SStefano Zampini   /* print some info if requested */
51066e683305SStefano Zampini   if (pcbddc->dbg_flag) {
51076e683305SStefano Zampini     if (!multilevel_allowed) {
51086e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
51096e683305SStefano Zampini       if (multilevel_requested) {
51106e683305SStefano 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);
51116e683305SStefano Zampini       } else if (pcbddc->max_levels) {
51126e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
51136e683305SStefano Zampini       }
51146e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
51156e683305SStefano Zampini     }
51166e683305SStefano Zampini   }
51176e683305SStefano Zampini 
5118f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
51196e683305SStefano Zampini   if (coarse_mat_is) {
51206e683305SStefano Zampini     MatReuse coarse_mat_reuse;
51216a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
51226e683305SStefano Zampini     if (pcbddc->dbg_flag) {
51236e683305SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat_is));
51246e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
51256e683305SStefano Zampini     }
5126f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
5127312be037SStefano Zampini       char prefix[256],str_level[16];
5128e604994aSStefano Zampini       size_t len;
51296e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat_is),&pcbddc->coarse_ksp);CHKERRQ(ierr);
5130422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
5131c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
5132f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
51335f76c7aeSStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat_is,coarse_mat_is);CHKERRQ(ierr);
5134c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
51356e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
5136c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
5137c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
5138e604994aSStefano Zampini       /* prefix */
5139e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
5140e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
5141e604994aSStefano Zampini       if (!pcbddc->current_level) {
5142e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
5143e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
5144c8587f34SStefano Zampini       } else {
5145e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
5146312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
5147312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
514834d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
5149312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
5150e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
5151e604994aSStefano Zampini       }
5152e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
51533e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
51543e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
51553e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
51563e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
5157f9eb5b7dSStefano Zampini       /* allow user customization */
5158f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
51593e3c6dadSStefano Zampini     }
51603e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
516151bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
51623e3c6dadSStefano Zampini     if (nisdofs) {
51633e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
51643e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
51653e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
51663e3c6dadSStefano Zampini       }
51673e3c6dadSStefano Zampini     }
51683e3c6dadSStefano Zampini     if (nisneu) {
51693e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
51703e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
5171312be037SStefano Zampini     }
5172*30368db7SStefano Zampini     if (nisvert) {
5173*30368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
5174*30368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
5175*30368db7SStefano Zampini     }
5176f9eb5b7dSStefano Zampini 
5177f9eb5b7dSStefano Zampini     /* get some info after set from options */
5178f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
5179f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
51804f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
51816e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
5182f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
5183f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
5184f9eb5b7dSStefano Zampini     }
518539f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
51864f3a063dSStefano Zampini     if (isredundant) {
51874f3a063dSStefano Zampini       KSP inner_ksp;
51884f3a063dSStefano Zampini       PC  inner_pc;
51894f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
51904f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
51914f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
51924f3a063dSStefano Zampini     }
5193f9eb5b7dSStefano Zampini 
5194f9eb5b7dSStefano Zampini     /* assemble coarse matrix */
5195fa7f1dd8SStefano Zampini     if (coarse_reuse) {
519681d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
5197fa7f1dd8SStefano Zampini       ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
51986e683305SStefano Zampini       coarse_mat_reuse = MAT_REUSE_MATRIX;
5199fa7f1dd8SStefano Zampini     } else {
52006e683305SStefano Zampini       coarse_mat_reuse = MAT_INITIAL_MATRIX;
5201fa7f1dd8SStefano Zampini     }
5202c8587f34SStefano Zampini     if (isbddc || isnn) {
520322bc73bbSStefano Zampini       if (pcbddc->coarsening_ratio > 1) {
520470cf5478SStefano Zampini         if (!pcbddc->coarse_subassembling) { /* subassembling info is not present */
5205b0c7d250SStefano Zampini           ierr = MatISGetSubassemblingPattern(coarse_mat_is,active_procs/pcbddc->coarsening_ratio,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
520622b6e8a2SStefano Zampini           if (pcbddc->dbg_flag) {
52076e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
52086e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"Subassembling pattern\n");CHKERRQ(ierr);
52096e683305SStefano Zampini             ierr = ISView(pcbddc->coarse_subassembling,dbg_viewer);CHKERRQ(ierr);
52106e683305SStefano Zampini             ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
521122b6e8a2SStefano Zampini           }
521270cf5478SStefano Zampini         }
521353a05cb3SStefano Zampini         ierr = MatISSubassemble(coarse_mat_is,pcbddc->coarse_subassembling,0,PETSC_FALSE,PETSC_FALSE,coarse_mat_reuse,&coarse_mat,0,NULL);CHKERRQ(ierr);
521470cf5478SStefano Zampini       } else {
521522bc73bbSStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
521622bc73bbSStefano Zampini         coarse_mat = coarse_mat_is;
521722bc73bbSStefano Zampini       }
521822bc73bbSStefano Zampini     } else {
52192e1e5fa4SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
5220c8587f34SStefano Zampini     }
5221c8587f34SStefano Zampini     ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
5222c8587f34SStefano Zampini 
52233301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
52245a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
52253301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
52263301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
52273301b35fSStefano Zampini     }
52283301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
52293301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
52303301b35fSStefano Zampini     }
52313301b35fSStefano Zampini     if (pc->pmat->spd_set) {
52323301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
52333301b35fSStefano Zampini     }
52346e683305SStefano Zampini     /* set operators */
52355f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
52366e683305SStefano Zampini     if (pcbddc->dbg_flag) {
52376e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
52386e683305SStefano Zampini     }
52396e683305SStefano Zampini   } else { /* processes non partecipating to coarse solver (if any) */
52406e683305SStefano Zampini     coarse_mat = 0;
52416e683305SStefano Zampini   }
52426e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
5243b1ecc7b1SStefano Zampini #if 0
5244b9b85e73SStefano Zampini   {
5245b9b85e73SStefano Zampini     PetscViewer viewer;
5246b9b85e73SStefano Zampini     char filename[256];
5247b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
5248b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
5249b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
5250b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
5251b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
5252b9b85e73SStefano Zampini   }
5253b9b85e73SStefano Zampini #endif
5254c8587f34SStefano Zampini 
5255c8587f34SStefano Zampini   /* Compute coarse null space (special handling by BDDC only) */
5256298c0119SStefano Zampini #if 0
5257c8587f34SStefano Zampini   if (pcbddc->NullSpace) {
5258c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,coarse_mat,&CoarseNullSpace);CHKERRQ(ierr);
525998a51de6SStefano Zampini   }
5260298c0119SStefano Zampini #endif
5261b0f5fe93SStefano Zampini   /* hack */
526298a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
526398a51de6SStefano Zampini     Vec crhs,csol;
526404708bb6SStefano Zampini 
5265f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
5266f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
5267f347579bSStefano Zampini     if (!csol) {
52682a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
5269f9eb5b7dSStefano Zampini     }
5270f347579bSStefano Zampini     if (!crhs) {
52712a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
5272f347579bSStefano Zampini     }
5273b0f5fe93SStefano Zampini   }
5274b0f5fe93SStefano Zampini 
5275b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
5276b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
5277b0f5fe93SStefano Zampini 
5278b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
52794f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
52804f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
52814f1b2e48SStefano Zampini     }
5282b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
5283b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
5284b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5285b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5286b0f5fe93SStefano Zampini     if (coarse_mat) {
5287b0f5fe93SStefano Zampini       Vec         nullv;
5288b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
5289b0f5fe93SStefano Zampini       PetscInt    nl;
5290b0f5fe93SStefano Zampini 
5291b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
5292b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
5293b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
5294b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
5295b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
5296b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
5297b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
5298b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
5299b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
5300b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
5301b0f5fe93SStefano Zampini     }
5302b0f5fe93SStefano Zampini   }
5303b0f5fe93SStefano Zampini 
5304b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
5305b0f5fe93SStefano Zampini     PetscBool ispreonly;
5306b0f5fe93SStefano Zampini 
5307b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
5308b0f5fe93SStefano Zampini       PetscBool isnull;
5309b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
5310b0f5fe93SStefano Zampini       if (isnull) {
5311*30368db7SStefano Zampini         if (isbddc && !pcbddc->benign_saddle_point) {
5312b0f5fe93SStefano Zampini           ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
5313b0f5fe93SStefano Zampini         } else {
5314b0f5fe93SStefano Zampini           ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
5315b0f5fe93SStefano Zampini         }
5316b0f5fe93SStefano Zampini       } else {
5317b0f5fe93SStefano Zampini         ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
5318b0f5fe93SStefano Zampini       }
5319b0f5fe93SStefano Zampini     }
5320b0f5fe93SStefano Zampini     /* setup coarse ksp */
5321b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
5322cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
5323cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
53246e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
5325c8587f34SStefano Zampini       KSP       check_ksp;
53262b510759SStefano Zampini       KSPType   check_ksp_type;
5327c8587f34SStefano Zampini       PC        check_pc;
53286e683305SStefano Zampini       Vec       check_vec,coarse_vec;
53296a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
53302b510759SStefano Zampini       PetscInt  its;
53316e683305SStefano Zampini       PetscBool compute_eigs;
53326e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
53336e683305SStefano Zampini       PetscInt  neigs;
53348e185a42SStefano Zampini       const char *prefix;
5335c8587f34SStefano Zampini 
53362b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
53376e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
5338422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
533923ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
5340f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
53412b510759SStefano Zampini       if (ispreonly) {
53422b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
53436e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
53442b510759SStefano Zampini       } else {
5345cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
53466e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
5347c8587f34SStefano Zampini       }
5348c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
53496e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
53506e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
53516e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
5352a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
5353a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
5354a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
5355a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
5356c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
5357c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
5358c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
5359c8587f34SStefano Zampini       /* create random vec */
53606e683305SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&coarse_vec);CHKERRQ(ierr);
53616e683305SStefano Zampini       ierr = VecDuplicate(coarse_vec,&check_vec);CHKERRQ(ierr);
5362c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
5363c8587f34SStefano Zampini       if (CoarseNullSpace) {
5364c8587f34SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
5365c8587f34SStefano Zampini       }
53666e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
5367c8587f34SStefano Zampini       /* solve coarse problem */
53686e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
5369c8587f34SStefano Zampini       if (CoarseNullSpace) {
53706e683305SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,coarse_vec);CHKERRQ(ierr);
5371c8587f34SStefano Zampini       }
5372cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
53736e683305SStefano Zampini       if (compute_eigs) {
5374854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
5375854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
53766e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
53776e683305SStefano Zampini         lambda_max = eigs_r[neigs-1];
53786e683305SStefano Zampini         lambda_min = eigs_r[0];
53796e683305SStefano Zampini         if (pcbddc->use_coarse_estimates) {
53806e683305SStefano Zampini           if (lambda_max>lambda_min) {
5381cbcc2c2aSStefano Zampini             ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max,lambda_min);CHKERRQ(ierr);
5382cbcc2c2aSStefano Zampini             ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
5383cbcc2c2aSStefano Zampini           }
5384c8587f34SStefano Zampini         }
5385c8587f34SStefano Zampini       }
5386cbcc2c2aSStefano Zampini 
5387c8587f34SStefano Zampini       /* check coarse problem residual error */
53886e683305SStefano Zampini       if (pcbddc->dbg_flag) {
53896e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
53906e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
53916e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
5392c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
53936e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
53946e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
5395c8587f34SStefano Zampini         ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
5396779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
53976e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
53986e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
53996e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
54006e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
5401b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
5402b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
5403b0f5fe93SStefano Zampini         }
54046e683305SStefano Zampini         if (compute_eigs) {
54056e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
5406deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
5407c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
54086e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
54096e683305SStefano 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);
54106e683305SStefano Zampini           for (i=0;i<neigs;i++) {
54116e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
5412c8587f34SStefano Zampini           }
54136e683305SStefano Zampini         }
54146e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
54156e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
54166e683305SStefano Zampini       }
5417c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
54186e683305SStefano Zampini       if (compute_eigs) {
54196e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
54206e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
5421c8587f34SStefano Zampini       }
54226e683305SStefano Zampini     }
54236e683305SStefano Zampini   }
5424cbcc2c2aSStefano Zampini   /* print additional info */
5425cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
54266e683305SStefano Zampini     /* waits until all processes reaches this point */
54276e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
5428cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
5429cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5430cbcc2c2aSStefano Zampini   }
5431cbcc2c2aSStefano Zampini 
54322b510759SStefano Zampini   /* free memory */
5433c8587f34SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
5434fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
5435c8587f34SStefano Zampini   PetscFunctionReturn(0);
5436c8587f34SStefano Zampini }
5437674ae819SStefano Zampini 
5438f34684f1SStefano Zampini #undef __FUNCT__
5439f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
5440f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
5441f34684f1SStefano Zampini {
5442f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
5443f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
5444f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
5445dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
5446dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
544773be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
5448dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
5449f34684f1SStefano Zampini   PetscErrorCode ierr;
5450f34684f1SStefano Zampini 
5451f34684f1SStefano Zampini   PetscFunctionBegin;
5452f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
54530e6343abSStefano Zampini   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) {
54540e6343abSStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
5455727cdba6SStefano Zampini   }
5456dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
54573bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
5458dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
5459dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
5460dc456d91SStefano Zampini   ierr = PCBDDCSubsetNumbering(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
5461dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
5462dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
5463dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
54640e6343abSStefano Zampini   if (local_size != pcbddc->local_primal_size) {
54650e6343abSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid number of local primal indices computed %d != %d",local_size,pcbddc->local_primal_size);
54660e6343abSStefano Zampini   }
5467dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
5468dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
5469dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
5470dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
5471dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
5472f34684f1SStefano Zampini 
5473f34684f1SStefano Zampini   /* check numbering */
5474f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
5475019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
5476dc456d91SStefano Zampini     PetscInt    i;
5477b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
5478f34684f1SStefano Zampini 
5479f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5480f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5481f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
54820fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
5483019a44ceSStefano Zampini     /* counter */
5484019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5485019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
5486019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5487019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5488019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5489019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5490019a44ceSStefano Zampini 
5491f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
5492f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
5493727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
5494f34684f1SStefano Zampini     }
5495f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
5496f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
5497f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5498e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5499e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5500e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5501e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5502f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5503019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
5504f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
5505019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
550675c01103SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]);
550775c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
5508b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
5509019a44ceSStefano 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);
5510f34684f1SStefano Zampini       }
5511f34684f1SStefano Zampini     }
5512019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
5513b9b85e73SStefano Zampini     ierr = MPI_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
5514f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5515f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
5516f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
5517f34684f1SStefano Zampini     }
5518f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5519f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5520e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5521e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5522f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
5523f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
5524b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
5525ca8b9ea9SStefano Zampini       PetscInt *gidxs;
5526ca8b9ea9SStefano Zampini 
5527ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
55283bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
5529f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
5530f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5531f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
5532f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
55334bc2dc4bSStefano 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);
5534f34684f1SStefano Zampini       }
5535f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5536ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
5537f34684f1SStefano Zampini     }
5538f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5539302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
5540f34684f1SStefano Zampini   }
55418bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
5542f34684f1SStefano Zampini   /* get back data */
5543f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
5544f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
5545674ae819SStefano Zampini   PetscFunctionReturn(0);
5546674ae819SStefano Zampini }
5547674ae819SStefano Zampini 
5548e456f2a8SStefano Zampini #undef __FUNCT__
5549e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
5550a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
5551e456f2a8SStefano Zampini {
5552e456f2a8SStefano Zampini   IS             localis_t;
5553a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
5554e456f2a8SStefano Zampini   PetscScalar    *vals;
5555e456f2a8SStefano Zampini   PetscErrorCode ierr;
5556e456f2a8SStefano Zampini 
5557e456f2a8SStefano Zampini   PetscFunctionBegin;
5558a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
5559e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
5560854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
5561e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
5562e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
5563a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
5564a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
55651035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
5566a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
55671035eff8SStefano Zampini   }
5568a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
5569e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
5570e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
5571a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
5572a7dc3881SStefano Zampini   /* now compute set in local ordering */
5573a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5574a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5575a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
5576a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
5577a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
5578ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
5579e456f2a8SStefano Zampini       lsize++;
5580e456f2a8SStefano Zampini     }
5581e456f2a8SStefano Zampini   }
5582854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
5583a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
5584ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
5585e456f2a8SStefano Zampini       idxs[lsize++] = i;
5586e456f2a8SStefano Zampini     }
5587e456f2a8SStefano Zampini   }
5588a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
5589a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
5590e456f2a8SStefano Zampini   *localis = localis_t;
5591e456f2a8SStefano Zampini   PetscFunctionReturn(0);
5592e456f2a8SStefano Zampini }
5593906d46d4SStefano Zampini 
5594906d46d4SStefano Zampini /* the next two functions will be called in KSPMatMult if a change of basis has been requested */
5595906d46d4SStefano Zampini #undef __FUNCT__
5596906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMult_Private"
5597906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMult_Private(Mat A, Vec x, Vec y)
5598906d46d4SStefano Zampini {
5599906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
5600906d46d4SStefano Zampini   PetscErrorCode   ierr;
5601906d46d4SStefano Zampini 
5602906d46d4SStefano Zampini   PetscFunctionBegin;
5603906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
5604906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
5605906d46d4SStefano Zampini   ierr = MatMult(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
5606906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
5607906d46d4SStefano Zampini   PetscFunctionReturn(0);
5608906d46d4SStefano Zampini }
5609906d46d4SStefano Zampini 
5610906d46d4SStefano Zampini #undef __FUNCT__
5611906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMultTranspose_Private"
5612906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMultTranspose_Private(Mat A, Vec x, Vec y)
5613906d46d4SStefano Zampini {
5614906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
5615906d46d4SStefano Zampini   PetscErrorCode   ierr;
5616906d46d4SStefano Zampini 
5617906d46d4SStefano Zampini   PetscFunctionBegin;
5618906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
5619906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
5620906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
5621906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
5622906d46d4SStefano Zampini   PetscFunctionReturn(0);
5623906d46d4SStefano Zampini }
5624b96c3477SStefano Zampini 
5625b96c3477SStefano Zampini #undef __FUNCT__
5626b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
562708122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
5628b96c3477SStefano Zampini {
5629a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
5630b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
5631b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
5632a64f4aa4SStefano Zampini   Mat                 S_j;
5633b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
5634b96c3477SStefano Zampini   PetscBool           free_used_adj;
5635b96c3477SStefano Zampini   PetscErrorCode      ierr;
5636b96c3477SStefano Zampini 
5637b96c3477SStefano Zampini   PetscFunctionBegin;
5638b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
5639b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
564008122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
5641b96c3477SStefano Zampini     used_xadj = NULL;
5642b96c3477SStefano Zampini     used_adjncy = NULL;
5643b96c3477SStefano Zampini   } else {
564408122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
564508122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
564608122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
564708122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
5648b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
5649b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
5650b96c3477SStefano Zampini     } else {
56512fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
5652b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
5653b96c3477SStefano Zampini       PetscInt       nvtxs;
5654b96c3477SStefano Zampini 
56552fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
56562fffb893SStefano Zampini       if (flg_row) {
5657b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
5658b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
5659b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
5660b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
56612fffb893SStefano Zampini       } else {
56622fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
56632fffb893SStefano Zampini         used_xadj = NULL;
56642fffb893SStefano Zampini         used_adjncy = NULL;
56652fffb893SStefano Zampini       }
56662fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
5667b96c3477SStefano Zampini     }
5668b96c3477SStefano Zampini   }
5669d5574798SStefano Zampini 
5670d5574798SStefano Zampini   /* setup sub_schurs data */
5671a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
5672a64f4aa4SStefano Zampini   if (!sub_schurs->use_mumps) {
5673a64f4aa4SStefano Zampini     /* pcbddc->ksp_D up to date only if not using MUMPS */
5674a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
567506a4e24aSStefano 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);
5676a64f4aa4SStefano Zampini   } else {
56776816873aSStefano Zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
567804708bb6SStefano Zampini     PetscBool isseqaij;
56795feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
56805feab87aSStefano Zampini       PetscInt n_vertices;
56815feab87aSStefano Zampini 
56825feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
56832034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
56845feab87aSStefano Zampini     }
568504708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
568604708bb6SStefano Zampini     if (!isseqaij) {
568704708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
568804708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
568904708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
569004708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
569104708bb6SStefano Zampini       } else {
569204708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
569304708bb6SStefano Zampini       }
569404708bb6SStefano Zampini     }
569506a4e24aSStefano 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);
5696a64f4aa4SStefano Zampini   }
5697a64f4aa4SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
5698b96c3477SStefano Zampini 
5699b96c3477SStefano Zampini   /* free adjacency */
5700b96c3477SStefano Zampini   if (free_used_adj) {
5701b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
5702b96c3477SStefano Zampini   }
5703b96c3477SStefano Zampini   PetscFunctionReturn(0);
5704b96c3477SStefano Zampini }
5705b96c3477SStefano Zampini 
5706b96c3477SStefano Zampini #undef __FUNCT__
5707b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
570808122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
5709b96c3477SStefano Zampini {
5710b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
5711b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
5712b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
5713b96c3477SStefano Zampini   PCBDDCGraph         graph;
5714b96c3477SStefano Zampini   PetscErrorCode      ierr;
5715b96c3477SStefano Zampini 
5716b96c3477SStefano Zampini   PetscFunctionBegin;
5717b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
571808122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
57193301b35fSStefano Zampini     IS       verticesIS,verticescomm;
57203301b35fSStefano Zampini     PetscInt vsize,*idxs;
5721b96c3477SStefano Zampini 
5722b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
57233301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
57243301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
57253301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
57263301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
57273301b35fSStefano Zampini     ierr = ISDestroy(&verticesIS);CHKERRQ(ierr);
5728b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
57297fb0e2dbSStefano Zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global);CHKERRQ(ierr);
57303301b35fSStefano Zampini     ierr = PCBDDCGraphSetUp(graph,0,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
57313301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
5732b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
5733b96c3477SStefano Zampini /*
5734b96c3477SStefano Zampini     if (pcbddc->dbg_flag) {
5735b96c3477SStefano Zampini       ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
5736b96c3477SStefano Zampini     }
5737b96c3477SStefano Zampini */
5738b96c3477SStefano Zampini   } else {
5739b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
5740b96c3477SStefano Zampini   }
5741b96c3477SStefano Zampini 
5742b96c3477SStefano Zampini   /* sub_schurs init */
5743a64f4aa4SStefano Zampini   ierr = PCBDDCSubSchursInit(sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap);CHKERRQ(ierr);
5744a64f4aa4SStefano Zampini 
5745b96c3477SStefano Zampini   /* free graph struct */
574608122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
5747b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
5748b96c3477SStefano Zampini   }
5749b96c3477SStefano Zampini   PetscFunctionReturn(0);
5750b96c3477SStefano Zampini }
5751fa34dd3eSStefano Zampini 
5752fa34dd3eSStefano Zampini #undef __FUNCT__
5753fa34dd3eSStefano Zampini #define __FUNCT__ "PCBDDCCheckOperator"
5754fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
5755fa34dd3eSStefano Zampini {
5756fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
5757fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
5758fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
5759fa34dd3eSStefano Zampini 
5760fa34dd3eSStefano Zampini   PetscFunctionBegin;
5761fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
5762fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
57634f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
5764fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
57654f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
576675c01103SStefano Zampini     PetscReal      norm;
5767fa34dd3eSStefano Zampini     PetscInt       i;
5768fa34dd3eSStefano Zampini 
5769fa34dd3eSStefano Zampini     /* B0 and B0_B */
5770fa34dd3eSStefano Zampini     if (zerodiag) {
5771fa34dd3eSStefano Zampini       IS       dummy;
5772fa34dd3eSStefano Zampini 
57734f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
57744f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
5775fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
5776fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
5777fa34dd3eSStefano Zampini     }
5778fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
5779fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
5780fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
5781fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5782fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5783fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5784fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5785fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
5786fa34dd3eSStefano Zampini     /* S_j */
5787fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
5788fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
5789fa34dd3eSStefano Zampini 
5790fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
5791fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
5792fa34dd3eSStefano Zampini     /* continuous in primal space */
5793fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
5794fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5795fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5796fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
57974f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
57984f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
5799fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
5800fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5801fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
5802fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
5803fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5804fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5805fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
5806fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
5807fa34dd3eSStefano Zampini 
5808fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
5809fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
5810fa34dd3eSStefano Zampini     /* local with Schur */
5811fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
5812fa34dd3eSStefano Zampini     if (zerodiag) {
5813fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
58144f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
5815fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
5816fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
5817fa34dd3eSStefano Zampini     }
5818fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
5819fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5820fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5821fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5822fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
5823fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
5824fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
5825fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5826fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
5827fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5828fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5829fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5830fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5831fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5832fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
5833fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
5834fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
5835fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5836fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
5837fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
5838fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5839fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5840fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
5841fa34dd3eSStefano Zampini     if (zerodiag) {
5842fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
5843fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
58444f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
5845fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
5846fa34dd3eSStefano Zampini     }
5847fa34dd3eSStefano Zampini     /* BDDC */
5848fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
5849fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
5850fa34dd3eSStefano Zampini 
5851fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
5852fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
5853fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
5854fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
58554f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
58564f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
5857fa34dd3eSStefano Zampini     }
58584f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
5859fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
5860fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
5861fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
5862fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
5863fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
5864fa34dd3eSStefano Zampini   }
5865fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
5866fa34dd3eSStefano Zampini }
5867