xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision a198735b2624f1734d8e2b44904b1efeddb7ac51)
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>
5daf8a457SStefano Zampini #include <petsc/private/sfimpl.h>
6674ae819SStefano Zampini 
7669cc0f4SStefano Zampini 
8669cc0f4SStefano Zampini #undef __FUNCT__
9669cc0f4SStefano Zampini #define __FUNCT__ "PCBDDCComputeNoNetFlux"
10669cc0f4SStefano Zampini PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, PCBDDCGraph graph, MatNullSpace *nnsp)
11669cc0f4SStefano Zampini {
12*a198735bSStefano Zampini   Mat                    loc_divudotp;
13*a198735bSStefano Zampini   Vec                    p,v,quad_vec,*quad_vecs;
14669cc0f4SStefano Zampini   ISLocalToGlobalMapping rmap;
15669cc0f4SStefano Zampini   IS                     *faces,*edges;
16669cc0f4SStefano Zampini   PetscScalar            *vals;
17669cc0f4SStefano Zampini   const PetscScalar      *array;
18669cc0f4SStefano Zampini   PetscInt               i,maxneighs,lmaxneighs,maxsize,nf,ne;
191ae86dd6SStefano Zampini   PetscMPIInt            rank;
20*a198735bSStefano Zampini   PetscErrorCode         ierr;
21669cc0f4SStefano Zampini 
22669cc0f4SStefano Zampini   PetscFunctionBegin;
23669cc0f4SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(graph,&nf,&faces,&ne,&edges,NULL);CHKERRQ(ierr);
24669cc0f4SStefano Zampini   if (graph->twodim) {
25669cc0f4SStefano Zampini     lmaxneighs = 2;
26669cc0f4SStefano Zampini   } else {
27669cc0f4SStefano Zampini     lmaxneighs = 1;
28669cc0f4SStefano Zampini     for (i=0;i<ne;i++) {
29669cc0f4SStefano Zampini       const PetscInt *idxs;
30669cc0f4SStefano Zampini       ierr = ISGetIndices(edges[i],&idxs);CHKERRQ(ierr);
31669cc0f4SStefano Zampini       lmaxneighs = PetscMax(lmaxneighs,graph->count[idxs[0]]);
32669cc0f4SStefano Zampini       ierr = ISRestoreIndices(edges[i],&idxs);CHKERRQ(ierr);
33669cc0f4SStefano Zampini     }
34669cc0f4SStefano Zampini     lmaxneighs++; /* graph count does not include self */
35669cc0f4SStefano Zampini   }
36669cc0f4SStefano Zampini   ierr = MPIU_Allreduce(&lmaxneighs,&maxneighs,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
37669cc0f4SStefano Zampini   maxsize = 0;
38669cc0f4SStefano Zampini   for (i=0;i<ne;i++) {
39669cc0f4SStefano Zampini     PetscInt nn;
40669cc0f4SStefano Zampini     ierr = ISGetLocalSize(edges[i],&nn);CHKERRQ(ierr);
41669cc0f4SStefano Zampini     maxsize = PetscMax(maxsize,nn);
42669cc0f4SStefano Zampini   }
43669cc0f4SStefano Zampini   for (i=0;i<nf;i++) {
44669cc0f4SStefano Zampini     PetscInt nn;
45669cc0f4SStefano Zampini     ierr = ISGetLocalSize(faces[i],&nn);CHKERRQ(ierr);
46669cc0f4SStefano Zampini     maxsize = PetscMax(maxsize,nn);
47669cc0f4SStefano Zampini   }
48669cc0f4SStefano Zampini   ierr = PetscMalloc1(maxsize,&vals);CHKERRQ(ierr);
49669cc0f4SStefano Zampini   /* create vectors to hold quadrature weights */
50669cc0f4SStefano Zampini   ierr = MatCreateVecs(A,&quad_vec,NULL);CHKERRQ(ierr);
51669cc0f4SStefano Zampini   ierr = MatGetLocalToGlobalMapping(A,&rmap,NULL);CHKERRQ(ierr);
52669cc0f4SStefano Zampini   ierr = VecDuplicateVecs(quad_vec,maxneighs,&quad_vecs);CHKERRQ(ierr);
531ae86dd6SStefano Zampini   ierr = VecDestroy(&quad_vec);CHKERRQ(ierr);
54669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
55669cc0f4SStefano Zampini     PetscInt first,last;
56669cc0f4SStefano Zampini 
57669cc0f4SStefano Zampini     ierr = VecSetLocalToGlobalMapping(quad_vecs[i],rmap);CHKERRQ(ierr);
58669cc0f4SStefano Zampini     /* the near-null space fo BDDC carries information on quadrature weights,
59669cc0f4SStefano Zampini        and these can be collinear -> so cheat with MatNullSpaceCreate
60669cc0f4SStefano Zampini        and create a suitable set of basis vectors first */
61669cc0f4SStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
62669cc0f4SStefano Zampini     if (i>=first && i < last) {
63669cc0f4SStefano Zampini       PetscScalar *data;
64669cc0f4SStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
65669cc0f4SStefano Zampini       data[i-first] = 1.;
66669cc0f4SStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
67669cc0f4SStefano Zampini     }
68669cc0f4SStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
69669cc0f4SStefano Zampini   }
70669cc0f4SStefano Zampini   ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)A),PETSC_FALSE,maxneighs,quad_vecs,nnsp);CHKERRQ(ierr);
711ae86dd6SStefano Zampini   for (i=0;i<maxneighs;i++) { /* reset vectors */
721ae86dd6SStefano Zampini     PetscInt first,last;
731ae86dd6SStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
741ae86dd6SStefano Zampini     if (i>=first && i < last) {
751ae86dd6SStefano Zampini       PetscScalar *data;
761ae86dd6SStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
771ae86dd6SStefano Zampini       data[i-first] = 0.;
781ae86dd6SStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
791ae86dd6SStefano Zampini     }
801ae86dd6SStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
811ae86dd6SStefano Zampini   }
82669cc0f4SStefano Zampini   /* compute local quad vec */
83*a198735bSStefano Zampini   ierr = MatISGetLocalMat(divudotp,&loc_divudotp);CHKERRQ(ierr);
84*a198735bSStefano Zampini   ierr = MatCreateVecs(loc_divudotp,&v,&p);CHKERRQ(ierr);
85669cc0f4SStefano Zampini   ierr = VecSet(p,1.);CHKERRQ(ierr);
86*a198735bSStefano Zampini   ierr = MatMultTranspose(loc_divudotp,p,v);CHKERRQ(ierr);
87669cc0f4SStefano Zampini   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
88669cc0f4SStefano Zampini   ierr = VecDestroy(&p);CHKERRQ(ierr);
891ae86dd6SStefano Zampini   /* insert in global quadrature vecs */
901ae86dd6SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank);CHKERRQ(ierr);
91669cc0f4SStefano Zampini   for (i=0;i<nf;i++) {
92669cc0f4SStefano Zampini     const PetscInt    *idxs;
93669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
94669cc0f4SStefano Zampini 
95669cc0f4SStefano Zampini     ierr = ISGetIndices(faces[i],&idxs);CHKERRQ(ierr);
96669cc0f4SStefano Zampini     ierr = ISGetLocalSize(faces[i],&nn);CHKERRQ(ierr);
97669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
981ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
99669cc0f4SStefano Zampini     idx = -(idx+1);
100669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
101669cc0f4SStefano Zampini     ierr = ISRestoreIndices(faces[i],&idxs);CHKERRQ(ierr);
102669cc0f4SStefano Zampini     ierr = ISDestroy(&faces[i]);CHKERRQ(ierr);
103669cc0f4SStefano Zampini   }
104669cc0f4SStefano Zampini   for (i=0;i<ne;i++) {
105669cc0f4SStefano Zampini     const PetscInt    *idxs;
106669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
107669cc0f4SStefano Zampini 
108669cc0f4SStefano Zampini     ierr = ISGetIndices(edges[i],&idxs);CHKERRQ(ierr);
109669cc0f4SStefano Zampini     ierr = ISGetLocalSize(edges[i],&nn);CHKERRQ(ierr);
110669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
1111ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
112669cc0f4SStefano Zampini     idx = -(idx+1);
113669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
114669cc0f4SStefano Zampini     ierr = ISRestoreIndices(edges[i],&idxs);CHKERRQ(ierr);
115669cc0f4SStefano Zampini     ierr = ISDestroy(&edges[i]);CHKERRQ(ierr);
116669cc0f4SStefano Zampini   }
117669cc0f4SStefano Zampini   ierr = PetscFree(edges);CHKERRQ(ierr);
118669cc0f4SStefano Zampini   ierr = PetscFree(faces);CHKERRQ(ierr);
119669cc0f4SStefano Zampini   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
120669cc0f4SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
121669cc0f4SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
122669cc0f4SStefano Zampini 
123669cc0f4SStefano Zampini   /* assemble near null space */
124669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
125669cc0f4SStefano Zampini     ierr = VecAssemblyBegin(quad_vecs[i]);CHKERRQ(ierr);
126669cc0f4SStefano Zampini   }
127669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
128669cc0f4SStefano Zampini     ierr = VecAssemblyEnd(quad_vecs[i]);CHKERRQ(ierr);
129669cc0f4SStefano Zampini   }
130669cc0f4SStefano Zampini   ierr = VecDestroyVecs(maxneighs,&quad_vecs);CHKERRQ(ierr);
131669cc0f4SStefano Zampini   PetscFunctionReturn(0);
132669cc0f4SStefano Zampini }
133669cc0f4SStefano Zampini 
134669cc0f4SStefano Zampini 
135a3df083aSStefano Zampini #undef __FUNCT__
1361f4df5f7SStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalTopologyInfo"
1371f4df5f7SStefano Zampini PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc)
1381f4df5f7SStefano Zampini {
1391f4df5f7SStefano Zampini   PetscErrorCode ierr;
1401f4df5f7SStefano Zampini   Vec            local,global;
1411f4df5f7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1421f4df5f7SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
1431f4df5f7SStefano Zampini 
1441f4df5f7SStefano Zampini   PetscFunctionBegin;
1451f4df5f7SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&global,NULL);CHKERRQ(ierr);
1461f4df5f7SStefano Zampini   /* need to convert from global to local topology information and remove references to information in global ordering */
1471f4df5f7SStefano Zampini   ierr = MatCreateVecs(matis->A,&local,NULL);CHKERRQ(ierr);
1481f4df5f7SStefano Zampini   if (pcbddc->user_provided_isfordofs) {
1491f4df5f7SStefano Zampini     if (pcbddc->n_ISForDofs) {
1501f4df5f7SStefano Zampini       PetscInt i;
1511f4df5f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
1521f4df5f7SStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
1531f4df5f7SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
1541f4df5f7SStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
1551f4df5f7SStefano Zampini       }
1561f4df5f7SStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
1571f4df5f7SStefano Zampini       pcbddc->n_ISForDofs = 0;
1581f4df5f7SStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
1591f4df5f7SStefano Zampini     }
1601f4df5f7SStefano Zampini   } else {
161986cdee1SStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering if bs > 1 */
1621f4df5f7SStefano Zampini       PetscInt i, n = matis->A->rmap->n;
163986cdee1SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&i);CHKERRQ(ierr);
164986cdee1SStefano Zampini       if (i > 1) {
165986cdee1SStefano Zampini         pcbddc->n_ISForDofsLocal = i;
1661f4df5f7SStefano Zampini         ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
1671f4df5f7SStefano Zampini         for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
1681f4df5f7SStefano Zampini           ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
1691f4df5f7SStefano Zampini         }
1701f4df5f7SStefano Zampini       }
1711f4df5f7SStefano Zampini     }
172986cdee1SStefano Zampini   }
1731f4df5f7SStefano Zampini 
1741f4df5f7SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) {
1751f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
1761f4df5f7SStefano Zampini   }
1771f4df5f7SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) {
1781f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
1791f4df5f7SStefano Zampini   }
1801f4df5f7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) {
1811f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
1821f4df5f7SStefano Zampini   }
1831f4df5f7SStefano Zampini   ierr = VecDestroy(&global);CHKERRQ(ierr);
1841f4df5f7SStefano Zampini   ierr = VecDestroy(&local);CHKERRQ(ierr);
1851f4df5f7SStefano Zampini   PetscFunctionReturn(0);
1861f4df5f7SStefano Zampini }
1871f4df5f7SStefano Zampini 
1881f4df5f7SStefano Zampini #undef __FUNCT__
1893e589ea0SStefano Zampini #define __FUNCT__ "PCBDDCBenignRemoveInterior"
1903e589ea0SStefano Zampini PetscErrorCode PCBDDCBenignRemoveInterior(PC pc,Vec r,Vec z)
1913e589ea0SStefano Zampini {
1923e589ea0SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
1933e589ea0SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1943e589ea0SStefano Zampini   PetscErrorCode    ierr;
1953e589ea0SStefano Zampini 
1963e589ea0SStefano Zampini   PetscFunctionBegin;
1973e589ea0SStefano Zampini   if (!pcbddc->benign_have_null) {
1983e589ea0SStefano Zampini     PetscFunctionReturn(0);
1993e589ea0SStefano Zampini   }
2003e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2013e589ea0SStefano Zampini     Vec swap;
2023e589ea0SStefano Zampini 
2033e589ea0SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
2043e589ea0SStefano Zampini     swap = pcbddc->work_change;
2053e589ea0SStefano Zampini     pcbddc->work_change = r;
2063e589ea0SStefano Zampini     r = swap;
2073e589ea0SStefano Zampini   }
2083e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2093e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2103e589ea0SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
2113e589ea0SStefano Zampini   ierr = VecSet(z,0.);CHKERRQ(ierr);
2123e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2133e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2143e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2153e589ea0SStefano Zampini     Vec swap;
2163e589ea0SStefano Zampini 
2173e589ea0SStefano Zampini     swap = r;
2183e589ea0SStefano Zampini     r = pcbddc->work_change;
2193e589ea0SStefano Zampini     pcbddc->work_change = swap;
2203e589ea0SStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
2213e589ea0SStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
2223e589ea0SStefano Zampini   }
2233e589ea0SStefano Zampini   PetscFunctionReturn(0);
2243e589ea0SStefano Zampini }
2253e589ea0SStefano Zampini 
2263e589ea0SStefano Zampini #undef __FUNCT__
227a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private_Private"
228a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
229a3df083aSStefano Zampini {
230a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
231a3df083aSStefano Zampini   PetscErrorCode          ierr;
232a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
233a3df083aSStefano Zampini 
234a3df083aSStefano Zampini   PetscFunctionBegin;
235a3df083aSStefano Zampini   ierr = MatShellGetContext(A,&ctx);CHKERRQ(ierr);
236a3df083aSStefano Zampini   if (transpose) {
237a3df083aSStefano Zampini     apply_right = ctx->apply_left;
238a3df083aSStefano Zampini     apply_left = ctx->apply_right;
239a3df083aSStefano Zampini   } else {
240a3df083aSStefano Zampini     apply_right = ctx->apply_right;
241a3df083aSStefano Zampini     apply_left = ctx->apply_left;
242a3df083aSStefano Zampini   }
243a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
244a3df083aSStefano Zampini   if (apply_right) {
245a3df083aSStefano Zampini     const PetscScalar *ax;
246a3df083aSStefano Zampini     PetscInt          nl,i;
247a3df083aSStefano Zampini 
248a3df083aSStefano Zampini     ierr = VecGetLocalSize(x,&nl);CHKERRQ(ierr);
249a3df083aSStefano Zampini     ierr = VecGetArrayRead(x,&ax);CHKERRQ(ierr);
250a3df083aSStefano Zampini     ierr = PetscMemcpy(ctx->work,ax,nl*sizeof(PetscScalar));CHKERRQ(ierr);
251a3df083aSStefano Zampini     ierr = VecRestoreArrayRead(x,&ax);CHKERRQ(ierr);
252a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
253a3df083aSStefano Zampini       PetscScalar    sum,val;
254a3df083aSStefano Zampini       const PetscInt *idxs;
255a3df083aSStefano Zampini       PetscInt       nz,j;
256a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
257a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
258a3df083aSStefano Zampini       sum = 0.;
259a3df083aSStefano Zampini       if (ctx->apply_p0) {
260a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
261a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
262a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
263a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
264a3df083aSStefano Zampini         }
265a3df083aSStefano Zampini       } else {
266a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
267a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
268a3df083aSStefano Zampini         }
269a3df083aSStefano Zampini       }
270a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
271a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
272a3df083aSStefano Zampini     }
273a3df083aSStefano Zampini     ierr = VecPlaceArray(x,ctx->work);CHKERRQ(ierr);
274a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
275a3df083aSStefano Zampini   }
276a3df083aSStefano Zampini   if (transpose) {
277a3df083aSStefano Zampini     ierr = MatMultTranspose(ctx->A,x,y);CHKERRQ(ierr);
278a3df083aSStefano Zampini   } else {
279a3df083aSStefano Zampini     ierr = MatMult(ctx->A,x,y);CHKERRQ(ierr);
280a3df083aSStefano Zampini   }
281a3df083aSStefano Zampini   if (reset_x) {
282a3df083aSStefano Zampini     ierr = VecResetArray(x);CHKERRQ(ierr);
283a3df083aSStefano Zampini   }
284a3df083aSStefano Zampini   if (apply_left) {
285a3df083aSStefano Zampini     PetscScalar *ay;
286a3df083aSStefano Zampini     PetscInt    i;
287a3df083aSStefano Zampini 
288a3df083aSStefano Zampini     ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
289a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
290a3df083aSStefano Zampini       PetscScalar    sum,val;
291a3df083aSStefano Zampini       const PetscInt *idxs;
292a3df083aSStefano Zampini       PetscInt       nz,j;
293a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
294a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
295a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
296a3df083aSStefano Zampini       if (ctx->apply_p0) {
297a3df083aSStefano Zampini         sum = 0.;
298a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
299a3df083aSStefano Zampini           sum += ay[idxs[j]];
300a3df083aSStefano Zampini           ay[idxs[j]] += val;
301a3df083aSStefano Zampini         }
302a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
303a3df083aSStefano Zampini       } else {
304a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
305a3df083aSStefano Zampini           ay[idxs[j]] += val;
306a3df083aSStefano Zampini         }
307a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
308a3df083aSStefano Zampini       }
309a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
310a3df083aSStefano Zampini     }
311a3df083aSStefano Zampini     ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
312a3df083aSStefano Zampini   }
313a3df083aSStefano Zampini   PetscFunctionReturn(0);
314a3df083aSStefano Zampini }
315a3df083aSStefano Zampini 
316a3df083aSStefano Zampini #undef __FUNCT__
317a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMultTranspose_Private"
318a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
319a3df083aSStefano Zampini {
320a3df083aSStefano Zampini   PetscErrorCode ierr;
321a3df083aSStefano Zampini 
322a3df083aSStefano Zampini   PetscFunctionBegin;
323a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
324a3df083aSStefano Zampini   PetscFunctionReturn(0);
325a3df083aSStefano Zampini }
326a3df083aSStefano Zampini 
327a3df083aSStefano Zampini #undef __FUNCT__
328a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private"
329a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
330a3df083aSStefano Zampini {
331a3df083aSStefano Zampini   PetscErrorCode ierr;
332a3df083aSStefano Zampini 
333a3df083aSStefano Zampini   PetscFunctionBegin;
334a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
335a3df083aSStefano Zampini   PetscFunctionReturn(0);
336a3df083aSStefano Zampini }
337a3df083aSStefano Zampini 
338a3df083aSStefano Zampini #undef __FUNCT__
339a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignShellMat"
340a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
341a3df083aSStefano Zampini {
342a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
343a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
344a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
345a3df083aSStefano Zampini   PetscErrorCode          ierr;
346a3df083aSStefano Zampini 
347a3df083aSStefano Zampini   PetscFunctionBegin;
348a3df083aSStefano Zampini   if (!restore) {
3491dd7afcfSStefano Zampini     Mat                A_IB,A_BI;
350a3df083aSStefano Zampini     PetscScalar        *work;
351b334f244SStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL;
352a3df083aSStefano Zampini 
3531dd7afcfSStefano Zampini     if (pcbddc->benign_original_mat) {
3541dd7afcfSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored");
3551dd7afcfSStefano Zampini     }
3561dd7afcfSStefano Zampini     if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) {
3571dd7afcfSStefano Zampini       PetscFunctionReturn(0);
3581dd7afcfSStefano Zampini     }
359a3df083aSStefano Zampini     ierr = PetscMalloc1(pcis->n,&work);CHKERRQ(ierr);
360a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A_IB);CHKERRQ(ierr);
361a3df083aSStefano Zampini     ierr = MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
362a3df083aSStefano Zampini     ierr = MatSetType(A_IB,MATSHELL);CHKERRQ(ierr);
363a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
364a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
365a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
366a3df083aSStefano Zampini     ierr = MatShellSetContext(A_IB,ctx);CHKERRQ(ierr);
367a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
368a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
369a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
370a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
371059032f7SStefano Zampini     if (reuse) {
372a3df083aSStefano Zampini       ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
3731dd7afcfSStefano Zampini       ctx->free = PETSC_FALSE;
374059032f7SStefano Zampini     } else { /* TODO: could be optimized for successive solves */
375059032f7SStefano Zampini       ISLocalToGlobalMapping N_to_D;
376059032f7SStefano Zampini       PetscInt               i;
377059032f7SStefano Zampini 
378059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D);CHKERRQ(ierr);
379059032f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs);CHKERRQ(ierr);
380059032f7SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
381059032f7SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
382059032f7SStefano Zampini       }
383059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&N_to_D);CHKERRQ(ierr);
3841dd7afcfSStefano Zampini       ctx->free = PETSC_TRUE;
385059032f7SStefano Zampini     }
386a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
387a3df083aSStefano Zampini     ctx->work = work;
388a3df083aSStefano Zampini     ierr = MatSetUp(A_IB);CHKERRQ(ierr);
389a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
390a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
391a3df083aSStefano Zampini     pcis->A_IB = A_IB;
392a3df083aSStefano Zampini 
393a3df083aSStefano Zampini     /* A_BI as A_IB^T */
394a3df083aSStefano Zampini     ierr = MatCreateTranspose(A_IB,&A_BI);CHKERRQ(ierr);
395a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
396a3df083aSStefano Zampini     pcis->A_BI = A_BI;
397a3df083aSStefano Zampini   } else {
3981dd7afcfSStefano Zampini     if (!pcbddc->benign_original_mat) {
3991dd7afcfSStefano Zampini       PetscFunctionReturn(0);
4001dd7afcfSStefano Zampini     }
401a3df083aSStefano Zampini     ierr = MatShellGetContext(pcis->A_IB,&ctx);CHKERRQ(ierr);
402a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
403a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
4041dd7afcfSStefano Zampini     ctx->A = NULL;
4051dd7afcfSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
4061dd7afcfSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
4071dd7afcfSStefano Zampini     pcbddc->benign_original_mat = NULL;
4081dd7afcfSStefano Zampini     if (ctx->free) {
409059032f7SStefano Zampini       PetscInt i;
4101dd7afcfSStefano Zampini       for (i=0;i<ctx->benign_n;i++) {
411059032f7SStefano Zampini         ierr = ISDestroy(&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
412059032f7SStefano Zampini       }
413059032f7SStefano Zampini       ierr = PetscFree(ctx->benign_zerodiag_subs);CHKERRQ(ierr);
414059032f7SStefano Zampini     }
415a3df083aSStefano Zampini     ierr = PetscFree(ctx->work);CHKERRQ(ierr);
416a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
417a3df083aSStefano Zampini   }
418a3df083aSStefano Zampini   PetscFunctionReturn(0);
419a3df083aSStefano Zampini }
420a3df083aSStefano Zampini 
421a3df083aSStefano Zampini /* used just in bddc debug mode */
422a3df083aSStefano Zampini #undef __FUNCT__
423a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignProject"
424a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
425a3df083aSStefano Zampini {
426a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
427a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
428a3df083aSStefano Zampini   Mat            An;
429a3df083aSStefano Zampini   PetscErrorCode ierr;
430a3df083aSStefano Zampini 
431a3df083aSStefano Zampini   PetscFunctionBegin;
432a3df083aSStefano Zampini   ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An);CHKERRQ(ierr);
433a3df083aSStefano Zampini   ierr = MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL);CHKERRQ(ierr);
434a3df083aSStefano Zampini   if (is1) {
435a3df083aSStefano Zampini     ierr = MatGetSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
436a3df083aSStefano Zampini     ierr = MatDestroy(&An);CHKERRQ(ierr);
437a3df083aSStefano Zampini   } else {
438a3df083aSStefano Zampini     *B = An;
439a3df083aSStefano Zampini   }
440a3df083aSStefano Zampini   PetscFunctionReturn(0);
441a3df083aSStefano Zampini }
442a3df083aSStefano Zampini 
4431cf9b237SStefano Zampini /* TODO: add reuse flag */
4441cf9b237SStefano Zampini #undef __FUNCT__
4451cf9b237SStefano Zampini #define __FUNCT__ "MatSeqAIJCompress"
4461cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
4471cf9b237SStefano Zampini {
4481cf9b237SStefano Zampini   Mat            Bt;
4491cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
4501cf9b237SStefano Zampini   const PetscInt *ii,*ij;
4511cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
4521cf9b237SStefano Zampini   PetscBool      flg_row;
4531cf9b237SStefano Zampini   PetscErrorCode ierr;
4541cf9b237SStefano Zampini 
4551cf9b237SStefano Zampini   PetscFunctionBegin;
4561cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
4571cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
4581cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
4591cf9b237SStefano Zampini   nnz = n;
4601cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
4611cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
4621cf9b237SStefano Zampini   }
4631cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
4641cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
4651cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
4661cf9b237SStefano Zampini   nnz = 0;
4671cf9b237SStefano Zampini   bii[0] = 0;
4681cf9b237SStefano Zampini   for (i=0;i<n;i++) {
4691cf9b237SStefano Zampini     PetscInt j;
4701cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
4711cf9b237SStefano Zampini       PetscScalar entry = a[j];
4721cf9b237SStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || ij[j] == i) {
4731cf9b237SStefano Zampini         bij[nnz] = ij[j];
4741cf9b237SStefano Zampini         bdata[nnz] = entry;
4751cf9b237SStefano Zampini         nnz++;
4761cf9b237SStefano Zampini       }
4771cf9b237SStefano Zampini     }
4781cf9b237SStefano Zampini     bii[i+1] = nnz;
4791cf9b237SStefano Zampini   }
4801cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
4811cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
4821cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
4831cf9b237SStefano Zampini   {
4841cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
4851cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
4861cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
4871cf9b237SStefano Zampini   }
4881cf9b237SStefano Zampini   *B = Bt;
4891cf9b237SStefano Zampini   PetscFunctionReturn(0);
4901cf9b237SStefano Zampini }
4911cf9b237SStefano Zampini 
492674ae819SStefano Zampini #undef __FUNCT__
4934f1b2e48SStefano Zampini #define __FUNCT__ "MatDetectDisconnectedComponents"
4944f1b2e48SStefano Zampini PetscErrorCode MatDetectDisconnectedComponents(Mat A, PetscBool filter, PetscInt *ncc, IS* cc[])
4954f1b2e48SStefano Zampini {
4964f1b2e48SStefano Zampini   Mat                    B;
4974f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
4984f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
4994f1b2e48SStefano Zampini   PCBDDCGraph            graph;
5004f1b2e48SStefano Zampini   PetscInt               i,n;
5014f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
5024f1b2e48SStefano Zampini   PetscInt               *xadj_filtered,*adjncy_filtered;
5034f1b2e48SStefano Zampini   PetscBool              flg_row,isseqaij;
5044f1b2e48SStefano Zampini   PetscErrorCode         ierr;
5054f1b2e48SStefano Zampini 
5064f1b2e48SStefano Zampini   PetscFunctionBegin;
50763c961adSStefano Zampini   if (!A->rmap->N || !A->cmap->N) {
50863c961adSStefano Zampini     *ncc = 0;
50963c961adSStefano Zampini     *cc = NULL;
51063c961adSStefano Zampini     PetscFunctionReturn(0);
51163c961adSStefano Zampini   }
5124f1b2e48SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
5134f1b2e48SStefano Zampini   if (!isseqaij && filter) {
5141cf9b237SStefano Zampini     PetscBool isseqdense;
5151cf9b237SStefano Zampini 
5161cf9b237SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
5171cf9b237SStefano Zampini     if (!isseqdense) {
5184f1b2e48SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
5191cf9b237SStefano Zampini     } else { /* TODO: rectangular case and LDA */
5201cf9b237SStefano Zampini       PetscScalar *array;
5211cf9b237SStefano Zampini       PetscReal   chop=1.e-6;
5221cf9b237SStefano Zampini 
5231cf9b237SStefano Zampini       ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
5241cf9b237SStefano Zampini       ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
5251cf9b237SStefano Zampini       ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
5261cf9b237SStefano Zampini       for (i=0;i<n;i++) {
5271cf9b237SStefano Zampini         PetscInt j;
5281cf9b237SStefano Zampini         for (j=i+1;j<n;j++) {
5291cf9b237SStefano Zampini           PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
5301cf9b237SStefano Zampini           if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
5311cf9b237SStefano Zampini           if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
5321cf9b237SStefano Zampini         }
5331cf9b237SStefano Zampini       }
5341cf9b237SStefano Zampini       ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
5359d54b7f4SStefano Zampini       ierr = MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
5361cf9b237SStefano Zampini     }
5374f1b2e48SStefano Zampini   } else {
5384f1b2e48SStefano Zampini     B = A;
5394f1b2e48SStefano Zampini   }
5404f1b2e48SStefano Zampini   ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
5414f1b2e48SStefano Zampini 
5424f1b2e48SStefano Zampini   /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
5434f1b2e48SStefano Zampini   if (filter) {
5444f1b2e48SStefano Zampini     PetscScalar *data;
5454f1b2e48SStefano Zampini     PetscInt    j,cum;
5464f1b2e48SStefano Zampini 
5474f1b2e48SStefano Zampini     ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
5484f1b2e48SStefano Zampini     ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
5494f1b2e48SStefano Zampini     cum = 0;
5504f1b2e48SStefano Zampini     for (i=0;i<n;i++) {
5514f1b2e48SStefano Zampini       PetscInt t;
5524f1b2e48SStefano Zampini 
5534f1b2e48SStefano Zampini       for (j=xadj[i];j<xadj[i+1];j++) {
5544f1b2e48SStefano Zampini         if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
5554f1b2e48SStefano Zampini           continue;
5564f1b2e48SStefano Zampini         }
5574f1b2e48SStefano Zampini         adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
5584f1b2e48SStefano Zampini       }
5594f1b2e48SStefano Zampini       t = xadj_filtered[i];
5604f1b2e48SStefano Zampini       xadj_filtered[i] = cum;
5614f1b2e48SStefano Zampini       cum += t;
5624f1b2e48SStefano Zampini     }
5634f1b2e48SStefano Zampini     ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
5644f1b2e48SStefano Zampini   } else {
5654f1b2e48SStefano Zampini     xadj_filtered = NULL;
5664f1b2e48SStefano Zampini     adjncy_filtered = NULL;
5674f1b2e48SStefano Zampini   }
5684f1b2e48SStefano Zampini 
5694f1b2e48SStefano Zampini   /* compute local connected components using PCBDDCGraph */
5704f1b2e48SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
5714f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
5724f1b2e48SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
5734f1b2e48SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
5744f1b2e48SStefano Zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n);CHKERRQ(ierr);
5754f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
5764f1b2e48SStefano Zampini   if (xadj_filtered) {
5774f1b2e48SStefano Zampini     graph->xadj = xadj_filtered;
5784f1b2e48SStefano Zampini     graph->adjncy = adjncy_filtered;
5794f1b2e48SStefano Zampini   } else {
5804f1b2e48SStefano Zampini     graph->xadj = xadj;
5814f1b2e48SStefano Zampini     graph->adjncy = adjncy;
5824f1b2e48SStefano Zampini   }
5834f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
5844f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
5854f1b2e48SStefano Zampini   /* partial clean up */
5864f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
5874f1b2e48SStefano Zampini   ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
5881cf9b237SStefano Zampini   if (A != B) {
5894f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
5904f1b2e48SStefano Zampini   }
5914f1b2e48SStefano Zampini 
5924f1b2e48SStefano Zampini   /* get back data */
5931cf9b237SStefano Zampini   if (ncc) *ncc = graph->ncc;
5941cf9b237SStefano Zampini   if (cc) {
5954f1b2e48SStefano Zampini     ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
5964f1b2e48SStefano Zampini     for (i=0;i<graph->ncc;i++) {
5974f1b2e48SStefano 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);
5984f1b2e48SStefano Zampini     }
5994f1b2e48SStefano Zampini     *cc = cc_n;
6001cf9b237SStefano Zampini   }
6014f1b2e48SStefano Zampini   /* clean up graph */
6024f1b2e48SStefano Zampini   graph->xadj = 0;
6034f1b2e48SStefano Zampini   graph->adjncy = 0;
6044f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
6054f1b2e48SStefano Zampini   PetscFunctionReturn(0);
6064f1b2e48SStefano Zampini }
6074f1b2e48SStefano Zampini 
6084f1b2e48SStefano Zampini #undef __FUNCT__
6095408967cSStefano Zampini #define __FUNCT__ "PCBDDCBenignCheck"
6105408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
6115408967cSStefano Zampini {
6125408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
6135408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
614dee84bffSStefano Zampini   IS             dirIS = NULL;
6154f1b2e48SStefano Zampini   PetscInt       i;
6165408967cSStefano Zampini   PetscErrorCode ierr;
6175408967cSStefano Zampini 
6185408967cSStefano Zampini   PetscFunctionBegin;
619dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
6205408967cSStefano Zampini   if (zerodiag) {
6215408967cSStefano Zampini     Mat            A;
6225408967cSStefano Zampini     Vec            vec3_N;
6235408967cSStefano Zampini     PetscScalar    *vals;
6245408967cSStefano Zampini     const PetscInt *idxs;
625d12d3064SStefano Zampini     PetscInt       nz,*count;
6265408967cSStefano Zampini 
6275408967cSStefano Zampini     /* p0 */
6285408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
6295408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
6305408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
6315408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
6324f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
6335408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
6345408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6355408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6365408967cSStefano Zampini     /* v_I */
6375408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
6385408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
6395408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
6405408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
6415408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
6425408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
6435408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
6445408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
6455408967cSStefano Zampini     if (dirIS) {
6465408967cSStefano Zampini       PetscInt n;
6475408967cSStefano Zampini 
6485408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
6495408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
6505408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
6515408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
6525408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
6535408967cSStefano Zampini     }
6545408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
6555408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
6565408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
6575408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
658669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
6595408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
6605408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
661fbfcb133SStefano Zampini     if (PetscAbsScalar(vals[0]) > 1.e-1) {
662b9b0e38cSStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! b(v_I,p_0) = %1.6e (should be numerically 0.)",PetscAbsScalar(vals[0]));
6635408967cSStefano Zampini     }
6645408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
6655408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
666d12d3064SStefano Zampini 
667d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
668d12d3064SStefano Zampini     ierr = PetscCalloc1(pcis->n,&count);CHKERRQ(ierr);
669d12d3064SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
670d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
671d12d3064SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
672d12d3064SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
673d4d8cf7bSStefano Zampini     for (i=0;i<nz;i++) {
674d12d3064SStefano Zampini       if (count[idxs[i]]) {
675d12d3064SStefano Zampini         SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! pressure dof %d is an interface dof",idxs[i]);
676d12d3064SStefano Zampini       }
677d4d8cf7bSStefano Zampini     }
678d12d3064SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
679d12d3064SStefano Zampini     ierr = PetscFree(count);CHKERRQ(ierr);
6805408967cSStefano Zampini   }
681dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
6825408967cSStefano Zampini 
6835408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
6845408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
6854f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
6865408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
6874f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
6885408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
6894f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
6904f1b2e48SStefano Zampini     if ((PetscInt)PetscRealPart(pcbddc->benign_p0[i]) != -PetscGlobalRank-i) {
6914f1b2e48SStefano 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);
6924f1b2e48SStefano Zampini     }
6935408967cSStefano Zampini   }
6945408967cSStefano Zampini   PetscFunctionReturn(0);
6955408967cSStefano Zampini }
6965408967cSStefano Zampini 
6975408967cSStefano Zampini #undef __FUNCT__
698339f8db1SStefano Zampini #define __FUNCT__ "PCBDDCBenignDetectSaddlePoint"
699339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
700339f8db1SStefano Zampini {
701339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
7024f1b2e48SStefano Zampini   IS             pressures,zerodiag,*zerodiag_subs;
703b0f5fe93SStefano Zampini   PetscInt       nz,n;
7041f4df5f7SStefano Zampini   PetscInt       *interior_dofs,n_interior_dofs;
7054f1b2e48SStefano Zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag;
706339f8db1SStefano Zampini   PetscErrorCode ierr;
707339f8db1SStefano Zampini 
708339f8db1SStefano Zampini   PetscFunctionBegin;
7099f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
7109f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
711a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
712a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
713a3df083aSStefano Zampini   }
714a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
715a3df083aSStefano Zampini   pcbddc->benign_n = 0;
7161ae86dd6SStefano Zampini   /* if a local info on dofs is present, assumes that the last field represents  "pressures"
7174f1b2e48SStefano Zampini      otherwise, it uses only zerodiagonal dofs (ok if the pressure block is all zero; it could fail if it is not)
7184f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
7194f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
7201ae86dd6SStefano Zampini      since the local Schur complements are already SPD
7214f1b2e48SStefano Zampini   */
7224f1b2e48SStefano Zampini   has_null_pressures = PETSC_TRUE;
7234f1b2e48SStefano Zampini   have_null = PETSC_TRUE;
72440fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
7254f1b2e48SStefano Zampini     PetscInt npl,*idxs,p = pcbddc->n_ISForDofsLocal-1;
7264f1b2e48SStefano Zampini 
7274f1b2e48SStefano Zampini     /* Dofs splitting for BDDC cannot have PETSC_COMM_SELF, so create a sequential IS */
7284f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[p],&npl);CHKERRQ(ierr);
7294f1b2e48SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
7304f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,npl,idxs,PETSC_COPY_VALUES,&pressures);CHKERRQ(ierr);
731ba14f8e3SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
73240fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
73340fa8d13SStefano Zampini     if (!sorted) {
73440fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
73540fa8d13SStefano Zampini     }
73640fa8d13SStefano Zampini   } else {
73740fa8d13SStefano Zampini     pressures = NULL;
73840fa8d13SStefano Zampini   }
73997d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
74097d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
74127b6a85dSStefano Zampini   if (!n) pcbddc->benign_change_explicit = PETSC_TRUE;
74297d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
743339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
744339f8db1SStefano Zampini   if (!sorted) {
745339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
746339f8db1SStefano Zampini   }
747339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
7484f1b2e48SStefano Zampini   if (!nz) {
7494f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
7504f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
75140fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
75240fa8d13SStefano Zampini   }
7534f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
7544f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
7554f1b2e48SStefano Zampini   zerodiag_subs = NULL;
7564f1b2e48SStefano Zampini   pcbddc->benign_n = 0;
7571f4df5f7SStefano Zampini   n_interior_dofs = 0;
7581f4df5f7SStefano Zampini   interior_dofs = NULL;
7591f4df5f7SStefano Zampini   if (pcbddc->current_level) { /* need to compute interior nodes */
7601f4df5f7SStefano Zampini     PetscInt n,i,j;
7611f4df5f7SStefano Zampini     PetscInt n_neigh,*neigh,*n_shared,**shared;
7621f4df5f7SStefano Zampini     PetscInt *iwork;
7631f4df5f7SStefano Zampini 
7641f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(pc->pmat->rmap->mapping,&n);CHKERRQ(ierr);
7651f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
7661f4df5f7SStefano Zampini     ierr = PetscCalloc1(n,&iwork);CHKERRQ(ierr);
7671f4df5f7SStefano Zampini     ierr = PetscMalloc1(n,&interior_dofs);CHKERRQ(ierr);
7681f4df5f7SStefano Zampini     for (i=0;i<n_neigh;i++)
7691f4df5f7SStefano Zampini       for (j=0;j<n_shared[i];j++)
7701f4df5f7SStefano Zampini           iwork[shared[i][j]] += 1;
7711f4df5f7SStefano Zampini     for (i=0;i<n;i++)
7721f4df5f7SStefano Zampini       if (!iwork[i])
7731f4df5f7SStefano Zampini         interior_dofs[n_interior_dofs++] = i;
7741f4df5f7SStefano Zampini     ierr = PetscFree(iwork);CHKERRQ(ierr);
7751f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
7761f4df5f7SStefano Zampini   }
7774f1b2e48SStefano Zampini   if (has_null_pressures) {
7784f1b2e48SStefano Zampini     IS             *subs;
7791f4df5f7SStefano Zampini     PetscInt       nsubs,i,j,nl;
7801f4df5f7SStefano Zampini     const PetscInt *idxs;
7811f4df5f7SStefano Zampini     PetscScalar    *array;
7821f4df5f7SStefano Zampini     Vec            *work;
7831f4df5f7SStefano Zampini     Mat_IS*        matis = (Mat_IS*)(pc->pmat->data);
7844f1b2e48SStefano Zampini 
7854f1b2e48SStefano Zampini     subs = pcbddc->local_subs;
7864f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
7871f4df5f7SStefano Zampini     /* these vectors are needed to check if the constant on pressures is in the kernel of the local operator B (i.e. B(v_I,p0) should be zero) */
7881f4df5f7SStefano Zampini     if (pcbddc->current_level) {
7891f4df5f7SStefano Zampini       ierr = VecDuplicateVecs(matis->y,2,&work);CHKERRQ(ierr);
7901f4df5f7SStefano Zampini       ierr = ISGetLocalSize(zerodiag,&nl);CHKERRQ(ierr);
7911f4df5f7SStefano Zampini       ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
7921f4df5f7SStefano Zampini       /* work[0] = 1_p */
7931f4df5f7SStefano Zampini       ierr = VecSet(work[0],0.);CHKERRQ(ierr);
7941f4df5f7SStefano Zampini       ierr = VecGetArray(work[0],&array);CHKERRQ(ierr);
7951f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 1.;
7961f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[0],&array);CHKERRQ(ierr);
7971f4df5f7SStefano Zampini       /* work[0] = 1_v */
7981f4df5f7SStefano Zampini       ierr = VecSet(work[1],1.);CHKERRQ(ierr);
7991f4df5f7SStefano Zampini       ierr = VecGetArray(work[1],&array);CHKERRQ(ierr);
8001f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 0.;
8011f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[1],&array);CHKERRQ(ierr);
8021f4df5f7SStefano Zampini       ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
8031f4df5f7SStefano Zampini     }
8044f1b2e48SStefano Zampini     if (nsubs > 1) {
8054f1b2e48SStefano Zampini       ierr = PetscCalloc1(nsubs,&zerodiag_subs);CHKERRQ(ierr);
8064f1b2e48SStefano Zampini       for (i=0;i<nsubs;i++) {
8074f1b2e48SStefano Zampini         ISLocalToGlobalMapping l2g;
8084f1b2e48SStefano Zampini         IS                     t_zerodiag_subs;
8094f1b2e48SStefano Zampini         PetscInt               nl;
8104f1b2e48SStefano Zampini 
8114f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
8124f1b2e48SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,zerodiag,&t_zerodiag_subs);CHKERRQ(ierr);
8134f1b2e48SStefano Zampini         ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
8144f1b2e48SStefano Zampini         if (nl) {
8154f1b2e48SStefano Zampini           PetscBool valid = PETSC_TRUE;
8164f1b2e48SStefano Zampini 
8171f4df5f7SStefano Zampini           if (pcbddc->current_level) {
8181f4df5f7SStefano Zampini             ierr = VecSet(matis->x,0);CHKERRQ(ierr);
8191f4df5f7SStefano Zampini             ierr = ISGetLocalSize(subs[i],&nl);CHKERRQ(ierr);
8201f4df5f7SStefano Zampini             ierr = ISGetIndices(subs[i],&idxs);CHKERRQ(ierr);
8211f4df5f7SStefano Zampini             ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
8221f4df5f7SStefano Zampini             for (j=0;j<nl;j++) array[idxs[j]] = 1.;
8231f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
8241f4df5f7SStefano Zampini             ierr = ISRestoreIndices(subs[i],&idxs);CHKERRQ(ierr);
8251f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->x,work[0],matis->x);CHKERRQ(ierr);
8261f4df5f7SStefano Zampini             ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
8271f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->y,work[1],matis->y);CHKERRQ(ierr);
8281f4df5f7SStefano Zampini             ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
8291f4df5f7SStefano Zampini             for (j=0;j<n_interior_dofs;j++) {
8301f4df5f7SStefano Zampini               if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
8311f4df5f7SStefano Zampini                 valid = PETSC_FALSE;
8321f4df5f7SStefano Zampini                 break;
8331f4df5f7SStefano Zampini               }
8341f4df5f7SStefano Zampini             }
8351f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
8361f4df5f7SStefano Zampini           }
8371f4df5f7SStefano Zampini           if (valid && pcbddc->NeumannBoundariesLocal) {
8381f4df5f7SStefano Zampini             IS       t_bc;
8391f4df5f7SStefano Zampini             PetscInt nzb;
8401f4df5f7SStefano Zampini 
8411f4df5f7SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pcbddc->NeumannBoundariesLocal,&t_bc);CHKERRQ(ierr);
8421f4df5f7SStefano Zampini             ierr = ISGetLocalSize(t_bc,&nzb);CHKERRQ(ierr);
8431f4df5f7SStefano Zampini             ierr = ISDestroy(&t_bc);CHKERRQ(ierr);
8441f4df5f7SStefano Zampini             if (nzb) valid = PETSC_FALSE;
8451f4df5f7SStefano Zampini           }
8461f4df5f7SStefano Zampini           if (valid && pressures) {
8474f1b2e48SStefano Zampini             IS t_pressure_subs;
8484f1b2e48SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
8494f1b2e48SStefano Zampini             ierr = ISEqual(t_pressure_subs,t_zerodiag_subs,&valid);CHKERRQ(ierr);
8504f1b2e48SStefano Zampini             ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
8514f1b2e48SStefano Zampini           }
8524f1b2e48SStefano Zampini           if (valid) {
8534f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[pcbddc->benign_n]);CHKERRQ(ierr);
8544f1b2e48SStefano Zampini             pcbddc->benign_n++;
8554f1b2e48SStefano Zampini           } else {
8564f1b2e48SStefano Zampini             recompute_zerodiag = PETSC_TRUE;
8574f1b2e48SStefano Zampini           }
8584f1b2e48SStefano Zampini         }
8594f1b2e48SStefano Zampini         ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
8604f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
8614f1b2e48SStefano Zampini       }
8624f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
8634f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
8641f4df5f7SStefano Zampini 
8651f4df5f7SStefano Zampini       if (pcbddc->NeumannBoundariesLocal) {
8661f4df5f7SStefano Zampini         PetscInt nzb;
8671f4df5f7SStefano Zampini         ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nzb);CHKERRQ(ierr);
8681f4df5f7SStefano Zampini         if (nzb) valid = PETSC_FALSE;
8691f4df5f7SStefano Zampini       }
8701f4df5f7SStefano Zampini       if (valid && pressures) {
8714f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
8724f1b2e48SStefano Zampini       }
8731f4df5f7SStefano Zampini       if (valid && pcbddc->current_level) {
8741f4df5f7SStefano Zampini         ierr = MatMult(matis->A,work[0],matis->x);CHKERRQ(ierr);
8751f4df5f7SStefano Zampini         ierr = VecPointwiseMult(matis->x,work[1],matis->x);CHKERRQ(ierr);
8761f4df5f7SStefano Zampini         ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
8771f4df5f7SStefano Zampini         for (j=0;j<n_interior_dofs;j++) {
8781f4df5f7SStefano Zampini             if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
8791f4df5f7SStefano Zampini               valid = PETSC_FALSE;
8801f4df5f7SStefano Zampini               break;
8811f4df5f7SStefano Zampini           }
8821f4df5f7SStefano Zampini         }
8831f4df5f7SStefano Zampini         ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
8841f4df5f7SStefano Zampini       }
8854f1b2e48SStefano Zampini       if (valid) {
8864f1b2e48SStefano Zampini         pcbddc->benign_n = 1;
887ca92afb2SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&zerodiag_subs);CHKERRQ(ierr);
8884f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
8894f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
8904f1b2e48SStefano Zampini       }
8914f1b2e48SStefano Zampini     }
8921f4df5f7SStefano Zampini     if (pcbddc->current_level) {
8931f4df5f7SStefano Zampini       ierr = VecDestroyVecs(2,&work);CHKERRQ(ierr);
8944f1b2e48SStefano Zampini     }
8951f4df5f7SStefano Zampini   }
8961f4df5f7SStefano Zampini   ierr = PetscFree(interior_dofs);CHKERRQ(ierr);
8974f1b2e48SStefano Zampini 
8984f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
899b9b0e38cSStefano Zampini     PetscInt n;
900b9b0e38cSStefano Zampini 
9014f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
9024f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
903b9b0e38cSStefano Zampini     ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
904b9b0e38cSStefano Zampini     if (n) {
9054f1b2e48SStefano Zampini       has_null_pressures = PETSC_FALSE;
9064f1b2e48SStefano Zampini       have_null = PETSC_FALSE;
9074f1b2e48SStefano Zampini     }
908b9b0e38cSStefano Zampini   }
9094f1b2e48SStefano Zampini 
9104f1b2e48SStefano Zampini   /* final check for null pressures */
9114f1b2e48SStefano Zampini   if (zerodiag && pressures) {
9124f1b2e48SStefano Zampini     PetscInt nz,np;
9134f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
9144f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
9154f1b2e48SStefano Zampini     if (nz != np) have_null = PETSC_FALSE;
9164f1b2e48SStefano Zampini   }
9174f1b2e48SStefano Zampini 
9184f1b2e48SStefano Zampini   if (recompute_zerodiag) {
9194f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
9204f1b2e48SStefano Zampini     if (pcbddc->benign_n == 1) {
9214f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
9224f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
9234f1b2e48SStefano Zampini     } else {
9244f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
9254f1b2e48SStefano Zampini 
9264f1b2e48SStefano Zampini       nzn = 0;
9274f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
9284f1b2e48SStefano Zampini         PetscInt ns;
9294f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
9304f1b2e48SStefano Zampini         nzn += ns;
9314f1b2e48SStefano Zampini       }
9324f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
9334f1b2e48SStefano Zampini       nzn = 0;
9344f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
9354f1b2e48SStefano Zampini         PetscInt ns,*idxs;
9364f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
9374f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
9384f1b2e48SStefano Zampini         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
9394f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
9404f1b2e48SStefano Zampini         nzn += ns;
9414f1b2e48SStefano Zampini       }
9424f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
9434f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
9444f1b2e48SStefano Zampini     }
9454f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
9464f1b2e48SStefano Zampini   }
9474f1b2e48SStefano Zampini 
948669cc0f4SStefano Zampini   /* Prepare matrix to compute no-net-flux */
949*a198735bSStefano Zampini   if (pcbddc->compute_nonetflux && !pcbddc->divudotp) {
950*a198735bSStefano Zampini     Mat                    A,loc_divudotp;
951*a198735bSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g,l2gmap;
952*a198735bSStefano Zampini     IS                     row,col,isused = NULL;
953*a198735bSStefano Zampini     PetscInt               M,N,n,st,n_isused;
954*a198735bSStefano Zampini 
9551f4df5f7SStefano Zampini     if (pressures) {
9561f4df5f7SStefano Zampini       isused = pressures;
9571f4df5f7SStefano Zampini     } else {
9581f4df5f7SStefano Zampini       isused = zerodiag;
9591f4df5f7SStefano Zampini     }
960*a198735bSStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&l2gmap,NULL);CHKERRQ(ierr);
961669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
9621ae86dd6SStefano Zampini     ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
9631ae86dd6SStefano Zampini     if (!isused && n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Don't know how to extract div u dot p! Please provide the pressure field");
964*a198735bSStefano Zampini     n_isused = 0;
965*a198735bSStefano Zampini     if (isused) {
966*a198735bSStefano Zampini       ierr = ISGetLocalSize(isused,&n_isused);CHKERRQ(ierr);
967*a198735bSStefano Zampini     }
968*a198735bSStefano Zampini     ierr = MPI_Scan(&n_isused,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
969*a198735bSStefano Zampini     st = st-n_isused;
9701ae86dd6SStefano Zampini     if (n) {
971*a198735bSStefano Zampini       const PetscInt *gidxs;
972*a198735bSStefano Zampini 
973*a198735bSStefano Zampini       ierr = MatGetSubMatrix(A,isused,NULL,MAT_INITIAL_MATRIX,&loc_divudotp);CHKERRQ(ierr);
974*a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
975*a198735bSStefano Zampini       /* TODO: extend ISCreateStride with st = PETSC_DECIDE */
976*a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
977*a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
978*a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
9791ae86dd6SStefano Zampini     } else {
980*a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&loc_divudotp);CHKERRQ(ierr);
981*a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
982*a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),0,NULL,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
983*a198735bSStefano Zampini     }
984*a198735bSStefano Zampini     ierr = MatGetSize(pc->pmat,NULL,&N);CHKERRQ(ierr);
985*a198735bSStefano Zampini     ierr = ISGetSize(row,&M);CHKERRQ(ierr);
986*a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
987*a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
988*a198735bSStefano Zampini     ierr = ISDestroy(&row);CHKERRQ(ierr);
989*a198735bSStefano Zampini     ierr = ISDestroy(&col);CHKERRQ(ierr);
990*a198735bSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->divudotp);CHKERRQ(ierr);
991*a198735bSStefano Zampini     ierr = MatSetType(pcbddc->divudotp,MATIS);CHKERRQ(ierr);
992*a198735bSStefano Zampini     ierr = MatSetSizes(pcbddc->divudotp,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
993*a198735bSStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->divudotp,rl2g,cl2g);CHKERRQ(ierr);
994*a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
995*a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
996*a198735bSStefano Zampini     ierr = MatISSetLocalMat(pcbddc->divudotp,loc_divudotp);CHKERRQ(ierr);
997*a198735bSStefano Zampini     ierr = MatDestroy(&loc_divudotp);CHKERRQ(ierr);
9981ae86dd6SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9991ae86dd6SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10001ae86dd6SStefano Zampini   }
1001b3afcdbeSStefano Zampini 
1002b3afcdbeSStefano Zampini   /* change of basis and p0 dofs */
10034f1b2e48SStefano Zampini   if (has_null_pressures) {
10044f1b2e48SStefano Zampini     IS             zerodiagc;
10054f1b2e48SStefano Zampini     const PetscInt *idxs,*idxsc;
10064f1b2e48SStefano Zampini     PetscInt       i,s,*nnz;
10074f1b2e48SStefano Zampini 
10084f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
1009339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
1010339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
1011339f8db1SStefano Zampini     /* local change of basis for pressures */
1012339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
101397d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
1014339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
1015339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1016339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
10174f1b2e48SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities plus pressure dofs for non-singular subdomains */
10184f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
10194f1b2e48SStefano Zampini       PetscInt nzs,j;
10204f1b2e48SStefano Zampini 
10214f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[i],&nzs);CHKERRQ(ierr);
10224f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
10234f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
10244f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
10254f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
10264f1b2e48SStefano Zampini     }
1027339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
1028339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
1029339f8db1SStefano Zampini     /* set identity on velocities */
1030339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
1031339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
1032339f8db1SStefano Zampini     }
10334f1b2e48SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
10344f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
10359f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
10364f1b2e48SStefano 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);
1037339f8db1SStefano Zampini     /* set change on pressures */
10384f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
10394f1b2e48SStefano Zampini       PetscScalar *array;
10404f1b2e48SStefano Zampini       PetscInt    nzs;
10414f1b2e48SStefano Zampini 
10424f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[s],&nzs);CHKERRQ(ierr);
10434f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
10444f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
1045339f8db1SStefano Zampini         PetscScalar vals[2];
1046339f8db1SStefano Zampini         PetscInt    cols[2];
1047339f8db1SStefano Zampini 
1048339f8db1SStefano Zampini         cols[0] = idxs[i];
10494f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
1050339f8db1SStefano Zampini         vals[0] = 1.;
1051b0f5fe93SStefano Zampini         vals[1] = 1.;
10524f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
1053339f8db1SStefano Zampini       }
10544f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
10554f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
10564f1b2e48SStefano Zampini       array[nzs-1] = 1.;
10574f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
10584f1b2e48SStefano Zampini       /* store local idxs for p0 */
10594f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
10604f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
1061339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
10624f1b2e48SStefano Zampini     }
1063339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1064339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1065a3df083aSStefano Zampini     /* project if needed */
1066a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
10671dd7afcfSStefano Zampini       Mat M;
10681dd7afcfSStefano Zampini 
10691dd7afcfSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
1070339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
10711dd7afcfSStefano Zampini       ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
10721dd7afcfSStefano Zampini       ierr = MatDestroy(&M);CHKERRQ(ierr);
1073a3df083aSStefano Zampini     }
10744f1b2e48SStefano Zampini     /* store global idxs for p0 */
10754f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
1076339f8db1SStefano Zampini   }
1077ca92afb2SStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
10784f1b2e48SStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
1079b0f5fe93SStefano Zampini 
1080b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
1081b0f5fe93SStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
108227b6a85dSStefano Zampini   /* determines if the problem has subdomains with 0 pressure block */
108327b6a85dSStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1084339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
1085339f8db1SStefano Zampini   PetscFunctionReturn(0);
1086339f8db1SStefano Zampini }
1087339f8db1SStefano Zampini 
1088339f8db1SStefano Zampini #undef __FUNCT__
1089015636ebSStefano Zampini #define __FUNCT__ "PCBDDCBenignGetOrSetP0"
1090015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
1091efc2fbd9SStefano Zampini {
1092efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
1093de9d7bd0SStefano Zampini   PetscScalar    *array;
1094efc2fbd9SStefano Zampini   PetscErrorCode ierr;
1095efc2fbd9SStefano Zampini 
1096efc2fbd9SStefano Zampini   PetscFunctionBegin;
1097efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
1098efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
10994f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
1100efc2fbd9SStefano Zampini   }
1101de9d7bd0SStefano Zampini   if (get) {
1102efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
11034f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
11044f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
1105efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
1106de9d7bd0SStefano Zampini   } else {
1107de9d7bd0SStefano Zampini     ierr = VecGetArray(v,&array);CHKERRQ(ierr);
1108de9d7bd0SStefano Zampini     ierr = PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
1109de9d7bd0SStefano Zampini     ierr = PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
1110de9d7bd0SStefano Zampini     ierr = VecRestoreArray(v,&array);CHKERRQ(ierr);
1111efc2fbd9SStefano Zampini   }
1112efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
1113efc2fbd9SStefano Zampini }
1114efc2fbd9SStefano Zampini 
1115efc2fbd9SStefano Zampini #undef __FUNCT__
1116c263805aSStefano Zampini #define __FUNCT__ "PCBDDCBenignPopOrPushB0"
1117c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
1118c263805aSStefano Zampini {
1119c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
1120c263805aSStefano Zampini   PetscErrorCode ierr;
1121c263805aSStefano Zampini 
1122c263805aSStefano Zampini   PetscFunctionBegin;
1123c263805aSStefano Zampini   /* TODO: add error checking
1124c263805aSStefano Zampini     - avoid nested pop (or push) calls.
1125c263805aSStefano Zampini     - cannot push before pop.
11261c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
1127c263805aSStefano Zampini   */
11284f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
1129efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
1130efc2fbd9SStefano Zampini   }
1131c263805aSStefano Zampini   if (pop) {
1132a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
11334f1b2e48SStefano Zampini       IS       is_p0;
11344f1b2e48SStefano Zampini       MatReuse reuse;
1135c263805aSStefano Zampini 
1136c263805aSStefano Zampini       /* extract B_0 */
11374f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
11384f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
11394f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
11404f1b2e48SStefano Zampini       }
11414f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
11424f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
1143c263805aSStefano Zampini       /* remove rows and cols from local problem */
1144c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
114597d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
11464f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
11474f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
1148a3df083aSStefano Zampini     } else {
1149a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
1150a3df083aSStefano Zampini       PetscScalar *vals;
1151a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
1152a3df083aSStefano Zampini 
1153a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
1154a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
1155a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
11560b5adadeSStefano Zampini         PetscInt *nnz;
1157a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
1158a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
1159a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1160331e053bSStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&nnz);CHKERRQ(ierr);
1161331e053bSStefano Zampini         for (i=0;i<pcbddc->benign_n;i++) {
1162331e053bSStefano Zampini           ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i]);CHKERRQ(ierr);
1163331e053bSStefano Zampini           nnz[i] = n - nnz[i];
1164331e053bSStefano Zampini         }
1165331e053bSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz);CHKERRQ(ierr);
1166331e053bSStefano Zampini         ierr = PetscFree(nnz);CHKERRQ(ierr);
1167331e053bSStefano Zampini       }
1168a3df083aSStefano Zampini 
1169a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
1170a3df083aSStefano Zampini         PetscScalar *array;
1171a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
1172a3df083aSStefano Zampini 
1173a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
1174a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1175a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
1176a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
1177a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1178a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
1179a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
1180a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
1181a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
1182a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
1183a3df083aSStefano Zampini         cum = 0;
1184a3df083aSStefano Zampini         for (j=0;j<n;j++) {
118522db5ddcSStefano Zampini           if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) {
1186a3df083aSStefano Zampini             vals[cum] = array[j];
1187a3df083aSStefano Zampini             idxs_ins[cum] = j;
1188a3df083aSStefano Zampini             cum++;
1189a3df083aSStefano Zampini           }
1190a3df083aSStefano Zampini         }
1191a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
1192a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
1193a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
1194a3df083aSStefano Zampini       }
1195a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1196a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1197a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
1198a3df083aSStefano Zampini     }
1199c263805aSStefano Zampini   } else { /* push */
1200a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
12014f1b2e48SStefano Zampini       PetscInt i;
12024f1b2e48SStefano Zampini 
12034f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
12044f1b2e48SStefano Zampini         PetscScalar *B0_vals;
12054f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
12064f1b2e48SStefano Zampini 
12074f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
12084f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
12097b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
12104f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
12114f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
12124f1b2e48SStefano Zampini       }
1213c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1214c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1215a3df083aSStefano Zampini     } else {
1216a3df083aSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!\n");
1217a3df083aSStefano Zampini     }
1218c263805aSStefano Zampini   }
1219c263805aSStefano Zampini   PetscFunctionReturn(0);
1220c263805aSStefano Zampini }
1221c263805aSStefano Zampini 
1222c263805aSStefano Zampini #undef __FUNCT__
1223b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
122408122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
1225b1b3d7a2SStefano Zampini {
1226b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
122708122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
122808122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
122908122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
123008122e43SStefano Zampini   PetscScalar     *work,lwork;
123108122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
123208122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
123308122e43SStefano Zampini   PetscReal       *eigs,thresh;
12341b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
1235f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
123608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
123708122e43SStefano Zampini   PetscReal       *rwork;
123808122e43SStefano Zampini #endif
1239b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
1240b1b3d7a2SStefano Zampini 
1241b1b3d7a2SStefano Zampini   PetscFunctionBegin;
1242b334f244SStefano Zampini   if (!sub_schurs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Adaptive selection of constraints requires SubSchurs data");
1243af25d912SStefano Zampini   if (!sub_schurs->schur_explicit) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
1244af25d912SStefano Zampini   if (sub_schurs->n_subs && (!sub_schurs->is_hermitian || !sub_schurs->is_posdef)) 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);
124506a4e24aSStefano Zampini 
1246fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
1247fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1248fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1249fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
12501575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
1251fd14bc51SStefano Zampini   }
1252fd14bc51SStefano Zampini 
1253e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
1254e496cd5dSStefano 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);
1255e496cd5dSStefano Zampini   }
1256e496cd5dSStefano Zampini 
125708122e43SStefano Zampini   /* max size of subsets */
125808122e43SStefano Zampini   mss = 0;
125908122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
126008122e43SStefano Zampini     PetscInt subset_size;
1261862806e4SStefano Zampini 
126208122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
126308122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
126408122e43SStefano Zampini   }
126508122e43SStefano Zampini 
126608122e43SStefano Zampini   /* min/max and threshold */
126708122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
1268f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
126908122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
1270f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
1271f6f667cfSStefano Zampini   if (nmin) {
1272f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
1273f6f667cfSStefano Zampini   }
127408122e43SStefano Zampini 
127508122e43SStefano Zampini   /* allocate lapack workspace */
127608122e43SStefano Zampini   cum = cum2 = 0;
127708122e43SStefano Zampini   maxneigs = 0;
127808122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
127908122e43SStefano Zampini     PetscInt n,subset_size;
1280f6f667cfSStefano Zampini 
128108122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
128208122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
12839162d606SStefano Zampini     cum += subset_size;
12849162d606SStefano Zampini     cum2 += subset_size*n;
128508122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
128608122e43SStefano Zampini   }
128708122e43SStefano Zampini   if (mss) {
12889ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
128908122e43SStefano Zampini       PetscBLASInt B_itype = 1;
129008122e43SStefano Zampini       PetscBLASInt B_N = mss;
12914c6709b3SStefano Zampini       PetscReal    zero = 0.0;
12924c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
129308122e43SStefano Zampini 
129408122e43SStefano Zampini       B_lwork = -1;
129508122e43SStefano Zampini       S = NULL;
129608122e43SStefano Zampini       St = NULL;
1297a58a30b4SStefano Zampini       eigs = NULL;
1298a58a30b4SStefano Zampini       eigv = NULL;
1299a58a30b4SStefano Zampini       B_iwork = NULL;
1300a58a30b4SStefano Zampini       B_ifail = NULL;
1301d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1302d1710679SStefano Zampini       rwork = NULL;
1303d1710679SStefano Zampini #endif
13048bec7fa6SStefano Zampini       thresh = 1.0;
130508122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
130608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
130708122e43SStefano 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));
130808122e43SStefano Zampini #else
130908122e43SStefano 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));
131008122e43SStefano Zampini #endif
131108122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
131208122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
131308122e43SStefano Zampini     } else {
131408122e43SStefano Zampini         /* TODO */
131508122e43SStefano Zampini     }
131608122e43SStefano Zampini   } else {
131708122e43SStefano Zampini     lwork = 0;
131808122e43SStefano Zampini   }
131908122e43SStefano Zampini 
132008122e43SStefano Zampini   nv = 0;
1321d62866d3SStefano 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) */
1322d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
132308122e43SStefano Zampini   }
13244c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
1325f6f667cfSStefano Zampini   if (allocated_S_St) {
1326f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
1327f6f667cfSStefano Zampini   }
1328f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
132908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
133008122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
133108122e43SStefano Zampini #endif
13329162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
13339162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
13349162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
133508122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
13369162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
133708122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
133808122e43SStefano Zampini 
133908122e43SStefano Zampini   maxneigs = 0;
134072b8c272SStefano Zampini   cum = cumarray = 0;
13419162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
13429162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
1343d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
134408122e43SStefano Zampini     const PetscInt *idxs;
134508122e43SStefano Zampini 
1346d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
134708122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
134808122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
134908122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
135008122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
13519162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
13529162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
135308122e43SStefano Zampini     }
1354d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
135508122e43SStefano Zampini   }
135608122e43SStefano Zampini 
135708122e43SStefano Zampini   if (mss) { /* multilevel */
135808122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
135908122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
136008122e43SStefano Zampini   }
136108122e43SStefano Zampini 
1362ffd830a3SStefano Zampini   thresh = pcbddc->adaptive_threshold;
136308122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
136408122e43SStefano Zampini     const PetscInt *idxs;
13659d54b7f4SStefano Zampini     PetscReal      upper,lower;
1366862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
136708122e43SStefano Zampini     PetscBLASInt   B_N;
1368aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
136908122e43SStefano Zampini 
13709d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
13719d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
13729d54b7f4SStefano Zampini       lower = thresh;
13739d54b7f4SStefano Zampini     } else {
13749d54b7f4SStefano Zampini       upper = 1./thresh;
13759d54b7f4SStefano Zampini       lower = 0.;
13769d54b7f4SStefano Zampini     }
1377862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
1378ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
1379f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
1380f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
13819ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
1382aff50787SStefano Zampini         PetscInt j,k;
1383aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
1384aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
1385aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
138608122e43SStefano Zampini         }
138708122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
1388aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
1389aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
1390aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
1391aff50787SStefano Zampini           }
139208122e43SStefano Zampini         }
139308122e43SStefano Zampini       } else {
139408122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
139508122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
139608122e43SStefano Zampini       }
13978bec7fa6SStefano Zampini     } else {
1398f6f667cfSStefano Zampini       S = Sarray + cumarray;
1399f6f667cfSStefano Zampini       St = Starray + cumarray;
14008bec7fa6SStefano Zampini     }
1401aff50787SStefano Zampini     /* see if we can save some work */
1402b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
1403aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
1404aff50787SStefano Zampini     }
1405aff50787SStefano Zampini 
1406b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
1407aff50787SStefano Zampini       B_neigs = 0;
1408aff50787SStefano Zampini     } else {
14099ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
141008122e43SStefano Zampini         PetscBLASInt B_itype = 1;
1411f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
14124c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
14139552c7c7SStefano Zampini         PetscInt     nmin_s;
1414b7ab4a40SStefano Zampini         PetscBool    compute_range = PETSC_FALSE;
141508122e43SStefano Zampini 
1416fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
14178bec7fa6SStefano 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]]);
1418fd14bc51SStefano Zampini         }
1419d16cbb6bSStefano Zampini 
1420b7ab4a40SStefano Zampini         compute_range = PETSC_FALSE;
1421b7ab4a40SStefano Zampini         if (thresh > 1.+PETSC_SMALL && !same_data) {
1422b7ab4a40SStefano Zampini           compute_range = PETSC_TRUE;
1423b7ab4a40SStefano Zampini         }
1424b7ab4a40SStefano Zampini 
142508122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1426b7ab4a40SStefano Zampini         if (compute_range) {
1427d16cbb6bSStefano Zampini 
1428d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
142908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
14309d54b7f4SStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
143108122e43SStefano Zampini #else
14329d54b7f4SStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","V","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
143308122e43SStefano Zampini #endif
1434b7ab4a40SStefano Zampini         } else if (!same_data) {
1435d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
1436d16cbb6bSStefano Zampini           B_IL = 1;
1437d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
14389d54b7f4SStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,rwork,B_iwork,B_ifail,&B_ierr));
1439d16cbb6bSStefano Zampini #else
14409d54b7f4SStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&B_IL,&B_IU,&eps,&B_neigs,eigs,eigv,&B_N,work,&B_lwork,B_iwork,B_ifail,&B_ierr));
1441d16cbb6bSStefano Zampini #endif
1442b7ab4a40SStefano Zampini         } else { /* same_data is true, so get the adaptive function requested by the user */
1443b7ab4a40SStefano Zampini           PetscInt k;
1444b7ab4a40SStefano Zampini           if (!sub_schurs->change_primal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
1445b7ab4a40SStefano Zampini           ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax);CHKERRQ(ierr);
1446b7ab4a40SStefano Zampini           ierr = PetscBLASIntCast(nmax,&B_neigs);CHKERRQ(ierr);
1447b7ab4a40SStefano Zampini           nmin = nmax;
1448b7ab4a40SStefano Zampini           ierr = PetscMemzero(eigv,subset_size*nmax*sizeof(PetscScalar));CHKERRQ(ierr);
1449b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
1450b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
1451b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
1452b7ab4a40SStefano Zampini           }
1453d16cbb6bSStefano Zampini         }
145408122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
145508122e43SStefano Zampini         if (B_ierr) {
14566c4ed002SBarry Smith           if (B_ierr < 0 ) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
14576c4ed002SBarry Smith           else if (B_ierr <= B_N) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
14586c4ed002SBarry Smith           else 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);
145908122e43SStefano Zampini         }
146008122e43SStefano Zampini 
146108122e43SStefano Zampini         if (B_neigs > nmax) {
1462fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
1463fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
1464fd14bc51SStefano Zampini           }
14659d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) eigs_start = B_neigs -nmax;
146608122e43SStefano Zampini           B_neigs = nmax;
146708122e43SStefano Zampini         }
146808122e43SStefano Zampini 
14699552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
14709552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
147108122e43SStefano Zampini           PetscBLASInt B_neigs2;
147208122e43SStefano Zampini 
14739d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) {
1474f6f667cfSStefano Zampini             B_IL = B_N - nmin_s + 1;
14759d54b7f4SStefano Zampini             B_IU = B_N - B_neigs;
14769d54b7f4SStefano Zampini           } else {
14779d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
14789d54b7f4SStefano Zampini             B_IU = nmin_s;
14799d54b7f4SStefano Zampini           }
1480fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
1481fd14bc51SStefano 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);
1482fd14bc51SStefano Zampini           }
14839ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
14841ae86dd6SStefano Zampini             PetscInt j,k;
148508122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
14861ae86dd6SStefano Zampini               for (k=j;k<subset_size;k++) {
14871ae86dd6SStefano Zampini                 S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
14881ae86dd6SStefano Zampini                 St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
148908122e43SStefano Zampini               }
149008122e43SStefano Zampini             }
149108122e43SStefano Zampini           } else {
149208122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
149308122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
149408122e43SStefano Zampini           }
149508122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
149608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
14979d54b7f4SStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&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));
149808122e43SStefano Zampini #else
14999d54b7f4SStefano Zampini           PetscStackCallBLAS("LAPACKsygvx",LAPACKsygvx_(&B_itype,"V","I","L",&B_N,St,&B_N,S,&B_N,&lower,&upper,&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));
150008122e43SStefano Zampini #endif
150108122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
150208122e43SStefano Zampini           B_neigs += B_neigs2;
150308122e43SStefano Zampini         }
150408122e43SStefano Zampini         if (B_ierr) {
15056c4ed002SBarry Smith           if (B_ierr < 0 ) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: illegal value for argument %d",-(int)B_ierr);
15066c4ed002SBarry Smith           else if (B_ierr <= B_N) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYGVX Lapack routine: %d eigenvalues failed to converge",(int)B_ierr);
15076c4ed002SBarry Smith           else 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);
150808122e43SStefano Zampini         }
1509fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
1510ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
151108122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
151208122e43SStefano Zampini             if (eigs[j] == 0.0) {
1513ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
151408122e43SStefano Zampini             } else {
15159d54b7f4SStefano Zampini               if (pcbddc->use_deluxe_scaling) {
1516ac47001eSStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
15179d54b7f4SStefano Zampini               } else {
15189d54b7f4SStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",1./eigs[j+eigs_start]);CHKERRQ(ierr);
15199d54b7f4SStefano Zampini               }
1520fd14bc51SStefano Zampini             }
152108122e43SStefano Zampini           }
152208122e43SStefano Zampini         }
152308122e43SStefano Zampini       } else {
152408122e43SStefano Zampini           /* TODO */
152508122e43SStefano Zampini       }
1526aff50787SStefano Zampini     }
15276c3e6151SStefano Zampini     /* change the basis back to the original one */
15286c3e6151SStefano Zampini     if (sub_schurs->change) {
152972b8c272SStefano Zampini       Mat change,phi,phit;
15306c3e6151SStefano Zampini 
15316c3e6151SStefano Zampini       if (pcbddc->dbg_flag > 1) {
15326c3e6151SStefano Zampini         PetscInt ii;
15336c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
15346c3e6151SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
15356c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
15366c3e6151SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",eigv[(ii+eigs_start)*subset_size+j]);CHKERRQ(ierr);
15376c3e6151SStefano Zampini           }
15386c3e6151SStefano Zampini         }
15396c3e6151SStefano Zampini       }
154072b8c272SStefano Zampini       ierr = KSPGetOperators(sub_schurs->change[i],&change,NULL);CHKERRQ(ierr);
15416c3e6151SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit);CHKERRQ(ierr);
154272b8c272SStefano Zampini       ierr = MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi);CHKERRQ(ierr);
15436c3e6151SStefano Zampini       ierr = MatCopy(phi,phit,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
15446c3e6151SStefano Zampini       ierr = MatDestroy(&phit);CHKERRQ(ierr);
15456c3e6151SStefano Zampini       ierr = MatDestroy(&phi);CHKERRQ(ierr);
15466c3e6151SStefano Zampini     }
15478bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
15488bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
15499162d606SStefano Zampini     if (B_neigs) {
15509162d606SStefano 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);
1551fd14bc51SStefano Zampini 
1552fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
15539552c7c7SStefano Zampini         PetscInt ii;
15549552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
1555ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
15569552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
1557ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
1558ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
1559ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
1560ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
1561ac47001eSStefano Zampini #else
1562ac47001eSStefano 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);
1563ac47001eSStefano Zampini #endif
15649552c7c7SStefano Zampini           }
15659552c7c7SStefano Zampini         }
1566fd14bc51SStefano Zampini       }
15679162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
15689162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
15699162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
15709162d606SStefano Zampini       cum++;
157108122e43SStefano Zampini     }
157208122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
157308122e43SStefano Zampini     /* shift for next computation */
157408122e43SStefano Zampini     cumarray += subset_size*subset_size;
157508122e43SStefano Zampini   }
1576fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
1577fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1578fd14bc51SStefano Zampini   }
157908122e43SStefano Zampini 
158008122e43SStefano Zampini   if (mss) {
158108122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
158208122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
1583f6f667cfSStefano Zampini     /* destroy matrices (junk) */
1584f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
1585f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
158608122e43SStefano Zampini   }
1587f6f667cfSStefano Zampini   if (allocated_S_St) {
1588f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
1589f6f667cfSStefano Zampini   }
1590f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
159108122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
159208122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
159308122e43SStefano Zampini #endif
159408122e43SStefano Zampini   if (pcbddc->dbg_flag) {
15951b968477SStefano Zampini     PetscInt maxneigs_r;
1596b2566f29SBarry Smith     ierr = MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
15979b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
159808122e43SStefano Zampini   }
159908122e43SStefano Zampini   PetscFunctionReturn(0);
160008122e43SStefano Zampini }
1601b1b3d7a2SStefano Zampini 
1602674ae819SStefano Zampini #undef __FUNCT__
1603c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
1604c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
1605c8587f34SStefano Zampini {
16068629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
1607c8587f34SStefano Zampini   PetscErrorCode ierr;
1608c8587f34SStefano Zampini 
1609c8587f34SStefano Zampini   PetscFunctionBegin;
1610f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
16115e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
1612c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
1613c8587f34SStefano Zampini 
1614684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
16150fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
1616684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
1617c8587f34SStefano Zampini 
16188629588bSStefano Zampini   /*
16198629588bSStefano Zampini      Setup local correction and local part of coarse basis.
16208629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
16218629588bSStefano Zampini   */
162247f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
16238629588bSStefano Zampini 
16248629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
16258629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
16268629588bSStefano Zampini 
16278629588bSStefano Zampini   /* free */
16288629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
1629c8587f34SStefano Zampini   PetscFunctionReturn(0);
1630c8587f34SStefano Zampini }
1631c8587f34SStefano Zampini 
1632c8587f34SStefano Zampini #undef __FUNCT__
1633674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
1634674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
1635674ae819SStefano Zampini {
1636674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1637674ae819SStefano Zampini   PetscErrorCode ierr;
1638674ae819SStefano Zampini 
1639674ae819SStefano Zampini   PetscFunctionBegin;
1640674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
1641674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
164230368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
1643674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
1644785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
1645674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
1646f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
1647f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
1648785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
164963602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
165063602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
1651674ae819SStefano Zampini   PetscFunctionReturn(0);
1652674ae819SStefano Zampini }
1653674ae819SStefano Zampini 
1654674ae819SStefano Zampini #undef __FUNCT__
1655674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
1656674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
1657674ae819SStefano Zampini {
1658674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
16594f1b2e48SStefano Zampini   PetscInt       i;
1660674ae819SStefano Zampini   PetscErrorCode ierr;
1661674ae819SStefano Zampini 
1662674ae819SStefano Zampini   PetscFunctionBegin;
1663b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
1664674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
166516909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
16661dd7afcfSStefano Zampini   ierr = VecDestroy(&pcbddc->work_change);CHKERRQ(ierr);
1667674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
1668669cc0f4SStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
1669*a198735bSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
1670674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
16714f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
16724f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
16734f1b2e48SStefano Zampini   }
16744f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
1675b334f244SStefano Zampini   if (pcbddc->sub_schurs) {
1676b96c3477SStefano Zampini     ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
1677b334f244SStefano Zampini   }
1678674ae819SStefano Zampini   PetscFunctionReturn(0);
1679674ae819SStefano Zampini }
1680674ae819SStefano Zampini 
1681674ae819SStefano Zampini #undef __FUNCT__
1682674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
1683674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
1684674ae819SStefano Zampini {
1685674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1686674ae819SStefano Zampini   PetscErrorCode ierr;
1687674ae819SStefano Zampini 
1688674ae819SStefano Zampini   PetscFunctionBegin;
1689674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
169058da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
1691ca92afb2SStefano Zampini     PetscScalar *array;
169206656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
169306656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
169458da7f69SStefano Zampini   }
1695674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1696674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
169715aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
169815aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
1699674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
1700674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
1701674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
170206656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
1703674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
1704674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
17058ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
1706674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
1707674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
1708674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
1709f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
1710f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
1711f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
1712f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
1713727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
17140e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
1715f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
171670cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
171781d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
17180369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
17191dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
17204f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
17218b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
1722ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
1723ca92afb2SStefano Zampini     PetscInt i;
1724ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
1725ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1726ca92afb2SStefano Zampini     }
1727ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
1728ca92afb2SStefano Zampini   }
17294f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
1730674ae819SStefano Zampini   PetscFunctionReturn(0);
1731674ae819SStefano Zampini }
1732674ae819SStefano Zampini 
1733674ae819SStefano Zampini #undef __FUNCT__
1734f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
1735f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
17366bfb1811SStefano Zampini {
17376bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
17386bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
17396bfb1811SStefano Zampini   VecType        impVecType;
17404f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
17416bfb1811SStefano Zampini   PetscErrorCode ierr;
17426bfb1811SStefano Zampini 
17436bfb1811SStefano Zampini   PetscFunctionBegin;
17446c4ed002SBarry Smith   if (!pcbddc->ConstraintMatrix) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
1745e7b262bdSStefano Zampini   /* get sizes */
17464f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
1747b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
17486bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
1749e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
1750e7b262bdSStefano Zampini   /* R nodes */
1751e7b262bdSStefano Zampini   old_size = -1;
1752e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
1753e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
1754e7b262bdSStefano Zampini   }
1755e7b262bdSStefano Zampini   if (n_R != old_size) {
1756e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
1757e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
17586bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
17596bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
17606bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
17616bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
1762e7b262bdSStefano Zampini   }
1763e7b262bdSStefano Zampini   /* local primal dofs */
1764e7b262bdSStefano Zampini   old_size = -1;
1765e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
1766e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
1767e7b262bdSStefano Zampini   }
1768e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
1769e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
177083b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
1771e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
17726bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
1773e7b262bdSStefano Zampini   }
1774e7b262bdSStefano Zampini   /* local explicit constraints */
1775e7b262bdSStefano Zampini   old_size = -1;
1776e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
1777e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
1778e7b262bdSStefano Zampini   }
1779e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
1780e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
178183b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
178283b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
178383b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
178483b7ccabSStefano Zampini   }
17856bfb1811SStefano Zampini   PetscFunctionReturn(0);
17866bfb1811SStefano Zampini }
17876bfb1811SStefano Zampini 
17886bfb1811SStefano Zampini #undef __FUNCT__
178947f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
179047f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
179188ebb749SStefano Zampini {
179225084f0cSStefano Zampini   PetscErrorCode  ierr;
179325084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
179488ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
179588ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1796d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
179725084f0cSStefano Zampini   /* submatrices of local problem */
179880677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
179906656605SStefano Zampini   /* submatrices of local coarse problem */
180006656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
180125084f0cSStefano Zampini   /* working matrices */
180206656605SStefano Zampini   Mat             C_CR;
180325084f0cSStefano Zampini   /* additional working stuff */
180406656605SStefano Zampini   PC              pc_R;
18054f1b2e48SStefano Zampini   Mat             F;
18065cbda25cSStefano Zampini   Vec             dummy_vec;
1807a3df083aSStefano Zampini   PetscBool       isLU,isCHOL,isILU,need_benign_correction;
180825084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
180906656605SStefano Zampini   PetscScalar     *work;
181006656605SStefano Zampini   PetscInt        *idx_V_B;
1811ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
181206656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
1813ffd830a3SStefano Zampini 
181425084f0cSStefano Zampini   /* some shortcuts to scalars */
181506656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
181688ebb749SStefano Zampini 
181788ebb749SStefano Zampini   PetscFunctionBegin;
1818ffd830a3SStefano Zampini   if (!pcbddc->symmetric_primal && pcbddc->benign_n) {
1819ffd830a3SStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Non-symmetric primal basis computation with benign trick not yet implemented");
1820ffd830a3SStefano Zampini   }
1821ffd830a3SStefano Zampini 
1822ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
1823b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
18244f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
1825b371cd4fSStefano Zampini   n_B = pcis->n_B;
1826b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
182788ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
182888ebb749SStefano Zampini 
182988ebb749SStefano Zampini   /* vertices in boundary numbering */
1830785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
18310e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
18326c4ed002SBarry Smith   if (i != n_vertices) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %D != %D\n",n_vertices,i);
183388ebb749SStefano Zampini 
183406656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
1835019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
183606656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
183706656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
183806656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
183906656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
184006656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
184106656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
184206656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
184306656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
184406656605SStefano Zampini 
184506656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
184606656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
184706656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
184806656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
184906656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
1850ffd830a3SStefano Zampini   lda_rhs = n_R;
1851a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
185206656605SStefano Zampini   if (isLU || isILU || isCHOL) {
185306656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
1854b334f244SStefano Zampini   } else if (sub_schurs && sub_schurs->reuse_solver) {
1855df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1856d62866d3SStefano Zampini     MatFactorType      type;
1857d62866d3SStefano Zampini 
1858df4d28bfSStefano Zampini     F = reuse_solver->F;
18596816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
1860d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
1861ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
186222db5ddcSStefano Zampini     need_benign_correction = (PetscBool)(!!reuse_solver->benign_n);
186306656605SStefano Zampini   } else {
186406656605SStefano Zampini     F = NULL;
186506656605SStefano Zampini   }
186606656605SStefano Zampini 
1867ffd830a3SStefano Zampini   /* allocate workspace */
1868ffd830a3SStefano Zampini   n = 0;
1869ffd830a3SStefano Zampini   if (n_constraints) {
1870ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
1871ffd830a3SStefano Zampini   }
1872ffd830a3SStefano Zampini   if (n_vertices) {
1873ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
1874ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
1875ffd830a3SStefano Zampini   }
1876ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
1877ffd830a3SStefano Zampini 
18785cbda25cSStefano Zampini   /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */
18795cbda25cSStefano Zampini   dummy_vec = NULL;
18805cbda25cSStefano Zampini   if (need_benign_correction && lda_rhs != n_R && F) {
18815cbda25cSStefano Zampini     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,lda_rhs,work,&dummy_vec);CHKERRQ(ierr);
18825cbda25cSStefano Zampini   }
18835cbda25cSStefano Zampini 
188488ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
188588ebb749SStefano Zampini   if (n_constraints) {
188672b8c272SStefano Zampini     Mat         M1,M2,M3,C_B;
188706656605SStefano Zampini     IS          is_aux;
188880677318SStefano Zampini     PetscScalar *array,*array2;
188906656605SStefano Zampini 
1890f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
189180677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
189288ebb749SStefano Zampini 
189325084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
189425084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
18958ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
189672b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
189788ebb749SStefano Zampini 
189880677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
189980677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
1900ffd830a3SStefano Zampini     ierr = PetscMemzero(work,lda_rhs*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
190188ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
190206656605SStefano Zampini       const PetscScalar *row_cmat_values;
190306656605SStefano Zampini       const PetscInt    *row_cmat_indices;
190406656605SStefano Zampini       PetscInt          size_of_constraint,j;
190588ebb749SStefano Zampini 
190606656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
190706656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
1908ffd830a3SStefano Zampini         work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
190906656605SStefano Zampini       }
191006656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
191106656605SStefano Zampini     }
1912ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
191306656605SStefano Zampini     if (F) {
191406656605SStefano Zampini       Mat B;
191506656605SStefano Zampini 
1916ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
1917a3df083aSStefano Zampini       if (need_benign_correction) {
1918df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1919a3df083aSStefano Zampini 
192072b8c272SStefano Zampini         /* rhs is already zero on interior dofs, no need to change the rhs */
192172b8c272SStefano Zampini         ierr = PetscMemzero(reuse_solver->benign_save_vals,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
1922a3df083aSStefano Zampini       }
192380677318SStefano Zampini       ierr = MatMatSolve(F,B,local_auxmat2_R);CHKERRQ(ierr);
1924a3df083aSStefano Zampini       if (need_benign_correction) {
1925a3df083aSStefano Zampini         PetscScalar        *marr;
1926df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1927a3df083aSStefano Zampini 
1928a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
19295cbda25cSStefano Zampini         if (lda_rhs != n_R) {
19305cbda25cSStefano Zampini           for (i=0;i<n_constraints;i++) {
19315cbda25cSStefano Zampini             ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
19325cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
19335cbda25cSStefano Zampini             ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
19345cbda25cSStefano Zampini           }
19355cbda25cSStefano Zampini         } else {
1936a3df083aSStefano Zampini           for (i=0;i<n_constraints;i++) {
1937a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
19385cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
1939a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1940a3df083aSStefano Zampini           }
19415cbda25cSStefano Zampini         }
1942a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
1943a3df083aSStefano Zampini       }
194406656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
194506656605SStefano Zampini     } else {
194680677318SStefano Zampini       PetscScalar *marr;
194780677318SStefano Zampini 
194880677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
194906656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
1950ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
1951ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
195206656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
195306656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
195406656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
195506656605SStefano Zampini       }
195680677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
195706656605SStefano Zampini     }
195880677318SStefano Zampini     if (!pcbddc->switch_static) {
195980677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
196080677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
196180677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
196280677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
1963ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
196480677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
196580677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
196680677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
196780677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
196880677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
196980677318SStefano Zampini       }
197080677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
197180677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
197272b8c272SStefano Zampini       ierr = MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
197380677318SStefano Zampini     } else {
1974ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
1975ffd830a3SStefano Zampini         IS dummy;
1976ffd830a3SStefano Zampini 
1977ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
197872b8c272SStefano Zampini         ierr = MatGetSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
1979ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1980ffd830a3SStefano Zampini       } else {
198180677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
198280677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
1983ffd830a3SStefano Zampini       }
198425084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
198580677318SStefano Zampini     }
198680677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
198780677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
198880677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
198906656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
199006656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
199180677318SStefano Zampini     if (isCHOL) {
199280677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
199380677318SStefano Zampini     } else {
199425084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
199580677318SStefano Zampini     }
199680677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,one);CHKERRQ(ierr);
199706656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
199825084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
199925084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
200025084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
200180677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
200272b8c272SStefano Zampini     ierr = MatMatMult(M1,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
200372b8c272SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
200406656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
200506656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
2006f4ddd8eeSStefano Zampini   }
2007fc227af8SStefano Zampini 
2008fc227af8SStefano Zampini   /* Get submatrices from subdomain matrix */
200988ebb749SStefano Zampini   if (n_vertices) {
201006656605SStefano Zampini     IS is_aux;
20113a50541eSStefano Zampini 
2012b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
20136816873aSStefano Zampini       IS tis;
20146816873aSStefano Zampini 
20156816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
20166816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
20176816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
20186816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
20196816873aSStefano Zampini     } else {
20203a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
20216816873aSStefano Zampini     }
20229577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
20239577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
202404708bb6SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
202525084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
202688ebb749SStefano Zampini   }
202788ebb749SStefano Zampini 
202888ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
2029f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
203006656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
203106656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
203206656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
203306656605SStefano Zampini     }
2034f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
203506656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
203606656605SStefano Zampini       PetscScalar *marray;
203706656605SStefano Zampini 
203806656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
203906656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
2040f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
2041f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
2042f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
2043f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
2044f4ddd8eeSStefano Zampini     }
2045f4ddd8eeSStefano Zampini   }
204606656605SStefano Zampini 
2047f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
204806656605SStefano Zampini     PetscScalar *marray;
204988ebb749SStefano Zampini 
205006656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
20518eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
205206656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
205388ebb749SStefano Zampini     }
20543301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
205506656605SStefano Zampini       n *= 2;
205688ebb749SStefano Zampini     }
205706656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
205806656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
205906656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
20608eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
206106656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
206206656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
206388ebb749SStefano Zampini     }
20643301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
206506656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
20668eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
206706656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
206806656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
206988ebb749SStefano Zampini       }
207088ebb749SStefano Zampini     } else {
2071c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
2072c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
20731b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
2074c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
2075c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
2076c0553b1fSStefano Zampini       }
207788ebb749SStefano Zampini     }
207806656605SStefano Zampini   }
2079019a44ceSStefano Zampini 
208006656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
20814f1b2e48SStefano Zampini   p0_lidx_I = NULL;
20824f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
2083d12edf2fSStefano Zampini     const PetscInt *idxs;
2084d12edf2fSStefano Zampini 
2085d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
20864f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
20874f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
20884f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
20894f1b2e48SStefano Zampini     }
2090d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
2091d12edf2fSStefano Zampini   }
2092d16cbb6bSStefano Zampini 
209306656605SStefano Zampini   /* vertices */
209406656605SStefano Zampini   if (n_vertices) {
209516f15bc4SStefano Zampini 
2096af25d912SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV);CHKERRQ(ierr);
209704708bb6SStefano Zampini 
209816f15bc4SStefano Zampini     if (n_R) {
209914393ed6SStefano Zampini       Mat          A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
210006656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
210116f15bc4SStefano Zampini       PetscScalar  *x,*y;
210204708bb6SStefano Zampini       PetscBool    isseqaij;
210306656605SStefano Zampini 
210421eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
210514393ed6SStefano Zampini       if (need_benign_correction) {
210614393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
210714393ed6SStefano Zampini         IS                     is_p0;
210814393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
210914393ed6SStefano Zampini 
211014393ed6SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
211114393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
211214393ed6SStefano Zampini         ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
2113af25d912SStefano Zampini         if (n != pcbddc->benign_n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in R numbering for benign p0! %d != %d\n",n,pcbddc->benign_n);
211414393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
211514393ed6SStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0);CHKERRQ(ierr);
211614393ed6SStefano Zampini         ierr = MatGetSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr);CHKERRQ(ierr);
211714393ed6SStefano Zampini         ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
211814393ed6SStefano Zampini       }
211914393ed6SStefano Zampini 
2120ffd830a3SStefano Zampini       if (lda_rhs == n_R) {
2121af25d912SStefano Zampini         ierr = MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
2122ffd830a3SStefano Zampini       } else {
2123ca92afb2SStefano Zampini         PetscScalar    *av,*array;
2124ca92afb2SStefano Zampini         const PetscInt *xadj,*adjncy;
2125ca92afb2SStefano Zampini         PetscInt       n;
2126ca92afb2SStefano Zampini         PetscBool      flg_row;
2127ffd830a3SStefano Zampini 
2128ca92afb2SStefano Zampini         array = work+lda_rhs*n_vertices;
2129ca92afb2SStefano Zampini         ierr = PetscMemzero(array,lda_rhs*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
21309d54b7f4SStefano Zampini         ierr = MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
2131ca92afb2SStefano Zampini         ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2132ca92afb2SStefano Zampini         ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
2133ca92afb2SStefano Zampini         for (i=0;i<n;i++) {
2134ca92afb2SStefano Zampini           PetscInt j;
2135ca92afb2SStefano Zampini           for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
2136ffd830a3SStefano Zampini         }
2137ca92afb2SStefano Zampini         ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2138ca92afb2SStefano Zampini         ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
2139ca92afb2SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
2140ffd830a3SStefano Zampini       }
2141ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
2142a3df083aSStefano Zampini       if (need_benign_correction) {
2143df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2144a3df083aSStefano Zampini         PetscScalar        *marr;
2145a3df083aSStefano Zampini 
2146a3df083aSStefano Zampini         ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
214714393ed6SStefano Zampini         /* need \Phi^T A_RV = (I+L)A_RV, L given by
214814393ed6SStefano Zampini 
214914393ed6SStefano Zampini                | 0 0  0 | (V)
215014393ed6SStefano Zampini            L = | 0 0 -1 | (P-p0)
215114393ed6SStefano Zampini                | 0 0 -1 | (p0)
215214393ed6SStefano Zampini 
215314393ed6SStefano Zampini         */
2154df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
215514393ed6SStefano Zampini           const PetscScalar *vals;
215614393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
215714393ed6SStefano Zampini           PetscInt          n,j,nz;
215814393ed6SStefano Zampini 
2159df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2160df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
216114393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
216214393ed6SStefano Zampini           for (j=0;j<n;j++) {
216314393ed6SStefano Zampini             PetscScalar val = vals[j];
216414393ed6SStefano Zampini             PetscInt    k,col = idxs[j];
216514393ed6SStefano Zampini             for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
216614393ed6SStefano Zampini           }
216714393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
2168df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
216914393ed6SStefano Zampini         }
217072b8c272SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
217172b8c272SStefano Zampini       }
217272b8c272SStefano Zampini       if (F) {
217314393ed6SStefano Zampini         /* need to correct the rhs */
217472b8c272SStefano Zampini         if (need_benign_correction) {
217572b8c272SStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
217672b8c272SStefano Zampini           PetscScalar        *marr;
217772b8c272SStefano Zampini 
217872b8c272SStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
21795cbda25cSStefano Zampini           if (lda_rhs != n_R) {
21805cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
21815cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
21825cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
21835cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
21845cbda25cSStefano Zampini             }
21855cbda25cSStefano Zampini           } else {
2186a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
2187a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
21885cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
2189a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
2190a3df083aSStefano Zampini             }
21915cbda25cSStefano Zampini           }
2192a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
2193a3df083aSStefano Zampini         }
219406656605SStefano Zampini         ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
219514393ed6SStefano Zampini         /* need to correct the solution */
2196a3df083aSStefano Zampini         if (need_benign_correction) {
2197df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2198a3df083aSStefano Zampini           PetscScalar        *marr;
2199a3df083aSStefano Zampini 
2200a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
22015cbda25cSStefano Zampini           if (lda_rhs != n_R) {
22025cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
22035cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
22045cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
22055cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
22065cbda25cSStefano Zampini             }
22075cbda25cSStefano Zampini           } else {
2208a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
2209a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
22105cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
2211a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
2212a3df083aSStefano Zampini             }
22135cbda25cSStefano Zampini           }
2214a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
2215a3df083aSStefano Zampini         }
221606656605SStefano Zampini       } else {
221706656605SStefano Zampini         ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
221806656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
2219ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
2220ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
222106656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
222206656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
222306656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
222406656605SStefano Zampini         }
222506656605SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
222606656605SStefano Zampini       }
222780677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
2228ffd830a3SStefano Zampini       /* S_VV and S_CV */
222906656605SStefano Zampini       if (n_constraints) {
223006656605SStefano Zampini         Mat B;
223180677318SStefano Zampini 
2232ffd830a3SStefano Zampini         ierr = PetscMemzero(work+lda_rhs*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
223380677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
2234ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
2235ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
223680677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
223780677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
223880677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
223980677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
224080677318SStefano Zampini         }
2241ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
224280677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
224380677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
2244ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
224580677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
224606656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
2247ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
2248ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
224906656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
225006656605SStefano Zampini       }
225104708bb6SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
225204708bb6SStefano Zampini       if (!isseqaij) { /* MatMatMult with SEQ(S)BAIJ below will raise an error */
2253511c6705SHong Zhang         ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
225404708bb6SStefano Zampini       }
2255ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
2256ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
2257ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
2258ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
2259ffd830a3SStefano Zampini       }
226006656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
226114393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
226214393ed6SStefano Zampini       if (need_benign_correction) {
2263df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
226414393ed6SStefano Zampini         PetscScalar      *marr,*sums;
226514393ed6SStefano Zampini 
226614393ed6SStefano Zampini         ierr = PetscMalloc1(n_vertices,&sums);CHKERRQ(ierr);
226714393ed6SStefano Zampini         ierr = MatDenseGetArray(S_VVt,&marr);
2268df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
226914393ed6SStefano Zampini           const PetscScalar *vals;
227014393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
227114393ed6SStefano Zampini           PetscInt          n,j,nz;
227214393ed6SStefano Zampini 
2273df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2274df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
227514393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
227614393ed6SStefano Zampini             PetscInt k;
227714393ed6SStefano Zampini             sums[j] = 0.;
227814393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
227914393ed6SStefano Zampini           }
228014393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
228114393ed6SStefano Zampini           for (j=0;j<n;j++) {
228214393ed6SStefano Zampini             PetscScalar val = vals[j];
228314393ed6SStefano Zampini             PetscInt k;
228414393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
228514393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
228614393ed6SStefano Zampini             }
228714393ed6SStefano Zampini           }
228814393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
2289df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
229014393ed6SStefano Zampini         }
229114393ed6SStefano Zampini         ierr = PetscFree(sums);CHKERRQ(ierr);
229214393ed6SStefano Zampini         ierr = MatDenseRestoreArray(S_VVt,&marr);
229314393ed6SStefano Zampini         ierr = MatDestroy(&A_RV_bcorr);CHKERRQ(ierr);
229414393ed6SStefano Zampini       }
229580677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
229606656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
229706656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
229806656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
229906656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
230006656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
230106656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
230206656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
2303d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
2304019a44ceSStefano Zampini     } else {
2305d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
2306d16cbb6bSStefano Zampini     }
230721eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
2308d16cbb6bSStefano Zampini 
230906656605SStefano Zampini     /* coarse basis functions */
231006656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
231116f15bc4SStefano Zampini       PetscScalar *y;
231216f15bc4SStefano Zampini 
2313ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
231406656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
231506656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
231606656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
231706656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
231806656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
231906656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
232006656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
232106656605SStefano Zampini 
232206656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
23234f1b2e48SStefano Zampini         PetscInt j;
23244f1b2e48SStefano Zampini 
232506656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
232606656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
232706656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
232806656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
232906656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
23304f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
233106656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
233206656605SStefano Zampini       }
233306656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
233406656605SStefano Zampini     }
233504708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
233604708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
233706656605SStefano Zampini   }
23385cbda25cSStefano Zampini   ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
233906656605SStefano Zampini 
234006656605SStefano Zampini   if (n_constraints) {
234106656605SStefano Zampini     Mat B;
234206656605SStefano Zampini 
2343ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
234406656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
234580677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
234606656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
234706656605SStefano Zampini     if (n_vertices) {
234880677318SStefano Zampini       if (isCHOL) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
234980677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
235080677318SStefano Zampini       } else {
235180677318SStefano Zampini         Mat S_VCt;
235280677318SStefano Zampini 
2353ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
2354ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
235572b8c272SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
2356ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
2357ffd830a3SStefano Zampini         }
235880677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
235980677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
236080677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
236180677318SStefano Zampini       }
236206656605SStefano Zampini     }
236306656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
236406656605SStefano Zampini     /* coarse basis functions */
236506656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
236606656605SStefano Zampini       PetscScalar *y;
236706656605SStefano Zampini 
2368ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
236906656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
237006656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
237106656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
237206656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
237306656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
237406656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
237506656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
23764f1b2e48SStefano Zampini         PetscInt j;
23774f1b2e48SStefano Zampini 
237806656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
237906656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
238006656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
238106656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
238206656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
23834f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
238406656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
238506656605SStefano Zampini       }
238606656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
238706656605SStefano Zampini     }
238806656605SStefano Zampini   }
238980677318SStefano Zampini   if (n_constraints) {
239080677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
239180677318SStefano Zampini   }
23924f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
239372b8c272SStefano Zampini 
239472b8c272SStefano Zampini   /* coarse matrix entries relative to B_0 */
239572b8c272SStefano Zampini   if (pcbddc->benign_n) {
239672b8c272SStefano Zampini     Mat         B0_B,B0_BPHI;
239772b8c272SStefano Zampini     IS          is_dummy;
239872b8c272SStefano Zampini     PetscScalar *data;
239972b8c272SStefano Zampini     PetscInt    j;
240072b8c272SStefano Zampini 
240172b8c272SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
240272b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
240372b8c272SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
240472b8c272SStefano Zampini     ierr = MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
240586c38910SStefano Zampini     ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
240672b8c272SStefano Zampini     ierr = MatDenseGetArray(B0_BPHI,&data);CHKERRQ(ierr);
240772b8c272SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) {
240872b8c272SStefano Zampini       PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
240972b8c272SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
241072b8c272SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j];
241172b8c272SStefano Zampini         coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j];
241272b8c272SStefano Zampini       }
241372b8c272SStefano Zampini     }
241472b8c272SStefano Zampini     ierr = MatDenseRestoreArray(B0_BPHI,&data);CHKERRQ(ierr);
241572b8c272SStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
241672b8c272SStefano Zampini     ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
241772b8c272SStefano Zampini   }
2418019a44ceSStefano Zampini 
241906656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
24203301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
2421ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
2422ffd830a3SStefano Zampini     PetscScalar *marray;
242306656605SStefano Zampini 
242406656605SStefano Zampini     if (n_constraints) {
2425ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
242606656605SStefano Zampini 
2427af25d912SStefano Zampini       ierr = MatTranspose(C_CR,MAT_INPLACE_MATRIX,&C_CRT);CHKERRQ(ierr);
242806656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
2429ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
243016f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
243106656605SStefano Zampini       if (n_vertices) {
2432ffd830a3SStefano Zampini         Mat S_VCT;
243306656605SStefano Zampini 
243406656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
2435ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
243616f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
243706656605SStefano Zampini       }
2438ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
24395b782168SStefano Zampini     } else {
24405b782168SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,NULL,&B_V);CHKERRQ(ierr);
244106656605SStefano Zampini     }
244216f15bc4SStefano Zampini     if (n_vertices && n_R) {
2443ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
2444ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
2445ffd830a3SStefano Zampini       PetscInt       n;
2446ffd830a3SStefano Zampini       PetscBool      flg_row;
244706656605SStefano Zampini 
2448ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
2449af25d912SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
2450ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2451ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
2452ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
2453ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
2454ffd830a3SStefano Zampini         PetscInt j;
2455ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
2456ffd830a3SStefano Zampini       }
2457ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
2458ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2459ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
246006656605SStefano Zampini     }
246106656605SStefano Zampini 
2462ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
2463ffd830a3SStefano Zampini     ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
2464ffd830a3SStefano Zampini     for (i=0;i<n_vertices;i++) {
2465ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
2466ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
246706656605SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
246806656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
246906656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
247006656605SStefano Zampini     }
2471ffd830a3SStefano Zampini     ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
24725b782168SStefano Zampini     if (B_C) {
2473ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
2474ffd830a3SStefano Zampini       for (i=n_vertices;i<n_constraints+n_vertices;i++) {
2475ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
2476ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
2477ffd830a3SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
2478ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
2479ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
248006656605SStefano Zampini       }
2481ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
24825b782168SStefano Zampini     }
24835b782168SStefano Zampini     for (i=n_vertices;i<n_constraints+n_vertices;i++) {
24845b782168SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
24855b782168SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
24865b782168SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
24875b782168SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
24885b782168SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
24895b782168SStefano Zampini     }
24905b782168SStefano Zampini     ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
249106656605SStefano Zampini     /* coarse basis functions */
249206656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
249306656605SStefano Zampini       PetscScalar *y;
249406656605SStefano Zampini 
2495ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
249606656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
249706656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
249806656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
249906656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
250006656605SStefano Zampini       if (i<n_vertices) {
250106656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
250206656605SStefano Zampini       }
250306656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
250406656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
250506656605SStefano Zampini 
250606656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
250706656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
250806656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
250906656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
251006656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
251106656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
251206656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
251306656605SStefano Zampini       }
251406656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
251506656605SStefano Zampini     }
2516ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
2517ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
251806656605SStefano Zampini   }
2519d62866d3SStefano Zampini   /* free memory */
252088ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
252106656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
252206656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
252306656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
252406656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
2525d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
2526d62866d3SStefano Zampini   if (n_vertices) {
2527d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
2528d62866d3SStefano Zampini   }
2529d62866d3SStefano Zampini   if (n_constraints) {
2530d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
2531d62866d3SStefano Zampini   }
253288ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
253388ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
253488ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
2535d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
253688ebb749SStefano Zampini     Mat         coarse_sub_mat;
253725084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
253888ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
253988ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
254088ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
25418bec7fa6SStefano Zampini     Mat         C_B,CPHI;
25428bec7fa6SStefano Zampini     IS          is_dummy;
25438bec7fa6SStefano Zampini     Vec         mones;
254488ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
254588ebb749SStefano Zampini     PetscReal   real_value;
254688ebb749SStefano Zampini 
2547a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
2548a3df083aSStefano Zampini       Mat A;
2549a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
2550a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
2551a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
2552a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
2553a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
2554a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
2555a3df083aSStefano Zampini     } else {
255688ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
255788ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
255888ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
255988ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
2560a3df083aSStefano Zampini     }
256188ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
256288ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
2563ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
256488ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
256588ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
256688ebb749SStefano Zampini     }
256788ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
256888ebb749SStefano Zampini 
256925084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
25703301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
257125084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2572ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
257388ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
257488ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
257588ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
257688ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
257788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
257888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
257988ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
258088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
258188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
258288ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
258388ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
258488ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
258588ebb749SStefano Zampini     } else {
258688ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
258788ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
258888ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
258988ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
259088ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
259188ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
259288ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
259388ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
259488ebb749SStefano Zampini     }
259588ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
259688ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
259788ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
2598511c6705SHong Zhang     ierr = MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1);CHKERRQ(ierr);
25994f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
2600fc227af8SStefano Zampini       Mat         B0_B,B0_BPHI;
2601d12edf2fSStefano Zampini       PetscScalar *data,*data2;
26024f1b2e48SStefano Zampini       PetscInt    j;
2603d12edf2fSStefano Zampini 
26044f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
2605fc227af8SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
2606d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
260786c38910SStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
2608d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
2609d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
26104f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
26114f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
2612d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
26134f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
26144f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
26154f1b2e48SStefano Zampini         }
2616d12edf2fSStefano Zampini       }
2617d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
2618d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
2619d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
2620d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
2621d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
2622d12edf2fSStefano Zampini     }
2623d12edf2fSStefano Zampini #if 0
2624d12edf2fSStefano Zampini   {
2625d12edf2fSStefano Zampini     PetscViewer viewer;
2626d12edf2fSStefano Zampini     char filename[256];
2627ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
2628d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
2629d12edf2fSStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2630ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
2631ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
2632ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
2633d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
263472b8c272SStefano Zampini     if (save_change) {
263572b8c272SStefano Zampini       Mat phi_B;
263672b8c272SStefano Zampini       ierr = MatMatMult(save_change,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&phi_B);CHKERRQ(ierr);
263772b8c272SStefano Zampini       ierr = PetscObjectSetName((PetscObject)phi_B,"phi_B");CHKERRQ(ierr);
263872b8c272SStefano Zampini       ierr = MatView(phi_B,viewer);CHKERRQ(ierr);
263972b8c272SStefano Zampini       ierr = MatDestroy(&phi_B);CHKERRQ(ierr);
264072b8c272SStefano Zampini     } else {
2641ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
2642ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
264372b8c272SStefano Zampini     }
2644ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
2645ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
2646ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
2647ffd830a3SStefano Zampini     }
2648ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
2649ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
2650ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
2651ffd830a3SStefano Zampini     }
265272b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
2653ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
2654ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
2655ffd830a3SStefano Zampini     }
2656d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
2657d12edf2fSStefano Zampini   }
2658d12edf2fSStefano Zampini #endif
265981d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
26608bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
26611575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
266206656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
26638bec7fa6SStefano Zampini 
26648bec7fa6SStefano Zampini     /* check constraints */
2665a00504b5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
2666a00504b5SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
26674f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
26688bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
2669a00504b5SStefano Zampini     } else {
2670a00504b5SStefano Zampini       PetscScalar *data;
2671a00504b5SStefano Zampini       Mat         tmat;
2672a00504b5SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
2673a00504b5SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat);CHKERRQ(ierr);
2674a00504b5SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
2675a00504b5SStefano Zampini       ierr = MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
2676a00504b5SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
2677a00504b5SStefano Zampini     }
26788bec7fa6SStefano Zampini     ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
26798bec7fa6SStefano Zampini     ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
26808bec7fa6SStefano Zampini     ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
26818bec7fa6SStefano Zampini     ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
2682bdae7319SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
2683ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
2684bdae7319SStefano Zampini       ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
2685bdae7319SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
2686bdae7319SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
2687bdae7319SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
2688bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
268988ebb749SStefano Zampini     }
26908bec7fa6SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
26918bec7fa6SStefano Zampini     ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
26928bec7fa6SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
26938bec7fa6SStefano Zampini     ierr = VecDestroy(&mones);CHKERRQ(ierr);
269425084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
269588ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
269688ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
269788ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
269888ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
269988ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
270088ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
270188ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
270288ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
270388ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
270488ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
2705ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
270688ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
270788ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
270888ebb749SStefano Zampini     }
270988ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
271088ebb749SStefano Zampini   }
27118629588bSStefano Zampini   /* get back data */
27128629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
271388ebb749SStefano Zampini   PetscFunctionReturn(0);
271488ebb749SStefano Zampini }
271588ebb749SStefano Zampini 
271688ebb749SStefano Zampini #undef __FUNCT__
2717d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
2718d648f858SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
2719aa0d41d4SStefano Zampini {
2720d65f70fdSStefano Zampini   Mat            *work_mat;
2721d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
2722d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
2723c43ebad9SStefano Zampini   PetscInt       rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL;
2724aa0d41d4SStefano Zampini   PetscErrorCode ierr;
2725aa0d41d4SStefano Zampini 
2726aa0d41d4SStefano Zampini   PetscFunctionBegin;
2727d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
2728d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
2729d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
2730d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
2731aa0d41d4SStefano Zampini 
2732d65f70fdSStefano Zampini   if (!rsorted) {
2733906d46d4SStefano Zampini     const PetscInt *idxs;
2734906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
2735aa0d41d4SStefano Zampini 
2736d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
2737d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
2738d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
2739d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
2740aa0d41d4SStefano Zampini     }
2741d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
2742d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
2743d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
2744d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
2745aa0d41d4SStefano Zampini     }
2746d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
2747d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
2748d65f70fdSStefano Zampini   } else {
2749d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
2750d65f70fdSStefano Zampini     isrow_s = isrow;
2751aa0d41d4SStefano Zampini   }
2752906d46d4SStefano Zampini 
2753d65f70fdSStefano Zampini   if (!csorted) {
2754d65f70fdSStefano Zampini     if (isrow == iscol) {
2755d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
2756d65f70fdSStefano Zampini       iscol_s = isrow_s;
2757d65f70fdSStefano Zampini     } else {
2758d65f70fdSStefano Zampini       const PetscInt *idxs;
2759d65f70fdSStefano Zampini       PetscInt       *idxs_sorted,i;
2760906d46d4SStefano Zampini 
2761d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
2762d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
2763d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
2764d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
2765d65f70fdSStefano Zampini       }
2766d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
2767d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
2768d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
2769d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
2770d65f70fdSStefano Zampini       }
2771d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
2772d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
2773d65f70fdSStefano Zampini     }
2774d65f70fdSStefano Zampini   } else {
2775d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
2776d65f70fdSStefano Zampini     iscol_s = iscol;
2777d65f70fdSStefano Zampini   }
2778d65f70fdSStefano Zampini 
2779d648f858SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
2780d65f70fdSStefano Zampini 
2781d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
2782906d46d4SStefano Zampini     Mat      new_mat;
2783d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
2784906d46d4SStefano Zampini 
2785d65f70fdSStefano Zampini     if (!rsorted) {
2786d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
2787d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
2788d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
2789d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
2790906d46d4SStefano Zampini       }
2791d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
2792d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
2793d65f70fdSStefano Zampini     } else {
2794d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
2795906d46d4SStefano Zampini     }
2796d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
2797d65f70fdSStefano Zampini 
2798d65f70fdSStefano Zampini     if (!csorted) {
2799d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
2800d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
2801d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
2802d65f70fdSStefano Zampini       } else {
2803d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
2804d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
2805d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
2806d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
2807d65f70fdSStefano Zampini         }
2808d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
2809d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
2810d65f70fdSStefano Zampini       }
2811d65f70fdSStefano Zampini     } else {
2812d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
2813d65f70fdSStefano Zampini     }
2814d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
2815d65f70fdSStefano Zampini 
2816d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
2817d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
2818d65f70fdSStefano Zampini     work_mat[0] = new_mat;
2819d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
2820d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
2821d65f70fdSStefano Zampini   }
2822d65f70fdSStefano Zampini 
2823d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
2824d65f70fdSStefano Zampini   *B = work_mat[0];
2825d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
2826d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
2827d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
2828d65f70fdSStefano Zampini   PetscFunctionReturn(0);
2829d65f70fdSStefano Zampini }
2830d65f70fdSStefano Zampini 
2831d65f70fdSStefano Zampini #undef __FUNCT__
28325e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
28335e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
2834aa0d41d4SStefano Zampini {
2835aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
28365e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2837d65f70fdSStefano Zampini   Mat            new_mat;
28385e8657edSStefano Zampini   IS             is_local,is_global;
2839d65f70fdSStefano Zampini   PetscInt       local_size;
2840d65f70fdSStefano Zampini   PetscBool      isseqaij;
2841aa0d41d4SStefano Zampini   PetscErrorCode ierr;
2842aa0d41d4SStefano Zampini 
2843aa0d41d4SStefano Zampini   PetscFunctionBegin;
2844aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
28455e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
28465e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
2847b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
2848aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
2849d648f858SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
2850aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
2851906d46d4SStefano Zampini 
2852906d46d4SStefano Zampini   /* check */
2853906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
2854906d46d4SStefano Zampini     Vec       x,x_change;
2855906d46d4SStefano Zampini     PetscReal error;
2856906d46d4SStefano Zampini 
28575e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
2858906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
28595e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
2860e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2861e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2862d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
2863e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2864e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2865906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
2866906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
2867906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2868906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
2869906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
2870906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
2871906d46d4SStefano Zampini   }
2872906d46d4SStefano Zampini 
287322d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
28749b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
287522d5777bSStefano Zampini   if (isseqaij) {
2876a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
2877a00504b5SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
2878aa0d41d4SStefano Zampini   } else {
2879a00504b5SStefano Zampini     Mat work_mat;
28801cf9b237SStefano Zampini 
2881a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
2882aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
2883a00504b5SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
28841d82a3b6SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
2885aa0d41d4SStefano Zampini   }
28863301b35fSStefano Zampini   if (matis->A->symmetric_set) {
28873301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
2888e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
28893301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
2890e496cd5dSStefano Zampini #endif
28913301b35fSStefano Zampini   }
2892d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
2893aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
2894aa0d41d4SStefano Zampini }
2895aa0d41d4SStefano Zampini 
2896aa0d41d4SStefano Zampini #undef __FUNCT__
2897a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
28988ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
2899a64d13efSStefano Zampini {
2900a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
2901a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
2902d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
290353892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
29043a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
29053a50541eSStefano Zampini   PetscInt        vbs,bs;
29066816873aSStefano Zampini   PetscBT         bitmask=NULL;
2907a64d13efSStefano Zampini   PetscErrorCode  ierr;
2908a64d13efSStefano Zampini 
2909a64d13efSStefano Zampini   PetscFunctionBegin;
2910b23d619eSStefano Zampini   /*
2911b23d619eSStefano Zampini     No need to setup local scatters if
2912b23d619eSStefano Zampini       - primal space is unchanged
2913b23d619eSStefano Zampini         AND
2914b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
2915b23d619eSStefano Zampini         AND
2916b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
2917b23d619eSStefano Zampini   */
2918b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
2919f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
2920f4ddd8eeSStefano Zampini   }
2921f4ddd8eeSStefano Zampini   /* destroy old objects */
2922f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
2923f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
2924f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
2925a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
2926b371cd4fSStefano Zampini   n_B = pcis->n_B;
2927b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
2928b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
29293a50541eSStefano Zampini 
2930a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
29316816873aSStefano Zampini 
293253892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
2933b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
2934854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
2935a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
2936a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
29370e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
2938a64d13efSStefano Zampini     }
2939a64d13efSStefano Zampini 
2940a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
29414641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
29426816873aSStefano Zampini         idx_R_local[n_R++] = i;
2943a64d13efSStefano Zampini       }
2944a64d13efSStefano Zampini     }
2945df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
2946df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
29476816873aSStefano Zampini 
2948df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2949df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
29506816873aSStefano Zampini   }
29513a50541eSStefano Zampini 
29523a50541eSStefano Zampini   /* Block code */
29533a50541eSStefano Zampini   vbs = 1;
29543a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
29553a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
29563a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
29573a50541eSStefano Zampini     PetscInt  *vary;
2958b334f244SStefano Zampini     if (!sub_schurs || !sub_schurs->reuse_solver) {
2959785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
29603a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
2961d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
2962d3df7717SStefano 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 */
29630e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
2964d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
29653a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
29663a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
29673a50541eSStefano Zampini           break;
29683a50541eSStefano Zampini         }
29693a50541eSStefano Zampini       }
2970d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
2971d3df7717SStefano Zampini     } else {
2972d3df7717SStefano Zampini       /* Verify directly the R set */
2973d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
2974d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
2975d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
2976d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
2977d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
2978d3df7717SStefano Zampini             break;
2979d3df7717SStefano Zampini           }
2980d3df7717SStefano Zampini         }
2981d3df7717SStefano Zampini       }
2982d3df7717SStefano Zampini     }
29833a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
29843a50541eSStefano Zampini       vbs = bs;
29853a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
29863a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
29873a50541eSStefano Zampini       }
29883a50541eSStefano Zampini     }
29893a50541eSStefano Zampini   }
29903a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
2991b334f244SStefano Zampini   if (sub_schurs && sub_schurs->reuse_solver) {
2992df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
299353892102SStefano Zampini 
2994df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2995df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
299653892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
2997df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
299853892102SStefano Zampini   } else {
29993a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
300053892102SStefano Zampini   }
3001a64d13efSStefano Zampini 
3002a64d13efSStefano Zampini   /* print some info if requested */
3003a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
3004a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
3005a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
30061575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3007a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
3008a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
30094f1b2e48SStefano 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);
3010a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3011a64d13efSStefano Zampini   }
3012a64d13efSStefano Zampini 
3013a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
3014b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
30156816873aSStefano Zampini     IS       is_aux1,is_aux2;
30166816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
30176816873aSStefano Zampini 
30183a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
3019854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
3020854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
3021a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
30224641a718SStefano Zampini     for (i=0; i<n_D; i++) {
30234641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
30244641a718SStefano Zampini     }
3025a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3026a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
30274641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
30284641a718SStefano Zampini         aux_array1[j++] = i;
3029a64d13efSStefano Zampini       }
3030a64d13efSStefano Zampini     }
3031a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
3032a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3033a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
30344641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
30354641a718SStefano Zampini         aux_array2[j++] = i;
3036a64d13efSStefano Zampini       }
3037a64d13efSStefano Zampini     }
3038a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3039a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
3040a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
3041a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
3042a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
3043a64d13efSStefano Zampini 
30448eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
3045785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
3046a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
30474641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
30484641a718SStefano Zampini           aux_array1[j++] = i;
3049a64d13efSStefano Zampini         }
3050a64d13efSStefano Zampini       }
3051a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
3052a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
3053a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
3054a64d13efSStefano Zampini     }
30554641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
30563a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
3057d62866d3SStefano Zampini   } else {
3058df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
30596816873aSStefano Zampini     IS                 tis;
30606816873aSStefano Zampini     PetscInt           schur_size;
30616816873aSStefano Zampini 
3062df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
30636816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
3064df4d28bfSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
30656816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
30666816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
30676816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
30686816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
30696816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
3070d62866d3SStefano Zampini     }
3071d62866d3SStefano Zampini   }
3072a64d13efSStefano Zampini   PetscFunctionReturn(0);
3073a64d13efSStefano Zampini }
3074a64d13efSStefano Zampini 
3075304d26faSStefano Zampini 
3076304d26faSStefano Zampini #undef __FUNCT__
3077304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
3078684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
3079304d26faSStefano Zampini {
3080304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3081304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
3082304d26faSStefano Zampini   PC             pc_temp;
3083304d26faSStefano Zampini   Mat            A_RR;
3084f4ddd8eeSStefano Zampini   MatReuse       reuse;
3085304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
3086304d26faSStefano Zampini   PetscReal      value;
308704708bb6SStefano Zampini   PetscInt       n_D,n_R;
3088c7017625SStefano Zampini   PetscBool      check_corr[2],issbaij;
3089304d26faSStefano Zampini   PetscErrorCode ierr;
3090e604994aSStefano Zampini   /* prefixes stuff */
3091312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
3092e604994aSStefano Zampini   size_t         len;
3093304d26faSStefano Zampini 
3094304d26faSStefano Zampini   PetscFunctionBegin;
3095304d26faSStefano Zampini 
3096e604994aSStefano Zampini   /* compute prefixes */
3097e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
3098e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
3099e604994aSStefano Zampini   if (!pcbddc->current_level) {
3100e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
3101e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
3102e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
3103e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
3104e604994aSStefano Zampini   } else {
3105e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
3106312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
3107e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
3108e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
3109312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
3110312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
311134d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
311234d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
3113e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
3114e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
3115e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
3116e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
3117e604994aSStefano Zampini   }
3118e604994aSStefano Zampini 
3119304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
3120684f6988SStefano Zampini   if (dirichlet) {
3121d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
3122450f8f5eSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
3123b334f244SStefano Zampini       if (!sub_schurs || !sub_schurs->reuse_solver) {
3124450f8f5eSStefano Zampini         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented\n");
3125450f8f5eSStefano Zampini       }
3126450f8f5eSStefano Zampini       if (pcbddc->dbg_flag) {
3127a3df083aSStefano Zampini         Mat    A_IIn;
3128a3df083aSStefano Zampini 
3129a3df083aSStefano Zampini         ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
3130a3df083aSStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
3131a3df083aSStefano Zampini         pcis->A_II = A_IIn;
3132a3df083aSStefano Zampini       }
3133450f8f5eSStefano Zampini     }
31343301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
31353301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
3136964fefecSStefano Zampini     }
3137ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
3138964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
3139304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
3140304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
3141304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
3142304d26faSStefano Zampini       /* default */
3143304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
3144e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
31459577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
3146304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
31479577ea80SStefano Zampini       if (issbaij) {
31489577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
31499577ea80SStefano Zampini       } else {
3150304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
31519577ea80SStefano Zampini       }
3152304d26faSStefano Zampini       /* Allow user's customization */
3153304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
3154304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
3155304d26faSStefano Zampini     }
3156d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
3157b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
3158df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3159d62866d3SStefano Zampini 
3160df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
3161d5574798SStefano Zampini     }
3162304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
3163304d26faSStefano Zampini     if (!n_D) {
3164304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
3165304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
3166304d26faSStefano Zampini     }
3167304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
3168304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
3169304d26faSStefano Zampini     /* set ksp_D into pcis data */
3170304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
3171304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
3172304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
3173684f6988SStefano Zampini   }
3174304d26faSStefano Zampini 
3175304d26faSStefano Zampini   /* NEUMANN PROBLEM */
3176684f6988SStefano Zampini   A_RR = 0;
3177684f6988SStefano Zampini   if (neumann) {
3178d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
317904708bb6SStefano Zampini     PetscInt        ibs,mbs;
318004708bb6SStefano Zampini     PetscBool       issbaij;
318104708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
3182f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
31838ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
3184f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
3185f4ddd8eeSStefano Zampini       PetscInt nn_R;
318681d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
3187f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
3188f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
3189f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
3190f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
3191f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3192f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
3193f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
3194727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
3195f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3196f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
3197f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
3198f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
3199f4ddd8eeSStefano Zampini         }
3200f4ddd8eeSStefano Zampini       }
3201f4ddd8eeSStefano Zampini       /* last check */
3202d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
3203f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3204f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
3205f4ddd8eeSStefano Zampini       }
3206f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
3207f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
3208f4ddd8eeSStefano Zampini     }
3209a00504b5SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection */
3210af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
3211af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
321204708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
321304708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
321404708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
321504708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
321604708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
3217af732b37SStefano Zampini       } else {
3218511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
32196816873aSStefano Zampini       }
322004708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
322104708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
322204708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
322304708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
322404708bb6SStefano Zampini       } else {
3225511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
322604708bb6SStefano Zampini       }
322704708bb6SStefano Zampini     }
3228a00504b5SStefano Zampini     /* extract A_RR */
3229b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
3230a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3231a00504b5SStefano Zampini 
3232a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
323316e386b8SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3234a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
323516e386b8SStefano Zampini           ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR);CHKERRQ(ierr);
323616e386b8SStefano Zampini         } else {
3237a00504b5SStefano Zampini           ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
3238a00504b5SStefano Zampini         }
3239a00504b5SStefano Zampini       } else {
3240a00504b5SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3241a00504b5SStefano Zampini         ierr = PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
3242a00504b5SStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
3243a00504b5SStefano Zampini       }
3244a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
3245f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
324616e386b8SStefano Zampini     }
32473301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
32483301b35fSStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
32496816873aSStefano Zampini     }
3250f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
3251304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
3252304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
3253304d26faSStefano Zampini       /* default */
3254304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
3255e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
3256304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
32579577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
32589577ea80SStefano Zampini       if (issbaij) {
32599577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
32609577ea80SStefano Zampini       } else {
3261304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
32629577ea80SStefano Zampini       }
3263304d26faSStefano Zampini       /* Allow user's customization */
3264304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
3265304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
3266304d26faSStefano Zampini     }
3267304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
3268304d26faSStefano Zampini     if (!n_R) {
3269304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
3270304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
3271304d26faSStefano Zampini     }
32725cbda25cSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
3273df4d28bfSStefano Zampini     /* Reuse solver if it is present */
3274b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
3275df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3276d62866d3SStefano Zampini 
3277df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
3278d62866d3SStefano Zampini     }
3279304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
3280304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
3281684f6988SStefano Zampini   }
3282304d26faSStefano Zampini 
3283684f6988SStefano Zampini   if (pcbddc->dbg_flag) {
3284684f6988SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
32851575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3286684f6988SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
3287684f6988SStefano Zampini   }
3288c7017625SStefano Zampini 
3289c7017625SStefano Zampini   /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */
3290c7017625SStefano Zampini   check_corr[0] = check_corr[1] = PETSC_FALSE;
3291c7017625SStefano Zampini   if (pcbddc->NullSpace_corr[0]) {
3292c7017625SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
3293c7017625SStefano Zampini   }
3294c7017625SStefano Zampini   if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) {
3295c7017625SStefano Zampini     check_corr[0] = PETSC_TRUE;
3296c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcbddc->NullSpace_corr[1]);CHKERRQ(ierr);
3297c7017625SStefano Zampini   }
3298c7017625SStefano Zampini   if (neumann && pcbddc->NullSpace_corr[2]) {
3299c7017625SStefano Zampini     check_corr[1] = PETSC_TRUE;
3300c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->NullSpace_corr[3]);CHKERRQ(ierr);
3301c7017625SStefano Zampini   }
3302c7017625SStefano Zampini 
3303c7017625SStefano Zampini   /* check Dirichlet and Neumann solvers */
3304c7017625SStefano Zampini   if (pcbddc->dbg_flag) {
3305684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
33060fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
33070fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
33080fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
33090fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
33100fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
3311e604994aSStefano 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);
3312c7017625SStefano Zampini       if (check_corr[0]) {
3313c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_TRUE);CHKERRQ(ierr);
3314c7017625SStefano Zampini       }
3315304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3316304d26faSStefano Zampini     }
3317684f6988SStefano Zampini     if (neumann) { /* Neumann */
33180fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
33190fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
33200fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
33210fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
33220fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
3323e604994aSStefano 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);
3324c7017625SStefano Zampini       if (check_corr[1]) {
3325c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_FALSE);CHKERRQ(ierr);
3326c7017625SStefano Zampini       }
3327304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3328304d26faSStefano Zampini     }
3329684f6988SStefano Zampini   }
33305cbda25cSStefano Zampini   /* free Neumann problem's matrix */
33315cbda25cSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3332304d26faSStefano Zampini   PetscFunctionReturn(0);
3333304d26faSStefano Zampini }
3334304d26faSStefano Zampini 
3335304d26faSStefano Zampini #undef __FUNCT__
3336ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
333780677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
3338674ae819SStefano Zampini {
3339674ae819SStefano Zampini   PetscErrorCode  ierr;
3340674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
3341be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
3342b334f244SStefano Zampini   PetscBool       reuse_solver = sub_schurs ? ( sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE ) : PETSC_FALSE;
3343674ae819SStefano Zampini 
3344674ae819SStefano Zampini   PetscFunctionBegin;
3345b334f244SStefano Zampini   if (!reuse_solver) {
334680677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
334720c7b377SStefano Zampini   }
334880677318SStefano Zampini   if (!pcbddc->switch_static) {
334980677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
335080677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
335180677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
335220c7b377SStefano Zampini     }
3353b334f244SStefano Zampini     if (!reuse_solver) {
335480677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
335580677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
335620c7b377SStefano Zampini     } else {
3357df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3358be83ff47SStefano Zampini 
3359df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3360df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
336120c7b377SStefano Zampini     }
3362be83ff47SStefano Zampini   } else {
336380677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
336480677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
336580677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
336680677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
336780677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
336880677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
336980677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
337080677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
337180677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3372674ae819SStefano Zampini     }
3373674ae819SStefano Zampini   }
3374b334f244SStefano Zampini   if (!reuse_solver || pcbddc->switch_static) {
337580677318SStefano Zampini     if (applytranspose) {
337680677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
337780677318SStefano Zampini     } else {
337880677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
337980677318SStefano Zampini     }
3380be83ff47SStefano Zampini   } else {
3381df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3382be83ff47SStefano Zampini 
3383be83ff47SStefano Zampini     if (applytranspose) {
3384df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
3385be83ff47SStefano Zampini     } else {
3386df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
3387be83ff47SStefano Zampini     }
3388be83ff47SStefano Zampini   }
338980677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
339080677318SStefano Zampini   if (!pcbddc->switch_static) {
3391b334f244SStefano Zampini     if (!reuse_solver) {
339280677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
339380677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3394be83ff47SStefano Zampini     } else {
3395df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3396be83ff47SStefano Zampini 
3397df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3398df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3399be83ff47SStefano Zampini     }
340080677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
340180677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
340280677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
340380677318SStefano Zampini     }
340480677318SStefano Zampini   } else {
340580677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
340680677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
340780677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
340880677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
340980677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
341080677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
341180677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
341280677318SStefano Zampini     }
341380677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
341480677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
341580677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
341680677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3417674ae819SStefano Zampini   }
3418674ae819SStefano Zampini   PetscFunctionReturn(0);
3419674ae819SStefano Zampini }
3420674ae819SStefano Zampini 
3421dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
3422674ae819SStefano Zampini #undef __FUNCT__
3423674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
3424dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
3425674ae819SStefano Zampini {
3426674ae819SStefano Zampini   PetscErrorCode ierr;
3427674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
3428674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
3429674ae819SStefano Zampini   const PetscScalar zero = 0.0;
3430674ae819SStefano Zampini 
3431674ae819SStefano Zampini   PetscFunctionBegin;
3432dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
34334fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
3434dc359a40SStefano Zampini     if (applytranspose) {
3435674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
34368eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
3437dc359a40SStefano Zampini     } else {
3438674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
3439674ae819SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
344015aaf578SStefano Zampini     }
34414fee134fSStefano Zampini   } else {
34424fee134fSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
34434fee134fSStefano Zampini   }
3444efc2fbd9SStefano Zampini 
3445efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
34464f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
3447efc2fbd9SStefano Zampini     PetscScalar *array;
34484f1b2e48SStefano Zampini     PetscInt    j;
3449efc2fbd9SStefano Zampini 
3450efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
34514f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
3452efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
3453efc2fbd9SStefano Zampini   }
3454efc2fbd9SStefano Zampini 
345512edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
345612edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
345712edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
345812edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
345912edc857SStefano Zampini 
34609f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
346112edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
346251694757SStefano Zampini     Mat          coarse_mat;
3463964fefecSStefano Zampini     Vec          rhs,sol;
346451694757SStefano Zampini     MatNullSpace nullsp;
346527b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
3466964fefecSStefano Zampini 
346727b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
346827b6a85dSStefano Zampini       PC        coarse_pc;
346927b6a85dSStefano Zampini 
347027b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
347127b6a85dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
347227b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
347327b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
347427b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
347527b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
34763bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
347727b6a85dSStefano Zampini       }
347827b6a85dSStefano Zampini     }
3479964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
3480964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
348151694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
348251694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
348351694757SStefano Zampini     if (nullsp) {
348451694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
348551694757SStefano Zampini     }
348612edc857SStefano Zampini     if (applytranspose) {
34871f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only) {
34881f4df5f7SStefano Zampini         SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
34892701bc32SStefano Zampini       } else {
3490964fefecSStefano Zampini         ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
34912701bc32SStefano Zampini       }
34922701bc32SStefano Zampini     } else {
34931f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
34942701bc32SStefano Zampini         PC        coarse_pc;
34952701bc32SStefano Zampini 
34962701bc32SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
34972701bc32SStefano Zampini         ierr = PCPreSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
34983e589ea0SStefano Zampini         ierr = PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol);CHKERRQ(ierr);
34992701bc32SStefano Zampini         ierr = PCPostSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
350012edc857SStefano Zampini       } else {
3501964fefecSStefano Zampini         ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
350212edc857SStefano Zampini       }
35032701bc32SStefano Zampini     }
35041d82a3b6SStefano Zampini     /* we don't need the benign correction at coarser levels anymore */
350527b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
350627b6a85dSStefano Zampini       PC        coarse_pc;
350727b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
350827b6a85dSStefano Zampini 
350927b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
351027b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
351127b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
35123bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
351327b6a85dSStefano Zampini     }
351451694757SStefano Zampini     if (nullsp) {
351551694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
351651694757SStefano Zampini     }
351712edc857SStefano Zampini   }
3518674ae819SStefano Zampini 
3519674ae819SStefano Zampini   /* Local solution on R nodes */
35204fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
352180677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
35229f00e9b4SStefano Zampini   }
35239f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
35249f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
352512edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3526674ae819SStefano Zampini 
35274fee134fSStefano Zampini   /* Sum contributions from the two levels */
35284fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
3529dc359a40SStefano Zampini     if (applytranspose) {
3530dc359a40SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
3531dc359a40SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
3532dc359a40SStefano Zampini     } else {
3533674ae819SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
35348eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
3535dc359a40SStefano Zampini     }
3536efc2fbd9SStefano Zampini     /* store p0 */
35374f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
3538efc2fbd9SStefano Zampini       PetscScalar *array;
35394f1b2e48SStefano Zampini       PetscInt    j;
3540efc2fbd9SStefano Zampini 
3541efc2fbd9SStefano Zampini       ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
35424f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
3543efc2fbd9SStefano Zampini       ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
3544efc2fbd9SStefano Zampini     }
35454fee134fSStefano Zampini   } else { /* expand the coarse solution */
35464fee134fSStefano Zampini     if (applytranspose) {
35474fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
35484fee134fSStefano Zampini     } else {
35494fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
35504fee134fSStefano Zampini     }
35514fee134fSStefano Zampini   }
3552674ae819SStefano Zampini   PetscFunctionReturn(0);
3553674ae819SStefano Zampini }
3554674ae819SStefano Zampini 
3555674ae819SStefano Zampini #undef __FUNCT__
3556674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
355712edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
3558674ae819SStefano Zampini {
3559674ae819SStefano Zampini   PetscErrorCode ierr;
3560674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
356158da7f69SStefano Zampini   PetscScalar    *array;
356212edc857SStefano Zampini   Vec            from,to;
3563674ae819SStefano Zampini 
3564674ae819SStefano Zampini   PetscFunctionBegin;
356512edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
356612edc857SStefano Zampini     from = pcbddc->coarse_vec;
356712edc857SStefano Zampini     to = pcbddc->vec1_P;
356812edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
356912edc857SStefano Zampini       Vec tvec;
357058da7f69SStefano Zampini 
357158da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
357258da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
357312edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
357458da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
357558da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
357658da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
357712edc857SStefano Zampini     }
357812edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
357912edc857SStefano Zampini     from = pcbddc->vec1_P;
358012edc857SStefano Zampini     to = pcbddc->coarse_vec;
358112edc857SStefano Zampini   }
358212edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
3583674ae819SStefano Zampini   PetscFunctionReturn(0);
3584674ae819SStefano Zampini }
3585674ae819SStefano Zampini 
3586674ae819SStefano Zampini #undef __FUNCT__
3587674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
358812edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
3589674ae819SStefano Zampini {
3590674ae819SStefano Zampini   PetscErrorCode ierr;
3591674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
359258da7f69SStefano Zampini   PetscScalar    *array;
359312edc857SStefano Zampini   Vec            from,to;
3594674ae819SStefano Zampini 
3595674ae819SStefano Zampini   PetscFunctionBegin;
359612edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
359712edc857SStefano Zampini     from = pcbddc->coarse_vec;
359812edc857SStefano Zampini     to = pcbddc->vec1_P;
359912edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
360012edc857SStefano Zampini     from = pcbddc->vec1_P;
360112edc857SStefano Zampini     to = pcbddc->coarse_vec;
360212edc857SStefano Zampini   }
360312edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
360412edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
360512edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
360612edc857SStefano Zampini       Vec tvec;
360758da7f69SStefano Zampini 
360812edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
360958da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
361058da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
361158da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
361258da7f69SStefano Zampini     }
361358da7f69SStefano Zampini   } else {
361458da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
361558da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
361612edc857SStefano Zampini     }
361712edc857SStefano Zampini   }
3618674ae819SStefano Zampini   PetscFunctionReturn(0);
3619674ae819SStefano Zampini }
3620674ae819SStefano Zampini 
3621984c4197SStefano Zampini /* uncomment for testing purposes */
3622984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
3623674ae819SStefano Zampini #undef __FUNCT__
3624674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
3625674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
3626674ae819SStefano Zampini {
3627674ae819SStefano Zampini   PetscErrorCode    ierr;
3628674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
3629674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
3630674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
3631984c4197SStefano Zampini   /* one and zero */
3632984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
3633984c4197SStefano Zampini   /* space to store constraints and their local indices */
36349162d606SStefano Zampini   PetscScalar       *constraints_data;
36359162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
36369162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
36379162d606SStefano Zampini   PetscInt          *constraints_n;
3638984c4197SStefano Zampini   /* iterators */
3639b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
3640984c4197SStefano Zampini   /* BLAS integers */
3641e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
3642e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
3643c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
3644727cdba6SStefano Zampini   /* reuse */
36450e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
36460e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
3647984c4197SStefano Zampini   /* change of basis */
3648b3d85658SStefano Zampini   PetscBool         qr_needed;
36499162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
3650984c4197SStefano Zampini   /* auxiliary stuff */
365164efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
36528a0068c3SStefano Zampini   PetscInt          ncc;
3653984c4197SStefano Zampini   /* some quantities */
365445a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
3655a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
3656984c4197SStefano Zampini 
3657674ae819SStefano Zampini   PetscFunctionBegin;
36588e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
36598e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
36608e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
366116909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
3662088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
3663088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
36640e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
36650e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
36660e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
36670e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
36680e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
3669088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
3670cf5a6209SStefano Zampini 
3671cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
36729162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
3673cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
3674cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
3675cf5a6209SStefano Zampini     Vec          *localnearnullsp;
3676cf5a6209SStefano Zampini     PetscScalar  *array;
3677cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
3678cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
3679674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
3680b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
3681674ae819SStefano Zampini     PetscScalar  *work;
3682674ae819SStefano Zampini     PetscReal    *singular_vals;
3683674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3684674ae819SStefano Zampini     PetscReal    *rwork;
3685674ae819SStefano Zampini #endif
3686674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3687674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
3688674ae819SStefano Zampini #else
3689964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
3690964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
3691674ae819SStefano Zampini #endif
3692674ae819SStefano Zampini 
3693674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
3694d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
3695e4d548c7SStefano Zampini     /* print some info */
36961f4df5f7SStefano Zampini     if (pcbddc->dbg_flag && !pcbddc->sub_schurs) {
3697e4d548c7SStefano Zampini       PetscInt nv;
3698e4d548c7SStefano Zampini 
3699e4d548c7SStefano Zampini       ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
3700e4d548c7SStefano Zampini       ierr = ISGetSize(ISForVertices,&nv);CHKERRQ(ierr);
3701e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3702e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3703e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
3704e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges);CHKERRQ(ierr);
3705e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces);CHKERRQ(ierr);
3706e4d548c7SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3707e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3708e4d548c7SStefano Zampini     }
3709e4d548c7SStefano Zampini 
3710d06fc5fdSStefano Zampini     /* free unneeded index sets */
3711d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
3712d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
3713674ae819SStefano Zampini     }
3714d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
3715d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
3716d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
3717d06fc5fdSStefano Zampini       }
3718d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
3719d06fc5fdSStefano Zampini       n_ISForEdges = 0;
3720d06fc5fdSStefano Zampini     }
3721d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
3722d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
3723d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
3724d06fc5fdSStefano Zampini       }
3725d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
3726d06fc5fdSStefano Zampini       n_ISForFaces = 0;
3727d06fc5fdSStefano Zampini     }
372870022509SStefano Zampini 
3729674ae819SStefano Zampini     /* check if near null space is attached to global mat */
3730674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
3731674ae819SStefano Zampini     if (nearnullsp) {
3732674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
3733f4ddd8eeSStefano Zampini       /* remove any stored info */
3734f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
3735f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3736f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
3737f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
3738f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
3739473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3740f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
3741f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
3742f4ddd8eeSStefano Zampini       }
3743984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
3744984c4197SStefano Zampini       nnsp_size = 0;
3745674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
3746674ae819SStefano Zampini     }
3747984c4197SStefano Zampini     /* get max number of constraints on a single cc */
3748984c4197SStefano Zampini     max_constraints = nnsp_size;
3749984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
3750984c4197SStefano Zampini 
3751674ae819SStefano Zampini     /*
3752674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
37539162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
37549162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
37559162d606SStefano Zampini          There can be multiple constraints per connected component
3756674ae819SStefano Zampini                                                                                                                                                            */
3757674ae819SStefano Zampini     n_vertices = 0;
3758674ae819SStefano Zampini     if (ISForVertices) {
3759674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
3760674ae819SStefano Zampini     }
37619162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
37629162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
37639162d606SStefano Zampini 
37649162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
37659162d606SStefano Zampini     total_counts *= max_constraints;
3766674ae819SStefano Zampini     total_counts += n_vertices;
37674641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
37689162d606SStefano Zampini 
3769674ae819SStefano Zampini     total_counts = 0;
3770674ae819SStefano Zampini     max_size_of_constraint = 0;
3771674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
37729162d606SStefano Zampini       IS used_is;
3773674ae819SStefano Zampini       if (i<n_ISForEdges) {
37749162d606SStefano Zampini         used_is = ISForEdges[i];
3775674ae819SStefano Zampini       } else {
37769162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
3777674ae819SStefano Zampini       }
37789162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
3779674ae819SStefano Zampini       total_counts += j;
3780674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
3781674ae819SStefano Zampini     }
37829162d606SStefano 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);
37839162d606SStefano Zampini 
3784984c4197SStefano Zampini     /* get local part of global near null space vectors */
3785785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
3786984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
3787984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
3788e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3789e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3790984c4197SStefano Zampini     }
3791674ae819SStefano Zampini 
3792242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
3793242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
3794a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
3795242a89d7SStefano Zampini 
3796984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
3797a773dcb8SStefano Zampini     if (!skip_lapack) {
3798674ae819SStefano Zampini       PetscScalar temp_work;
3799911cabfeSStefano Zampini 
3800674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3801984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
3802785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
3803785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
3804785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
3805674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3806785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
3807674ae819SStefano Zampini #endif
3808674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
3809c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
3810c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
3811674ae819SStefano Zampini       lwork = -1;
3812674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3813674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
3814c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
3815674ae819SStefano Zampini #else
3816c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
3817674ae819SStefano Zampini #endif
3818674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3819984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
3820674ae819SStefano Zampini #else /* on missing GESVD */
3821674ae819SStefano Zampini       /* SVD */
3822674ae819SStefano Zampini       PetscInt max_n,min_n;
3823674ae819SStefano Zampini       max_n = max_size_of_constraint;
3824984c4197SStefano Zampini       min_n = max_constraints;
3825984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
3826674ae819SStefano Zampini         min_n = max_size_of_constraint;
3827984c4197SStefano Zampini         max_n = max_constraints;
3828674ae819SStefano Zampini       }
3829785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
3830674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3831785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
3832674ae819SStefano Zampini #endif
3833674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
3834674ae819SStefano Zampini       lwork = -1;
3835e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
3836e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
3837b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
3838674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3839674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
38409162d606SStefano 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));
3841674ae819SStefano Zampini #else
38429162d606SStefano 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));
3843674ae819SStefano Zampini #endif
3844674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3845984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
3846984c4197SStefano Zampini #endif /* on missing GESVD */
3847674ae819SStefano Zampini       /* Allocate optimal workspace */
3848674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
3849854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
3850674ae819SStefano Zampini     }
3851674ae819SStefano Zampini     /* Now we can loop on constraining sets */
3852674ae819SStefano Zampini     total_counts = 0;
38539162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
38549162d606SStefano Zampini     constraints_data_ptr[0] = 0;
3855674ae819SStefano Zampini     /* vertices */
38569162d606SStefano Zampini     if (n_vertices) {
3857674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
38589162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
3859674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
38609162d606SStefano Zampini         constraints_n[total_counts] = 1;
38619162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
38629162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
38639162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
3864674ae819SStefano Zampini         total_counts++;
3865674ae819SStefano Zampini       }
3866674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3867674ae819SStefano Zampini       n_vertices = total_counts;
3868674ae819SStefano Zampini     }
3869984c4197SStefano Zampini 
3870674ae819SStefano Zampini     /* edges and faces */
38719162d606SStefano Zampini     total_counts_cc = total_counts;
3872911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
38739162d606SStefano Zampini       IS        used_is;
38749162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
38759162d606SStefano Zampini 
3876911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
38779162d606SStefano Zampini         used_is = ISForEdges[ncc];
3878984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
3879674ae819SStefano Zampini       } else {
38809162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
3881984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
3882674ae819SStefano Zampini       }
3883674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
38849162d606SStefano Zampini 
38859162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
38869162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3887984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
3888984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
3889674ae819SStefano Zampini       if (nnsp_has_cnst) {
38905b08dc53SStefano Zampini         PetscScalar quad_value;
38919162d606SStefano Zampini 
38929162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
38939162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
38949162d606SStefano Zampini 
3895a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
3896674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
3897a773dcb8SStefano Zampini         } else {
3898a773dcb8SStefano Zampini           quad_value = 1.0;
3899a773dcb8SStefano Zampini         }
3900674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
39019162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
3902674ae819SStefano Zampini         }
39039162d606SStefano Zampini         temp_constraints++;
3904674ae819SStefano Zampini         total_counts++;
3905674ae819SStefano Zampini       }
3906674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
3907984c4197SStefano Zampini         PetscReal real_value;
39089162d606SStefano Zampini         PetscScalar *ptr_to_data;
39099162d606SStefano Zampini 
3910984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
39119162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
3912674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
39139162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
3914674ae819SStefano Zampini         }
3915984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
3916984c4197SStefano Zampini         /* check if array is null on the connected component */
3917e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
39189162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
39195b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
3920674ae819SStefano Zampini           temp_constraints++;
3921674ae819SStefano Zampini           total_counts++;
39229162d606SStefano Zampini           if (!idxs_copied) {
39239162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
39249162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
3925674ae819SStefano Zampini           }
3926674ae819SStefano Zampini         }
39279162d606SStefano Zampini       }
39289162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
392945a1bb75SStefano Zampini       valid_constraints = temp_constraints;
3930eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
3931a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
39329162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
39339162d606SStefano Zampini 
39349162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
3935a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
39369162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
3937a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
39389162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
3939a773dcb8SStefano Zampini         } else { /* perform SVD */
3940984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
39419162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
3942674ae819SStefano Zampini 
3943674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3944984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
3945984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
3946984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
3947984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
3948984c4197SStefano Zampini                 from that computed using LAPACKgesvd
3949984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
3950984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
3951984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
3952674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
3953e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3954984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3955674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
3956674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
39579162d606SStefano 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));
3958674ae819SStefano Zampini             }
3959674ae819SStefano Zampini           }
3960e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
3961e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3962e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
3963674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
3964c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
3965674ae819SStefano Zampini #else
3966c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
3967674ae819SStefano Zampini #endif
3968674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3969984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
3970984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
3971674ae819SStefano Zampini           j = 0;
3972984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
3973674ae819SStefano Zampini           total_counts = total_counts-j;
397445a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
3975e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
3976c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3977c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3978c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
3979c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3980c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
3981c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
3982674ae819SStefano Zampini           if (j<temp_constraints) {
3983984c4197SStefano Zampini             PetscInt ii;
3984984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
3985674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
39869162d606SStefano 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));
3987674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
3988984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
3989674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
39909162d606SStefano 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];
3991674ae819SStefano Zampini               }
3992674ae819SStefano Zampini             }
3993674ae819SStefano Zampini           }
3994674ae819SStefano Zampini #else  /* on missing GESVD */
3995e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3996e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3997b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3998674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3999674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
40009162d606SStefano 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));
4001674ae819SStefano Zampini #else
40029162d606SStefano 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));
4003674ae819SStefano Zampini #endif
4004984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
4005674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4006984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
4007e310c8b4SStefano Zampini           k = temp_constraints;
4008e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
4009674ae819SStefano Zampini           j = 0;
4010e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
401145a1bb75SStefano Zampini           valid_constraints = k-j;
4012911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
4013984c4197SStefano Zampini #endif /* on missing GESVD */
4014674ae819SStefano Zampini         }
4015a773dcb8SStefano Zampini       }
40169162d606SStefano Zampini       /* update pointers information */
40179162d606SStefano Zampini       if (valid_constraints) {
40189162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
40199162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
40209162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
40219162d606SStefano Zampini         /* set change_of_basis flag */
402245a1bb75SStefano Zampini         if (boolforchange) {
4023b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
40249162d606SStefano Zampini         }
4025b3d85658SStefano Zampini         total_counts_cc++;
402645a1bb75SStefano Zampini       }
402745a1bb75SStefano Zampini     }
4028984c4197SStefano Zampini     /* free workspace */
40298f1c130eSStefano Zampini     if (!skip_lapack) {
4030984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
4031984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
4032984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
4033984c4197SStefano Zampini #endif
4034984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
4035984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
4036984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
4037984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
4038984c4197SStefano Zampini #endif
4039984c4197SStefano Zampini     }
4040984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
4041984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
4042984c4197SStefano Zampini     }
4043984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
4044cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
4045cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
4046cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
4047cf5a6209SStefano Zampini     }
4048cf5a6209SStefano Zampini     if (n_ISForFaces) {
4049cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
4050cf5a6209SStefano Zampini     }
4051cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
4052cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
4053cf5a6209SStefano Zampini     }
4054cf5a6209SStefano Zampini     if (n_ISForEdges) {
4055cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
4056cf5a6209SStefano Zampini     }
4057cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
405808122e43SStefano Zampini   } else {
405908122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
4060984c4197SStefano Zampini 
406108122e43SStefano Zampini     total_counts = 0;
406208122e43SStefano Zampini     n_vertices = 0;
4063d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
4064d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
406508122e43SStefano Zampini     }
406608122e43SStefano Zampini     max_constraints = 0;
40679162d606SStefano Zampini     total_counts_cc = 0;
406808122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
406908122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
40709162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
407108122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
407208122e43SStefano Zampini     }
40739162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
40749162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
40759162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
40769162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
407774d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
40789162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
40799162d606SStefano Zampini     total_counts_cc = 0;
40809162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
40819162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
40829162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
408308122e43SStefano Zampini       }
408408122e43SStefano Zampini     }
40859162d606SStefano Zampini #if 0
40869162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
40879162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
40889162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
40899162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
40909162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
40919162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
40929162d606SStefano Zampini       }
40939162d606SStefano Zampini       printf("\n");
40949162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
40959162d606SStefano Zampini     }
40961b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
40978bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
40981b968477SStefano Zampini     }
40991b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
41008bec7fa6SStefano 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]);
41011b968477SStefano Zampini     }
410208122e43SStefano Zampini #endif
410308122e43SStefano Zampini 
41048bec7fa6SStefano Zampini     max_size_of_constraint = 0;
41059162d606SStefano 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]);
41069162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
410708122e43SStefano Zampini     /* Change of basis */
4108b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
410908122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
411008122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
411108122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
4112b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
411308122e43SStefano Zampini         }
411408122e43SStefano Zampini       }
411508122e43SStefano Zampini     }
411608122e43SStefano Zampini   }
4117984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
41184f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
411908122e43SStefano Zampini 
41209162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
41219162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
41226c4ed002SBarry Smith   if (i != constraints_idxs_ptr[total_counts_cc]) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for constraints indices %D != %D\n",constraints_idxs_ptr[total_counts_cc],i);
4123674ae819SStefano Zampini 
4124674ae819SStefano Zampini   /* Create constraint matrix */
4125674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
412616f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
4127984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
4128984c4197SStefano Zampini 
4129984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
4130a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
4131a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
413274d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
4133984c4197SStefano Zampini   total_primal_vertices=0;
4134b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
41359162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
41369162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
413772b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
41389162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
4139b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
414064efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
41419162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
41429162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
4143a717540cSStefano Zampini       }
4144b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
414591af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
4146a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
4147a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
4148a717540cSStefano Zampini       }
4149fa434743SStefano Zampini     } else {
4150b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
4151fa434743SStefano Zampini     }
4152a717540cSStefano Zampini   }
4153b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
4154b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
4155674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
415670022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
4157b3d85658SStefano Zampini 
41584f1b2e48SStefano 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);
41590e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
41600e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
4161984c4197SStefano Zampini 
4162984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
416374d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
4164785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
4165984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
416674d5cdf7SStefano Zampini 
4167984c4197SStefano Zampini   j = total_primal_vertices;
416874d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
4169b3d85658SStefano Zampini   cum = total_primal_vertices;
41709162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
41714641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
4172b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
4173b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
4174b3d85658SStefano Zampini       cum++;
41759162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
417674d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
417774d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
417874d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
417974d5cdf7SStefano Zampini       }
41809162d606SStefano Zampini       j += constraints_n[i];
4181674ae819SStefano Zampini     }
4182674ae819SStefano Zampini   }
4183674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
4184674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
4185088faed8SStefano Zampini 
4186674ae819SStefano Zampini   /* set values in constraint matrix */
4187984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
41880e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
4189674ae819SStefano Zampini   }
4190984c4197SStefano Zampini   total_counts = total_primal_vertices;
41919162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
41924641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
41939162d606SStefano Zampini       PetscInt *cols;
41949162d606SStefano Zampini 
41959162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
41969162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
41979162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
41989162d606SStefano Zampini         PetscInt    row = total_counts+k;
41999162d606SStefano Zampini         PetscScalar *vals;
42009162d606SStefano Zampini 
42019162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
42029162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
42039162d606SStefano Zampini       }
42049162d606SStefano Zampini       total_counts += constraints_n[i];
4205674ae819SStefano Zampini     }
4206674ae819SStefano Zampini   }
4207674ae819SStefano Zampini   /* assembling */
4208674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4209674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4210088faed8SStefano Zampini 
4211984c4197SStefano Zampini   /*
42126a9046bcSBarry Smith   ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4213984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
4214f159cad9SBarry Smith   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
4215984c4197SStefano Zampini   */
4216674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
4217674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
4218026de310SStefano Zampini     /* dual and primal dofs on a single cc */
4219984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
4220984c4197SStefano Zampini     /* working stuff for GEQRF */
422181d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
4222984c4197SStefano Zampini     PetscBLASInt lqr_work;
4223984c4197SStefano Zampini     /* working stuff for UNGQR */
4224984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
4225984c4197SStefano Zampini     PetscBLASInt lgqr_work;
4226984c4197SStefano Zampini     /* working stuff for TRTRS */
4227984c4197SStefano Zampini     PetscScalar  *trs_rhs;
42283f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
4229984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
4230984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
4231984c4197SStefano Zampini     PetscScalar  *start_vals;
4232984c4197SStefano Zampini     /* working stuff for values insertion */
42334641a718SStefano Zampini     PetscBT      is_primal;
423464efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
4235906d46d4SStefano Zampini     /* matrix sizes */
4236906d46d4SStefano Zampini     PetscInt     global_size,local_size;
4237906d46d4SStefano Zampini     /* temporary change of basis */
4238906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
4239cf5a6209SStefano Zampini     /* extra space for debugging */
4240cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
4241984c4197SStefano Zampini 
4242906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
4243906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
424416f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
4245bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
4246906d46d4SStefano Zampini     /* nonzeros for local mat */
4247bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
42481dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
4249bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
42501dd7afcfSStefano Zampini     } else {
42511dd7afcfSStefano Zampini       const PetscInt *ii;
42521dd7afcfSStefano Zampini       PetscInt       n;
42531dd7afcfSStefano Zampini       PetscBool      flg_row;
42541dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
42551dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
42561dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
42571dd7afcfSStefano Zampini     }
42589162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
4259a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
42609162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
4261a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
42629162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
4263a717540cSStefano Zampini         } else {
42649162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
42659162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
4266a717540cSStefano Zampini         }
4267a717540cSStefano Zampini       }
4268a717540cSStefano Zampini     }
4269906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
4270bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
42711dd7afcfSStefano Zampini     /* Set interior change in the matrix */
42721dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
4273bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
4274906d46d4SStefano Zampini         ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
4275a717540cSStefano Zampini       }
42761dd7afcfSStefano Zampini     } else {
42771dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
42781dd7afcfSStefano Zampini       PetscScalar    *aa;
42791dd7afcfSStefano Zampini       PetscInt       n;
42801dd7afcfSStefano Zampini       PetscBool      flg_row;
42811dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
42821dd7afcfSStefano Zampini       ierr = MatSeqAIJGetArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
42831dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
42841dd7afcfSStefano Zampini         ierr = MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES);CHKERRQ(ierr);
42851dd7afcfSStefano Zampini       }
42861dd7afcfSStefano Zampini       ierr = MatSeqAIJRestoreArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
42871dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
42881dd7afcfSStefano Zampini     }
4289a717540cSStefano Zampini 
4290a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
4291a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
4292a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
4293a717540cSStefano Zampini     }
4294a717540cSStefano Zampini 
4295a717540cSStefano Zampini 
4296a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
4297a717540cSStefano Zampini     /*
4298a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
4299a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
4300a717540cSStefano Zampini 
4301a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
4302a717540cSStefano Zampini 
4303a6b551f4SStefano 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)
4304a6b551f4SStefano Zampini 
4305a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
4306a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
4307a717540cSStefano Zampini             |              ...                        |
4308a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
4309a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
4310a717540cSStefano Zampini 
4311a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
4312a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
4313a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
4314a6b551f4SStefano Zampini 
4315a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
4316a717540cSStefano Zampini     */
4317a717540cSStefano Zampini     if (qr_needed) {
4318984c4197SStefano Zampini       /* space to store Q */
4319854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
4320984c4197SStefano Zampini       /* first we issue queries for optimal work */
43213f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
43223f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
43233f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4324984c4197SStefano Zampini       lqr_work = -1;
43253f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
4326984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
4327984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
4328785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
4329984c4197SStefano Zampini       lgqr_work = -1;
43303f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
43313f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
43323f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
43333f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
43343f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
43353f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
4336984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
4337984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
4338785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
4339984c4197SStefano Zampini       /* array to store scaling factors for reflectors */
4340785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
4341984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
4342785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
4343a717540cSStefano Zampini       /* allocating workspace for check */
4344a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
4345cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
4346a717540cSStefano Zampini       }
4347a717540cSStefano Zampini     }
4348984c4197SStefano Zampini     /* array to store whether a node is primal or not */
43494641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
4350473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
43510e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
43526c4ed002SBarry Smith     if (i != total_primal_vertices) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %D != %D\n",total_primal_vertices,i);
435339e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
435439e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
435539e2fb2aSStefano Zampini     }
435639e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
4357984c4197SStefano Zampini 
4358a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
43599162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
43609162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
43614641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
4362984c4197SStefano Zampini         /* get constraint info */
43639162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
4364984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
4365984c4197SStefano Zampini 
4366984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
43679162d606SStefano 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);
4368674ae819SStefano Zampini         }
4369984c4197SStefano Zampini 
4370fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
4371a717540cSStefano Zampini 
4372a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
4373a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
43749162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
4375a717540cSStefano Zampini           }
4376984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
43779162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
4378984c4197SStefano Zampini 
4379984c4197SStefano Zampini           /* compute QR decomposition of constraints */
43803f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
43813f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
43823f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4383674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
43843f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
4385984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
4386674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4387984c4197SStefano Zampini 
4388984c4197SStefano Zampini           /* explictly compute R^-T */
4389984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
4390984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
43913f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
43923f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
43933f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
43943f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
4395984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
43963f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
4397984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
4398984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4399984c4197SStefano Zampini 
4400a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
44013f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
44023f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
44033f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
44043f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4405984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
44063f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
4407984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
4408984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4409984c4197SStefano Zampini 
4410984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
4411984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
4412984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
44133f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
44143f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
44153f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
44163f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
44173f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
44183f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
4419984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
44209162d606SStefano 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));
4421984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
44229162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
4423984c4197SStefano Zampini 
4424984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
44259162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
4426984c4197SStefano Zampini           /* insert cols for primal dofs */
4427984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
4428984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
44299162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
4430906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
4431984c4197SStefano Zampini           }
4432984c4197SStefano Zampini           /* insert cols for dual dofs */
4433984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
44349162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
4435984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
44369162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
4437906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
4438984c4197SStefano Zampini               j++;
4439674ae819SStefano Zampini             }
4440674ae819SStefano Zampini           }
4441984c4197SStefano Zampini 
4442984c4197SStefano Zampini           /* check change of basis */
4443984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
4444984c4197SStefano Zampini             PetscInt   ii,jj;
4445984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
4446c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
4447c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
4448c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
4449c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4450c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
4451c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
4452984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
4453cf5a6209SStefano 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));
4454984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
4455984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
4456984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
4457cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
4458cf5a6209SStefano 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;
4459674ae819SStefano Zampini               }
4460674ae819SStefano Zampini             }
4461984c4197SStefano Zampini             if (!valid_qr) {
446222d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
4463984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
4464984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
4465cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
4466cf5a6209SStefano 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]));
4467674ae819SStefano Zampini                   }
4468cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
4469cf5a6209SStefano 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]));
4470984c4197SStefano Zampini                   }
4471984c4197SStefano Zampini                 }
4472984c4197SStefano Zampini               }
4473674ae819SStefano Zampini             } else {
447422d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
4475674ae819SStefano Zampini             }
4476674ae819SStefano Zampini           }
4477a717540cSStefano Zampini         } else { /* simple transformation block */
4478a717540cSStefano Zampini           PetscInt    row,col;
4479a6b551f4SStefano Zampini           PetscScalar val,norm;
4480a6b551f4SStefano Zampini 
4481a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
44829162d606SStefano 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));
4483a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
44849162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
44859162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
4486bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
44879162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
4488906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
44899162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
4490a717540cSStefano Zampini             } else {
4491a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
44929162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
4493a717540cSStefano Zampini                 if (row != col) {
44949162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
4495a717540cSStefano Zampini                 } else {
44969162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
4497a717540cSStefano Zampini                 }
4498906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
4499a717540cSStefano Zampini               }
4500a717540cSStefano Zampini             }
4501a717540cSStefano Zampini           }
450298a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
450322d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
4504a717540cSStefano Zampini           }
4505674ae819SStefano Zampini         }
4506984c4197SStefano Zampini       } else {
4507984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
45089162d606SStefano 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);
4509674ae819SStefano Zampini         }
4510674ae819SStefano Zampini       }
4511674ae819SStefano Zampini     }
4512a717540cSStefano Zampini 
4513a717540cSStefano Zampini     /* free workspace */
4514a717540cSStefano Zampini     if (qr_needed) {
4515984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
4516cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
4517984c4197SStefano Zampini       }
4518984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
4519984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
4520984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
4521984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
4522984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
4523674ae819SStefano Zampini     }
4524a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
4525906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4526906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4527906d46d4SStefano Zampini 
4528906d46d4SStefano Zampini     /* assembling of global change of variable */
452988c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
4530bbb9e6c6SStefano Zampini       Mat      tmat;
453116f15bc4SStefano Zampini       PetscInt bs;
453216f15bc4SStefano Zampini 
4533906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
4534906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
4535bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
4536bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
4537bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
4538bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
453916f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
454016f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
4541906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
4542bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
4543bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
4544bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4545bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4546bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
4547e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4548e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4549bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
4550bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
455188c03ad3SStefano Zampini 
4552906d46d4SStefano Zampini       /* check */
4553906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
4554906d46d4SStefano Zampini         PetscReal error;
4555906d46d4SStefano Zampini         Vec       x,x_change;
4556906d46d4SStefano Zampini 
4557906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
4558906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
4559906d46d4SStefano Zampini         ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
4560906d46d4SStefano Zampini         ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
4561e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4562e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4563bbb9e6c6SStefano Zampini         ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
4564e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4565e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4566906d46d4SStefano Zampini         ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
4567906d46d4SStefano Zampini         ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
4568906d46d4SStefano Zampini         ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
4569906d46d4SStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4570bbb9e6c6SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
4571906d46d4SStefano Zampini         ierr = VecDestroy(&x);CHKERRQ(ierr);
4572906d46d4SStefano Zampini         ierr = VecDestroy(&x_change);CHKERRQ(ierr);
4573906d46d4SStefano Zampini       }
4574b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
4575b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
4576b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
4577bf3a8328SStefano Zampini 
4578bf3a8328SStefano Zampini         if (pcbddc->use_change_of_basis && pcbddc->adaptive_userdefined) {
4579bf3a8328SStefano Zampini           SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot mix automatic change of basis, adaptive selection and user-defined constraints");CHKERRQ(ierr);
4580bf3a8328SStefano Zampini         }
4581b334f244SStefano Zampini         if (sub_schurs && sub_schurs->S_Ej_all) {
4582ac632422SStefano Zampini           Mat                    S_new,tmat;
4583bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
4584bbb9e6c6SStefano Zampini 
4585bbb9e6c6SStefano Zampini           ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
45866816873aSStefano Zampini           ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
4587bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
4588bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
4589bf3a8328SStefano Zampini             IS                     is_V;
4590b087196eSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
4591b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
4592b087196eSStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
4593b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
4594b087196eSStefano Zampini             ierr = ISDestroy(&is_V);CHKERRQ(ierr);
4595bf3a8328SStefano Zampini           }
4596bf3a8328SStefano Zampini           ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
4597ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
4598b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
4599ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
4600bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
4601bf3a8328SStefano Zampini             const PetscScalar *array;
4602bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
4603bf3a8328SStefano Zampini             PetscInt          i,n_V;
4604bf3a8328SStefano Zampini 
4605b087196eSStefano Zampini             ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
4606b087196eSStefano Zampini             ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
4607b087196eSStefano Zampini             ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
4608b087196eSStefano Zampini             ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
4609b087196eSStefano Zampini             ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
4610b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
4611b087196eSStefano Zampini               PetscScalar val;
4612b087196eSStefano Zampini               PetscInt    idx;
4613b087196eSStefano Zampini 
4614b087196eSStefano Zampini               idx = idxs_V[i];
4615b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
4616b087196eSStefano Zampini               ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
4617b087196eSStefano Zampini             }
4618b087196eSStefano Zampini             ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4619b087196eSStefano Zampini             ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4620bf3a8328SStefano Zampini             ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
4621bf3a8328SStefano Zampini             ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
4622bf3a8328SStefano Zampini             ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
4623bf3a8328SStefano Zampini           }
4624ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
4625ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
4626ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
4627ac632422SStefano Zampini             ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
4628b96c3477SStefano Zampini             ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
4629ac632422SStefano Zampini             ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
4630bf3a8328SStefano Zampini             if (pcbddc->deluxe_zerorows) {
4631b087196eSStefano Zampini               ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
4632bf3a8328SStefano Zampini             }
4633ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
4634ac632422SStefano Zampini             ierr = MatDestroy(&S_new);CHKERRQ(ierr);
4635ac632422SStefano Zampini           }
4636b087196eSStefano Zampini           ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
463788c03ad3SStefano Zampini           ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4638b96c3477SStefano Zampini         }
4639c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
4640b334f244SStefano Zampini         if (sub_schurs && sub_schurs->change) {
4641c9db6a07SStefano Zampini           PetscInt i;
4642c9db6a07SStefano Zampini 
4643c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
4644c9db6a07SStefano Zampini             ierr = KSPDestroy(&sub_schurs->change[i]);CHKERRQ(ierr);
4645c9db6a07SStefano Zampini           }
4646c9db6a07SStefano Zampini           ierr = PetscFree(sub_schurs->change);CHKERRQ(ierr);
4647c9db6a07SStefano Zampini         }
4648b96c3477SStefano Zampini       }
464916909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
465016909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
465116909a7fSStefano Zampini       } else {
4652906d46d4SStefano Zampini         ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
465316909a7fSStefano Zampini       }
46541dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
465527b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
465672b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
465772b8c272SStefano Zampini       ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
465872b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
465972b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
466072b8c272SStefano Zampini     }
46611dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
466227b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
4663b9b85e73SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
4664b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
4665906d46d4SStefano Zampini     } else {
46661dd7afcfSStefano Zampini       Mat benign_global = NULL;
466727b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
46681dd7afcfSStefano Zampini         Mat tmat;
46691dd7afcfSStefano Zampini 
46701dd7afcfSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
46711dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
46721dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
46731dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
46741dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
46751dd7afcfSStefano Zampini         ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
46761dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
46771dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
46781dd7afcfSStefano Zampini         ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
46791dd7afcfSStefano Zampini         if (pcbddc->benign_change) {
46801dd7afcfSStefano Zampini           Mat M;
46811dd7afcfSStefano Zampini 
46821dd7afcfSStefano Zampini           ierr = MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M);CHKERRQ(ierr);
46831dd7afcfSStefano Zampini           ierr = MatDiagonalScale(M,pcis->vec1_N,NULL);CHKERRQ(ierr);
46841dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,M);CHKERRQ(ierr);
46851dd7afcfSStefano Zampini           ierr = MatDestroy(&M);CHKERRQ(ierr);
4686906d46d4SStefano Zampini         } else {
46871dd7afcfSStefano Zampini           Mat         eye;
46881dd7afcfSStefano Zampini           PetscScalar *array;
46891dd7afcfSStefano Zampini 
46901dd7afcfSStefano Zampini           ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
46911dd7afcfSStefano Zampini           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&eye);CHKERRQ(ierr);
46921dd7afcfSStefano Zampini           for (i=0;i<pcis->n;i++) {
46931dd7afcfSStefano Zampini             ierr = MatSetValue(eye,i,i,array[i],INSERT_VALUES);CHKERRQ(ierr);
4694906d46d4SStefano Zampini           }
46951dd7afcfSStefano Zampini           ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
46961dd7afcfSStefano Zampini           ierr = MatAssemblyBegin(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
46971dd7afcfSStefano Zampini           ierr = MatAssemblyEnd(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
46981dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,eye);CHKERRQ(ierr);
46991dd7afcfSStefano Zampini           ierr = MatDestroy(&eye);CHKERRQ(ierr);
47001dd7afcfSStefano Zampini         }
47011dd7afcfSStefano Zampini         ierr = MatISGetMPIXAIJ(tmat,MAT_INITIAL_MATRIX,&benign_global);CHKERRQ(ierr);
47021dd7afcfSStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
47031dd7afcfSStefano Zampini       }
47041dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
47051dd7afcfSStefano Zampini         ierr = MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
47061dd7afcfSStefano Zampini         ierr = MatDestroy(&benign_global);CHKERRQ(ierr);
470727b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
47081dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
47091dd7afcfSStefano Zampini       }
47101dd7afcfSStefano Zampini     }
471116909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
471216909a7fSStefano Zampini       IS             is_global;
471316909a7fSStefano Zampini       const PetscInt *gidxs;
471416909a7fSStefano Zampini 
471516909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
471616909a7fSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global);CHKERRQ(ierr);
471716909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
471816909a7fSStefano Zampini       ierr = MatGetSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change);CHKERRQ(ierr);
471916909a7fSStefano Zampini       ierr = ISDestroy(&is_global);CHKERRQ(ierr);
472016909a7fSStefano Zampini     }
47211dd7afcfSStefano Zampini   }
47221dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
47231dd7afcfSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->work_change);CHKERRQ(ierr);
4724b9b85e73SStefano Zampini   }
4725a717540cSStefano Zampini 
472672b8c272SStefano Zampini   if (!pcbddc->fake_change) {
47274f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
47284f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
47294f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
47304f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
4731019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
4732019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
4733019a44ceSStefano Zampini       pcbddc->local_primal_size++;
4734019a44ceSStefano Zampini     }
4735019a44ceSStefano Zampini 
4736019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
4737727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
4738727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
47399f47a83aSStefano 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);
4740c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
47410e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
47429f47a83aSStefano 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);
4743727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
4744727cdba6SStefano Zampini       }
47450e6343abSStefano Zampini     }
4746727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
4747b2566f29SBarry Smith     ierr = MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
474872b8c272SStefano Zampini   }
474972b8c272SStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
4750727cdba6SStefano Zampini 
4751a717540cSStefano Zampini   /* flush dbg viewer */
4752b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
4753b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4754b8ffe317SStefano Zampini   }
4755a717540cSStefano Zampini 
4756e310c8b4SStefano Zampini   /* free workspace */
4757a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
47584641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
475908122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
47609162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
47619162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
476208122e43SStefano Zampini   } else {
47639162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
47649162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
47659162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
476608122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
476708122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
47689162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
47699162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
477008122e43SStefano Zampini   }
4771674ae819SStefano Zampini   PetscFunctionReturn(0);
4772674ae819SStefano Zampini }
4773674ae819SStefano Zampini 
4774674ae819SStefano Zampini #undef __FUNCT__
4775674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
4776674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
4777674ae819SStefano Zampini {
4778674ae819SStefano Zampini   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
4779674ae819SStefano Zampini   PC_IS       *pcis = (PC_IS*)pc->data;
4780674ae819SStefano Zampini   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
478114f95afaSStefano Zampini   PetscInt    ierr,i,N;
4782674ae819SStefano Zampini 
4783674ae819SStefano Zampini   PetscFunctionBegin;
47848e61c736SStefano Zampini   /* Reset previously computed graph */
47858e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
4786674ae819SStefano Zampini   /* Init local Graph struct */
47877fb0e2dbSStefano Zampini   ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
47883bbff08aSStefano Zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,pcis->mapping,N);CHKERRQ(ierr);
4789674ae819SStefano Zampini 
4790575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
47915099eff2SStefano Zampini   if (pcbddc->mat_graph->nvtxs_csr && pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) {
47925099eff2SStefano 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);
4793575ad6abSStefano Zampini   }
47949577ea80SStefano Zampini 
4795674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
4796d4d8cf7bSStefano Zampini   if ( (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) && pcbddc->use_local_adj) {
47974d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
47984d379d7bSStefano Zampini     PetscInt  nvtxs;
4799e496cd5dSStefano Zampini     PetscBool flg_row=PETSC_FALSE;
4800674ae819SStefano Zampini 
48012fffb893SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
48022fffb893SStefano Zampini     if (flg_row) {
48034d379d7bSStefano Zampini       ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
4804b96c3477SStefano Zampini       pcbddc->computed_rowadj = PETSC_TRUE;
48052fffb893SStefano Zampini     }
48062fffb893SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
4807674ae819SStefano Zampini   }
48089b28b941SStefano Zampini   if (pcbddc->dbg_flag) {
48099b28b941SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4810674ae819SStefano Zampini   }
4811674ae819SStefano Zampini 
4812674ae819SStefano Zampini   /* Setup of Graph */
48134b2aedd3SStefano Zampini   pcbddc->mat_graph->commsizelimit = 0; /* don't use the COMM_SELF variant of the graph */
481414f95afaSStefano Zampini   ierr = PCBDDCGraphSetUp(pcbddc->mat_graph,pcbddc->vertex_size,pcbddc->NeumannBoundariesLocal,pcbddc->DirichletBoundariesLocal,pcbddc->n_ISForDofsLocal,pcbddc->ISForDofsLocal,pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
4815674ae819SStefano Zampini 
48164f1b2e48SStefano Zampini   /* attach info on disconnected subdomains if present */
48174f1b2e48SStefano Zampini   if (pcbddc->n_local_subs) {
48184f1b2e48SStefano Zampini     PetscInt *local_subs;
48194f1b2e48SStefano Zampini 
48204f1b2e48SStefano Zampini     ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
48214f1b2e48SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
48224f1b2e48SStefano Zampini       const PetscInt *idxs;
48234f1b2e48SStefano Zampini       PetscInt       nl,j;
48244f1b2e48SStefano Zampini 
48254f1b2e48SStefano Zampini       ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
48264f1b2e48SStefano Zampini       ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
48274f1b2e48SStefano Zampini       for (j=0;j<nl;j++) {
48284f1b2e48SStefano Zampini         local_subs[idxs[j]] = i;
48294f1b2e48SStefano Zampini       }
48304f1b2e48SStefano Zampini       ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
48314f1b2e48SStefano Zampini     }
48324f1b2e48SStefano Zampini     pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
48334f1b2e48SStefano Zampini     pcbddc->mat_graph->local_subs = local_subs;
48344f1b2e48SStefano Zampini   }
48354f1b2e48SStefano Zampini 
4836674ae819SStefano Zampini   /* Graph's connected components analysis */
4837674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
4838674ae819SStefano Zampini   PetscFunctionReturn(0);
4839674ae819SStefano Zampini }
4840674ae819SStefano Zampini 
4841dc456d91SStefano Zampini /* given an index sets possibly with holes, renumbers the indexes removing the holes */
4842674ae819SStefano Zampini #undef __FUNCT__
4843674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSubsetNumbering"
4844dc456d91SStefano Zampini PetscErrorCode PCBDDCSubsetNumbering(IS subset, IS subset_mult, PetscInt *N_n, IS *subset_n)
4845674ae819SStefano Zampini {
4846dc456d91SStefano Zampini   PetscSF        sf;
4847dc456d91SStefano Zampini   PetscLayout    map;
4848dc456d91SStefano Zampini   const PetscInt *idxs;
4849dc456d91SStefano Zampini   PetscInt       *leaf_data,*root_data,*gidxs;
4850dc456d91SStefano Zampini   PetscInt       N,n,i,lbounds[2],gbounds[2],Nl;
4851dc456d91SStefano Zampini   PetscInt       n_n,nlocals,start,first_index;
4852dc456d91SStefano Zampini   PetscMPIInt    commsize;
4853674ae819SStefano Zampini   PetscBool      first_found;
4854674ae819SStefano Zampini   PetscErrorCode ierr;
4855674ae819SStefano Zampini 
4856674ae819SStefano Zampini   PetscFunctionBegin;
4857dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset,&n);CHKERRQ(ierr);
4858dc456d91SStefano Zampini   if (subset_mult) {
4859dc456d91SStefano Zampini     PetscCheckSameComm(subset,1,subset_mult,2);
4860dc456d91SStefano Zampini     ierr = ISGetLocalSize(subset,&i);CHKERRQ(ierr);
4861dc456d91SStefano Zampini     if (i != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local subset and multiplicity sizes don't match! %d != %d",n,i);
4862674ae819SStefano Zampini   }
4863dc456d91SStefano Zampini   /* create workspace layout for computing global indices of subset */
4864dc456d91SStefano Zampini   ierr = ISGetIndices(subset,&idxs);CHKERRQ(ierr);
4865dc456d91SStefano Zampini   lbounds[0] = lbounds[1] = 0;
4866dc456d91SStefano Zampini   for (i=0;i<n;i++) {
4867dc456d91SStefano Zampini     if (idxs[i] < lbounds[0]) lbounds[0] = idxs[i];
4868dc456d91SStefano Zampini     else if (idxs[i] > lbounds[1]) lbounds[1] = idxs[i];
4869674ae819SStefano Zampini   }
4870dc456d91SStefano Zampini   lbounds[0] = -lbounds[0];
4871b2566f29SBarry Smith   ierr = MPIU_Allreduce(lbounds,gbounds,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
4872dc456d91SStefano Zampini   gbounds[0] = -gbounds[0];
4873dc456d91SStefano Zampini   N = gbounds[1] - gbounds[0] + 1;
4874dc456d91SStefano Zampini   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)subset),&map);CHKERRQ(ierr);
4875dc456d91SStefano Zampini   ierr = PetscLayoutSetBlockSize(map,1);CHKERRQ(ierr);
4876dc456d91SStefano Zampini   ierr = PetscLayoutSetSize(map,N);CHKERRQ(ierr);
4877dc456d91SStefano Zampini   ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
4878dc456d91SStefano Zampini   ierr = PetscLayoutGetLocalSize(map,&Nl);CHKERRQ(ierr);
4879dc456d91SStefano Zampini 
4880dc456d91SStefano Zampini   /* create sf : leaf_data == multiplicity of indexes, root data == global index in layout */
4881dc456d91SStefano Zampini   ierr = PetscMalloc2(n,&leaf_data,Nl,&root_data);CHKERRQ(ierr);
4882dc456d91SStefano Zampini   if (subset_mult) {
4883dc456d91SStefano Zampini     const PetscInt* idxs_mult;
4884dc456d91SStefano Zampini 
4885dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4886dc456d91SStefano Zampini     ierr = PetscMemcpy(leaf_data,idxs_mult,n*sizeof(PetscInt));CHKERRQ(ierr);
4887dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4888674ae819SStefano Zampini   } else {
4889dc456d91SStefano Zampini     for (i=0;i<n;i++) leaf_data[i] = 1;
4890674ae819SStefano Zampini   }
4891dc456d91SStefano Zampini   /* local size of new subset */
4892dc456d91SStefano Zampini   n_n = 0;
4893dc456d91SStefano Zampini   for (i=0;i<n;i++) n_n += leaf_data[i];
4894dc456d91SStefano Zampini 
4895dc456d91SStefano Zampini   /* global indexes in layout */
4896dc456d91SStefano Zampini   ierr = PetscMalloc1(n_n,&gidxs);CHKERRQ(ierr); /* allocating possibly extra space in gidxs which will be used later */
4897dc456d91SStefano Zampini   for (i=0;i<n;i++) gidxs[i] = idxs[i] - gbounds[0];
4898dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset,&idxs);CHKERRQ(ierr);
4899dc456d91SStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)subset),&sf);CHKERRQ(ierr);
4900dc456d91SStefano Zampini   ierr = PetscSFSetGraphLayout(sf,map,n,NULL,PETSC_COPY_VALUES,gidxs);CHKERRQ(ierr);
4901dc456d91SStefano Zampini   ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr);
4902dc456d91SStefano Zampini 
4903dc456d91SStefano Zampini   /* reduce from leaves to roots */
4904dc456d91SStefano Zampini   ierr = PetscMemzero(root_data,Nl*sizeof(PetscInt));CHKERRQ(ierr);
490564a8e5bcSStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
490664a8e5bcSStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
4907dc456d91SStefano Zampini 
4908dc456d91SStefano Zampini   /* count indexes in local part of layout */
4909674ae819SStefano Zampini   nlocals = 0;
4910674ae819SStefano Zampini   first_index = -1;
4911674ae819SStefano Zampini   first_found = PETSC_FALSE;
4912dc456d91SStefano Zampini   for (i=0;i<Nl;i++) {
4913dc456d91SStefano Zampini     if (!first_found && root_data[i]) {
4914674ae819SStefano Zampini       first_found = PETSC_TRUE;
4915674ae819SStefano Zampini       first_index = i;
4916674ae819SStefano Zampini     }
4917dc456d91SStefano Zampini     nlocals += root_data[i];
4918674ae819SStefano Zampini   }
4919dc456d91SStefano Zampini 
4920dc456d91SStefano Zampini   /* cumulative of number of indexes and size of subset without holes */
49215fa240b1SStefano Zampini #if defined(PETSC_HAVE_MPI_EXSCAN)
4922dc456d91SStefano Zampini   start = 0;
492364a8e5bcSStefano Zampini   ierr = MPI_Exscan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
49245fa240b1SStefano Zampini #else
492564a8e5bcSStefano Zampini   ierr = MPI_Scan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
49265fa240b1SStefano Zampini   start = start-nlocals;
49275fa240b1SStefano Zampini #endif
49285fa240b1SStefano Zampini 
4929dc456d91SStefano Zampini   if (N_n) { /* compute total size of new subset if requested */
4930dc456d91SStefano Zampini     *N_n = start + nlocals;
4931dc456d91SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)subset),&commsize);CHKERRQ(ierr);
4932dc456d91SStefano Zampini     ierr = MPI_Bcast(N_n,1,MPIU_INT,commsize-1,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
4933674ae819SStefano Zampini   }
49345fa240b1SStefano Zampini 
49355fa240b1SStefano Zampini   /* adapt root data with cumulative */
4936674ae819SStefano Zampini   if (first_found) {
4937dc456d91SStefano Zampini     PetscInt old_index;
4938dc456d91SStefano Zampini 
4939dc456d91SStefano Zampini     root_data[first_index] += start;
4940674ae819SStefano Zampini     old_index = first_index;
4941dc456d91SStefano Zampini     for (i=first_index+1;i<Nl;i++) {
4942dc456d91SStefano Zampini       if (root_data[i]) {
4943dc456d91SStefano Zampini         root_data[i] += root_data[old_index];
4944674ae819SStefano Zampini         old_index = i;
4945674ae819SStefano Zampini       }
4946674ae819SStefano Zampini     }
4947674ae819SStefano Zampini   }
4948dc456d91SStefano Zampini 
4949dc456d91SStefano Zampini   /* from roots to leaves */
4950dc456d91SStefano Zampini   ierr = PetscSFBcastBegin(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
4951dc456d91SStefano Zampini   ierr = PetscSFBcastEnd(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
4952dc456d91SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
4953dc456d91SStefano Zampini 
4954dc456d91SStefano Zampini   /* create new IS with global indexes without holes */
4955dc456d91SStefano Zampini   if (subset_mult) {
4956dc456d91SStefano Zampini     const PetscInt* idxs_mult;
4957dc456d91SStefano Zampini     PetscInt        cum;
4958dc456d91SStefano Zampini 
4959dc456d91SStefano Zampini     cum = 0;
4960dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4961dc456d91SStefano Zampini     for (i=0;i<n;i++) {
4962dc456d91SStefano Zampini       PetscInt j;
4963dc456d91SStefano Zampini       for (j=0;j<idxs_mult[i];j++) gidxs[cum++] = leaf_data[i] - idxs_mult[i] + j;
4964674ae819SStefano Zampini     }
4965dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4966674ae819SStefano Zampini   } else {
4967dc456d91SStefano Zampini     for (i=0;i<n;i++) {
4968dc456d91SStefano Zampini       gidxs[i] = leaf_data[i]-1;
4969674ae819SStefano Zampini     }
4970674ae819SStefano Zampini   }
4971dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)subset),n_n,gidxs,PETSC_OWN_POINTER,subset_n);CHKERRQ(ierr);
4972dc456d91SStefano Zampini   ierr = PetscFree2(leaf_data,root_data);CHKERRQ(ierr);
4973674ae819SStefano Zampini   PetscFunctionReturn(0);
4974674ae819SStefano Zampini }
49759a7d3425SStefano Zampini 
4976669cc0f4SStefano Zampini /* this implements stabilized Gram-Schmidt */
49779a7d3425SStefano Zampini #undef __FUNCT__
49789a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
49799a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
49809a7d3425SStefano Zampini {
49819a7d3425SStefano Zampini   PetscInt       i,j;
49829a7d3425SStefano Zampini   PetscScalar    *alphas;
49839a7d3425SStefano Zampini   PetscErrorCode ierr;
49849a7d3425SStefano Zampini 
49859a7d3425SStefano Zampini   PetscFunctionBegin;
4986785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
49879a7d3425SStefano Zampini   for (i=0;i<n;i++) {
49889a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
4989669cc0f4SStefano Zampini     ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],alphas);CHKERRQ(ierr);
4990669cc0f4SStefano Zampini     for (j=0;j<n-i-1;j++) alphas[j] = PetscConj(-alphas[j]);
4991669cc0f4SStefano Zampini     ierr = VecMAXPY(vecs[j],n-i-1,alphas,vecs+i);CHKERRQ(ierr);
49929a7d3425SStefano Zampini   }
49939a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
49949a7d3425SStefano Zampini   PetscFunctionReturn(0);
49959a7d3425SStefano Zampini }
49969a7d3425SStefano Zampini 
4997e7931f94SStefano Zampini #undef __FUNCT__
499870cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
499957de7509SStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
5000e7931f94SStefano Zampini {
500157de7509SStefano Zampini   Mat            A;
5002e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
5003e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
500452e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
500552e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
500627b6a85dSStefano Zampini   PetscInt       im_active,active_procs,n,i,j,local_size,threshold = 2;
500757de7509SStefano Zampini   PetscInt       void_procs,*procs_candidates = NULL;
500827b6a85dSStefano Zampini   PetscInt       xadj_count, *count;
500927b6a85dSStefano Zampini   PetscBool      ismatis,use_vwgt=PETSC_FALSE;
501027b6a85dSStefano Zampini   PetscSubcomm   psubcomm;
501127b6a85dSStefano Zampini   MPI_Comm       subcomm;
501252e5ac9dSStefano Zampini   PetscErrorCode ierr;
5013a57a6d2fSStefano Zampini 
5014e7931f94SStefano Zampini   PetscFunctionBegin;
501557de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
501657de7509SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
501757de7509SStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
501857de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
501957de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
502057de7509SStefano Zampini   if (*n_subdomains <=0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %d\n",*n_subdomains);
502157de7509SStefano Zampini 
502257de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
502357de7509SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
502457de7509SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
502557de7509SStefano Zampini   ierr = MatISGetLocalMat(mat,&A);CHKERRQ(ierr);
502657de7509SStefano Zampini   ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
502757de7509SStefano Zampini   im_active = !!(n);
502857de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
502957de7509SStefano Zampini   void_procs = size - active_procs;
503057de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
503157de7509SStefano Zampini   if (void_procs) {
503257de7509SStefano Zampini     PetscInt ncand;
503357de7509SStefano Zampini 
503457de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
503557de7509SStefano Zampini     ierr = PetscMalloc1(size,&procs_candidates);CHKERRQ(ierr);
503657de7509SStefano Zampini     ierr = MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
503757de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
503857de7509SStefano Zampini       if (!procs_candidates[i]) {
503957de7509SStefano Zampini         procs_candidates[ncand++] = i;
504057de7509SStefano Zampini       }
504157de7509SStefano Zampini     }
504257de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
504357de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
504457de7509SStefano Zampini   }
504557de7509SStefano Zampini 
504657de7509SStefano Zampini   /* number of subdomains requested greater than active processes -> just shift the matrix */
504757de7509SStefano Zampini   if (active_procs < *n_subdomains) {
504857de7509SStefano Zampini     PetscInt issize,isidx;
504957de7509SStefano Zampini     if (im_active) {
505057de7509SStefano Zampini       issize = 1;
505157de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
505257de7509SStefano Zampini         isidx = procs_candidates[rank];
505357de7509SStefano Zampini       } else {
505457de7509SStefano Zampini         isidx = rank;
505557de7509SStefano Zampini       }
505657de7509SStefano Zampini     } else {
505757de7509SStefano Zampini       issize = 0;
505857de7509SStefano Zampini       isidx = -1;
505957de7509SStefano Zampini     }
506057de7509SStefano Zampini     *n_subdomains = active_procs;
506157de7509SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends);CHKERRQ(ierr);
5062daf8a457SStefano Zampini     ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
506357de7509SStefano Zampini     PetscFunctionReturn(0);
506457de7509SStefano Zampini   }
5065c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
5066c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
506727b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
5068e7931f94SStefano Zampini 
5069e7931f94SStefano Zampini   /* Get info on mapping */
50703bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&local_size);CHKERRQ(ierr);
50713bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
5072e7931f94SStefano Zampini 
5073e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
5074785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
5075e7931f94SStefano Zampini   xadj[0] = 0;
5076e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
5077785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
5078785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
507927b6a85dSStefano Zampini   ierr = PetscCalloc1(local_size,&count);CHKERRQ(ierr);
508027b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
508127b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
508227b6a85dSStefano Zampini       count[shared[i][j]] += 1;
5083e7931f94SStefano Zampini 
508427b6a85dSStefano Zampini   xadj_count = 0;
50852b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
508627b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
508727b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
5088d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
5089d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
5090d023bfaeSStefano Zampini         xadj_count++;
509127b6a85dSStefano Zampini         break;
509227b6a85dSStefano Zampini       }
5093e7931f94SStefano Zampini     }
5094e7931f94SStefano Zampini   }
5095d023bfaeSStefano Zampini   xadj[1] = xadj_count;
509627b6a85dSStefano Zampini   ierr = PetscFree(count);CHKERRQ(ierr);
50973bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
5098e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
5099e7931f94SStefano Zampini 
51003837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
5101e7931f94SStefano Zampini 
510227b6a85dSStefano Zampini   /* Restrict work on active processes only */
510327b6a85dSStefano Zampini   ierr = PetscMPIIntCast(im_active,&color);CHKERRQ(ierr);
510427b6a85dSStefano Zampini   if (void_procs) {
510527b6a85dSStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm);CHKERRQ(ierr);
510627b6a85dSStefano Zampini     ierr = PetscSubcommSetNumber(psubcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
510727b6a85dSStefano Zampini     ierr = PetscSubcommSetTypeGeneral(psubcomm,color,rank);CHKERRQ(ierr);
510827b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
510927b6a85dSStefano Zampini   } else {
511027b6a85dSStefano Zampini     psubcomm = NULL;
511127b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
511227b6a85dSStefano Zampini   }
511327b6a85dSStefano Zampini 
511427b6a85dSStefano Zampini   v_wgt = NULL;
511527b6a85dSStefano Zampini   if (!color) {
5116e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
5117e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
5118e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
5119c8587f34SStefano Zampini   } else {
512052e5ac9dSStefano Zampini     Mat             subdomain_adj;
512152e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
512252e5ac9dSStefano Zampini     MatPartitioning partitioner;
512327b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
512452e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
512557de7509SStefano Zampini     PetscMPIInt     size;
5126b0c7d250SStefano Zampini     PetscBool       aggregate;
5127b0c7d250SStefano Zampini 
512827b6a85dSStefano Zampini     ierr = MPI_Comm_size(subcomm,&size);CHKERRQ(ierr);
512927b6a85dSStefano Zampini     if (void_procs) {
513027b6a85dSStefano Zampini       PetscInt prank = rank;
5131785e854fSJed Brown       ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
513227b6a85dSStefano Zampini       ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm);CHKERRQ(ierr);
5133e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
5134e7931f94SStefano Zampini         ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
5135c8587f34SStefano Zampini       }
5136e7931f94SStefano Zampini       ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
513727b6a85dSStefano Zampini     } else {
513827b6a85dSStefano Zampini       oldranks = NULL;
513927b6a85dSStefano Zampini     }
5140b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
514127b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
5142b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
5143b0c7d250SStefano Zampini       PetscMPIInt nrank;
5144b0c7d250SStefano Zampini       PetscScalar *vals;
5145b0c7d250SStefano Zampini 
514627b6a85dSStefano Zampini       ierr = MPI_Comm_rank(subcomm,&nrank);CHKERRQ(ierr);
5147b0c7d250SStefano Zampini       lrows = 0;
5148b0c7d250SStefano Zampini       if (nrank<redprocs) {
5149b0c7d250SStefano Zampini         lrows = size/redprocs;
5150b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
5151b0c7d250SStefano Zampini       }
515227b6a85dSStefano Zampini       ierr = MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
5153b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
5154b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
5155b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
5156b0c7d250SStefano Zampini       row = nrank;
5157b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
5158b0c7d250SStefano Zampini       cols = adjncy;
5159b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
5160b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
5161b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
5162b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5163b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
516452e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
516552e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
516652e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
5167b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
516827b6a85dSStefano Zampini       if (use_vwgt) {
516927b6a85dSStefano Zampini         Vec               v;
517027b6a85dSStefano Zampini         const PetscScalar *array;
517127b6a85dSStefano Zampini         PetscInt          nl;
517227b6a85dSStefano Zampini 
517327b6a85dSStefano Zampini         ierr = MatCreateVecs(subdomain_adj,&v,NULL);CHKERRQ(ierr);
517427b6a85dSStefano Zampini         ierr = VecSetValue(v,row,(PetscScalar)local_size,INSERT_VALUES);CHKERRQ(ierr);
517527b6a85dSStefano Zampini         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
517627b6a85dSStefano Zampini         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
517727b6a85dSStefano Zampini         ierr = VecGetLocalSize(v,&nl);CHKERRQ(ierr);
517827b6a85dSStefano Zampini         ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
517927b6a85dSStefano Zampini         ierr = PetscMalloc1(nl,&v_wgt);CHKERRQ(ierr);
518022db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
518127b6a85dSStefano Zampini         ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
518227b6a85dSStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
518327b6a85dSStefano Zampini       }
5184b0c7d250SStefano Zampini     } else {
518527b6a85dSStefano Zampini       ierr = MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
518627b6a85dSStefano Zampini       if (use_vwgt) {
518727b6a85dSStefano Zampini         ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
518827b6a85dSStefano Zampini         v_wgt[0] = local_size;
518927b6a85dSStefano Zampini       }
5190b0c7d250SStefano Zampini     }
519122b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
5192e7931f94SStefano Zampini 
5193e7931f94SStefano Zampini     /* Partition */
519427b6a85dSStefano Zampini     ierr = MatPartitioningCreate(subcomm,&partitioner);CHKERRQ(ierr);
5195e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
519627b6a85dSStefano Zampini     if (v_wgt) {
5197e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
5198c8587f34SStefano Zampini     }
519957de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
520057de7509SStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,*n_subdomains);CHKERRQ(ierr);
5201e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
5202e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
520322b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
5204e7931f94SStefano Zampini 
520552e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
520652e5ac9dSStefano Zampini     ierr = PCBDDCSubsetNumbering(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
520752e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
520852e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
520957de7509SStefano Zampini     if (!aggregate) {
521057de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
521127b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
521227b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
521327b6a85dSStefano Zampini #endif
521457de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
521527b6a85dSStefano Zampini       } else if (oldranks) {
5216b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
521727b6a85dSStefano Zampini       } else {
521827b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
521957de7509SStefano Zampini       }
522028143c3dSStefano Zampini     } else {
5221b0c7d250SStefano Zampini       PetscInt    idxs[1];
5222b0c7d250SStefano Zampini       PetscMPIInt tag;
5223b0c7d250SStefano Zampini       MPI_Request *reqs;
5224b0c7d250SStefano Zampini 
5225b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
5226b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
5227b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
522827b6a85dSStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]);CHKERRQ(ierr);
522928143c3dSStefano Zampini       }
523027b6a85dSStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE);CHKERRQ(ierr);
5231b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5232b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
523357de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
523427b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
523527b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
523627b6a85dSStefano Zampini #endif
523757de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[idxs[0]]];
523827b6a85dSStefano Zampini       } else if (oldranks) {
5239b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[idxs[0]];
524027b6a85dSStefano Zampini       } else {
524127b6a85dSStefano Zampini         ranks_send_to_idx[0] = idxs[0];
5242e7931f94SStefano Zampini       }
524357de7509SStefano Zampini     }
524452e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5245e7931f94SStefano Zampini     /* clean up */
5246e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
524752e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
5248e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
5249e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
5250e7931f94SStefano Zampini   }
525127b6a85dSStefano Zampini   ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr);
525257de7509SStefano Zampini   ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
5253e7931f94SStefano Zampini 
5254e7931f94SStefano Zampini   /* assemble parallel IS for sends */
5255e7931f94SStefano Zampini   i = 1;
525627b6a85dSStefano Zampini   if (!color) i=0;
525757de7509SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends);CHKERRQ(ierr);
5258e7931f94SStefano Zampini   PetscFunctionReturn(0);
5259e7931f94SStefano Zampini }
5260e7931f94SStefano Zampini 
5261e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
5262e7931f94SStefano Zampini 
5263e7931f94SStefano Zampini #undef __FUNCT__
5264e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
52651ae86dd6SStefano Zampini PetscErrorCode MatISSubassemble(Mat mat, IS is_sends, PetscInt n_subdomains, PetscBool restrict_comm, PetscBool restrict_full, PetscBool reuse, Mat *mat_n, PetscInt nis, IS isarray[], PetscInt nvecs, Vec nnsp_vec[])
5266e7931f94SStefano Zampini {
526770cf5478SStefano Zampini   Mat                    local_mat;
5268e7931f94SStefano Zampini   IS                     is_sends_internal;
52699d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
52701ae86dd6SStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals,buf_size_vecs;
52719d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
5272e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
5273e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
5274e7931f94SStefano Zampini   const PetscInt*        is_indices;
5275e7931f94SStefano Zampini   MatType                new_local_type;
5276e7931f94SStefano Zampini   /* buffers */
5277e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
527828143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
52799d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
5280e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
52811ae86dd6SStefano Zampini   PetscScalar            *ptr_vecs,*send_buffer_vecs,*recv_buffer_vecs;
5282e7931f94SStefano Zampini   /* MPI */
528328143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
528428143c3dSStefano Zampini   PetscSubcomm           subcomm;
5285e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
528628143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
528728143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
52881ae86dd6SStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,tag_vecs,source_dest;
52891ae86dd6SStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals,*send_req_vecs;
52901ae86dd6SStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals,*recv_req_vecs;
5291e7931f94SStefano Zampini   PetscErrorCode         ierr;
5292e7931f94SStefano Zampini 
5293e7931f94SStefano Zampini   PetscFunctionBegin;
529457de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5295e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
529628143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
529757de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
529857de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
529957de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
530057de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
530157de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
53021ae86dd6SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nvecs,10);
53031ae86dd6SStefano Zampini   if (nvecs) {
53041ae86dd6SStefano Zampini     if (nvecs > 1) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Just 1 vector supported");
53051ae86dd6SStefano Zampini     PetscValidHeaderSpecific(nnsp_vec[0],VEC_CLASSID,11);
53061ae86dd6SStefano Zampini   }
530757de7509SStefano Zampini   /* further checks */
5308e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
5309e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
5310e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
5311e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
5312e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
531357de7509SStefano Zampini   if (reuse && *mat_n) {
531470cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
531557de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
531670cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
531728143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
531870cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
531970cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
532070cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
532170cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
532270cf5478SStefano Zampini   }
5323e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
5324e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
532557de7509SStefano Zampini 
5326e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
5327e7931f94SStefano Zampini   if (!is_sends) {
532828143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
532957de7509SStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL);CHKERRQ(ierr);
5330c8587f34SStefano Zampini   } else {
5331e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
5332e7931f94SStefano Zampini     is_sends_internal = is_sends;
5333c8587f34SStefano Zampini   }
5334e7931f94SStefano Zampini 
5335e7931f94SStefano Zampini   /* get comm */
5336a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
5337e7931f94SStefano Zampini 
5338e7931f94SStefano Zampini   /* compute number of sends */
5339e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
5340e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
5341e7931f94SStefano Zampini 
5342e7931f94SStefano Zampini   /* compute number of receives */
5343e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
5344785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
5345e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
5346e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
5347e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
5348e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
5349e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
5350e7931f94SStefano Zampini 
535128143c3dSStefano Zampini   /* restrict comm if requested */
535228143c3dSStefano Zampini   subcomm = 0;
535328143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
535428143c3dSStefano Zampini   if (restrict_comm) {
5355779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
5356779c1cceSStefano Zampini 
535728143c3dSStefano Zampini     color = 0;
535853a05cb3SStefano Zampini     if (restrict_full) {
535953a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
536053a05cb3SStefano Zampini     } else {
536153a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
536253a05cb3SStefano Zampini     }
5363b2566f29SBarry Smith     ierr = MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
536428143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
536528143c3dSStefano Zampini     /* check if reuse has been requested */
536657de7509SStefano Zampini     if (reuse) {
536728143c3dSStefano Zampini       if (*mat_n) {
536828143c3dSStefano Zampini         PetscMPIInt subcommsize2;
536928143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
537028143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
537128143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
537228143c3dSStefano Zampini       } else {
537328143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
537428143c3dSStefano Zampini       }
537528143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
5376779c1cceSStefano Zampini       PetscMPIInt rank;
5377779c1cceSStefano Zampini 
5378779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
537928143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
538028143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
538128143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
5382306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
538328143c3dSStefano Zampini     }
538428143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
538528143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
538628143c3dSStefano Zampini   } else {
538728143c3dSStefano Zampini     comm_n = comm;
538828143c3dSStefano Zampini   }
538928143c3dSStefano Zampini 
5390e7931f94SStefano Zampini   /* prepare send/receive buffers */
5391785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
5392e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
5393785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
5394e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
539528143c3dSStefano Zampini   if (nis) {
5396854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
539728143c3dSStefano Zampini   }
5398e7931f94SStefano Zampini 
539928143c3dSStefano Zampini   /* Get data from local matrices */
54006c4ed002SBarry Smith   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
5401e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
5402e7931f94SStefano Zampini     /*
5403e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
5404e7931f94SStefano Zampini        send_buffer_idxs should contain:
5405e7931f94SStefano Zampini        - MatType_PRIVATE type
5406e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
5407e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
5408e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
5409e7931f94SStefano Zampini     */
54106c4ed002SBarry Smith   else {
5411e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
54123bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
5413854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
5414e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
5415e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
54163bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
5417e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
54183bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
5419e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
5420e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
5421e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
5422e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
5423c8587f34SStefano Zampini     }
5424c8587f34SStefano Zampini   }
5425e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
542628143c3dSStefano Zampini   /* additional is (if any) */
542728143c3dSStefano Zampini   if (nis) {
542828143c3dSStefano Zampini     PetscMPIInt psum;
542928143c3dSStefano Zampini     PetscInt j;
543028143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
543128143c3dSStefano Zampini       PetscInt plen;
543228143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
543328143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
543428143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
543528143c3dSStefano Zampini     }
5436854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
543728143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
543828143c3dSStefano Zampini       PetscInt plen;
543928143c3dSStefano Zampini       const PetscInt *is_array_idxs;
544028143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
544128143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
544228143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
544328143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
544428143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
544528143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
544628143c3dSStefano Zampini     }
544728143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
544828143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
544928143c3dSStefano Zampini     }
545028143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
545128143c3dSStefano Zampini   }
545228143c3dSStefano Zampini 
5453e7931f94SStefano Zampini   buf_size_idxs = 0;
5454e7931f94SStefano Zampini   buf_size_vals = 0;
545528143c3dSStefano Zampini   buf_size_idxs_is = 0;
54561ae86dd6SStefano Zampini   buf_size_vecs = 0;
5457e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
5458e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
5459e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
546028143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
54611ae86dd6SStefano Zampini     if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i];
5462e7931f94SStefano Zampini   }
5463785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
5464785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
546595ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
54661ae86dd6SStefano Zampini   ierr = PetscMalloc1(buf_size_vecs,&recv_buffer_vecs);CHKERRQ(ierr);
5467e7931f94SStefano Zampini 
5468e7931f94SStefano Zampini   /* get new tags for clean communications */
5469e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
5470e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
547128143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
54721ae86dd6SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vecs);CHKERRQ(ierr);
5473e7931f94SStefano Zampini 
5474e7931f94SStefano Zampini   /* allocate for requests */
5475785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
5476785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
547795ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
54781ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_vecs);CHKERRQ(ierr);
5479785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
5480785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
548195ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
54821ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_vecs);CHKERRQ(ierr);
5483e7931f94SStefano Zampini 
5484e7931f94SStefano Zampini   /* communications */
5485e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
5486e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
548728143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
54881ae86dd6SStefano Zampini   ptr_vecs = recv_buffer_vecs;
5489e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
5490e7931f94SStefano Zampini     source_dest = onodes[i];
5491e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
5492e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
5493e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5494e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
549528143c3dSStefano Zampini     if (nis) {
549657de7509SStefano Zampini       source_dest = onodes_is[i];
549728143c3dSStefano 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);
549828143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
549928143c3dSStefano Zampini     }
55001ae86dd6SStefano Zampini     if (nvecs) {
55011ae86dd6SStefano Zampini       source_dest = onodes[i];
55021ae86dd6SStefano Zampini       ierr = MPI_Irecv(ptr_vecs,olengths_idxs[i]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&recv_req_vecs[i]);CHKERRQ(ierr);
55031ae86dd6SStefano Zampini       ptr_vecs += olengths_idxs[i]-2;
55041ae86dd6SStefano Zampini     }
5505e7931f94SStefano Zampini   }
5506e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
5507e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
5508e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
5509e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
551028143c3dSStefano Zampini     if (nis) {
551128143c3dSStefano 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);
551228143c3dSStefano Zampini     }
55131ae86dd6SStefano Zampini     if (nvecs) {
55141ae86dd6SStefano Zampini       ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
55151ae86dd6SStefano Zampini       ierr = MPI_Isend(send_buffer_vecs,ilengths_idxs[source_dest]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&send_req_vecs[i]);CHKERRQ(ierr);
55161ae86dd6SStefano Zampini     }
5517e7931f94SStefano Zampini   }
5518e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
5519e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
5520e7931f94SStefano Zampini 
5521e7931f94SStefano Zampini   /* assemble new l2g map */
5522e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5523e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
55249d30be91SStefano Zampini   new_local_rows = 0;
5525e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
55269d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
5527e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5528e7931f94SStefano Zampini   }
55299d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
5530e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
55319d30be91SStefano Zampini   new_local_rows = 0;
5532e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
55339d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
55349d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
5535e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5536e7931f94SStefano Zampini   }
55379d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
55389d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
5539e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
5540e7931f94SStefano Zampini 
5541e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
5542e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
5543e7931f94SStefano 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) */
5544e7931f94SStefano Zampini   if (n_recvs) {
554528143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
5546e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
5547e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
5548e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
5549e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
5550e7931f94SStefano Zampini         break;
5551e7931f94SStefano Zampini       }
5552e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
5553e7931f94SStefano Zampini     }
5554e7931f94SStefano Zampini     switch (new_local_type_private) {
555528143c3dSStefano Zampini       case MATDENSE_PRIVATE:
555628143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
5557e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
5558e7931f94SStefano Zampini           bs = 1;
555928143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
556028143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
556128143c3dSStefano Zampini           bs = 1;
556228143c3dSStefano Zampini         }
5563e7931f94SStefano Zampini         break;
5564e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
5565e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
5566e7931f94SStefano Zampini         bs = 1;
5567e7931f94SStefano Zampini         break;
5568e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
5569e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
5570e7931f94SStefano Zampini         break;
5571e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
5572e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
5573e7931f94SStefano Zampini         break;
5574e7931f94SStefano Zampini       default:
55759d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
5576e7931f94SStefano Zampini         break;
5577e7931f94SStefano Zampini     }
557828143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
557928143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
558028143c3dSStefano Zampini     bs = 1;
5581e7931f94SStefano Zampini   }
5582e7931f94SStefano Zampini 
558370cf5478SStefano Zampini   /* create MATIS object if needed */
558457de7509SStefano Zampini   if (!reuse) {
5585e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
5586e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
558770cf5478SStefano Zampini   } else {
558870cf5478SStefano Zampini     /* it also destroys the local matrices */
558957de7509SStefano Zampini     if (*mat_n) {
559070cf5478SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
559157de7509SStefano Zampini     } else { /* this is a fake object */
559257de7509SStefano Zampini       ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
559357de7509SStefano Zampini     }
559470cf5478SStefano Zampini   }
559570cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
5596e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
55979d30be91SStefano Zampini 
55989d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
55999d30be91SStefano Zampini 
56009d30be91SStefano Zampini   /* Global to local map of received indices */
56019d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
56029d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
56039d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
56049d30be91SStefano Zampini 
56059d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
56069d30be91SStefano Zampini   buf_size_idxs = 0;
56079d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
56089d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
56099d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
56109d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
56119d30be91SStefano Zampini   }
56129d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
56139d30be91SStefano Zampini 
56149d30be91SStefano Zampini   /* set preallocation */
56159d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
56169d30be91SStefano Zampini   if (!newisdense) {
56179d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
56189d30be91SStefano Zampini 
56199d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
56209d30be91SStefano Zampini     if (n_recvs) {
56219d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
56229d30be91SStefano Zampini     }
56239d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
56249d30be91SStefano Zampini       PetscInt j;
56259d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
56269d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
56279d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
56289d30be91SStefano Zampini         }
56299d30be91SStefano Zampini       } else {
56309d30be91SStefano Zampini         /* TODO */
56319d30be91SStefano Zampini       }
56329d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
56339d30be91SStefano Zampini     }
56349d30be91SStefano Zampini     if (new_local_nnz) {
56359d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
56369d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
56379d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
56389d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
56399d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
56409d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
56419d30be91SStefano Zampini     } else {
56429d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
56439d30be91SStefano Zampini     }
56449d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
56459d30be91SStefano Zampini   } else {
56469d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
56479d30be91SStefano Zampini   }
5648e7931f94SStefano Zampini 
5649e7931f94SStefano Zampini   /* set values */
5650e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
56519d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
5652e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
5653e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
5654e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
56559d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
5656e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
5657e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
5658e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
565928143c3dSStefano Zampini     } else {
566028143c3dSStefano Zampini       /* TODO */
5661e7931f94SStefano Zampini     }
5662e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5663e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
5664e7931f94SStefano Zampini   }
5665e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5666e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
566770cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
566870cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
56699d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
5670e7931f94SStefano Zampini 
5671dfd14d43SStefano Zampini #if 0
567228143c3dSStefano Zampini   if (!restrict_comm) { /* check */
5673e7931f94SStefano Zampini     Vec       lvec,rvec;
5674e7931f94SStefano Zampini     PetscReal infty_error;
5675e7931f94SStefano Zampini 
56762a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
5677e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
5678e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
5679e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
568070cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
5681e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
5682e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
5683e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
5684e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
5685e7931f94SStefano Zampini   }
568628143c3dSStefano Zampini #endif
5687e7931f94SStefano Zampini 
568828143c3dSStefano Zampini   /* assemble new additional is (if any) */
568928143c3dSStefano Zampini   if (nis) {
569028143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
569128143c3dSStefano Zampini 
569228143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5693854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
569428143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
569528143c3dSStefano Zampini     psum = 0;
569628143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
569728143c3dSStefano Zampini       for (j=0;j<nis;j++) {
569828143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
569928143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
570028143c3dSStefano Zampini         psum += plen;
570128143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
570228143c3dSStefano Zampini       }
570328143c3dSStefano Zampini     }
5704854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
5705854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
570628143c3dSStefano Zampini     for (i=1;i<nis;i++) {
570728143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
570828143c3dSStefano Zampini     }
570928143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
571028143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
571128143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
571228143c3dSStefano Zampini       for (j=0;j<nis;j++) {
571328143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
571428143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
571528143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
571628143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
571728143c3dSStefano Zampini       }
571828143c3dSStefano Zampini     }
571928143c3dSStefano Zampini     for (i=0;i<nis;i++) {
572028143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
572128143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
572228143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
572328143c3dSStefano Zampini     }
572428143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
572528143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
572628143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
572728143c3dSStefano Zampini   }
5728e7931f94SStefano Zampini   /* free workspace */
572928143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
5730e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5731e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
5732e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5733e7931f94SStefano Zampini   if (isdense) {
5734e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
5735e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
5736e7931f94SStefano Zampini   } else {
5737e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
5738e7931f94SStefano Zampini   }
573928143c3dSStefano Zampini   if (nis) {
574028143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
574128143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
574228143c3dSStefano Zampini   }
57431ae86dd6SStefano Zampini 
57441ae86dd6SStefano Zampini   if (nvecs) {
57451ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
57461ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
57471ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
57481ae86dd6SStefano Zampini     ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
57491ae86dd6SStefano Zampini     ierr = VecCreate(comm_n,&nnsp_vec[0]);CHKERRQ(ierr);
57501ae86dd6SStefano Zampini     ierr = VecSetSizes(nnsp_vec[0],new_local_rows,PETSC_DECIDE);CHKERRQ(ierr);
57511ae86dd6SStefano Zampini     ierr = VecSetType(nnsp_vec[0],VECSTANDARD);CHKERRQ(ierr);
57521ae86dd6SStefano Zampini     /* set values */
57531ae86dd6SStefano Zampini     ptr_vals = recv_buffer_vecs;
57541ae86dd6SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
57551ae86dd6SStefano Zampini     ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
57561ae86dd6SStefano Zampini     for (i=0;i<n_recvs;i++) {
57571ae86dd6SStefano Zampini       PetscInt j;
57581ae86dd6SStefano Zampini       for (j=0;j<*(ptr_idxs+1);j++) {
57591ae86dd6SStefano Zampini         send_buffer_vecs[*(ptr_idxs+2+j)] += *(ptr_vals + j);
57601ae86dd6SStefano Zampini       }
57611ae86dd6SStefano Zampini       ptr_idxs += olengths_idxs[i];
57621ae86dd6SStefano Zampini       ptr_vals += olengths_idxs[i]-2;
57631ae86dd6SStefano Zampini     }
57641ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
57651ae86dd6SStefano Zampini     ierr = VecAssemblyBegin(nnsp_vec[0]);CHKERRQ(ierr);
57661ae86dd6SStefano Zampini     ierr = VecAssemblyEnd(nnsp_vec[0]);CHKERRQ(ierr);
57671ae86dd6SStefano Zampini   }
57681ae86dd6SStefano Zampini 
57691ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_vecs);CHKERRQ(ierr);
57701ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
5771e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
5772e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
57731ae86dd6SStefano Zampini   ierr = PetscFree(recv_req_vecs);CHKERRQ(ierr);
577428143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
5775e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
5776e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
57771ae86dd6SStefano Zampini   ierr = PetscFree(send_req_vecs);CHKERRQ(ierr);
577828143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
5779e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
5780e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
5781e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
5782e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
5783e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
578428143c3dSStefano Zampini   if (nis) {
578528143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
578628143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
578728143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
578828143c3dSStefano Zampini   }
578928143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
579028143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
579128143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
579228143c3dSStefano Zampini     for (i=0;i<nis;i++) {
579328143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
579428143c3dSStefano Zampini     }
57951ae86dd6SStefano Zampini     if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */
57961ae86dd6SStefano Zampini       ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
57971ae86dd6SStefano Zampini     }
579853a05cb3SStefano Zampini     *mat_n = NULL;
579928143c3dSStefano Zampini   }
5800e7931f94SStefano Zampini   PetscFunctionReturn(0);
5801e7931f94SStefano Zampini }
5802a57a6d2fSStefano Zampini 
580312edc857SStefano Zampini /* temporary hack into ksp private data structure */
5804af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
580512edc857SStefano Zampini 
5806c8587f34SStefano Zampini #undef __FUNCT__
5807c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
5808c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
5809c8587f34SStefano Zampini {
5810c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
5811c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
581220a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
58131ae86dd6SStefano Zampini   Mat                    coarsedivudotp = NULL;
58149881197aSStefano Zampini   MatNullSpace           CoarseNullSpace = NULL;
581520a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
58166e683305SStefano Zampini   IS                     coarse_is,*isarray;
58176e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
581830368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
5819f9eb5b7dSStefano Zampini   PC                     pc_temp;
5820c8587f34SStefano Zampini   PCType                 coarse_pc_type;
5821c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
5822f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
58234f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
58246e683305SStefano Zampini   Mat                    t_coarse_mat_is;
582557de7509SStefano Zampini   PetscInt               ncoarse;
582668457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
582722bc73bbSStefano Zampini   PetscScalar            *array;
582857de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
582957de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
58309881197aSStefano Zampini   PetscErrorCode         ierr;
5831fdc09c96SStefano Zampini 
5832c8587f34SStefano Zampini   PetscFunctionBegin;
5833c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
583468457ee5SStefano 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 */
5835fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
58365a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
5837fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
5838f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
5839f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
5840f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
5841fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
584251bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
584351bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
5844dc4bcba2SStefano Zampini         PC        pc;
5845dc4bcba2SStefano Zampini         PetscBool isbddc;
5846dc4bcba2SStefano Zampini 
5847dc4bcba2SStefano Zampini         /* temporary workaround since PCBDDC does not have a reset method so far */
5848dc4bcba2SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
5849dc4bcba2SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
5850dc4bcba2SStefano Zampini         if (isbddc) {
585163c961adSStefano Zampini           ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
585263c961adSStefano Zampini         } else {
5853727cdba6SStefano Zampini           ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
585463c961adSStefano Zampini         }
5855fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
5856fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
5857fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
5858f4ddd8eeSStefano Zampini       }
5859fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
5860fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
5861f4ddd8eeSStefano Zampini     }
586270cf5478SStefano Zampini     /* reset any subassembling information */
586357de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
586470cf5478SStefano Zampini       ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
586557de7509SStefano Zampini     }
58666e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
5867fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
5868f4ddd8eeSStefano Zampini   }
586957de7509SStefano Zampini   /* assemble coarse matrix */
587057de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
587157de7509SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
587257de7509SStefano Zampini     ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
587357de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
587418a45a71SStefano Zampini   } else {
587557de7509SStefano Zampini     coarse_mat = NULL;
587657de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
58776e683305SStefano Zampini   }
5878e7931f94SStefano Zampini 
5879abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
5880abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
5881abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
5882abbbba34SStefano Zampini 
5883abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
588422bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
588522bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
588622bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
588722bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
5888e176bc59SStefano 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);
58896e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
58906e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
58916e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5892abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
5893abbbba34SStefano Zampini 
589457de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
589557de7509SStefano Zampini   im_active = !!(pcis->n);
589657de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
589757de7509SStefano Zampini 
589857de7509SStefano Zampini   /* determine number of process partecipating to coarse solver and compute subassembling pattern */
589957de7509SStefano Zampini   /* restr : whether if we want to exclude senders (which are not receivers) from the subassembling pattern */
590057de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
590157de7509SStefano Zampini   coarse_mat_is = NULL;
590257de7509SStefano Zampini   multilevel_allowed = PETSC_FALSE;
590357de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
590457de7509SStefano Zampini   full_restr = PETSC_TRUE;
59051ae86dd6SStefano Zampini   pcbddc->coarse_eqs_per_proc = PetscMin(PetscMax(pcbddc->coarse_size,1),pcbddc->coarse_eqs_per_proc);
590657de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
590757de7509SStefano Zampini   if (multilevel_requested) {
590857de7509SStefano Zampini     ncoarse = active_procs/pcbddc->coarsening_ratio;
590957de7509SStefano Zampini     restr = PETSC_FALSE;
591057de7509SStefano Zampini     full_restr = PETSC_FALSE;
591157de7509SStefano Zampini   } else {
591257de7509SStefano Zampini     ncoarse = pcbddc->coarse_size/pcbddc->coarse_eqs_per_proc;
591357de7509SStefano Zampini     restr = PETSC_TRUE;
591457de7509SStefano Zampini     full_restr = PETSC_TRUE;
591557de7509SStefano Zampini   }
59164b2aedd3SStefano Zampini   if (!pcbddc->coarse_size) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE;
591757de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
591857de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
5919*a198735bSStefano Zampini     if (pcbddc->coarsening_ratio > 1) {
592057de7509SStefano Zampini       ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
5921*a198735bSStefano Zampini     } else {
5922*a198735bSStefano Zampini       PetscMPIInt size,rank;
5923*a198735bSStefano Zampini       ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
5924*a198735bSStefano Zampini       ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
5925*a198735bSStefano Zampini       have_void = (active_procs == (PetscInt)size) ? PETSC_FALSE : PETSC_TRUE;
5926*a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),1,rank,1,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
5927*a198735bSStefano Zampini     }
592857de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
592957de7509SStefano Zampini     PetscInt    psum;
593057de7509SStefano Zampini     PetscMPIInt size;
593157de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
593257de7509SStefano Zampini     else psum = 0;
593357de7509SStefano Zampini     ierr = MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
593457de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
593557de7509SStefano Zampini     if (ncoarse < size) have_void = PETSC_TRUE;
593657de7509SStefano Zampini   }
593757de7509SStefano Zampini   /* determine if we can go multilevel */
593857de7509SStefano Zampini   if (multilevel_requested) {
593957de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
594057de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
594157de7509SStefano Zampini   }
594257de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
594357de7509SStefano Zampini 
5944e4d548c7SStefano Zampini   /* dump subassembling pattern */
5945e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
5946e4d548c7SStefano Zampini     ierr = ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer);CHKERRQ(ierr);
5947e4d548c7SStefano Zampini   }
5948e4d548c7SStefano Zampini 
59496e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
595027b6a85dSStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal)) { /* protects from unneded computations */
59516e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
59526e683305SStefano Zampini     const PetscInt         *idxs;
59536e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
59546e683305SStefano Zampini 
59556e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
59560be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
59576e683305SStefano Zampini     /* allocate space for temporary storage */
5958854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
5959854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
59606e683305SStefano Zampini     /* allocate for IS array */
59616e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
59626e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
596327b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
596430368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
5965854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
59666e683305SStefano Zampini     /* dofs splitting */
59676e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
59686e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
59696e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
59706e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
59716e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
59726e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
59736e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
597430368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
59756e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
59766e683305SStefano Zampini     }
59776e683305SStefano Zampini     /* neumann boundaries */
59786e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
59796e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
59806e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
59816e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
59826e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
59836e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
59846e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
598530368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
59866e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
59876e683305SStefano Zampini     }
59886e683305SStefano Zampini     /* free memory */
59896e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
59906e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
59916e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
59926e683305SStefano Zampini   } else {
59936e683305SStefano Zampini     nis = 0;
59946e683305SStefano Zampini     nisdofs = 0;
59956e683305SStefano Zampini     nisneu = 0;
599630368db7SStefano Zampini     nisvert = 0;
59976e683305SStefano Zampini     isarray = NULL;
59986e683305SStefano Zampini   }
59996e683305SStefano Zampini   /* destroy no longer needed map */
60006e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
60016e683305SStefano Zampini 
600257de7509SStefano Zampini   /* subassemble */
600357de7509SStefano Zampini   if (multilevel_allowed) {
60041ae86dd6SStefano Zampini     Vec       vp[1];
60051ae86dd6SStefano Zampini     PetscInt  nvecs = 0;
600657de7509SStefano Zampini     PetscBool reuse,reuser;
60071ae86dd6SStefano Zampini 
600857de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
600957de7509SStefano Zampini     else reuse = PETSC_FALSE;
601057de7509SStefano Zampini     ierr = MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
60111ae86dd6SStefano Zampini     vp[0] = NULL;
60121ae86dd6SStefano Zampini     if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */
60131ae86dd6SStefano Zampini       ierr = VecCreate(PetscObjectComm((PetscObject)pc),&vp[0]);CHKERRQ(ierr);
60141ae86dd6SStefano Zampini       ierr = VecSetSizes(vp[0],pcbddc->local_primal_size,PETSC_DECIDE);CHKERRQ(ierr);
60151ae86dd6SStefano Zampini       ierr = VecSetType(vp[0],VECSTANDARD);CHKERRQ(ierr);
60161ae86dd6SStefano Zampini       nvecs = 1;
60171ae86dd6SStefano Zampini 
60181ae86dd6SStefano Zampini       if (pcbddc->divudotp) {
6019*a198735bSStefano Zampini         Mat      B,loc_divudotp;
60201ae86dd6SStefano Zampini         Vec      v,p;
60211ae86dd6SStefano Zampini         IS       dummy;
60221ae86dd6SStefano Zampini         PetscInt np;
60231ae86dd6SStefano Zampini 
6024*a198735bSStefano Zampini         ierr = MatISGetLocalMat(pcbddc->divudotp,&loc_divudotp);CHKERRQ(ierr);
6025*a198735bSStefano Zampini         ierr = MatGetSize(loc_divudotp,&np,NULL);CHKERRQ(ierr);
60261ae86dd6SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,np,0,1,&dummy);CHKERRQ(ierr);
6027*a198735bSStefano Zampini         ierr = MatGetSubMatrix(loc_divudotp,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
60281ae86dd6SStefano Zampini         ierr = MatCreateVecs(B,&v,&p);CHKERRQ(ierr);
60291ae86dd6SStefano Zampini         ierr = VecSet(p,1.);CHKERRQ(ierr);
60301ae86dd6SStefano Zampini         ierr = MatMultTranspose(B,p,v);CHKERRQ(ierr);
60311ae86dd6SStefano Zampini         ierr = VecDestroy(&p);CHKERRQ(ierr);
60321ae86dd6SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
60331ae86dd6SStefano Zampini         ierr = VecGetArray(vp[0],&array);CHKERRQ(ierr);
60341ae86dd6SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_P,array);CHKERRQ(ierr);
60351ae86dd6SStefano Zampini         ierr = VecRestoreArray(vp[0],&array);CHKERRQ(ierr);
60361ae86dd6SStefano Zampini         ierr = MatMultTranspose(pcbddc->coarse_phi_B,v,pcbddc->vec1_P);CHKERRQ(ierr);
60371ae86dd6SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_P);CHKERRQ(ierr);
60381ae86dd6SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
60391ae86dd6SStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
604074e2c79eSStefano Zampini       }
60411ae86dd6SStefano Zampini     }
60421ae86dd6SStefano Zampini     if (reuser) {
60431ae86dd6SStefano Zampini       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray,nvecs,vp);CHKERRQ(ierr);
604474e2c79eSStefano Zampini     } else {
60451ae86dd6SStefano Zampini       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_FALSE,&coarse_mat_is,nis,isarray,nvecs,vp);CHKERRQ(ierr);
60461ae86dd6SStefano Zampini     }
60471ae86dd6SStefano Zampini     if (vp[0]) { /* vp[0] could have been placed on a different set of processes */
60481ae86dd6SStefano Zampini       PetscScalar *arraym,*arrayv;
60491ae86dd6SStefano Zampini       PetscInt    nl;
60501ae86dd6SStefano Zampini       ierr = VecGetLocalSize(vp[0],&nl);CHKERRQ(ierr);
60511ae86dd6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,1,nl,NULL,&coarsedivudotp);CHKERRQ(ierr);
60521ae86dd6SStefano Zampini       ierr = MatDenseGetArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
60531ae86dd6SStefano Zampini       ierr = VecGetArray(vp[0],&arrayv);CHKERRQ(ierr);
60541ae86dd6SStefano Zampini       ierr = PetscMemcpy(arraym,arrayv,nl*sizeof(PetscScalar));CHKERRQ(ierr);
60551ae86dd6SStefano Zampini       ierr = VecRestoreArray(vp[0],&arrayv);CHKERRQ(ierr);
60561ae86dd6SStefano Zampini       ierr = MatDenseRestoreArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
60571ae86dd6SStefano Zampini       ierr = VecDestroy(&vp[0]);CHKERRQ(ierr);
6058*a198735bSStefano Zampini     } else {
6059*a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&coarsedivudotp);CHKERRQ(ierr);
60601ae86dd6SStefano Zampini     }
60611ae86dd6SStefano Zampini   } else {
60621ae86dd6SStefano Zampini     ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_FALSE,&coarse_mat_is,nis,isarray,0,NULL);CHKERRQ(ierr);
60636e683305SStefano Zampini   }
606457de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
606557de7509SStefano Zampini     PetscMPIInt size;
606657de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)coarse_mat_is),&size);
606757de7509SStefano Zampini     if (!multilevel_allowed) {
606857de7509SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
60696e683305SStefano Zampini     } else {
607057de7509SStefano Zampini       Mat A;
6071779c1cceSStefano Zampini 
607257de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
607357de7509SStefano Zampini       if (coarse_mat_is) {
607457de7509SStefano Zampini         if (coarse_mat) SETERRQ(PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
607557de7509SStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
607657de7509SStefano Zampini         coarse_mat = coarse_mat_is;
607757de7509SStefano Zampini       }
607857de7509SStefano Zampini       /* be sure we don't have MatSeqDENSE as local mat */
607957de7509SStefano Zampini       ierr = MatISGetLocalMat(coarse_mat,&A);CHKERRQ(ierr);
608057de7509SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr);
6081779c1cceSStefano Zampini     }
6082779c1cceSStefano Zampini   }
608357de7509SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
608457de7509SStefano Zampini   ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
60856e683305SStefano Zampini 
60866e683305SStefano Zampini   /* create local to global scatters for coarse problem */
608768457ee5SStefano Zampini   if (compute_vecs) {
60886e683305SStefano Zampini     PetscInt lrows;
60896e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
609057de7509SStefano Zampini     if (coarse_mat) {
609157de7509SStefano Zampini       ierr = MatGetLocalSize(coarse_mat,&lrows,NULL);CHKERRQ(ierr);
60926e683305SStefano Zampini     } else {
60936e683305SStefano Zampini       lrows = 0;
60946e683305SStefano Zampini     }
60956e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
60966e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
60976e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
60986e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
60996e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
61006e683305SStefano Zampini   }
61016e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
6102c8587f34SStefano Zampini 
6103f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
6104f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
6105f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
6106f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
6107f9eb5b7dSStefano Zampini   } else {
6108f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
6109f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
6110c8587f34SStefano Zampini   }
6111c8587f34SStefano Zampini 
61126e683305SStefano Zampini   /* print some info if requested */
61136e683305SStefano Zampini   if (pcbddc->dbg_flag) {
61146e683305SStefano Zampini     if (!multilevel_allowed) {
61156e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
61166e683305SStefano Zampini       if (multilevel_requested) {
61176e683305SStefano 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);
61186e683305SStefano Zampini       } else if (pcbddc->max_levels) {
61196e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
61206e683305SStefano Zampini       }
61216e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
61226e683305SStefano Zampini     }
61236e683305SStefano Zampini   }
61246e683305SStefano Zampini 
6125f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
612657de7509SStefano Zampini   if (coarse_mat) {
61276a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
61286e683305SStefano Zampini     if (pcbddc->dbg_flag) {
612957de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
61306e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
61316e683305SStefano Zampini     }
6132f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
6133312be037SStefano Zampini       char prefix[256],str_level[16];
6134e604994aSStefano Zampini       size_t len;
613557de7509SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp);CHKERRQ(ierr);
6136422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
6137c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
6138f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
613957de7509SStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
6140c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
61416e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
6142c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
6143c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
6144e604994aSStefano Zampini       /* prefix */
6145e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
6146e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
6147e604994aSStefano Zampini       if (!pcbddc->current_level) {
6148e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
6149e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
6150c8587f34SStefano Zampini       } else {
6151e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
6152312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
6153312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
615434d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
6155312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
6156e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
6157e604994aSStefano Zampini       }
6158e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
61593e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
61603e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
61613e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
61623e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
6163f9eb5b7dSStefano Zampini       /* allow user customization */
6164f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
61653e3c6dadSStefano Zampini     }
61663e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
616751bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
61683e3c6dadSStefano Zampini     if (nisdofs) {
61693e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
61703e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
61713e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
61723e3c6dadSStefano Zampini       }
61733e3c6dadSStefano Zampini     }
61743e3c6dadSStefano Zampini     if (nisneu) {
61753e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
61763e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
6177312be037SStefano Zampini     }
617830368db7SStefano Zampini     if (nisvert) {
617930368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
618030368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
618130368db7SStefano Zampini     }
6182f9eb5b7dSStefano Zampini 
6183f9eb5b7dSStefano Zampini     /* get some info after set from options */
6184f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
6185f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
61864f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
61876e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
6188f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
6189f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
6190f9eb5b7dSStefano Zampini     }
619139f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
61924f3a063dSStefano Zampini     if (isredundant) {
61934f3a063dSStefano Zampini       KSP inner_ksp;
61944f3a063dSStefano Zampini       PC  inner_pc;
61954f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
61964f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
61974f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
61984f3a063dSStefano Zampini     }
6199f9eb5b7dSStefano Zampini 
620057de7509SStefano Zampini     /* parameters which miss an API */
620157de7509SStefano Zampini     if (isbddc) {
6202720d30f9SStefano Zampini       PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data;
6203720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
620457de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
620527b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
620627b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
6207*a198735bSStefano Zampini         Mat                    coarsedivudotp_is;
6208*a198735bSStefano Zampini         ISLocalToGlobalMapping l2gmap,rl2g,cl2g;
6209*a198735bSStefano Zampini         IS                     row,col;
6210*a198735bSStefano Zampini         const PetscInt         *gidxs;
6211*a198735bSStefano Zampini         PetscInt               n,st,M,N;
6212*a198735bSStefano Zampini 
6213*a198735bSStefano Zampini         ierr = MatGetSize(coarsedivudotp,&n,NULL);CHKERRQ(ierr);
6214*a198735bSStefano Zampini         ierr = MPI_Scan(&n,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)coarse_mat));CHKERRQ(ierr);
6215*a198735bSStefano Zampini         st = st-n;
6216*a198735bSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)coarse_mat),1,st,1,&row);CHKERRQ(ierr);
6217*a198735bSStefano Zampini         ierr = MatGetLocalToGlobalMapping(coarse_mat,&l2gmap,NULL);CHKERRQ(ierr);
6218*a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(l2gmap,&n);CHKERRQ(ierr);
6219*a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
6220*a198735bSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
6221*a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
6222*a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
6223*a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
6224*a198735bSStefano Zampini         ierr = ISGetSize(row,&M);CHKERRQ(ierr);
6225*a198735bSStefano Zampini         ierr = MatGetSize(coarse_mat,&N,NULL);CHKERRQ(ierr);
6226*a198735bSStefano Zampini         ierr = ISDestroy(&row);CHKERRQ(ierr);
6227*a198735bSStefano Zampini         ierr = ISDestroy(&col);CHKERRQ(ierr);
6228*a198735bSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)coarse_mat),&coarsedivudotp_is);CHKERRQ(ierr);
6229*a198735bSStefano Zampini         ierr = MatSetType(coarsedivudotp_is,MATIS);CHKERRQ(ierr);
6230*a198735bSStefano Zampini         ierr = MatSetSizes(coarsedivudotp_is,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
6231*a198735bSStefano Zampini         ierr = MatSetLocalToGlobalMapping(coarsedivudotp_is,rl2g,cl2g);CHKERRQ(ierr);
6232*a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
6233*a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
6234*a198735bSStefano Zampini         ierr = MatISSetLocalMat(coarsedivudotp_is,coarsedivudotp);CHKERRQ(ierr);
6235*a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
6236*a198735bSStefano Zampini         ierr = PCBDDCSetDivergenceMat(pc_temp,coarsedivudotp_is,NULL);CHKERRQ(ierr);
6237*a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp_is);CHKERRQ(ierr);
6238720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
623959e48ca4SStefano Zampini         if (pcbddc->adaptive_threshold < 1.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
6240720d30f9SStefano Zampini       }
6241d4d8cf7bSStefano Zampini     }
62429881197aSStefano Zampini 
62433301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
62445a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
62453301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
62463301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
62473301b35fSStefano Zampini     }
62483301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
62493301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
62503301b35fSStefano Zampini     }
62513301b35fSStefano Zampini     if (pc->pmat->spd_set) {
62523301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
62533301b35fSStefano Zampini     }
625427b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
625527b6a85dSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
625627b6a85dSStefano Zampini     }
62576e683305SStefano Zampini     /* set operators */
62585f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
62596e683305SStefano Zampini     if (pcbddc->dbg_flag) {
62606e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
62616e683305SStefano Zampini     }
62626e683305SStefano Zampini   }
62636e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
6264b1ecc7b1SStefano Zampini #if 0
6265b9b85e73SStefano Zampini   {
6266b9b85e73SStefano Zampini     PetscViewer viewer;
6267b9b85e73SStefano Zampini     char filename[256];
6268b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
6269b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
62706a9046bcSBarry Smith     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
6271b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
6272f159cad9SBarry Smith     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
6273b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
6274b9b85e73SStefano Zampini   }
6275b9b85e73SStefano Zampini #endif
6276f9eb5b7dSStefano Zampini 
627798a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
627898a51de6SStefano Zampini     Vec crhs,csol;
627904708bb6SStefano Zampini 
6280f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
6281f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
6282f347579bSStefano Zampini     if (!csol) {
62832a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
6284f9eb5b7dSStefano Zampini     }
6285f347579bSStefano Zampini     if (!crhs) {
62862a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
6287f347579bSStefano Zampini     }
6288b0f5fe93SStefano Zampini   }
62891ae86dd6SStefano Zampini   ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
6290b0f5fe93SStefano Zampini 
6291b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
6292b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
6293b0f5fe93SStefano Zampini 
6294b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
62954f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
62964f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
62974f1b2e48SStefano Zampini     }
6298b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
6299b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
6300b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6301b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6302b0f5fe93SStefano Zampini     if (coarse_mat) {
6303b0f5fe93SStefano Zampini       Vec         nullv;
6304b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
6305b0f5fe93SStefano Zampini       PetscInt    nl;
6306b0f5fe93SStefano Zampini 
6307b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
6308b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
6309b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
6310b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
6311b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
6312b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
6313b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
6314b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
6315b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
6316b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
6317b0f5fe93SStefano Zampini     }
6318b0f5fe93SStefano Zampini   }
6319b0f5fe93SStefano Zampini 
6320b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
6321b0f5fe93SStefano Zampini     PetscBool ispreonly;
6322b0f5fe93SStefano Zampini 
6323b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
6324b0f5fe93SStefano Zampini       PetscBool isnull;
6325b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
6326bef83e63SStefano Zampini       if (isnull) {
6327b0f5fe93SStefano Zampini         ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
6328b0f5fe93SStefano Zampini       }
6329bef83e63SStefano Zampini       /* TODO: add local nullspaces (if any) */
6330b0f5fe93SStefano Zampini     }
6331b0f5fe93SStefano Zampini     /* setup coarse ksp */
6332b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
6333cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
6334cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
63356e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
6336c8587f34SStefano Zampini       KSP       check_ksp;
63372b510759SStefano Zampini       KSPType   check_ksp_type;
6338c8587f34SStefano Zampini       PC        check_pc;
63396e683305SStefano Zampini       Vec       check_vec,coarse_vec;
63406a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
63412b510759SStefano Zampini       PetscInt  its;
63426e683305SStefano Zampini       PetscBool compute_eigs;
63436e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
63446e683305SStefano Zampini       PetscInt  neigs;
63458e185a42SStefano Zampini       const char *prefix;
6346c8587f34SStefano Zampini 
63472b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
63486e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
6349422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
635023ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
6351f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
6352e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
6353e4d548c7SStefano Zampini       ierr = KSPGetPC(check_ksp,&check_pc);CHKERRQ(ierr);
6354e4d548c7SStefano Zampini       ierr = PCSetType(check_pc,PCNONE);CHKERRQ(ierr);
63552b510759SStefano Zampini       if (ispreonly) {
63562b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
63576e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
63582b510759SStefano Zampini       } else {
6359cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
63606e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
6361c8587f34SStefano Zampini       }
6362c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
63636e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
63646e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
63656e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
6366a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
6367a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
6368a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
6369a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
6370c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
6371c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
6372c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
6373c8587f34SStefano Zampini       /* create random vec */
63742701bc32SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&coarse_vec,&check_vec);CHKERRQ(ierr);
6375c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
63766e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
6377c8587f34SStefano Zampini       /* solve coarse problem */
63786e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
6379cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
63806e683305SStefano Zampini       if (compute_eigs) {
6381854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
6382854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
63836e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
63841ae86dd6SStefano Zampini         if (neigs) {
63856e683305SStefano Zampini           lambda_max = eigs_r[neigs-1];
63866e683305SStefano Zampini           lambda_min = eigs_r[0];
63876e683305SStefano Zampini           if (pcbddc->use_coarse_estimates) {
63882701bc32SStefano Zampini             if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
63892701bc32SStefano Zampini               ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min);CHKERRQ(ierr);
6390cbcc2c2aSStefano Zampini               ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
6391cbcc2c2aSStefano Zampini             }
6392c8587f34SStefano Zampini           }
6393c8587f34SStefano Zampini         }
63941ae86dd6SStefano Zampini       }
6395cbcc2c2aSStefano Zampini 
6396c8587f34SStefano Zampini       /* check coarse problem residual error */
63976e683305SStefano Zampini       if (pcbddc->dbg_flag) {
63986e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
63996e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
64006e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
6401c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
64026e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
64036e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
6404779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
64056e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
64066e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
64076e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
64086e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
6409b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
6410b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
6411b0f5fe93SStefano Zampini         }
64126e683305SStefano Zampini         if (compute_eigs) {
64136e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
6414deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
6415c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
64166e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
64176e683305SStefano 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);
64186e683305SStefano Zampini           for (i=0;i<neigs;i++) {
64196e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
6420c8587f34SStefano Zampini           }
64216e683305SStefano Zampini         }
64226e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
64236e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
64246e683305SStefano Zampini       }
6425e4d548c7SStefano Zampini       ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
64262701bc32SStefano Zampini       ierr = VecDestroy(&coarse_vec);CHKERRQ(ierr);
6427c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
64286e683305SStefano Zampini       if (compute_eigs) {
64296e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
64306e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
6431c8587f34SStefano Zampini       }
64326e683305SStefano Zampini     }
64336e683305SStefano Zampini   }
6434bef83e63SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
6435cbcc2c2aSStefano Zampini   /* print additional info */
6436cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
64376e683305SStefano Zampini     /* waits until all processes reaches this point */
64386e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
6439cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
6440cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6441cbcc2c2aSStefano Zampini   }
6442cbcc2c2aSStefano Zampini 
64432b510759SStefano Zampini   /* free memory */
6444fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
6445c8587f34SStefano Zampini   PetscFunctionReturn(0);
6446c8587f34SStefano Zampini }
6447674ae819SStefano Zampini 
6448f34684f1SStefano Zampini #undef __FUNCT__
6449f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
6450f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
6451f34684f1SStefano Zampini {
6452f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
6453f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
6454f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
6455dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
6456dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
645773be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
6458dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
6459f34684f1SStefano Zampini   PetscErrorCode ierr;
6460f34684f1SStefano Zampini 
6461f34684f1SStefano Zampini   PetscFunctionBegin;
6462f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
64636c4ed002SBarry Smith   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
6464dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
64653bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
6466dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
6467dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
6468dc456d91SStefano Zampini   ierr = PCBDDCSubsetNumbering(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
6469dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
6470dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
6471dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
64726c4ed002SBarry Smith   if (local_size != pcbddc->local_primal_size) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid number of local primal indices computed %D != %D",local_size,pcbddc->local_primal_size);
6473dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
6474dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
6475dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
6476dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
6477dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
6478f34684f1SStefano Zampini 
6479f34684f1SStefano Zampini   /* check numbering */
6480f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
6481019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
6482dc456d91SStefano Zampini     PetscInt    i;
6483b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
6484f34684f1SStefano Zampini 
6485f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6486f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
6487f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
64881575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6489019a44ceSStefano Zampini     /* counter */
6490019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6491019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
6492019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6493019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6494019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6495019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6496f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
6497f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
6498727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
6499f34684f1SStefano Zampini     }
6500f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6501f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6502f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6503e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6504e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6505e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6506e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6507f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6508019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
6509f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
6510019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
65112c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
651275c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
6513b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
65142c66d082SStefano Zampini         ierr = ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi);CHKERRQ(ierr);
65152c66d082SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d: local index %d (gid %d) owned by %d processes instead of %d!\n",PetscGlobalRank,i,gi,owned,neigh);CHKERRQ(ierr);
6516f34684f1SStefano Zampini       }
6517f34684f1SStefano Zampini     }
6518019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
6519b2566f29SBarry Smith     ierr = MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
6520f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6521f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
6522f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
6523f34684f1SStefano Zampini     }
6524f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6525f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6526e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6527e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6528f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
6529f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
6530b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
6531ca8b9ea9SStefano Zampini       PetscInt *gidxs;
6532ca8b9ea9SStefano Zampini 
6533ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
65343bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
6535f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
6536f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6537f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
6538f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
65394bc2dc4bSStefano 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);
6540f34684f1SStefano Zampini       }
6541f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6542ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
6543f34684f1SStefano Zampini     }
6544f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
65451575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6546302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
6547f34684f1SStefano Zampini   }
65488bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
6549f34684f1SStefano Zampini   /* get back data */
6550f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
6551f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
6552674ae819SStefano Zampini   PetscFunctionReturn(0);
6553674ae819SStefano Zampini }
6554674ae819SStefano Zampini 
6555e456f2a8SStefano Zampini #undef __FUNCT__
6556e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
6557a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
6558e456f2a8SStefano Zampini {
6559e456f2a8SStefano Zampini   IS             localis_t;
6560a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
6561e456f2a8SStefano Zampini   PetscScalar    *vals;
6562e456f2a8SStefano Zampini   PetscErrorCode ierr;
6563e456f2a8SStefano Zampini 
6564e456f2a8SStefano Zampini   PetscFunctionBegin;
6565a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
6566e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
6567854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
6568e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
6569e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
6570a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
6571a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
65721035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
6573a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
65741035eff8SStefano Zampini   }
6575a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
6576e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
6577e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
6578a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
6579a7dc3881SStefano Zampini   /* now compute set in local ordering */
6580a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6581a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6582a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
6583a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
6584a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
6585ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
6586e456f2a8SStefano Zampini       lsize++;
6587e456f2a8SStefano Zampini     }
6588e456f2a8SStefano Zampini   }
6589854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
6590a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
6591ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
6592e456f2a8SStefano Zampini       idxs[lsize++] = i;
6593e456f2a8SStefano Zampini     }
6594e456f2a8SStefano Zampini   }
6595a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
6596a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
6597e456f2a8SStefano Zampini   *localis = localis_t;
6598e456f2a8SStefano Zampini   PetscFunctionReturn(0);
6599e456f2a8SStefano Zampini }
6600906d46d4SStefano Zampini 
6601b96c3477SStefano Zampini #undef __FUNCT__
6602b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
660308122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
6604b96c3477SStefano Zampini {
6605a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6606b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6607b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
6608a64f4aa4SStefano Zampini   Mat                 S_j;
6609b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
6610b96c3477SStefano Zampini   PetscBool           free_used_adj;
6611b96c3477SStefano Zampini   PetscErrorCode      ierr;
6612b96c3477SStefano Zampini 
6613b96c3477SStefano Zampini   PetscFunctionBegin;
6614b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
6615b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
661608122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
6617b96c3477SStefano Zampini     used_xadj = NULL;
6618b96c3477SStefano Zampini     used_adjncy = NULL;
6619b96c3477SStefano Zampini   } else {
662008122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
662108122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
662208122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
662308122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
6624b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
6625b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
6626b96c3477SStefano Zampini     } else {
66272fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
6628b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
6629b96c3477SStefano Zampini       PetscInt       nvtxs;
6630b96c3477SStefano Zampini 
66312fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
66322fffb893SStefano Zampini       if (flg_row) {
6633b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
6634b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
6635b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
6636b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
66372fffb893SStefano Zampini       } else {
66382fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
66392fffb893SStefano Zampini         used_xadj = NULL;
66402fffb893SStefano Zampini         used_adjncy = NULL;
66412fffb893SStefano Zampini       }
66422fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
6643b96c3477SStefano Zampini     }
6644b96c3477SStefano Zampini   }
6645d5574798SStefano Zampini 
6646d5574798SStefano Zampini   /* setup sub_schurs data */
6647a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
6648df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
6649df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
6650a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
665191af6908SStefano Zampini     ierr = PCBDDCSubSchursSetUp(sub_schurs,NULL,S_j,PETSC_FALSE,used_xadj,used_adjncy,pcbddc->sub_schurs_layers,NULL,pcbddc->adaptive_selection,PETSC_FALSE,PETSC_FALSE,0,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
6652a64f4aa4SStefano Zampini   } else {
66536816873aSStefano Zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
6654b7ab4a40SStefano Zampini     PetscBool isseqaij,need_change = PETSC_FALSE;;
6655a3df083aSStefano Zampini     PetscInt  benign_n;
665672b8c272SStefano Zampini     Mat       change = NULL;
66579d54b7f4SStefano Zampini     Vec       scaling = NULL;
665872b8c272SStefano Zampini     IS        change_primal = NULL;
6659a3df083aSStefano Zampini 
66605feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
66615feab87aSStefano Zampini       PetscInt n_vertices;
66625feab87aSStefano Zampini 
66635feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
66642034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
66655feab87aSStefano Zampini     }
666604708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
666704708bb6SStefano Zampini     if (!isseqaij) {
666804708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
666904708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
667004708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
667104708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
667204708bb6SStefano Zampini       } else {
6673511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
667404708bb6SStefano Zampini       }
667504708bb6SStefano Zampini     }
6676a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
6677a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
6678ca92afb2SStefano Zampini     } else {
6679a3df083aSStefano Zampini       benign_n = 0;
6680ca92afb2SStefano Zampini     }
6681b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
6682b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
6683b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
668472b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
668522db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
6686b7ab4a40SStefano Zampini       ierr = MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
668722db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
6688b7ab4a40SStefano Zampini     }
6689b7ab4a40SStefano Zampini     /* If the user defines additional constraints, we import them here.
6690b7ab4a40SStefano Zampini        We need to compute the change of basis according to the quadrature weights attached to pmat via MatSetNearNullSpace, and this could not be done (at the moment) without some hacking */
6691b7ab4a40SStefano Zampini     if (need_change) {
669288c03ad3SStefano Zampini       PC_IS   *pcisf;
669388c03ad3SStefano Zampini       PC_BDDC *pcbddcf;
669488c03ad3SStefano Zampini       PC      pcf;
669588c03ad3SStefano Zampini 
6696e4d548c7SStefano Zampini       if (pcbddc->sub_schurs_rebuild) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
669788c03ad3SStefano Zampini       ierr = PCCreate(PetscObjectComm((PetscObject)pc),&pcf);CHKERRQ(ierr);
669888c03ad3SStefano Zampini       ierr = PCSetOperators(pcf,pc->mat,pc->pmat);CHKERRQ(ierr);
669988c03ad3SStefano Zampini       ierr = PCSetType(pcf,PCBDDC);CHKERRQ(ierr);
670088c03ad3SStefano Zampini       /* hacks */
670188c03ad3SStefano Zampini       pcisf = (PC_IS*)pcf->data;
670272b8c272SStefano Zampini       pcisf->is_B_local = pcis->is_B_local;
670372b8c272SStefano Zampini       pcisf->vec1_N = pcis->vec1_N;
670472b8c272SStefano Zampini       pcisf->BtoNmap = pcis->BtoNmap;
670572b8c272SStefano Zampini       pcisf->n = pcis->n;
670672b8c272SStefano Zampini       pcisf->n_B = pcis->n_B;
670788c03ad3SStefano Zampini       pcbddcf = (PC_BDDC*)pcf->data;
670888c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->mat_graph);CHKERRQ(ierr);
670988c03ad3SStefano Zampini       pcbddcf->mat_graph = pcbddc->mat_graph;
671088c03ad3SStefano Zampini       pcbddcf->use_faces = PETSC_TRUE;
671188c03ad3SStefano Zampini       pcbddcf->use_change_of_basis = PETSC_TRUE;
671288c03ad3SStefano Zampini       pcbddcf->use_change_on_faces = PETSC_TRUE;
671372b8c272SStefano Zampini       pcbddcf->use_qr_single = PETSC_TRUE;
671488c03ad3SStefano Zampini       pcbddcf->fake_change = PETSC_TRUE;
671588c03ad3SStefano Zampini       ierr = PCBDDCConstraintsSetUp(pcf);CHKERRQ(ierr);
671672b8c272SStefano Zampini       /* store information on primal vertices and change of basis (in local numbering) */
671772b8c272SStefano Zampini       sub_schurs->change_with_qr = pcbddcf->use_qr_single;
671872b8c272SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal);CHKERRQ(ierr);
671972b8c272SStefano Zampini       change = pcbddcf->ConstraintMatrix;
672072b8c272SStefano Zampini       pcbddcf->ConstraintMatrix = NULL;
672188c03ad3SStefano Zampini       /* free unneeded memory allocated in PCBDDCConstraintsSetUp */
672272b8c272SStefano Zampini       ierr = PetscFree(pcbddcf->sub_schurs);CHKERRQ(ierr);
672388c03ad3SStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddcf->onearnullspace);CHKERRQ(ierr);
672488c03ad3SStefano Zampini       ierr = PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult);CHKERRQ(ierr);
672588c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->primal_indices_local_idxs);CHKERRQ(ierr);
672688c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->onearnullvecs_state);CHKERRQ(ierr);
672788c03ad3SStefano Zampini       ierr = PetscFree(pcf->data);CHKERRQ(ierr);
672888c03ad3SStefano Zampini       pcf->ops->destroy = NULL;
672988c03ad3SStefano Zampini       ierr = PCDestroy(&pcf);CHKERRQ(ierr);
673088c03ad3SStefano Zampini     }
67319d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
673291af6908SStefano Zampini     ierr = PCBDDCSubSchursSetUp(sub_schurs,pcbddc->local_mat,S_j,pcbddc->sub_schurs_exact_schur,used_xadj,used_adjncy,pcbddc->sub_schurs_layers,scaling,pcbddc->adaptive_selection,reuse_solvers,pcbddc->benign_saddle_point,benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_zerodiag_subs,change,change_primal);CHKERRQ(ierr);
673372b8c272SStefano Zampini     ierr = MatDestroy(&change);CHKERRQ(ierr);
673472b8c272SStefano Zampini     ierr = ISDestroy(&change_primal);CHKERRQ(ierr);
6735ca92afb2SStefano Zampini   }
6736d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
6737b96c3477SStefano Zampini 
6738b96c3477SStefano Zampini   /* free adjacency */
6739b96c3477SStefano Zampini   if (free_used_adj) {
6740b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
6741b96c3477SStefano Zampini   }
6742b96c3477SStefano Zampini   PetscFunctionReturn(0);
6743b96c3477SStefano Zampini }
6744b96c3477SStefano Zampini 
6745b96c3477SStefano Zampini #undef __FUNCT__
6746b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
674708122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
6748b96c3477SStefano Zampini {
6749b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6750b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6751b96c3477SStefano Zampini   PCBDDCGraph         graph;
6752b96c3477SStefano Zampini   PetscErrorCode      ierr;
6753b96c3477SStefano Zampini 
6754b96c3477SStefano Zampini   PetscFunctionBegin;
6755b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
675608122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
67573301b35fSStefano Zampini     IS       verticesIS,verticescomm;
67583301b35fSStefano Zampini     PetscInt vsize,*idxs;
6759b96c3477SStefano Zampini 
6760b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
67613301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
67623301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
67633301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
67643301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
67653301b35fSStefano Zampini     ierr = ISDestroy(&verticesIS);CHKERRQ(ierr);
6766b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
67677fb0e2dbSStefano Zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global);CHKERRQ(ierr);
6768441e0de0SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
67693301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
6770b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
6771b96c3477SStefano Zampini   } else {
6772b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
6773b96c3477SStefano Zampini   }
6774e4d548c7SStefano Zampini   /* print some info */
6775e4d548c7SStefano Zampini   if (pcbddc->dbg_flag) {
6776e4d548c7SStefano Zampini     IS       vertices;
6777e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
6778e4d548c7SStefano Zampini     ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
6779e4d548c7SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
6780e4d548c7SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
6781e4d548c7SStefano Zampini     ierr = ISDestroy(&vertices);CHKERRQ(ierr);
6782e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6783e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
6784e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
6785e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
6786e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
6787e4d548c7SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6788e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6789e4d548c7SStefano Zampini   }
6790b96c3477SStefano Zampini 
6791b96c3477SStefano Zampini   /* sub_schurs init */
6792b334f244SStefano Zampini   if (!pcbddc->sub_schurs) {
6793b334f244SStefano Zampini     ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
6794b334f244SStefano Zampini   }
6795b334f244SStefano Zampini   ierr = PCBDDCSubSchursInit(pcbddc->sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap);CHKERRQ(ierr);
6796a64f4aa4SStefano Zampini 
6797b96c3477SStefano Zampini   /* free graph struct */
679808122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
6799b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
6800b96c3477SStefano Zampini   }
6801b96c3477SStefano Zampini   PetscFunctionReturn(0);
6802b96c3477SStefano Zampini }
6803fa34dd3eSStefano Zampini 
6804fa34dd3eSStefano Zampini #undef __FUNCT__
6805fa34dd3eSStefano Zampini #define __FUNCT__ "PCBDDCCheckOperator"
6806fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
6807fa34dd3eSStefano Zampini {
6808fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6809fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6810fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
6811fa34dd3eSStefano Zampini 
6812fa34dd3eSStefano Zampini   PetscFunctionBegin;
6813fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
6814fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
68154f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
6816fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
68174f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
681875c01103SStefano Zampini     PetscReal      norm;
6819fa34dd3eSStefano Zampini     PetscInt       i;
6820fa34dd3eSStefano Zampini 
6821fa34dd3eSStefano Zampini     /* B0 and B0_B */
6822fa34dd3eSStefano Zampini     if (zerodiag) {
6823fa34dd3eSStefano Zampini       IS       dummy;
6824fa34dd3eSStefano Zampini 
68254f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
68264f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
6827fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
6828fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
6829fa34dd3eSStefano Zampini     }
6830fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
6831fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
6832fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
6833fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6834fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6835fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6836fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6837fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
6838fa34dd3eSStefano Zampini     /* S_j */
6839fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
6840fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
6841fa34dd3eSStefano Zampini 
6842fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
6843fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
6844fa34dd3eSStefano Zampini     /* continuous in primal space */
6845fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
6846fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6847fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6848fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
68494f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
68504f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
6851fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
6852fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6853fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6854fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6855fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6856fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6857fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
6858fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
6859fa34dd3eSStefano Zampini 
6860fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
6861fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
6862fa34dd3eSStefano Zampini     /* local with Schur */
6863fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
6864fa34dd3eSStefano Zampini     if (zerodiag) {
6865fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
68664f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
6867fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
6868fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
6869fa34dd3eSStefano Zampini     }
6870fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
6871fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6872fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6873fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6874fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
6875fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
6876fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
6877fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6878fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
6879fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6880fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6881fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6882fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6883fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6884fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
6885fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
6886fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
6887fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6888fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6889fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6890fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6891fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6892fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
6893fa34dd3eSStefano Zampini     if (zerodiag) {
6894fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
6895fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
68964f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
6897fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
6898fa34dd3eSStefano Zampini     }
6899fa34dd3eSStefano Zampini     /* BDDC */
6900fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
6901fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
6902fa34dd3eSStefano Zampini 
6903fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
6904fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
6905fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
6906fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
69074f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
69084f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
6909fa34dd3eSStefano Zampini     }
69104f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
6911fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
6912fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
6913fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
6914fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
6915fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
6916fa34dd3eSStefano Zampini   }
6917fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
6918fa34dd3eSStefano Zampini }
6919