xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision ffd830a353d0919fb77324c0e33a98985abf7504)
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 
698*ffd830a3SStefano Zampini   thresh = pcbddc->adaptive_threshold;
69908122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
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);
707*ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
708f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
709f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
7109ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
711aff50787SStefano Zampini         PetscInt j,k;
712aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
713aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
714aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
71508122e43SStefano Zampini         }
71608122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
717aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
718aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
719aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
720aff50787SStefano Zampini           }
72108122e43SStefano Zampini         }
72208122e43SStefano Zampini       } else {
72308122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
72408122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
72508122e43SStefano Zampini       }
7268bec7fa6SStefano Zampini     } else {
727f6f667cfSStefano Zampini       S = Sarray + cumarray;
728f6f667cfSStefano Zampini       St = Starray + cumarray;
7298bec7fa6SStefano Zampini     }
73008122e43SStefano Zampini 
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 {
7391cf9b237SStefano Zampini       if (nmin) {
7401cf9b237SStefano Zampini         Mat SM,StM;
7411cf9b237SStefano Zampini         PetscInt j,k,nccs,nccst;
7421cf9b237SStefano Zampini 
7431cf9b237SStefano Zampini         for (j=0;j<subset_size;j++) {
7441cf9b237SStefano Zampini           for (k=j;k<subset_size;k++) {
7451cf9b237SStefano Zampini             S [k*subset_size+j] = S [j*subset_size+k];
7461cf9b237SStefano Zampini             St[k*subset_size+j] = St[j*subset_size+k];
7471cf9b237SStefano Zampini           }
7481cf9b237SStefano Zampini         }
7491cf9b237SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,subset_size,S,&SM);CHKERRQ(ierr);
7501cf9b237SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,subset_size,St,&StM);CHKERRQ(ierr);
7511cf9b237SStefano Zampini         ierr = MatDetectDisconnectedComponents(SM,PETSC_TRUE,&nccs,NULL);CHKERRQ(ierr);
7521cf9b237SStefano Zampini         ierr = MatDetectDisconnectedComponents(StM,PETSC_TRUE,&nccst,NULL);CHKERRQ(ierr);
7531cf9b237SStefano Zampini         if (nccs != 1 || nccst != 1) {
7541cf9b237SStefano Zampini           PetscPrintf(PETSC_COMM_SELF,"[%d] Found disc %d %d (size %d)\n",PetscGlobalRank,nccs,nccst,subset_size);
7551cf9b237SStefano Zampini         }
7561cf9b237SStefano Zampini         ierr = MatDestroy(&SM);CHKERRQ(ierr);
7571cf9b237SStefano Zampini         ierr = MatDestroy(&StM);CHKERRQ(ierr);
7581cf9b237SStefano Zampini       }
759f6f667cfSStefano Zampini 
7609ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
76108122e43SStefano Zampini         PetscBLASInt B_itype = 1;
762f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
7634c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
7649552c7c7SStefano Zampini         PetscInt     nmin_s;
76508122e43SStefano Zampini 
766fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
7678bec7fa6SStefano 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]]);
768fd14bc51SStefano Zampini         }
769d16cbb6bSStefano Zampini 
77008122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
771d16cbb6bSStefano Zampini         if (thresh > 1.+PETSC_SMALL) {
772d16cbb6bSStefano Zampini 
773d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
77408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
775f6f667cfSStefano 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));
77608122e43SStefano Zampini #else
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,B_iwork,B_ifail,&B_ierr));
77808122e43SStefano Zampini #endif
779d16cbb6bSStefano Zampini         } else {
780d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
781d16cbb6bSStefano Zampini           B_IL = 1;
782d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
783d16cbb6bSStefano 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));
784d16cbb6bSStefano Zampini #else
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,B_iwork,B_ifail,&B_ierr));
786d16cbb6bSStefano Zampini #endif
787d16cbb6bSStefano Zampini         }
78808122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
78908122e43SStefano Zampini         if (B_ierr) {
79008122e43SStefano Zampini           if (B_ierr < 0 ) {
79108122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
79208122e43SStefano Zampini           } else if (B_ierr <= B_N) {
79308122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
79408122e43SStefano Zampini           } else {
7959552c7c7SStefano 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);
79608122e43SStefano Zampini           }
79708122e43SStefano Zampini         }
79808122e43SStefano Zampini 
79908122e43SStefano Zampini         if (B_neigs > nmax) {
800fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
801fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
802fd14bc51SStefano Zampini           }
803f6f667cfSStefano Zampini           eigs_start = B_neigs -nmax;
80408122e43SStefano Zampini           B_neigs = nmax;
80508122e43SStefano Zampini         }
80608122e43SStefano Zampini 
8079552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
8089552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
80908122e43SStefano Zampini           PetscBLASInt B_neigs2;
81008122e43SStefano Zampini 
811f6f667cfSStefano Zampini           B_IU = B_N - B_neigs;
812f6f667cfSStefano Zampini           B_IL = B_N - nmin_s + 1;
813fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
814fd14bc51SStefano 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);
815fd14bc51SStefano Zampini           }
8169ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
81708122e43SStefano Zampini             PetscInt j;
81808122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
81908122e43SStefano Zampini               ierr = PetscMemcpy(S+j*(subset_size+1),Sarray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
82008122e43SStefano Zampini             }
82108122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
82208122e43SStefano Zampini               ierr = PetscMemcpy(St+j*(subset_size+1),Starray+cumarray+j*(subset_size+1),(subset_size-j)*sizeof(PetscScalar));CHKERRQ(ierr);
82308122e43SStefano Zampini             }
82408122e43SStefano Zampini           } else {
82508122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
82608122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
82708122e43SStefano Zampini           }
82808122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
82908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
830f6f667cfSStefano 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));
83108122e43SStefano Zampini #else
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,B_iwork,B_ifail,&B_ierr));
83308122e43SStefano Zampini #endif
83408122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
83508122e43SStefano Zampini           B_neigs += B_neigs2;
83608122e43SStefano Zampini         }
83708122e43SStefano Zampini         if (B_ierr) {
83808122e43SStefano Zampini           if (B_ierr < 0 ) {
83908122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
84008122e43SStefano Zampini           } else if (B_ierr <= B_N) {
84108122e43SStefano Zampini             SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
84208122e43SStefano Zampini           } else {
8439552c7c7SStefano 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);
84408122e43SStefano Zampini           }
84508122e43SStefano Zampini         }
846fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
847ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
84808122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
84908122e43SStefano Zampini             if (eigs[j] == 0.0) {
850ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
85108122e43SStefano Zampini             } else {
852ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
853fd14bc51SStefano Zampini             }
85408122e43SStefano Zampini           }
85508122e43SStefano Zampini         }
85608122e43SStefano Zampini       } else {
85708122e43SStefano Zampini           /* TODO */
85808122e43SStefano Zampini       }
859aff50787SStefano Zampini     }
8608bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
8618bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
8629162d606SStefano Zampini     if (B_neigs) {
8639162d606SStefano 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);
864fd14bc51SStefano Zampini 
865fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
8669552c7c7SStefano Zampini         PetscInt ii;
8679552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
868ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
8699552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
870ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
871ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
872ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
873ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
874ac47001eSStefano Zampini #else
875ac47001eSStefano 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);
876ac47001eSStefano Zampini #endif
8779552c7c7SStefano Zampini           }
8789552c7c7SStefano Zampini         }
879fd14bc51SStefano Zampini       }
88008122e43SStefano Zampini #if 0
8819162d606SStefano Zampini       for (j=0;j<B_neigs;j++) {
88208122e43SStefano Zampini         PetscBLASInt Blas_N,Blas_one = 1.0;
88308122e43SStefano Zampini         PetscScalar norm;
88408122e43SStefano Zampini         ierr = PetscBLASIntCast(subset_size,&Blas_N);CHKERRQ(ierr);
8859162d606SStefano Zampini         PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,
8869162d606SStefano Zampini                                                    &Blas_one,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,&Blas_one));
88708122e43SStefano Zampini         if (pcbddc->adaptive_constraints_data[cum2] > 0.0) {
88808122e43SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
88908122e43SStefano Zampini         } else {
89008122e43SStefano Zampini           norm = -1.0/PetscSqrtReal(PetscRealPart(norm));
89108122e43SStefano Zampini         }
8929162d606SStefano Zampini         PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,pcbddc->adaptive_constraints_data+pcbddc->adaptive_constraints_data_ptr[cum]+j*subset_size,&Blas_one));
893b1b3d7a2SStefano Zampini       }
894b1b3d7a2SStefano Zampini #endif
8959162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
8969162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
8979162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
8989162d606SStefano Zampini       cum++;
89908122e43SStefano Zampini     }
90008122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
90108122e43SStefano Zampini     /* shift for next computation */
90208122e43SStefano Zampini     cumarray += subset_size*subset_size;
90308122e43SStefano Zampini   }
904fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
905fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
906fd14bc51SStefano Zampini   }
90708122e43SStefano Zampini 
90808122e43SStefano Zampini   if (mss) {
90908122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
91008122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
911f6f667cfSStefano Zampini     /* destroy matrices (junk) */
912f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
913f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
91408122e43SStefano Zampini   }
915f6f667cfSStefano Zampini   if (allocated_S_St) {
916f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
917f6f667cfSStefano Zampini   }
918f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
91908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
92008122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
92108122e43SStefano Zampini #endif
92208122e43SStefano Zampini   if (pcbddc->dbg_flag) {
9231b968477SStefano Zampini     PetscInt maxneigs_r;
92408122e43SStefano Zampini     ierr = MPI_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
9259b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
92608122e43SStefano Zampini   }
92708122e43SStefano Zampini   PetscFunctionReturn(0);
92808122e43SStefano Zampini }
929b1b3d7a2SStefano Zampini 
930674ae819SStefano Zampini #undef __FUNCT__
931c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
932c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
933c8587f34SStefano Zampini {
934c8587f34SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
9358629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
936c8587f34SStefano Zampini   PetscErrorCode ierr;
937c8587f34SStefano Zampini 
938c8587f34SStefano Zampini   PetscFunctionBegin;
939f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
9405e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
941c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
942c8587f34SStefano Zampini 
943684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
9440fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
945684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
946c8587f34SStefano Zampini 
947c8587f34SStefano Zampini   /* Change global null space passed in by the user if change of basis has been requested */
948b9b85e73SStefano Zampini   if (pcbddc->NullSpace && pcbddc->ChangeOfBasisMatrix) {
949c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAdaptGlobal(pc);CHKERRQ(ierr);
950c8587f34SStefano Zampini   }
951c8587f34SStefano Zampini 
9528629588bSStefano Zampini   /*
9538629588bSStefano Zampini      Setup local correction and local part of coarse basis.
9548629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
9558629588bSStefano Zampini   */
95647f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
9578629588bSStefano Zampini 
9588629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
9598629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
9608629588bSStefano Zampini 
9618629588bSStefano Zampini   /* free */
9628629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
963c8587f34SStefano Zampini   PetscFunctionReturn(0);
964c8587f34SStefano Zampini }
965c8587f34SStefano Zampini 
966c8587f34SStefano Zampini #undef __FUNCT__
967674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
968674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
969674ae819SStefano Zampini {
970674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
971674ae819SStefano Zampini   PetscErrorCode ierr;
972674ae819SStefano Zampini 
973674ae819SStefano Zampini   PetscFunctionBegin;
974674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
975674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
97630368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
977674ae819SStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
978674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
979785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
980674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
981f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
982f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
983785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
98463602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
98563602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
986674ae819SStefano Zampini   PetscFunctionReturn(0);
987674ae819SStefano Zampini }
988674ae819SStefano Zampini 
989674ae819SStefano Zampini #undef __FUNCT__
990674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
991674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
992674ae819SStefano Zampini {
993674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
9944f1b2e48SStefano Zampini   PetscInt       i;
995674ae819SStefano Zampini   PetscErrorCode ierr;
996674ae819SStefano Zampini 
997674ae819SStefano Zampini   PetscFunctionBegin;
998b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
999674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
1000674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
1001674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
10024f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
10034f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
10044f1b2e48SStefano Zampini   }
10054f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
1006b96c3477SStefano Zampini   ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
1007674ae819SStefano Zampini   PetscFunctionReturn(0);
1008674ae819SStefano Zampini }
1009674ae819SStefano Zampini 
1010674ae819SStefano Zampini #undef __FUNCT__
1011674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
1012674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
1013674ae819SStefano Zampini {
1014674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
101506656605SStefano Zampini   PetscScalar    *array;
1016674ae819SStefano Zampini   PetscErrorCode ierr;
1017674ae819SStefano Zampini 
1018674ae819SStefano Zampini   PetscFunctionBegin;
1019674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
102058da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
102106656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
102206656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
102358da7f69SStefano Zampini   }
1024674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1025674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
102615aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
102715aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
1028674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
1029674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
1030674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
103106656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
1032674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
1033674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
10348ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
1035674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
1036674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
1037674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
1038f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
1039f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
1040f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
1041f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
1042727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
10430e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
1044f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
104570cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
10466e683305SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
104781d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
10480369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
10498b9f24d4SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
10504f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr);
10514f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
10528b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
10534f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
1054674ae819SStefano Zampini   PetscFunctionReturn(0);
1055674ae819SStefano Zampini }
1056674ae819SStefano Zampini 
1057674ae819SStefano Zampini #undef __FUNCT__
1058f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
1059f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
10606bfb1811SStefano Zampini {
10616bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
10626bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
10636bfb1811SStefano Zampini   VecType        impVecType;
10644f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
10656bfb1811SStefano Zampini   PetscErrorCode ierr;
10666bfb1811SStefano Zampini 
10676bfb1811SStefano Zampini   PetscFunctionBegin;
1068f4ddd8eeSStefano Zampini   if (!pcbddc->ConstraintMatrix) {
1069019a44ceSStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
1070f4ddd8eeSStefano Zampini   }
1071e7b262bdSStefano Zampini   /* get sizes */
10724f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
1073b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
10746bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
1075e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
1076e7b262bdSStefano Zampini   /* R nodes */
1077e7b262bdSStefano Zampini   old_size = -1;
1078e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
1079e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
1080e7b262bdSStefano Zampini   }
1081e7b262bdSStefano Zampini   if (n_R != old_size) {
1082e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
1083e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
10846bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
10856bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
10866bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
10876bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
1088e7b262bdSStefano Zampini   }
1089e7b262bdSStefano Zampini   /* local primal dofs */
1090e7b262bdSStefano Zampini   old_size = -1;
1091e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
1092e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
1093e7b262bdSStefano Zampini   }
1094e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
1095e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
109683b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
1097e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
10986bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
1099e7b262bdSStefano Zampini   }
1100e7b262bdSStefano Zampini   /* local explicit constraints */
1101e7b262bdSStefano Zampini   old_size = -1;
1102e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
1103e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
1104e7b262bdSStefano Zampini   }
1105e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
1106e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
110783b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
110883b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
110983b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
111083b7ccabSStefano Zampini   }
11116bfb1811SStefano Zampini   PetscFunctionReturn(0);
11126bfb1811SStefano Zampini }
11136bfb1811SStefano Zampini 
11146bfb1811SStefano Zampini #undef __FUNCT__
111547f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
111647f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
111788ebb749SStefano Zampini {
111825084f0cSStefano Zampini   PetscErrorCode  ierr;
111925084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
112088ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
112188ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1122d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
112325084f0cSStefano Zampini   /* submatrices of local problem */
112480677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
1125019a44ceSStefano Zampini   /* submatrices of benign trick */
1126d16cbb6bSStefano Zampini   Mat             B0_V = NULL;
112706656605SStefano Zampini   /* submatrices of local coarse problem */
112806656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
112925084f0cSStefano Zampini   /* working matrices */
113006656605SStefano Zampini   Mat             C_CR;
113125084f0cSStefano Zampini   /* additional working stuff */
113206656605SStefano Zampini   PC              pc_R;
11334f1b2e48SStefano Zampini   Mat             F;
113406656605SStefano Zampini   PetscBool       isLU,isCHOL,isILU;
113506656605SStefano Zampini 
113625084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
113706656605SStefano Zampini   PetscScalar     *work;
113806656605SStefano Zampini   PetscInt        *idx_V_B;
1139*ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
114006656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
1141*ffd830a3SStefano Zampini 
114225084f0cSStefano Zampini   /* some shortcuts to scalars */
114306656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
114488ebb749SStefano Zampini 
114588ebb749SStefano Zampini   PetscFunctionBegin;
1146*ffd830a3SStefano Zampini   if (!pcbddc->symmetric_primal && pcbddc->benign_n) {
1147*ffd830a3SStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Non-symmetric primal basis computation with benign trick not yet implemented");
1148*ffd830a3SStefano Zampini   }
1149*ffd830a3SStefano Zampini 
1150*ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
1151b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
11524f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
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   /* vertices in boundary numbering */
1158785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
11590e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
116088ebb749SStefano Zampini   if (i != n_vertices) {
116122d5777bSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %d != %d\n",n_vertices,i);
116288ebb749SStefano Zampini   }
116388ebb749SStefano Zampini 
116406656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
1165019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
116606656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
116706656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
116806656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
116906656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
117006656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
117106656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
117206656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
117306656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
117406656605SStefano Zampini 
117506656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
117606656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
117706656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
117806656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
117906656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
1180*ffd830a3SStefano Zampini   lda_rhs = n_R;
118106656605SStefano Zampini   if (isLU || isILU || isCHOL) {
118206656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
1183d62866d3SStefano Zampini   } else if (sub_schurs->reuse_mumps) {
1184d62866d3SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
1185d62866d3SStefano Zampini     MatFactorType type;
1186d62866d3SStefano Zampini 
11876816873aSStefano Zampini     F = reuse_mumps->F;
11886816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
1189d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
1190*ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
119106656605SStefano Zampini   } else {
119206656605SStefano Zampini     F = NULL;
119306656605SStefano Zampini   }
119406656605SStefano Zampini 
1195*ffd830a3SStefano Zampini   /* allocate workspace */
1196*ffd830a3SStefano Zampini   n = 0;
1197*ffd830a3SStefano Zampini   if (n_constraints) {
1198*ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
1199*ffd830a3SStefano Zampini   }
1200*ffd830a3SStefano Zampini   if (n_vertices) {
1201*ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
1202*ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
1203*ffd830a3SStefano Zampini   }
1204*ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
1205*ffd830a3SStefano Zampini 
120688ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
120788ebb749SStefano Zampini   if (n_constraints) {
120806656605SStefano Zampini     Mat         M1,M2,M3;
120980677318SStefano Zampini     Mat         auxmat;
121006656605SStefano Zampini     IS          is_aux;
121180677318SStefano Zampini     PetscScalar *array,*array2;
121206656605SStefano Zampini 
1213f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
121480677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
121588ebb749SStefano Zampini 
121625084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
121725084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
12188ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
121980677318SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&auxmat);CHKERRQ(ierr);
122088ebb749SStefano Zampini 
122180677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
122280677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
1223*ffd830a3SStefano Zampini     ierr = PetscMemzero(work,lda_rhs*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
122488ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
122506656605SStefano Zampini       const PetscScalar *row_cmat_values;
122606656605SStefano Zampini       const PetscInt    *row_cmat_indices;
122706656605SStefano Zampini       PetscInt          size_of_constraint,j;
122888ebb749SStefano Zampini 
122906656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
123006656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
1231*ffd830a3SStefano Zampini         work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
123206656605SStefano Zampini       }
123306656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
123406656605SStefano Zampini     }
1235*ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
123606656605SStefano Zampini     if (F) {
123706656605SStefano Zampini       Mat B;
123806656605SStefano Zampini 
1239*ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
124080677318SStefano Zampini       ierr = MatMatSolve(F,B,local_auxmat2_R);CHKERRQ(ierr);
124106656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
124206656605SStefano Zampini     } else {
124380677318SStefano Zampini       PetscScalar *marr;
124480677318SStefano Zampini 
124580677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
124606656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
1247*ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
1248*ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
124906656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
125006656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
125106656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
125206656605SStefano Zampini       }
125380677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
125406656605SStefano Zampini     }
125580677318SStefano Zampini     if (!pcbddc->switch_static) {
125680677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
125780677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
125880677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
125980677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
1260*ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
126180677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
126280677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
126380677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
126480677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
126580677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
126680677318SStefano Zampini       }
126780677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
126880677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
126980677318SStefano Zampini       ierr = MatMatMult(auxmat,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
127080677318SStefano Zampini     } else {
1271*ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
1272*ffd830a3SStefano Zampini         IS dummy;
1273*ffd830a3SStefano Zampini 
1274*ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
1275*ffd830a3SStefano Zampini         ierr = MatGetSubMatrix(local_auxmat2_R,dummy,dummy,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
1276*ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1277*ffd830a3SStefano Zampini       } else {
127880677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
127980677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
1280*ffd830a3SStefano Zampini       }
128125084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
128280677318SStefano Zampini     }
128380677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
128480677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
128580677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
128606656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
128706656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
128880677318SStefano Zampini     if (isCHOL) {
128980677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
129080677318SStefano Zampini     } else {
129125084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
129280677318SStefano Zampini     }
129380677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,one);CHKERRQ(ierr);
129406656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
129525084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
129625084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
129725084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
129880677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
129980677318SStefano Zampini     ierr = MatMatMult(M1,auxmat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
130080677318SStefano Zampini     ierr = MatDestroy(&auxmat);CHKERRQ(ierr);
130106656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
130206656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
1303f4ddd8eeSStefano Zampini   }
130488ebb749SStefano Zampini   /* Get submatrices from subdomain matrix */
13054f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
1306d16cbb6bSStefano Zampini     IS        dummy;
1307d16cbb6bSStefano Zampini     Mat       B0_R;
1308d16cbb6bSStefano Zampini     PetscReal norm;
1309d16cbb6bSStefano Zampini 
13104f1b2e48SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
13114f1b2e48SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&B0_R);CHKERRQ(ierr);
1312d16cbb6bSStefano Zampini     ierr = MatNorm(B0_R,NORM_INFINITY,&norm);CHKERRQ(ierr);
1313d16cbb6bSStefano Zampini     if (norm > PETSC_SMALL) {
1314d16cbb6bSStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! ||B0_R|| = %f (should be numerically 0.)",norm);
1315d16cbb6bSStefano Zampini     }
1316d16cbb6bSStefano Zampini     ierr = MatDestroy(&B0_R);CHKERRQ(ierr);
1317d16cbb6bSStefano Zampini     ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1318d16cbb6bSStefano Zampini   }
1319d16cbb6bSStefano Zampini 
132088ebb749SStefano Zampini   if (n_vertices) {
132106656605SStefano Zampini     IS is_aux;
13223a50541eSStefano Zampini 
13236816873aSStefano Zampini     if (sub_schurs->reuse_mumps) { /* is_R_local is not sorted, ISComplement doesn't like it */
13246816873aSStefano Zampini       IS tis;
13256816873aSStefano Zampini 
13266816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
13276816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
13286816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
13296816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
13306816873aSStefano Zampini     } else {
13313a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
13326816873aSStefano Zampini     }
13339577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
13349577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
133504708bb6SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
13364f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
1337019a44ceSStefano Zampini       IS dummy;
1338019a44ceSStefano Zampini 
13394f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
13404f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,is_aux,MAT_INITIAL_MATRIX,&B0_V);CHKERRQ(ierr);
1341019a44ceSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1342019a44ceSStefano Zampini     }
134325084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
134488ebb749SStefano Zampini   }
134588ebb749SStefano Zampini 
134688ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
1347f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
134806656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
134906656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
135006656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
135106656605SStefano Zampini     }
1352f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
135306656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
135406656605SStefano Zampini       PetscScalar *marray;
135506656605SStefano Zampini 
135606656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
135706656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
1358f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1359f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
1360f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
1361f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
1362f4ddd8eeSStefano Zampini     }
1363f4ddd8eeSStefano Zampini   }
136406656605SStefano Zampini 
1365f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
136606656605SStefano Zampini     PetscScalar *marray;
136788ebb749SStefano Zampini 
136806656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
13698eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
137006656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
137188ebb749SStefano Zampini     }
13723301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
137306656605SStefano Zampini       n *= 2;
137488ebb749SStefano Zampini     }
137506656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
137606656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
137706656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
13788eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
137906656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
138006656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
138188ebb749SStefano Zampini     }
13823301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
138306656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
13848eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
138506656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
138606656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
138788ebb749SStefano Zampini       }
138888ebb749SStefano Zampini     } else {
1389c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
1390c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
13911b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
1392c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
1393c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
1394c0553b1fSStefano Zampini       }
139588ebb749SStefano Zampini     }
139606656605SStefano Zampini   }
1397019a44ceSStefano Zampini 
139806656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
13994f1b2e48SStefano Zampini   p0_lidx_I = NULL;
14004f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
1401d12edf2fSStefano Zampini     const PetscInt *idxs;
1402d12edf2fSStefano Zampini 
1403d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
14044f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
14054f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
14064f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
14074f1b2e48SStefano Zampini     }
1408d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
1409d12edf2fSStefano Zampini   }
1410d16cbb6bSStefano Zampini 
141106656605SStefano Zampini   /* vertices */
141206656605SStefano Zampini   if (n_vertices) {
141316f15bc4SStefano Zampini 
1414*ffd830a3SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_REUSE_MATRIX,&A_VV);CHKERRQ(ierr);
141504708bb6SStefano Zampini 
141616f15bc4SStefano Zampini     if (n_R) {
141706656605SStefano Zampini       Mat          A_RRmA_RV,S_VVt; /* S_VVt with LDA=N */
141806656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
141916f15bc4SStefano Zampini       PetscScalar  *x,*y;
142004708bb6SStefano Zampini       PetscBool    isseqaij;
142106656605SStefano Zampini 
142221eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
1423*ffd830a3SStefano Zampini       if (lda_rhs == n_R) {
1424*ffd830a3SStefano Zampini         ierr = MatConvert(A_RV,MATDENSE,MAT_REUSE_MATRIX,&A_RV);CHKERRQ(ierr);
1425*ffd830a3SStefano Zampini       } else {
1426*ffd830a3SStefano Zampini         Mat         A_RVt;
1427*ffd830a3SStefano Zampini         PetscScalar *array;
1428*ffd830a3SStefano Zampini 
1429*ffd830a3SStefano Zampini         /* TODO optimize */
1430*ffd830a3SStefano Zampini         ierr = MatConvert(A_RV,MATDENSE,MAT_INITIAL_MATRIX,&A_RVt);CHKERRQ(ierr);
1431*ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
1432*ffd830a3SStefano Zampini         ierr = PetscMemzero(work+lda_rhs*n_vertices,lda_rhs*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
1433*ffd830a3SStefano Zampini         ierr = MatDenseGetArray(A_RVt,&array);CHKERRQ(ierr);
1434*ffd830a3SStefano Zampini         for (i=0;i<n_vertices;i++) {
1435*ffd830a3SStefano Zampini           ierr = PetscMemcpy(work+(n_vertices+i)*lda_rhs,array+i*n_R,n_R*sizeof(PetscScalar));CHKERRQ(ierr);
1436*ffd830a3SStefano Zampini         }
1437*ffd830a3SStefano Zampini         ierr = MatDenseRestoreArray(A_RVt,&array);CHKERRQ(ierr);
1438*ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RVt);CHKERRQ(ierr);
1439*ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&A_RV);CHKERRQ(ierr);
1440*ffd830a3SStefano Zampini       }
1441*ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
14426816873aSStefano Zampini       if (F) { /* TODO could be optimized for symmetric problems */
144306656605SStefano Zampini         ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
144406656605SStefano Zampini       } else {
144506656605SStefano Zampini         ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
144606656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
1447*ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
1448*ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
144906656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
145006656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
145106656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
145206656605SStefano Zampini         }
145306656605SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
145406656605SStefano Zampini       }
145580677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
1456*ffd830a3SStefano Zampini       /* S_VV and S_CV */
145706656605SStefano Zampini       if (n_constraints) {
145806656605SStefano Zampini         Mat B;
145980677318SStefano Zampini 
1460*ffd830a3SStefano Zampini         ierr = PetscMemzero(work+lda_rhs*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
146180677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
1462*ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
1463*ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
146480677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
146580677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
146680677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
146780677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
146880677318SStefano Zampini         }
1469*ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
147080677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
147180677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
1472*ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
147380677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
147406656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
1475*ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
1476*ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
147706656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
147806656605SStefano Zampini       }
147904708bb6SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
148004708bb6SStefano Zampini       if (!isseqaij) { /* MatMatMult with SEQ(S)BAIJ below will raise an error */
148104708bb6SStefano Zampini         ierr = MatConvert(A_VR,MATSEQAIJ,MAT_REUSE_MATRIX,&A_VR);CHKERRQ(ierr);
148204708bb6SStefano Zampini       }
1483*ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
1484*ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
1485*ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
1486*ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
1487*ffd830a3SStefano Zampini       }
148806656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
148980677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
149006656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
149106656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
149206656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
149306656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
149406656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
149506656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
149606656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
1497d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
1498019a44ceSStefano Zampini     } else {
1499d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
1500d16cbb6bSStefano Zampini     }
15014f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
1502019a44ceSStefano Zampini       const PetscScalar *vals;
1503019a44ceSStefano Zampini       const PetscInt    *idxs;
15044f1b2e48SStefano Zampini       PetscInt          n,j,primal_idx;
1505019a44ceSStefano Zampini 
15064f1b2e48SStefano Zampini       ierr = MatGetRow(B0_V,i,&n,&idxs,&vals);CHKERRQ(ierr);
15074f1b2e48SStefano Zampini       primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + i;
1508d16cbb6bSStefano Zampini       for (j=0;j<n;j++) {
15094f1b2e48SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+idxs[j]] = vals[j];
15104f1b2e48SStefano Zampini         coarse_submat_vals[idxs[j]*pcbddc->local_primal_size+primal_idx] = vals[j];
1511019a44ceSStefano Zampini       }
15124f1b2e48SStefano Zampini       ierr = MatRestoreRow(B0_V,i,&n,&idxs,&vals);CHKERRQ(ierr);
151316f15bc4SStefano Zampini     }
151421eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
1515d16cbb6bSStefano Zampini 
151606656605SStefano Zampini     /* coarse basis functions */
151706656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
151816f15bc4SStefano Zampini       PetscScalar *y;
151916f15bc4SStefano Zampini 
1520*ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
152106656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
152206656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
152306656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
152406656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
152506656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
152606656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
152706656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
152806656605SStefano Zampini 
152906656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
15304f1b2e48SStefano Zampini         PetscInt j;
15314f1b2e48SStefano Zampini 
153206656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
153306656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
153406656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
153506656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
153606656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
15374f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
153806656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
153906656605SStefano Zampini       }
154006656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
154106656605SStefano Zampini     }
154204708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
154304708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
154406656605SStefano Zampini   }
154506656605SStefano Zampini 
154606656605SStefano Zampini   if (n_constraints) {
154706656605SStefano Zampini     Mat B;
154806656605SStefano Zampini 
1549*ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
155006656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
155180677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
155206656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
155306656605SStefano Zampini     if (n_vertices) {
155480677318SStefano Zampini       if (isCHOL) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
155580677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
155680677318SStefano Zampini       } else {
155780677318SStefano Zampini         Mat S_VCt;
155880677318SStefano Zampini 
1559*ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
1560*ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
1561*ffd830a3SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&B);CHKERRQ(ierr);
1562*ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
1563*ffd830a3SStefano Zampini         }
156480677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
156580677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
156680677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
156780677318SStefano Zampini       }
156806656605SStefano Zampini     }
156906656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
157006656605SStefano Zampini     /* coarse basis functions */
157106656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
157206656605SStefano Zampini       PetscScalar *y;
157306656605SStefano Zampini 
1574*ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
157506656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
157606656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
157706656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
157806656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
157906656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
158006656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
158106656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
15824f1b2e48SStefano Zampini         PetscInt j;
15834f1b2e48SStefano Zampini 
158406656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
158506656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
158606656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
158706656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
158806656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
15894f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
159006656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
159106656605SStefano Zampini       }
159206656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
159306656605SStefano Zampini     }
159406656605SStefano Zampini   }
159580677318SStefano Zampini   if (n_constraints) {
159680677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
159780677318SStefano Zampini   }
15984f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
1599019a44ceSStefano Zampini   ierr = MatDestroy(&B0_V);CHKERRQ(ierr);
1600019a44ceSStefano Zampini 
160106656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
16023301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
1603*ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
1604*ffd830a3SStefano Zampini     PetscScalar *marray;
160506656605SStefano Zampini 
160606656605SStefano Zampini     if (n_constraints) {
1607*ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
160806656605SStefano Zampini 
1609*ffd830a3SStefano Zampini       ierr = MatTranspose(C_CR,MAT_INITIAL_MATRIX,&C_CRT);CHKERRQ(ierr);
161006656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
1611*ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
161216f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
161306656605SStefano Zampini       if (n_vertices) {
1614*ffd830a3SStefano Zampini         Mat S_VCT;
161506656605SStefano Zampini 
161606656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
1617*ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
161816f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
161906656605SStefano Zampini       }
1620*ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
162106656605SStefano Zampini     }
162216f15bc4SStefano Zampini     if (n_vertices && n_R) {
1623*ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
1624*ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
1625*ffd830a3SStefano Zampini       PetscInt       n;
1626*ffd830a3SStefano Zampini       PetscBool      flg_row;
162706656605SStefano Zampini 
1628*ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
1629*ffd830a3SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_REUSE_MATRIX,&A_VR);CHKERRQ(ierr);
1630*ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
1631*ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
1632*ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
1633*ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
1634*ffd830a3SStefano Zampini         PetscInt j;
1635*ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
1636*ffd830a3SStefano Zampini       }
1637*ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
1638*ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
1639*ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
164006656605SStefano Zampini     }
164106656605SStefano Zampini 
1642*ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
1643*ffd830a3SStefano Zampini     ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
1644*ffd830a3SStefano Zampini     for (i=0;i<n_vertices;i++) {
1645*ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
1646*ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
164706656605SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
164806656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
164906656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
165006656605SStefano Zampini     }
1651*ffd830a3SStefano Zampini     ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
1652*ffd830a3SStefano Zampini     ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
1653*ffd830a3SStefano Zampini     for (i=n_vertices;i<n_constraints+n_vertices;i++) {
1654*ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
1655*ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
1656*ffd830a3SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
1657*ffd830a3SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1658*ffd830a3SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
165906656605SStefano Zampini     }
1660*ffd830a3SStefano Zampini     ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
166106656605SStefano Zampini     /* coarse basis functions */
166206656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
166306656605SStefano Zampini       PetscScalar *y;
166406656605SStefano Zampini 
1665*ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
166606656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
166706656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
166806656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
166906656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
167006656605SStefano Zampini       if (i<n_vertices) {
167106656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
167206656605SStefano Zampini       }
167306656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
167406656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
167506656605SStefano Zampini 
167606656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
167706656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
167806656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
167906656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
168006656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
168106656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
168206656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
168306656605SStefano Zampini       }
168406656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
168506656605SStefano Zampini     }
1686*ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
1687*ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
168806656605SStefano Zampini   }
1689d62866d3SStefano Zampini   /* free memory */
169088ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
169106656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
169206656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
169306656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
169406656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
1695d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
1696d62866d3SStefano Zampini   if (n_vertices) {
1697d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
1698d62866d3SStefano Zampini   }
1699d62866d3SStefano Zampini   if (n_constraints) {
1700d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
1701d62866d3SStefano Zampini   }
170288ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
170388ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
170488ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
1705d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
170688ebb749SStefano Zampini     Mat         coarse_sub_mat;
170725084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
170888ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
170988ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
171088ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
17118bec7fa6SStefano Zampini     Mat         C_B,CPHI;
17128bec7fa6SStefano Zampini     IS          is_dummy;
17138bec7fa6SStefano Zampini     Vec         mones;
171488ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
171588ebb749SStefano Zampini     PetscReal   real_value;
171688ebb749SStefano Zampini 
171788ebb749SStefano Zampini     ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
171888ebb749SStefano Zampini     ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
171988ebb749SStefano Zampini     ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
172088ebb749SStefano Zampini     ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
172188ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
172288ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
1723*ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
172488ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
172588ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
172688ebb749SStefano Zampini     }
172788ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
172888ebb749SStefano Zampini 
172925084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
17303301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
173125084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1732*ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
173388ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
173488ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
173588ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
173688ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
173788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
173888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
173988ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
174088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
174188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
174288ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
174388ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
174488ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
174588ebb749SStefano Zampini     } else {
174688ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
174788ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
174888ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
174988ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
175088ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
175188ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
175288ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
175388ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
175488ebb749SStefano Zampini     }
175588ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
175688ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
175788ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
175888ebb749SStefano Zampini     ierr = MatConvert(TM1,MATSEQDENSE,MAT_REUSE_MATRIX,&TM1);CHKERRQ(ierr);
17594f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
1760d12edf2fSStefano Zampini       Mat         B0_I,B0_B,B0_BPHI,B0_IPHI;
1761d12edf2fSStefano Zampini       PetscScalar *data,*data2;
17624f1b2e48SStefano Zampini       PetscInt    j;
1763d12edf2fSStefano Zampini 
17644f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
17654f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);
17664f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_I_local,MAT_INITIAL_MATRIX,&B0_I);
1767d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
1768d12edf2fSStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_REUSE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
1769d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
1770d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
17714f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
17724f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
1773d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
17744f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
17754f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
17764f1b2e48SStefano Zampini         }
1777d12edf2fSStefano Zampini       }
1778d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
1779d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
1780d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
1781d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
1782d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
1783d12edf2fSStefano Zampini       ierr = MatMatMult(B0_I,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&B0_IPHI);CHKERRQ(ierr);
1784d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_I);CHKERRQ(ierr);
1785d12edf2fSStefano Zampini       ierr = MatNorm(B0_IPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
1786d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_IPHI);CHKERRQ(ierr);
1787d12edf2fSStefano Zampini     }
1788d12edf2fSStefano Zampini #if 0
1789d12edf2fSStefano Zampini   {
1790d12edf2fSStefano Zampini     PetscViewer viewer;
1791d12edf2fSStefano Zampini     char filename[256];
1792*ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
1793d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
1794d12edf2fSStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1795*ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
1796*ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
1797*ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
1798d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
1799*ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
1800*ffd830a3SStefano Zampini     ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
1801*ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
1802*ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
1803*ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
1804*ffd830a3SStefano Zampini     }
1805*ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
1806*ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
1807*ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
1808*ffd830a3SStefano Zampini     }
1809*ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_B) {
1810*ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
1811*ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
1812*ffd830a3SStefano Zampini     }
1813d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1814d12edf2fSStefano Zampini   }
1815d12edf2fSStefano Zampini #endif
181681d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
18178bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
18180fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
181906656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
18208bec7fa6SStefano Zampini 
18218bec7fa6SStefano Zampini     /* check constraints */
18224f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
18238bec7fa6SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&is_dummy);CHKERRQ(ierr);
18248bec7fa6SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);
18258bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
18268bec7fa6SStefano Zampini       ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
18278bec7fa6SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
18288bec7fa6SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
18298bec7fa6SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
1830bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
1831*ffd830a3SStefano Zampini       if (!pcbddc->symmetric_primal) {
1832bdae7319SStefano Zampini         ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
1833bdae7319SStefano Zampini         ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
1834bdae7319SStefano Zampini         ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
1835bdae7319SStefano Zampini         ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
1836bdae7319SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
183788ebb749SStefano Zampini       }
18388bec7fa6SStefano Zampini       ierr = MatDestroy(&C_B);CHKERRQ(ierr);
18398bec7fa6SStefano Zampini       ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
18408bec7fa6SStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
18418bec7fa6SStefano Zampini       ierr = VecDestroy(&mones);CHKERRQ(ierr);
1842d12edf2fSStefano Zampini     }
184325084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
184488ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
184588ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
184688ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
184788ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
184888ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
184988ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
185088ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
185188ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
185288ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
185388ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
1854*ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
185588ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
185688ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
185788ebb749SStefano Zampini     }
185888ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
185988ebb749SStefano Zampini   }
18608629588bSStefano Zampini   /* get back data */
18618629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
186288ebb749SStefano Zampini   PetscFunctionReturn(0);
186388ebb749SStefano Zampini }
186488ebb749SStefano Zampini 
186588ebb749SStefano Zampini #undef __FUNCT__
1866d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
1867d648f858SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
1868aa0d41d4SStefano Zampini {
1869d65f70fdSStefano Zampini   Mat            *work_mat;
1870d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
1871d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
1872d65f70fdSStefano Zampini   PetscInt       rsize,*idxs_perm_r,csize,*idxs_perm_c;
1873aa0d41d4SStefano Zampini   PetscErrorCode ierr;
1874aa0d41d4SStefano Zampini 
1875aa0d41d4SStefano Zampini   PetscFunctionBegin;
1876d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
1877d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
1878d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
1879d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
1880aa0d41d4SStefano Zampini 
1881d65f70fdSStefano Zampini   if (!rsorted) {
1882906d46d4SStefano Zampini     const PetscInt *idxs;
1883906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
1884aa0d41d4SStefano Zampini 
1885d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
1886d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
1887d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
1888d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
1889aa0d41d4SStefano Zampini     }
1890d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
1891d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
1892d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
1893d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
1894aa0d41d4SStefano Zampini     }
1895d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
1896d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
1897d65f70fdSStefano Zampini   } else {
1898d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
1899d65f70fdSStefano Zampini     isrow_s = isrow;
1900aa0d41d4SStefano Zampini   }
1901906d46d4SStefano Zampini 
1902d65f70fdSStefano Zampini   if (!csorted) {
1903d65f70fdSStefano Zampini     if (isrow == iscol) {
1904d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
1905d65f70fdSStefano Zampini       iscol_s = isrow_s;
1906d65f70fdSStefano Zampini     } else {
1907d65f70fdSStefano Zampini       const PetscInt *idxs;
1908d65f70fdSStefano Zampini       PetscInt *idxs_sorted,i;
1909906d46d4SStefano Zampini 
1910d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
1911d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
1912d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
1913d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
1914d65f70fdSStefano Zampini       }
1915d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
1916d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
1917d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
1918d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
1919d65f70fdSStefano Zampini       }
1920d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
1921d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
1922d65f70fdSStefano Zampini     }
1923d65f70fdSStefano Zampini   } else {
1924d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
1925d65f70fdSStefano Zampini     iscol_s = iscol;
1926d65f70fdSStefano Zampini   }
1927d65f70fdSStefano Zampini 
1928d648f858SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
1929d65f70fdSStefano Zampini 
1930d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
1931906d46d4SStefano Zampini     Mat      new_mat;
1932d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
1933906d46d4SStefano Zampini 
1934d65f70fdSStefano Zampini     if (!rsorted) {
1935d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
1936d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
1937d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
1938d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
1939906d46d4SStefano Zampini       }
1940d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
1941d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
1942d65f70fdSStefano Zampini     } else {
1943d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
1944906d46d4SStefano Zampini     }
1945d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
1946d65f70fdSStefano Zampini 
1947d65f70fdSStefano Zampini     if (!csorted) {
1948d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
1949d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
1950d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
1951d65f70fdSStefano Zampini       } else {
1952d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
1953d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
1954d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
1955d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
1956d65f70fdSStefano Zampini         }
1957d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
1958d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
1959d65f70fdSStefano Zampini       }
1960d65f70fdSStefano Zampini     } else {
1961d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
1962d65f70fdSStefano Zampini     }
1963d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
1964d65f70fdSStefano Zampini 
1965d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
1966d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
1967d65f70fdSStefano Zampini     work_mat[0] = new_mat;
1968d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
1969d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
1970d65f70fdSStefano Zampini   }
1971d65f70fdSStefano Zampini 
1972d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
1973d65f70fdSStefano Zampini   *B = work_mat[0];
1974d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
1975d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
1976d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
1977d65f70fdSStefano Zampini   PetscFunctionReturn(0);
1978d65f70fdSStefano Zampini }
1979d65f70fdSStefano Zampini 
1980d65f70fdSStefano Zampini #undef __FUNCT__
19815e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
19825e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
1983aa0d41d4SStefano Zampini {
1984aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
19855e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
1986d65f70fdSStefano Zampini   Mat            new_mat;
19875e8657edSStefano Zampini   IS             is_local,is_global;
1988d65f70fdSStefano Zampini   PetscInt       local_size;
1989d65f70fdSStefano Zampini   PetscBool      isseqaij;
1990aa0d41d4SStefano Zampini   PetscErrorCode ierr;
1991aa0d41d4SStefano Zampini 
1992aa0d41d4SStefano Zampini   PetscFunctionBegin;
1993aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
19945e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
19955e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
1996b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
1997aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
1998d648f858SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
1999aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
2000906d46d4SStefano Zampini 
2001906d46d4SStefano Zampini   /* check */
2002906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
2003906d46d4SStefano Zampini     Vec       x,x_change;
2004906d46d4SStefano Zampini     PetscReal error;
2005906d46d4SStefano Zampini 
20065e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
2007906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
20085e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
2009e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2010e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2011d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
2012e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2013e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2014906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
2015906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
2016906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2017906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
2018906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
2019906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
2020906d46d4SStefano Zampini   }
2021906d46d4SStefano Zampini 
202222d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
20239b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
202422d5777bSStefano Zampini   if (isseqaij) {
20251cf9b237SStefano Zampini     Mat M;
20261cf9b237SStefano Zampini 
20271cf9b237SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
20281cf9b237SStefano Zampini     ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
20291cf9b237SStefano Zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
2030aa0d41d4SStefano Zampini   } else {
20311cf9b237SStefano Zampini     Mat work_mat,M;
20321cf9b237SStefano Zampini 
2033aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
20341cf9b237SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
20351cf9b237SStefano Zampini     ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
20361cf9b237SStefano Zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
2037aa0d41d4SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
2038aa0d41d4SStefano Zampini   }
20393301b35fSStefano Zampini   if (matis->A->symmetric_set) {
20403301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
2041e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
20423301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
2043e496cd5dSStefano Zampini #endif
20443301b35fSStefano Zampini   }
204545a1bb75SStefano Zampini   /*
204645a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2047d65f70fdSStefano Zampini   ierr = MatView(new_mat,(PetscViewer)0);CHKERRQ(ierr);
204845a1bb75SStefano Zampini   */
2049d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
2050aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
2051aa0d41d4SStefano Zampini }
2052aa0d41d4SStefano Zampini 
2053aa0d41d4SStefano Zampini #undef __FUNCT__
2054a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
20558ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
2056a64d13efSStefano Zampini {
2057a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
2058a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
2059d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
206053892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
20613a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
20623a50541eSStefano Zampini   PetscInt        vbs,bs;
20636816873aSStefano Zampini   PetscBT         bitmask=NULL;
2064a64d13efSStefano Zampini   PetscErrorCode  ierr;
2065a64d13efSStefano Zampini 
2066a64d13efSStefano Zampini   PetscFunctionBegin;
2067b23d619eSStefano Zampini   /*
2068b23d619eSStefano Zampini     No need to setup local scatters if
2069b23d619eSStefano Zampini       - primal space is unchanged
2070b23d619eSStefano Zampini         AND
2071b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
2072b23d619eSStefano Zampini         AND
2073b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
2074b23d619eSStefano Zampini   */
2075b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
2076f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
2077f4ddd8eeSStefano Zampini   }
2078f4ddd8eeSStefano Zampini   /* destroy old objects */
2079f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
2080f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
2081f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
2082a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
2083b371cd4fSStefano Zampini   n_B = pcis->n_B;
2084b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
2085b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
20863a50541eSStefano Zampini 
2087a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
20886816873aSStefano Zampini 
208953892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
20906816873aSStefano Zampini   if (!sub_schurs->reuse_mumps) {
2091854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
2092a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
2093a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
20940e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
2095a64d13efSStefano Zampini     }
2096a64d13efSStefano Zampini 
2097a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
20984641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
20996816873aSStefano Zampini         idx_R_local[n_R++] = i;
2100a64d13efSStefano Zampini       }
2101a64d13efSStefano Zampini     }
210253892102SStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing MUMPS Schur solver */
21036816873aSStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
21046816873aSStefano Zampini 
210553892102SStefano Zampini     ierr = ISGetIndices(reuse_mumps->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
210653892102SStefano Zampini     ierr = ISGetLocalSize(reuse_mumps->is_R,&n_R);CHKERRQ(ierr);
21076816873aSStefano Zampini   }
21083a50541eSStefano Zampini 
21093a50541eSStefano Zampini   /* Block code */
21103a50541eSStefano Zampini   vbs = 1;
21113a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
21123a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
21133a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
21143a50541eSStefano Zampini     PetscInt  *vary;
2115d3df7717SStefano Zampini     if (!sub_schurs->reuse_mumps) {
2116785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
21173a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
2118d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
2119d3df7717SStefano 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 */
21200e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
2121d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
21223a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
21233a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
21243a50541eSStefano Zampini           break;
21253a50541eSStefano Zampini         }
21263a50541eSStefano Zampini       }
2127d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
2128d3df7717SStefano Zampini     } else {
2129d3df7717SStefano Zampini       /* Verify directly the R set */
2130d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
2131d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
2132d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
2133d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
2134d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
2135d3df7717SStefano Zampini             break;
2136d3df7717SStefano Zampini           }
2137d3df7717SStefano Zampini         }
2138d3df7717SStefano Zampini       }
2139d3df7717SStefano Zampini     }
21403a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
21413a50541eSStefano Zampini       vbs = bs;
21423a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
21433a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
21443a50541eSStefano Zampini       }
21453a50541eSStefano Zampini     }
21463a50541eSStefano Zampini   }
21473a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
214853892102SStefano Zampini   if (sub_schurs->reuse_mumps) {
214953892102SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
215053892102SStefano Zampini 
215153892102SStefano Zampini     ierr = ISRestoreIndices(reuse_mumps->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
215253892102SStefano Zampini     ierr = ISDestroy(&reuse_mumps->is_R);CHKERRQ(ierr);
215353892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
215453892102SStefano Zampini     reuse_mumps->is_R = pcbddc->is_R_local;
215553892102SStefano Zampini   } else {
21563a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
215753892102SStefano Zampini   }
2158a64d13efSStefano Zampini 
2159a64d13efSStefano Zampini   /* print some info if requested */
2160a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
2161a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2162a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
21630fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
2164a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
2165a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
21664f1b2e48SStefano 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);
2167a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2168a64d13efSStefano Zampini   }
2169a64d13efSStefano Zampini 
2170a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
21716816873aSStefano Zampini   if (!sub_schurs->reuse_mumps) {
21726816873aSStefano Zampini     IS       is_aux1,is_aux2;
21736816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
21746816873aSStefano Zampini 
21753a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2176854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
2177854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
2178a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
21794641a718SStefano Zampini     for (i=0; i<n_D; i++) {
21804641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
21814641a718SStefano Zampini     }
2182a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2183a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
21844641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
21854641a718SStefano Zampini         aux_array1[j++] = i;
2186a64d13efSStefano Zampini       }
2187a64d13efSStefano Zampini     }
2188a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
2189a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2190a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
21914641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
21924641a718SStefano Zampini         aux_array2[j++] = i;
2193a64d13efSStefano Zampini       }
2194a64d13efSStefano Zampini     }
2195a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2196a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
2197a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
2198a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
2199a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
2200a64d13efSStefano Zampini 
22018eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
2202785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
2203a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
22044641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
22054641a718SStefano Zampini           aux_array1[j++] = i;
2206a64d13efSStefano Zampini         }
2207a64d13efSStefano Zampini       }
2208a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
2209a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
2210a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
2211a64d13efSStefano Zampini     }
22124641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
22133a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2214d62866d3SStefano Zampini   } else {
221553892102SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
22166816873aSStefano Zampini     IS               tis;
22176816873aSStefano Zampini     PetscInt         schur_size;
22186816873aSStefano Zampini 
221953892102SStefano Zampini     ierr = ISGetLocalSize(reuse_mumps->is_B,&schur_size);CHKERRQ(ierr);
22206816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
222153892102SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_mumps->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
22226816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
22236816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
22246816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
22256816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
22266816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
2227d62866d3SStefano Zampini     }
2228d62866d3SStefano Zampini   }
2229a64d13efSStefano Zampini   PetscFunctionReturn(0);
2230a64d13efSStefano Zampini }
2231a64d13efSStefano Zampini 
2232304d26faSStefano Zampini 
2233304d26faSStefano Zampini #undef __FUNCT__
2234304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
2235684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
2236304d26faSStefano Zampini {
2237304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2238304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
2239304d26faSStefano Zampini   PC             pc_temp;
2240304d26faSStefano Zampini   Mat            A_RR;
2241f4ddd8eeSStefano Zampini   MatReuse       reuse;
2242304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
2243304d26faSStefano Zampini   PetscReal      value;
224404708bb6SStefano Zampini   PetscInt       n_D,n_R;
22459577ea80SStefano Zampini   PetscBool      use_exact,use_exact_reduced,issbaij;
2246304d26faSStefano Zampini   PetscErrorCode ierr;
2247e604994aSStefano Zampini   /* prefixes stuff */
2248312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
2249e604994aSStefano Zampini   size_t         len;
2250304d26faSStefano Zampini 
2251304d26faSStefano Zampini   PetscFunctionBegin;
2252304d26faSStefano Zampini 
2253e604994aSStefano Zampini   /* compute prefixes */
2254e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
2255e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
2256e604994aSStefano Zampini   if (!pcbddc->current_level) {
2257e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
2258e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
2259e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
2260e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
2261e604994aSStefano Zampini   } else {
2262e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
2263312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
2264e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
2265e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
2266312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
2267312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
226834d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
226934d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
2270e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
2271e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
2272e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
2273e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
2274e604994aSStefano Zampini   }
2275e604994aSStefano Zampini 
2276304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
2277684f6988SStefano Zampini   if (dirichlet) {
2278d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
22793301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
22803301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
2281964fefecSStefano Zampini     }
2282ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
2283964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
2284304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
2285304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
2286304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
2287304d26faSStefano Zampini       /* default */
2288304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
2289e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
22909577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
2291304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
22929577ea80SStefano Zampini       if (issbaij) {
22939577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
22949577ea80SStefano Zampini       } else {
2295304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
22969577ea80SStefano Zampini       }
2297304d26faSStefano Zampini       /* Allow user's customization */
2298304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
2299304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
2300304d26faSStefano Zampini     }
2301d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
2302d62866d3SStefano Zampini     if (sub_schurs->reuse_mumps) {
2303d62866d3SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2304d62866d3SStefano Zampini 
2305d62866d3SStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_mumps->interior_solver);CHKERRQ(ierr);
2306d5574798SStefano Zampini     }
2307304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
2308304d26faSStefano Zampini     if (!n_D) {
2309304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
2310304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
2311304d26faSStefano Zampini     }
2312304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
2313304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
2314304d26faSStefano Zampini     /* set ksp_D into pcis data */
2315304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
2316304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
2317304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
2318684f6988SStefano Zampini   }
2319304d26faSStefano Zampini 
2320304d26faSStefano Zampini   /* NEUMANN PROBLEM */
2321684f6988SStefano Zampini   A_RR = 0;
2322684f6988SStefano Zampini   if (neumann) {
2323d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
232404708bb6SStefano Zampini     PetscInt        ibs,mbs;
232504708bb6SStefano Zampini     PetscBool       issbaij;
232604708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
2327f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
23288ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
2329f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
2330f4ddd8eeSStefano Zampini       PetscInt nn_R;
233181d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
2332f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
2333f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
2334f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
2335f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
2336f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2337f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
2338f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
2339727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
2340f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2341f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
2342f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
2343f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
2344f4ddd8eeSStefano Zampini         }
2345f4ddd8eeSStefano Zampini       }
2346f4ddd8eeSStefano Zampini       /* last check */
2347d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
2348f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2349f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
2350f4ddd8eeSStefano Zampini       }
2351f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
2352f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
2353f4ddd8eeSStefano Zampini     }
2354f4ddd8eeSStefano Zampini     /* extract A_RR */
2355af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
2356af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
235704708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
235804708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
235904708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
236004708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
236104708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
2362af732b37SStefano Zampini       } else {
236304708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
23646816873aSStefano Zampini       }
236504708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
236604708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
236704708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
236804708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
236904708bb6SStefano Zampini       } else {
237004708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
237104708bb6SStefano Zampini       }
237204708bb6SStefano Zampini     }
2373f4ddd8eeSStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
23743301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
23753301b35fSStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
23766816873aSStefano Zampini     }
2377f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
2378304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
2379304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
2380304d26faSStefano Zampini       /* default */
2381304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
2382e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
2383304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
23849577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
23859577ea80SStefano Zampini       if (issbaij) {
23869577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
23879577ea80SStefano Zampini       } else {
2388304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
23899577ea80SStefano Zampini       }
2390304d26faSStefano Zampini       /* Allow user's customization */
2391304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
2392304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
2393304d26faSStefano Zampini     }
2394304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
2395304d26faSStefano Zampini     if (!n_R) {
2396304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
2397304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
2398304d26faSStefano Zampini     }
2399d62866d3SStefano Zampini     /* Reuse MUMPS solver if it is present */
2400d62866d3SStefano Zampini     if (sub_schurs->reuse_mumps) {
2401d62866d3SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2402d62866d3SStefano Zampini 
2403d62866d3SStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_mumps->correction_solver);CHKERRQ(ierr);
2404d62866d3SStefano Zampini     }
2405*ffd830a3SStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
2406304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
2407304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
2408684f6988SStefano Zampini   }
24096816873aSStefano Zampini   /* free Neumann problem's matrix */
24106816873aSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
2411304d26faSStefano Zampini 
2412304d26faSStefano Zampini   /* check Dirichlet and Neumann solvers and adapt them if a nullspace correction is needed */
24130fccc4e9SStefano Zampini   if (pcbddc->NullSpace || pcbddc->dbg_flag) {
2414684f6988SStefano Zampini     if (pcbddc->dbg_flag) {
2415684f6988SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2416684f6988SStefano Zampini       ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
2417684f6988SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2418684f6988SStefano Zampini     }
2419684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
24200fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
24210fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
24220fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
24230fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
24240fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
2425304d26faSStefano Zampini       /* need to be adapted? */
2426b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
2427b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2428b8ffe317SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,use_exact_reduced);CHKERRQ(ierr);
2429304d26faSStefano Zampini       /* print info */
2430304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
2431e604994aSStefano 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);
2432304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2433304d26faSStefano Zampini       }
2434b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced && !pcbddc->switch_static) {
2435298c0119SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcis->is_I_local);CHKERRQ(ierr);
2436304d26faSStefano Zampini       }
2437684f6988SStefano Zampini     }
2438684f6988SStefano Zampini     if (neumann) { /* Neumann */
24396816873aSStefano Zampini       ierr = KSPGetOperators(pcbddc->ksp_R,&A_RR,NULL);CHKERRQ(ierr);
24400fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
24410fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
24420fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
24430fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
24440fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
2445304d26faSStefano Zampini       /* need to be adapted? */
2446b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
2447b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2448304d26faSStefano Zampini       /* print info */
2449304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
2450e604994aSStefano 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);
2451304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2452304d26faSStefano Zampini       }
2453b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced) { /* is it the right logic? */
2454298c0119SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->is_R_local);CHKERRQ(ierr);
2455304d26faSStefano Zampini       }
24560fccc4e9SStefano Zampini     }
2457684f6988SStefano Zampini   }
2458304d26faSStefano Zampini   PetscFunctionReturn(0);
2459304d26faSStefano Zampini }
2460304d26faSStefano Zampini 
2461304d26faSStefano Zampini #undef __FUNCT__
2462ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
246380677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
2464674ae819SStefano Zampini {
2465674ae819SStefano Zampini   PetscErrorCode  ierr;
2466674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
2467be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
2468674ae819SStefano Zampini 
2469674ae819SStefano Zampini   PetscFunctionBegin;
2470be83ff47SStefano Zampini   if (!sub_schurs->reuse_mumps) {
247180677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
247220c7b377SStefano Zampini   }
247380677318SStefano Zampini   if (!pcbddc->switch_static) {
247480677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
247580677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
247680677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
247720c7b377SStefano Zampini     }
2478be83ff47SStefano Zampini     if (!sub_schurs->reuse_mumps) {
247980677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
248080677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
248120c7b377SStefano Zampini     } else {
2482be83ff47SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2483be83ff47SStefano Zampini 
248453892102SStefano Zampini       ierr = VecScatterBegin(reuse_mumps->correction_scatter_B,inout_B,reuse_mumps->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
248553892102SStefano Zampini       ierr = VecScatterEnd(reuse_mumps->correction_scatter_B,inout_B,reuse_mumps->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
248620c7b377SStefano Zampini     }
2487be83ff47SStefano Zampini   } else {
248880677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
248980677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
249080677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
249180677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
249280677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
249380677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
249480677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
249580677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
249680677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2497674ae819SStefano Zampini     }
2498674ae819SStefano Zampini   }
2499be83ff47SStefano Zampini   if (!sub_schurs->reuse_mumps) {
250080677318SStefano Zampini     if (applytranspose) {
250180677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
250280677318SStefano Zampini     } else {
250380677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
250480677318SStefano Zampini     }
250553892102SStefano Zampini #if defined(PETSC_HAVE_MUMPS)
2506be83ff47SStefano Zampini   } else {
2507be83ff47SStefano Zampini     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2508be83ff47SStefano Zampini 
2509be83ff47SStefano Zampini     if (applytranspose) {
251053892102SStefano Zampini       ierr = MatMumpsSolveSchurComplementTranspose(reuse_mumps->F,reuse_mumps->rhs_B,reuse_mumps->sol_B);CHKERRQ(ierr);
2511be83ff47SStefano Zampini     } else {
251253892102SStefano Zampini       ierr = MatMumpsSolveSchurComplement(reuse_mumps->F,reuse_mumps->rhs_B,reuse_mumps->sol_B);CHKERRQ(ierr);
2513be83ff47SStefano Zampini     }
251453892102SStefano Zampini #endif
2515be83ff47SStefano Zampini   }
251680677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
251780677318SStefano Zampini   if (!pcbddc->switch_static) {
2518be83ff47SStefano Zampini     if (!sub_schurs->reuse_mumps) {
251980677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
252080677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2521be83ff47SStefano Zampini     } else {
2522be83ff47SStefano Zampini       PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
2523be83ff47SStefano Zampini 
252453892102SStefano Zampini       ierr = VecScatterBegin(reuse_mumps->correction_scatter_B,reuse_mumps->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
252553892102SStefano Zampini       ierr = VecScatterEnd(reuse_mumps->correction_scatter_B,reuse_mumps->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2526be83ff47SStefano Zampini     }
252780677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
252880677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
252980677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
253080677318SStefano Zampini     }
253180677318SStefano Zampini   } else {
253280677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
253380677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
253480677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
253580677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
253680677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
253780677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
253880677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
253980677318SStefano Zampini     }
254080677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
254180677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
254280677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
254380677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2544674ae819SStefano Zampini   }
2545674ae819SStefano Zampini   PetscFunctionReturn(0);
2546674ae819SStefano Zampini }
2547674ae819SStefano Zampini 
2548dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
2549674ae819SStefano Zampini #undef __FUNCT__
2550674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
2551dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
2552674ae819SStefano Zampini {
2553674ae819SStefano Zampini   PetscErrorCode ierr;
2554674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
2555674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
2556674ae819SStefano Zampini   const PetscScalar zero = 0.0;
2557674ae819SStefano Zampini 
2558674ae819SStefano Zampini   PetscFunctionBegin;
2559dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
2560dc359a40SStefano Zampini   if (applytranspose) {
2561674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
25628eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
2563dc359a40SStefano Zampini   } else {
2564674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
2565674ae819SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
256615aaf578SStefano Zampini   }
2567efc2fbd9SStefano Zampini 
2568efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
25694f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
2570efc2fbd9SStefano Zampini     PetscScalar *array;
25714f1b2e48SStefano Zampini     PetscInt    j;
2572efc2fbd9SStefano Zampini 
2573efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
25744f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
2575efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2576efc2fbd9SStefano Zampini   }
2577efc2fbd9SStefano Zampini 
257812edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
257912edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
258012edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
258112edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
258212edc857SStefano Zampini 
25839f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
258412edc857SStefano Zampini   /* TODO remove null space when doing multilevel */
258512edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
258651694757SStefano Zampini     Mat coarse_mat;
2587964fefecSStefano Zampini     Vec rhs,sol;
258851694757SStefano Zampini     MatNullSpace nullsp;
2589964fefecSStefano Zampini 
2590964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
2591964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
259251694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
259351694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
259451694757SStefano Zampini     if (nullsp) {
259551694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
259651694757SStefano Zampini     }
259712edc857SStefano Zampini     if (applytranspose) {
2598964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
259912edc857SStefano Zampini     } else {
2600964fefecSStefano Zampini       ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
260112edc857SStefano Zampini     }
260251694757SStefano Zampini     if (nullsp) {
260351694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
260451694757SStefano Zampini     }
260512edc857SStefano Zampini   }
2606674ae819SStefano Zampini 
2607674ae819SStefano Zampini   /* Local solution on R nodes */
260880677318SStefano Zampini   if (pcis->n) { /* in/out pcbddc->vec1_B,pcbddc->vec1_D */
260980677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
26109f00e9b4SStefano Zampini   }
2611674ae819SStefano Zampini 
26129f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
26139f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
261412edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2615674ae819SStefano Zampini 
2616674ae819SStefano Zampini   /* Sum contributions from two levels */
2617dc359a40SStefano Zampini   if (applytranspose) {
2618dc359a40SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
2619dc359a40SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
2620dc359a40SStefano Zampini   } else {
2621674ae819SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
26228eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
2623dc359a40SStefano Zampini   }
2624efc2fbd9SStefano Zampini   /* store p0 */
26254f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
2626efc2fbd9SStefano Zampini     PetscScalar *array;
26274f1b2e48SStefano Zampini     PetscInt    j;
2628efc2fbd9SStefano Zampini 
2629efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
26304f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
2631efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
2632efc2fbd9SStefano Zampini   }
2633674ae819SStefano Zampini   PetscFunctionReturn(0);
2634674ae819SStefano Zampini }
2635674ae819SStefano Zampini 
2636674ae819SStefano Zampini #undef __FUNCT__
2637674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
263812edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
2639674ae819SStefano Zampini {
2640674ae819SStefano Zampini   PetscErrorCode ierr;
2641674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
264258da7f69SStefano Zampini   PetscScalar    *array;
264312edc857SStefano Zampini   Vec            from,to;
2644674ae819SStefano Zampini 
2645674ae819SStefano Zampini   PetscFunctionBegin;
264612edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
264712edc857SStefano Zampini     from = pcbddc->coarse_vec;
264812edc857SStefano Zampini     to = pcbddc->vec1_P;
264912edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
265012edc857SStefano Zampini       Vec tvec;
265158da7f69SStefano Zampini 
265258da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
265358da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
265412edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
265558da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
265658da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
265758da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
265812edc857SStefano Zampini     }
265912edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
266012edc857SStefano Zampini     from = pcbddc->vec1_P;
266112edc857SStefano Zampini     to = pcbddc->coarse_vec;
266212edc857SStefano Zampini   }
266312edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
2664674ae819SStefano Zampini   PetscFunctionReturn(0);
2665674ae819SStefano Zampini }
2666674ae819SStefano Zampini 
2667674ae819SStefano Zampini #undef __FUNCT__
2668674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
266912edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
2670674ae819SStefano Zampini {
2671674ae819SStefano Zampini   PetscErrorCode ierr;
2672674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
267358da7f69SStefano Zampini   PetscScalar    *array;
267412edc857SStefano Zampini   Vec            from,to;
2675674ae819SStefano Zampini 
2676674ae819SStefano Zampini   PetscFunctionBegin;
267712edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
267812edc857SStefano Zampini     from = pcbddc->coarse_vec;
267912edc857SStefano Zampini     to = pcbddc->vec1_P;
268012edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
268112edc857SStefano Zampini     from = pcbddc->vec1_P;
268212edc857SStefano Zampini     to = pcbddc->coarse_vec;
268312edc857SStefano Zampini   }
268412edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
268512edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
268612edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
268712edc857SStefano Zampini       Vec tvec;
268858da7f69SStefano Zampini 
268912edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
269058da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
269158da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
269258da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
269358da7f69SStefano Zampini     }
269458da7f69SStefano Zampini   } else {
269558da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
269658da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
269712edc857SStefano Zampini     }
269812edc857SStefano Zampini   }
2699674ae819SStefano Zampini   PetscFunctionReturn(0);
2700674ae819SStefano Zampini }
2701674ae819SStefano Zampini 
2702984c4197SStefano Zampini /* uncomment for testing purposes */
2703984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
2704674ae819SStefano Zampini #undef __FUNCT__
2705674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
2706674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
2707674ae819SStefano Zampini {
2708674ae819SStefano Zampini   PetscErrorCode    ierr;
2709674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
2710674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
2711674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
2712984c4197SStefano Zampini   /* one and zero */
2713984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
2714984c4197SStefano Zampini   /* space to store constraints and their local indices */
27159162d606SStefano Zampini   PetscScalar       *constraints_data;
27169162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
27179162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
27189162d606SStefano Zampini   PetscInt          *constraints_n;
2719984c4197SStefano Zampini   /* iterators */
2720b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
2721984c4197SStefano Zampini   /* BLAS integers */
2722e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
2723e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
2724c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
2725727cdba6SStefano Zampini   /* reuse */
27260e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
27270e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
2728984c4197SStefano Zampini   /* change of basis */
2729b3d85658SStefano Zampini   PetscBool         qr_needed;
27309162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
2731984c4197SStefano Zampini   /* auxiliary stuff */
273264efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
27338a0068c3SStefano Zampini   PetscInt          ncc;
2734984c4197SStefano Zampini   /* some quantities */
273545a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
2736a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
2737984c4197SStefano Zampini 
2738674ae819SStefano Zampini   PetscFunctionBegin;
27398e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
27408e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
27418e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
2742088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
2743088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
27440e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
27450e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
27460e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
27470e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
27480e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
2749088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
2750cf5a6209SStefano Zampini 
2751cf5a6209SStefano Zampini   /* print some info */
2752cf5a6209SStefano Zampini   if (pcbddc->dbg_flag) {
2753cf5a6209SStefano Zampini     IS       vertices;
2754cf5a6209SStefano Zampini     PetscInt nv,nedges,nfaces;
2755cf5a6209SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
2756cf5a6209SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
2757cf5a6209SStefano Zampini     ierr = ISDestroy(&vertices);CHKERRQ(ierr);
2758cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
2759cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2760cf5a6209SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
2761fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
2762fd14bc51SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
2763cf5a6209SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2764cf5a6209SStefano Zampini   }
2765cf5a6209SStefano Zampini 
2766cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
27679162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
2768cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
2769cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
2770cf5a6209SStefano Zampini     Vec          *localnearnullsp;
2771cf5a6209SStefano Zampini     PetscScalar  *array;
2772cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
2773cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
2774674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
2775b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
2776674ae819SStefano Zampini     PetscScalar  *work;
2777674ae819SStefano Zampini     PetscReal    *singular_vals;
2778674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2779674ae819SStefano Zampini     PetscReal    *rwork;
2780674ae819SStefano Zampini #endif
2781674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2782674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
2783674ae819SStefano Zampini #else
2784964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
2785964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
2786674ae819SStefano Zampini #endif
2787674ae819SStefano Zampini 
2788674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
2789d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
2790d06fc5fdSStefano Zampini     /* free unneeded index sets */
2791d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
2792d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
2793674ae819SStefano Zampini     }
2794d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
2795d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
2796d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
2797d06fc5fdSStefano Zampini       }
2798d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
2799d06fc5fdSStefano Zampini       n_ISForEdges = 0;
2800d06fc5fdSStefano Zampini     }
2801d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
2802d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
2803d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
2804d06fc5fdSStefano Zampini       }
2805d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
2806d06fc5fdSStefano Zampini       n_ISForFaces = 0;
2807d06fc5fdSStefano Zampini     }
280870022509SStefano Zampini 
280970022509SStefano Zampini #if defined(PETSC_USE_DEBUG)
281070022509SStefano Zampini     /* HACK: when solving singular problems not using vertices, a change of basis is mandatory.
281170022509SStefano Zampini        Also use_change_of_basis should be consistent among processors */
281270022509SStefano Zampini     if (pcbddc->NullSpace) {
281370022509SStefano Zampini       PetscBool tbool[2],gbool[2];
281470022509SStefano Zampini 
281570022509SStefano Zampini       if (!ISForVertices && !pcbddc->user_ChangeOfBasisMatrix) {
2816b8ffe317SStefano Zampini         pcbddc->use_change_of_basis = PETSC_TRUE;
2817d06fc5fdSStefano Zampini         if (!ISForEdges) {
2818d06fc5fdSStefano Zampini           pcbddc->use_change_on_faces = PETSC_TRUE;
2819d06fc5fdSStefano Zampini         }
2820b8ffe317SStefano Zampini       }
2821d06fc5fdSStefano Zampini       tbool[0] = pcbddc->use_change_of_basis;
2822d06fc5fdSStefano Zampini       tbool[1] = pcbddc->use_change_on_faces;
2823d06fc5fdSStefano Zampini       ierr = MPI_Allreduce(tbool,gbool,2,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2824d06fc5fdSStefano Zampini       pcbddc->use_change_of_basis = gbool[0];
2825d06fc5fdSStefano Zampini       pcbddc->use_change_on_faces = gbool[1];
282698a51de6SStefano Zampini     }
282770022509SStefano Zampini #endif
282808122e43SStefano Zampini 
2829674ae819SStefano Zampini     /* check if near null space is attached to global mat */
2830674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
2831674ae819SStefano Zampini     if (nearnullsp) {
2832674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
2833f4ddd8eeSStefano Zampini       /* remove any stored info */
2834f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
2835f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
2836f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
2837f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
2838f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
2839473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
2840f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
2841f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
2842f4ddd8eeSStefano Zampini       }
2843984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
2844984c4197SStefano Zampini       nnsp_size = 0;
2845674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
2846674ae819SStefano Zampini     }
2847984c4197SStefano Zampini     /* get max number of constraints on a single cc */
2848984c4197SStefano Zampini     max_constraints = nnsp_size;
2849984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
2850984c4197SStefano Zampini 
2851674ae819SStefano Zampini     /*
2852674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
28539162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
28549162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
28559162d606SStefano Zampini          There can be multiple constraints per connected component
2856674ae819SStefano Zampini                                                                                                                                                            */
2857674ae819SStefano Zampini     n_vertices = 0;
2858674ae819SStefano Zampini     if (ISForVertices) {
2859674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
2860674ae819SStefano Zampini     }
28619162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
28629162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
28639162d606SStefano Zampini 
28649162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
28659162d606SStefano Zampini     total_counts *= max_constraints;
2866674ae819SStefano Zampini     total_counts += n_vertices;
28674641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
28689162d606SStefano Zampini 
2869674ae819SStefano Zampini     total_counts = 0;
2870674ae819SStefano Zampini     max_size_of_constraint = 0;
2871674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
28729162d606SStefano Zampini       IS used_is;
2873674ae819SStefano Zampini       if (i<n_ISForEdges) {
28749162d606SStefano Zampini         used_is = ISForEdges[i];
2875674ae819SStefano Zampini       } else {
28769162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
2877674ae819SStefano Zampini       }
28789162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
2879674ae819SStefano Zampini       total_counts += j;
2880674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
2881674ae819SStefano Zampini     }
28829162d606SStefano 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);
28839162d606SStefano Zampini 
2884984c4197SStefano Zampini     /* get local part of global near null space vectors */
2885785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
2886984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
2887984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
2888e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2889e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2890984c4197SStefano Zampini     }
2891674ae819SStefano Zampini 
2892242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
2893242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
2894a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
2895242a89d7SStefano Zampini 
2896984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
2897a773dcb8SStefano Zampini     if (!skip_lapack) {
2898674ae819SStefano Zampini       PetscScalar temp_work;
2899911cabfeSStefano Zampini 
2900674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
2901984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
2902785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
2903785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
2904785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
2905674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2906785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
2907674ae819SStefano Zampini #endif
2908674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
2909c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
2910c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
2911674ae819SStefano Zampini       lwork = -1;
2912674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2913674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
2914c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
2915674ae819SStefano Zampini #else
2916c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
2917674ae819SStefano Zampini #endif
2918674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
2919984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
2920674ae819SStefano Zampini #else /* on missing GESVD */
2921674ae819SStefano Zampini       /* SVD */
2922674ae819SStefano Zampini       PetscInt max_n,min_n;
2923674ae819SStefano Zampini       max_n = max_size_of_constraint;
2924984c4197SStefano Zampini       min_n = max_constraints;
2925984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
2926674ae819SStefano Zampini         min_n = max_size_of_constraint;
2927984c4197SStefano Zampini         max_n = max_constraints;
2928674ae819SStefano Zampini       }
2929785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
2930674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
2931785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
2932674ae819SStefano Zampini #endif
2933674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
2934674ae819SStefano Zampini       lwork = -1;
2935e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
2936e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
2937b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
2938674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2939674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
29409162d606SStefano 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));
2941674ae819SStefano Zampini #else
29429162d606SStefano 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));
2943674ae819SStefano Zampini #endif
2944674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
2945984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
2946984c4197SStefano Zampini #endif /* on missing GESVD */
2947674ae819SStefano Zampini       /* Allocate optimal workspace */
2948674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
2949854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
2950674ae819SStefano Zampini     }
2951674ae819SStefano Zampini     /* Now we can loop on constraining sets */
2952674ae819SStefano Zampini     total_counts = 0;
29539162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
29549162d606SStefano Zampini     constraints_data_ptr[0] = 0;
2955674ae819SStefano Zampini     /* vertices */
29569162d606SStefano Zampini     if (n_vertices) {
2957674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
29589162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
2959674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
29609162d606SStefano Zampini         constraints_n[total_counts] = 1;
29619162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
29629162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
29639162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
2964674ae819SStefano Zampini         total_counts++;
2965674ae819SStefano Zampini       }
2966674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2967674ae819SStefano Zampini       n_vertices = total_counts;
2968674ae819SStefano Zampini     }
2969984c4197SStefano Zampini 
2970674ae819SStefano Zampini     /* edges and faces */
29719162d606SStefano Zampini     total_counts_cc = total_counts;
2972911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
29739162d606SStefano Zampini       IS        used_is;
29749162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
29759162d606SStefano Zampini 
2976911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
29779162d606SStefano Zampini         used_is = ISForEdges[ncc];
2978984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
2979674ae819SStefano Zampini       } else {
29809162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
2981984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
2982674ae819SStefano Zampini       }
2983674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
29849162d606SStefano Zampini 
29859162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
29869162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2987984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
2988984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
2989674ae819SStefano Zampini       if (nnsp_has_cnst) {
29905b08dc53SStefano Zampini         PetscScalar quad_value;
29919162d606SStefano Zampini 
29929162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
29939162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
29949162d606SStefano Zampini 
2995a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
2996674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
2997a773dcb8SStefano Zampini         } else {
2998a773dcb8SStefano Zampini           quad_value = 1.0;
2999a773dcb8SStefano Zampini         }
3000674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
30019162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
3002674ae819SStefano Zampini         }
30039162d606SStefano Zampini         temp_constraints++;
3004674ae819SStefano Zampini         total_counts++;
3005674ae819SStefano Zampini       }
3006674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
3007984c4197SStefano Zampini         PetscReal real_value;
30089162d606SStefano Zampini         PetscScalar *ptr_to_data;
30099162d606SStefano Zampini 
3010984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
30119162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
3012674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
30139162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
3014674ae819SStefano Zampini         }
3015984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
3016984c4197SStefano Zampini         /* check if array is null on the connected component */
3017e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
30189162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
30195b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
3020674ae819SStefano Zampini           temp_constraints++;
3021674ae819SStefano Zampini           total_counts++;
30229162d606SStefano Zampini           if (!idxs_copied) {
30239162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
30249162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
3025674ae819SStefano Zampini           }
3026674ae819SStefano Zampini         }
30279162d606SStefano Zampini       }
30289162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
302945a1bb75SStefano Zampini       valid_constraints = temp_constraints;
3030eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
3031a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
30329162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
30339162d606SStefano Zampini 
30349162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
3035a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
30369162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
3037a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
30389162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
3039a773dcb8SStefano Zampini         } else { /* perform SVD */
3040984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
30419162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
3042674ae819SStefano Zampini 
3043674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3044984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
3045984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
3046984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
3047984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
3048984c4197SStefano Zampini                 from that computed using LAPACKgesvd
3049984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
3050984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
3051984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
3052674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
3053e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3054984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3055674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
3056674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
30579162d606SStefano 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));
3058674ae819SStefano Zampini             }
3059674ae819SStefano Zampini           }
3060e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
3061e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3062e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
3063674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
3064c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
3065674ae819SStefano Zampini #else
3066c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
3067674ae819SStefano Zampini #endif
3068674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3069984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
3070984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
3071674ae819SStefano Zampini           j = 0;
3072984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
3073674ae819SStefano Zampini           total_counts = total_counts-j;
307445a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
3075e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
3076c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3077c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3078c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
3079c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3080c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
3081c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
3082674ae819SStefano Zampini           if (j<temp_constraints) {
3083984c4197SStefano Zampini             PetscInt ii;
3084984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
3085674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
30869162d606SStefano 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));
3087674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
3088984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
3089674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
30909162d606SStefano 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];
3091674ae819SStefano Zampini               }
3092674ae819SStefano Zampini             }
3093674ae819SStefano Zampini           }
3094674ae819SStefano Zampini #else  /* on missing GESVD */
3095e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3096e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3097b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3098674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3099674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
31009162d606SStefano 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));
3101674ae819SStefano Zampini #else
31029162d606SStefano 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));
3103674ae819SStefano Zampini #endif
3104984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
3105674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3106984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
3107e310c8b4SStefano Zampini           k = temp_constraints;
3108e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
3109674ae819SStefano Zampini           j = 0;
3110e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
311145a1bb75SStefano Zampini           valid_constraints = k-j;
3112911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
3113984c4197SStefano Zampini #endif /* on missing GESVD */
3114674ae819SStefano Zampini         }
3115a773dcb8SStefano Zampini       }
31169162d606SStefano Zampini       /* update pointers information */
31179162d606SStefano Zampini       if (valid_constraints) {
31189162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
31199162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
31209162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
31219162d606SStefano Zampini         /* set change_of_basis flag */
312245a1bb75SStefano Zampini         if (boolforchange) {
3123b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
31249162d606SStefano Zampini         }
3125b3d85658SStefano Zampini         total_counts_cc++;
312645a1bb75SStefano Zampini       }
312745a1bb75SStefano Zampini     }
3128984c4197SStefano Zampini     /* free workspace */
31298f1c130eSStefano Zampini     if (!skip_lapack) {
3130984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
3131984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3132984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
3133984c4197SStefano Zampini #endif
3134984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
3135984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3136984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
3137984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
3138984c4197SStefano Zampini #endif
3139984c4197SStefano Zampini     }
3140984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
3141984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
3142984c4197SStefano Zampini     }
3143984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
3144cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
3145cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
3146cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
3147cf5a6209SStefano Zampini     }
3148cf5a6209SStefano Zampini     if (n_ISForFaces) {
3149cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
3150cf5a6209SStefano Zampini     }
3151cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
3152cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
3153cf5a6209SStefano Zampini     }
3154cf5a6209SStefano Zampini     if (n_ISForEdges) {
3155cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
3156cf5a6209SStefano Zampini     }
3157cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
315808122e43SStefano Zampini   } else {
315908122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
3160984c4197SStefano Zampini 
316108122e43SStefano Zampini     total_counts = 0;
316208122e43SStefano Zampini     n_vertices = 0;
3163d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
3164d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
316508122e43SStefano Zampini     }
316608122e43SStefano Zampini     max_constraints = 0;
31679162d606SStefano Zampini     total_counts_cc = 0;
316808122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
316908122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
31709162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
317108122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
317208122e43SStefano Zampini     }
31739162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
31749162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
31759162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
31769162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
317774d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
31789162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
31799162d606SStefano Zampini     total_counts_cc = 0;
31809162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
31819162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
31829162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
318308122e43SStefano Zampini       }
318408122e43SStefano Zampini     }
31859162d606SStefano Zampini #if 0
31869162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
31879162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
31889162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
31899162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
31909162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
31919162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
31929162d606SStefano Zampini       }
31939162d606SStefano Zampini       printf("\n");
31949162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
31959162d606SStefano Zampini     }
31961b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
31978bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
31981b968477SStefano Zampini     }
31991b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
32008bec7fa6SStefano 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]);
32011b968477SStefano Zampini     }
320208122e43SStefano Zampini #endif
320308122e43SStefano Zampini 
32048bec7fa6SStefano Zampini     max_size_of_constraint = 0;
32059162d606SStefano 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]);
32069162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
320708122e43SStefano Zampini     /* Change of basis */
3208b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
320908122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
321008122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
321108122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
3212b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
321308122e43SStefano Zampini         }
321408122e43SStefano Zampini       }
321508122e43SStefano Zampini     }
321608122e43SStefano Zampini   }
3217984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
32184f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
321908122e43SStefano Zampini 
32209162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
32219162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
32229162d606SStefano Zampini   if (i != constraints_idxs_ptr[total_counts_cc]) {
32239162d606SStefano 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);
322408122e43SStefano Zampini   }
3225674ae819SStefano Zampini 
3226674ae819SStefano Zampini   /* Create constraint matrix */
3227674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
322816f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
3229984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
3230984c4197SStefano Zampini 
3231984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
3232a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
3233a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
323474d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
3235984c4197SStefano Zampini   total_primal_vertices=0;
3236b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
32379162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
32389162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
3239984c4197SStefano Zampini     if (size_of_constraint == 1) {
32409162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
3241b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
324264efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
32439162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
32449162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
3245a717540cSStefano Zampini       }
3246b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
324774d5cdf7SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single || pcbddc->faster_deluxe) {
3248a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
3249a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
3250a717540cSStefano Zampini       }
3251fa434743SStefano Zampini     } else {
3252b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
3253fa434743SStefano Zampini     }
3254a717540cSStefano Zampini   }
3255b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
3256b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
3257674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
325870022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
3259b3d85658SStefano Zampini 
32604f1b2e48SStefano 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);
32610e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
32620e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
3263984c4197SStefano Zampini 
3264984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
326574d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
3266785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
3267984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
326874d5cdf7SStefano Zampini 
3269984c4197SStefano Zampini   j = total_primal_vertices;
327074d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
3271b3d85658SStefano Zampini   cum = total_primal_vertices;
32729162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
32734641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
3274b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
3275b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
3276b3d85658SStefano Zampini       cum++;
32779162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
327874d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
327974d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
328074d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
328174d5cdf7SStefano Zampini       }
32829162d606SStefano Zampini       j += constraints_n[i];
3283674ae819SStefano Zampini     }
3284674ae819SStefano Zampini   }
3285674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
3286674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
3287088faed8SStefano Zampini 
3288674ae819SStefano Zampini   /* set values in constraint matrix */
3289984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
32900e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
3291674ae819SStefano Zampini   }
3292984c4197SStefano Zampini   total_counts = total_primal_vertices;
32939162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
32944641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
32959162d606SStefano Zampini       PetscInt *cols;
32969162d606SStefano Zampini 
32979162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
32989162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
32999162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
33009162d606SStefano Zampini         PetscInt    row = total_counts+k;
33019162d606SStefano Zampini         PetscScalar *vals;
33029162d606SStefano Zampini 
33039162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
33049162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
33059162d606SStefano Zampini       }
33069162d606SStefano Zampini       total_counts += constraints_n[i];
3307674ae819SStefano Zampini     }
3308674ae819SStefano Zampini   }
3309674ae819SStefano Zampini   /* assembling */
3310674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3311674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3312088faed8SStefano Zampini 
3313984c4197SStefano Zampini   /*
331445a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
3315984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
3316984c4197SStefano Zampini   */
3317674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
3318674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
3319026de310SStefano Zampini     /* dual and primal dofs on a single cc */
3320984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
3321984c4197SStefano Zampini     /* working stuff for GEQRF */
332281d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
3323984c4197SStefano Zampini     PetscBLASInt lqr_work;
3324984c4197SStefano Zampini     /* working stuff for UNGQR */
3325984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
3326984c4197SStefano Zampini     PetscBLASInt lgqr_work;
3327984c4197SStefano Zampini     /* working stuff for TRTRS */
3328984c4197SStefano Zampini     PetscScalar  *trs_rhs;
33293f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
3330984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
3331984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
3332984c4197SStefano Zampini     PetscScalar  *start_vals;
3333984c4197SStefano Zampini     /* working stuff for values insertion */
33344641a718SStefano Zampini     PetscBT      is_primal;
333564efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
3336906d46d4SStefano Zampini     /* matrix sizes */
3337906d46d4SStefano Zampini     PetscInt     global_size,local_size;
3338906d46d4SStefano Zampini     /* temporary change of basis */
3339906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
3340cf5a6209SStefano Zampini     /* extra space for debugging */
3341cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
3342984c4197SStefano Zampini 
3343906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
3344906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
334516f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
3346bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
3347906d46d4SStefano Zampini     /* nonzeros for local mat */
3348bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
3349bbb9e6c6SStefano Zampini     for (i=0;i<pcis->n;i++) nnz[i]=1;
33509162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
3351a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
33529162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
3353a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
33549162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
3355a717540cSStefano Zampini         } else {
33569162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
33579162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
3358a717540cSStefano Zampini         }
3359a717540cSStefano Zampini       }
3360a717540cSStefano Zampini     }
3361906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
3362bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
3363a717540cSStefano Zampini     /* Set initial identity in the matrix */
3364bbb9e6c6SStefano Zampini     for (i=0;i<pcis->n;i++) {
3365906d46d4SStefano Zampini       ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
3366a717540cSStefano Zampini     }
3367a717540cSStefano Zampini 
3368a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
3369a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3370a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
3371a717540cSStefano Zampini     }
3372a717540cSStefano Zampini 
3373a717540cSStefano Zampini 
3374a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
3375a717540cSStefano Zampini     /*
3376a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
3377a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
3378a717540cSStefano Zampini 
3379a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
3380a717540cSStefano Zampini 
3381a6b551f4SStefano 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)
3382a6b551f4SStefano Zampini 
3383a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
3384a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
3385a717540cSStefano Zampini             |              ...                        |
3386a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
3387a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
3388a717540cSStefano Zampini 
3389a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
3390a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
3391a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
3392a6b551f4SStefano Zampini 
3393a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
3394a717540cSStefano Zampini     */
3395a717540cSStefano Zampini     if (qr_needed) {
3396984c4197SStefano Zampini       /* space to store Q */
3397854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
3398984c4197SStefano Zampini       /* first we issue queries for optimal work */
33993f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
34003f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
34013f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3402984c4197SStefano Zampini       lqr_work = -1;
34033f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
3404984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
3405984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
3406785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
3407984c4197SStefano Zampini       lgqr_work = -1;
34083f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
34093f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
34103f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
34113f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
34123f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
34133f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
3414984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
3415984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
3416785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
3417984c4197SStefano Zampini       /* array to store scaling factors for reflectors */
3418785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
3419984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
3420785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
3421a717540cSStefano Zampini       /* allocating workspace for check */
3422a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
3423cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
3424a717540cSStefano Zampini       }
3425a717540cSStefano Zampini     }
3426984c4197SStefano Zampini     /* array to store whether a node is primal or not */
34274641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
3428473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
34290e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
343039e2fb2aSStefano Zampini     if (i != total_primal_vertices) {
343139e2fb2aSStefano Zampini       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %d != %d\n",total_primal_vertices,i);
34324641a718SStefano Zampini     }
343339e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
343439e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
343539e2fb2aSStefano Zampini     }
343639e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
3437984c4197SStefano Zampini 
3438a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
34399162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
34409162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
34414641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
3442984c4197SStefano Zampini         /* get constraint info */
34439162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
3444984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
3445984c4197SStefano Zampini 
3446984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
34479162d606SStefano 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);
3448674ae819SStefano Zampini         }
3449984c4197SStefano Zampini 
3450fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
3451a717540cSStefano Zampini 
3452a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
3453a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
34549162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3455a717540cSStefano Zampini           }
3456984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
34579162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3458984c4197SStefano Zampini 
3459984c4197SStefano Zampini           /* compute QR decomposition of constraints */
34603f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
34613f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
34623f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3463674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
34643f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
3465984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
3466674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3467984c4197SStefano Zampini 
3468984c4197SStefano Zampini           /* explictly compute R^-T */
3469984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
3470984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
34713f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
34723f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
34733f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
34743f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
3475984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
34763f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
3477984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
3478984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3479984c4197SStefano Zampini 
3480a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
34813f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
34823f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
34833f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
34843f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3485984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
34863f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
3487984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
3488984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3489984c4197SStefano Zampini 
3490984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
3491984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
3492984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
34933f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
34943f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
34953f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
34963f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
34973f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
34983f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
3499984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
35009162d606SStefano 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));
3501984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
35029162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
3503984c4197SStefano Zampini 
3504984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
35059162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
3506984c4197SStefano Zampini           /* insert cols for primal dofs */
3507984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
3508984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
35099162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
3510906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
3511984c4197SStefano Zampini           }
3512984c4197SStefano Zampini           /* insert cols for dual dofs */
3513984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
35149162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
3515984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
35169162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
3517906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
3518984c4197SStefano Zampini               j++;
3519674ae819SStefano Zampini             }
3520674ae819SStefano Zampini           }
3521984c4197SStefano Zampini 
3522984c4197SStefano Zampini           /* check change of basis */
3523984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
3524984c4197SStefano Zampini             PetscInt   ii,jj;
3525984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
3526c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
3527c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3528c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
3529c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3530c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
3531c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
3532984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3533cf5a6209SStefano 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));
3534984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
3535984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
3536984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
3537cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
3538cf5a6209SStefano 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;
3539674ae819SStefano Zampini               }
3540674ae819SStefano Zampini             }
3541984c4197SStefano Zampini             if (!valid_qr) {
354222d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
3543984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
3544984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
3545cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
3546cf5a6209SStefano 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]));
3547674ae819SStefano Zampini                   }
3548cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
3549cf5a6209SStefano 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]));
3550984c4197SStefano Zampini                   }
3551984c4197SStefano Zampini                 }
3552984c4197SStefano Zampini               }
3553674ae819SStefano Zampini             } else {
355422d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
3555674ae819SStefano Zampini             }
3556674ae819SStefano Zampini           }
3557a717540cSStefano Zampini         } else { /* simple transformation block */
3558a717540cSStefano Zampini           PetscInt    row,col;
3559a6b551f4SStefano Zampini           PetscScalar val,norm;
3560a6b551f4SStefano Zampini 
3561a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
35629162d606SStefano 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));
3563a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
35649162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
35659162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
3566bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
35679162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
3568906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
35699162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
3570a717540cSStefano Zampini             } else {
3571a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
35729162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
3573a717540cSStefano Zampini                 if (row != col) {
35749162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
3575a717540cSStefano Zampini                 } else {
35769162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
3577a717540cSStefano Zampini                 }
3578906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
3579a717540cSStefano Zampini               }
3580a717540cSStefano Zampini             }
3581a717540cSStefano Zampini           }
358298a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
358322d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
3584a717540cSStefano Zampini           }
3585674ae819SStefano Zampini         }
3586984c4197SStefano Zampini       } else {
3587984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
35889162d606SStefano 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);
3589674ae819SStefano Zampini         }
3590674ae819SStefano Zampini       }
3591674ae819SStefano Zampini     }
3592a717540cSStefano Zampini 
3593a717540cSStefano Zampini     /* free workspace */
3594a717540cSStefano Zampini     if (qr_needed) {
3595984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
3596cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
3597984c4197SStefano Zampini       }
3598984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
3599984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
3600984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
3601984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
3602984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
3603674ae819SStefano Zampini     }
3604a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
3605906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3606906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3607906d46d4SStefano Zampini 
3608906d46d4SStefano Zampini     /* assembling of global change of variable */
3609bbb9e6c6SStefano Zampini     {
3610bbb9e6c6SStefano Zampini       Mat      tmat;
361116f15bc4SStefano Zampini       PetscInt bs;
361216f15bc4SStefano Zampini 
3613906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
3614906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
3615bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
3616bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
3617bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3618bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
361916f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
362016f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
3621906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
3622bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
3623bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3624bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
3625bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
3626bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
3627e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3628e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3629bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
3630bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
3631906d46d4SStefano Zampini     }
3632906d46d4SStefano Zampini     /* check */
3633906d46d4SStefano Zampini     if (pcbddc->dbg_flag) {
3634906d46d4SStefano Zampini       PetscReal error;
3635906d46d4SStefano Zampini       Vec       x,x_change;
3636906d46d4SStefano Zampini 
3637906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
3638906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
3639906d46d4SStefano Zampini       ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
3640906d46d4SStefano Zampini       ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
3641e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3642e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3643bbb9e6c6SStefano Zampini       ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
3644e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3645e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3646906d46d4SStefano Zampini       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
3647906d46d4SStefano Zampini       ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
3648906d46d4SStefano Zampini       ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
3649906d46d4SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3650bbb9e6c6SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
3651906d46d4SStefano Zampini       ierr = VecDestroy(&x);CHKERRQ(ierr);
3652906d46d4SStefano Zampini       ierr = VecDestroy(&x_change);CHKERRQ(ierr);
3653906d46d4SStefano Zampini     }
3654b96c3477SStefano Zampini 
3655b96c3477SStefano Zampini     /* adapt sub_schurs computed (if any) */
3656b96c3477SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
3657b96c3477SStefano Zampini       PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
3658b96c3477SStefano Zampini       if (sub_schurs->S_Ej_all) {
3659ac632422SStefano Zampini         Mat                    S_new,tmat;
3660b087196eSStefano Zampini         ISLocalToGlobalMapping NtoSall;
3661b087196eSStefano Zampini         IS                     is_all_N,is_V,is_V_Sall;
3662b087196eSStefano Zampini         const PetscScalar      *array;
3663b087196eSStefano Zampini         const PetscInt         *idxs_V,*idxs_all;
3664b087196eSStefano Zampini         PetscInt               i,n_V;
3665bbb9e6c6SStefano Zampini 
3666bbb9e6c6SStefano Zampini         ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
36676816873aSStefano Zampini         ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
3668b087196eSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
3669b087196eSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
3670b087196eSStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
3671b087196eSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
3672bbb9e6c6SStefano Zampini         ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
3673b087196eSStefano Zampini         ierr = ISDestroy(&is_V);CHKERRQ(ierr);
3674ac632422SStefano Zampini         ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
3675b96c3477SStefano Zampini         ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
3676ac632422SStefano Zampini         ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
3677b087196eSStefano Zampini         ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
3678b087196eSStefano Zampini         ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
3679b087196eSStefano Zampini         ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
3680b087196eSStefano Zampini         ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
3681b087196eSStefano Zampini         ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
3682b087196eSStefano Zampini         for (i=0;i<n_V;i++) {
3683b087196eSStefano Zampini           PetscScalar val;
3684b087196eSStefano Zampini           PetscInt    idx;
3685b087196eSStefano Zampini 
3686b087196eSStefano Zampini           idx = idxs_V[i];
3687b087196eSStefano Zampini           val = array[idxs_all[idxs_V[i]]];
3688b087196eSStefano Zampini           ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
3689b087196eSStefano Zampini         }
3690b087196eSStefano Zampini         ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3691b087196eSStefano Zampini         ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3692ac632422SStefano Zampini         sub_schurs->S_Ej_all = S_new;
3693ac632422SStefano Zampini         ierr = MatDestroy(&S_new);CHKERRQ(ierr);
3694ac632422SStefano Zampini         if (sub_schurs->sum_S_Ej_all) {
3695ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
3696b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
3697ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
3698b087196eSStefano Zampini           ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
3699ac632422SStefano Zampini           sub_schurs->sum_S_Ej_all = S_new;
3700ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
3701ac632422SStefano Zampini         }
3702b087196eSStefano Zampini         ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
3703b087196eSStefano Zampini         ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
3704b087196eSStefano Zampini         ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
3705b96c3477SStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
3706b087196eSStefano Zampini         ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
3707b96c3477SStefano Zampini       }
3708b96c3477SStefano Zampini     }
3709906d46d4SStefano Zampini     ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
3710906d46d4SStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix) {
3711b9b85e73SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3712b9b85e73SStefano Zampini     pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
3713b9b85e73SStefano Zampini   }
3714906d46d4SStefano Zampini 
3715906d46d4SStefano Zampini   /* set up change of basis context */
3716906d46d4SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
3717906d46d4SStefano Zampini     PCBDDCChange_ctx change_ctx;
3718906d46d4SStefano Zampini 
3719906d46d4SStefano Zampini     if (!pcbddc->new_global_mat) {
3720906d46d4SStefano Zampini       PetscInt global_size,local_size;
3721906d46d4SStefano Zampini 
3722906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
3723906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
3724906d46d4SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->new_global_mat);CHKERRQ(ierr);
3725906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->new_global_mat,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
3726906d46d4SStefano Zampini       ierr = MatSetType(pcbddc->new_global_mat,MATSHELL);CHKERRQ(ierr);
3727906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT,(void (*)(void))PCBDDCMatMult_Private);CHKERRQ(ierr);
3728906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCMatMultTranspose_Private);CHKERRQ(ierr);
3729906d46d4SStefano Zampini       ierr = PetscNew(&change_ctx);CHKERRQ(ierr);
3730906d46d4SStefano Zampini       ierr = MatShellSetContext(pcbddc->new_global_mat,change_ctx);CHKERRQ(ierr);
3731906d46d4SStefano Zampini     } else {
3732906d46d4SStefano Zampini       ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
3733906d46d4SStefano Zampini       ierr = MatDestroy(&change_ctx->global_change);CHKERRQ(ierr);
3734906d46d4SStefano Zampini       ierr = VecDestroyVecs(2,&change_ctx->work);CHKERRQ(ierr);
3735906d46d4SStefano Zampini     }
3736906d46d4SStefano Zampini     if (!pcbddc->user_ChangeOfBasisMatrix) {
3737906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
3738906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->ChangeOfBasisMatrix;
3739906d46d4SStefano Zampini     } else {
3740906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
3741906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->user_ChangeOfBasisMatrix;
3742906d46d4SStefano Zampini     }
3743906d46d4SStefano Zampini     ierr = VecDuplicateVecs(pcis->vec1_global,2,&change_ctx->work);CHKERRQ(ierr);
3744906d46d4SStefano Zampini     ierr = MatSetUp(pcbddc->new_global_mat);CHKERRQ(ierr);
3745906d46d4SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3746906d46d4SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3747b9b85e73SStefano Zampini   }
3748a717540cSStefano Zampini 
37494f1b2e48SStefano Zampini   /* add pressure dofs to set of primal nodes for numbering purposes */
37504f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
37514f1b2e48SStefano Zampini     pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
37524f1b2e48SStefano Zampini     pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
3753019a44ceSStefano Zampini     pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
3754019a44ceSStefano Zampini     pcbddc->local_primal_size_cc++;
3755019a44ceSStefano Zampini     pcbddc->local_primal_size++;
3756019a44ceSStefano Zampini   }
3757019a44ceSStefano Zampini 
3758019a44ceSStefano Zampini   /* check if a new primal space has been introduced (also take into account benign trick) */
3759727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_TRUE;
3760727cdba6SStefano Zampini   if (olocal_primal_size == pcbddc->local_primal_size) {
37619f47a83aSStefano 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);
3762c1c8e736SStefano Zampini     pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
37630e6343abSStefano Zampini     if (!pcbddc->new_primal_space_local) {
37649f47a83aSStefano 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);
3765727cdba6SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
3766727cdba6SStefano Zampini     }
37670e6343abSStefano Zampini   }
37680e6343abSStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
3769727cdba6SStefano Zampini   /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
3770727cdba6SStefano Zampini   ierr = MPI_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
3771727cdba6SStefano Zampini 
3772a717540cSStefano Zampini   /* flush dbg viewer */
3773b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
3774b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3775b8ffe317SStefano Zampini   }
3776a717540cSStefano Zampini 
3777e310c8b4SStefano Zampini   /* free workspace */
3778a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
37794641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
378008122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
37819162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
37829162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
378308122e43SStefano Zampini   } else {
37849162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
37859162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
37869162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
378708122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
378808122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
37899162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
37909162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
379108122e43SStefano Zampini   }
3792674ae819SStefano Zampini   PetscFunctionReturn(0);
3793674ae819SStefano Zampini }
3794674ae819SStefano Zampini 
3795674ae819SStefano Zampini #undef __FUNCT__
3796674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
3797674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
3798674ae819SStefano Zampini {
3799674ae819SStefano Zampini   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
3800674ae819SStefano Zampini   PC_IS       *pcis = (PC_IS*)pc->data;
3801674ae819SStefano Zampini   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
38027fb0e2dbSStefano Zampini   PetscInt    ierr,i,vertex_size,N;
3803674ae819SStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
3804674ae819SStefano Zampini 
3805674ae819SStefano Zampini   PetscFunctionBegin;
38068e61c736SStefano Zampini   /* Reset previously computed graph */
38078e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
3808674ae819SStefano Zampini   /* Init local Graph struct */
38097fb0e2dbSStefano Zampini   ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
38103bbff08aSStefano Zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,pcis->mapping,N);CHKERRQ(ierr);
3811674ae819SStefano Zampini 
3812575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
38135099eff2SStefano Zampini   if (pcbddc->mat_graph->nvtxs_csr && pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) {
38145099eff2SStefano 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);
3815575ad6abSStefano Zampini   }
38169577ea80SStefano Zampini 
3817674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
38184d379d7bSStefano Zampini   if (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) {
38194d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
38204d379d7bSStefano Zampini     PetscInt  nvtxs;
3821e496cd5dSStefano Zampini     PetscBool flg_row=PETSC_FALSE;
3822674ae819SStefano Zampini 
38234d379d7bSStefano Zampini     if (pcbddc->use_local_adj) {
38242fffb893SStefano Zampini 
38252fffb893SStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
38262fffb893SStefano Zampini       if (flg_row) {
38274d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
3828b96c3477SStefano Zampini         pcbddc->computed_rowadj = PETSC_TRUE;
38292fffb893SStefano Zampini       }
38302fffb893SStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
38319b28b941SStefano 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 */
38324d379d7bSStefano Zampini       IS                     is_dummy;
38334d379d7bSStefano Zampini       ISLocalToGlobalMapping l2gmap_dummy;
38344d379d7bSStefano Zampini       PetscInt               j,sum;
38354d379d7bSStefano Zampini       PetscInt               *cxadj,*cadjncy;
38364d379d7bSStefano Zampini       const PetscInt         *idxs;
38374d379d7bSStefano Zampini       PCBDDCGraph            graph;
38384d379d7bSStefano Zampini       PetscBT                is_on_boundary;
38394d379d7bSStefano Zampini 
38404d379d7bSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcis->n,0,1,&is_dummy);CHKERRQ(ierr);
38414d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
38424d379d7bSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
38434d379d7bSStefano Zampini       ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
38447fb0e2dbSStefano Zampini       ierr = PCBDDCGraphInit(graph,l2gmap_dummy,pcis->n);CHKERRQ(ierr);
38454d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
3846e496cd5dSStefano Zampini       ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
3847e496cd5dSStefano Zampini       if (flg_row) {
38484d379d7bSStefano Zampini         graph->xadj = xadj;
38494d379d7bSStefano Zampini         graph->adjncy = adjncy;
3850e496cd5dSStefano Zampini       }
38514d379d7bSStefano Zampini       ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
38524d379d7bSStefano Zampini       ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
3853e496cd5dSStefano Zampini       ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
38544d379d7bSStefano Zampini 
38554d379d7bSStefano Zampini       if (pcbddc->dbg_flag) {
38569b28b941SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] Found %d subdomains (local size %d)\n",PetscGlobalRank,graph->ncc,pcis->n);CHKERRQ(ierr);
38574d379d7bSStefano Zampini         for (i=0;i<graph->ncc;i++) {
38584d379d7bSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] %d cc size %d\n",PetscGlobalRank,i,graph->cptr[i+1]-graph->cptr[i]);CHKERRQ(ierr);
38594d379d7bSStefano Zampini         }
38604d379d7bSStefano Zampini       }
38614d379d7bSStefano Zampini 
3862e496cd5dSStefano Zampini       ierr = PetscBTCreate(pcis->n,&is_on_boundary);CHKERRQ(ierr);
38634d379d7bSStefano Zampini       ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
38644d379d7bSStefano Zampini       for (i=0;i<pcis->n_B;i++) {
38654d379d7bSStefano Zampini         ierr = PetscBTSet(is_on_boundary,idxs[i]);CHKERRQ(ierr);
38664d379d7bSStefano Zampini       }
38674d379d7bSStefano Zampini       ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
38684d379d7bSStefano Zampini 
3869e496cd5dSStefano Zampini       ierr = PetscCalloc1(pcis->n+1,&cxadj);CHKERRQ(ierr);
38704d379d7bSStefano Zampini       sum = 0;
38714d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
38724d379d7bSStefano Zampini         PetscInt sizecc = 0;
38734d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
38744d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
38754d379d7bSStefano Zampini             sizecc++;
38764d379d7bSStefano Zampini           }
38774d379d7bSStefano Zampini         }
38784d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
38794d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
38804d379d7bSStefano Zampini             cxadj[graph->queue[j]] = sizecc;
38814d379d7bSStefano Zampini           }
38824d379d7bSStefano Zampini         }
38834d379d7bSStefano Zampini         sum += sizecc*sizecc;
38844d379d7bSStefano Zampini       }
38854d379d7bSStefano Zampini       ierr = PetscMalloc1(sum,&cadjncy);CHKERRQ(ierr);
38864d379d7bSStefano Zampini       sum = 0;
3887e496cd5dSStefano Zampini       for (i=0;i<pcis->n;i++) {
38884d379d7bSStefano Zampini         PetscInt temp = cxadj[i];
38894d379d7bSStefano Zampini         cxadj[i] = sum;
38904d379d7bSStefano Zampini         sum += temp;
38914d379d7bSStefano Zampini       }
3892e496cd5dSStefano Zampini       cxadj[pcis->n] = sum;
38934d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
38944d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
38954d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
38964d379d7bSStefano Zampini             PetscInt k,sizecc = 0;
38974d379d7bSStefano Zampini             for (k=graph->cptr[i];k<graph->cptr[i+1];k++) {
38984d379d7bSStefano Zampini               if (PetscBTLookup(is_on_boundary,graph->queue[k])) {
38994d379d7bSStefano Zampini                 cadjncy[cxadj[graph->queue[j]]+sizecc]=graph->queue[k];
39004d379d7bSStefano Zampini                 sizecc++;
39014d379d7bSStefano Zampini               }
39024d379d7bSStefano Zampini             }
39034d379d7bSStefano Zampini           }
39044d379d7bSStefano Zampini         }
39054d379d7bSStefano Zampini       }
39069b28b941SStefano Zampini       if (sum) {
3907e496cd5dSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,pcis->n,cxadj,cadjncy,PETSC_OWN_POINTER);CHKERRQ(ierr);
39084d379d7bSStefano Zampini       } else {
39094d379d7bSStefano Zampini         ierr = PetscFree(cxadj);CHKERRQ(ierr);
39104d379d7bSStefano Zampini         ierr = PetscFree(cadjncy);CHKERRQ(ierr);
39114d379d7bSStefano Zampini       }
39124d379d7bSStefano Zampini       graph->xadj = 0;
39134d379d7bSStefano Zampini       graph->adjncy = 0;
39144d379d7bSStefano Zampini       ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
39154d379d7bSStefano Zampini       ierr = PetscBTDestroy(&is_on_boundary);CHKERRQ(ierr);
39164d379d7bSStefano Zampini     }
3917674ae819SStefano Zampini   }
39189b28b941SStefano Zampini   if (pcbddc->dbg_flag) {
39199b28b941SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3920674ae819SStefano Zampini   }
3921674ae819SStefano Zampini 
392263602bcaSStefano Zampini   /* Set default dofs' splitting if no information has been provided by the user with PCBDDCSetDofsSplitting or PCBDDCSetDofsSplittingLocal */
3923674ae819SStefano Zampini   vertex_size = 1;
392463602bcaSStefano Zampini   if (pcbddc->user_provided_isfordofs) {
392563602bcaSStefano Zampini     if (pcbddc->n_ISForDofs) { /* need to convert from global to local and remove references to global dofs splitting */
392695ecbf38SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
392763602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
3928e176bc59SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
392963602bcaSStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
3930674ae819SStefano Zampini       }
393163602bcaSStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
393263602bcaSStefano Zampini       pcbddc->n_ISForDofs = 0;
393363602bcaSStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
3934674ae819SStefano Zampini     }
393563602bcaSStefano Zampini     /* mat block size as vertex size (used for elasticity with rigid body modes as nearnullspace) */
3936674ae819SStefano Zampini     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
393763602bcaSStefano Zampini   } else {
393863602bcaSStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering */
393963602bcaSStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->n_ISForDofsLocal);CHKERRQ(ierr);
3940854ce69bSBarry Smith       ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
394163602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
394263602bcaSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),pcis->n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
394363602bcaSStefano Zampini       }
394463602bcaSStefano Zampini     }
3945674ae819SStefano Zampini   }
3946674ae819SStefano Zampini 
3947674ae819SStefano Zampini   /* Setup of Graph */
3948785d1243SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) { /* need to convert from global to local */
3949e176bc59SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
3950785d1243SStefano Zampini   }
3951785d1243SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) { /* need to convert from global to local */
3952e176bc59SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
3953785d1243SStefano Zampini   }
395430368db7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) { /* need to convert from global to local */
395530368db7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,pcis->vec1_global,pcis->vec1_N,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
395630368db7SStefano Zampini   }
395730368db7SStefano Zampini   ierr = PCBDDCGraphSetUp(pcbddc->mat_graph,vertex_size,pcbddc->NeumannBoundariesLocal,pcbddc->DirichletBoundariesLocal,pcbddc->n_ISForDofsLocal,pcbddc->ISForDofsLocal,pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
3958674ae819SStefano Zampini 
39594f1b2e48SStefano Zampini   /* attach info on disconnected subdomains if present */
39604f1b2e48SStefano Zampini   if (pcbddc->n_local_subs) {
39614f1b2e48SStefano Zampini     PetscInt *local_subs;
39624f1b2e48SStefano Zampini 
39634f1b2e48SStefano Zampini     ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
39644f1b2e48SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
39654f1b2e48SStefano Zampini       const PetscInt *idxs;
39664f1b2e48SStefano Zampini       PetscInt       nl,j;
39674f1b2e48SStefano Zampini 
39684f1b2e48SStefano Zampini       ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
39694f1b2e48SStefano Zampini       ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
39704f1b2e48SStefano Zampini       for (j=0;j<nl;j++) {
39714f1b2e48SStefano Zampini         local_subs[idxs[j]] = i;
39724f1b2e48SStefano Zampini       }
39734f1b2e48SStefano Zampini       ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
39744f1b2e48SStefano Zampini     }
39754f1b2e48SStefano Zampini     pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
39764f1b2e48SStefano Zampini     pcbddc->mat_graph->local_subs = local_subs;
39774f1b2e48SStefano Zampini   }
39784f1b2e48SStefano Zampini 
3979674ae819SStefano Zampini   /* Graph's connected components analysis */
3980674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
3981674ae819SStefano Zampini 
3982674ae819SStefano Zampini   /* print some info to stdout */
3983674ae819SStefano Zampini   if (pcbddc->dbg_flag) {
3984302440fdSBarry Smith     ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,viewer);CHKERRQ(ierr);
3985674ae819SStefano Zampini   }
3986fb180af4SStefano Zampini 
3987fb180af4SStefano Zampini   /* mark topography has done */
3988fb180af4SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
3989674ae819SStefano Zampini   PetscFunctionReturn(0);
3990674ae819SStefano Zampini }
3991674ae819SStefano Zampini 
3992dc456d91SStefano Zampini /* given an index sets possibly with holes, renumbers the indexes removing the holes */
3993674ae819SStefano Zampini #undef __FUNCT__
3994674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSubsetNumbering"
3995dc456d91SStefano Zampini PetscErrorCode PCBDDCSubsetNumbering(IS subset, IS subset_mult, PetscInt *N_n, IS *subset_n)
3996674ae819SStefano Zampini {
3997dc456d91SStefano Zampini   PetscSF        sf;
3998dc456d91SStefano Zampini   PetscLayout    map;
3999dc456d91SStefano Zampini   const PetscInt *idxs;
4000dc456d91SStefano Zampini   PetscInt       *leaf_data,*root_data,*gidxs;
4001dc456d91SStefano Zampini   PetscInt       N,n,i,lbounds[2],gbounds[2],Nl;
4002dc456d91SStefano Zampini   PetscInt       n_n,nlocals,start,first_index;
4003dc456d91SStefano Zampini   PetscMPIInt    commsize;
4004674ae819SStefano Zampini   PetscBool      first_found;
4005674ae819SStefano Zampini   PetscErrorCode ierr;
4006674ae819SStefano Zampini 
4007674ae819SStefano Zampini   PetscFunctionBegin;
4008dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset,&n);CHKERRQ(ierr);
4009dc456d91SStefano Zampini   if (subset_mult) {
4010dc456d91SStefano Zampini     PetscCheckSameComm(subset,1,subset_mult,2);
4011dc456d91SStefano Zampini     ierr = ISGetLocalSize(subset,&i);CHKERRQ(ierr);
4012dc456d91SStefano Zampini     if (i != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local subset and multiplicity sizes don't match! %d != %d",n,i);
4013674ae819SStefano Zampini   }
4014dc456d91SStefano Zampini   /* create workspace layout for computing global indices of subset */
4015dc456d91SStefano Zampini   ierr = ISGetIndices(subset,&idxs);CHKERRQ(ierr);
4016dc456d91SStefano Zampini   lbounds[0] = lbounds[1] = 0;
4017dc456d91SStefano Zampini   for (i=0;i<n;i++) {
4018dc456d91SStefano Zampini     if (idxs[i] < lbounds[0]) lbounds[0] = idxs[i];
4019dc456d91SStefano Zampini     else if (idxs[i] > lbounds[1]) lbounds[1] = idxs[i];
4020674ae819SStefano Zampini   }
4021dc456d91SStefano Zampini   lbounds[0] = -lbounds[0];
4022dc456d91SStefano Zampini   ierr = MPI_Allreduce(lbounds,gbounds,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
4023dc456d91SStefano Zampini   gbounds[0] = -gbounds[0];
4024dc456d91SStefano Zampini   N = gbounds[1] - gbounds[0] + 1;
4025dc456d91SStefano Zampini   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)subset),&map);CHKERRQ(ierr);
4026dc456d91SStefano Zampini   ierr = PetscLayoutSetBlockSize(map,1);CHKERRQ(ierr);
4027dc456d91SStefano Zampini   ierr = PetscLayoutSetSize(map,N);CHKERRQ(ierr);
4028dc456d91SStefano Zampini   ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
4029dc456d91SStefano Zampini   ierr = PetscLayoutGetLocalSize(map,&Nl);CHKERRQ(ierr);
4030dc456d91SStefano Zampini 
4031dc456d91SStefano Zampini   /* create sf : leaf_data == multiplicity of indexes, root data == global index in layout */
4032dc456d91SStefano Zampini   ierr = PetscMalloc2(n,&leaf_data,Nl,&root_data);CHKERRQ(ierr);
4033dc456d91SStefano Zampini   if (subset_mult) {
4034dc456d91SStefano Zampini     const PetscInt* idxs_mult;
4035dc456d91SStefano Zampini 
4036dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4037dc456d91SStefano Zampini     ierr = PetscMemcpy(leaf_data,idxs_mult,n*sizeof(PetscInt));CHKERRQ(ierr);
4038dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4039674ae819SStefano Zampini   } else {
4040dc456d91SStefano Zampini     for (i=0;i<n;i++) leaf_data[i] = 1;
4041674ae819SStefano Zampini   }
4042dc456d91SStefano Zampini   /* local size of new subset */
4043dc456d91SStefano Zampini   n_n = 0;
4044dc456d91SStefano Zampini   for (i=0;i<n;i++) n_n += leaf_data[i];
4045dc456d91SStefano Zampini 
4046dc456d91SStefano Zampini   /* global indexes in layout */
4047dc456d91SStefano Zampini   ierr = PetscMalloc1(n_n,&gidxs);CHKERRQ(ierr); /* allocating possibly extra space in gidxs which will be used later */
4048dc456d91SStefano Zampini   for (i=0;i<n;i++) gidxs[i] = idxs[i] - gbounds[0];
4049dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset,&idxs);CHKERRQ(ierr);
4050dc456d91SStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)subset),&sf);CHKERRQ(ierr);
4051dc456d91SStefano Zampini   ierr = PetscSFSetGraphLayout(sf,map,n,NULL,PETSC_COPY_VALUES,gidxs);CHKERRQ(ierr);
4052dc456d91SStefano Zampini   ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr);
4053dc456d91SStefano Zampini 
4054dc456d91SStefano Zampini   /* reduce from leaves to roots */
4055dc456d91SStefano Zampini   ierr = PetscMemzero(root_data,Nl*sizeof(PetscInt));CHKERRQ(ierr);
405664a8e5bcSStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
405764a8e5bcSStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
4058dc456d91SStefano Zampini 
4059dc456d91SStefano Zampini   /* count indexes in local part of layout */
4060674ae819SStefano Zampini   nlocals = 0;
4061674ae819SStefano Zampini   first_index = -1;
4062674ae819SStefano Zampini   first_found = PETSC_FALSE;
4063dc456d91SStefano Zampini   for (i=0;i<Nl;i++) {
4064dc456d91SStefano Zampini     if (!first_found && root_data[i]) {
4065674ae819SStefano Zampini       first_found = PETSC_TRUE;
4066674ae819SStefano Zampini       first_index = i;
4067674ae819SStefano Zampini     }
4068dc456d91SStefano Zampini     nlocals += root_data[i];
4069674ae819SStefano Zampini   }
4070dc456d91SStefano Zampini 
4071dc456d91SStefano Zampini   /* cumulative of number of indexes and size of subset without holes */
40725fa240b1SStefano Zampini #if defined(PETSC_HAVE_MPI_EXSCAN)
4073dc456d91SStefano Zampini   start = 0;
407464a8e5bcSStefano Zampini   ierr = MPI_Exscan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
40755fa240b1SStefano Zampini #else
407664a8e5bcSStefano Zampini   ierr = MPI_Scan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
40775fa240b1SStefano Zampini   start = start-nlocals;
40785fa240b1SStefano Zampini #endif
40795fa240b1SStefano Zampini 
4080dc456d91SStefano Zampini   if (N_n) { /* compute total size of new subset if requested */
4081dc456d91SStefano Zampini     *N_n = start + nlocals;
4082dc456d91SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)subset),&commsize);CHKERRQ(ierr);
4083dc456d91SStefano Zampini     ierr = MPI_Bcast(N_n,1,MPIU_INT,commsize-1,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
4084674ae819SStefano Zampini   }
40855fa240b1SStefano Zampini 
40865fa240b1SStefano Zampini   /* adapt root data with cumulative */
4087674ae819SStefano Zampini   if (first_found) {
4088dc456d91SStefano Zampini     PetscInt old_index;
4089dc456d91SStefano Zampini 
4090dc456d91SStefano Zampini     root_data[first_index] += start;
4091674ae819SStefano Zampini     old_index = first_index;
4092dc456d91SStefano Zampini     for (i=first_index+1;i<Nl;i++) {
4093dc456d91SStefano Zampini       if (root_data[i]) {
4094dc456d91SStefano Zampini         root_data[i] += root_data[old_index];
4095674ae819SStefano Zampini         old_index = i;
4096674ae819SStefano Zampini       }
4097674ae819SStefano Zampini     }
4098674ae819SStefano Zampini   }
4099dc456d91SStefano Zampini 
4100dc456d91SStefano Zampini   /* from roots to leaves */
4101dc456d91SStefano Zampini   ierr = PetscSFBcastBegin(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
4102dc456d91SStefano Zampini   ierr = PetscSFBcastEnd(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
4103dc456d91SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
4104dc456d91SStefano Zampini 
4105dc456d91SStefano Zampini   /* create new IS with global indexes without holes */
4106dc456d91SStefano Zampini   if (subset_mult) {
4107dc456d91SStefano Zampini     const PetscInt* idxs_mult;
4108dc456d91SStefano Zampini     PetscInt        cum;
4109dc456d91SStefano Zampini 
4110dc456d91SStefano Zampini     cum = 0;
4111dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4112dc456d91SStefano Zampini     for (i=0;i<n;i++) {
4113dc456d91SStefano Zampini       PetscInt j;
4114dc456d91SStefano Zampini       for (j=0;j<idxs_mult[i];j++) gidxs[cum++] = leaf_data[i] - idxs_mult[i] + j;
4115674ae819SStefano Zampini     }
4116dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4117674ae819SStefano Zampini   } else {
4118dc456d91SStefano Zampini     for (i=0;i<n;i++) {
4119dc456d91SStefano Zampini       gidxs[i] = leaf_data[i]-1;
4120674ae819SStefano Zampini     }
4121674ae819SStefano Zampini   }
4122dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)subset),n_n,gidxs,PETSC_OWN_POINTER,subset_n);CHKERRQ(ierr);
4123dc456d91SStefano Zampini   ierr = PetscFree2(leaf_data,root_data);CHKERRQ(ierr);
4124674ae819SStefano Zampini   PetscFunctionReturn(0);
4125674ae819SStefano Zampini }
41269a7d3425SStefano Zampini 
41279a7d3425SStefano Zampini #undef __FUNCT__
41289a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
41299a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
41309a7d3425SStefano Zampini {
41319a7d3425SStefano Zampini   PetscInt       i,j;
41329a7d3425SStefano Zampini   PetscScalar    *alphas;
41339a7d3425SStefano Zampini   PetscErrorCode ierr;
41349a7d3425SStefano Zampini 
41359a7d3425SStefano Zampini   PetscFunctionBegin;
41369a7d3425SStefano Zampini   /* this implements stabilized Gram-Schmidt */
4137785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
41389a7d3425SStefano Zampini   for (i=0;i<n;i++) {
41399a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
41409a7d3425SStefano Zampini     if (i<n) { ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],&alphas[i+1]);CHKERRQ(ierr); }
41419a7d3425SStefano Zampini     for (j=i+1;j<n;j++) { ierr = VecAXPY(vecs[j],PetscConj(-alphas[j]),vecs[i]);CHKERRQ(ierr); }
41429a7d3425SStefano Zampini   }
41439a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
41449a7d3425SStefano Zampini   PetscFunctionReturn(0);
41459a7d3425SStefano Zampini }
41469a7d3425SStefano Zampini 
4147e7931f94SStefano Zampini #undef __FUNCT__
414870cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
4149b0c7d250SStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt n_subdomains, PetscInt redprocs, IS* is_sends)
4150e7931f94SStefano Zampini {
415152e5ac9dSStefano Zampini   IS             ranks_send_to;
4152e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
4153e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
415452e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
415552e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
41563837a79fSStefano Zampini   PetscInt       i,local_size,threshold=0;
41572b510759SStefano Zampini   PetscBool      use_vwgt=PETSC_FALSE,use_square=PETSC_FALSE;
4158e7931f94SStefano Zampini   PetscSubcomm   subcomm;
415952e5ac9dSStefano Zampini   PetscErrorCode ierr;
4160a57a6d2fSStefano Zampini 
4161e7931f94SStefano Zampini   PetscFunctionBegin;
41622b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_square",&use_square,NULL);CHKERRQ(ierr);
41632b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
41642b510759SStefano Zampini   ierr = PetscOptionsGetInt(NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
4165e7931f94SStefano Zampini 
4166e7931f94SStefano Zampini   /* Get info on mapping */
41673bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&local_size);CHKERRQ(ierr);
41683bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
4169e7931f94SStefano Zampini 
4170e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
4171785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
4172e7931f94SStefano Zampini   xadj[0] = 0;
4173e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
4174785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
4175785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
4176e7931f94SStefano Zampini 
41772b510759SStefano Zampini   if (threshold) {
4178d023bfaeSStefano Zampini     PetscInt xadj_count = 0;
41792b510759SStefano Zampini     for (i=1;i<n_neighs;i++) {
4180d023bfaeSStefano Zampini       if (n_shared[i] > threshold) {
4181d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
4182d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
4183d023bfaeSStefano Zampini         xadj_count++;
4184e7931f94SStefano Zampini       }
4185e7931f94SStefano Zampini     }
4186d023bfaeSStefano Zampini     xadj[1] = xadj_count;
4187c8587f34SStefano Zampini   } else {
4188e7931f94SStefano Zampini     if (xadj[1]) {
4189e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy,&neighs[1],xadj[1]*sizeof(*adjncy));CHKERRQ(ierr);
4190e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy_wgt,&n_shared[1],xadj[1]*sizeof(*adjncy_wgt));CHKERRQ(ierr);
4191c8587f34SStefano Zampini     }
4192e7931f94SStefano Zampini   }
41933bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
4194e7931f94SStefano Zampini   if (use_square) {
4195e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
4196e7931f94SStefano Zampini       adjncy_wgt[i] = adjncy_wgt[i]*adjncy_wgt[i];
4197e7931f94SStefano Zampini     }
4198e7931f94SStefano Zampini   }
4199e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
4200e7931f94SStefano Zampini 
42013837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
4202e7931f94SStefano Zampini 
4203e7931f94SStefano Zampini   /*
4204e7931f94SStefano Zampini     Restrict work on active processes only.
4205e7931f94SStefano Zampini   */
4206e7931f94SStefano Zampini   ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&subcomm);CHKERRQ(ierr);
4207e7931f94SStefano Zampini   ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
4208e7931f94SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
42092b510759SStefano Zampini   ierr = PetscMPIIntCast(!local_size,&color);CHKERRQ(ierr);
4210d3531aaaSJed Brown   ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
4211e7931f94SStefano Zampini   if (color) {
4212e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
4213e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
4214e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
4215c8587f34SStefano Zampini   } else {
421652e5ac9dSStefano Zampini     Mat             subdomain_adj;
421752e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
421852e5ac9dSStefano Zampini     MatPartitioning partitioner;
421952e5ac9dSStefano Zampini     PetscInt        prank,rstart=0,rend=0;
422052e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
4221b0c7d250SStefano Zampini     PetscBool       aggregate;
4222b0c7d250SStefano Zampini 
4223306c2d5bSBarry Smith     ierr = MPI_Comm_size(PetscSubcommChild(subcomm),&size);CHKERRQ(ierr);
4224785e854fSJed Brown     ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
4225e7931f94SStefano Zampini     prank = rank;
4226306c2d5bSBarry Smith     ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,PetscSubcommChild(subcomm));CHKERRQ(ierr);
42278002ef2cSStefano Zampini     /*
4228e7931f94SStefano Zampini     for (i=0;i<size;i++) {
4229e7931f94SStefano Zampini       PetscPrintf(subcomm->comm,"oldranks[%d] = %d\n",i,oldranks[i]);
4230c8587f34SStefano Zampini     }
42318002ef2cSStefano Zampini     */
4232e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
4233e7931f94SStefano Zampini       ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
4234c8587f34SStefano Zampini     }
4235e7931f94SStefano Zampini     ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
4236b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
4237b0c7d250SStefano Zampini     if (aggregate) {
4238b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
4239b0c7d250SStefano Zampini       PetscMPIInt nrank;
4240b0c7d250SStefano Zampini       PetscScalar *vals;
4241b0c7d250SStefano Zampini 
4242b0c7d250SStefano Zampini       ierr = MPI_Comm_rank(PetscSubcommChild(subcomm),&nrank);CHKERRQ(ierr);
4243b0c7d250SStefano Zampini       lrows = 0;
4244b0c7d250SStefano Zampini       if (nrank<redprocs) {
4245b0c7d250SStefano Zampini         lrows = size/redprocs;
4246b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
4247b0c7d250SStefano Zampini       }
42485fa240b1SStefano Zampini       ierr = MatCreateAIJ(PetscSubcommChild(subcomm),lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
4249b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
4250b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
4251b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
4252b0c7d250SStefano Zampini       row = nrank;
4253b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
4254b0c7d250SStefano Zampini       cols = adjncy;
4255b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
4256b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
4257b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
4258b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4259b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
426052e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
426152e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
426252e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
4263b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
4264b0c7d250SStefano Zampini     } else {
4265306c2d5bSBarry Smith       ierr = MatCreateMPIAdj(PetscSubcommChild(subcomm),1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
4266b0c7d250SStefano Zampini     }
426722b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
4268e7931f94SStefano Zampini 
4269e7931f94SStefano Zampini     /* Partition */
4270306c2d5bSBarry Smith     ierr = MatPartitioningCreate(PetscSubcommChild(subcomm),&partitioner);CHKERRQ(ierr);
4271e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
4272e7931f94SStefano Zampini     if (use_vwgt) {
42733837a79fSStefano Zampini       ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
4274e7931f94SStefano Zampini       v_wgt[0] = local_size;
4275e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
4276c8587f34SStefano Zampini     }
427728143c3dSStefano Zampini     n_subdomains = PetscMin((PetscInt)size,n_subdomains);
427828143c3dSStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,n_subdomains);CHKERRQ(ierr);
4279e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
4280e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
428122b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
4282e7931f94SStefano Zampini 
428352e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
428452e5ac9dSStefano Zampini     ierr = PCBDDCSubsetNumbering(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
428552e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
428652e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4287b0c7d250SStefano Zampini     if (!redprocs) {
4288b0c7d250SStefano Zampini       ranks_send_to_idx[0] = oldranks[is_indices[0]];
428928143c3dSStefano Zampini     } else {
4290b0c7d250SStefano Zampini       PetscInt    idxs[1];
4291b0c7d250SStefano Zampini       PetscMPIInt tag;
4292b0c7d250SStefano Zampini       MPI_Request *reqs;
4293b0c7d250SStefano Zampini 
4294b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
4295b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
4296b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
4297b0c7d250SStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,PetscSubcommChild(subcomm),&reqs[i-rstart]);CHKERRQ(ierr);
429828143c3dSStefano Zampini       }
4299b0c7d250SStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,PetscSubcommChild(subcomm),MPI_STATUS_IGNORE);CHKERRQ(ierr);
4300b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4301b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
4302b0c7d250SStefano Zampini       ranks_send_to_idx[0] = oldranks[idxs[0]];
4303e7931f94SStefano Zampini     }
430452e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
4305e7931f94SStefano Zampini     /* clean up */
4306e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
430752e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
4308e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
4309e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
4310e7931f94SStefano Zampini   }
4311e7931f94SStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
4312e7931f94SStefano Zampini 
4313e7931f94SStefano Zampini   /* assemble parallel IS for sends */
4314e7931f94SStefano Zampini   i = 1;
4315e7931f94SStefano Zampini   if (color) i=0;
4316e7931f94SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,&ranks_send_to);CHKERRQ(ierr);
4317e7931f94SStefano Zampini   /* get back IS */
4318e7931f94SStefano Zampini   *is_sends = ranks_send_to;
4319e7931f94SStefano Zampini   PetscFunctionReturn(0);
4320e7931f94SStefano Zampini }
4321e7931f94SStefano Zampini 
4322e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
4323e7931f94SStefano Zampini 
4324e7931f94SStefano Zampini #undef __FUNCT__
4325e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
432653a05cb3SStefano 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[])
4327e7931f94SStefano Zampini {
432870cf5478SStefano Zampini   Mat                    local_mat;
4329e7931f94SStefano Zampini   IS                     is_sends_internal;
43309d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
433128143c3dSStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals;
43329d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
4333e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
4334e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
4335e7931f94SStefano Zampini   const PetscInt*        is_indices;
4336e7931f94SStefano Zampini   MatType                new_local_type;
4337e7931f94SStefano Zampini   /* buffers */
4338e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
433928143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
43409d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
4341e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
4342e7931f94SStefano Zampini   /* MPI */
434328143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
434428143c3dSStefano Zampini   PetscSubcomm           subcomm;
4345e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
434628143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
434728143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
434828143c3dSStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,source_dest;
434928143c3dSStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals;
435028143c3dSStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals;
4351e7931f94SStefano Zampini   PetscErrorCode         ierr;
4352e7931f94SStefano Zampini 
4353e7931f94SStefano Zampini   PetscFunctionBegin;
435428143c3dSStefano Zampini   /* TODO: add missing checks */
435528143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
435628143c3dSStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
435728143c3dSStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,5);
435828143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,7);
4359e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
436028143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
4361e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
4362e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
4363e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
4364e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
4365e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
436628143c3dSStefano Zampini   if (reuse == MAT_REUSE_MATRIX && *mat_n) {
436770cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
436870cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
436928143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
437070cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
437170cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
437270cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
437370cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
437470cf5478SStefano Zampini   }
4375e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
4376e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
4377e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
4378e7931f94SStefano Zampini   if (!is_sends) {
437928143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
4380b0c7d250SStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,n_subdomains,0,&is_sends_internal);CHKERRQ(ierr);
4381c8587f34SStefano Zampini   } else {
4382e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
4383e7931f94SStefano Zampini     is_sends_internal = is_sends;
4384c8587f34SStefano Zampini   }
4385e7931f94SStefano Zampini 
4386e7931f94SStefano Zampini   /* get comm */
4387a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
4388e7931f94SStefano Zampini 
4389e7931f94SStefano Zampini   /* compute number of sends */
4390e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
4391e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
4392e7931f94SStefano Zampini 
4393e7931f94SStefano Zampini   /* compute number of receives */
4394e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
4395785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
4396e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
4397e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
4398e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
4399e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
4400e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
4401e7931f94SStefano Zampini 
440228143c3dSStefano Zampini   /* restrict comm if requested */
440328143c3dSStefano Zampini   subcomm = 0;
440428143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
440528143c3dSStefano Zampini   if (restrict_comm) {
4406779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
4407779c1cceSStefano Zampini 
440828143c3dSStefano Zampini     color = 0;
440953a05cb3SStefano Zampini     if (restrict_full) {
441053a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
441153a05cb3SStefano Zampini     } else {
441253a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
441353a05cb3SStefano Zampini     }
441428143c3dSStefano Zampini     ierr = MPI_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
441528143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
441628143c3dSStefano Zampini     /* check if reuse has been requested */
441728143c3dSStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
441828143c3dSStefano Zampini       if (*mat_n) {
441928143c3dSStefano Zampini         PetscMPIInt subcommsize2;
442028143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
442128143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
442228143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
442328143c3dSStefano Zampini       } else {
442428143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
442528143c3dSStefano Zampini       }
442628143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
4427779c1cceSStefano Zampini       PetscMPIInt rank;
4428779c1cceSStefano Zampini 
4429779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
443028143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
443128143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
443228143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
4433306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
443428143c3dSStefano Zampini     }
443528143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
443628143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
443728143c3dSStefano Zampini   } else {
443828143c3dSStefano Zampini     comm_n = comm;
443928143c3dSStefano Zampini   }
444028143c3dSStefano Zampini 
4441e7931f94SStefano Zampini   /* prepare send/receive buffers */
4442785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
4443e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
4444785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
4445e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
444628143c3dSStefano Zampini   if (nis) {
4447854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
444828143c3dSStefano Zampini   }
4449e7931f94SStefano Zampini 
445028143c3dSStefano Zampini   /* Get data from local matrices */
4451e7931f94SStefano Zampini   if (!isdense) {
4452a26c9d0eSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
4453e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
4454e7931f94SStefano Zampini     /*
4455e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
4456e7931f94SStefano Zampini        send_buffer_idxs should contain:
4457e7931f94SStefano Zampini        - MatType_PRIVATE type
4458e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
4459e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
4460e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
4461e7931f94SStefano Zampini     */
4462e7931f94SStefano Zampini   } else {
4463e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
44643bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
4465854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
4466e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
4467e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
44683bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
4469e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
44703bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
4471e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
4472e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
4473e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
4474e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
4475c8587f34SStefano Zampini     }
4476c8587f34SStefano Zampini   }
4477e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
447828143c3dSStefano Zampini   /* additional is (if any) */
447928143c3dSStefano Zampini   if (nis) {
448028143c3dSStefano Zampini     PetscMPIInt psum;
448128143c3dSStefano Zampini     PetscInt j;
448228143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
448328143c3dSStefano Zampini       PetscInt plen;
448428143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
448528143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
448628143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
448728143c3dSStefano Zampini     }
4488854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
448928143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
449028143c3dSStefano Zampini       PetscInt plen;
449128143c3dSStefano Zampini       const PetscInt *is_array_idxs;
449228143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
449328143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
449428143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
449528143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
449628143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
449728143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
449828143c3dSStefano Zampini     }
449928143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
450028143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
450128143c3dSStefano Zampini     }
450228143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
450328143c3dSStefano Zampini   }
450428143c3dSStefano Zampini 
4505e7931f94SStefano Zampini   buf_size_idxs = 0;
4506e7931f94SStefano Zampini   buf_size_vals = 0;
450728143c3dSStefano Zampini   buf_size_idxs_is = 0;
4508e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4509e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
4510e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
451128143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
4512e7931f94SStefano Zampini   }
4513785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
4514785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
451595ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
4516e7931f94SStefano Zampini 
4517e7931f94SStefano Zampini   /* get new tags for clean communications */
4518e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
4519e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
452028143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
4521e7931f94SStefano Zampini 
4522e7931f94SStefano Zampini   /* allocate for requests */
4523785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
4524785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
452595ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
4526785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
4527785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
452895ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
4529e7931f94SStefano Zampini 
4530e7931f94SStefano Zampini   /* communications */
4531e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
4532e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
453328143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
4534e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4535e7931f94SStefano Zampini     source_dest = onodes[i];
4536e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
4537e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
4538e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4539e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
454028143c3dSStefano Zampini     if (nis) {
454128143c3dSStefano 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);
454228143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
454328143c3dSStefano Zampini     }
4544e7931f94SStefano Zampini   }
4545e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
4546e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
4547e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
4548e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
454928143c3dSStefano Zampini     if (nis) {
455028143c3dSStefano 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);
455128143c3dSStefano Zampini     }
4552e7931f94SStefano Zampini   }
4553e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
4554e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
4555e7931f94SStefano Zampini 
4556e7931f94SStefano Zampini   /* assemble new l2g map */
4557e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4558e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
45599d30be91SStefano Zampini   new_local_rows = 0;
4560e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
45619d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
4562e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4563e7931f94SStefano Zampini   }
45649d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
4565e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
45669d30be91SStefano Zampini   new_local_rows = 0;
4567e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
45689d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
45699d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
4570e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4571e7931f94SStefano Zampini   }
45729d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
45739d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
4574e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
4575e7931f94SStefano Zampini 
4576e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
4577e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
4578e7931f94SStefano 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) */
4579e7931f94SStefano Zampini   if (n_recvs) {
458028143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
4581e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
4582e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
4583e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
4584e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
4585e7931f94SStefano Zampini         break;
4586e7931f94SStefano Zampini       }
4587e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
4588e7931f94SStefano Zampini     }
4589e7931f94SStefano Zampini     switch (new_local_type_private) {
459028143c3dSStefano Zampini       case MATDENSE_PRIVATE:
459128143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
4592e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
4593e7931f94SStefano Zampini           bs = 1;
459428143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
459528143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
459628143c3dSStefano Zampini           bs = 1;
459728143c3dSStefano Zampini         }
4598e7931f94SStefano Zampini         break;
4599e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
4600e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
4601e7931f94SStefano Zampini         bs = 1;
4602e7931f94SStefano Zampini         break;
4603e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
4604e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
4605e7931f94SStefano Zampini         break;
4606e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
4607e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
4608e7931f94SStefano Zampini         break;
4609e7931f94SStefano Zampini       default:
46109d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
4611e7931f94SStefano Zampini         break;
4612e7931f94SStefano Zampini     }
461328143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
461428143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
461528143c3dSStefano Zampini     bs = 1;
4616e7931f94SStefano Zampini   }
4617e7931f94SStefano Zampini 
461870cf5478SStefano Zampini   /* create MATIS object if needed */
461970cf5478SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
4620e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
4621e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
462270cf5478SStefano Zampini   } else {
462370cf5478SStefano Zampini     /* it also destroys the local matrices */
462470cf5478SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
462570cf5478SStefano Zampini   }
462670cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
4627e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
46289d30be91SStefano Zampini 
46299d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
46309d30be91SStefano Zampini 
46319d30be91SStefano Zampini   /* Global to local map of received indices */
46329d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
46339d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
46349d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
46359d30be91SStefano Zampini 
46369d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
46379d30be91SStefano Zampini   buf_size_idxs = 0;
46389d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
46399d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
46409d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
46419d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
46429d30be91SStefano Zampini   }
46439d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
46449d30be91SStefano Zampini 
46459d30be91SStefano Zampini   /* set preallocation */
46469d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
46479d30be91SStefano Zampini   if (!newisdense) {
46489d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
46499d30be91SStefano Zampini 
46509d30be91SStefano Zampini     ptr_vals = recv_buffer_vals;
46519d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
46529d30be91SStefano Zampini     if (n_recvs) {
46539d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
46549d30be91SStefano Zampini     }
46559d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
46569d30be91SStefano Zampini       PetscInt j;
46579d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
46589d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
46599d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
46609d30be91SStefano Zampini         }
46619d30be91SStefano Zampini       } else {
46629d30be91SStefano Zampini         /* TODO */
46639d30be91SStefano Zampini       }
46649d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
46659d30be91SStefano Zampini     }
46669d30be91SStefano Zampini     if (new_local_nnz) {
46679d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
46689d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
46699d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
46709d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
46719d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
46729d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
46739d30be91SStefano Zampini     } else {
46749d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
46759d30be91SStefano Zampini     }
46769d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
46779d30be91SStefano Zampini   } else {
46789d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
46799d30be91SStefano Zampini   }
4680e7931f94SStefano Zampini 
4681e7931f94SStefano Zampini   /* set values */
4682e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
46839d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
4684e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
4685e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
4686e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
46879d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
4688e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
4689e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
4690e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
469128143c3dSStefano Zampini     } else {
469228143c3dSStefano Zampini       /* TODO */
4693e7931f94SStefano Zampini     }
4694e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
4695e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
4696e7931f94SStefano Zampini   }
4697e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4698e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
469970cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
470070cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
47019d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
47029d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
4703e7931f94SStefano Zampini 
4704dfd14d43SStefano Zampini #if 0
470528143c3dSStefano Zampini   if (!restrict_comm) { /* check */
4706e7931f94SStefano Zampini     Vec       lvec,rvec;
4707e7931f94SStefano Zampini     PetscReal infty_error;
4708e7931f94SStefano Zampini 
47092a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
4710e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
4711e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
4712e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
471370cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
4714e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
4715e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
4716e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
4717e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
4718e7931f94SStefano Zampini   }
471928143c3dSStefano Zampini #endif
4720e7931f94SStefano Zampini 
472128143c3dSStefano Zampini   /* assemble new additional is (if any) */
472228143c3dSStefano Zampini   if (nis) {
472328143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
472428143c3dSStefano Zampini 
472528143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4726854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
472728143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
472828143c3dSStefano Zampini     psum = 0;
472928143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
473028143c3dSStefano Zampini       for (j=0;j<nis;j++) {
473128143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
473228143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
473328143c3dSStefano Zampini         psum += plen;
473428143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
473528143c3dSStefano Zampini       }
473628143c3dSStefano Zampini     }
4737854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
4738854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
473928143c3dSStefano Zampini     for (i=1;i<nis;i++) {
474028143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
474128143c3dSStefano Zampini     }
474228143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
474328143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
474428143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
474528143c3dSStefano Zampini       for (j=0;j<nis;j++) {
474628143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
474728143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
474828143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
474928143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
475028143c3dSStefano Zampini       }
475128143c3dSStefano Zampini     }
475228143c3dSStefano Zampini     for (i=0;i<nis;i++) {
475328143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
475428143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
475528143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
475628143c3dSStefano Zampini     }
475728143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
475828143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
475928143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
476028143c3dSStefano Zampini   }
4761e7931f94SStefano Zampini   /* free workspace */
476228143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
4763e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4764e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
4765e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4766e7931f94SStefano Zampini   if (isdense) {
4767e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
4768e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
4769e7931f94SStefano Zampini   } else {
4770e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
4771e7931f94SStefano Zampini   }
477228143c3dSStefano Zampini   if (nis) {
477328143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
477428143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
477528143c3dSStefano Zampini   }
4776e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
4777e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
477828143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
4779e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
4780e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
478128143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
4782e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
4783e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
4784e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
4785e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
4786e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
478728143c3dSStefano Zampini   if (nis) {
478828143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
478928143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
479028143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
479128143c3dSStefano Zampini   }
479228143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
479328143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
479428143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
479528143c3dSStefano Zampini     for (i=0;i<nis;i++) {
479628143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
479728143c3dSStefano Zampini     }
479853a05cb3SStefano Zampini     *mat_n = NULL;
479928143c3dSStefano Zampini   }
4800e7931f94SStefano Zampini   PetscFunctionReturn(0);
4801e7931f94SStefano Zampini }
4802a57a6d2fSStefano Zampini 
480312edc857SStefano Zampini /* temporary hack into ksp private data structure */
4804af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
480512edc857SStefano Zampini 
4806c8587f34SStefano Zampini #undef __FUNCT__
4807c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
4808c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
4809c8587f34SStefano Zampini {
4810c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
4811c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
481220a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
48139881197aSStefano Zampini   MatNullSpace           CoarseNullSpace=NULL;
481420a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
48156e683305SStefano Zampini   IS                     coarse_is,*isarray;
48166e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
481730368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
4818f9eb5b7dSStefano Zampini   PC                     pc_temp;
4819c8587f34SStefano Zampini   PCType                 coarse_pc_type;
4820c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
4821f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
48224f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
48236e683305SStefano Zampini   Mat                    t_coarse_mat_is;
48246e683305SStefano Zampini   PetscInt               void_procs,ncoarse_ml,ncoarse_ds,ncoarse;
48256e683305SStefano Zampini   PetscMPIInt            all_procs;
482674e2c79eSStefano Zampini   PetscBool              csin_ml,csin_ds,csin,csin_type_simple,redist;
482768457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
482822bc73bbSStefano Zampini   PetscScalar            *array;
48299881197aSStefano Zampini   PetscErrorCode         ierr;
4830fdc09c96SStefano Zampini 
4831c8587f34SStefano Zampini   PetscFunctionBegin;
4832c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
483368457ee5SStefano 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 */
4834fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
48355a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
4836fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
4837f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
4838f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
4839f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
4840fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
484151bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
484251bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
4843dc4bcba2SStefano Zampini         PC        pc;
4844dc4bcba2SStefano Zampini         PetscBool isbddc;
4845dc4bcba2SStefano Zampini 
4846dc4bcba2SStefano Zampini         /* temporary workaround since PCBDDC does not have a reset method so far */
4847dc4bcba2SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
4848dc4bcba2SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
4849dc4bcba2SStefano Zampini         if (isbddc) {
4850dc4bcba2SStefano Zampini           ierr = PCDestroy(&pc);CHKERRQ(ierr);
4851dc4bcba2SStefano Zampini         }
4852727cdba6SStefano Zampini         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
4853fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
4854fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
4855fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
4856f4ddd8eeSStefano Zampini       }
4857fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
4858fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
4859f4ddd8eeSStefano Zampini     }
486070cf5478SStefano Zampini     /* reset any subassembling information */
486170cf5478SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
48626e683305SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
48636e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
4864fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
4865f4ddd8eeSStefano Zampini   }
4866c8587f34SStefano Zampini 
48676e683305SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
48682b510759SStefano Zampini   im_active = !!(pcis->n);
48692b510759SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
48706e683305SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&all_procs);CHKERRQ(ierr);
48716e683305SStefano Zampini   void_procs = all_procs-active_procs;
48726e683305SStefano Zampini   csin_type_simple = PETSC_TRUE;
487374e2c79eSStefano Zampini   redist = PETSC_FALSE;
487422bc73bbSStefano Zampini   if (pcbddc->current_level && void_procs) {
48756e683305SStefano Zampini     csin_ml = PETSC_TRUE;
48766e683305SStefano Zampini     ncoarse_ml = void_procs;
4877779c1cceSStefano Zampini     /* it has no sense to redistribute on a set of processors larger than the number of active processes */
4878779c1cceSStefano Zampini     if (pcbddc->redistribute_coarse > 0 && pcbddc->redistribute_coarse < active_procs) {
48796e683305SStefano Zampini       csin_ds = PETSC_TRUE;
488018a45a71SStefano Zampini       ncoarse_ds = pcbddc->redistribute_coarse;
488118a45a71SStefano Zampini       redist = PETSC_TRUE;
488218a45a71SStefano Zampini     } else {
48836e683305SStefano Zampini       csin_ds = PETSC_TRUE;
4884779c1cceSStefano Zampini       ncoarse_ds = active_procs;
4885779c1cceSStefano Zampini       redist = PETSC_TRUE;
488618a45a71SStefano Zampini     }
48876e683305SStefano Zampini   } else {
48886e683305SStefano Zampini     csin_ml = PETSC_FALSE;
48896e683305SStefano Zampini     ncoarse_ml = all_procs;
48906e683305SStefano Zampini     if (void_procs) {
48916e683305SStefano Zampini       csin_ds = PETSC_TRUE;
48926e683305SStefano Zampini       ncoarse_ds = void_procs;
48936e683305SStefano Zampini       csin_type_simple = PETSC_FALSE;
48946e683305SStefano Zampini     } else {
4895779c1cceSStefano Zampini       if (pcbddc->redistribute_coarse > 0 && pcbddc->redistribute_coarse < all_procs) {
489674e2c79eSStefano Zampini         csin_ds = PETSC_TRUE;
489774e2c79eSStefano Zampini         ncoarse_ds = pcbddc->redistribute_coarse;
489874e2c79eSStefano Zampini         redist = PETSC_TRUE;
489974e2c79eSStefano Zampini       } else {
49006e683305SStefano Zampini         csin_ds = PETSC_FALSE;
49016e683305SStefano Zampini         ncoarse_ds = all_procs;
49026e683305SStefano Zampini       }
49036e683305SStefano Zampini     }
490474e2c79eSStefano Zampini   }
49056e683305SStefano Zampini 
49066e683305SStefano Zampini   /*
49076e683305SStefano Zampini     test if we can go multilevel: three conditions must be satisfied:
49086e683305SStefano Zampini     - we have not exceeded the number of levels requested
49096e683305SStefano Zampini     - we can actually subassemble the active processes
49106e683305SStefano Zampini     - we can find a suitable number of MPI processes where we can place the subassembled problem
49116e683305SStefano Zampini   */
49126e683305SStefano Zampini   multilevel_allowed = PETSC_FALSE;
49136e683305SStefano Zampini   multilevel_requested = PETSC_FALSE;
49146e683305SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
49156e683305SStefano Zampini     multilevel_requested = PETSC_TRUE;
49166e683305SStefano Zampini     if (active_procs/pcbddc->coarsening_ratio < 2 || ncoarse_ml/pcbddc->coarsening_ratio < 2) {
4917f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_FALSE;
49182b510759SStefano Zampini     } else {
4919f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_TRUE;
4920c8587f34SStefano Zampini     }
4921c8587f34SStefano Zampini   }
49226e683305SStefano Zampini   /* determine number of process partecipating to coarse solver */
49236e683305SStefano Zampini   if (multilevel_allowed) {
49246e683305SStefano Zampini     ncoarse = ncoarse_ml;
49256e683305SStefano Zampini     csin = csin_ml;
492658da7f69SStefano Zampini     redist = PETSC_FALSE;
49276e683305SStefano Zampini   } else {
49286e683305SStefano Zampini     ncoarse = ncoarse_ds;
49296e683305SStefano Zampini     csin = csin_ds;
49306e683305SStefano Zampini   }
4931e7931f94SStefano Zampini 
4932abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
4933abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
4934abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
4935abbbba34SStefano Zampini 
4936abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
493722bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
493822bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
493922bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
494022bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
4941e176bc59SStefano 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);
49426e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
49436e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
49446e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4945abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
4946abbbba34SStefano Zampini 
49476e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
494830368db7SStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal || (pcbddc->benign_saddle_point && pcbddc->user_primal_vertices_local))) { /* protects from unneded computations */
49496e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
49506e683305SStefano Zampini     const PetscInt         *idxs;
49516e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
49526e683305SStefano Zampini 
49536e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
49540be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
49556e683305SStefano Zampini     /* allocate space for temporary storage */
4956854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
4957854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
49586e683305SStefano Zampini     /* allocate for IS array */
49596e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
49606e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
496130368db7SStefano Zampini     nisvert = 0;
496230368db7SStefano Zampini     if (pcbddc->benign_saddle_point && pcbddc->user_primal_vertices_local) {
496330368db7SStefano Zampini       nisvert = 1;
496430368db7SStefano Zampini     }
496530368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
4966854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
49676e683305SStefano Zampini     /* dofs splitting */
49686e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
49696e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
49706e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
49716e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
49726e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
49736e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
49746e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
497530368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
49766e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
49776e683305SStefano Zampini     }
49786e683305SStefano Zampini     /* neumann boundaries */
49796e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
49806e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
49816e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
49826e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
49836e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
49846e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
49856e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
498630368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
49876e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
49886e683305SStefano Zampini     }
498930368db7SStefano Zampini     /* primal vertices (benign) */
499030368db7SStefano Zampini     if (pcbddc->benign_saddle_point && pcbddc->user_primal_vertices_local) {
499130368db7SStefano Zampini       ierr = ISGetLocalSize(pcbddc->user_primal_vertices_local,&tsize);CHKERRQ(ierr);
499230368db7SStefano Zampini       ierr = ISGetIndices(pcbddc->user_primal_vertices_local,&idxs);CHKERRQ(ierr);
499330368db7SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
499430368db7SStefano Zampini       ierr = ISRestoreIndices(pcbddc->user_primal_vertices_local,&idxs);CHKERRQ(ierr);
499530368db7SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
499630368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nis-1]);CHKERRQ(ierr);
499730368db7SStefano Zampini     }
49986e683305SStefano Zampini     /* free memory */
49996e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
50006e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
50016e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
50026e683305SStefano Zampini   } else {
50036e683305SStefano Zampini     nis = 0;
50046e683305SStefano Zampini     nisdofs = 0;
50056e683305SStefano Zampini     nisneu = 0;
500630368db7SStefano Zampini     nisvert = 0;
50076e683305SStefano Zampini     isarray = NULL;
50086e683305SStefano Zampini   }
50096e683305SStefano Zampini   /* destroy no longer needed map */
50106e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
50116e683305SStefano Zampini 
50126e683305SStefano Zampini   /* restrict on coarse candidates (if needed) */
50136e683305SStefano Zampini   coarse_mat_is = NULL;
50146e683305SStefano Zampini   if (csin) {
50156e683305SStefano Zampini     if (!pcbddc->coarse_subassembling_init ) { /* creates subassembling init pattern if not present */
501674e2c79eSStefano Zampini       if (redist) {
501774e2c79eSStefano Zampini         PetscMPIInt rank;
5018779c1cceSStefano Zampini         PetscInt    spc,n_spc_p1,dest[1],destsize;
501974e2c79eSStefano Zampini 
502074e2c79eSStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
502158da7f69SStefano Zampini         spc = active_procs/ncoarse;
502258da7f69SStefano Zampini         n_spc_p1 = active_procs%ncoarse;
5023779c1cceSStefano Zampini         if (im_active) {
5024779c1cceSStefano Zampini           destsize = 1;
502574e2c79eSStefano Zampini           if (rank > n_spc_p1*(spc+1)-1) {
502674e2c79eSStefano Zampini             dest[0] = n_spc_p1+(rank-(n_spc_p1*(spc+1)))/spc;
502774e2c79eSStefano Zampini           } else {
502874e2c79eSStefano Zampini             dest[0] = rank/(spc+1);
502974e2c79eSStefano Zampini           }
503074e2c79eSStefano Zampini         } else {
5031779c1cceSStefano Zampini           destsize = 0;
50326e683305SStefano Zampini         }
5033779c1cceSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),destsize,dest,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
5034779c1cceSStefano Zampini       } else if (csin_type_simple) {
50356e683305SStefano Zampini         PetscMPIInt rank;
50366e683305SStefano Zampini         PetscInt    issize,isidx;
5037779c1cceSStefano Zampini 
50386e683305SStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
50396e683305SStefano Zampini         if (im_active) {
50406e683305SStefano Zampini           issize = 1;
50416e683305SStefano Zampini           isidx = (PetscInt)rank;
50426e683305SStefano Zampini         } else {
50436e683305SStefano Zampini           issize = 0;
50446e683305SStefano Zampini           isidx = -1;
50456e683305SStefano Zampini         }
50466e683305SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),issize,&isidx,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
5047779c1cceSStefano Zampini       } else { /* get a suitable subassembling pattern from MATIS code */
5048b0c7d250SStefano Zampini         ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
50496e683305SStefano Zampini       }
5050779c1cceSStefano Zampini 
5051779c1cceSStefano Zampini       /* we need to shift on coarse candidates either if we are not redistributing or we are redistributing and we have enough void processes */
5052779c1cceSStefano Zampini       if (!redist || ncoarse <= void_procs) {
5053779c1cceSStefano Zampini         PetscInt ncoarse_cand,tissize,*nisindices;
5054779c1cceSStefano Zampini         PetscInt *coarse_candidates;
5055779c1cceSStefano Zampini         const PetscInt* tisindices;
5056779c1cceSStefano Zampini 
5057779c1cceSStefano Zampini         /* get coarse candidates' ranks in pc communicator */
5058779c1cceSStefano Zampini         ierr = PetscMalloc1(all_procs,&coarse_candidates);CHKERRQ(ierr);
5059779c1cceSStefano Zampini         ierr = MPI_Allgather(&im_active,1,MPIU_INT,coarse_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
5060779c1cceSStefano Zampini         for (i=0,ncoarse_cand=0;i<all_procs;i++) {
5061779c1cceSStefano Zampini           if (!coarse_candidates[i]) {
5062779c1cceSStefano Zampini             coarse_candidates[ncoarse_cand++]=i;
5063779c1cceSStefano Zampini           }
5064779c1cceSStefano Zampini         }
5065779c1cceSStefano Zampini         if (ncoarse_cand < ncoarse) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen! %d < %d",ncoarse_cand,ncoarse);
5066779c1cceSStefano Zampini 
5067779c1cceSStefano Zampini 
50686e683305SStefano Zampini         if (pcbddc->dbg_flag) {
50696e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
50706e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init (before shift)\n");CHKERRQ(ierr);
50716e683305SStefano Zampini           ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
50726e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse candidates\n");CHKERRQ(ierr);
5073779c1cceSStefano Zampini           for (i=0;i<ncoarse_cand;i++) {
50746e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"%d ",coarse_candidates[i]);CHKERRQ(ierr);
50756e683305SStefano Zampini           }
50766e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"\n");CHKERRQ(ierr);
50776e683305SStefano Zampini           ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
50786e683305SStefano Zampini         }
50796e683305SStefano Zampini         /* shift the pattern on coarse candidates */
50806e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->coarse_subassembling_init,&tissize);CHKERRQ(ierr);
50816e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
5082854ce69bSBarry Smith         ierr = PetscMalloc1(tissize,&nisindices);CHKERRQ(ierr);
50836e683305SStefano Zampini         for (i=0;i<tissize;i++) nisindices[i] = coarse_candidates[tisindices[i]];
50846e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
50856e683305SStefano Zampini         ierr = ISGeneralSetIndices(pcbddc->coarse_subassembling_init,tissize,nisindices,PETSC_OWN_POINTER);CHKERRQ(ierr);
50866e683305SStefano Zampini         ierr = PetscFree(coarse_candidates);CHKERRQ(ierr);
50876e683305SStefano Zampini       }
50886e683305SStefano Zampini       if (pcbddc->dbg_flag) {
50896e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
50906e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init\n");CHKERRQ(ierr);
50916e683305SStefano Zampini         ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
50926e683305SStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
50936e683305SStefano Zampini       }
5094779c1cceSStefano Zampini     }
50956e683305SStefano Zampini     /* get temporary coarse mat in IS format restricted on coarse procs (plus additional index sets of isarray) */
509653a05cb3SStefano Zampini     if (multilevel_allowed) { /* we need to keep tracking of void processes for future placements */
509753a05cb3SStefano 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);
509853a05cb3SStefano Zampini     } else { /* this is the last level, so use just receiving processes in subcomm */
509953a05cb3SStefano 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);
510053a05cb3SStefano Zampini     }
51016e683305SStefano Zampini   } else {
51026e683305SStefano Zampini     if (pcbddc->dbg_flag) {
51036e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
51046e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init not needed\n");CHKERRQ(ierr);
51056e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
51066e683305SStefano Zampini     }
51076e683305SStefano Zampini     ierr = PetscObjectReference((PetscObject)t_coarse_mat_is);CHKERRQ(ierr);
51086e683305SStefano Zampini     coarse_mat_is = t_coarse_mat_is;
51096e683305SStefano Zampini   }
51106e683305SStefano Zampini 
51116e683305SStefano Zampini   /* create local to global scatters for coarse problem */
511268457ee5SStefano Zampini   if (compute_vecs) {
51136e683305SStefano Zampini     PetscInt lrows;
51146e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
51156e683305SStefano Zampini     if (coarse_mat_is) {
51166e683305SStefano Zampini       ierr = MatGetLocalSize(coarse_mat_is,&lrows,NULL);CHKERRQ(ierr);
51176e683305SStefano Zampini     } else {
51186e683305SStefano Zampini       lrows = 0;
51196e683305SStefano Zampini     }
51206e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
51216e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
51226e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
51236e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
51246e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
51256e683305SStefano Zampini   }
51266e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
51276e683305SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
5128c8587f34SStefano Zampini 
5129f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
5130f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
5131f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
5132f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
5133f9eb5b7dSStefano Zampini   } else {
5134f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
5135f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
5136c8587f34SStefano Zampini   }
5137c8587f34SStefano Zampini 
51386e683305SStefano Zampini   /* print some info if requested */
51396e683305SStefano Zampini   if (pcbddc->dbg_flag) {
51406e683305SStefano Zampini     if (!multilevel_allowed) {
51416e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
51426e683305SStefano Zampini       if (multilevel_requested) {
51436e683305SStefano 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);
51446e683305SStefano Zampini       } else if (pcbddc->max_levels) {
51456e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
51466e683305SStefano Zampini       }
51476e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
51486e683305SStefano Zampini     }
51496e683305SStefano Zampini   }
51506e683305SStefano Zampini 
5151f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
51526e683305SStefano Zampini   if (coarse_mat_is) {
51536e683305SStefano Zampini     MatReuse coarse_mat_reuse;
51546a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
51556e683305SStefano Zampini     if (pcbddc->dbg_flag) {
51566e683305SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat_is));
51576e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
51586e683305SStefano Zampini     }
5159f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
5160312be037SStefano Zampini       char prefix[256],str_level[16];
5161e604994aSStefano Zampini       size_t len;
51626e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat_is),&pcbddc->coarse_ksp);CHKERRQ(ierr);
5163422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
5164c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
5165f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
51665f76c7aeSStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat_is,coarse_mat_is);CHKERRQ(ierr);
5167c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
51686e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
5169c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
5170c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
5171e604994aSStefano Zampini       /* prefix */
5172e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
5173e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
5174e604994aSStefano Zampini       if (!pcbddc->current_level) {
5175e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
5176e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
5177c8587f34SStefano Zampini       } else {
5178e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
5179312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
5180312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
518134d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
5182312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
5183e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
5184e604994aSStefano Zampini       }
5185e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
51863e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
51873e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
51883e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
51893e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
5190f9eb5b7dSStefano Zampini       /* allow user customization */
5191f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
51923e3c6dadSStefano Zampini     }
51933e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
519451bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
51953e3c6dadSStefano Zampini     if (nisdofs) {
51963e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
51973e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
51983e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
51993e3c6dadSStefano Zampini       }
52003e3c6dadSStefano Zampini     }
52013e3c6dadSStefano Zampini     if (nisneu) {
52023e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
52033e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
5204312be037SStefano Zampini     }
520530368db7SStefano Zampini     if (nisvert) {
520630368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
520730368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
520830368db7SStefano Zampini     }
5209f9eb5b7dSStefano Zampini 
5210f9eb5b7dSStefano Zampini     /* get some info after set from options */
5211f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
5212f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
52134f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
52146e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
5215f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
5216f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
5217f9eb5b7dSStefano Zampini     }
521839f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
52194f3a063dSStefano Zampini     if (isredundant) {
52204f3a063dSStefano Zampini       KSP inner_ksp;
52214f3a063dSStefano Zampini       PC  inner_pc;
52224f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
52234f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
52244f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
52254f3a063dSStefano Zampini     }
5226f9eb5b7dSStefano Zampini 
5227f9eb5b7dSStefano Zampini     /* assemble coarse matrix */
5228fa7f1dd8SStefano Zampini     if (coarse_reuse) {
522981d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
5230fa7f1dd8SStefano Zampini       ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
52316e683305SStefano Zampini       coarse_mat_reuse = MAT_REUSE_MATRIX;
5232fa7f1dd8SStefano Zampini     } else {
52336e683305SStefano Zampini       coarse_mat_reuse = MAT_INITIAL_MATRIX;
5234fa7f1dd8SStefano Zampini     }
5235c8587f34SStefano Zampini     if (isbddc || isnn) {
523622bc73bbSStefano Zampini       if (pcbddc->coarsening_ratio > 1) {
523770cf5478SStefano Zampini         if (!pcbddc->coarse_subassembling) { /* subassembling info is not present */
5238b0c7d250SStefano Zampini           ierr = MatISGetSubassemblingPattern(coarse_mat_is,active_procs/pcbddc->coarsening_ratio,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
523922b6e8a2SStefano Zampini           if (pcbddc->dbg_flag) {
52406e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
52416e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"Subassembling pattern\n");CHKERRQ(ierr);
52426e683305SStefano Zampini             ierr = ISView(pcbddc->coarse_subassembling,dbg_viewer);CHKERRQ(ierr);
52436e683305SStefano Zampini             ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
524422b6e8a2SStefano Zampini           }
524570cf5478SStefano Zampini         }
524653a05cb3SStefano Zampini         ierr = MatISSubassemble(coarse_mat_is,pcbddc->coarse_subassembling,0,PETSC_FALSE,PETSC_FALSE,coarse_mat_reuse,&coarse_mat,0,NULL);CHKERRQ(ierr);
524770cf5478SStefano Zampini       } else {
524822bc73bbSStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
524922bc73bbSStefano Zampini         coarse_mat = coarse_mat_is;
525022bc73bbSStefano Zampini       }
525122bc73bbSStefano Zampini     } else {
52522e1e5fa4SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
5253c8587f34SStefano Zampini     }
5254c8587f34SStefano Zampini     ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
5255c8587f34SStefano Zampini 
52563301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
52575a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
52583301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
52593301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
52603301b35fSStefano Zampini     }
52613301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
52623301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
52633301b35fSStefano Zampini     }
52643301b35fSStefano Zampini     if (pc->pmat->spd_set) {
52653301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
52663301b35fSStefano Zampini     }
52676e683305SStefano Zampini     /* set operators */
52685f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
52696e683305SStefano Zampini     if (pcbddc->dbg_flag) {
52706e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
52716e683305SStefano Zampini     }
52726e683305SStefano Zampini   } else { /* processes non partecipating to coarse solver (if any) */
52736e683305SStefano Zampini     coarse_mat = 0;
52746e683305SStefano Zampini   }
52756e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
5276b1ecc7b1SStefano Zampini #if 0
5277b9b85e73SStefano Zampini   {
5278b9b85e73SStefano Zampini     PetscViewer viewer;
5279b9b85e73SStefano Zampini     char filename[256];
5280b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
5281b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
5282b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
5283b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
5284b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
5285b9b85e73SStefano Zampini   }
5286b9b85e73SStefano Zampini #endif
5287c8587f34SStefano Zampini 
5288c8587f34SStefano Zampini   /* Compute coarse null space (special handling by BDDC only) */
5289298c0119SStefano Zampini #if 0
5290c8587f34SStefano Zampini   if (pcbddc->NullSpace) {
5291c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,coarse_mat,&CoarseNullSpace);CHKERRQ(ierr);
529298a51de6SStefano Zampini   }
5293298c0119SStefano Zampini #endif
5294b0f5fe93SStefano Zampini   /* hack */
529598a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
529698a51de6SStefano Zampini     Vec crhs,csol;
529704708bb6SStefano Zampini 
5298f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
5299f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
5300f347579bSStefano Zampini     if (!csol) {
53012a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
5302f9eb5b7dSStefano Zampini     }
5303f347579bSStefano Zampini     if (!crhs) {
53042a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
5305f347579bSStefano Zampini     }
5306b0f5fe93SStefano Zampini   }
5307b0f5fe93SStefano Zampini 
5308b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
5309b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
5310b0f5fe93SStefano Zampini 
5311b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
53124f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
53134f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
53144f1b2e48SStefano Zampini     }
5315b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
5316b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
5317b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5318b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5319b0f5fe93SStefano Zampini     if (coarse_mat) {
5320b0f5fe93SStefano Zampini       Vec         nullv;
5321b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
5322b0f5fe93SStefano Zampini       PetscInt    nl;
5323b0f5fe93SStefano Zampini 
5324b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
5325b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
5326b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
5327b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
5328b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
5329b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
5330b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
5331b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
5332b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
5333b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
5334b0f5fe93SStefano Zampini     }
5335b0f5fe93SStefano Zampini   }
5336b0f5fe93SStefano Zampini 
5337b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
5338b0f5fe93SStefano Zampini     PetscBool ispreonly;
5339b0f5fe93SStefano Zampini 
5340b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
5341b0f5fe93SStefano Zampini       PetscBool isnull;
5342b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
5343b0f5fe93SStefano Zampini       if (isnull) {
534430368db7SStefano Zampini         if (isbddc && !pcbddc->benign_saddle_point) {
5345b0f5fe93SStefano Zampini           ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
5346b0f5fe93SStefano Zampini         } else {
5347b0f5fe93SStefano Zampini           ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
5348b0f5fe93SStefano Zampini         }
5349b0f5fe93SStefano Zampini       } else {
5350b0f5fe93SStefano Zampini         ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
5351b0f5fe93SStefano Zampini       }
5352b0f5fe93SStefano Zampini     }
5353b0f5fe93SStefano Zampini     /* setup coarse ksp */
5354b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
5355cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
5356cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
53576e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
5358c8587f34SStefano Zampini       KSP       check_ksp;
53592b510759SStefano Zampini       KSPType   check_ksp_type;
5360c8587f34SStefano Zampini       PC        check_pc;
53616e683305SStefano Zampini       Vec       check_vec,coarse_vec;
53626a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
53632b510759SStefano Zampini       PetscInt  its;
53646e683305SStefano Zampini       PetscBool compute_eigs;
53656e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
53666e683305SStefano Zampini       PetscInt  neigs;
53678e185a42SStefano Zampini       const char *prefix;
5368c8587f34SStefano Zampini 
53692b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
53706e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
5371422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
537223ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
5373f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
53742b510759SStefano Zampini       if (ispreonly) {
53752b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
53766e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
53772b510759SStefano Zampini       } else {
5378cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
53796e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
5380c8587f34SStefano Zampini       }
5381c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
53826e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
53836e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
53846e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
5385a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
5386a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
5387a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
5388a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
5389c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
5390c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
5391c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
5392c8587f34SStefano Zampini       /* create random vec */
53936e683305SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&coarse_vec);CHKERRQ(ierr);
53946e683305SStefano Zampini       ierr = VecDuplicate(coarse_vec,&check_vec);CHKERRQ(ierr);
5395c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
5396c8587f34SStefano Zampini       if (CoarseNullSpace) {
5397c8587f34SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
5398c8587f34SStefano Zampini       }
53996e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
5400c8587f34SStefano Zampini       /* solve coarse problem */
54016e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
5402c8587f34SStefano Zampini       if (CoarseNullSpace) {
54036e683305SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,coarse_vec);CHKERRQ(ierr);
5404c8587f34SStefano Zampini       }
5405cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
54066e683305SStefano Zampini       if (compute_eigs) {
5407854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
5408854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
54096e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
54106e683305SStefano Zampini         lambda_max = eigs_r[neigs-1];
54116e683305SStefano Zampini         lambda_min = eigs_r[0];
54126e683305SStefano Zampini         if (pcbddc->use_coarse_estimates) {
54136e683305SStefano Zampini           if (lambda_max>lambda_min) {
5414cbcc2c2aSStefano Zampini             ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max,lambda_min);CHKERRQ(ierr);
5415cbcc2c2aSStefano Zampini             ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
5416cbcc2c2aSStefano Zampini           }
5417c8587f34SStefano Zampini         }
5418c8587f34SStefano Zampini       }
5419cbcc2c2aSStefano Zampini 
5420c8587f34SStefano Zampini       /* check coarse problem residual error */
54216e683305SStefano Zampini       if (pcbddc->dbg_flag) {
54226e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
54236e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
54246e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
5425c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
54266e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
54276e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
5428c8587f34SStefano Zampini         ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
5429779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
54306e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
54316e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
54326e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
54336e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
5434b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
5435b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
5436b0f5fe93SStefano Zampini         }
54376e683305SStefano Zampini         if (compute_eigs) {
54386e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
5439deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
5440c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
54416e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
54426e683305SStefano 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);
54436e683305SStefano Zampini           for (i=0;i<neigs;i++) {
54446e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
5445c8587f34SStefano Zampini           }
54466e683305SStefano Zampini         }
54476e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
54486e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
54496e683305SStefano Zampini       }
5450c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
54516e683305SStefano Zampini       if (compute_eigs) {
54526e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
54536e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
5454c8587f34SStefano Zampini       }
54556e683305SStefano Zampini     }
54566e683305SStefano Zampini   }
5457cbcc2c2aSStefano Zampini   /* print additional info */
5458cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
54596e683305SStefano Zampini     /* waits until all processes reaches this point */
54606e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
5461cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
5462cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5463cbcc2c2aSStefano Zampini   }
5464cbcc2c2aSStefano Zampini 
54652b510759SStefano Zampini   /* free memory */
5466c8587f34SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
5467fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
5468c8587f34SStefano Zampini   PetscFunctionReturn(0);
5469c8587f34SStefano Zampini }
5470674ae819SStefano Zampini 
5471f34684f1SStefano Zampini #undef __FUNCT__
5472f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
5473f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
5474f34684f1SStefano Zampini {
5475f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
5476f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
5477f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
5478dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
5479dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
548073be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
5481dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
5482f34684f1SStefano Zampini   PetscErrorCode ierr;
5483f34684f1SStefano Zampini 
5484f34684f1SStefano Zampini   PetscFunctionBegin;
5485f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
54860e6343abSStefano Zampini   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) {
54870e6343abSStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
5488727cdba6SStefano Zampini   }
5489dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
54903bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
5491dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
5492dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
5493dc456d91SStefano Zampini   ierr = PCBDDCSubsetNumbering(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
5494dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
5495dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
5496dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
54970e6343abSStefano Zampini   if (local_size != pcbddc->local_primal_size) {
54980e6343abSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid number of local primal indices computed %d != %d",local_size,pcbddc->local_primal_size);
54990e6343abSStefano Zampini   }
5500dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
5501dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
5502dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
5503dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
5504dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
5505f34684f1SStefano Zampini 
5506f34684f1SStefano Zampini   /* check numbering */
5507f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
5508019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
5509dc456d91SStefano Zampini     PetscInt    i;
5510b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
5511f34684f1SStefano Zampini 
5512f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5513f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
5514f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
55150fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
5516019a44ceSStefano Zampini     /* counter */
5517019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5518019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
5519019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5520019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5521019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5522019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5523019a44ceSStefano Zampini 
5524f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
5525f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
5526727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
5527f34684f1SStefano Zampini     }
5528f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
5529f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
5530f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5531e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5532e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5533e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5534e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5535f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5536019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
5537f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
5538019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
553975c01103SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]);
554075c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
5541b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
5542019a44ceSStefano 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);
5543f34684f1SStefano Zampini       }
5544f34684f1SStefano Zampini     }
5545019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
5546b9b85e73SStefano Zampini     ierr = MPI_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
5547f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5548f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
5549f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
5550f34684f1SStefano Zampini     }
5551f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5552f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
5553e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5554e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5555f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
5556f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
5557b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
5558ca8b9ea9SStefano Zampini       PetscInt *gidxs;
5559ca8b9ea9SStefano Zampini 
5560ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
55613bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
5562f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
5563f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5564f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
5565f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
55664bc2dc4bSStefano 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);
5567f34684f1SStefano Zampini       }
5568f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5569ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
5570f34684f1SStefano Zampini     }
5571f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
5572302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
5573f34684f1SStefano Zampini   }
55748bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
5575f34684f1SStefano Zampini   /* get back data */
5576f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
5577f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
5578674ae819SStefano Zampini   PetscFunctionReturn(0);
5579674ae819SStefano Zampini }
5580674ae819SStefano Zampini 
5581e456f2a8SStefano Zampini #undef __FUNCT__
5582e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
5583a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
5584e456f2a8SStefano Zampini {
5585e456f2a8SStefano Zampini   IS             localis_t;
5586a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
5587e456f2a8SStefano Zampini   PetscScalar    *vals;
5588e456f2a8SStefano Zampini   PetscErrorCode ierr;
5589e456f2a8SStefano Zampini 
5590e456f2a8SStefano Zampini   PetscFunctionBegin;
5591a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
5592e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
5593854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
5594e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
5595e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
5596a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
5597a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
55981035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
5599a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
56001035eff8SStefano Zampini   }
5601a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
5602e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
5603e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
5604a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
5605a7dc3881SStefano Zampini   /* now compute set in local ordering */
5606a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5607a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5608a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
5609a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
5610a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
5611ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
5612e456f2a8SStefano Zampini       lsize++;
5613e456f2a8SStefano Zampini     }
5614e456f2a8SStefano Zampini   }
5615854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
5616a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
5617ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
5618e456f2a8SStefano Zampini       idxs[lsize++] = i;
5619e456f2a8SStefano Zampini     }
5620e456f2a8SStefano Zampini   }
5621a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
5622a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
5623e456f2a8SStefano Zampini   *localis = localis_t;
5624e456f2a8SStefano Zampini   PetscFunctionReturn(0);
5625e456f2a8SStefano Zampini }
5626906d46d4SStefano Zampini 
5627906d46d4SStefano Zampini /* the next two functions will be called in KSPMatMult if a change of basis has been requested */
5628906d46d4SStefano Zampini #undef __FUNCT__
5629906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMult_Private"
5630906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMult_Private(Mat A, Vec x, Vec y)
5631906d46d4SStefano Zampini {
5632906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
5633906d46d4SStefano Zampini   PetscErrorCode   ierr;
5634906d46d4SStefano Zampini 
5635906d46d4SStefano Zampini   PetscFunctionBegin;
5636906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
5637906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
5638906d46d4SStefano Zampini   ierr = MatMult(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
5639906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
5640906d46d4SStefano Zampini   PetscFunctionReturn(0);
5641906d46d4SStefano Zampini }
5642906d46d4SStefano Zampini 
5643906d46d4SStefano Zampini #undef __FUNCT__
5644906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMultTranspose_Private"
5645906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMultTranspose_Private(Mat A, Vec x, Vec y)
5646906d46d4SStefano Zampini {
5647906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
5648906d46d4SStefano Zampini   PetscErrorCode   ierr;
5649906d46d4SStefano Zampini 
5650906d46d4SStefano Zampini   PetscFunctionBegin;
5651906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
5652906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
5653906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
5654906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
5655906d46d4SStefano Zampini   PetscFunctionReturn(0);
5656906d46d4SStefano Zampini }
5657b96c3477SStefano Zampini 
5658b96c3477SStefano Zampini #undef __FUNCT__
5659b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
566008122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
5661b96c3477SStefano Zampini {
5662a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
5663b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
5664b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
5665a64f4aa4SStefano Zampini   Mat                 S_j;
5666b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
5667b96c3477SStefano Zampini   PetscBool           free_used_adj;
5668b96c3477SStefano Zampini   PetscErrorCode      ierr;
5669b96c3477SStefano Zampini 
5670b96c3477SStefano Zampini   PetscFunctionBegin;
5671b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
5672b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
567308122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
5674b96c3477SStefano Zampini     used_xadj = NULL;
5675b96c3477SStefano Zampini     used_adjncy = NULL;
5676b96c3477SStefano Zampini   } else {
567708122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
567808122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
567908122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
568008122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
5681b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
5682b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
5683b96c3477SStefano Zampini     } else {
56842fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
5685b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
5686b96c3477SStefano Zampini       PetscInt       nvtxs;
5687b96c3477SStefano Zampini 
56882fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
56892fffb893SStefano Zampini       if (flg_row) {
5690b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
5691b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
5692b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
5693b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
56942fffb893SStefano Zampini       } else {
56952fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
56962fffb893SStefano Zampini         used_xadj = NULL;
56972fffb893SStefano Zampini         used_adjncy = NULL;
56982fffb893SStefano Zampini       }
56992fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
5700b96c3477SStefano Zampini     }
5701b96c3477SStefano Zampini   }
5702d5574798SStefano Zampini 
5703d5574798SStefano Zampini   /* setup sub_schurs data */
5704a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
5705a64f4aa4SStefano Zampini   if (!sub_schurs->use_mumps) {
5706a64f4aa4SStefano Zampini     /* pcbddc->ksp_D up to date only if not using MUMPS */
5707a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
570806a4e24aSStefano 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);
5709a64f4aa4SStefano Zampini   } else {
57106816873aSStefano Zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
571104708bb6SStefano Zampini     PetscBool isseqaij;
57125feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
57135feab87aSStefano Zampini       PetscInt n_vertices;
57145feab87aSStefano Zampini 
57155feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
57162034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
57175feab87aSStefano Zampini     }
571804708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
571904708bb6SStefano Zampini     if (!isseqaij) {
572004708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
572104708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
572204708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
572304708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
572404708bb6SStefano Zampini       } else {
572504708bb6SStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_REUSE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
572604708bb6SStefano Zampini       }
572704708bb6SStefano Zampini     }
572806a4e24aSStefano 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);
5729a64f4aa4SStefano Zampini   }
5730a64f4aa4SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
5731b96c3477SStefano Zampini 
5732b96c3477SStefano Zampini   /* free adjacency */
5733b96c3477SStefano Zampini   if (free_used_adj) {
5734b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
5735b96c3477SStefano Zampini   }
5736b96c3477SStefano Zampini   PetscFunctionReturn(0);
5737b96c3477SStefano Zampini }
5738b96c3477SStefano Zampini 
5739b96c3477SStefano Zampini #undef __FUNCT__
5740b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
574108122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
5742b96c3477SStefano Zampini {
5743b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
5744b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
5745b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
5746b96c3477SStefano Zampini   PCBDDCGraph         graph;
5747b96c3477SStefano Zampini   PetscErrorCode      ierr;
5748b96c3477SStefano Zampini 
5749b96c3477SStefano Zampini   PetscFunctionBegin;
5750b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
575108122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
57523301b35fSStefano Zampini     IS       verticesIS,verticescomm;
57533301b35fSStefano Zampini     PetscInt vsize,*idxs;
5754b96c3477SStefano Zampini 
5755b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
57563301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
57573301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
57583301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
57593301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
57603301b35fSStefano Zampini     ierr = ISDestroy(&verticesIS);CHKERRQ(ierr);
5761b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
57627fb0e2dbSStefano Zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global);CHKERRQ(ierr);
57633301b35fSStefano Zampini     ierr = PCBDDCGraphSetUp(graph,0,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
57643301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
5765b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
5766b96c3477SStefano Zampini /*
5767b96c3477SStefano Zampini     if (pcbddc->dbg_flag) {
5768b96c3477SStefano Zampini       ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
5769b96c3477SStefano Zampini     }
5770b96c3477SStefano Zampini */
5771b96c3477SStefano Zampini   } else {
5772b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
5773b96c3477SStefano Zampini   }
5774b96c3477SStefano Zampini 
5775b96c3477SStefano Zampini   /* sub_schurs init */
5776a64f4aa4SStefano Zampini   ierr = PCBDDCSubSchursInit(sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap);CHKERRQ(ierr);
5777a64f4aa4SStefano Zampini 
5778b96c3477SStefano Zampini   /* free graph struct */
577908122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
5780b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
5781b96c3477SStefano Zampini   }
5782b96c3477SStefano Zampini   PetscFunctionReturn(0);
5783b96c3477SStefano Zampini }
5784fa34dd3eSStefano Zampini 
5785fa34dd3eSStefano Zampini #undef __FUNCT__
5786fa34dd3eSStefano Zampini #define __FUNCT__ "PCBDDCCheckOperator"
5787fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
5788fa34dd3eSStefano Zampini {
5789fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
5790fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
5791fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
5792fa34dd3eSStefano Zampini 
5793fa34dd3eSStefano Zampini   PetscFunctionBegin;
5794fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
5795fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
57964f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
5797fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
57984f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
579975c01103SStefano Zampini     PetscReal      norm;
5800fa34dd3eSStefano Zampini     PetscInt       i;
5801fa34dd3eSStefano Zampini 
5802fa34dd3eSStefano Zampini     /* B0 and B0_B */
5803fa34dd3eSStefano Zampini     if (zerodiag) {
5804fa34dd3eSStefano Zampini       IS       dummy;
5805fa34dd3eSStefano Zampini 
58064f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
58074f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
5808fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
5809fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
5810fa34dd3eSStefano Zampini     }
5811fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
5812fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
5813fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
5814fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5815fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5816fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5817fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5818fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
5819fa34dd3eSStefano Zampini     /* S_j */
5820fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
5821fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
5822fa34dd3eSStefano Zampini 
5823fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
5824fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
5825fa34dd3eSStefano Zampini     /* continuous in primal space */
5826fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
5827fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5828fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5829fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
58304f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
58314f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
5832fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
5833fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5834fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
5835fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
5836fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5837fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5838fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
5839fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
5840fa34dd3eSStefano Zampini 
5841fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
5842fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
5843fa34dd3eSStefano Zampini     /* local with Schur */
5844fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
5845fa34dd3eSStefano Zampini     if (zerodiag) {
5846fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
58474f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
5848fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
5849fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
5850fa34dd3eSStefano Zampini     }
5851fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
5852fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5853fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5854fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5855fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
5856fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
5857fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
5858fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5859fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
5860fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5861fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5862fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5863fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5864fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5865fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
5866fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
5867fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
5868fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
5869fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
5870fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
5871fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5872fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5873fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
5874fa34dd3eSStefano Zampini     if (zerodiag) {
5875fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
5876fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
58774f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
5878fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
5879fa34dd3eSStefano Zampini     }
5880fa34dd3eSStefano Zampini     /* BDDC */
5881fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
5882fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
5883fa34dd3eSStefano Zampini 
5884fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
5885fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
5886fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
5887fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
58884f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
58894f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
5890fa34dd3eSStefano Zampini     }
58914f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
5892fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
5893fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
5894fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
5895fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
5896fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
5897fa34dd3eSStefano Zampini   }
5898fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
5899fa34dd3eSStefano Zampini }
5900