xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision 9a962809db5c7fdf86423e5aca0bb85c2c0e6828)
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 #undef __FUNCT__
8669cc0f4SStefano Zampini #define __FUNCT__ "PCBDDCComputeNoNetFlux"
9fa23a32eSStefano Zampini PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp)
10669cc0f4SStefano Zampini {
11a198735bSStefano Zampini   Mat                    loc_divudotp;
12fa23a32eSStefano Zampini   Vec                    p,v,vins,quad_vec,*quad_vecs;
13669cc0f4SStefano Zampini   ISLocalToGlobalMapping rmap;
14669cc0f4SStefano Zampini   IS                     *faces,*edges;
15669cc0f4SStefano Zampini   PetscScalar            *vals;
16669cc0f4SStefano Zampini   const PetscScalar      *array;
17669cc0f4SStefano Zampini   PetscInt               i,maxneighs,lmaxneighs,maxsize,nf,ne;
181ae86dd6SStefano Zampini   PetscMPIInt            rank;
19a198735bSStefano Zampini   PetscErrorCode         ierr;
20669cc0f4SStefano Zampini 
21669cc0f4SStefano Zampini   PetscFunctionBegin;
22669cc0f4SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(graph,&nf,&faces,&ne,&edges,NULL);CHKERRQ(ierr);
23669cc0f4SStefano Zampini   if (graph->twodim) {
24669cc0f4SStefano Zampini     lmaxneighs = 2;
25669cc0f4SStefano Zampini   } else {
26669cc0f4SStefano Zampini     lmaxneighs = 1;
27669cc0f4SStefano Zampini     for (i=0;i<ne;i++) {
28669cc0f4SStefano Zampini       const PetscInt *idxs;
29669cc0f4SStefano Zampini       ierr = ISGetIndices(edges[i],&idxs);CHKERRQ(ierr);
30669cc0f4SStefano Zampini       lmaxneighs = PetscMax(lmaxneighs,graph->count[idxs[0]]);
31669cc0f4SStefano Zampini       ierr = ISRestoreIndices(edges[i],&idxs);CHKERRQ(ierr);
32669cc0f4SStefano Zampini     }
33669cc0f4SStefano Zampini     lmaxneighs++; /* graph count does not include self */
34669cc0f4SStefano Zampini   }
35669cc0f4SStefano Zampini   ierr = MPIU_Allreduce(&lmaxneighs,&maxneighs,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
36669cc0f4SStefano Zampini   maxsize = 0;
37669cc0f4SStefano Zampini   for (i=0;i<ne;i++) {
38669cc0f4SStefano Zampini     PetscInt nn;
39669cc0f4SStefano Zampini     ierr = ISGetLocalSize(edges[i],&nn);CHKERRQ(ierr);
40669cc0f4SStefano Zampini     maxsize = PetscMax(maxsize,nn);
41669cc0f4SStefano Zampini   }
42669cc0f4SStefano Zampini   for (i=0;i<nf;i++) {
43669cc0f4SStefano Zampini     PetscInt nn;
44669cc0f4SStefano Zampini     ierr = ISGetLocalSize(faces[i],&nn);CHKERRQ(ierr);
45669cc0f4SStefano Zampini     maxsize = PetscMax(maxsize,nn);
46669cc0f4SStefano Zampini   }
47669cc0f4SStefano Zampini   ierr = PetscMalloc1(maxsize,&vals);CHKERRQ(ierr);
48669cc0f4SStefano Zampini   /* create vectors to hold quadrature weights */
49669cc0f4SStefano Zampini   ierr = MatCreateVecs(A,&quad_vec,NULL);CHKERRQ(ierr);
50669cc0f4SStefano Zampini   ierr = MatGetLocalToGlobalMapping(A,&rmap,NULL);CHKERRQ(ierr);
51669cc0f4SStefano Zampini   ierr = VecDuplicateVecs(quad_vec,maxneighs,&quad_vecs);CHKERRQ(ierr);
521ae86dd6SStefano Zampini   ierr = VecDestroy(&quad_vec);CHKERRQ(ierr);
53669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
54669cc0f4SStefano Zampini     PetscInt first,last;
55669cc0f4SStefano Zampini 
56669cc0f4SStefano Zampini     ierr = VecSetLocalToGlobalMapping(quad_vecs[i],rmap);CHKERRQ(ierr);
57669cc0f4SStefano Zampini     /* the near-null space fo BDDC carries information on quadrature weights,
58669cc0f4SStefano Zampini        and these can be collinear -> so cheat with MatNullSpaceCreate
59669cc0f4SStefano Zampini        and create a suitable set of basis vectors first */
60669cc0f4SStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
61669cc0f4SStefano Zampini     if (i>=first && i < last) {
62669cc0f4SStefano Zampini       PetscScalar *data;
63669cc0f4SStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
64669cc0f4SStefano Zampini       data[i-first] = 1.;
65669cc0f4SStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
66669cc0f4SStefano Zampini     }
67669cc0f4SStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
68669cc0f4SStefano Zampini   }
69669cc0f4SStefano Zampini   ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)A),PETSC_FALSE,maxneighs,quad_vecs,nnsp);CHKERRQ(ierr);
701ae86dd6SStefano Zampini   for (i=0;i<maxneighs;i++) { /* reset vectors */
711ae86dd6SStefano Zampini     PetscInt first,last;
721ae86dd6SStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
731ae86dd6SStefano Zampini     if (i>=first && i < last) {
741ae86dd6SStefano Zampini       PetscScalar *data;
751ae86dd6SStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
761ae86dd6SStefano Zampini       data[i-first] = 0.;
771ae86dd6SStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
781ae86dd6SStefano Zampini     }
791ae86dd6SStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
801ae86dd6SStefano Zampini   }
81669cc0f4SStefano Zampini   /* compute local quad vec */
82a198735bSStefano Zampini   ierr = MatISGetLocalMat(divudotp,&loc_divudotp);CHKERRQ(ierr);
83a198735bSStefano Zampini   ierr = MatCreateVecs(loc_divudotp,&v,&p);CHKERRQ(ierr);
84669cc0f4SStefano Zampini   ierr = VecSet(p,1.);CHKERRQ(ierr);
85a198735bSStefano Zampini   ierr = MatMultTranspose(loc_divudotp,p,v);CHKERRQ(ierr);
86fa23a32eSStefano Zampini   if (vl2l) {
87fa23a32eSStefano Zampini     ierr = VecGetSubVector(v,vl2l,&vins);CHKERRQ(ierr);
88fa23a32eSStefano Zampini   } else {
89fa23a32eSStefano Zampini     vins = v;
90fa23a32eSStefano Zampini   }
91fa23a32eSStefano Zampini   ierr = VecGetArrayRead(vins,&array);CHKERRQ(ierr);
92669cc0f4SStefano Zampini   ierr = VecDestroy(&p);CHKERRQ(ierr);
93*9a962809SStefano Zampini 
941ae86dd6SStefano Zampini   /* insert in global quadrature vecs */
951ae86dd6SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank);CHKERRQ(ierr);
96669cc0f4SStefano Zampini   for (i=0;i<nf;i++) {
97669cc0f4SStefano Zampini     const PetscInt    *idxs;
98669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
99669cc0f4SStefano Zampini 
100669cc0f4SStefano Zampini     ierr = ISGetIndices(faces[i],&idxs);CHKERRQ(ierr);
101669cc0f4SStefano Zampini     ierr = ISGetLocalSize(faces[i],&nn);CHKERRQ(ierr);
102669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
1031ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
104669cc0f4SStefano Zampini     idx = -(idx+1);
105669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
106669cc0f4SStefano Zampini     ierr = ISRestoreIndices(faces[i],&idxs);CHKERRQ(ierr);
107669cc0f4SStefano Zampini     ierr = ISDestroy(&faces[i]);CHKERRQ(ierr);
108669cc0f4SStefano Zampini   }
109669cc0f4SStefano Zampini   for (i=0;i<ne;i++) {
110669cc0f4SStefano Zampini     const PetscInt    *idxs;
111669cc0f4SStefano Zampini     PetscInt          idx,nn,j;
112669cc0f4SStefano Zampini 
113669cc0f4SStefano Zampini     ierr = ISGetIndices(edges[i],&idxs);CHKERRQ(ierr);
114669cc0f4SStefano Zampini     ierr = ISGetLocalSize(edges[i],&nn);CHKERRQ(ierr);
115669cc0f4SStefano Zampini     for (j=0;j<nn;j++) vals[j] = array[idxs[j]];
1161ae86dd6SStefano Zampini     ierr = PetscFindInt(rank,graph->count[idxs[0]],graph->neighbours_set[idxs[0]],&idx);CHKERRQ(ierr);
117669cc0f4SStefano Zampini     idx = -(idx+1);
118669cc0f4SStefano Zampini     ierr = VecSetValuesLocal(quad_vecs[idx],nn,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
119669cc0f4SStefano Zampini     ierr = ISRestoreIndices(edges[i],&idxs);CHKERRQ(ierr);
120669cc0f4SStefano Zampini     ierr = ISDestroy(&edges[i]);CHKERRQ(ierr);
121669cc0f4SStefano Zampini   }
122669cc0f4SStefano Zampini   ierr = PetscFree(edges);CHKERRQ(ierr);
123669cc0f4SStefano Zampini   ierr = PetscFree(faces);CHKERRQ(ierr);
124fa23a32eSStefano Zampini   ierr = VecRestoreArrayRead(vins,&array);CHKERRQ(ierr);
125fa23a32eSStefano Zampini   if (vl2l) {
126fa23a32eSStefano Zampini     ierr = VecRestoreSubVector(v,vl2l,&vins);CHKERRQ(ierr);
127fa23a32eSStefano Zampini   }
128669cc0f4SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
129669cc0f4SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
130669cc0f4SStefano Zampini 
131669cc0f4SStefano Zampini   /* assemble near null space */
132669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
133669cc0f4SStefano Zampini     ierr = VecAssemblyBegin(quad_vecs[i]);CHKERRQ(ierr);
134669cc0f4SStefano Zampini   }
135669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
136669cc0f4SStefano Zampini     ierr = VecAssemblyEnd(quad_vecs[i]);CHKERRQ(ierr);
137669cc0f4SStefano Zampini   }
138669cc0f4SStefano Zampini   ierr = VecDestroyVecs(maxneighs,&quad_vecs);CHKERRQ(ierr);
139669cc0f4SStefano Zampini   PetscFunctionReturn(0);
140669cc0f4SStefano Zampini }
141669cc0f4SStefano Zampini 
142669cc0f4SStefano Zampini 
143a3df083aSStefano Zampini #undef __FUNCT__
1441f4df5f7SStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalTopologyInfo"
1451f4df5f7SStefano Zampini PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc)
1461f4df5f7SStefano Zampini {
1471f4df5f7SStefano Zampini   PetscErrorCode ierr;
1481f4df5f7SStefano Zampini   Vec            local,global;
1491f4df5f7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1501f4df5f7SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
1511f4df5f7SStefano Zampini 
1521f4df5f7SStefano Zampini   PetscFunctionBegin;
1531f4df5f7SStefano Zampini   ierr = MatCreateVecs(pc->pmat,&global,NULL);CHKERRQ(ierr);
1541f4df5f7SStefano Zampini   /* need to convert from global to local topology information and remove references to information in global ordering */
1551f4df5f7SStefano Zampini   ierr = MatCreateVecs(matis->A,&local,NULL);CHKERRQ(ierr);
1561f4df5f7SStefano Zampini   if (pcbddc->user_provided_isfordofs) {
1571f4df5f7SStefano Zampini     if (pcbddc->n_ISForDofs) {
1581f4df5f7SStefano Zampini       PetscInt i;
1591f4df5f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
1601f4df5f7SStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
1611f4df5f7SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
1621f4df5f7SStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
1631f4df5f7SStefano Zampini       }
1641f4df5f7SStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
1651f4df5f7SStefano Zampini       pcbddc->n_ISForDofs = 0;
1661f4df5f7SStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
1671f4df5f7SStefano Zampini     }
1681f4df5f7SStefano Zampini   } else {
169986cdee1SStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering if bs > 1 */
1701f4df5f7SStefano Zampini       PetscInt i, n = matis->A->rmap->n;
171986cdee1SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&i);CHKERRQ(ierr);
172986cdee1SStefano Zampini       if (i > 1) {
173986cdee1SStefano Zampini         pcbddc->n_ISForDofsLocal = i;
1741f4df5f7SStefano Zampini         ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
1751f4df5f7SStefano Zampini         for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
1761f4df5f7SStefano Zampini           ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
1771f4df5f7SStefano Zampini         }
1781f4df5f7SStefano Zampini       }
1791f4df5f7SStefano Zampini     }
180986cdee1SStefano Zampini   }
1811f4df5f7SStefano Zampini 
1821f4df5f7SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) {
1831f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
1841f4df5f7SStefano Zampini   }
1851f4df5f7SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) {
1861f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
1871f4df5f7SStefano Zampini   }
1881f4df5f7SStefano Zampini   if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) {
1891f4df5f7SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->rctx,global,local,pcbddc->user_primal_vertices,&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
1901f4df5f7SStefano Zampini   }
1911f4df5f7SStefano Zampini   ierr = VecDestroy(&global);CHKERRQ(ierr);
1921f4df5f7SStefano Zampini   ierr = VecDestroy(&local);CHKERRQ(ierr);
1931f4df5f7SStefano Zampini   PetscFunctionReturn(0);
1941f4df5f7SStefano Zampini }
1951f4df5f7SStefano Zampini 
1961f4df5f7SStefano Zampini #undef __FUNCT__
1973e589ea0SStefano Zampini #define __FUNCT__ "PCBDDCBenignRemoveInterior"
1983e589ea0SStefano Zampini PetscErrorCode PCBDDCBenignRemoveInterior(PC pc,Vec r,Vec z)
1993e589ea0SStefano Zampini {
2003e589ea0SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
2013e589ea0SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
2023e589ea0SStefano Zampini   PetscErrorCode    ierr;
2033e589ea0SStefano Zampini 
2043e589ea0SStefano Zampini   PetscFunctionBegin;
2053e589ea0SStefano Zampini   if (!pcbddc->benign_have_null) {
2063e589ea0SStefano Zampini     PetscFunctionReturn(0);
2073e589ea0SStefano Zampini   }
2083e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2093e589ea0SStefano Zampini     Vec swap;
2103e589ea0SStefano Zampini 
2113e589ea0SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
2123e589ea0SStefano Zampini     swap = pcbddc->work_change;
2133e589ea0SStefano Zampini     pcbddc->work_change = r;
2143e589ea0SStefano Zampini     r = swap;
2153e589ea0SStefano Zampini   }
2163e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2173e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2183e589ea0SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
2193e589ea0SStefano Zampini   ierr = VecSet(z,0.);CHKERRQ(ierr);
2203e589ea0SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2213e589ea0SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2223e589ea0SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2233e589ea0SStefano Zampini     Vec swap;
2243e589ea0SStefano Zampini 
2253e589ea0SStefano Zampini     swap = r;
2263e589ea0SStefano Zampini     r = pcbddc->work_change;
2273e589ea0SStefano Zampini     pcbddc->work_change = swap;
2283e589ea0SStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
2293e589ea0SStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
2303e589ea0SStefano Zampini   }
2313e589ea0SStefano Zampini   PetscFunctionReturn(0);
2323e589ea0SStefano Zampini }
2333e589ea0SStefano Zampini 
2343e589ea0SStefano Zampini #undef __FUNCT__
235a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private_Private"
236a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose)
237a3df083aSStefano Zampini {
238a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
239a3df083aSStefano Zampini   PetscErrorCode          ierr;
240a3df083aSStefano Zampini   PetscBool               apply_right,apply_left,reset_x;
241a3df083aSStefano Zampini 
242a3df083aSStefano Zampini   PetscFunctionBegin;
243a3df083aSStefano Zampini   ierr = MatShellGetContext(A,&ctx);CHKERRQ(ierr);
244a3df083aSStefano Zampini   if (transpose) {
245a3df083aSStefano Zampini     apply_right = ctx->apply_left;
246a3df083aSStefano Zampini     apply_left = ctx->apply_right;
247a3df083aSStefano Zampini   } else {
248a3df083aSStefano Zampini     apply_right = ctx->apply_right;
249a3df083aSStefano Zampini     apply_left = ctx->apply_left;
250a3df083aSStefano Zampini   }
251a3df083aSStefano Zampini   reset_x = PETSC_FALSE;
252a3df083aSStefano Zampini   if (apply_right) {
253a3df083aSStefano Zampini     const PetscScalar *ax;
254a3df083aSStefano Zampini     PetscInt          nl,i;
255a3df083aSStefano Zampini 
256a3df083aSStefano Zampini     ierr = VecGetLocalSize(x,&nl);CHKERRQ(ierr);
257a3df083aSStefano Zampini     ierr = VecGetArrayRead(x,&ax);CHKERRQ(ierr);
258a3df083aSStefano Zampini     ierr = PetscMemcpy(ctx->work,ax,nl*sizeof(PetscScalar));CHKERRQ(ierr);
259a3df083aSStefano Zampini     ierr = VecRestoreArrayRead(x,&ax);CHKERRQ(ierr);
260a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
261a3df083aSStefano Zampini       PetscScalar    sum,val;
262a3df083aSStefano Zampini       const PetscInt *idxs;
263a3df083aSStefano Zampini       PetscInt       nz,j;
264a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
265a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
266a3df083aSStefano Zampini       sum = 0.;
267a3df083aSStefano Zampini       if (ctx->apply_p0) {
268a3df083aSStefano Zampini         val = ctx->work[idxs[nz-1]];
269a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
270a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
271a3df083aSStefano Zampini           ctx->work[idxs[j]] += val;
272a3df083aSStefano Zampini         }
273a3df083aSStefano Zampini       } else {
274a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
275a3df083aSStefano Zampini           sum += ctx->work[idxs[j]];
276a3df083aSStefano Zampini         }
277a3df083aSStefano Zampini       }
278a3df083aSStefano Zampini       ctx->work[idxs[nz-1]] -= sum;
279a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
280a3df083aSStefano Zampini     }
281a3df083aSStefano Zampini     ierr = VecPlaceArray(x,ctx->work);CHKERRQ(ierr);
282a3df083aSStefano Zampini     reset_x = PETSC_TRUE;
283a3df083aSStefano Zampini   }
284a3df083aSStefano Zampini   if (transpose) {
285a3df083aSStefano Zampini     ierr = MatMultTranspose(ctx->A,x,y);CHKERRQ(ierr);
286a3df083aSStefano Zampini   } else {
287a3df083aSStefano Zampini     ierr = MatMult(ctx->A,x,y);CHKERRQ(ierr);
288a3df083aSStefano Zampini   }
289a3df083aSStefano Zampini   if (reset_x) {
290a3df083aSStefano Zampini     ierr = VecResetArray(x);CHKERRQ(ierr);
291a3df083aSStefano Zampini   }
292a3df083aSStefano Zampini   if (apply_left) {
293a3df083aSStefano Zampini     PetscScalar *ay;
294a3df083aSStefano Zampini     PetscInt    i;
295a3df083aSStefano Zampini 
296a3df083aSStefano Zampini     ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
297a3df083aSStefano Zampini     for (i=0;i<ctx->benign_n;i++) {
298a3df083aSStefano Zampini       PetscScalar    sum,val;
299a3df083aSStefano Zampini       const PetscInt *idxs;
300a3df083aSStefano Zampini       PetscInt       nz,j;
301a3df083aSStefano Zampini       ierr = ISGetLocalSize(ctx->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
302a3df083aSStefano Zampini       ierr = ISGetIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
303a3df083aSStefano Zampini       val = -ay[idxs[nz-1]];
304a3df083aSStefano Zampini       if (ctx->apply_p0) {
305a3df083aSStefano Zampini         sum = 0.;
306a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
307a3df083aSStefano Zampini           sum += ay[idxs[j]];
308a3df083aSStefano Zampini           ay[idxs[j]] += val;
309a3df083aSStefano Zampini         }
310a3df083aSStefano Zampini         ay[idxs[nz-1]] += sum;
311a3df083aSStefano Zampini       } else {
312a3df083aSStefano Zampini         for (j=0;j<nz-1;j++) {
313a3df083aSStefano Zampini           ay[idxs[j]] += val;
314a3df083aSStefano Zampini         }
315a3df083aSStefano Zampini         ay[idxs[nz-1]] = 0.;
316a3df083aSStefano Zampini       }
317a3df083aSStefano Zampini       ierr = ISRestoreIndices(ctx->benign_zerodiag_subs[i],&idxs);CHKERRQ(ierr);
318a3df083aSStefano Zampini     }
319a3df083aSStefano Zampini     ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
320a3df083aSStefano Zampini   }
321a3df083aSStefano Zampini   PetscFunctionReturn(0);
322a3df083aSStefano Zampini }
323a3df083aSStefano Zampini 
324a3df083aSStefano Zampini #undef __FUNCT__
325a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMultTranspose_Private"
326a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y)
327a3df083aSStefano Zampini {
328a3df083aSStefano Zampini   PetscErrorCode ierr;
329a3df083aSStefano Zampini 
330a3df083aSStefano Zampini   PetscFunctionBegin;
331a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
332a3df083aSStefano Zampini   PetscFunctionReturn(0);
333a3df083aSStefano Zampini }
334a3df083aSStefano Zampini 
335a3df083aSStefano Zampini #undef __FUNCT__
336a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignMatMult_Private"
337a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y)
338a3df083aSStefano Zampini {
339a3df083aSStefano Zampini   PetscErrorCode ierr;
340a3df083aSStefano Zampini 
341a3df083aSStefano Zampini   PetscFunctionBegin;
342a3df083aSStefano Zampini   ierr = PCBDDCBenignMatMult_Private_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
343a3df083aSStefano Zampini   PetscFunctionReturn(0);
344a3df083aSStefano Zampini }
345a3df083aSStefano Zampini 
346a3df083aSStefano Zampini #undef __FUNCT__
347a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignShellMat"
348a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore)
349a3df083aSStefano Zampini {
350a3df083aSStefano Zampini   PC_IS                   *pcis = (PC_IS*)pc->data;
351a3df083aSStefano Zampini   PC_BDDC                 *pcbddc = (PC_BDDC*)pc->data;
352a3df083aSStefano Zampini   PCBDDCBenignMatMult_ctx ctx;
353a3df083aSStefano Zampini   PetscErrorCode          ierr;
354a3df083aSStefano Zampini 
355a3df083aSStefano Zampini   PetscFunctionBegin;
356a3df083aSStefano Zampini   if (!restore) {
3571dd7afcfSStefano Zampini     Mat                A_IB,A_BI;
358a3df083aSStefano Zampini     PetscScalar        *work;
359b334f244SStefano Zampini     PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL;
360a3df083aSStefano Zampini 
361*9a962809SStefano Zampini     if (pcbddc->benign_original_mat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored");
362*9a962809SStefano Zampini     if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(0);
363a3df083aSStefano Zampini     ierr = PetscMalloc1(pcis->n,&work);CHKERRQ(ierr);
364a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A_IB);CHKERRQ(ierr);
365a3df083aSStefano Zampini     ierr = MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
366a3df083aSStefano Zampini     ierr = MatSetType(A_IB,MATSHELL);CHKERRQ(ierr);
367a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
368a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
369a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
370a3df083aSStefano Zampini     ierr = MatShellSetContext(A_IB,ctx);CHKERRQ(ierr);
371a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
372a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
373a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
374a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
375059032f7SStefano Zampini     if (reuse) {
376a3df083aSStefano Zampini       ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
3771dd7afcfSStefano Zampini       ctx->free = PETSC_FALSE;
378059032f7SStefano Zampini     } else { /* TODO: could be optimized for successive solves */
379059032f7SStefano Zampini       ISLocalToGlobalMapping N_to_D;
380059032f7SStefano Zampini       PetscInt               i;
381059032f7SStefano Zampini 
382059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D);CHKERRQ(ierr);
383059032f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs);CHKERRQ(ierr);
384059032f7SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
385059032f7SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
386059032f7SStefano Zampini       }
387059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&N_to_D);CHKERRQ(ierr);
3881dd7afcfSStefano Zampini       ctx->free = PETSC_TRUE;
389059032f7SStefano Zampini     }
390a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
391a3df083aSStefano Zampini     ctx->work = work;
392a3df083aSStefano Zampini     ierr = MatSetUp(A_IB);CHKERRQ(ierr);
393a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
394a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
395a3df083aSStefano Zampini     pcis->A_IB = A_IB;
396a3df083aSStefano Zampini 
397a3df083aSStefano Zampini     /* A_BI as A_IB^T */
398a3df083aSStefano Zampini     ierr = MatCreateTranspose(A_IB,&A_BI);CHKERRQ(ierr);
399a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
400a3df083aSStefano Zampini     pcis->A_BI = A_BI;
401a3df083aSStefano Zampini   } else {
4021dd7afcfSStefano Zampini     if (!pcbddc->benign_original_mat) {
4031dd7afcfSStefano Zampini       PetscFunctionReturn(0);
4041dd7afcfSStefano Zampini     }
405a3df083aSStefano Zampini     ierr = MatShellGetContext(pcis->A_IB,&ctx);CHKERRQ(ierr);
406a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
407a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
4081dd7afcfSStefano Zampini     ctx->A = NULL;
4091dd7afcfSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
4101dd7afcfSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
4111dd7afcfSStefano Zampini     pcbddc->benign_original_mat = NULL;
4121dd7afcfSStefano Zampini     if (ctx->free) {
413059032f7SStefano Zampini       PetscInt i;
4141dd7afcfSStefano Zampini       for (i=0;i<ctx->benign_n;i++) {
415059032f7SStefano Zampini         ierr = ISDestroy(&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
416059032f7SStefano Zampini       }
417059032f7SStefano Zampini       ierr = PetscFree(ctx->benign_zerodiag_subs);CHKERRQ(ierr);
418059032f7SStefano Zampini     }
419a3df083aSStefano Zampini     ierr = PetscFree(ctx->work);CHKERRQ(ierr);
420a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
421a3df083aSStefano Zampini   }
422a3df083aSStefano Zampini   PetscFunctionReturn(0);
423a3df083aSStefano Zampini }
424a3df083aSStefano Zampini 
425a3df083aSStefano Zampini /* used just in bddc debug mode */
426a3df083aSStefano Zampini #undef __FUNCT__
427a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignProject"
428a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
429a3df083aSStefano Zampini {
430a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
431a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
432a3df083aSStefano Zampini   Mat            An;
433a3df083aSStefano Zampini   PetscErrorCode ierr;
434a3df083aSStefano Zampini 
435a3df083aSStefano Zampini   PetscFunctionBegin;
436a3df083aSStefano Zampini   ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An);CHKERRQ(ierr);
437a3df083aSStefano Zampini   ierr = MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL);CHKERRQ(ierr);
438a3df083aSStefano Zampini   if (is1) {
439a3df083aSStefano Zampini     ierr = MatGetSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
440a3df083aSStefano Zampini     ierr = MatDestroy(&An);CHKERRQ(ierr);
441a3df083aSStefano Zampini   } else {
442a3df083aSStefano Zampini     *B = An;
443a3df083aSStefano Zampini   }
444a3df083aSStefano Zampini   PetscFunctionReturn(0);
445a3df083aSStefano Zampini }
446a3df083aSStefano Zampini 
4471cf9b237SStefano Zampini /* TODO: add reuse flag */
4481cf9b237SStefano Zampini #undef __FUNCT__
4491cf9b237SStefano Zampini #define __FUNCT__ "MatSeqAIJCompress"
4501cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
4511cf9b237SStefano Zampini {
4521cf9b237SStefano Zampini   Mat            Bt;
4531cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
4541cf9b237SStefano Zampini   const PetscInt *ii,*ij;
4551cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
4561cf9b237SStefano Zampini   PetscBool      flg_row;
4571cf9b237SStefano Zampini   PetscErrorCode ierr;
4581cf9b237SStefano Zampini 
4591cf9b237SStefano Zampini   PetscFunctionBegin;
4601cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
4611cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
4621cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
4631cf9b237SStefano Zampini   nnz = n;
4641cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
4651cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
4661cf9b237SStefano Zampini   }
4671cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
4681cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
4691cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
4701cf9b237SStefano Zampini   nnz = 0;
4711cf9b237SStefano Zampini   bii[0] = 0;
4721cf9b237SStefano Zampini   for (i=0;i<n;i++) {
4731cf9b237SStefano Zampini     PetscInt j;
4741cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
4751cf9b237SStefano Zampini       PetscScalar entry = a[j];
4761cf9b237SStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || ij[j] == i) {
4771cf9b237SStefano Zampini         bij[nnz] = ij[j];
4781cf9b237SStefano Zampini         bdata[nnz] = entry;
4791cf9b237SStefano Zampini         nnz++;
4801cf9b237SStefano Zampini       }
4811cf9b237SStefano Zampini     }
4821cf9b237SStefano Zampini     bii[i+1] = nnz;
4831cf9b237SStefano Zampini   }
4841cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
4851cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
4861cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
4871cf9b237SStefano Zampini   {
4881cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
4891cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
4901cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
4911cf9b237SStefano Zampini   }
4921cf9b237SStefano Zampini   *B = Bt;
4931cf9b237SStefano Zampini   PetscFunctionReturn(0);
4941cf9b237SStefano Zampini }
4951cf9b237SStefano Zampini 
496674ae819SStefano Zampini #undef __FUNCT__
4974f1b2e48SStefano Zampini #define __FUNCT__ "MatDetectDisconnectedComponents"
4984f1b2e48SStefano Zampini PetscErrorCode MatDetectDisconnectedComponents(Mat A, PetscBool filter, PetscInt *ncc, IS* cc[])
4994f1b2e48SStefano Zampini {
5004f1b2e48SStefano Zampini   Mat                    B;
5014f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
5024f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
5034f1b2e48SStefano Zampini   PCBDDCGraph            graph;
5044f1b2e48SStefano Zampini   PetscInt               i,n;
5054f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
5064f1b2e48SStefano Zampini   PetscInt               *xadj_filtered,*adjncy_filtered;
5074f1b2e48SStefano Zampini   PetscBool              flg_row,isseqaij;
5084f1b2e48SStefano Zampini   PetscErrorCode         ierr;
5094f1b2e48SStefano Zampini 
5104f1b2e48SStefano Zampini   PetscFunctionBegin;
51163c961adSStefano Zampini   if (!A->rmap->N || !A->cmap->N) {
51263c961adSStefano Zampini     *ncc = 0;
51363c961adSStefano Zampini     *cc = NULL;
51463c961adSStefano Zampini     PetscFunctionReturn(0);
51563c961adSStefano Zampini   }
5164f1b2e48SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
5174f1b2e48SStefano Zampini   if (!isseqaij && filter) {
5181cf9b237SStefano Zampini     PetscBool isseqdense;
5191cf9b237SStefano Zampini 
5201cf9b237SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
5211cf9b237SStefano Zampini     if (!isseqdense) {
5224f1b2e48SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
5231cf9b237SStefano Zampini     } else { /* TODO: rectangular case and LDA */
5241cf9b237SStefano Zampini       PetscScalar *array;
5251cf9b237SStefano Zampini       PetscReal   chop=1.e-6;
5261cf9b237SStefano Zampini 
5271cf9b237SStefano Zampini       ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
5281cf9b237SStefano Zampini       ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
5291cf9b237SStefano Zampini       ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
5301cf9b237SStefano Zampini       for (i=0;i<n;i++) {
5311cf9b237SStefano Zampini         PetscInt j;
5321cf9b237SStefano Zampini         for (j=i+1;j<n;j++) {
5331cf9b237SStefano Zampini           PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
5341cf9b237SStefano Zampini           if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
5351cf9b237SStefano Zampini           if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
5361cf9b237SStefano Zampini         }
5371cf9b237SStefano Zampini       }
5381cf9b237SStefano Zampini       ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
5399d54b7f4SStefano Zampini       ierr = MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
5401cf9b237SStefano Zampini     }
5414f1b2e48SStefano Zampini   } else {
5424f1b2e48SStefano Zampini     B = A;
5434f1b2e48SStefano Zampini   }
5444f1b2e48SStefano Zampini   ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
5454f1b2e48SStefano Zampini 
5464f1b2e48SStefano Zampini   /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
5474f1b2e48SStefano Zampini   if (filter) {
5484f1b2e48SStefano Zampini     PetscScalar *data;
5494f1b2e48SStefano Zampini     PetscInt    j,cum;
5504f1b2e48SStefano Zampini 
5514f1b2e48SStefano Zampini     ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
5524f1b2e48SStefano Zampini     ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
5534f1b2e48SStefano Zampini     cum = 0;
5544f1b2e48SStefano Zampini     for (i=0;i<n;i++) {
5554f1b2e48SStefano Zampini       PetscInt t;
5564f1b2e48SStefano Zampini 
5574f1b2e48SStefano Zampini       for (j=xadj[i];j<xadj[i+1];j++) {
5584f1b2e48SStefano Zampini         if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
5594f1b2e48SStefano Zampini           continue;
5604f1b2e48SStefano Zampini         }
5614f1b2e48SStefano Zampini         adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
5624f1b2e48SStefano Zampini       }
5634f1b2e48SStefano Zampini       t = xadj_filtered[i];
5644f1b2e48SStefano Zampini       xadj_filtered[i] = cum;
5654f1b2e48SStefano Zampini       cum += t;
5664f1b2e48SStefano Zampini     }
5674f1b2e48SStefano Zampini     ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
5684f1b2e48SStefano Zampini   } else {
5694f1b2e48SStefano Zampini     xadj_filtered = NULL;
5704f1b2e48SStefano Zampini     adjncy_filtered = NULL;
5714f1b2e48SStefano Zampini   }
5724f1b2e48SStefano Zampini 
5734f1b2e48SStefano Zampini   /* compute local connected components using PCBDDCGraph */
5744f1b2e48SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
5754f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
5764f1b2e48SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
5774f1b2e48SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
5784f1b2e48SStefano Zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n);CHKERRQ(ierr);
5794f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
5804f1b2e48SStefano Zampini   if (xadj_filtered) {
5814f1b2e48SStefano Zampini     graph->xadj = xadj_filtered;
5824f1b2e48SStefano Zampini     graph->adjncy = adjncy_filtered;
5834f1b2e48SStefano Zampini   } else {
5844f1b2e48SStefano Zampini     graph->xadj = xadj;
5854f1b2e48SStefano Zampini     graph->adjncy = adjncy;
5864f1b2e48SStefano Zampini   }
5874f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
5884f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
5894f1b2e48SStefano Zampini   /* partial clean up */
5904f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
5914f1b2e48SStefano Zampini   ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
5921cf9b237SStefano Zampini   if (A != B) {
5934f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
5944f1b2e48SStefano Zampini   }
5954f1b2e48SStefano Zampini 
5964f1b2e48SStefano Zampini   /* get back data */
5971cf9b237SStefano Zampini   if (ncc) *ncc = graph->ncc;
5981cf9b237SStefano Zampini   if (cc) {
5994f1b2e48SStefano Zampini     ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
6004f1b2e48SStefano Zampini     for (i=0;i<graph->ncc;i++) {
6014f1b2e48SStefano 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);
6024f1b2e48SStefano Zampini     }
6034f1b2e48SStefano Zampini     *cc = cc_n;
6041cf9b237SStefano Zampini   }
6054f1b2e48SStefano Zampini   /* clean up graph */
6064f1b2e48SStefano Zampini   graph->xadj = 0;
6074f1b2e48SStefano Zampini   graph->adjncy = 0;
6084f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
6094f1b2e48SStefano Zampini   PetscFunctionReturn(0);
6104f1b2e48SStefano Zampini }
6114f1b2e48SStefano Zampini 
6124f1b2e48SStefano Zampini #undef __FUNCT__
6135408967cSStefano Zampini #define __FUNCT__ "PCBDDCBenignCheck"
6145408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
6155408967cSStefano Zampini {
6165408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
6175408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
618dee84bffSStefano Zampini   IS             dirIS = NULL;
6194f1b2e48SStefano Zampini   PetscInt       i;
6205408967cSStefano Zampini   PetscErrorCode ierr;
6215408967cSStefano Zampini 
6225408967cSStefano Zampini   PetscFunctionBegin;
623dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
6245408967cSStefano Zampini   if (zerodiag) {
6255408967cSStefano Zampini     Mat            A;
6265408967cSStefano Zampini     Vec            vec3_N;
6275408967cSStefano Zampini     PetscScalar    *vals;
6285408967cSStefano Zampini     const PetscInt *idxs;
629d12d3064SStefano Zampini     PetscInt       nz,*count;
6305408967cSStefano Zampini 
6315408967cSStefano Zampini     /* p0 */
6325408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
6335408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
6345408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
6355408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
6364f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
6375408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
6385408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6395408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6405408967cSStefano Zampini     /* v_I */
6415408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
6425408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
6435408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
6445408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
6455408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
6465408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
6475408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
6485408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
6495408967cSStefano Zampini     if (dirIS) {
6505408967cSStefano Zampini       PetscInt n;
6515408967cSStefano Zampini 
6525408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
6535408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
6545408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
6555408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
6565408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
6575408967cSStefano Zampini     }
6585408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
6595408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
6605408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
6615408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
662669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
6635408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
6645408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
665*9a962809SStefano Zampini     if (PetscAbsScalar(vals[0]) > 1.e-1) 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]));
6665408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
6675408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
668d12d3064SStefano Zampini 
669d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
670d12d3064SStefano Zampini     ierr = PetscCalloc1(pcis->n,&count);CHKERRQ(ierr);
671d12d3064SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
672d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
673d12d3064SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
674d12d3064SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
675*9a962809SStefano Zampini     for (i=0;i<nz;i++) if (count[idxs[i]]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! pressure dof %d is an interface dof",idxs[i]);
676d12d3064SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
677d12d3064SStefano Zampini     ierr = PetscFree(count);CHKERRQ(ierr);
6785408967cSStefano Zampini   }
679dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
6805408967cSStefano Zampini 
6815408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
6825408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
6834f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
6845408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
6854f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
6865408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
687*9a962809SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) if ((PetscInt)PetscRealPart(pcbddc->benign_p0[i]) != -PetscGlobalRank-i) 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);
6885408967cSStefano Zampini   PetscFunctionReturn(0);
6895408967cSStefano Zampini }
6905408967cSStefano Zampini 
6915408967cSStefano Zampini #undef __FUNCT__
692339f8db1SStefano Zampini #define __FUNCT__ "PCBDDCBenignDetectSaddlePoint"
693339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
694339f8db1SStefano Zampini {
695339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
6964f1b2e48SStefano Zampini   IS             pressures,zerodiag,*zerodiag_subs;
697b0f5fe93SStefano Zampini   PetscInt       nz,n;
6981f4df5f7SStefano Zampini   PetscInt       *interior_dofs,n_interior_dofs;
6994f1b2e48SStefano Zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag;
700339f8db1SStefano Zampini   PetscErrorCode ierr;
701339f8db1SStefano Zampini 
702339f8db1SStefano Zampini   PetscFunctionBegin;
7039f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
7049f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
705a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
706a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
707a3df083aSStefano Zampini   }
708a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
709a3df083aSStefano Zampini   pcbddc->benign_n = 0;
7101ae86dd6SStefano Zampini   /* if a local info on dofs is present, assumes that the last field represents  "pressures"
7114f1b2e48SStefano Zampini      otherwise, it uses only zerodiagonal dofs (ok if the pressure block is all zero; it could fail if it is not)
7124f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
7134f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
7141ae86dd6SStefano Zampini      since the local Schur complements are already SPD
7154f1b2e48SStefano Zampini   */
7164f1b2e48SStefano Zampini   has_null_pressures = PETSC_TRUE;
7174f1b2e48SStefano Zampini   have_null = PETSC_TRUE;
71840fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
7194f1b2e48SStefano Zampini     PetscInt npl,*idxs,p = pcbddc->n_ISForDofsLocal-1;
7204f1b2e48SStefano Zampini 
7214f1b2e48SStefano Zampini     /* Dofs splitting for BDDC cannot have PETSC_COMM_SELF, so create a sequential IS */
7224f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[p],&npl);CHKERRQ(ierr);
7234f1b2e48SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
7244f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,npl,idxs,PETSC_COPY_VALUES,&pressures);CHKERRQ(ierr);
725ba14f8e3SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
72640fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
72740fa8d13SStefano Zampini     if (!sorted) {
72840fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
72940fa8d13SStefano Zampini     }
73040fa8d13SStefano Zampini   } else {
73140fa8d13SStefano Zampini     pressures = NULL;
73240fa8d13SStefano Zampini   }
73397d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
73497d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
73527b6a85dSStefano Zampini   if (!n) pcbddc->benign_change_explicit = PETSC_TRUE;
73697d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
737339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
738339f8db1SStefano Zampini   if (!sorted) {
739339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
740339f8db1SStefano Zampini   }
741339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
7424f1b2e48SStefano Zampini   if (!nz) {
7434f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
7444f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
74540fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
74640fa8d13SStefano Zampini   }
7474f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
7484f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
7494f1b2e48SStefano Zampini   zerodiag_subs = NULL;
7504f1b2e48SStefano Zampini   pcbddc->benign_n = 0;
7511f4df5f7SStefano Zampini   n_interior_dofs = 0;
7521f4df5f7SStefano Zampini   interior_dofs = NULL;
7531f4df5f7SStefano Zampini   if (pcbddc->current_level) { /* need to compute interior nodes */
7541f4df5f7SStefano Zampini     PetscInt n,i,j;
7551f4df5f7SStefano Zampini     PetscInt n_neigh,*neigh,*n_shared,**shared;
7561f4df5f7SStefano Zampini     PetscInt *iwork;
7571f4df5f7SStefano Zampini 
7581f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(pc->pmat->rmap->mapping,&n);CHKERRQ(ierr);
7591f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
7601f4df5f7SStefano Zampini     ierr = PetscCalloc1(n,&iwork);CHKERRQ(ierr);
7611f4df5f7SStefano Zampini     ierr = PetscMalloc1(n,&interior_dofs);CHKERRQ(ierr);
7621f4df5f7SStefano Zampini     for (i=0;i<n_neigh;i++)
7631f4df5f7SStefano Zampini       for (j=0;j<n_shared[i];j++)
7641f4df5f7SStefano Zampini           iwork[shared[i][j]] += 1;
7651f4df5f7SStefano Zampini     for (i=0;i<n;i++)
7661f4df5f7SStefano Zampini       if (!iwork[i])
7671f4df5f7SStefano Zampini         interior_dofs[n_interior_dofs++] = i;
7681f4df5f7SStefano Zampini     ierr = PetscFree(iwork);CHKERRQ(ierr);
7691f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
7701f4df5f7SStefano Zampini   }
7714f1b2e48SStefano Zampini   if (has_null_pressures) {
7724f1b2e48SStefano Zampini     IS             *subs;
7731f4df5f7SStefano Zampini     PetscInt       nsubs,i,j,nl;
7741f4df5f7SStefano Zampini     const PetscInt *idxs;
7751f4df5f7SStefano Zampini     PetscScalar    *array;
7761f4df5f7SStefano Zampini     Vec            *work;
7771f4df5f7SStefano Zampini     Mat_IS*        matis = (Mat_IS*)(pc->pmat->data);
7784f1b2e48SStefano Zampini 
7794f1b2e48SStefano Zampini     subs = pcbddc->local_subs;
7804f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
7811f4df5f7SStefano 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) */
7821f4df5f7SStefano Zampini     if (pcbddc->current_level) {
7831f4df5f7SStefano Zampini       ierr = VecDuplicateVecs(matis->y,2,&work);CHKERRQ(ierr);
7841f4df5f7SStefano Zampini       ierr = ISGetLocalSize(zerodiag,&nl);CHKERRQ(ierr);
7851f4df5f7SStefano Zampini       ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
7861f4df5f7SStefano Zampini       /* work[0] = 1_p */
7871f4df5f7SStefano Zampini       ierr = VecSet(work[0],0.);CHKERRQ(ierr);
7881f4df5f7SStefano Zampini       ierr = VecGetArray(work[0],&array);CHKERRQ(ierr);
7891f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 1.;
7901f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[0],&array);CHKERRQ(ierr);
7911f4df5f7SStefano Zampini       /* work[0] = 1_v */
7921f4df5f7SStefano Zampini       ierr = VecSet(work[1],1.);CHKERRQ(ierr);
7931f4df5f7SStefano Zampini       ierr = VecGetArray(work[1],&array);CHKERRQ(ierr);
7941f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 0.;
7951f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[1],&array);CHKERRQ(ierr);
7961f4df5f7SStefano Zampini       ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
7971f4df5f7SStefano Zampini     }
7984f1b2e48SStefano Zampini     if (nsubs > 1) {
7994f1b2e48SStefano Zampini       ierr = PetscCalloc1(nsubs,&zerodiag_subs);CHKERRQ(ierr);
8004f1b2e48SStefano Zampini       for (i=0;i<nsubs;i++) {
8014f1b2e48SStefano Zampini         ISLocalToGlobalMapping l2g;
8024f1b2e48SStefano Zampini         IS                     t_zerodiag_subs;
8034f1b2e48SStefano Zampini         PetscInt               nl;
8044f1b2e48SStefano Zampini 
8054f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
8064f1b2e48SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,zerodiag,&t_zerodiag_subs);CHKERRQ(ierr);
8074f1b2e48SStefano Zampini         ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
8084f1b2e48SStefano Zampini         if (nl) {
8094f1b2e48SStefano Zampini           PetscBool valid = PETSC_TRUE;
8104f1b2e48SStefano Zampini 
8111f4df5f7SStefano Zampini           if (pcbddc->current_level) {
8121f4df5f7SStefano Zampini             ierr = VecSet(matis->x,0);CHKERRQ(ierr);
8131f4df5f7SStefano Zampini             ierr = ISGetLocalSize(subs[i],&nl);CHKERRQ(ierr);
8141f4df5f7SStefano Zampini             ierr = ISGetIndices(subs[i],&idxs);CHKERRQ(ierr);
8151f4df5f7SStefano Zampini             ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
8161f4df5f7SStefano Zampini             for (j=0;j<nl;j++) array[idxs[j]] = 1.;
8171f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
8181f4df5f7SStefano Zampini             ierr = ISRestoreIndices(subs[i],&idxs);CHKERRQ(ierr);
8191f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->x,work[0],matis->x);CHKERRQ(ierr);
8201f4df5f7SStefano Zampini             ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
8211f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->y,work[1],matis->y);CHKERRQ(ierr);
8221f4df5f7SStefano Zampini             ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
8231f4df5f7SStefano Zampini             for (j=0;j<n_interior_dofs;j++) {
8241f4df5f7SStefano Zampini               if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
8251f4df5f7SStefano Zampini                 valid = PETSC_FALSE;
8261f4df5f7SStefano Zampini                 break;
8271f4df5f7SStefano Zampini               }
8281f4df5f7SStefano Zampini             }
8291f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
8301f4df5f7SStefano Zampini           }
8311f4df5f7SStefano Zampini           if (valid && pcbddc->NeumannBoundariesLocal) {
8321f4df5f7SStefano Zampini             IS       t_bc;
8331f4df5f7SStefano Zampini             PetscInt nzb;
8341f4df5f7SStefano Zampini 
8351f4df5f7SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pcbddc->NeumannBoundariesLocal,&t_bc);CHKERRQ(ierr);
8361f4df5f7SStefano Zampini             ierr = ISGetLocalSize(t_bc,&nzb);CHKERRQ(ierr);
8371f4df5f7SStefano Zampini             ierr = ISDestroy(&t_bc);CHKERRQ(ierr);
8381f4df5f7SStefano Zampini             if (nzb) valid = PETSC_FALSE;
8391f4df5f7SStefano Zampini           }
8401f4df5f7SStefano Zampini           if (valid && pressures) {
8414f1b2e48SStefano Zampini             IS t_pressure_subs;
8424f1b2e48SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
8434f1b2e48SStefano Zampini             ierr = ISEqual(t_pressure_subs,t_zerodiag_subs,&valid);CHKERRQ(ierr);
8444f1b2e48SStefano Zampini             ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
8454f1b2e48SStefano Zampini           }
8464f1b2e48SStefano Zampini           if (valid) {
8474f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[pcbddc->benign_n]);CHKERRQ(ierr);
8484f1b2e48SStefano Zampini             pcbddc->benign_n++;
8494f1b2e48SStefano Zampini           } else {
8504f1b2e48SStefano Zampini             recompute_zerodiag = PETSC_TRUE;
8514f1b2e48SStefano Zampini           }
8524f1b2e48SStefano Zampini         }
8534f1b2e48SStefano Zampini         ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
8544f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
8554f1b2e48SStefano Zampini       }
8564f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
8574f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
8581f4df5f7SStefano Zampini 
8591f4df5f7SStefano Zampini       if (pcbddc->NeumannBoundariesLocal) {
8601f4df5f7SStefano Zampini         PetscInt nzb;
8611f4df5f7SStefano Zampini         ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nzb);CHKERRQ(ierr);
8621f4df5f7SStefano Zampini         if (nzb) valid = PETSC_FALSE;
8631f4df5f7SStefano Zampini       }
8641f4df5f7SStefano Zampini       if (valid && pressures) {
8654f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
8664f1b2e48SStefano Zampini       }
8671f4df5f7SStefano Zampini       if (valid && pcbddc->current_level) {
8681f4df5f7SStefano Zampini         ierr = MatMult(matis->A,work[0],matis->x);CHKERRQ(ierr);
8691f4df5f7SStefano Zampini         ierr = VecPointwiseMult(matis->x,work[1],matis->x);CHKERRQ(ierr);
8701f4df5f7SStefano Zampini         ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
8711f4df5f7SStefano Zampini         for (j=0;j<n_interior_dofs;j++) {
8721f4df5f7SStefano Zampini             if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
8731f4df5f7SStefano Zampini               valid = PETSC_FALSE;
8741f4df5f7SStefano Zampini               break;
8751f4df5f7SStefano Zampini           }
8761f4df5f7SStefano Zampini         }
8771f4df5f7SStefano Zampini         ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
8781f4df5f7SStefano Zampini       }
8794f1b2e48SStefano Zampini       if (valid) {
8804f1b2e48SStefano Zampini         pcbddc->benign_n = 1;
881ca92afb2SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&zerodiag_subs);CHKERRQ(ierr);
8824f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
8834f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
8844f1b2e48SStefano Zampini       }
8854f1b2e48SStefano Zampini     }
8861f4df5f7SStefano Zampini     if (pcbddc->current_level) {
8871f4df5f7SStefano Zampini       ierr = VecDestroyVecs(2,&work);CHKERRQ(ierr);
8884f1b2e48SStefano Zampini     }
8891f4df5f7SStefano Zampini   }
8901f4df5f7SStefano Zampini   ierr = PetscFree(interior_dofs);CHKERRQ(ierr);
8914f1b2e48SStefano Zampini 
8924f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
893b9b0e38cSStefano Zampini     PetscInt n;
894b9b0e38cSStefano Zampini 
8954f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
8964f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
897b9b0e38cSStefano Zampini     ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
898b9b0e38cSStefano Zampini     if (n) {
8994f1b2e48SStefano Zampini       has_null_pressures = PETSC_FALSE;
9004f1b2e48SStefano Zampini       have_null = PETSC_FALSE;
9014f1b2e48SStefano Zampini     }
902b9b0e38cSStefano Zampini   }
9034f1b2e48SStefano Zampini 
9044f1b2e48SStefano Zampini   /* final check for null pressures */
9054f1b2e48SStefano Zampini   if (zerodiag && pressures) {
9064f1b2e48SStefano Zampini     PetscInt nz,np;
9074f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
9084f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
9094f1b2e48SStefano Zampini     if (nz != np) have_null = PETSC_FALSE;
9104f1b2e48SStefano Zampini   }
9114f1b2e48SStefano Zampini 
9124f1b2e48SStefano Zampini   if (recompute_zerodiag) {
9134f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
9144f1b2e48SStefano Zampini     if (pcbddc->benign_n == 1) {
9154f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
9164f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
9174f1b2e48SStefano Zampini     } else {
9184f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
9194f1b2e48SStefano Zampini 
9204f1b2e48SStefano Zampini       nzn = 0;
9214f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
9224f1b2e48SStefano Zampini         PetscInt ns;
9234f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
9244f1b2e48SStefano Zampini         nzn += ns;
9254f1b2e48SStefano Zampini       }
9264f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
9274f1b2e48SStefano Zampini       nzn = 0;
9284f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
9294f1b2e48SStefano Zampini         PetscInt ns,*idxs;
9304f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
9314f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
9324f1b2e48SStefano Zampini         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
9334f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
9344f1b2e48SStefano Zampini         nzn += ns;
9354f1b2e48SStefano Zampini       }
9364f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
9374f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
9384f1b2e48SStefano Zampini     }
9394f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
9404f1b2e48SStefano Zampini   }
9414f1b2e48SStefano Zampini 
942669cc0f4SStefano Zampini   /* Prepare matrix to compute no-net-flux */
943a198735bSStefano Zampini   if (pcbddc->compute_nonetflux && !pcbddc->divudotp) {
944a198735bSStefano Zampini     Mat                    A,loc_divudotp;
945a198735bSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g,l2gmap;
946a198735bSStefano Zampini     IS                     row,col,isused = NULL;
947a198735bSStefano Zampini     PetscInt               M,N,n,st,n_isused;
948a198735bSStefano Zampini 
9491f4df5f7SStefano Zampini     if (pressures) {
9501f4df5f7SStefano Zampini       isused = pressures;
9511f4df5f7SStefano Zampini     } else {
9521f4df5f7SStefano Zampini       isused = zerodiag;
9531f4df5f7SStefano Zampini     }
954a198735bSStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&l2gmap,NULL);CHKERRQ(ierr);
955669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
9561ae86dd6SStefano Zampini     ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
9571ae86dd6SStefano 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");
958a198735bSStefano Zampini     n_isused = 0;
959a198735bSStefano Zampini     if (isused) {
960a198735bSStefano Zampini       ierr = ISGetLocalSize(isused,&n_isused);CHKERRQ(ierr);
961a198735bSStefano Zampini     }
962a198735bSStefano Zampini     ierr = MPI_Scan(&n_isused,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
963a198735bSStefano Zampini     st = st-n_isused;
9641ae86dd6SStefano Zampini     if (n) {
965a198735bSStefano Zampini       const PetscInt *gidxs;
966a198735bSStefano Zampini 
967a198735bSStefano Zampini       ierr = MatGetSubMatrix(A,isused,NULL,MAT_INITIAL_MATRIX,&loc_divudotp);CHKERRQ(ierr);
968a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
969a198735bSStefano Zampini       /* TODO: extend ISCreateStride with st = PETSC_DECIDE */
970a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
971a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
972a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
9731ae86dd6SStefano Zampini     } else {
974a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&loc_divudotp);CHKERRQ(ierr);
975a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
976a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),0,NULL,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
977a198735bSStefano Zampini     }
978a198735bSStefano Zampini     ierr = MatGetSize(pc->pmat,NULL,&N);CHKERRQ(ierr);
979a198735bSStefano Zampini     ierr = ISGetSize(row,&M);CHKERRQ(ierr);
980a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
981a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
982a198735bSStefano Zampini     ierr = ISDestroy(&row);CHKERRQ(ierr);
983a198735bSStefano Zampini     ierr = ISDestroy(&col);CHKERRQ(ierr);
984a198735bSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->divudotp);CHKERRQ(ierr);
985a198735bSStefano Zampini     ierr = MatSetType(pcbddc->divudotp,MATIS);CHKERRQ(ierr);
986a198735bSStefano Zampini     ierr = MatSetSizes(pcbddc->divudotp,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
987a198735bSStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->divudotp,rl2g,cl2g);CHKERRQ(ierr);
988a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
989a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
990a198735bSStefano Zampini     ierr = MatISSetLocalMat(pcbddc->divudotp,loc_divudotp);CHKERRQ(ierr);
991a198735bSStefano Zampini     ierr = MatDestroy(&loc_divudotp);CHKERRQ(ierr);
9921ae86dd6SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9931ae86dd6SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9941ae86dd6SStefano Zampini   }
995b3afcdbeSStefano Zampini 
996b3afcdbeSStefano Zampini   /* change of basis and p0 dofs */
9974f1b2e48SStefano Zampini   if (has_null_pressures) {
9984f1b2e48SStefano Zampini     IS             zerodiagc;
9994f1b2e48SStefano Zampini     const PetscInt *idxs,*idxsc;
10004f1b2e48SStefano Zampini     PetscInt       i,s,*nnz;
10014f1b2e48SStefano Zampini 
10024f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
1003339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
1004339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
1005339f8db1SStefano Zampini     /* local change of basis for pressures */
1006339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
100797d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
1008339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
1009339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1010339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
10114f1b2e48SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities plus pressure dofs for non-singular subdomains */
10124f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
10134f1b2e48SStefano Zampini       PetscInt nzs,j;
10144f1b2e48SStefano Zampini 
10154f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[i],&nzs);CHKERRQ(ierr);
10164f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
10174f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
10184f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
10194f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
10204f1b2e48SStefano Zampini     }
1021339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
1022339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
1023339f8db1SStefano Zampini     /* set identity on velocities */
1024339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
1025339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
1026339f8db1SStefano Zampini     }
10274f1b2e48SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
10284f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
10299f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
10304f1b2e48SStefano 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);
1031339f8db1SStefano Zampini     /* set change on pressures */
10324f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
10334f1b2e48SStefano Zampini       PetscScalar *array;
10344f1b2e48SStefano Zampini       PetscInt    nzs;
10354f1b2e48SStefano Zampini 
10364f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[s],&nzs);CHKERRQ(ierr);
10374f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
10384f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
1039339f8db1SStefano Zampini         PetscScalar vals[2];
1040339f8db1SStefano Zampini         PetscInt    cols[2];
1041339f8db1SStefano Zampini 
1042339f8db1SStefano Zampini         cols[0] = idxs[i];
10434f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
1044339f8db1SStefano Zampini         vals[0] = 1.;
1045b0f5fe93SStefano Zampini         vals[1] = 1.;
10464f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
1047339f8db1SStefano Zampini       }
10484f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
10494f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
10504f1b2e48SStefano Zampini       array[nzs-1] = 1.;
10514f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
10524f1b2e48SStefano Zampini       /* store local idxs for p0 */
10534f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
10544f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
1055339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
10564f1b2e48SStefano Zampini     }
1057339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1058339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1059a3df083aSStefano Zampini     /* project if needed */
1060a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
10611dd7afcfSStefano Zampini       Mat M;
10621dd7afcfSStefano Zampini 
10631dd7afcfSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
1064339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
10651dd7afcfSStefano Zampini       ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
10661dd7afcfSStefano Zampini       ierr = MatDestroy(&M);CHKERRQ(ierr);
1067a3df083aSStefano Zampini     }
10684f1b2e48SStefano Zampini     /* store global idxs for p0 */
10694f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
1070339f8db1SStefano Zampini   }
1071ca92afb2SStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
10724f1b2e48SStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
1073b0f5fe93SStefano Zampini 
1074b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
1075b0f5fe93SStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
107627b6a85dSStefano Zampini   /* determines if the problem has subdomains with 0 pressure block */
107727b6a85dSStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1078339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
1079339f8db1SStefano Zampini   PetscFunctionReturn(0);
1080339f8db1SStefano Zampini }
1081339f8db1SStefano Zampini 
1082339f8db1SStefano Zampini #undef __FUNCT__
1083015636ebSStefano Zampini #define __FUNCT__ "PCBDDCBenignGetOrSetP0"
1084015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
1085efc2fbd9SStefano Zampini {
1086efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
1087de9d7bd0SStefano Zampini   PetscScalar    *array;
1088efc2fbd9SStefano Zampini   PetscErrorCode ierr;
1089efc2fbd9SStefano Zampini 
1090efc2fbd9SStefano Zampini   PetscFunctionBegin;
1091efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
1092efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
10934f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
1094efc2fbd9SStefano Zampini   }
1095de9d7bd0SStefano Zampini   if (get) {
1096efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
10974f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
10984f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
1099efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
1100de9d7bd0SStefano Zampini   } else {
1101de9d7bd0SStefano Zampini     ierr = VecGetArray(v,&array);CHKERRQ(ierr);
1102de9d7bd0SStefano Zampini     ierr = PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
1103de9d7bd0SStefano Zampini     ierr = PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
1104de9d7bd0SStefano Zampini     ierr = VecRestoreArray(v,&array);CHKERRQ(ierr);
1105efc2fbd9SStefano Zampini   }
1106efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
1107efc2fbd9SStefano Zampini }
1108efc2fbd9SStefano Zampini 
1109efc2fbd9SStefano Zampini #undef __FUNCT__
1110c263805aSStefano Zampini #define __FUNCT__ "PCBDDCBenignPopOrPushB0"
1111c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
1112c263805aSStefano Zampini {
1113c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
1114c263805aSStefano Zampini   PetscErrorCode ierr;
1115c263805aSStefano Zampini 
1116c263805aSStefano Zampini   PetscFunctionBegin;
1117c263805aSStefano Zampini   /* TODO: add error checking
1118c263805aSStefano Zampini     - avoid nested pop (or push) calls.
1119c263805aSStefano Zampini     - cannot push before pop.
11201c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
1121c263805aSStefano Zampini   */
11224f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
1123efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
1124efc2fbd9SStefano Zampini   }
1125c263805aSStefano Zampini   if (pop) {
1126a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
11274f1b2e48SStefano Zampini       IS       is_p0;
11284f1b2e48SStefano Zampini       MatReuse reuse;
1129c263805aSStefano Zampini 
1130c263805aSStefano Zampini       /* extract B_0 */
11314f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
11324f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
11334f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
11344f1b2e48SStefano Zampini       }
11354f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
11364f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
1137c263805aSStefano Zampini       /* remove rows and cols from local problem */
1138c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
113997d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
11404f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
11414f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
1142a3df083aSStefano Zampini     } else {
1143a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
1144a3df083aSStefano Zampini       PetscScalar *vals;
1145a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
1146a3df083aSStefano Zampini 
1147a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
1148a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
1149a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
11500b5adadeSStefano Zampini         PetscInt *nnz;
1151a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
1152a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
1153a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1154331e053bSStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&nnz);CHKERRQ(ierr);
1155331e053bSStefano Zampini         for (i=0;i<pcbddc->benign_n;i++) {
1156331e053bSStefano Zampini           ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i]);CHKERRQ(ierr);
1157331e053bSStefano Zampini           nnz[i] = n - nnz[i];
1158331e053bSStefano Zampini         }
1159331e053bSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz);CHKERRQ(ierr);
1160331e053bSStefano Zampini         ierr = PetscFree(nnz);CHKERRQ(ierr);
1161331e053bSStefano Zampini       }
1162a3df083aSStefano Zampini 
1163a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
1164a3df083aSStefano Zampini         PetscScalar *array;
1165a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
1166a3df083aSStefano Zampini 
1167a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
1168a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1169a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
1170a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
1171a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1172a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
1173a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
1174a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
1175a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
1176a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
1177a3df083aSStefano Zampini         cum = 0;
1178a3df083aSStefano Zampini         for (j=0;j<n;j++) {
117922db5ddcSStefano Zampini           if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) {
1180a3df083aSStefano Zampini             vals[cum] = array[j];
1181a3df083aSStefano Zampini             idxs_ins[cum] = j;
1182a3df083aSStefano Zampini             cum++;
1183a3df083aSStefano Zampini           }
1184a3df083aSStefano Zampini         }
1185a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
1186a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
1187a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
1188a3df083aSStefano Zampini       }
1189a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1190a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1191a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
1192a3df083aSStefano Zampini     }
1193c263805aSStefano Zampini   } else { /* push */
1194a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
11954f1b2e48SStefano Zampini       PetscInt i;
11964f1b2e48SStefano Zampini 
11974f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
11984f1b2e48SStefano Zampini         PetscScalar *B0_vals;
11994f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
12004f1b2e48SStefano Zampini 
12014f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
12024f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
12037b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
12044f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
12054f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
12064f1b2e48SStefano Zampini       }
1207c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1208c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1209a3df083aSStefano Zampini     } else {
1210a3df083aSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!\n");
1211a3df083aSStefano Zampini     }
1212c263805aSStefano Zampini   }
1213c263805aSStefano Zampini   PetscFunctionReturn(0);
1214c263805aSStefano Zampini }
1215c263805aSStefano Zampini 
1216c263805aSStefano Zampini #undef __FUNCT__
1217b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
121808122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
1219b1b3d7a2SStefano Zampini {
1220b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
122108122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
122208122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
122308122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
122408122e43SStefano Zampini   PetscScalar     *work,lwork;
122508122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
122608122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
122708122e43SStefano Zampini   PetscReal       *eigs,thresh;
12281b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
1229f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
123008122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
123108122e43SStefano Zampini   PetscReal       *rwork;
123208122e43SStefano Zampini #endif
1233b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
1234b1b3d7a2SStefano Zampini 
1235b1b3d7a2SStefano Zampini   PetscFunctionBegin;
1236b334f244SStefano Zampini   if (!sub_schurs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Adaptive selection of constraints requires SubSchurs data");
1237af25d912SStefano Zampini   if (!sub_schurs->schur_explicit) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
1238af25d912SStefano 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);
123906a4e24aSStefano Zampini 
1240fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
1241fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1242fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1243fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
12441575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
1245fd14bc51SStefano Zampini   }
1246fd14bc51SStefano Zampini 
1247e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
1248e496cd5dSStefano 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);
1249e496cd5dSStefano Zampini   }
1250e496cd5dSStefano Zampini 
125108122e43SStefano Zampini   /* max size of subsets */
125208122e43SStefano Zampini   mss = 0;
125308122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
125408122e43SStefano Zampini     PetscInt subset_size;
1255862806e4SStefano Zampini 
125608122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
125708122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
125808122e43SStefano Zampini   }
125908122e43SStefano Zampini 
126008122e43SStefano Zampini   /* min/max and threshold */
126108122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
1262f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
126308122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
1264f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
1265f6f667cfSStefano Zampini   if (nmin) {
1266f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
1267f6f667cfSStefano Zampini   }
126808122e43SStefano Zampini 
126908122e43SStefano Zampini   /* allocate lapack workspace */
127008122e43SStefano Zampini   cum = cum2 = 0;
127108122e43SStefano Zampini   maxneigs = 0;
127208122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
127308122e43SStefano Zampini     PetscInt n,subset_size;
1274f6f667cfSStefano Zampini 
127508122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
127608122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
12779162d606SStefano Zampini     cum += subset_size;
12789162d606SStefano Zampini     cum2 += subset_size*n;
127908122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
128008122e43SStefano Zampini   }
128108122e43SStefano Zampini   if (mss) {
12829ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
128308122e43SStefano Zampini       PetscBLASInt B_itype = 1;
128408122e43SStefano Zampini       PetscBLASInt B_N = mss;
12854c6709b3SStefano Zampini       PetscReal    zero = 0.0;
12864c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
128708122e43SStefano Zampini 
128808122e43SStefano Zampini       B_lwork = -1;
128908122e43SStefano Zampini       S = NULL;
129008122e43SStefano Zampini       St = NULL;
1291a58a30b4SStefano Zampini       eigs = NULL;
1292a58a30b4SStefano Zampini       eigv = NULL;
1293a58a30b4SStefano Zampini       B_iwork = NULL;
1294a58a30b4SStefano Zampini       B_ifail = NULL;
1295d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1296d1710679SStefano Zampini       rwork = NULL;
1297d1710679SStefano Zampini #endif
12988bec7fa6SStefano Zampini       thresh = 1.0;
129908122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
130008122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
130108122e43SStefano 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));
130208122e43SStefano Zampini #else
130308122e43SStefano 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));
130408122e43SStefano Zampini #endif
130508122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
130608122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
130708122e43SStefano Zampini     } else {
130808122e43SStefano Zampini         /* TODO */
130908122e43SStefano Zampini     }
131008122e43SStefano Zampini   } else {
131108122e43SStefano Zampini     lwork = 0;
131208122e43SStefano Zampini   }
131308122e43SStefano Zampini 
131408122e43SStefano Zampini   nv = 0;
1315d62866d3SStefano 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) */
1316d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
131708122e43SStefano Zampini   }
13184c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
1319f6f667cfSStefano Zampini   if (allocated_S_St) {
1320f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
1321f6f667cfSStefano Zampini   }
1322f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
132308122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
132408122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
132508122e43SStefano Zampini #endif
13269162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
13279162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
13289162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
132908122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
13309162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
133108122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
133208122e43SStefano Zampini 
133308122e43SStefano Zampini   maxneigs = 0;
133472b8c272SStefano Zampini   cum = cumarray = 0;
13359162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
13369162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
1337d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
133808122e43SStefano Zampini     const PetscInt *idxs;
133908122e43SStefano Zampini 
1340d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
134108122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
134208122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
134308122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
134408122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
13459162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
13469162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
134708122e43SStefano Zampini     }
1348d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
134908122e43SStefano Zampini   }
135008122e43SStefano Zampini 
135108122e43SStefano Zampini   if (mss) { /* multilevel */
135208122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
135308122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
135408122e43SStefano Zampini   }
135508122e43SStefano Zampini 
1356ffd830a3SStefano Zampini   thresh = pcbddc->adaptive_threshold;
135708122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
135808122e43SStefano Zampini     const PetscInt *idxs;
13599d54b7f4SStefano Zampini     PetscReal      upper,lower;
1360862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
136108122e43SStefano Zampini     PetscBLASInt   B_N;
1362aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
136308122e43SStefano Zampini 
13649d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
13659d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
13669d54b7f4SStefano Zampini       lower = thresh;
13679d54b7f4SStefano Zampini     } else {
13689d54b7f4SStefano Zampini       upper = 1./thresh;
13699d54b7f4SStefano Zampini       lower = 0.;
13709d54b7f4SStefano Zampini     }
1371862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
1372ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
1373f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
1374f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
13759ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
1376aff50787SStefano Zampini         PetscInt j,k;
1377aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
1378aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
1379aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
138008122e43SStefano Zampini         }
138108122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
1382aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
1383aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
1384aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
1385aff50787SStefano Zampini           }
138608122e43SStefano Zampini         }
138708122e43SStefano Zampini       } else {
138808122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
138908122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
139008122e43SStefano Zampini       }
13918bec7fa6SStefano Zampini     } else {
1392f6f667cfSStefano Zampini       S = Sarray + cumarray;
1393f6f667cfSStefano Zampini       St = Starray + cumarray;
13948bec7fa6SStefano Zampini     }
1395aff50787SStefano Zampini     /* see if we can save some work */
1396b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
1397aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
1398aff50787SStefano Zampini     }
1399aff50787SStefano Zampini 
1400b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
1401aff50787SStefano Zampini       B_neigs = 0;
1402aff50787SStefano Zampini     } else {
14039ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
140408122e43SStefano Zampini         PetscBLASInt B_itype = 1;
1405f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
14064c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
14079552c7c7SStefano Zampini         PetscInt     nmin_s;
1408b7ab4a40SStefano Zampini         PetscBool    compute_range = PETSC_FALSE;
140908122e43SStefano Zampini 
1410fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
14118bec7fa6SStefano 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]]);
1412fd14bc51SStefano Zampini         }
1413d16cbb6bSStefano Zampini 
1414b7ab4a40SStefano Zampini         compute_range = PETSC_FALSE;
1415b7ab4a40SStefano Zampini         if (thresh > 1.+PETSC_SMALL && !same_data) {
1416b7ab4a40SStefano Zampini           compute_range = PETSC_TRUE;
1417b7ab4a40SStefano Zampini         }
1418b7ab4a40SStefano Zampini 
141908122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1420b7ab4a40SStefano Zampini         if (compute_range) {
1421d16cbb6bSStefano Zampini 
1422d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
142308122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
14249d54b7f4SStefano 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));
142508122e43SStefano Zampini #else
14269d54b7f4SStefano 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));
142708122e43SStefano Zampini #endif
1428b7ab4a40SStefano Zampini         } else if (!same_data) {
1429d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
1430d16cbb6bSStefano Zampini           B_IL = 1;
1431d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
14329d54b7f4SStefano 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));
1433d16cbb6bSStefano Zampini #else
14349d54b7f4SStefano 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));
1435d16cbb6bSStefano Zampini #endif
1436b7ab4a40SStefano Zampini         } else { /* same_data is true, so get the adaptive function requested by the user */
1437b7ab4a40SStefano Zampini           PetscInt k;
1438b7ab4a40SStefano Zampini           if (!sub_schurs->change_primal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
1439b7ab4a40SStefano Zampini           ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax);CHKERRQ(ierr);
1440b7ab4a40SStefano Zampini           ierr = PetscBLASIntCast(nmax,&B_neigs);CHKERRQ(ierr);
1441b7ab4a40SStefano Zampini           nmin = nmax;
1442b7ab4a40SStefano Zampini           ierr = PetscMemzero(eigv,subset_size*nmax*sizeof(PetscScalar));CHKERRQ(ierr);
1443b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
1444b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
1445b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
1446b7ab4a40SStefano Zampini           }
1447d16cbb6bSStefano Zampini         }
144808122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
144908122e43SStefano Zampini         if (B_ierr) {
14506c4ed002SBarry 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);
14516c4ed002SBarry 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);
14526c4ed002SBarry 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);
145308122e43SStefano Zampini         }
145408122e43SStefano Zampini 
145508122e43SStefano Zampini         if (B_neigs > nmax) {
1456fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
1457fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
1458fd14bc51SStefano Zampini           }
14599d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) eigs_start = B_neigs -nmax;
146008122e43SStefano Zampini           B_neigs = nmax;
146108122e43SStefano Zampini         }
146208122e43SStefano Zampini 
14639552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
14649552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
146508122e43SStefano Zampini           PetscBLASInt B_neigs2;
146608122e43SStefano Zampini 
14679d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) {
1468f6f667cfSStefano Zampini             B_IL = B_N - nmin_s + 1;
14699d54b7f4SStefano Zampini             B_IU = B_N - B_neigs;
14709d54b7f4SStefano Zampini           } else {
14719d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
14729d54b7f4SStefano Zampini             B_IU = nmin_s;
14739d54b7f4SStefano Zampini           }
1474fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
1475fd14bc51SStefano 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);
1476fd14bc51SStefano Zampini           }
14779ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
14781ae86dd6SStefano Zampini             PetscInt j,k;
147908122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
14801ae86dd6SStefano Zampini               for (k=j;k<subset_size;k++) {
14811ae86dd6SStefano Zampini                 S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
14821ae86dd6SStefano Zampini                 St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
148308122e43SStefano Zampini               }
148408122e43SStefano Zampini             }
148508122e43SStefano Zampini           } else {
148608122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
148708122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
148808122e43SStefano Zampini           }
148908122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
149008122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
14919d54b7f4SStefano 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));
149208122e43SStefano Zampini #else
14939d54b7f4SStefano 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));
149408122e43SStefano Zampini #endif
149508122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
149608122e43SStefano Zampini           B_neigs += B_neigs2;
149708122e43SStefano Zampini         }
149808122e43SStefano Zampini         if (B_ierr) {
14996c4ed002SBarry 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);
15006c4ed002SBarry 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);
15016c4ed002SBarry 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);
150208122e43SStefano Zampini         }
1503fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
1504ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
150508122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
150608122e43SStefano Zampini             if (eigs[j] == 0.0) {
1507ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
150808122e43SStefano Zampini             } else {
15099d54b7f4SStefano Zampini               if (pcbddc->use_deluxe_scaling) {
1510ac47001eSStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
15119d54b7f4SStefano Zampini               } else {
15129d54b7f4SStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",1./eigs[j+eigs_start]);CHKERRQ(ierr);
15139d54b7f4SStefano Zampini               }
1514fd14bc51SStefano Zampini             }
151508122e43SStefano Zampini           }
151608122e43SStefano Zampini         }
151708122e43SStefano Zampini       } else {
151808122e43SStefano Zampini           /* TODO */
151908122e43SStefano Zampini       }
1520aff50787SStefano Zampini     }
15216c3e6151SStefano Zampini     /* change the basis back to the original one */
15226c3e6151SStefano Zampini     if (sub_schurs->change) {
152372b8c272SStefano Zampini       Mat change,phi,phit;
15246c3e6151SStefano Zampini 
15256c3e6151SStefano Zampini       if (pcbddc->dbg_flag > 1) {
15266c3e6151SStefano Zampini         PetscInt ii;
15276c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
15286c3e6151SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
15296c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
15306c3e6151SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",eigv[(ii+eigs_start)*subset_size+j]);CHKERRQ(ierr);
15316c3e6151SStefano Zampini           }
15326c3e6151SStefano Zampini         }
15336c3e6151SStefano Zampini       }
153472b8c272SStefano Zampini       ierr = KSPGetOperators(sub_schurs->change[i],&change,NULL);CHKERRQ(ierr);
15356c3e6151SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit);CHKERRQ(ierr);
153672b8c272SStefano Zampini       ierr = MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi);CHKERRQ(ierr);
15376c3e6151SStefano Zampini       ierr = MatCopy(phi,phit,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
15386c3e6151SStefano Zampini       ierr = MatDestroy(&phit);CHKERRQ(ierr);
15396c3e6151SStefano Zampini       ierr = MatDestroy(&phi);CHKERRQ(ierr);
15406c3e6151SStefano Zampini     }
15418bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
15428bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
15439162d606SStefano Zampini     if (B_neigs) {
15449162d606SStefano 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);
1545fd14bc51SStefano Zampini 
1546fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
15479552c7c7SStefano Zampini         PetscInt ii;
15489552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
1549ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
15509552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
1551ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
1552ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
1553ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
1554ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
1555ac47001eSStefano Zampini #else
1556ac47001eSStefano 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);
1557ac47001eSStefano Zampini #endif
15589552c7c7SStefano Zampini           }
15599552c7c7SStefano Zampini         }
1560fd14bc51SStefano Zampini       }
15619162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
15629162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
15639162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
15649162d606SStefano Zampini       cum++;
156508122e43SStefano Zampini     }
156608122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
156708122e43SStefano Zampini     /* shift for next computation */
156808122e43SStefano Zampini     cumarray += subset_size*subset_size;
156908122e43SStefano Zampini   }
1570fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
1571fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1572fd14bc51SStefano Zampini   }
157308122e43SStefano Zampini 
157408122e43SStefano Zampini   if (mss) {
157508122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
157608122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
1577f6f667cfSStefano Zampini     /* destroy matrices (junk) */
1578f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
1579f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
158008122e43SStefano Zampini   }
1581f6f667cfSStefano Zampini   if (allocated_S_St) {
1582f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
1583f6f667cfSStefano Zampini   }
1584f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
158508122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
158608122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
158708122e43SStefano Zampini #endif
158808122e43SStefano Zampini   if (pcbddc->dbg_flag) {
15891b968477SStefano Zampini     PetscInt maxneigs_r;
1590b2566f29SBarry Smith     ierr = MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
15919b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
159208122e43SStefano Zampini   }
159308122e43SStefano Zampini   PetscFunctionReturn(0);
159408122e43SStefano Zampini }
1595b1b3d7a2SStefano Zampini 
1596674ae819SStefano Zampini #undef __FUNCT__
1597c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
1598c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
1599c8587f34SStefano Zampini {
16008629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
1601c8587f34SStefano Zampini   PetscErrorCode ierr;
1602c8587f34SStefano Zampini 
1603c8587f34SStefano Zampini   PetscFunctionBegin;
1604f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
16055e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
1606c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
1607c8587f34SStefano Zampini 
1608684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
16090fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
1610684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
1611c8587f34SStefano Zampini 
16128629588bSStefano Zampini   /*
16138629588bSStefano Zampini      Setup local correction and local part of coarse basis.
16148629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
16158629588bSStefano Zampini   */
161647f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
16178629588bSStefano Zampini 
16188629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
16198629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
16208629588bSStefano Zampini 
16218629588bSStefano Zampini   /* free */
16228629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
1623c8587f34SStefano Zampini   PetscFunctionReturn(0);
1624c8587f34SStefano Zampini }
1625c8587f34SStefano Zampini 
1626c8587f34SStefano Zampini #undef __FUNCT__
1627674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
1628674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
1629674ae819SStefano Zampini {
1630674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1631674ae819SStefano Zampini   PetscErrorCode ierr;
1632674ae819SStefano Zampini 
1633674ae819SStefano Zampini   PetscFunctionBegin;
1634674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
1635674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
163630368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
1637674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
1638785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
1639674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
1640f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
1641f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
1642785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
164363602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
164463602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
1645674ae819SStefano Zampini   PetscFunctionReturn(0);
1646674ae819SStefano Zampini }
1647674ae819SStefano Zampini 
1648674ae819SStefano Zampini #undef __FUNCT__
1649674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
1650674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
1651674ae819SStefano Zampini {
1652674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
16534f1b2e48SStefano Zampini   PetscInt       i;
1654674ae819SStefano Zampini   PetscErrorCode ierr;
1655674ae819SStefano Zampini 
1656674ae819SStefano Zampini   PetscFunctionBegin;
1657b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
1658674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
165916909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
16601dd7afcfSStefano Zampini   ierr = VecDestroy(&pcbddc->work_change);CHKERRQ(ierr);
1661674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
1662669cc0f4SStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
1663fa23a32eSStefano Zampini   ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
1664674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
16654f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
16664f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
16674f1b2e48SStefano Zampini   }
16684f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
1669b334f244SStefano Zampini   if (pcbddc->sub_schurs) {
1670b96c3477SStefano Zampini     ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
1671b334f244SStefano Zampini   }
1672674ae819SStefano Zampini   PetscFunctionReturn(0);
1673674ae819SStefano Zampini }
1674674ae819SStefano Zampini 
1675674ae819SStefano Zampini #undef __FUNCT__
1676674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
1677674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
1678674ae819SStefano Zampini {
1679674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1680674ae819SStefano Zampini   PetscErrorCode ierr;
1681674ae819SStefano Zampini 
1682674ae819SStefano Zampini   PetscFunctionBegin;
1683674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
168458da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
1685ca92afb2SStefano Zampini     PetscScalar *array;
168606656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
168706656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
168858da7f69SStefano Zampini   }
1689674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1690674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
169115aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
169215aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
1693674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
1694674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
1695674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
169606656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
1697674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
1698674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
16998ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
1700674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
1701674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
1702674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
1703f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
1704f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
1705f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
1706f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
1707727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
17080e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
1709f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
171070cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
171181d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
17120369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
17131dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
17144f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
17158b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
1716ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
1717ca92afb2SStefano Zampini     PetscInt i;
1718ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
1719ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1720ca92afb2SStefano Zampini     }
1721ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
1722ca92afb2SStefano Zampini   }
17234f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
1724674ae819SStefano Zampini   PetscFunctionReturn(0);
1725674ae819SStefano Zampini }
1726674ae819SStefano Zampini 
1727674ae819SStefano Zampini #undef __FUNCT__
1728f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
1729f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
17306bfb1811SStefano Zampini {
17316bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
17326bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
17336bfb1811SStefano Zampini   VecType        impVecType;
17344f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
17356bfb1811SStefano Zampini   PetscErrorCode ierr;
17366bfb1811SStefano Zampini 
17376bfb1811SStefano Zampini   PetscFunctionBegin;
17386c4ed002SBarry Smith   if (!pcbddc->ConstraintMatrix) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
1739e7b262bdSStefano Zampini   /* get sizes */
17404f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
1741b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
17426bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
1743e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
1744e7b262bdSStefano Zampini   /* R nodes */
1745e7b262bdSStefano Zampini   old_size = -1;
1746e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
1747e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
1748e7b262bdSStefano Zampini   }
1749e7b262bdSStefano Zampini   if (n_R != old_size) {
1750e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
1751e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
17526bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
17536bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
17546bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
17556bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
1756e7b262bdSStefano Zampini   }
1757e7b262bdSStefano Zampini   /* local primal dofs */
1758e7b262bdSStefano Zampini   old_size = -1;
1759e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
1760e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
1761e7b262bdSStefano Zampini   }
1762e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
1763e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
176483b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
1765e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
17666bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
1767e7b262bdSStefano Zampini   }
1768e7b262bdSStefano Zampini   /* local explicit constraints */
1769e7b262bdSStefano Zampini   old_size = -1;
1770e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
1771e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
1772e7b262bdSStefano Zampini   }
1773e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
1774e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
177583b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
177683b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
177783b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
177883b7ccabSStefano Zampini   }
17796bfb1811SStefano Zampini   PetscFunctionReturn(0);
17806bfb1811SStefano Zampini }
17816bfb1811SStefano Zampini 
17826bfb1811SStefano Zampini #undef __FUNCT__
178347f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
178447f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
178588ebb749SStefano Zampini {
178625084f0cSStefano Zampini   PetscErrorCode  ierr;
178725084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
178888ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
178988ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1790d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
179125084f0cSStefano Zampini   /* submatrices of local problem */
179280677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
179306656605SStefano Zampini   /* submatrices of local coarse problem */
179406656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
179525084f0cSStefano Zampini   /* working matrices */
179606656605SStefano Zampini   Mat             C_CR;
179725084f0cSStefano Zampini   /* additional working stuff */
179806656605SStefano Zampini   PC              pc_R;
17994f1b2e48SStefano Zampini   Mat             F;
18005cbda25cSStefano Zampini   Vec             dummy_vec;
1801a3df083aSStefano Zampini   PetscBool       isLU,isCHOL,isILU,need_benign_correction;
180225084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
180306656605SStefano Zampini   PetscScalar     *work;
180406656605SStefano Zampini   PetscInt        *idx_V_B;
1805ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
180606656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
1807ffd830a3SStefano Zampini 
180825084f0cSStefano Zampini   /* some shortcuts to scalars */
180906656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
181088ebb749SStefano Zampini 
181188ebb749SStefano Zampini   PetscFunctionBegin;
1812*9a962809SStefano Zampini   if (!pcbddc->symmetric_primal && pcbddc->benign_n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Non-symmetric primal basis computation with benign trick not yet implemented");
1813ffd830a3SStefano Zampini 
1814ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
1815b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
18164f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
1817b371cd4fSStefano Zampini   n_B = pcis->n_B;
1818b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
181988ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
182088ebb749SStefano Zampini 
182188ebb749SStefano Zampini   /* vertices in boundary numbering */
1822785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
18230e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
18246c4ed002SBarry 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);
182588ebb749SStefano Zampini 
182606656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
1827019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
182806656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
182906656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
183006656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
183106656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
183206656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
183306656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
183406656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
183506656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
183606656605SStefano Zampini 
183706656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
183806656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
183906656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
184006656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
184106656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
1842ffd830a3SStefano Zampini   lda_rhs = n_R;
1843a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
184406656605SStefano Zampini   if (isLU || isILU || isCHOL) {
184506656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
1846b334f244SStefano Zampini   } else if (sub_schurs && sub_schurs->reuse_solver) {
1847df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1848d62866d3SStefano Zampini     MatFactorType      type;
1849d62866d3SStefano Zampini 
1850df4d28bfSStefano Zampini     F = reuse_solver->F;
18516816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
1852d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
1853ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
185422db5ddcSStefano Zampini     need_benign_correction = (PetscBool)(!!reuse_solver->benign_n);
185506656605SStefano Zampini   } else {
185606656605SStefano Zampini     F = NULL;
185706656605SStefano Zampini   }
185806656605SStefano Zampini 
1859ffd830a3SStefano Zampini   /* allocate workspace */
1860ffd830a3SStefano Zampini   n = 0;
1861ffd830a3SStefano Zampini   if (n_constraints) {
1862ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
1863ffd830a3SStefano Zampini   }
1864ffd830a3SStefano Zampini   if (n_vertices) {
1865ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
1866ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
1867ffd830a3SStefano Zampini   }
1868ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
1869ffd830a3SStefano Zampini 
18705cbda25cSStefano Zampini   /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */
18715cbda25cSStefano Zampini   dummy_vec = NULL;
18725cbda25cSStefano Zampini   if (need_benign_correction && lda_rhs != n_R && F) {
18735cbda25cSStefano Zampini     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,lda_rhs,work,&dummy_vec);CHKERRQ(ierr);
18745cbda25cSStefano Zampini   }
18755cbda25cSStefano Zampini 
187688ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
187788ebb749SStefano Zampini   if (n_constraints) {
187872b8c272SStefano Zampini     Mat         M1,M2,M3,C_B;
187906656605SStefano Zampini     IS          is_aux;
188080677318SStefano Zampini     PetscScalar *array,*array2;
188106656605SStefano Zampini 
1882f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
188380677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
188488ebb749SStefano Zampini 
188525084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
188625084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
18878ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
188872b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
188988ebb749SStefano Zampini 
189080677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
189180677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
1892ffd830a3SStefano Zampini     ierr = PetscMemzero(work,lda_rhs*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
189388ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
189406656605SStefano Zampini       const PetscScalar *row_cmat_values;
189506656605SStefano Zampini       const PetscInt    *row_cmat_indices;
189606656605SStefano Zampini       PetscInt          size_of_constraint,j;
189788ebb749SStefano Zampini 
189806656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
189906656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
1900ffd830a3SStefano Zampini         work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
190106656605SStefano Zampini       }
190206656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
190306656605SStefano Zampini     }
1904ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
190506656605SStefano Zampini     if (F) {
190606656605SStefano Zampini       Mat B;
190706656605SStefano Zampini 
1908ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
1909a3df083aSStefano Zampini       if (need_benign_correction) {
1910df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1911a3df083aSStefano Zampini 
191272b8c272SStefano Zampini         /* rhs is already zero on interior dofs, no need to change the rhs */
191372b8c272SStefano Zampini         ierr = PetscMemzero(reuse_solver->benign_save_vals,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
1914a3df083aSStefano Zampini       }
191580677318SStefano Zampini       ierr = MatMatSolve(F,B,local_auxmat2_R);CHKERRQ(ierr);
1916a3df083aSStefano Zampini       if (need_benign_correction) {
1917a3df083aSStefano Zampini         PetscScalar        *marr;
1918df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1919a3df083aSStefano Zampini 
1920a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
19215cbda25cSStefano Zampini         if (lda_rhs != n_R) {
19225cbda25cSStefano Zampini           for (i=0;i<n_constraints;i++) {
19235cbda25cSStefano Zampini             ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
19245cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
19255cbda25cSStefano Zampini             ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
19265cbda25cSStefano Zampini           }
19275cbda25cSStefano Zampini         } else {
1928a3df083aSStefano Zampini           for (i=0;i<n_constraints;i++) {
1929a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
19305cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
1931a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1932a3df083aSStefano Zampini           }
19335cbda25cSStefano Zampini         }
1934a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
1935a3df083aSStefano Zampini       }
193606656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
193706656605SStefano Zampini     } else {
193880677318SStefano Zampini       PetscScalar *marr;
193980677318SStefano Zampini 
194080677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
194106656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
1942ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
1943ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
194406656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
194506656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
194606656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
194706656605SStefano Zampini       }
194880677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
194906656605SStefano Zampini     }
195080677318SStefano Zampini     if (!pcbddc->switch_static) {
195180677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
195280677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
195380677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
195480677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
1955ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
195680677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
195780677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
195880677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
195980677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
196080677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
196180677318SStefano Zampini       }
196280677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
196380677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
196472b8c272SStefano Zampini       ierr = MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
196580677318SStefano Zampini     } else {
1966ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
1967ffd830a3SStefano Zampini         IS dummy;
1968ffd830a3SStefano Zampini 
1969ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
197072b8c272SStefano Zampini         ierr = MatGetSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
1971ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1972ffd830a3SStefano Zampini       } else {
197380677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
197480677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
1975ffd830a3SStefano Zampini       }
197625084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
197780677318SStefano Zampini     }
197880677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
197980677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
198080677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
198106656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
198206656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
198380677318SStefano Zampini     if (isCHOL) {
198480677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
198580677318SStefano Zampini     } else {
198625084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
198780677318SStefano Zampini     }
198880677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,one);CHKERRQ(ierr);
198906656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
199025084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
199125084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
199225084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
199380677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
199472b8c272SStefano Zampini     ierr = MatMatMult(M1,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
199572b8c272SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
199606656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
199706656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
1998f4ddd8eeSStefano Zampini   }
1999fc227af8SStefano Zampini 
2000fc227af8SStefano Zampini   /* Get submatrices from subdomain matrix */
200188ebb749SStefano Zampini   if (n_vertices) {
200206656605SStefano Zampini     IS is_aux;
20033a50541eSStefano Zampini 
2004b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
20056816873aSStefano Zampini       IS tis;
20066816873aSStefano Zampini 
20076816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
20086816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
20096816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
20106816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
20116816873aSStefano Zampini     } else {
20123a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
20136816873aSStefano Zampini     }
20149577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
20159577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
201604708bb6SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
201725084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
201888ebb749SStefano Zampini   }
201988ebb749SStefano Zampini 
202088ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
2021f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
202206656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
202306656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
202406656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
202506656605SStefano Zampini     }
2026f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
202706656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
202806656605SStefano Zampini       PetscScalar *marray;
202906656605SStefano Zampini 
203006656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
203106656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
2032f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
2033f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
2034f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
2035f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
2036f4ddd8eeSStefano Zampini     }
2037f4ddd8eeSStefano Zampini   }
203806656605SStefano Zampini 
2039f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
204006656605SStefano Zampini     PetscScalar *marray;
204188ebb749SStefano Zampini 
204206656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
20438eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
204406656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
204588ebb749SStefano Zampini     }
20463301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
204706656605SStefano Zampini       n *= 2;
204888ebb749SStefano Zampini     }
204906656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
205006656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
205106656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
20528eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
205306656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
205406656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
205588ebb749SStefano Zampini     }
20563301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
205706656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
20588eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
205906656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
206006656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
206188ebb749SStefano Zampini       }
206288ebb749SStefano Zampini     } else {
2063c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
2064c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
20651b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
2066c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
2067c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
2068c0553b1fSStefano Zampini       }
206988ebb749SStefano Zampini     }
207006656605SStefano Zampini   }
2071019a44ceSStefano Zampini 
207206656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
20734f1b2e48SStefano Zampini   p0_lidx_I = NULL;
20744f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
2075d12edf2fSStefano Zampini     const PetscInt *idxs;
2076d12edf2fSStefano Zampini 
2077d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
20784f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
20794f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
20804f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
20814f1b2e48SStefano Zampini     }
2082d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
2083d12edf2fSStefano Zampini   }
2084d16cbb6bSStefano Zampini 
208506656605SStefano Zampini   /* vertices */
208606656605SStefano Zampini   if (n_vertices) {
208716f15bc4SStefano Zampini 
2088af25d912SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV);CHKERRQ(ierr);
208904708bb6SStefano Zampini 
209016f15bc4SStefano Zampini     if (n_R) {
209114393ed6SStefano Zampini       Mat          A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
209206656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
209316f15bc4SStefano Zampini       PetscScalar  *x,*y;
209404708bb6SStefano Zampini       PetscBool    isseqaij;
209506656605SStefano Zampini 
209621eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
209714393ed6SStefano Zampini       if (need_benign_correction) {
209814393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
209914393ed6SStefano Zampini         IS                     is_p0;
210014393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
210114393ed6SStefano Zampini 
210214393ed6SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
210314393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
210414393ed6SStefano Zampini         ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
2105af25d912SStefano 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);
210614393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
210714393ed6SStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0);CHKERRQ(ierr);
210814393ed6SStefano Zampini         ierr = MatGetSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr);CHKERRQ(ierr);
210914393ed6SStefano Zampini         ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
211014393ed6SStefano Zampini       }
211114393ed6SStefano Zampini 
2112ffd830a3SStefano Zampini       if (lda_rhs == n_R) {
2113af25d912SStefano Zampini         ierr = MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
2114ffd830a3SStefano Zampini       } else {
2115ca92afb2SStefano Zampini         PetscScalar    *av,*array;
2116ca92afb2SStefano Zampini         const PetscInt *xadj,*adjncy;
2117ca92afb2SStefano Zampini         PetscInt       n;
2118ca92afb2SStefano Zampini         PetscBool      flg_row;
2119ffd830a3SStefano Zampini 
2120ca92afb2SStefano Zampini         array = work+lda_rhs*n_vertices;
2121ca92afb2SStefano Zampini         ierr = PetscMemzero(array,lda_rhs*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
21229d54b7f4SStefano Zampini         ierr = MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
2123ca92afb2SStefano Zampini         ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2124ca92afb2SStefano Zampini         ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
2125ca92afb2SStefano Zampini         for (i=0;i<n;i++) {
2126ca92afb2SStefano Zampini           PetscInt j;
2127ca92afb2SStefano Zampini           for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
2128ffd830a3SStefano Zampini         }
2129ca92afb2SStefano Zampini         ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2130ca92afb2SStefano Zampini         ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
2131ca92afb2SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
2132ffd830a3SStefano Zampini       }
2133ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
2134a3df083aSStefano Zampini       if (need_benign_correction) {
2135df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2136a3df083aSStefano Zampini         PetscScalar        *marr;
2137a3df083aSStefano Zampini 
2138a3df083aSStefano Zampini         ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
213914393ed6SStefano Zampini         /* need \Phi^T A_RV = (I+L)A_RV, L given by
214014393ed6SStefano Zampini 
214114393ed6SStefano Zampini                | 0 0  0 | (V)
214214393ed6SStefano Zampini            L = | 0 0 -1 | (P-p0)
214314393ed6SStefano Zampini                | 0 0 -1 | (p0)
214414393ed6SStefano Zampini 
214514393ed6SStefano Zampini         */
2146df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
214714393ed6SStefano Zampini           const PetscScalar *vals;
214814393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
214914393ed6SStefano Zampini           PetscInt          n,j,nz;
215014393ed6SStefano Zampini 
2151df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2152df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
215314393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
215414393ed6SStefano Zampini           for (j=0;j<n;j++) {
215514393ed6SStefano Zampini             PetscScalar val = vals[j];
215614393ed6SStefano Zampini             PetscInt    k,col = idxs[j];
215714393ed6SStefano Zampini             for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
215814393ed6SStefano Zampini           }
215914393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
2160df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
216114393ed6SStefano Zampini         }
216272b8c272SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
216372b8c272SStefano Zampini       }
216472b8c272SStefano Zampini       if (F) {
216514393ed6SStefano Zampini         /* need to correct the rhs */
216672b8c272SStefano Zampini         if (need_benign_correction) {
216772b8c272SStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
216872b8c272SStefano Zampini           PetscScalar        *marr;
216972b8c272SStefano Zampini 
217072b8c272SStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
21715cbda25cSStefano Zampini           if (lda_rhs != n_R) {
21725cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
21735cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
21745cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
21755cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
21765cbda25cSStefano Zampini             }
21775cbda25cSStefano Zampini           } else {
2178a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
2179a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
21805cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
2181a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
2182a3df083aSStefano Zampini             }
21835cbda25cSStefano Zampini           }
2184a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
2185a3df083aSStefano Zampini         }
218606656605SStefano Zampini         ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
218714393ed6SStefano Zampini         /* need to correct the solution */
2188a3df083aSStefano Zampini         if (need_benign_correction) {
2189df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2190a3df083aSStefano Zampini           PetscScalar        *marr;
2191a3df083aSStefano Zampini 
2192a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
21935cbda25cSStefano Zampini           if (lda_rhs != n_R) {
21945cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
21955cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
21965cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
21975cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
21985cbda25cSStefano Zampini             }
21995cbda25cSStefano Zampini           } else {
2200a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
2201a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
22025cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
2203a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
2204a3df083aSStefano Zampini             }
22055cbda25cSStefano Zampini           }
2206a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
2207a3df083aSStefano Zampini         }
220806656605SStefano Zampini       } else {
220906656605SStefano Zampini         ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
221006656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
2211ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
2212ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
221306656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
221406656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
221506656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
221606656605SStefano Zampini         }
221706656605SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
221806656605SStefano Zampini       }
221980677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
2220ffd830a3SStefano Zampini       /* S_VV and S_CV */
222106656605SStefano Zampini       if (n_constraints) {
222206656605SStefano Zampini         Mat B;
222380677318SStefano Zampini 
2224ffd830a3SStefano Zampini         ierr = PetscMemzero(work+lda_rhs*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
222580677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
2226ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
2227ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
222880677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
222980677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
223080677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
223180677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
223280677318SStefano Zampini         }
2233ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
223480677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
223580677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
2236ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
223780677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
223806656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
2239ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
2240ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
224106656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
224206656605SStefano Zampini       }
224304708bb6SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
224404708bb6SStefano Zampini       if (!isseqaij) { /* MatMatMult with SEQ(S)BAIJ below will raise an error */
2245511c6705SHong Zhang         ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
224604708bb6SStefano Zampini       }
2247ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
2248ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
2249ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
2250ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
2251ffd830a3SStefano Zampini       }
225206656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
225314393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
225414393ed6SStefano Zampini       if (need_benign_correction) {
2255df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
225614393ed6SStefano Zampini         PetscScalar      *marr,*sums;
225714393ed6SStefano Zampini 
225814393ed6SStefano Zampini         ierr = PetscMalloc1(n_vertices,&sums);CHKERRQ(ierr);
225914393ed6SStefano Zampini         ierr = MatDenseGetArray(S_VVt,&marr);
2260df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
226114393ed6SStefano Zampini           const PetscScalar *vals;
226214393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
226314393ed6SStefano Zampini           PetscInt          n,j,nz;
226414393ed6SStefano Zampini 
2265df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2266df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
226714393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
226814393ed6SStefano Zampini             PetscInt k;
226914393ed6SStefano Zampini             sums[j] = 0.;
227014393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
227114393ed6SStefano Zampini           }
227214393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
227314393ed6SStefano Zampini           for (j=0;j<n;j++) {
227414393ed6SStefano Zampini             PetscScalar val = vals[j];
227514393ed6SStefano Zampini             PetscInt k;
227614393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
227714393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
227814393ed6SStefano Zampini             }
227914393ed6SStefano Zampini           }
228014393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
2281df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
228214393ed6SStefano Zampini         }
228314393ed6SStefano Zampini         ierr = PetscFree(sums);CHKERRQ(ierr);
228414393ed6SStefano Zampini         ierr = MatDenseRestoreArray(S_VVt,&marr);
228514393ed6SStefano Zampini         ierr = MatDestroy(&A_RV_bcorr);CHKERRQ(ierr);
228614393ed6SStefano Zampini       }
228780677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
228806656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
228906656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
229006656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
229106656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
229206656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
229306656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
229406656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
2295d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
2296019a44ceSStefano Zampini     } else {
2297d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
2298d16cbb6bSStefano Zampini     }
229921eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
2300d16cbb6bSStefano Zampini 
230106656605SStefano Zampini     /* coarse basis functions */
230206656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
230316f15bc4SStefano Zampini       PetscScalar *y;
230416f15bc4SStefano Zampini 
2305ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
230606656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
230706656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
230806656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
230906656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
231006656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
231106656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
231206656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
231306656605SStefano Zampini 
231406656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
23154f1b2e48SStefano Zampini         PetscInt j;
23164f1b2e48SStefano Zampini 
231706656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
231806656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
231906656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
232006656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
232106656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
23224f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
232306656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
232406656605SStefano Zampini       }
232506656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
232606656605SStefano Zampini     }
232704708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
232804708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
232906656605SStefano Zampini   }
23305cbda25cSStefano Zampini   ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
233106656605SStefano Zampini 
233206656605SStefano Zampini   if (n_constraints) {
233306656605SStefano Zampini     Mat B;
233406656605SStefano Zampini 
2335ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
233606656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
233780677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
233806656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
233906656605SStefano Zampini     if (n_vertices) {
234080677318SStefano Zampini       if (isCHOL) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
234180677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
234280677318SStefano Zampini       } else {
234380677318SStefano Zampini         Mat S_VCt;
234480677318SStefano Zampini 
2345ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
2346ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
234772b8c272SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
2348ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
2349ffd830a3SStefano Zampini         }
235080677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
235180677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
235280677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
235380677318SStefano Zampini       }
235406656605SStefano Zampini     }
235506656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
235606656605SStefano Zampini     /* coarse basis functions */
235706656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
235806656605SStefano Zampini       PetscScalar *y;
235906656605SStefano Zampini 
2360ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
236106656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
236206656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
236306656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
236406656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
236506656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
236606656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
236706656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
23684f1b2e48SStefano Zampini         PetscInt j;
23694f1b2e48SStefano Zampini 
237006656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
237106656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
237206656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
237306656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
237406656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
23754f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
237606656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
237706656605SStefano Zampini       }
237806656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
237906656605SStefano Zampini     }
238006656605SStefano Zampini   }
238180677318SStefano Zampini   if (n_constraints) {
238280677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
238380677318SStefano Zampini   }
23844f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
238572b8c272SStefano Zampini 
238672b8c272SStefano Zampini   /* coarse matrix entries relative to B_0 */
238772b8c272SStefano Zampini   if (pcbddc->benign_n) {
238872b8c272SStefano Zampini     Mat         B0_B,B0_BPHI;
238972b8c272SStefano Zampini     IS          is_dummy;
239072b8c272SStefano Zampini     PetscScalar *data;
239172b8c272SStefano Zampini     PetscInt    j;
239272b8c272SStefano Zampini 
239372b8c272SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
239472b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
239572b8c272SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
239672b8c272SStefano Zampini     ierr = MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
239786c38910SStefano Zampini     ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
239872b8c272SStefano Zampini     ierr = MatDenseGetArray(B0_BPHI,&data);CHKERRQ(ierr);
239972b8c272SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) {
240072b8c272SStefano Zampini       PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
240172b8c272SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
240272b8c272SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j];
240372b8c272SStefano Zampini         coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j];
240472b8c272SStefano Zampini       }
240572b8c272SStefano Zampini     }
240672b8c272SStefano Zampini     ierr = MatDenseRestoreArray(B0_BPHI,&data);CHKERRQ(ierr);
240772b8c272SStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
240872b8c272SStefano Zampini     ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
240972b8c272SStefano Zampini   }
2410019a44ceSStefano Zampini 
241106656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
24123301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
2413ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
2414ffd830a3SStefano Zampini     PetscScalar *marray;
241506656605SStefano Zampini 
241606656605SStefano Zampini     if (n_constraints) {
2417ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
241806656605SStefano Zampini 
2419af25d912SStefano Zampini       ierr = MatTranspose(C_CR,MAT_INPLACE_MATRIX,&C_CRT);CHKERRQ(ierr);
242006656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
2421ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
242216f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
242306656605SStefano Zampini       if (n_vertices) {
2424ffd830a3SStefano Zampini         Mat S_VCT;
242506656605SStefano Zampini 
242606656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
2427ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
242816f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
242906656605SStefano Zampini       }
2430ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
24315b782168SStefano Zampini     } else {
24325b782168SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,NULL,&B_V);CHKERRQ(ierr);
243306656605SStefano Zampini     }
243416f15bc4SStefano Zampini     if (n_vertices && n_R) {
2435ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
2436ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
2437ffd830a3SStefano Zampini       PetscInt       n;
2438ffd830a3SStefano Zampini       PetscBool      flg_row;
243906656605SStefano Zampini 
2440ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
2441af25d912SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
2442ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2443ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
2444ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
2445ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
2446ffd830a3SStefano Zampini         PetscInt j;
2447ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
2448ffd830a3SStefano Zampini       }
2449ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
2450ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2451ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
245206656605SStefano Zampini     }
245306656605SStefano Zampini 
2454ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
2455ffd830a3SStefano Zampini     ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
2456ffd830a3SStefano Zampini     for (i=0;i<n_vertices;i++) {
2457ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
2458ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
245906656605SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
246006656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
246106656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
246206656605SStefano Zampini     }
2463ffd830a3SStefano Zampini     ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
24645b782168SStefano Zampini     if (B_C) {
2465ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
2466ffd830a3SStefano Zampini       for (i=n_vertices;i<n_constraints+n_vertices;i++) {
2467ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
2468ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
2469ffd830a3SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
2470ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
2471ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
247206656605SStefano Zampini       }
2473ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
24745b782168SStefano Zampini     }
247506656605SStefano Zampini     /* coarse basis functions */
247606656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
247706656605SStefano Zampini       PetscScalar *y;
247806656605SStefano Zampini 
2479ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
248006656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
248106656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
248206656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
248306656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
248406656605SStefano Zampini       if (i<n_vertices) {
248506656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
248606656605SStefano Zampini       }
248706656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
248806656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
248906656605SStefano Zampini 
249006656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
249106656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
249206656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
249306656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
249406656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
249506656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
249606656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
249706656605SStefano Zampini       }
249806656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
249906656605SStefano Zampini     }
2500ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
2501ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
250206656605SStefano Zampini   }
2503d62866d3SStefano Zampini   /* free memory */
250488ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
250506656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
250606656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
250706656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
250806656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
2509d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
2510d62866d3SStefano Zampini   if (n_vertices) {
2511d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
2512d62866d3SStefano Zampini   }
2513d62866d3SStefano Zampini   if (n_constraints) {
2514d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
2515d62866d3SStefano Zampini   }
251688ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
251788ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
251888ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
2519d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
252088ebb749SStefano Zampini     Mat         coarse_sub_mat;
252125084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
252288ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
252388ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
252488ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
25258bec7fa6SStefano Zampini     Mat         C_B,CPHI;
25268bec7fa6SStefano Zampini     IS          is_dummy;
25278bec7fa6SStefano Zampini     Vec         mones;
252888ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
252988ebb749SStefano Zampini     PetscReal   real_value;
253088ebb749SStefano Zampini 
2531a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
2532a3df083aSStefano Zampini       Mat A;
2533a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
2534a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
2535a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
2536a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
2537a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
2538a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
2539a3df083aSStefano Zampini     } else {
254088ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
254188ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
254288ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
254388ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
2544a3df083aSStefano Zampini     }
254588ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
254688ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
2547ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
254888ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
254988ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
255088ebb749SStefano Zampini     }
255188ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
255288ebb749SStefano Zampini 
255325084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
25543301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
255525084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2556ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
255788ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
255888ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
255988ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
256088ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
256188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
256288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
256388ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
256488ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
256588ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
256688ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
256788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
256888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
256988ebb749SStefano Zampini     } else {
257088ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
257188ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
257288ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
257388ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
257488ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
257588ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
257688ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
257788ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
257888ebb749SStefano Zampini     }
257988ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
258088ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
258188ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
2582511c6705SHong Zhang     ierr = MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1);CHKERRQ(ierr);
25834f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
2584fc227af8SStefano Zampini       Mat         B0_B,B0_BPHI;
2585d12edf2fSStefano Zampini       PetscScalar *data,*data2;
25864f1b2e48SStefano Zampini       PetscInt    j;
2587d12edf2fSStefano Zampini 
25884f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
2589fc227af8SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
2590d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
259186c38910SStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
2592d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
2593d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
25944f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
25954f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
2596d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
25974f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
25984f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
25994f1b2e48SStefano Zampini         }
2600d12edf2fSStefano Zampini       }
2601d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
2602d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
2603d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
2604d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
2605d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
2606d12edf2fSStefano Zampini     }
2607d12edf2fSStefano Zampini #if 0
2608d12edf2fSStefano Zampini   {
2609d12edf2fSStefano Zampini     PetscViewer viewer;
2610d12edf2fSStefano Zampini     char filename[256];
2611ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
2612d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
2613d12edf2fSStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2614ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
2615ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
2616ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
2617d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
261872b8c272SStefano Zampini     if (save_change) {
261972b8c272SStefano Zampini       Mat phi_B;
262072b8c272SStefano Zampini       ierr = MatMatMult(save_change,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&phi_B);CHKERRQ(ierr);
262172b8c272SStefano Zampini       ierr = PetscObjectSetName((PetscObject)phi_B,"phi_B");CHKERRQ(ierr);
262272b8c272SStefano Zampini       ierr = MatView(phi_B,viewer);CHKERRQ(ierr);
262372b8c272SStefano Zampini       ierr = MatDestroy(&phi_B);CHKERRQ(ierr);
262472b8c272SStefano Zampini     } else {
2625ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
2626ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
262772b8c272SStefano Zampini     }
2628ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
2629ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
2630ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
2631ffd830a3SStefano Zampini     }
2632ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
2633ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
2634ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
2635ffd830a3SStefano Zampini     }
263672b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
2637ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
2638ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
2639ffd830a3SStefano Zampini     }
2640d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
2641d12edf2fSStefano Zampini   }
2642d12edf2fSStefano Zampini #endif
264381d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
26448bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
26451575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
264606656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
26478bec7fa6SStefano Zampini 
26488bec7fa6SStefano Zampini     /* check constraints */
2649a00504b5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
2650a00504b5SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
26514f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
26528bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
2653a00504b5SStefano Zampini     } else {
2654a00504b5SStefano Zampini       PetscScalar *data;
2655a00504b5SStefano Zampini       Mat         tmat;
2656a00504b5SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
2657a00504b5SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat);CHKERRQ(ierr);
2658a00504b5SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
2659a00504b5SStefano Zampini       ierr = MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
2660a00504b5SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
2661a00504b5SStefano Zampini     }
26628bec7fa6SStefano Zampini     ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
26638bec7fa6SStefano Zampini     ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
26648bec7fa6SStefano Zampini     ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
26658bec7fa6SStefano Zampini     ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
2666bdae7319SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
2667ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
2668bdae7319SStefano Zampini       ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
2669bdae7319SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
2670bdae7319SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
2671bdae7319SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
2672bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
267388ebb749SStefano Zampini     }
26748bec7fa6SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
26758bec7fa6SStefano Zampini     ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
26768bec7fa6SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
26778bec7fa6SStefano Zampini     ierr = VecDestroy(&mones);CHKERRQ(ierr);
267825084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
267988ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
268088ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
268188ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
268288ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
268388ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
268488ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
268588ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
268688ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
268788ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
268888ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
2689ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
269088ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
269188ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
269288ebb749SStefano Zampini     }
269388ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
269488ebb749SStefano Zampini   }
26958629588bSStefano Zampini   /* get back data */
26968629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
269788ebb749SStefano Zampini   PetscFunctionReturn(0);
269888ebb749SStefano Zampini }
269988ebb749SStefano Zampini 
270088ebb749SStefano Zampini #undef __FUNCT__
2701d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
2702d648f858SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
2703aa0d41d4SStefano Zampini {
2704d65f70fdSStefano Zampini   Mat            *work_mat;
2705d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
2706d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
2707c43ebad9SStefano Zampini   PetscInt       rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL;
2708aa0d41d4SStefano Zampini   PetscErrorCode ierr;
2709aa0d41d4SStefano Zampini 
2710aa0d41d4SStefano Zampini   PetscFunctionBegin;
2711d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
2712d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
2713d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
2714d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
2715aa0d41d4SStefano Zampini 
2716d65f70fdSStefano Zampini   if (!rsorted) {
2717906d46d4SStefano Zampini     const PetscInt *idxs;
2718906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
2719aa0d41d4SStefano Zampini 
2720d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
2721d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
2722d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
2723d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
2724aa0d41d4SStefano Zampini     }
2725d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
2726d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
2727d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
2728d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
2729aa0d41d4SStefano Zampini     }
2730d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
2731d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
2732d65f70fdSStefano Zampini   } else {
2733d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
2734d65f70fdSStefano Zampini     isrow_s = isrow;
2735aa0d41d4SStefano Zampini   }
2736906d46d4SStefano Zampini 
2737d65f70fdSStefano Zampini   if (!csorted) {
2738d65f70fdSStefano Zampini     if (isrow == iscol) {
2739d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
2740d65f70fdSStefano Zampini       iscol_s = isrow_s;
2741d65f70fdSStefano Zampini     } else {
2742d65f70fdSStefano Zampini       const PetscInt *idxs;
2743d65f70fdSStefano Zampini       PetscInt       *idxs_sorted,i;
2744906d46d4SStefano Zampini 
2745d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
2746d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
2747d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
2748d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
2749d65f70fdSStefano Zampini       }
2750d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
2751d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
2752d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
2753d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
2754d65f70fdSStefano Zampini       }
2755d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
2756d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
2757d65f70fdSStefano Zampini     }
2758d65f70fdSStefano Zampini   } else {
2759d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
2760d65f70fdSStefano Zampini     iscol_s = iscol;
2761d65f70fdSStefano Zampini   }
2762d65f70fdSStefano Zampini 
2763d648f858SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
2764d65f70fdSStefano Zampini 
2765d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
2766906d46d4SStefano Zampini     Mat      new_mat;
2767d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
2768906d46d4SStefano Zampini 
2769d65f70fdSStefano Zampini     if (!rsorted) {
2770d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
2771d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
2772d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
2773d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
2774906d46d4SStefano Zampini       }
2775d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
2776d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
2777d65f70fdSStefano Zampini     } else {
2778d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
2779906d46d4SStefano Zampini     }
2780d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
2781d65f70fdSStefano Zampini 
2782d65f70fdSStefano Zampini     if (!csorted) {
2783d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
2784d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
2785d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
2786d65f70fdSStefano Zampini       } else {
2787d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
2788d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
2789d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
2790d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
2791d65f70fdSStefano Zampini         }
2792d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
2793d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
2794d65f70fdSStefano Zampini       }
2795d65f70fdSStefano Zampini     } else {
2796d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
2797d65f70fdSStefano Zampini     }
2798d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
2799d65f70fdSStefano Zampini 
2800d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
2801d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
2802d65f70fdSStefano Zampini     work_mat[0] = new_mat;
2803d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
2804d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
2805d65f70fdSStefano Zampini   }
2806d65f70fdSStefano Zampini 
2807d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
2808d65f70fdSStefano Zampini   *B = work_mat[0];
2809d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
2810d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
2811d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
2812d65f70fdSStefano Zampini   PetscFunctionReturn(0);
2813d65f70fdSStefano Zampini }
2814d65f70fdSStefano Zampini 
2815d65f70fdSStefano Zampini #undef __FUNCT__
28165e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
28175e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
2818aa0d41d4SStefano Zampini {
2819aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
28205e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2821d65f70fdSStefano Zampini   Mat            new_mat;
28225e8657edSStefano Zampini   IS             is_local,is_global;
2823d65f70fdSStefano Zampini   PetscInt       local_size;
2824d65f70fdSStefano Zampini   PetscBool      isseqaij;
2825aa0d41d4SStefano Zampini   PetscErrorCode ierr;
2826aa0d41d4SStefano Zampini 
2827aa0d41d4SStefano Zampini   PetscFunctionBegin;
2828aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
28295e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
28305e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
2831b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
2832aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
2833d648f858SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
2834aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
2835906d46d4SStefano Zampini 
2836906d46d4SStefano Zampini   /* check */
2837906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
2838906d46d4SStefano Zampini     Vec       x,x_change;
2839906d46d4SStefano Zampini     PetscReal error;
2840906d46d4SStefano Zampini 
28415e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
2842906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
28435e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
2844e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2845e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2846d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
2847e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2848e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2849906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
2850906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
2851906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2852906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
2853906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
2854906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
2855906d46d4SStefano Zampini   }
2856906d46d4SStefano Zampini 
285722d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
28589b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
285922d5777bSStefano Zampini   if (isseqaij) {
2860a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
2861a00504b5SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
2862aa0d41d4SStefano Zampini   } else {
2863a00504b5SStefano Zampini     Mat work_mat;
28641cf9b237SStefano Zampini 
2865a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
2866aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
2867a00504b5SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
28681d82a3b6SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
2869aa0d41d4SStefano Zampini   }
28703301b35fSStefano Zampini   if (matis->A->symmetric_set) {
28713301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
2872e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
28733301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
2874e496cd5dSStefano Zampini #endif
28753301b35fSStefano Zampini   }
2876d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
2877aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
2878aa0d41d4SStefano Zampini }
2879aa0d41d4SStefano Zampini 
2880aa0d41d4SStefano Zampini #undef __FUNCT__
2881a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
28828ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
2883a64d13efSStefano Zampini {
2884a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
2885a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
2886d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
288753892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
28883a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
28893a50541eSStefano Zampini   PetscInt        vbs,bs;
28906816873aSStefano Zampini   PetscBT         bitmask=NULL;
2891a64d13efSStefano Zampini   PetscErrorCode  ierr;
2892a64d13efSStefano Zampini 
2893a64d13efSStefano Zampini   PetscFunctionBegin;
2894b23d619eSStefano Zampini   /*
2895b23d619eSStefano Zampini     No need to setup local scatters if
2896b23d619eSStefano Zampini       - primal space is unchanged
2897b23d619eSStefano Zampini         AND
2898b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
2899b23d619eSStefano Zampini         AND
2900b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
2901b23d619eSStefano Zampini   */
2902b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
2903f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
2904f4ddd8eeSStefano Zampini   }
2905f4ddd8eeSStefano Zampini   /* destroy old objects */
2906f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
2907f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
2908f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
2909a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
2910b371cd4fSStefano Zampini   n_B = pcis->n_B;
2911b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
2912b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
29133a50541eSStefano Zampini 
2914a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
29156816873aSStefano Zampini 
291653892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
2917b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
2918854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
2919a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
2920a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
29210e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
2922a64d13efSStefano Zampini     }
2923a64d13efSStefano Zampini 
2924a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
29254641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
29266816873aSStefano Zampini         idx_R_local[n_R++] = i;
2927a64d13efSStefano Zampini       }
2928a64d13efSStefano Zampini     }
2929df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
2930df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
29316816873aSStefano Zampini 
2932df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2933df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
29346816873aSStefano Zampini   }
29353a50541eSStefano Zampini 
29363a50541eSStefano Zampini   /* Block code */
29373a50541eSStefano Zampini   vbs = 1;
29383a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
29393a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
29403a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
29413a50541eSStefano Zampini     PetscInt  *vary;
2942b334f244SStefano Zampini     if (!sub_schurs || !sub_schurs->reuse_solver) {
2943785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
29443a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
2945d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
2946d3df7717SStefano 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 */
29470e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
2948d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
29493a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
29503a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
29513a50541eSStefano Zampini           break;
29523a50541eSStefano Zampini         }
29533a50541eSStefano Zampini       }
2954d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
2955d3df7717SStefano Zampini     } else {
2956d3df7717SStefano Zampini       /* Verify directly the R set */
2957d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
2958d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
2959d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
2960d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
2961d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
2962d3df7717SStefano Zampini             break;
2963d3df7717SStefano Zampini           }
2964d3df7717SStefano Zampini         }
2965d3df7717SStefano Zampini       }
2966d3df7717SStefano Zampini     }
29673a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
29683a50541eSStefano Zampini       vbs = bs;
29693a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
29703a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
29713a50541eSStefano Zampini       }
29723a50541eSStefano Zampini     }
29733a50541eSStefano Zampini   }
29743a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
2975b334f244SStefano Zampini   if (sub_schurs && sub_schurs->reuse_solver) {
2976df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
297753892102SStefano Zampini 
2978df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2979df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
298053892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
2981df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
298253892102SStefano Zampini   } else {
29833a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
298453892102SStefano Zampini   }
2985a64d13efSStefano Zampini 
2986a64d13efSStefano Zampini   /* print some info if requested */
2987a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
2988a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
2989a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
29901575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
2991a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
2992a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
29934f1b2e48SStefano 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);
2994a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2995a64d13efSStefano Zampini   }
2996a64d13efSStefano Zampini 
2997a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
2998b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
29996816873aSStefano Zampini     IS       is_aux1,is_aux2;
30006816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
30016816873aSStefano Zampini 
30023a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
3003854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
3004854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
3005a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
30064641a718SStefano Zampini     for (i=0; i<n_D; i++) {
30074641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
30084641a718SStefano Zampini     }
3009a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3010a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
30114641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
30124641a718SStefano Zampini         aux_array1[j++] = i;
3013a64d13efSStefano Zampini       }
3014a64d13efSStefano Zampini     }
3015a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
3016a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3017a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
30184641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
30194641a718SStefano Zampini         aux_array2[j++] = i;
3020a64d13efSStefano Zampini       }
3021a64d13efSStefano Zampini     }
3022a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3023a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
3024a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
3025a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
3026a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
3027a64d13efSStefano Zampini 
30288eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
3029785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
3030a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
30314641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
30324641a718SStefano Zampini           aux_array1[j++] = i;
3033a64d13efSStefano Zampini         }
3034a64d13efSStefano Zampini       }
3035a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
3036a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
3037a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
3038a64d13efSStefano Zampini     }
30394641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
30403a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
3041d62866d3SStefano Zampini   } else {
3042df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
30436816873aSStefano Zampini     IS                 tis;
30446816873aSStefano Zampini     PetscInt           schur_size;
30456816873aSStefano Zampini 
3046df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
30476816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
3048df4d28bfSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
30496816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
30506816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
30516816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
30526816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
30536816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
3054d62866d3SStefano Zampini     }
3055d62866d3SStefano Zampini   }
3056a64d13efSStefano Zampini   PetscFunctionReturn(0);
3057a64d13efSStefano Zampini }
3058a64d13efSStefano Zampini 
3059304d26faSStefano Zampini 
3060304d26faSStefano Zampini #undef __FUNCT__
3061304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
3062684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
3063304d26faSStefano Zampini {
3064304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3065304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
3066304d26faSStefano Zampini   PC             pc_temp;
3067304d26faSStefano Zampini   Mat            A_RR;
3068f4ddd8eeSStefano Zampini   MatReuse       reuse;
3069304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
3070304d26faSStefano Zampini   PetscReal      value;
307104708bb6SStefano Zampini   PetscInt       n_D,n_R;
3072c7017625SStefano Zampini   PetscBool      check_corr[2],issbaij;
3073304d26faSStefano Zampini   PetscErrorCode ierr;
3074e604994aSStefano Zampini   /* prefixes stuff */
3075312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
3076e604994aSStefano Zampini   size_t         len;
3077304d26faSStefano Zampini 
3078304d26faSStefano Zampini   PetscFunctionBegin;
3079304d26faSStefano Zampini 
3080e604994aSStefano Zampini   /* compute prefixes */
3081e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
3082e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
3083e604994aSStefano Zampini   if (!pcbddc->current_level) {
3084e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
3085e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
3086e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
3087e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
3088e604994aSStefano Zampini   } else {
3089e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
3090312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
3091e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
3092e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
3093312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
3094312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
309534d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
309634d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
3097e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
3098e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
3099e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
3100e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
3101e604994aSStefano Zampini   }
3102e604994aSStefano Zampini 
3103304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
3104684f6988SStefano Zampini   if (dirichlet) {
3105d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
3106450f8f5eSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
3107*9a962809SStefano Zampini       if (!sub_schurs || !sub_schurs->reuse_solver) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented\n");
3108450f8f5eSStefano Zampini       if (pcbddc->dbg_flag) {
3109a3df083aSStefano Zampini         Mat    A_IIn;
3110a3df083aSStefano Zampini 
3111a3df083aSStefano Zampini         ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
3112a3df083aSStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
3113a3df083aSStefano Zampini         pcis->A_II = A_IIn;
3114a3df083aSStefano Zampini       }
3115450f8f5eSStefano Zampini     }
31163301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
31173301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
3118964fefecSStefano Zampini     }
3119ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
3120964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
3121304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
3122304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
3123304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
3124304d26faSStefano Zampini       /* default */
3125304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
3126e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
31279577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
3128304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
31299577ea80SStefano Zampini       if (issbaij) {
31309577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
31319577ea80SStefano Zampini       } else {
3132304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
31339577ea80SStefano Zampini       }
3134304d26faSStefano Zampini       /* Allow user's customization */
3135304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
3136304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
3137304d26faSStefano Zampini     }
3138d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
3139b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
3140df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3141d62866d3SStefano Zampini 
3142df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
3143d5574798SStefano Zampini     }
3144304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
3145304d26faSStefano Zampini     if (!n_D) {
3146304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
3147304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
3148304d26faSStefano Zampini     }
3149304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
3150304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
3151304d26faSStefano Zampini     /* set ksp_D into pcis data */
3152304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
3153304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
3154304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
3155684f6988SStefano Zampini   }
3156304d26faSStefano Zampini 
3157304d26faSStefano Zampini   /* NEUMANN PROBLEM */
3158684f6988SStefano Zampini   A_RR = 0;
3159684f6988SStefano Zampini   if (neumann) {
3160d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
316104708bb6SStefano Zampini     PetscInt        ibs,mbs;
316204708bb6SStefano Zampini     PetscBool       issbaij;
316304708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
3164f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
31658ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
3166f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
3167f4ddd8eeSStefano Zampini       PetscInt nn_R;
316881d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
3169f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
3170f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
3171f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
3172f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
3173f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3174f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
3175f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
3176727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
3177f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3178f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
3179f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
3180f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
3181f4ddd8eeSStefano Zampini         }
3182f4ddd8eeSStefano Zampini       }
3183f4ddd8eeSStefano Zampini       /* last check */
3184d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
3185f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3186f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
3187f4ddd8eeSStefano Zampini       }
3188f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
3189f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
3190f4ddd8eeSStefano Zampini     }
3191a00504b5SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection */
3192af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
3193af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
319404708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
319504708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
319604708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
319704708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
319804708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
3199af732b37SStefano Zampini       } else {
3200511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
32016816873aSStefano Zampini       }
320204708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
320304708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
320404708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
320504708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
320604708bb6SStefano Zampini       } else {
3207511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
320804708bb6SStefano Zampini       }
320904708bb6SStefano Zampini     }
3210a00504b5SStefano Zampini     /* extract A_RR */
3211b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
3212a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3213a00504b5SStefano Zampini 
3214a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
321516e386b8SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3216a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
321716e386b8SStefano Zampini           ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR);CHKERRQ(ierr);
321816e386b8SStefano Zampini         } else {
3219a00504b5SStefano Zampini           ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
3220a00504b5SStefano Zampini         }
3221a00504b5SStefano Zampini       } else {
3222a00504b5SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3223a00504b5SStefano Zampini         ierr = PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
3224a00504b5SStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
3225a00504b5SStefano Zampini       }
3226a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
3227f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
322816e386b8SStefano Zampini     }
32293301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
32303301b35fSStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
32316816873aSStefano Zampini     }
3232f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
3233304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
3234304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
3235304d26faSStefano Zampini       /* default */
3236304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
3237e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
3238304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
32399577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
32409577ea80SStefano Zampini       if (issbaij) {
32419577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
32429577ea80SStefano Zampini       } else {
3243304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
32449577ea80SStefano Zampini       }
3245304d26faSStefano Zampini       /* Allow user's customization */
3246304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
3247304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
3248304d26faSStefano Zampini     }
3249304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
3250304d26faSStefano Zampini     if (!n_R) {
3251304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
3252304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
3253304d26faSStefano Zampini     }
32545cbda25cSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
3255df4d28bfSStefano Zampini     /* Reuse solver if it is present */
3256b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
3257df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3258d62866d3SStefano Zampini 
3259df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
3260d62866d3SStefano Zampini     }
3261304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
3262304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
3263684f6988SStefano Zampini   }
3264304d26faSStefano Zampini 
3265684f6988SStefano Zampini   if (pcbddc->dbg_flag) {
3266684f6988SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
32671575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3268684f6988SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
3269684f6988SStefano Zampini   }
3270c7017625SStefano Zampini 
3271c7017625SStefano Zampini   /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */
3272c7017625SStefano Zampini   check_corr[0] = check_corr[1] = PETSC_FALSE;
3273c7017625SStefano Zampini   if (pcbddc->NullSpace_corr[0]) {
3274c7017625SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
3275c7017625SStefano Zampini   }
3276c7017625SStefano Zampini   if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) {
3277c7017625SStefano Zampini     check_corr[0] = PETSC_TRUE;
3278c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcbddc->NullSpace_corr[1]);CHKERRQ(ierr);
3279c7017625SStefano Zampini   }
3280c7017625SStefano Zampini   if (neumann && pcbddc->NullSpace_corr[2]) {
3281c7017625SStefano Zampini     check_corr[1] = PETSC_TRUE;
3282c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->NullSpace_corr[3]);CHKERRQ(ierr);
3283c7017625SStefano Zampini   }
3284c7017625SStefano Zampini 
3285c7017625SStefano Zampini   /* check Dirichlet and Neumann solvers */
3286c7017625SStefano Zampini   if (pcbddc->dbg_flag) {
3287684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
32880fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
32890fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
32900fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
32910fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
32920fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
3293e604994aSStefano 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);
3294c7017625SStefano Zampini       if (check_corr[0]) {
3295c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_TRUE);CHKERRQ(ierr);
3296c7017625SStefano Zampini       }
3297304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3298304d26faSStefano Zampini     }
3299684f6988SStefano Zampini     if (neumann) { /* Neumann */
33000fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
33010fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
33020fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
33030fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
33040fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
3305e604994aSStefano 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);
3306c7017625SStefano Zampini       if (check_corr[1]) {
3307c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_FALSE);CHKERRQ(ierr);
3308c7017625SStefano Zampini       }
3309304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3310304d26faSStefano Zampini     }
3311684f6988SStefano Zampini   }
33125cbda25cSStefano Zampini   /* free Neumann problem's matrix */
33135cbda25cSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3314304d26faSStefano Zampini   PetscFunctionReturn(0);
3315304d26faSStefano Zampini }
3316304d26faSStefano Zampini 
3317304d26faSStefano Zampini #undef __FUNCT__
3318ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
331980677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
3320674ae819SStefano Zampini {
3321674ae819SStefano Zampini   PetscErrorCode  ierr;
3322674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
3323be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
3324b334f244SStefano Zampini   PetscBool       reuse_solver = sub_schurs ? ( sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE ) : PETSC_FALSE;
3325674ae819SStefano Zampini 
3326674ae819SStefano Zampini   PetscFunctionBegin;
3327b334f244SStefano Zampini   if (!reuse_solver) {
332880677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
332920c7b377SStefano Zampini   }
333080677318SStefano Zampini   if (!pcbddc->switch_static) {
333180677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
333280677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
333380677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
333420c7b377SStefano Zampini     }
3335b334f244SStefano Zampini     if (!reuse_solver) {
333680677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
333780677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
333820c7b377SStefano Zampini     } else {
3339df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3340be83ff47SStefano Zampini 
3341df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3342df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
334320c7b377SStefano Zampini     }
3344be83ff47SStefano Zampini   } else {
334580677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
334680677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
334780677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
334880677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
334980677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
335080677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
335180677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
335280677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
335380677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3354674ae819SStefano Zampini     }
3355674ae819SStefano Zampini   }
3356b334f244SStefano Zampini   if (!reuse_solver || pcbddc->switch_static) {
335780677318SStefano Zampini     if (applytranspose) {
335880677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
335980677318SStefano Zampini     } else {
336080677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
336180677318SStefano Zampini     }
3362be83ff47SStefano Zampini   } else {
3363df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3364be83ff47SStefano Zampini 
3365be83ff47SStefano Zampini     if (applytranspose) {
3366df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
3367be83ff47SStefano Zampini     } else {
3368df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
3369be83ff47SStefano Zampini     }
3370be83ff47SStefano Zampini   }
337180677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
337280677318SStefano Zampini   if (!pcbddc->switch_static) {
3373b334f244SStefano Zampini     if (!reuse_solver) {
337480677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
337580677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3376be83ff47SStefano Zampini     } else {
3377df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3378be83ff47SStefano Zampini 
3379df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3380df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3381be83ff47SStefano Zampini     }
338280677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
338380677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
338480677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
338580677318SStefano Zampini     }
338680677318SStefano Zampini   } else {
338780677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
338880677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
338980677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
339080677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
339180677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
339280677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
339380677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
339480677318SStefano Zampini     }
339580677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
339680677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
339780677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
339880677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3399674ae819SStefano Zampini   }
3400674ae819SStefano Zampini   PetscFunctionReturn(0);
3401674ae819SStefano Zampini }
3402674ae819SStefano Zampini 
3403dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
3404674ae819SStefano Zampini #undef __FUNCT__
3405674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
3406dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
3407674ae819SStefano Zampini {
3408674ae819SStefano Zampini   PetscErrorCode ierr;
3409674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
3410674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
3411674ae819SStefano Zampini   const PetscScalar zero = 0.0;
3412674ae819SStefano Zampini 
3413674ae819SStefano Zampini   PetscFunctionBegin;
3414dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
34154fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
3416dc359a40SStefano Zampini     if (applytranspose) {
3417674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
34188eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
3419dc359a40SStefano Zampini     } else {
3420674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
3421674ae819SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
342215aaf578SStefano Zampini     }
34234fee134fSStefano Zampini   } else {
34244fee134fSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
34254fee134fSStefano Zampini   }
3426efc2fbd9SStefano Zampini 
3427efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
34284f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
3429efc2fbd9SStefano Zampini     PetscScalar *array;
34304f1b2e48SStefano Zampini     PetscInt    j;
3431efc2fbd9SStefano Zampini 
3432efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
34334f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
3434efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
3435efc2fbd9SStefano Zampini   }
3436efc2fbd9SStefano Zampini 
343712edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
343812edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
343912edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
344012edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
344112edc857SStefano Zampini 
34429f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
344312edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
344451694757SStefano Zampini     Mat          coarse_mat;
3445964fefecSStefano Zampini     Vec          rhs,sol;
344651694757SStefano Zampini     MatNullSpace nullsp;
344727b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
3448964fefecSStefano Zampini 
344927b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
345027b6a85dSStefano Zampini       PC        coarse_pc;
345127b6a85dSStefano Zampini 
345227b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
345327b6a85dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
345427b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
345527b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
345627b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
345727b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
34583bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
345927b6a85dSStefano Zampini       }
346027b6a85dSStefano Zampini     }
3461964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
3462964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
346351694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
346451694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
346551694757SStefano Zampini     if (nullsp) {
346651694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
346751694757SStefano Zampini     }
346812edc857SStefano Zampini     if (applytranspose) {
3469*9a962809SStefano Zampini       if (pcbddc->benign_apply_coarse_only) SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
3470964fefecSStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
34712701bc32SStefano Zampini     } else {
34721f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
34732701bc32SStefano Zampini         PC        coarse_pc;
34742701bc32SStefano Zampini 
34752701bc32SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
34762701bc32SStefano Zampini         ierr = PCPreSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
34773e589ea0SStefano Zampini         ierr = PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol);CHKERRQ(ierr);
34782701bc32SStefano Zampini         ierr = PCPostSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
347912edc857SStefano Zampini       } else {
3480964fefecSStefano Zampini         ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
348112edc857SStefano Zampini       }
34822701bc32SStefano Zampini     }
34831d82a3b6SStefano Zampini     /* we don't need the benign correction at coarser levels anymore */
348427b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
348527b6a85dSStefano Zampini       PC        coarse_pc;
348627b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
348727b6a85dSStefano Zampini 
348827b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
348927b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
349027b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
34913bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
349227b6a85dSStefano Zampini     }
349351694757SStefano Zampini     if (nullsp) {
349451694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
349551694757SStefano Zampini     }
349612edc857SStefano Zampini   }
3497674ae819SStefano Zampini 
3498674ae819SStefano Zampini   /* Local solution on R nodes */
34994fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
350080677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
35019f00e9b4SStefano Zampini   }
35029f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
35039f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
350412edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3505674ae819SStefano Zampini 
35064fee134fSStefano Zampini   /* Sum contributions from the two levels */
35074fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
3508dc359a40SStefano Zampini     if (applytranspose) {
3509dc359a40SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
3510dc359a40SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
3511dc359a40SStefano Zampini     } else {
3512674ae819SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
35138eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
3514dc359a40SStefano Zampini     }
3515efc2fbd9SStefano Zampini     /* store p0 */
35164f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
3517efc2fbd9SStefano Zampini       PetscScalar *array;
35184f1b2e48SStefano Zampini       PetscInt    j;
3519efc2fbd9SStefano Zampini 
3520efc2fbd9SStefano Zampini       ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
35214f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
3522efc2fbd9SStefano Zampini       ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
3523efc2fbd9SStefano Zampini     }
35244fee134fSStefano Zampini   } else { /* expand the coarse solution */
35254fee134fSStefano Zampini     if (applytranspose) {
35264fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
35274fee134fSStefano Zampini     } else {
35284fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
35294fee134fSStefano Zampini     }
35304fee134fSStefano Zampini   }
3531674ae819SStefano Zampini   PetscFunctionReturn(0);
3532674ae819SStefano Zampini }
3533674ae819SStefano Zampini 
3534674ae819SStefano Zampini #undef __FUNCT__
3535674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
353612edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
3537674ae819SStefano Zampini {
3538674ae819SStefano Zampini   PetscErrorCode ierr;
3539674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
354058da7f69SStefano Zampini   PetscScalar    *array;
354112edc857SStefano Zampini   Vec            from,to;
3542674ae819SStefano Zampini 
3543674ae819SStefano Zampini   PetscFunctionBegin;
354412edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
354512edc857SStefano Zampini     from = pcbddc->coarse_vec;
354612edc857SStefano Zampini     to = pcbddc->vec1_P;
354712edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
354812edc857SStefano Zampini       Vec tvec;
354958da7f69SStefano Zampini 
355058da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
355158da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
355212edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
355358da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
355458da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
355558da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
355612edc857SStefano Zampini     }
355712edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
355812edc857SStefano Zampini     from = pcbddc->vec1_P;
355912edc857SStefano Zampini     to = pcbddc->coarse_vec;
356012edc857SStefano Zampini   }
356112edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
3562674ae819SStefano Zampini   PetscFunctionReturn(0);
3563674ae819SStefano Zampini }
3564674ae819SStefano Zampini 
3565674ae819SStefano Zampini #undef __FUNCT__
3566674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
356712edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
3568674ae819SStefano Zampini {
3569674ae819SStefano Zampini   PetscErrorCode ierr;
3570674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
357158da7f69SStefano Zampini   PetscScalar    *array;
357212edc857SStefano Zampini   Vec            from,to;
3573674ae819SStefano Zampini 
3574674ae819SStefano Zampini   PetscFunctionBegin;
357512edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
357612edc857SStefano Zampini     from = pcbddc->coarse_vec;
357712edc857SStefano Zampini     to = pcbddc->vec1_P;
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 = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
358312edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
358412edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
358512edc857SStefano Zampini       Vec tvec;
358658da7f69SStefano Zampini 
358712edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
358858da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
358958da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
359058da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
359158da7f69SStefano Zampini     }
359258da7f69SStefano Zampini   } else {
359358da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
359458da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
359512edc857SStefano Zampini     }
359612edc857SStefano Zampini   }
3597674ae819SStefano Zampini   PetscFunctionReturn(0);
3598674ae819SStefano Zampini }
3599674ae819SStefano Zampini 
3600984c4197SStefano Zampini /* uncomment for testing purposes */
3601984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
3602674ae819SStefano Zampini #undef __FUNCT__
3603674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
3604674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
3605674ae819SStefano Zampini {
3606674ae819SStefano Zampini   PetscErrorCode    ierr;
3607674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
3608674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
3609674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
3610984c4197SStefano Zampini   /* one and zero */
3611984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
3612984c4197SStefano Zampini   /* space to store constraints and their local indices */
36139162d606SStefano Zampini   PetscScalar       *constraints_data;
36149162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
36159162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
36169162d606SStefano Zampini   PetscInt          *constraints_n;
3617984c4197SStefano Zampini   /* iterators */
3618b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
3619984c4197SStefano Zampini   /* BLAS integers */
3620e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
3621e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
3622c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
3623727cdba6SStefano Zampini   /* reuse */
36240e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
36250e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
3626984c4197SStefano Zampini   /* change of basis */
3627b3d85658SStefano Zampini   PetscBool         qr_needed;
36289162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
3629984c4197SStefano Zampini   /* auxiliary stuff */
363064efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
36318a0068c3SStefano Zampini   PetscInt          ncc;
3632984c4197SStefano Zampini   /* some quantities */
363345a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
3634a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
3635984c4197SStefano Zampini 
3636674ae819SStefano Zampini   PetscFunctionBegin;
36378e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
36388e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
36398e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
364016909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
3641088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
3642088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
36430e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
36440e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
36450e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
36460e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
36470e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
3648088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
3649cf5a6209SStefano Zampini 
3650cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
36519162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
3652cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
3653cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
3654cf5a6209SStefano Zampini     Vec          *localnearnullsp;
3655cf5a6209SStefano Zampini     PetscScalar  *array;
3656cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
3657cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
3658674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
3659b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
3660674ae819SStefano Zampini     PetscScalar  *work;
3661674ae819SStefano Zampini     PetscReal    *singular_vals;
3662674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3663674ae819SStefano Zampini     PetscReal    *rwork;
3664674ae819SStefano Zampini #endif
3665674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3666674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
3667674ae819SStefano Zampini #else
3668964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
3669964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
3670674ae819SStefano Zampini #endif
3671674ae819SStefano Zampini 
3672674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
3673d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
3674e4d548c7SStefano Zampini     /* print some info */
36751f4df5f7SStefano Zampini     if (pcbddc->dbg_flag && !pcbddc->sub_schurs) {
3676e4d548c7SStefano Zampini       PetscInt nv;
3677e4d548c7SStefano Zampini 
3678e4d548c7SStefano Zampini       ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
3679e4d548c7SStefano Zampini       ierr = ISGetSize(ISForVertices,&nv);CHKERRQ(ierr);
3680e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3681e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3682e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
3683e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges);CHKERRQ(ierr);
3684e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces);CHKERRQ(ierr);
3685e4d548c7SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3686e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3687e4d548c7SStefano Zampini     }
3688e4d548c7SStefano Zampini 
3689d06fc5fdSStefano Zampini     /* free unneeded index sets */
3690d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
3691d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
3692674ae819SStefano Zampini     }
3693d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
3694d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
3695d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
3696d06fc5fdSStefano Zampini       }
3697d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
3698d06fc5fdSStefano Zampini       n_ISForEdges = 0;
3699d06fc5fdSStefano Zampini     }
3700d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
3701d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
3702d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
3703d06fc5fdSStefano Zampini       }
3704d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
3705d06fc5fdSStefano Zampini       n_ISForFaces = 0;
3706d06fc5fdSStefano Zampini     }
370770022509SStefano Zampini 
3708674ae819SStefano Zampini     /* check if near null space is attached to global mat */
3709674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
3710674ae819SStefano Zampini     if (nearnullsp) {
3711674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
3712f4ddd8eeSStefano Zampini       /* remove any stored info */
3713f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
3714f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3715f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
3716f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
3717f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
3718473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3719f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
3720f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
3721f4ddd8eeSStefano Zampini       }
3722984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
3723984c4197SStefano Zampini       nnsp_size = 0;
3724674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
3725674ae819SStefano Zampini     }
3726984c4197SStefano Zampini     /* get max number of constraints on a single cc */
3727984c4197SStefano Zampini     max_constraints = nnsp_size;
3728984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
3729984c4197SStefano Zampini 
3730674ae819SStefano Zampini     /*
3731674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
37329162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
37339162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
37349162d606SStefano Zampini          There can be multiple constraints per connected component
3735674ae819SStefano Zampini                                                                                                                                                            */
3736674ae819SStefano Zampini     n_vertices = 0;
3737674ae819SStefano Zampini     if (ISForVertices) {
3738674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
3739674ae819SStefano Zampini     }
37409162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
37419162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
37429162d606SStefano Zampini 
37439162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
37449162d606SStefano Zampini     total_counts *= max_constraints;
3745674ae819SStefano Zampini     total_counts += n_vertices;
37464641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
37479162d606SStefano Zampini 
3748674ae819SStefano Zampini     total_counts = 0;
3749674ae819SStefano Zampini     max_size_of_constraint = 0;
3750674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
37519162d606SStefano Zampini       IS used_is;
3752674ae819SStefano Zampini       if (i<n_ISForEdges) {
37539162d606SStefano Zampini         used_is = ISForEdges[i];
3754674ae819SStefano Zampini       } else {
37559162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
3756674ae819SStefano Zampini       }
37579162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
3758674ae819SStefano Zampini       total_counts += j;
3759674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
3760674ae819SStefano Zampini     }
37619162d606SStefano 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);
37629162d606SStefano Zampini 
3763984c4197SStefano Zampini     /* get local part of global near null space vectors */
3764785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
3765984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
3766984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
3767e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3768e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3769984c4197SStefano Zampini     }
3770674ae819SStefano Zampini 
3771242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
3772242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
3773a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
3774242a89d7SStefano Zampini 
3775984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
3776a773dcb8SStefano Zampini     if (!skip_lapack) {
3777674ae819SStefano Zampini       PetscScalar temp_work;
3778911cabfeSStefano Zampini 
3779674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3780984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
3781785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
3782785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
3783785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
3784674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3785785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
3786674ae819SStefano Zampini #endif
3787674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
3788c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
3789c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
3790674ae819SStefano Zampini       lwork = -1;
3791674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3792674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
3793c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
3794674ae819SStefano Zampini #else
3795c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
3796674ae819SStefano Zampini #endif
3797674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3798984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
3799674ae819SStefano Zampini #else /* on missing GESVD */
3800674ae819SStefano Zampini       /* SVD */
3801674ae819SStefano Zampini       PetscInt max_n,min_n;
3802674ae819SStefano Zampini       max_n = max_size_of_constraint;
3803984c4197SStefano Zampini       min_n = max_constraints;
3804984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
3805674ae819SStefano Zampini         min_n = max_size_of_constraint;
3806984c4197SStefano Zampini         max_n = max_constraints;
3807674ae819SStefano Zampini       }
3808785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
3809674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3810785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
3811674ae819SStefano Zampini #endif
3812674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
3813674ae819SStefano Zampini       lwork = -1;
3814e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
3815e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
3816b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
3817674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3818674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
38199162d606SStefano 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));
3820674ae819SStefano Zampini #else
38219162d606SStefano 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));
3822674ae819SStefano Zampini #endif
3823674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3824984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
3825984c4197SStefano Zampini #endif /* on missing GESVD */
3826674ae819SStefano Zampini       /* Allocate optimal workspace */
3827674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
3828854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
3829674ae819SStefano Zampini     }
3830674ae819SStefano Zampini     /* Now we can loop on constraining sets */
3831674ae819SStefano Zampini     total_counts = 0;
38329162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
38339162d606SStefano Zampini     constraints_data_ptr[0] = 0;
3834674ae819SStefano Zampini     /* vertices */
38359162d606SStefano Zampini     if (n_vertices) {
3836674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
38379162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
3838674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
38399162d606SStefano Zampini         constraints_n[total_counts] = 1;
38409162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
38419162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
38429162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
3843674ae819SStefano Zampini         total_counts++;
3844674ae819SStefano Zampini       }
3845674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3846674ae819SStefano Zampini       n_vertices = total_counts;
3847674ae819SStefano Zampini     }
3848984c4197SStefano Zampini 
3849674ae819SStefano Zampini     /* edges and faces */
38509162d606SStefano Zampini     total_counts_cc = total_counts;
3851911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
38529162d606SStefano Zampini       IS        used_is;
38539162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
38549162d606SStefano Zampini 
3855911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
38569162d606SStefano Zampini         used_is = ISForEdges[ncc];
3857984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
3858674ae819SStefano Zampini       } else {
38599162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
3860984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
3861674ae819SStefano Zampini       }
3862674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
38639162d606SStefano Zampini 
38649162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
38659162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3866984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
3867984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
3868674ae819SStefano Zampini       if (nnsp_has_cnst) {
38695b08dc53SStefano Zampini         PetscScalar quad_value;
38709162d606SStefano Zampini 
38719162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
38729162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
38739162d606SStefano Zampini 
3874a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
3875674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
3876a773dcb8SStefano Zampini         } else {
3877a773dcb8SStefano Zampini           quad_value = 1.0;
3878a773dcb8SStefano Zampini         }
3879674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
38809162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
3881674ae819SStefano Zampini         }
38829162d606SStefano Zampini         temp_constraints++;
3883674ae819SStefano Zampini         total_counts++;
3884674ae819SStefano Zampini       }
3885674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
3886984c4197SStefano Zampini         PetscReal real_value;
38879162d606SStefano Zampini         PetscScalar *ptr_to_data;
38889162d606SStefano Zampini 
3889984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
38909162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
3891674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
38929162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
3893674ae819SStefano Zampini         }
3894984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
3895984c4197SStefano Zampini         /* check if array is null on the connected component */
3896e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
38979162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
38985b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
3899674ae819SStefano Zampini           temp_constraints++;
3900674ae819SStefano Zampini           total_counts++;
39019162d606SStefano Zampini           if (!idxs_copied) {
39029162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
39039162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
3904674ae819SStefano Zampini           }
3905674ae819SStefano Zampini         }
39069162d606SStefano Zampini       }
39079162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
390845a1bb75SStefano Zampini       valid_constraints = temp_constraints;
3909eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
3910a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
39119162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
39129162d606SStefano Zampini 
39139162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
3914a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
39159162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
3916a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
39179162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
3918a773dcb8SStefano Zampini         } else { /* perform SVD */
3919984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
39209162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
3921674ae819SStefano Zampini 
3922674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3923984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
3924984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
3925984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
3926984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
3927984c4197SStefano Zampini                 from that computed using LAPACKgesvd
3928984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
3929984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
3930984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
3931674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
3932e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3933984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3934674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
3935674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
39369162d606SStefano 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));
3937674ae819SStefano Zampini             }
3938674ae819SStefano Zampini           }
3939e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
3940e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3941e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
3942674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
3943c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
3944674ae819SStefano Zampini #else
3945c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
3946674ae819SStefano Zampini #endif
3947674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3948984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
3949984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
3950674ae819SStefano Zampini           j = 0;
3951984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
3952674ae819SStefano Zampini           total_counts = total_counts-j;
395345a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
3954e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
3955c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3956c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3957c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
3958c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3959c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
3960c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
3961674ae819SStefano Zampini           if (j<temp_constraints) {
3962984c4197SStefano Zampini             PetscInt ii;
3963984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
3964674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
39659162d606SStefano 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));
3966674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
3967984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
3968674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
39699162d606SStefano 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];
3970674ae819SStefano Zampini               }
3971674ae819SStefano Zampini             }
3972674ae819SStefano Zampini           }
3973674ae819SStefano Zampini #else  /* on missing GESVD */
3974e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3975e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3976b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3977674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3978674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
39799162d606SStefano 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));
3980674ae819SStefano Zampini #else
39819162d606SStefano 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));
3982674ae819SStefano Zampini #endif
3983984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
3984674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3985984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
3986e310c8b4SStefano Zampini           k = temp_constraints;
3987e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
3988674ae819SStefano Zampini           j = 0;
3989e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
399045a1bb75SStefano Zampini           valid_constraints = k-j;
3991911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
3992984c4197SStefano Zampini #endif /* on missing GESVD */
3993674ae819SStefano Zampini         }
3994a773dcb8SStefano Zampini       }
39959162d606SStefano Zampini       /* update pointers information */
39969162d606SStefano Zampini       if (valid_constraints) {
39979162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
39989162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
39999162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
40009162d606SStefano Zampini         /* set change_of_basis flag */
400145a1bb75SStefano Zampini         if (boolforchange) {
4002b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
40039162d606SStefano Zampini         }
4004b3d85658SStefano Zampini         total_counts_cc++;
400545a1bb75SStefano Zampini       }
400645a1bb75SStefano Zampini     }
4007984c4197SStefano Zampini     /* free workspace */
40088f1c130eSStefano Zampini     if (!skip_lapack) {
4009984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
4010984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
4011984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
4012984c4197SStefano Zampini #endif
4013984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
4014984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
4015984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
4016984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
4017984c4197SStefano Zampini #endif
4018984c4197SStefano Zampini     }
4019984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
4020984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
4021984c4197SStefano Zampini     }
4022984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
4023cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
4024cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
4025cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
4026cf5a6209SStefano Zampini     }
4027cf5a6209SStefano Zampini     if (n_ISForFaces) {
4028cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
4029cf5a6209SStefano Zampini     }
4030cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
4031cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
4032cf5a6209SStefano Zampini     }
4033cf5a6209SStefano Zampini     if (n_ISForEdges) {
4034cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
4035cf5a6209SStefano Zampini     }
4036cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
403708122e43SStefano Zampini   } else {
403808122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
4039984c4197SStefano Zampini 
404008122e43SStefano Zampini     total_counts = 0;
404108122e43SStefano Zampini     n_vertices = 0;
4042d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
4043d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
404408122e43SStefano Zampini     }
404508122e43SStefano Zampini     max_constraints = 0;
40469162d606SStefano Zampini     total_counts_cc = 0;
404708122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
404808122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
40499162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
405008122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
405108122e43SStefano Zampini     }
40529162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
40539162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
40549162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
40559162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
405674d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
40579162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
40589162d606SStefano Zampini     total_counts_cc = 0;
40599162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
40609162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
40619162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
406208122e43SStefano Zampini       }
406308122e43SStefano Zampini     }
40649162d606SStefano Zampini #if 0
40659162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
40669162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
40679162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
40689162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
40699162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
40709162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
40719162d606SStefano Zampini       }
40729162d606SStefano Zampini       printf("\n");
40739162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
40749162d606SStefano Zampini     }
40751b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
40768bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
40771b968477SStefano Zampini     }
40781b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
40798bec7fa6SStefano 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]);
40801b968477SStefano Zampini     }
408108122e43SStefano Zampini #endif
408208122e43SStefano Zampini 
40838bec7fa6SStefano Zampini     max_size_of_constraint = 0;
40849162d606SStefano 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]);
40859162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
408608122e43SStefano Zampini     /* Change of basis */
4087b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
408808122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
408908122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
409008122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
4091b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
409208122e43SStefano Zampini         }
409308122e43SStefano Zampini       }
409408122e43SStefano Zampini     }
409508122e43SStefano Zampini   }
4096984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
40974f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
409808122e43SStefano Zampini 
40999162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
41009162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
41016c4ed002SBarry 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);
4102674ae819SStefano Zampini 
4103674ae819SStefano Zampini   /* Create constraint matrix */
4104674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
410516f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
4106984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
4107984c4197SStefano Zampini 
4108984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
4109a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
4110a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
411174d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
4112984c4197SStefano Zampini   total_primal_vertices=0;
4113b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
41149162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
41159162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
411672b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
41179162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
4118b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
411964efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
41209162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
41219162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
4122a717540cSStefano Zampini       }
4123b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
412491af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
4125a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
4126a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
4127a717540cSStefano Zampini       }
4128fa434743SStefano Zampini     } else {
4129b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
4130fa434743SStefano Zampini     }
4131a717540cSStefano Zampini   }
4132b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
4133b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
4134674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
413570022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
4136b3d85658SStefano Zampini 
41374f1b2e48SStefano 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);
41380e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
41390e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
4140984c4197SStefano Zampini 
4141984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
414274d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
4143785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
4144984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
414574d5cdf7SStefano Zampini 
4146984c4197SStefano Zampini   j = total_primal_vertices;
414774d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
4148b3d85658SStefano Zampini   cum = total_primal_vertices;
41499162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
41504641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
4151b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
4152b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
4153b3d85658SStefano Zampini       cum++;
41549162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
415574d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
415674d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
415774d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
415874d5cdf7SStefano Zampini       }
41599162d606SStefano Zampini       j += constraints_n[i];
4160674ae819SStefano Zampini     }
4161674ae819SStefano Zampini   }
4162674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
4163674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
4164088faed8SStefano Zampini 
4165674ae819SStefano Zampini   /* set values in constraint matrix */
4166984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
41670e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
4168674ae819SStefano Zampini   }
4169984c4197SStefano Zampini   total_counts = total_primal_vertices;
41709162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
41714641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
41729162d606SStefano Zampini       PetscInt *cols;
41739162d606SStefano Zampini 
41749162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
41759162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
41769162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
41779162d606SStefano Zampini         PetscInt    row = total_counts+k;
41789162d606SStefano Zampini         PetscScalar *vals;
41799162d606SStefano Zampini 
41809162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
41819162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
41829162d606SStefano Zampini       }
41839162d606SStefano Zampini       total_counts += constraints_n[i];
4184674ae819SStefano Zampini     }
4185674ae819SStefano Zampini   }
4186674ae819SStefano Zampini   /* assembling */
4187674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4188674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4189088faed8SStefano Zampini 
4190984c4197SStefano Zampini   /*
41916a9046bcSBarry Smith   ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4192984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
4193f159cad9SBarry Smith   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
4194984c4197SStefano Zampini   */
4195674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
4196674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
4197026de310SStefano Zampini     /* dual and primal dofs on a single cc */
4198984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
4199984c4197SStefano Zampini     /* working stuff for GEQRF */
420081d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
4201984c4197SStefano Zampini     PetscBLASInt lqr_work;
4202984c4197SStefano Zampini     /* working stuff for UNGQR */
4203984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
4204984c4197SStefano Zampini     PetscBLASInt lgqr_work;
4205984c4197SStefano Zampini     /* working stuff for TRTRS */
4206984c4197SStefano Zampini     PetscScalar  *trs_rhs;
42073f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
4208984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
4209984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
4210984c4197SStefano Zampini     PetscScalar  *start_vals;
4211984c4197SStefano Zampini     /* working stuff for values insertion */
42124641a718SStefano Zampini     PetscBT      is_primal;
421364efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
4214906d46d4SStefano Zampini     /* matrix sizes */
4215906d46d4SStefano Zampini     PetscInt     global_size,local_size;
4216906d46d4SStefano Zampini     /* temporary change of basis */
4217906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
4218cf5a6209SStefano Zampini     /* extra space for debugging */
4219cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
4220984c4197SStefano Zampini 
4221906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
4222906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
422316f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
4224bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
4225906d46d4SStefano Zampini     /* nonzeros for local mat */
4226bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
42271dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
4228bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
42291dd7afcfSStefano Zampini     } else {
42301dd7afcfSStefano Zampini       const PetscInt *ii;
42311dd7afcfSStefano Zampini       PetscInt       n;
42321dd7afcfSStefano Zampini       PetscBool      flg_row;
42331dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
42341dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
42351dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
42361dd7afcfSStefano Zampini     }
42379162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
4238a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
42399162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
4240a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
42419162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
4242a717540cSStefano Zampini         } else {
42439162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
42449162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
4245a717540cSStefano Zampini         }
4246a717540cSStefano Zampini       }
4247a717540cSStefano Zampini     }
4248906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
4249bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
42501dd7afcfSStefano Zampini     /* Set interior change in the matrix */
42511dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
4252bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
4253906d46d4SStefano Zampini         ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
4254a717540cSStefano Zampini       }
42551dd7afcfSStefano Zampini     } else {
42561dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
42571dd7afcfSStefano Zampini       PetscScalar    *aa;
42581dd7afcfSStefano Zampini       PetscInt       n;
42591dd7afcfSStefano Zampini       PetscBool      flg_row;
42601dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
42611dd7afcfSStefano Zampini       ierr = MatSeqAIJGetArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
42621dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
42631dd7afcfSStefano Zampini         ierr = MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES);CHKERRQ(ierr);
42641dd7afcfSStefano Zampini       }
42651dd7afcfSStefano Zampini       ierr = MatSeqAIJRestoreArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
42661dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
42671dd7afcfSStefano Zampini     }
4268a717540cSStefano Zampini 
4269a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
4270a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
4271a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
4272a717540cSStefano Zampini     }
4273a717540cSStefano Zampini 
4274a717540cSStefano Zampini 
4275a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
4276a717540cSStefano Zampini     /*
4277a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
4278a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
4279a717540cSStefano Zampini 
4280a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
4281a717540cSStefano Zampini 
4282a6b551f4SStefano 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)
4283a6b551f4SStefano Zampini 
4284a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
4285a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
4286a717540cSStefano Zampini             |              ...                        |
4287a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
4288a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
4289a717540cSStefano Zampini 
4290a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
4291a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
4292a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
4293a6b551f4SStefano Zampini 
4294a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
4295a717540cSStefano Zampini     */
4296a717540cSStefano Zampini     if (qr_needed) {
4297984c4197SStefano Zampini       /* space to store Q */
4298854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
4299984c4197SStefano Zampini       /* first we issue queries for optimal work */
43003f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
43013f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
43023f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4303984c4197SStefano Zampini       lqr_work = -1;
43043f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
4305984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
4306984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
4307785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
4308984c4197SStefano Zampini       lgqr_work = -1;
43093f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
43103f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
43113f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
43123f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
43133f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
43143f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
4315984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
4316984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
4317785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
4318984c4197SStefano Zampini       /* array to store scaling factors for reflectors */
4319785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
4320984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
4321785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
4322a717540cSStefano Zampini       /* allocating workspace for check */
4323a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
4324cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
4325a717540cSStefano Zampini       }
4326a717540cSStefano Zampini     }
4327984c4197SStefano Zampini     /* array to store whether a node is primal or not */
43284641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
4329473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
43300e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
43316c4ed002SBarry 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);
433239e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
433339e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
433439e2fb2aSStefano Zampini     }
433539e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
4336984c4197SStefano Zampini 
4337a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
43389162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
43399162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
43404641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
4341984c4197SStefano Zampini         /* get constraint info */
43429162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
4343984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
4344984c4197SStefano Zampini 
4345984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
43469162d606SStefano 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);
4347674ae819SStefano Zampini         }
4348984c4197SStefano Zampini 
4349fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
4350a717540cSStefano Zampini 
4351a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
4352a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
43539162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
4354a717540cSStefano Zampini           }
4355984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
43569162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
4357984c4197SStefano Zampini 
4358984c4197SStefano Zampini           /* compute QR decomposition of constraints */
43593f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
43603f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
43613f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4362674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
43633f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
4364984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
4365674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4366984c4197SStefano Zampini 
4367984c4197SStefano Zampini           /* explictly compute R^-T */
4368984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
4369984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
43703f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
43713f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
43723f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
43733f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
4374984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
43753f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
4376984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
4377984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4378984c4197SStefano Zampini 
4379a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
43803f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
43813f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
43823f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
43833f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4384984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
43853f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
4386984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
4387984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4388984c4197SStefano Zampini 
4389984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
4390984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
4391984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
43923f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
43933f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
43943f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
43953f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
43963f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
43973f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
4398984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
43999162d606SStefano 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));
4400984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
44019162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
4402984c4197SStefano Zampini 
4403984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
44049162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
4405984c4197SStefano Zampini           /* insert cols for primal dofs */
4406984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
4407984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
44089162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
4409906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
4410984c4197SStefano Zampini           }
4411984c4197SStefano Zampini           /* insert cols for dual dofs */
4412984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
44139162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
4414984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
44159162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
4416906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
4417984c4197SStefano Zampini               j++;
4418674ae819SStefano Zampini             }
4419674ae819SStefano Zampini           }
4420984c4197SStefano Zampini 
4421984c4197SStefano Zampini           /* check change of basis */
4422984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
4423984c4197SStefano Zampini             PetscInt   ii,jj;
4424984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
4425c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
4426c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
4427c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
4428c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4429c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
4430c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
4431984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
4432cf5a6209SStefano 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));
4433984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
4434984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
4435984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
4436cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
4437cf5a6209SStefano 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;
4438674ae819SStefano Zampini               }
4439674ae819SStefano Zampini             }
4440984c4197SStefano Zampini             if (!valid_qr) {
444122d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
4442984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
4443984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
4444cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
4445cf5a6209SStefano 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]));
4446674ae819SStefano Zampini                   }
4447cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
4448cf5a6209SStefano 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]));
4449984c4197SStefano Zampini                   }
4450984c4197SStefano Zampini                 }
4451984c4197SStefano Zampini               }
4452674ae819SStefano Zampini             } else {
445322d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
4454674ae819SStefano Zampini             }
4455674ae819SStefano Zampini           }
4456a717540cSStefano Zampini         } else { /* simple transformation block */
4457a717540cSStefano Zampini           PetscInt    row,col;
4458a6b551f4SStefano Zampini           PetscScalar val,norm;
4459a6b551f4SStefano Zampini 
4460a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
44619162d606SStefano 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));
4462a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
44639162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
44649162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
4465bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
44669162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
4467906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
44689162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
4469a717540cSStefano Zampini             } else {
4470a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
44719162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
4472a717540cSStefano Zampini                 if (row != col) {
44739162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
4474a717540cSStefano Zampini                 } else {
44759162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
4476a717540cSStefano Zampini                 }
4477906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
4478a717540cSStefano Zampini               }
4479a717540cSStefano Zampini             }
4480a717540cSStefano Zampini           }
448198a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
448222d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
4483a717540cSStefano Zampini           }
4484674ae819SStefano Zampini         }
4485984c4197SStefano Zampini       } else {
4486984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
44879162d606SStefano 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);
4488674ae819SStefano Zampini         }
4489674ae819SStefano Zampini       }
4490674ae819SStefano Zampini     }
4491a717540cSStefano Zampini 
4492a717540cSStefano Zampini     /* free workspace */
4493a717540cSStefano Zampini     if (qr_needed) {
4494984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
4495cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
4496984c4197SStefano Zampini       }
4497984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
4498984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
4499984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
4500984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
4501984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
4502674ae819SStefano Zampini     }
4503a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
4504906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4505906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4506906d46d4SStefano Zampini 
4507906d46d4SStefano Zampini     /* assembling of global change of variable */
450888c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
4509bbb9e6c6SStefano Zampini       Mat      tmat;
451016f15bc4SStefano Zampini       PetscInt bs;
451116f15bc4SStefano Zampini 
4512906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
4513906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
4514bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
4515bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
4516bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
4517bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
451816f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
451916f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
4520906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
4521bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
4522bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
4523bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4524bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4525bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
4526e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4527e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4528bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
4529bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
453088c03ad3SStefano Zampini 
4531906d46d4SStefano Zampini       /* check */
4532906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
4533906d46d4SStefano Zampini         PetscReal error;
4534906d46d4SStefano Zampini         Vec       x,x_change;
4535906d46d4SStefano Zampini 
4536906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
4537906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
4538906d46d4SStefano Zampini         ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
4539906d46d4SStefano Zampini         ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
4540e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4541e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4542bbb9e6c6SStefano Zampini         ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
4543e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4544e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4545906d46d4SStefano Zampini         ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
4546906d46d4SStefano Zampini         ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
4547906d46d4SStefano Zampini         ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
4548906d46d4SStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4549bbb9e6c6SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
4550906d46d4SStefano Zampini         ierr = VecDestroy(&x);CHKERRQ(ierr);
4551906d46d4SStefano Zampini         ierr = VecDestroy(&x_change);CHKERRQ(ierr);
4552906d46d4SStefano Zampini       }
4553b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
4554b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
4555b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
4556bf3a8328SStefano Zampini 
4557*9a962809SStefano Zampini         if (pcbddc->use_change_of_basis && pcbddc->adaptive_userdefined) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot mix automatic change of basis, adaptive selection and user-defined constraints");CHKERRQ(ierr);
4558b334f244SStefano Zampini         if (sub_schurs && sub_schurs->S_Ej_all) {
4559ac632422SStefano Zampini           Mat                    S_new,tmat;
4560bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
4561bbb9e6c6SStefano Zampini 
4562bbb9e6c6SStefano Zampini           ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
45636816873aSStefano Zampini           ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
4564bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
4565bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
4566bf3a8328SStefano Zampini             IS                     is_V;
4567b087196eSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
4568b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
4569b087196eSStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
4570b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
4571b087196eSStefano Zampini             ierr = ISDestroy(&is_V);CHKERRQ(ierr);
4572bf3a8328SStefano Zampini           }
4573bf3a8328SStefano Zampini           ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
4574ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
4575b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
4576ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
4577bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
4578bf3a8328SStefano Zampini             const PetscScalar *array;
4579bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
4580bf3a8328SStefano Zampini             PetscInt          i,n_V;
4581bf3a8328SStefano Zampini 
4582b087196eSStefano Zampini             ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
4583b087196eSStefano Zampini             ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
4584b087196eSStefano Zampini             ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
4585b087196eSStefano Zampini             ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
4586b087196eSStefano Zampini             ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
4587b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
4588b087196eSStefano Zampini               PetscScalar val;
4589b087196eSStefano Zampini               PetscInt    idx;
4590b087196eSStefano Zampini 
4591b087196eSStefano Zampini               idx = idxs_V[i];
4592b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
4593b087196eSStefano Zampini               ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
4594b087196eSStefano Zampini             }
4595b087196eSStefano Zampini             ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4596b087196eSStefano Zampini             ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4597bf3a8328SStefano Zampini             ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
4598bf3a8328SStefano Zampini             ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
4599bf3a8328SStefano Zampini             ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
4600bf3a8328SStefano Zampini           }
4601ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
4602ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
4603ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
4604ac632422SStefano Zampini             ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
4605b96c3477SStefano Zampini             ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
4606ac632422SStefano Zampini             ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
4607bf3a8328SStefano Zampini             if (pcbddc->deluxe_zerorows) {
4608b087196eSStefano Zampini               ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
4609bf3a8328SStefano Zampini             }
4610ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
4611ac632422SStefano Zampini             ierr = MatDestroy(&S_new);CHKERRQ(ierr);
4612ac632422SStefano Zampini           }
4613b087196eSStefano Zampini           ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
461488c03ad3SStefano Zampini           ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4615b96c3477SStefano Zampini         }
4616c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
4617b334f244SStefano Zampini         if (sub_schurs && sub_schurs->change) {
4618c9db6a07SStefano Zampini           PetscInt i;
4619c9db6a07SStefano Zampini 
4620c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
4621c9db6a07SStefano Zampini             ierr = KSPDestroy(&sub_schurs->change[i]);CHKERRQ(ierr);
4622c9db6a07SStefano Zampini           }
4623c9db6a07SStefano Zampini           ierr = PetscFree(sub_schurs->change);CHKERRQ(ierr);
4624c9db6a07SStefano Zampini         }
4625b96c3477SStefano Zampini       }
462616909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
462716909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
462816909a7fSStefano Zampini       } else {
4629906d46d4SStefano Zampini         ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
463016909a7fSStefano Zampini       }
46311dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
463227b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
463372b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
463472b8c272SStefano Zampini       ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
463572b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
463672b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
463772b8c272SStefano Zampini     }
46381dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
463927b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
4640b9b85e73SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
4641b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
4642906d46d4SStefano Zampini     } else {
46431dd7afcfSStefano Zampini       Mat benign_global = NULL;
464427b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
46451dd7afcfSStefano Zampini         Mat tmat;
46461dd7afcfSStefano Zampini 
46471dd7afcfSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
46481dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
46491dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
46501dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
46511dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
46521dd7afcfSStefano Zampini         ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
46531dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
46541dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
46551dd7afcfSStefano Zampini         ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
46561dd7afcfSStefano Zampini         if (pcbddc->benign_change) {
46571dd7afcfSStefano Zampini           Mat M;
46581dd7afcfSStefano Zampini 
46591dd7afcfSStefano Zampini           ierr = MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M);CHKERRQ(ierr);
46601dd7afcfSStefano Zampini           ierr = MatDiagonalScale(M,pcis->vec1_N,NULL);CHKERRQ(ierr);
46611dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,M);CHKERRQ(ierr);
46621dd7afcfSStefano Zampini           ierr = MatDestroy(&M);CHKERRQ(ierr);
4663906d46d4SStefano Zampini         } else {
46641dd7afcfSStefano Zampini           Mat         eye;
46651dd7afcfSStefano Zampini           PetscScalar *array;
46661dd7afcfSStefano Zampini 
46671dd7afcfSStefano Zampini           ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
46681dd7afcfSStefano Zampini           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&eye);CHKERRQ(ierr);
46691dd7afcfSStefano Zampini           for (i=0;i<pcis->n;i++) {
46701dd7afcfSStefano Zampini             ierr = MatSetValue(eye,i,i,array[i],INSERT_VALUES);CHKERRQ(ierr);
4671906d46d4SStefano Zampini           }
46721dd7afcfSStefano Zampini           ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
46731dd7afcfSStefano Zampini           ierr = MatAssemblyBegin(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
46741dd7afcfSStefano Zampini           ierr = MatAssemblyEnd(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
46751dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,eye);CHKERRQ(ierr);
46761dd7afcfSStefano Zampini           ierr = MatDestroy(&eye);CHKERRQ(ierr);
46771dd7afcfSStefano Zampini         }
46781dd7afcfSStefano Zampini         ierr = MatISGetMPIXAIJ(tmat,MAT_INITIAL_MATRIX,&benign_global);CHKERRQ(ierr);
46791dd7afcfSStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
46801dd7afcfSStefano Zampini       }
46811dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
46821dd7afcfSStefano Zampini         ierr = MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
46831dd7afcfSStefano Zampini         ierr = MatDestroy(&benign_global);CHKERRQ(ierr);
468427b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
46851dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
46861dd7afcfSStefano Zampini       }
46871dd7afcfSStefano Zampini     }
468816909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
468916909a7fSStefano Zampini       IS             is_global;
469016909a7fSStefano Zampini       const PetscInt *gidxs;
469116909a7fSStefano Zampini 
469216909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
469316909a7fSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global);CHKERRQ(ierr);
469416909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
469516909a7fSStefano Zampini       ierr = MatGetSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change);CHKERRQ(ierr);
469616909a7fSStefano Zampini       ierr = ISDestroy(&is_global);CHKERRQ(ierr);
469716909a7fSStefano Zampini     }
46981dd7afcfSStefano Zampini   }
46991dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
47001dd7afcfSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->work_change);CHKERRQ(ierr);
4701b9b85e73SStefano Zampini   }
4702a717540cSStefano Zampini 
470372b8c272SStefano Zampini   if (!pcbddc->fake_change) {
47044f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
47054f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
47064f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
47074f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
4708019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
4709019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
4710019a44ceSStefano Zampini       pcbddc->local_primal_size++;
4711019a44ceSStefano Zampini     }
4712019a44ceSStefano Zampini 
4713019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
4714727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
4715727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
47169f47a83aSStefano 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);
4717c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
47180e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
47199f47a83aSStefano 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);
4720727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
4721727cdba6SStefano Zampini       }
47220e6343abSStefano Zampini     }
4723727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
4724b2566f29SBarry Smith     ierr = MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
472572b8c272SStefano Zampini   }
472672b8c272SStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
4727727cdba6SStefano Zampini 
4728a717540cSStefano Zampini   /* flush dbg viewer */
4729b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
4730b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4731b8ffe317SStefano Zampini   }
4732a717540cSStefano Zampini 
4733e310c8b4SStefano Zampini   /* free workspace */
4734a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
47354641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
473608122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
47379162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
47389162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
473908122e43SStefano Zampini   } else {
47409162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
47419162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
47429162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
474308122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
474408122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
47459162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
47469162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
474708122e43SStefano Zampini   }
4748674ae819SStefano Zampini   PetscFunctionReturn(0);
4749674ae819SStefano Zampini }
4750674ae819SStefano Zampini 
4751674ae819SStefano Zampini #undef __FUNCT__
4752674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
4753674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
4754674ae819SStefano Zampini {
4755674ae819SStefano Zampini   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
4756674ae819SStefano Zampini   PC_IS       *pcis = (PC_IS*)pc->data;
4757674ae819SStefano Zampini   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
475814f95afaSStefano Zampini   PetscInt    ierr,i,N;
4759674ae819SStefano Zampini 
4760674ae819SStefano Zampini   PetscFunctionBegin;
47618e61c736SStefano Zampini   /* Reset previously computed graph */
47628e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
4763674ae819SStefano Zampini   /* Init local Graph struct */
47647fb0e2dbSStefano Zampini   ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
47653bbff08aSStefano Zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,pcis->mapping,N);CHKERRQ(ierr);
4766674ae819SStefano Zampini 
4767575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
4768*9a962809SStefano Zampini   if (pcbddc->mat_graph->nvtxs_csr && pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) 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);
47699577ea80SStefano Zampini 
4770674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
4771d4d8cf7bSStefano Zampini   if ( (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) && pcbddc->use_local_adj) {
47724d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
47734d379d7bSStefano Zampini     PetscInt  nvtxs;
4774e496cd5dSStefano Zampini     PetscBool flg_row=PETSC_FALSE;
4775674ae819SStefano Zampini 
47762fffb893SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
47772fffb893SStefano Zampini     if (flg_row) {
47784d379d7bSStefano Zampini       ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
4779b96c3477SStefano Zampini       pcbddc->computed_rowadj = PETSC_TRUE;
47802fffb893SStefano Zampini     }
47812fffb893SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
4782674ae819SStefano Zampini   }
47839b28b941SStefano Zampini   if (pcbddc->dbg_flag) {
47849b28b941SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4785674ae819SStefano Zampini   }
4786674ae819SStefano Zampini 
4787674ae819SStefano Zampini   /* Setup of Graph */
47884b2aedd3SStefano Zampini   pcbddc->mat_graph->commsizelimit = 0; /* don't use the COMM_SELF variant of the graph */
478914f95afaSStefano 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);
4790674ae819SStefano Zampini 
47914f1b2e48SStefano Zampini   /* attach info on disconnected subdomains if present */
47924f1b2e48SStefano Zampini   if (pcbddc->n_local_subs) {
47934f1b2e48SStefano Zampini     PetscInt *local_subs;
47944f1b2e48SStefano Zampini 
47954f1b2e48SStefano Zampini     ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
47964f1b2e48SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
47974f1b2e48SStefano Zampini       const PetscInt *idxs;
47984f1b2e48SStefano Zampini       PetscInt       nl,j;
47994f1b2e48SStefano Zampini 
48004f1b2e48SStefano Zampini       ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
48014f1b2e48SStefano Zampini       ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
48024f1b2e48SStefano Zampini       for (j=0;j<nl;j++) {
48034f1b2e48SStefano Zampini         local_subs[idxs[j]] = i;
48044f1b2e48SStefano Zampini       }
48054f1b2e48SStefano Zampini       ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
48064f1b2e48SStefano Zampini     }
48074f1b2e48SStefano Zampini     pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
48084f1b2e48SStefano Zampini     pcbddc->mat_graph->local_subs = local_subs;
48094f1b2e48SStefano Zampini   }
48104f1b2e48SStefano Zampini 
4811674ae819SStefano Zampini   /* Graph's connected components analysis */
4812674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
4813674ae819SStefano Zampini   PetscFunctionReturn(0);
4814674ae819SStefano Zampini }
4815674ae819SStefano Zampini 
48169a7d3425SStefano Zampini #undef __FUNCT__
48179a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
48189a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
48199a7d3425SStefano Zampini {
48209a7d3425SStefano Zampini   PetscInt       i,j;
48219a7d3425SStefano Zampini   PetscScalar    *alphas;
48229a7d3425SStefano Zampini   PetscErrorCode ierr;
48239a7d3425SStefano Zampini 
48249a7d3425SStefano Zampini   PetscFunctionBegin;
4825785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
48269a7d3425SStefano Zampini   for (i=0;i<n;i++) {
48279a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
4828669cc0f4SStefano Zampini     ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],alphas);CHKERRQ(ierr);
4829669cc0f4SStefano Zampini     for (j=0;j<n-i-1;j++) alphas[j] = PetscConj(-alphas[j]);
4830669cc0f4SStefano Zampini     ierr = VecMAXPY(vecs[j],n-i-1,alphas,vecs+i);CHKERRQ(ierr);
48319a7d3425SStefano Zampini   }
48329a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
48339a7d3425SStefano Zampini   PetscFunctionReturn(0);
48349a7d3425SStefano Zampini }
48359a7d3425SStefano Zampini 
4836e7931f94SStefano Zampini #undef __FUNCT__
483770cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
483857de7509SStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
4839e7931f94SStefano Zampini {
484057de7509SStefano Zampini   Mat            A;
4841e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
4842e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
484352e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
484452e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
484527b6a85dSStefano Zampini   PetscInt       im_active,active_procs,n,i,j,local_size,threshold = 2;
484657de7509SStefano Zampini   PetscInt       void_procs,*procs_candidates = NULL;
484727b6a85dSStefano Zampini   PetscInt       xadj_count, *count;
484827b6a85dSStefano Zampini   PetscBool      ismatis,use_vwgt=PETSC_FALSE;
484927b6a85dSStefano Zampini   PetscSubcomm   psubcomm;
485027b6a85dSStefano Zampini   MPI_Comm       subcomm;
485152e5ac9dSStefano Zampini   PetscErrorCode ierr;
4852a57a6d2fSStefano Zampini 
4853e7931f94SStefano Zampini   PetscFunctionBegin;
485457de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
485557de7509SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
485657de7509SStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
485757de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
485857de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
485957de7509SStefano Zampini   if (*n_subdomains <=0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %d\n",*n_subdomains);
486057de7509SStefano Zampini 
486157de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
486257de7509SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
486357de7509SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
486457de7509SStefano Zampini   ierr = MatISGetLocalMat(mat,&A);CHKERRQ(ierr);
486557de7509SStefano Zampini   ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
486657de7509SStefano Zampini   im_active = !!(n);
486757de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
486857de7509SStefano Zampini   void_procs = size - active_procs;
486957de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
487057de7509SStefano Zampini   if (void_procs) {
487157de7509SStefano Zampini     PetscInt ncand;
487257de7509SStefano Zampini 
487357de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
487457de7509SStefano Zampini     ierr = PetscMalloc1(size,&procs_candidates);CHKERRQ(ierr);
487557de7509SStefano Zampini     ierr = MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
487657de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
487757de7509SStefano Zampini       if (!procs_candidates[i]) {
487857de7509SStefano Zampini         procs_candidates[ncand++] = i;
487957de7509SStefano Zampini       }
488057de7509SStefano Zampini     }
488157de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
488257de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
488357de7509SStefano Zampini   }
488457de7509SStefano Zampini 
488557de7509SStefano Zampini   /* number of subdomains requested greater than active processes -> just shift the matrix */
488657de7509SStefano Zampini   if (active_procs < *n_subdomains) {
488757de7509SStefano Zampini     PetscInt issize,isidx;
488857de7509SStefano Zampini     if (im_active) {
488957de7509SStefano Zampini       issize = 1;
489057de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
489157de7509SStefano Zampini         isidx = procs_candidates[rank];
489257de7509SStefano Zampini       } else {
489357de7509SStefano Zampini         isidx = rank;
489457de7509SStefano Zampini       }
489557de7509SStefano Zampini     } else {
489657de7509SStefano Zampini       issize = 0;
489757de7509SStefano Zampini       isidx = -1;
489857de7509SStefano Zampini     }
489957de7509SStefano Zampini     *n_subdomains = active_procs;
490057de7509SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends);CHKERRQ(ierr);
4901daf8a457SStefano Zampini     ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
490257de7509SStefano Zampini     PetscFunctionReturn(0);
490357de7509SStefano Zampini   }
4904c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
4905c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
490627b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
4907e7931f94SStefano Zampini 
4908e7931f94SStefano Zampini   /* Get info on mapping */
49093bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&local_size);CHKERRQ(ierr);
49103bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
4911e7931f94SStefano Zampini 
4912e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
4913785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
4914e7931f94SStefano Zampini   xadj[0] = 0;
4915e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
4916785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
4917785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
491827b6a85dSStefano Zampini   ierr = PetscCalloc1(local_size,&count);CHKERRQ(ierr);
491927b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
492027b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
492127b6a85dSStefano Zampini       count[shared[i][j]] += 1;
4922e7931f94SStefano Zampini 
492327b6a85dSStefano Zampini   xadj_count = 0;
49242b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
492527b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
492627b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
4927d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
4928d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
4929d023bfaeSStefano Zampini         xadj_count++;
493027b6a85dSStefano Zampini         break;
493127b6a85dSStefano Zampini       }
4932e7931f94SStefano Zampini     }
4933e7931f94SStefano Zampini   }
4934d023bfaeSStefano Zampini   xadj[1] = xadj_count;
493527b6a85dSStefano Zampini   ierr = PetscFree(count);CHKERRQ(ierr);
49363bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
4937e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
4938e7931f94SStefano Zampini 
49393837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
4940e7931f94SStefano Zampini 
494127b6a85dSStefano Zampini   /* Restrict work on active processes only */
494227b6a85dSStefano Zampini   ierr = PetscMPIIntCast(im_active,&color);CHKERRQ(ierr);
494327b6a85dSStefano Zampini   if (void_procs) {
494427b6a85dSStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm);CHKERRQ(ierr);
494527b6a85dSStefano Zampini     ierr = PetscSubcommSetNumber(psubcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
494627b6a85dSStefano Zampini     ierr = PetscSubcommSetTypeGeneral(psubcomm,color,rank);CHKERRQ(ierr);
494727b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
494827b6a85dSStefano Zampini   } else {
494927b6a85dSStefano Zampini     psubcomm = NULL;
495027b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
495127b6a85dSStefano Zampini   }
495227b6a85dSStefano Zampini 
495327b6a85dSStefano Zampini   v_wgt = NULL;
495427b6a85dSStefano Zampini   if (!color) {
4955e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
4956e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
4957e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
4958c8587f34SStefano Zampini   } else {
495952e5ac9dSStefano Zampini     Mat             subdomain_adj;
496052e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
496152e5ac9dSStefano Zampini     MatPartitioning partitioner;
496227b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
496352e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
496457de7509SStefano Zampini     PetscMPIInt     size;
4965b0c7d250SStefano Zampini     PetscBool       aggregate;
4966b0c7d250SStefano Zampini 
496727b6a85dSStefano Zampini     ierr = MPI_Comm_size(subcomm,&size);CHKERRQ(ierr);
496827b6a85dSStefano Zampini     if (void_procs) {
496927b6a85dSStefano Zampini       PetscInt prank = rank;
4970785e854fSJed Brown       ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
497127b6a85dSStefano Zampini       ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm);CHKERRQ(ierr);
4972e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
4973e7931f94SStefano Zampini         ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
4974c8587f34SStefano Zampini       }
4975e7931f94SStefano Zampini       ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
497627b6a85dSStefano Zampini     } else {
497727b6a85dSStefano Zampini       oldranks = NULL;
497827b6a85dSStefano Zampini     }
4979b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
498027b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
4981b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
4982b0c7d250SStefano Zampini       PetscMPIInt nrank;
4983b0c7d250SStefano Zampini       PetscScalar *vals;
4984b0c7d250SStefano Zampini 
498527b6a85dSStefano Zampini       ierr = MPI_Comm_rank(subcomm,&nrank);CHKERRQ(ierr);
4986b0c7d250SStefano Zampini       lrows = 0;
4987b0c7d250SStefano Zampini       if (nrank<redprocs) {
4988b0c7d250SStefano Zampini         lrows = size/redprocs;
4989b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
4990b0c7d250SStefano Zampini       }
499127b6a85dSStefano Zampini       ierr = MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
4992b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
4993b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
4994b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
4995b0c7d250SStefano Zampini       row = nrank;
4996b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
4997b0c7d250SStefano Zampini       cols = adjncy;
4998b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
4999b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
5000b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
5001b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5002b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
500352e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
500452e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
500552e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
5006b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
500727b6a85dSStefano Zampini       if (use_vwgt) {
500827b6a85dSStefano Zampini         Vec               v;
500927b6a85dSStefano Zampini         const PetscScalar *array;
501027b6a85dSStefano Zampini         PetscInt          nl;
501127b6a85dSStefano Zampini 
501227b6a85dSStefano Zampini         ierr = MatCreateVecs(subdomain_adj,&v,NULL);CHKERRQ(ierr);
501327b6a85dSStefano Zampini         ierr = VecSetValue(v,row,(PetscScalar)local_size,INSERT_VALUES);CHKERRQ(ierr);
501427b6a85dSStefano Zampini         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
501527b6a85dSStefano Zampini         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
501627b6a85dSStefano Zampini         ierr = VecGetLocalSize(v,&nl);CHKERRQ(ierr);
501727b6a85dSStefano Zampini         ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
501827b6a85dSStefano Zampini         ierr = PetscMalloc1(nl,&v_wgt);CHKERRQ(ierr);
501922db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
502027b6a85dSStefano Zampini         ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
502127b6a85dSStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
502227b6a85dSStefano Zampini       }
5023b0c7d250SStefano Zampini     } else {
502427b6a85dSStefano Zampini       ierr = MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
502527b6a85dSStefano Zampini       if (use_vwgt) {
502627b6a85dSStefano Zampini         ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
502727b6a85dSStefano Zampini         v_wgt[0] = local_size;
502827b6a85dSStefano Zampini       }
5029b0c7d250SStefano Zampini     }
503022b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
5031e7931f94SStefano Zampini 
5032e7931f94SStefano Zampini     /* Partition */
503327b6a85dSStefano Zampini     ierr = MatPartitioningCreate(subcomm,&partitioner);CHKERRQ(ierr);
5034e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
503527b6a85dSStefano Zampini     if (v_wgt) {
5036e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
5037c8587f34SStefano Zampini     }
503857de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
503957de7509SStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,*n_subdomains);CHKERRQ(ierr);
5040e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
5041e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
504222b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
5043e7931f94SStefano Zampini 
504452e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
50456583bcc1SStefano Zampini     ierr = ISRenumber(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
504652e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
504752e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
504857de7509SStefano Zampini     if (!aggregate) {
504957de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
505027b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
505127b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
505227b6a85dSStefano Zampini #endif
505357de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
505427b6a85dSStefano Zampini       } else if (oldranks) {
5055b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
505627b6a85dSStefano Zampini       } else {
505727b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
505857de7509SStefano Zampini       }
505928143c3dSStefano Zampini     } else {
5060b0c7d250SStefano Zampini       PetscInt    idxs[1];
5061b0c7d250SStefano Zampini       PetscMPIInt tag;
5062b0c7d250SStefano Zampini       MPI_Request *reqs;
5063b0c7d250SStefano Zampini 
5064b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
5065b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
5066b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
506727b6a85dSStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]);CHKERRQ(ierr);
506828143c3dSStefano Zampini       }
506927b6a85dSStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE);CHKERRQ(ierr);
5070b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5071b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
507257de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
507327b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
507427b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
507527b6a85dSStefano Zampini #endif
507657de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[idxs[0]]];
507727b6a85dSStefano Zampini       } else if (oldranks) {
5078b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[idxs[0]];
507927b6a85dSStefano Zampini       } else {
508027b6a85dSStefano Zampini         ranks_send_to_idx[0] = idxs[0];
5081e7931f94SStefano Zampini       }
508257de7509SStefano Zampini     }
508352e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5084e7931f94SStefano Zampini     /* clean up */
5085e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
508652e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
5087e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
5088e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
5089e7931f94SStefano Zampini   }
509027b6a85dSStefano Zampini   ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr);
509157de7509SStefano Zampini   ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
5092e7931f94SStefano Zampini 
5093e7931f94SStefano Zampini   /* assemble parallel IS for sends */
5094e7931f94SStefano Zampini   i = 1;
509527b6a85dSStefano Zampini   if (!color) i=0;
509657de7509SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends);CHKERRQ(ierr);
5097e7931f94SStefano Zampini   PetscFunctionReturn(0);
5098e7931f94SStefano Zampini }
5099e7931f94SStefano Zampini 
5100e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
5101e7931f94SStefano Zampini 
5102e7931f94SStefano Zampini #undef __FUNCT__
5103e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
51041ae86dd6SStefano 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[])
5105e7931f94SStefano Zampini {
510670cf5478SStefano Zampini   Mat                    local_mat;
5107e7931f94SStefano Zampini   IS                     is_sends_internal;
51089d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
51091ae86dd6SStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals,buf_size_vecs;
51109d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
5111e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
5112e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
5113e7931f94SStefano Zampini   const PetscInt*        is_indices;
5114e7931f94SStefano Zampini   MatType                new_local_type;
5115e7931f94SStefano Zampini   /* buffers */
5116e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
511728143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
51189d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
5119e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
51201ae86dd6SStefano Zampini   PetscScalar            *ptr_vecs,*send_buffer_vecs,*recv_buffer_vecs;
5121e7931f94SStefano Zampini   /* MPI */
512228143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
512328143c3dSStefano Zampini   PetscSubcomm           subcomm;
5124e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
512528143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
512628143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
51271ae86dd6SStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,tag_vecs,source_dest;
51281ae86dd6SStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals,*send_req_vecs;
51291ae86dd6SStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals,*recv_req_vecs;
5130e7931f94SStefano Zampini   PetscErrorCode         ierr;
5131e7931f94SStefano Zampini 
5132e7931f94SStefano Zampini   PetscFunctionBegin;
513357de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5134e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
513528143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
513657de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
513757de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
513857de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
513957de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
514057de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
51411ae86dd6SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nvecs,10);
51421ae86dd6SStefano Zampini   if (nvecs) {
51431ae86dd6SStefano Zampini     if (nvecs > 1) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Just 1 vector supported");
51441ae86dd6SStefano Zampini     PetscValidHeaderSpecific(nnsp_vec[0],VEC_CLASSID,11);
51451ae86dd6SStefano Zampini   }
514657de7509SStefano Zampini   /* further checks */
5147e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
5148e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
5149e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
5150e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
5151e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
515257de7509SStefano Zampini   if (reuse && *mat_n) {
515370cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
515457de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
515570cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
515628143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
515770cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
515870cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
515970cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
516070cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
516170cf5478SStefano Zampini   }
5162e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
5163e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
516457de7509SStefano Zampini 
5165e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
5166e7931f94SStefano Zampini   if (!is_sends) {
516728143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
516857de7509SStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL);CHKERRQ(ierr);
5169c8587f34SStefano Zampini   } else {
5170e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
5171e7931f94SStefano Zampini     is_sends_internal = is_sends;
5172c8587f34SStefano Zampini   }
5173e7931f94SStefano Zampini 
5174e7931f94SStefano Zampini   /* get comm */
5175a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
5176e7931f94SStefano Zampini 
5177e7931f94SStefano Zampini   /* compute number of sends */
5178e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
5179e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
5180e7931f94SStefano Zampini 
5181e7931f94SStefano Zampini   /* compute number of receives */
5182e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
5183785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
5184e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
5185e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
5186e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
5187e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
5188e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
5189e7931f94SStefano Zampini 
519028143c3dSStefano Zampini   /* restrict comm if requested */
519128143c3dSStefano Zampini   subcomm = 0;
519228143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
519328143c3dSStefano Zampini   if (restrict_comm) {
5194779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
5195779c1cceSStefano Zampini 
519628143c3dSStefano Zampini     color = 0;
519753a05cb3SStefano Zampini     if (restrict_full) {
519853a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
519953a05cb3SStefano Zampini     } else {
520053a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
520153a05cb3SStefano Zampini     }
5202b2566f29SBarry Smith     ierr = MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
520328143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
520428143c3dSStefano Zampini     /* check if reuse has been requested */
520557de7509SStefano Zampini     if (reuse) {
520628143c3dSStefano Zampini       if (*mat_n) {
520728143c3dSStefano Zampini         PetscMPIInt subcommsize2;
520828143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
520928143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
521028143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
521128143c3dSStefano Zampini       } else {
521228143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
521328143c3dSStefano Zampini       }
521428143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
5215779c1cceSStefano Zampini       PetscMPIInt rank;
5216779c1cceSStefano Zampini 
5217779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
521828143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
521928143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
522028143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
5221306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
522228143c3dSStefano Zampini     }
522328143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
522428143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
522528143c3dSStefano Zampini   } else {
522628143c3dSStefano Zampini     comm_n = comm;
522728143c3dSStefano Zampini   }
522828143c3dSStefano Zampini 
5229e7931f94SStefano Zampini   /* prepare send/receive buffers */
5230785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
5231e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
5232785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
5233e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
523428143c3dSStefano Zampini   if (nis) {
5235854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
523628143c3dSStefano Zampini   }
5237e7931f94SStefano Zampini 
523828143c3dSStefano Zampini   /* Get data from local matrices */
52396c4ed002SBarry Smith   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
5240e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
5241e7931f94SStefano Zampini     /*
5242e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
5243e7931f94SStefano Zampini        send_buffer_idxs should contain:
5244e7931f94SStefano Zampini        - MatType_PRIVATE type
5245e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
5246e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
5247e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
5248e7931f94SStefano Zampini     */
52496c4ed002SBarry Smith   else {
5250e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
52513bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
5252854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
5253e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
5254e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
52553bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
5256e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
52573bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
5258e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
5259e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
5260e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
5261e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
5262c8587f34SStefano Zampini     }
5263c8587f34SStefano Zampini   }
5264e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
526528143c3dSStefano Zampini   /* additional is (if any) */
526628143c3dSStefano Zampini   if (nis) {
526728143c3dSStefano Zampini     PetscMPIInt psum;
526828143c3dSStefano Zampini     PetscInt j;
526928143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
527028143c3dSStefano Zampini       PetscInt plen;
527128143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
527228143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
527328143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
527428143c3dSStefano Zampini     }
5275854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
527628143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
527728143c3dSStefano Zampini       PetscInt plen;
527828143c3dSStefano Zampini       const PetscInt *is_array_idxs;
527928143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
528028143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
528128143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
528228143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
528328143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
528428143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
528528143c3dSStefano Zampini     }
528628143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
528728143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
528828143c3dSStefano Zampini     }
528928143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
529028143c3dSStefano Zampini   }
529128143c3dSStefano Zampini 
5292e7931f94SStefano Zampini   buf_size_idxs = 0;
5293e7931f94SStefano Zampini   buf_size_vals = 0;
529428143c3dSStefano Zampini   buf_size_idxs_is = 0;
52951ae86dd6SStefano Zampini   buf_size_vecs = 0;
5296e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
5297e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
5298e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
529928143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
53001ae86dd6SStefano Zampini     if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i];
5301e7931f94SStefano Zampini   }
5302785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
5303785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
530495ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
53051ae86dd6SStefano Zampini   ierr = PetscMalloc1(buf_size_vecs,&recv_buffer_vecs);CHKERRQ(ierr);
5306e7931f94SStefano Zampini 
5307e7931f94SStefano Zampini   /* get new tags for clean communications */
5308e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
5309e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
531028143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
53111ae86dd6SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vecs);CHKERRQ(ierr);
5312e7931f94SStefano Zampini 
5313e7931f94SStefano Zampini   /* allocate for requests */
5314785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
5315785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
531695ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
53171ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_vecs);CHKERRQ(ierr);
5318785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
5319785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
532095ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
53211ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_vecs);CHKERRQ(ierr);
5322e7931f94SStefano Zampini 
5323e7931f94SStefano Zampini   /* communications */
5324e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
5325e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
532628143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
53271ae86dd6SStefano Zampini   ptr_vecs = recv_buffer_vecs;
5328e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
5329e7931f94SStefano Zampini     source_dest = onodes[i];
5330e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
5331e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
5332e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5333e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
533428143c3dSStefano Zampini     if (nis) {
533557de7509SStefano Zampini       source_dest = onodes_is[i];
533628143c3dSStefano 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);
533728143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
533828143c3dSStefano Zampini     }
53391ae86dd6SStefano Zampini     if (nvecs) {
53401ae86dd6SStefano Zampini       source_dest = onodes[i];
53411ae86dd6SStefano Zampini       ierr = MPI_Irecv(ptr_vecs,olengths_idxs[i]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&recv_req_vecs[i]);CHKERRQ(ierr);
53421ae86dd6SStefano Zampini       ptr_vecs += olengths_idxs[i]-2;
53431ae86dd6SStefano Zampini     }
5344e7931f94SStefano Zampini   }
5345e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
5346e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
5347e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
5348e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
534928143c3dSStefano Zampini     if (nis) {
535028143c3dSStefano 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);
535128143c3dSStefano Zampini     }
53521ae86dd6SStefano Zampini     if (nvecs) {
53531ae86dd6SStefano Zampini       ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
53541ae86dd6SStefano 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);
53551ae86dd6SStefano Zampini     }
5356e7931f94SStefano Zampini   }
5357e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
5358e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
5359e7931f94SStefano Zampini 
5360e7931f94SStefano Zampini   /* assemble new l2g map */
5361e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5362e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
53639d30be91SStefano Zampini   new_local_rows = 0;
5364e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
53659d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
5366e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5367e7931f94SStefano Zampini   }
53689d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
5369e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
53709d30be91SStefano Zampini   new_local_rows = 0;
5371e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
53729d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
53739d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
5374e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5375e7931f94SStefano Zampini   }
53769d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
53779d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
5378e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
5379e7931f94SStefano Zampini 
5380e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
5381e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
5382e7931f94SStefano 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) */
5383e7931f94SStefano Zampini   if (n_recvs) {
538428143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
5385e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
5386e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
5387e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
5388e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
5389e7931f94SStefano Zampini         break;
5390e7931f94SStefano Zampini       }
5391e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
5392e7931f94SStefano Zampini     }
5393e7931f94SStefano Zampini     switch (new_local_type_private) {
539428143c3dSStefano Zampini       case MATDENSE_PRIVATE:
539528143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
5396e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
5397e7931f94SStefano Zampini           bs = 1;
539828143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
539928143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
540028143c3dSStefano Zampini           bs = 1;
540128143c3dSStefano Zampini         }
5402e7931f94SStefano Zampini         break;
5403e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
5404e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
5405e7931f94SStefano Zampini         bs = 1;
5406e7931f94SStefano Zampini         break;
5407e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
5408e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
5409e7931f94SStefano Zampini         break;
5410e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
5411e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
5412e7931f94SStefano Zampini         break;
5413e7931f94SStefano Zampini       default:
54149d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
5415e7931f94SStefano Zampini         break;
5416e7931f94SStefano Zampini     }
541728143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
541828143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
541928143c3dSStefano Zampini     bs = 1;
5420e7931f94SStefano Zampini   }
5421e7931f94SStefano Zampini 
542270cf5478SStefano Zampini   /* create MATIS object if needed */
542357de7509SStefano Zampini   if (!reuse) {
5424e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
5425e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
542670cf5478SStefano Zampini   } else {
542770cf5478SStefano Zampini     /* it also destroys the local matrices */
542857de7509SStefano Zampini     if (*mat_n) {
542970cf5478SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
543057de7509SStefano Zampini     } else { /* this is a fake object */
543157de7509SStefano Zampini       ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
543257de7509SStefano Zampini     }
543370cf5478SStefano Zampini   }
543470cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
5435e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
54369d30be91SStefano Zampini 
54379d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
54389d30be91SStefano Zampini 
54399d30be91SStefano Zampini   /* Global to local map of received indices */
54409d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
54419d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
54429d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
54439d30be91SStefano Zampini 
54449d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
54459d30be91SStefano Zampini   buf_size_idxs = 0;
54469d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
54479d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
54489d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
54499d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
54509d30be91SStefano Zampini   }
54519d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
54529d30be91SStefano Zampini 
54539d30be91SStefano Zampini   /* set preallocation */
54549d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
54559d30be91SStefano Zampini   if (!newisdense) {
54569d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
54579d30be91SStefano Zampini 
54589d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
54599d30be91SStefano Zampini     if (n_recvs) {
54609d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
54619d30be91SStefano Zampini     }
54629d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
54639d30be91SStefano Zampini       PetscInt j;
54649d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
54659d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
54669d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
54679d30be91SStefano Zampini         }
54689d30be91SStefano Zampini       } else {
54699d30be91SStefano Zampini         /* TODO */
54709d30be91SStefano Zampini       }
54719d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
54729d30be91SStefano Zampini     }
54739d30be91SStefano Zampini     if (new_local_nnz) {
54749d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
54759d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
54769d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
54779d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
54789d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
54799d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
54809d30be91SStefano Zampini     } else {
54819d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
54829d30be91SStefano Zampini     }
54839d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
54849d30be91SStefano Zampini   } else {
54859d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
54869d30be91SStefano Zampini   }
5487e7931f94SStefano Zampini 
5488e7931f94SStefano Zampini   /* set values */
5489e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
54909d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
5491e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
5492e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
5493e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
54949d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
5495e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
5496e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
5497e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
549828143c3dSStefano Zampini     } else {
549928143c3dSStefano Zampini       /* TODO */
5500e7931f94SStefano Zampini     }
5501e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5502e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
5503e7931f94SStefano Zampini   }
5504e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5505e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
550670cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
550770cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
55089d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
5509e7931f94SStefano Zampini 
5510dfd14d43SStefano Zampini #if 0
551128143c3dSStefano Zampini   if (!restrict_comm) { /* check */
5512e7931f94SStefano Zampini     Vec       lvec,rvec;
5513e7931f94SStefano Zampini     PetscReal infty_error;
5514e7931f94SStefano Zampini 
55152a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
5516e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
5517e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
5518e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
551970cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
5520e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
5521e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
5522e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
5523e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
5524e7931f94SStefano Zampini   }
552528143c3dSStefano Zampini #endif
5526e7931f94SStefano Zampini 
552728143c3dSStefano Zampini   /* assemble new additional is (if any) */
552828143c3dSStefano Zampini   if (nis) {
552928143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
553028143c3dSStefano Zampini 
553128143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5532854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
553328143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
553428143c3dSStefano Zampini     psum = 0;
553528143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
553628143c3dSStefano Zampini       for (j=0;j<nis;j++) {
553728143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
553828143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
553928143c3dSStefano Zampini         psum += plen;
554028143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
554128143c3dSStefano Zampini       }
554228143c3dSStefano Zampini     }
5543854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
5544854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
554528143c3dSStefano Zampini     for (i=1;i<nis;i++) {
554628143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
554728143c3dSStefano Zampini     }
554828143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
554928143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
555028143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
555128143c3dSStefano Zampini       for (j=0;j<nis;j++) {
555228143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
555328143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
555428143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
555528143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
555628143c3dSStefano Zampini       }
555728143c3dSStefano Zampini     }
555828143c3dSStefano Zampini     for (i=0;i<nis;i++) {
555928143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
556028143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
556128143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
556228143c3dSStefano Zampini     }
556328143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
556428143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
556528143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
556628143c3dSStefano Zampini   }
5567e7931f94SStefano Zampini   /* free workspace */
556828143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
5569e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5570e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
5571e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5572e7931f94SStefano Zampini   if (isdense) {
5573e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
5574e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
5575e7931f94SStefano Zampini   } else {
5576e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
5577e7931f94SStefano Zampini   }
557828143c3dSStefano Zampini   if (nis) {
557928143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
558028143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
558128143c3dSStefano Zampini   }
55821ae86dd6SStefano Zampini 
55831ae86dd6SStefano Zampini   if (nvecs) {
55841ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
55851ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
55861ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
55871ae86dd6SStefano Zampini     ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
55881ae86dd6SStefano Zampini     ierr = VecCreate(comm_n,&nnsp_vec[0]);CHKERRQ(ierr);
55891ae86dd6SStefano Zampini     ierr = VecSetSizes(nnsp_vec[0],new_local_rows,PETSC_DECIDE);CHKERRQ(ierr);
55901ae86dd6SStefano Zampini     ierr = VecSetType(nnsp_vec[0],VECSTANDARD);CHKERRQ(ierr);
55911ae86dd6SStefano Zampini     /* set values */
55921ae86dd6SStefano Zampini     ptr_vals = recv_buffer_vecs;
55931ae86dd6SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
55941ae86dd6SStefano Zampini     ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
55951ae86dd6SStefano Zampini     for (i=0;i<n_recvs;i++) {
55961ae86dd6SStefano Zampini       PetscInt j;
55971ae86dd6SStefano Zampini       for (j=0;j<*(ptr_idxs+1);j++) {
55981ae86dd6SStefano Zampini         send_buffer_vecs[*(ptr_idxs+2+j)] += *(ptr_vals + j);
55991ae86dd6SStefano Zampini       }
56001ae86dd6SStefano Zampini       ptr_idxs += olengths_idxs[i];
56011ae86dd6SStefano Zampini       ptr_vals += olengths_idxs[i]-2;
56021ae86dd6SStefano Zampini     }
56031ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
56041ae86dd6SStefano Zampini     ierr = VecAssemblyBegin(nnsp_vec[0]);CHKERRQ(ierr);
56051ae86dd6SStefano Zampini     ierr = VecAssemblyEnd(nnsp_vec[0]);CHKERRQ(ierr);
56061ae86dd6SStefano Zampini   }
56071ae86dd6SStefano Zampini 
56081ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_vecs);CHKERRQ(ierr);
56091ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
5610e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
5611e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
56121ae86dd6SStefano Zampini   ierr = PetscFree(recv_req_vecs);CHKERRQ(ierr);
561328143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
5614e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
5615e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
56161ae86dd6SStefano Zampini   ierr = PetscFree(send_req_vecs);CHKERRQ(ierr);
561728143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
5618e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
5619e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
5620e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
5621e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
5622e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
562328143c3dSStefano Zampini   if (nis) {
562428143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
562528143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
562628143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
562728143c3dSStefano Zampini   }
562828143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
562928143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
563028143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
563128143c3dSStefano Zampini     for (i=0;i<nis;i++) {
563228143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
563328143c3dSStefano Zampini     }
56341ae86dd6SStefano Zampini     if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */
56351ae86dd6SStefano Zampini       ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
56361ae86dd6SStefano Zampini     }
563753a05cb3SStefano Zampini     *mat_n = NULL;
563828143c3dSStefano Zampini   }
5639e7931f94SStefano Zampini   PetscFunctionReturn(0);
5640e7931f94SStefano Zampini }
5641a57a6d2fSStefano Zampini 
564212edc857SStefano Zampini /* temporary hack into ksp private data structure */
5643af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
564412edc857SStefano Zampini 
5645c8587f34SStefano Zampini #undef __FUNCT__
5646c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
5647c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
5648c8587f34SStefano Zampini {
5649c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
5650c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
565120a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
56521ae86dd6SStefano Zampini   Mat                    coarsedivudotp = NULL;
56539881197aSStefano Zampini   MatNullSpace           CoarseNullSpace = NULL;
565420a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
56556e683305SStefano Zampini   IS                     coarse_is,*isarray;
56566e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
565730368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
5658f9eb5b7dSStefano Zampini   PC                     pc_temp;
5659c8587f34SStefano Zampini   PCType                 coarse_pc_type;
5660c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
5661f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
56624f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
56636e683305SStefano Zampini   Mat                    t_coarse_mat_is;
566457de7509SStefano Zampini   PetscInt               ncoarse;
566568457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
566622bc73bbSStefano Zampini   PetscScalar            *array;
566757de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
566857de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
56699881197aSStefano Zampini   PetscErrorCode         ierr;
5670fdc09c96SStefano Zampini 
5671c8587f34SStefano Zampini   PetscFunctionBegin;
5672c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
567368457ee5SStefano 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 */
5674fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
56755a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
5676fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
5677f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
5678f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
5679f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
5680fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
568151bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
568251bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
5683dc4bcba2SStefano Zampini         PC        pc;
5684dc4bcba2SStefano Zampini         PetscBool isbddc;
5685dc4bcba2SStefano Zampini 
5686dc4bcba2SStefano Zampini         /* temporary workaround since PCBDDC does not have a reset method so far */
5687dc4bcba2SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
5688dc4bcba2SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
5689dc4bcba2SStefano Zampini         if (isbddc) {
569063c961adSStefano Zampini           ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
569163c961adSStefano Zampini         } else {
5692727cdba6SStefano Zampini           ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
569363c961adSStefano Zampini         }
5694fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
5695fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
5696fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
5697f4ddd8eeSStefano Zampini       }
5698fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
5699fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
5700f4ddd8eeSStefano Zampini     }
570170cf5478SStefano Zampini     /* reset any subassembling information */
570257de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
570370cf5478SStefano Zampini       ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
570457de7509SStefano Zampini     }
57056e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
5706fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
5707f4ddd8eeSStefano Zampini   }
570857de7509SStefano Zampini   /* assemble coarse matrix */
570957de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
571057de7509SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
571157de7509SStefano Zampini     ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
571257de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
571318a45a71SStefano Zampini   } else {
571457de7509SStefano Zampini     coarse_mat = NULL;
571557de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
57166e683305SStefano Zampini   }
5717e7931f94SStefano Zampini 
5718abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
5719abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
5720abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
5721abbbba34SStefano Zampini 
5722abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
572322bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
572422bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
572522bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
572622bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
5727e176bc59SStefano 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);
57286e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
57296e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
57306e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5731abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
5732abbbba34SStefano Zampini 
573357de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
573457de7509SStefano Zampini   im_active = !!(pcis->n);
573557de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
573657de7509SStefano Zampini 
573757de7509SStefano Zampini   /* determine number of process partecipating to coarse solver and compute subassembling pattern */
573857de7509SStefano Zampini   /* restr : whether if we want to exclude senders (which are not receivers) from the subassembling pattern */
573957de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
574057de7509SStefano Zampini   coarse_mat_is = NULL;
574157de7509SStefano Zampini   multilevel_allowed = PETSC_FALSE;
574257de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
574357de7509SStefano Zampini   full_restr = PETSC_TRUE;
57441ae86dd6SStefano Zampini   pcbddc->coarse_eqs_per_proc = PetscMin(PetscMax(pcbddc->coarse_size,1),pcbddc->coarse_eqs_per_proc);
574557de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
574657de7509SStefano Zampini   if (multilevel_requested) {
574757de7509SStefano Zampini     ncoarse = active_procs/pcbddc->coarsening_ratio;
574857de7509SStefano Zampini     restr = PETSC_FALSE;
574957de7509SStefano Zampini     full_restr = PETSC_FALSE;
575057de7509SStefano Zampini   } else {
575157de7509SStefano Zampini     ncoarse = pcbddc->coarse_size/pcbddc->coarse_eqs_per_proc;
575257de7509SStefano Zampini     restr = PETSC_TRUE;
575357de7509SStefano Zampini     full_restr = PETSC_TRUE;
575457de7509SStefano Zampini   }
57554b2aedd3SStefano Zampini   if (!pcbddc->coarse_size) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE;
575657de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
575757de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
5758a198735bSStefano Zampini     if (pcbddc->coarsening_ratio > 1) {
575957de7509SStefano Zampini       ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
5760a198735bSStefano Zampini     } else {
5761a198735bSStefano Zampini       PetscMPIInt size,rank;
5762a198735bSStefano Zampini       ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
5763a198735bSStefano Zampini       ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
5764a198735bSStefano Zampini       have_void = (active_procs == (PetscInt)size) ? PETSC_FALSE : PETSC_TRUE;
5765a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),1,rank,1,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
5766a198735bSStefano Zampini     }
576757de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
576857de7509SStefano Zampini     PetscInt    psum;
576957de7509SStefano Zampini     PetscMPIInt size;
577057de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
577157de7509SStefano Zampini     else psum = 0;
577257de7509SStefano Zampini     ierr = MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
577357de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
577457de7509SStefano Zampini     if (ncoarse < size) have_void = PETSC_TRUE;
577557de7509SStefano Zampini   }
577657de7509SStefano Zampini   /* determine if we can go multilevel */
577757de7509SStefano Zampini   if (multilevel_requested) {
577857de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
577957de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
578057de7509SStefano Zampini   }
578157de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
578257de7509SStefano Zampini 
5783e4d548c7SStefano Zampini   /* dump subassembling pattern */
5784e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
5785e4d548c7SStefano Zampini     ierr = ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer);CHKERRQ(ierr);
5786e4d548c7SStefano Zampini   }
5787e4d548c7SStefano Zampini 
57886e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
578927b6a85dSStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal)) { /* protects from unneded computations */
57906e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
57916e683305SStefano Zampini     const PetscInt         *idxs;
57926e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
57936e683305SStefano Zampini 
57946e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
57950be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
57966e683305SStefano Zampini     /* allocate space for temporary storage */
5797854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
5798854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
57996e683305SStefano Zampini     /* allocate for IS array */
58006e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
58016e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
580227b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
580330368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
5804854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
58056e683305SStefano Zampini     /* dofs splitting */
58066e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
58076e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
58086e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
58096e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
58106e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
58116e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
58126e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
581330368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
58146e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
58156e683305SStefano Zampini     }
58166e683305SStefano Zampini     /* neumann boundaries */
58176e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
58186e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
58196e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
58206e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
58216e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
58226e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
58236e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
582430368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
58256e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
58266e683305SStefano Zampini     }
58276e683305SStefano Zampini     /* free memory */
58286e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
58296e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
58306e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
58316e683305SStefano Zampini   } else {
58326e683305SStefano Zampini     nis = 0;
58336e683305SStefano Zampini     nisdofs = 0;
58346e683305SStefano Zampini     nisneu = 0;
583530368db7SStefano Zampini     nisvert = 0;
58366e683305SStefano Zampini     isarray = NULL;
58376e683305SStefano Zampini   }
58386e683305SStefano Zampini   /* destroy no longer needed map */
58396e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
58406e683305SStefano Zampini 
584157de7509SStefano Zampini   /* subassemble */
584257de7509SStefano Zampini   if (multilevel_allowed) {
58431ae86dd6SStefano Zampini     Vec       vp[1];
58441ae86dd6SStefano Zampini     PetscInt  nvecs = 0;
584557de7509SStefano Zampini     PetscBool reuse,reuser;
58461ae86dd6SStefano Zampini 
584757de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
584857de7509SStefano Zampini     else reuse = PETSC_FALSE;
584957de7509SStefano Zampini     ierr = MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
58501ae86dd6SStefano Zampini     vp[0] = NULL;
58511ae86dd6SStefano Zampini     if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */
58521ae86dd6SStefano Zampini       ierr = VecCreate(PetscObjectComm((PetscObject)pc),&vp[0]);CHKERRQ(ierr);
58531ae86dd6SStefano Zampini       ierr = VecSetSizes(vp[0],pcbddc->local_primal_size,PETSC_DECIDE);CHKERRQ(ierr);
58541ae86dd6SStefano Zampini       ierr = VecSetType(vp[0],VECSTANDARD);CHKERRQ(ierr);
58551ae86dd6SStefano Zampini       nvecs = 1;
58561ae86dd6SStefano Zampini 
58571ae86dd6SStefano Zampini       if (pcbddc->divudotp) {
5858a198735bSStefano Zampini         Mat      B,loc_divudotp;
58591ae86dd6SStefano Zampini         Vec      v,p;
58601ae86dd6SStefano Zampini         IS       dummy;
58611ae86dd6SStefano Zampini         PetscInt np;
58621ae86dd6SStefano Zampini 
5863a198735bSStefano Zampini         ierr = MatISGetLocalMat(pcbddc->divudotp,&loc_divudotp);CHKERRQ(ierr);
5864a198735bSStefano Zampini         ierr = MatGetSize(loc_divudotp,&np,NULL);CHKERRQ(ierr);
58651ae86dd6SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,np,0,1,&dummy);CHKERRQ(ierr);
5866a198735bSStefano Zampini         ierr = MatGetSubMatrix(loc_divudotp,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
58671ae86dd6SStefano Zampini         ierr = MatCreateVecs(B,&v,&p);CHKERRQ(ierr);
58681ae86dd6SStefano Zampini         ierr = VecSet(p,1.);CHKERRQ(ierr);
58691ae86dd6SStefano Zampini         ierr = MatMultTranspose(B,p,v);CHKERRQ(ierr);
58701ae86dd6SStefano Zampini         ierr = VecDestroy(&p);CHKERRQ(ierr);
58711ae86dd6SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
58721ae86dd6SStefano Zampini         ierr = VecGetArray(vp[0],&array);CHKERRQ(ierr);
58731ae86dd6SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_P,array);CHKERRQ(ierr);
58741ae86dd6SStefano Zampini         ierr = VecRestoreArray(vp[0],&array);CHKERRQ(ierr);
58751ae86dd6SStefano Zampini         ierr = MatMultTranspose(pcbddc->coarse_phi_B,v,pcbddc->vec1_P);CHKERRQ(ierr);
58761ae86dd6SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_P);CHKERRQ(ierr);
58771ae86dd6SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
58781ae86dd6SStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
587974e2c79eSStefano Zampini       }
58801ae86dd6SStefano Zampini     }
58811ae86dd6SStefano Zampini     if (reuser) {
58821ae86dd6SStefano Zampini       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray,nvecs,vp);CHKERRQ(ierr);
588374e2c79eSStefano Zampini     } else {
58841ae86dd6SStefano 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);
58851ae86dd6SStefano Zampini     }
58861ae86dd6SStefano Zampini     if (vp[0]) { /* vp[0] could have been placed on a different set of processes */
58871ae86dd6SStefano Zampini       PetscScalar *arraym,*arrayv;
58881ae86dd6SStefano Zampini       PetscInt    nl;
58891ae86dd6SStefano Zampini       ierr = VecGetLocalSize(vp[0],&nl);CHKERRQ(ierr);
58901ae86dd6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,1,nl,NULL,&coarsedivudotp);CHKERRQ(ierr);
58911ae86dd6SStefano Zampini       ierr = MatDenseGetArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
58921ae86dd6SStefano Zampini       ierr = VecGetArray(vp[0],&arrayv);CHKERRQ(ierr);
58931ae86dd6SStefano Zampini       ierr = PetscMemcpy(arraym,arrayv,nl*sizeof(PetscScalar));CHKERRQ(ierr);
58941ae86dd6SStefano Zampini       ierr = VecRestoreArray(vp[0],&arrayv);CHKERRQ(ierr);
58951ae86dd6SStefano Zampini       ierr = MatDenseRestoreArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
58961ae86dd6SStefano Zampini       ierr = VecDestroy(&vp[0]);CHKERRQ(ierr);
5897a198735bSStefano Zampini     } else {
5898a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&coarsedivudotp);CHKERRQ(ierr);
58991ae86dd6SStefano Zampini     }
59001ae86dd6SStefano Zampini   } else {
59011ae86dd6SStefano 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);
59026e683305SStefano Zampini   }
590357de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
590457de7509SStefano Zampini     PetscMPIInt size;
590557de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)coarse_mat_is),&size);
590657de7509SStefano Zampini     if (!multilevel_allowed) {
590757de7509SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
59086e683305SStefano Zampini     } else {
590957de7509SStefano Zampini       Mat A;
5910779c1cceSStefano Zampini 
591157de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
591257de7509SStefano Zampini       if (coarse_mat_is) {
591357de7509SStefano Zampini         if (coarse_mat) SETERRQ(PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
591457de7509SStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
591557de7509SStefano Zampini         coarse_mat = coarse_mat_is;
591657de7509SStefano Zampini       }
591757de7509SStefano Zampini       /* be sure we don't have MatSeqDENSE as local mat */
591857de7509SStefano Zampini       ierr = MatISGetLocalMat(coarse_mat,&A);CHKERRQ(ierr);
591957de7509SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr);
5920779c1cceSStefano Zampini     }
5921779c1cceSStefano Zampini   }
592257de7509SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
592357de7509SStefano Zampini   ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
59246e683305SStefano Zampini 
59256e683305SStefano Zampini   /* create local to global scatters for coarse problem */
592668457ee5SStefano Zampini   if (compute_vecs) {
59276e683305SStefano Zampini     PetscInt lrows;
59286e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
592957de7509SStefano Zampini     if (coarse_mat) {
593057de7509SStefano Zampini       ierr = MatGetLocalSize(coarse_mat,&lrows,NULL);CHKERRQ(ierr);
59316e683305SStefano Zampini     } else {
59326e683305SStefano Zampini       lrows = 0;
59336e683305SStefano Zampini     }
59346e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
59356e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
59366e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
59376e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
59386e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
59396e683305SStefano Zampini   }
59406e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
5941c8587f34SStefano Zampini 
5942f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
5943f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
5944f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
5945f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
5946f9eb5b7dSStefano Zampini   } else {
5947f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
5948f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
5949c8587f34SStefano Zampini   }
5950c8587f34SStefano Zampini 
59516e683305SStefano Zampini   /* print some info if requested */
59526e683305SStefano Zampini   if (pcbddc->dbg_flag) {
59536e683305SStefano Zampini     if (!multilevel_allowed) {
59546e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
59556e683305SStefano Zampini       if (multilevel_requested) {
59566e683305SStefano 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);
59576e683305SStefano Zampini       } else if (pcbddc->max_levels) {
59586e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
59596e683305SStefano Zampini       }
59606e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
59616e683305SStefano Zampini     }
59626e683305SStefano Zampini   }
59636e683305SStefano Zampini 
5964f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
596557de7509SStefano Zampini   if (coarse_mat) {
59666a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
59676e683305SStefano Zampini     if (pcbddc->dbg_flag) {
596857de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
59696e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
59706e683305SStefano Zampini     }
5971f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
5972312be037SStefano Zampini       char prefix[256],str_level[16];
5973e604994aSStefano Zampini       size_t len;
597457de7509SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp);CHKERRQ(ierr);
5975422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
5976c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
5977f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
597857de7509SStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
5979c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
59806e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
5981c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
5982c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
5983e604994aSStefano Zampini       /* prefix */
5984e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
5985e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
5986e604994aSStefano Zampini       if (!pcbddc->current_level) {
5987e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
5988e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
5989c8587f34SStefano Zampini       } else {
5990e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
5991312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
5992312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
599334d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
5994312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
5995e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
5996e604994aSStefano Zampini       }
5997e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
59983e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
59993e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
60003e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
60013e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
6002f9eb5b7dSStefano Zampini       /* allow user customization */
6003f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
60043e3c6dadSStefano Zampini     }
60053e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
600651bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
60073e3c6dadSStefano Zampini     if (nisdofs) {
60083e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
60093e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
60103e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
60113e3c6dadSStefano Zampini       }
60123e3c6dadSStefano Zampini     }
60133e3c6dadSStefano Zampini     if (nisneu) {
60143e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
60153e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
6016312be037SStefano Zampini     }
601730368db7SStefano Zampini     if (nisvert) {
601830368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
601930368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
602030368db7SStefano Zampini     }
6021f9eb5b7dSStefano Zampini 
6022f9eb5b7dSStefano Zampini     /* get some info after set from options */
6023f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
6024f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
60254f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
60266e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
6027f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
6028f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
6029f9eb5b7dSStefano Zampini     }
603039f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
60314f3a063dSStefano Zampini     if (isredundant) {
60324f3a063dSStefano Zampini       KSP inner_ksp;
60334f3a063dSStefano Zampini       PC  inner_pc;
60344f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
60354f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
60364f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
60374f3a063dSStefano Zampini     }
6038f9eb5b7dSStefano Zampini 
603957de7509SStefano Zampini     /* parameters which miss an API */
604057de7509SStefano Zampini     if (isbddc) {
6041720d30f9SStefano Zampini       PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data;
6042720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
604357de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
604427b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
604527b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
6046a198735bSStefano Zampini         Mat                    coarsedivudotp_is;
6047a198735bSStefano Zampini         ISLocalToGlobalMapping l2gmap,rl2g,cl2g;
6048a198735bSStefano Zampini         IS                     row,col;
6049a198735bSStefano Zampini         const PetscInt         *gidxs;
6050a198735bSStefano Zampini         PetscInt               n,st,M,N;
6051a198735bSStefano Zampini 
6052a198735bSStefano Zampini         ierr = MatGetSize(coarsedivudotp,&n,NULL);CHKERRQ(ierr);
6053a198735bSStefano Zampini         ierr = MPI_Scan(&n,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)coarse_mat));CHKERRQ(ierr);
6054a198735bSStefano Zampini         st = st-n;
6055a198735bSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)coarse_mat),1,st,1,&row);CHKERRQ(ierr);
6056a198735bSStefano Zampini         ierr = MatGetLocalToGlobalMapping(coarse_mat,&l2gmap,NULL);CHKERRQ(ierr);
6057a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(l2gmap,&n);CHKERRQ(ierr);
6058a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
6059a198735bSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
6060a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
6061a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
6062a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
6063a198735bSStefano Zampini         ierr = ISGetSize(row,&M);CHKERRQ(ierr);
6064a198735bSStefano Zampini         ierr = MatGetSize(coarse_mat,&N,NULL);CHKERRQ(ierr);
6065a198735bSStefano Zampini         ierr = ISDestroy(&row);CHKERRQ(ierr);
6066a198735bSStefano Zampini         ierr = ISDestroy(&col);CHKERRQ(ierr);
6067a198735bSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)coarse_mat),&coarsedivudotp_is);CHKERRQ(ierr);
6068a198735bSStefano Zampini         ierr = MatSetType(coarsedivudotp_is,MATIS);CHKERRQ(ierr);
6069a198735bSStefano Zampini         ierr = MatSetSizes(coarsedivudotp_is,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
6070a198735bSStefano Zampini         ierr = MatSetLocalToGlobalMapping(coarsedivudotp_is,rl2g,cl2g);CHKERRQ(ierr);
6071a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
6072a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
6073a198735bSStefano Zampini         ierr = MatISSetLocalMat(coarsedivudotp_is,coarsedivudotp);CHKERRQ(ierr);
6074a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
6075a198735bSStefano Zampini         ierr = PCBDDCSetDivergenceMat(pc_temp,coarsedivudotp_is,NULL);CHKERRQ(ierr);
6076a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp_is);CHKERRQ(ierr);
6077720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
607859e48ca4SStefano Zampini         if (pcbddc->adaptive_threshold < 1.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
6079720d30f9SStefano Zampini       }
6080d4d8cf7bSStefano Zampini     }
60819881197aSStefano Zampini 
60823301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
60835a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
60843301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
60853301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
60863301b35fSStefano Zampini     }
60873301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
60883301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
60893301b35fSStefano Zampini     }
60903301b35fSStefano Zampini     if (pc->pmat->spd_set) {
60913301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
60923301b35fSStefano Zampini     }
609327b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
609427b6a85dSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
609527b6a85dSStefano Zampini     }
60966e683305SStefano Zampini     /* set operators */
60975f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
60986e683305SStefano Zampini     if (pcbddc->dbg_flag) {
60996e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
61006e683305SStefano Zampini     }
61016e683305SStefano Zampini   }
61026e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
6103b1ecc7b1SStefano Zampini #if 0
6104b9b85e73SStefano Zampini   {
6105b9b85e73SStefano Zampini     PetscViewer viewer;
6106b9b85e73SStefano Zampini     char filename[256];
6107b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
6108b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
61096a9046bcSBarry Smith     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
6110b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
6111f159cad9SBarry Smith     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
6112b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
6113b9b85e73SStefano Zampini   }
6114b9b85e73SStefano Zampini #endif
6115f9eb5b7dSStefano Zampini 
611698a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
611798a51de6SStefano Zampini     Vec crhs,csol;
611804708bb6SStefano Zampini 
6119f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
6120f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
6121f347579bSStefano Zampini     if (!csol) {
61222a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
6123f9eb5b7dSStefano Zampini     }
6124f347579bSStefano Zampini     if (!crhs) {
61252a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
6126f347579bSStefano Zampini     }
6127b0f5fe93SStefano Zampini   }
61281ae86dd6SStefano Zampini   ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
6129b0f5fe93SStefano Zampini 
6130b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
6131b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
6132b0f5fe93SStefano Zampini 
6133b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
61344f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
61354f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
61364f1b2e48SStefano Zampini     }
6137b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
6138b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
6139b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6140b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6141b0f5fe93SStefano Zampini     if (coarse_mat) {
6142b0f5fe93SStefano Zampini       Vec         nullv;
6143b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
6144b0f5fe93SStefano Zampini       PetscInt    nl;
6145b0f5fe93SStefano Zampini 
6146b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
6147b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
6148b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
6149b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
6150b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
6151b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
6152b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
6153b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
6154b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
6155b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
6156b0f5fe93SStefano Zampini     }
6157b0f5fe93SStefano Zampini   }
6158b0f5fe93SStefano Zampini 
6159b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
6160b0f5fe93SStefano Zampini     PetscBool ispreonly;
6161b0f5fe93SStefano Zampini 
6162b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
6163b0f5fe93SStefano Zampini       PetscBool isnull;
6164b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
6165bef83e63SStefano Zampini       if (isnull) {
6166b0f5fe93SStefano Zampini         ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
6167b0f5fe93SStefano Zampini       }
6168bef83e63SStefano Zampini       /* TODO: add local nullspaces (if any) */
6169b0f5fe93SStefano Zampini     }
6170b0f5fe93SStefano Zampini     /* setup coarse ksp */
6171b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
6172cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
6173cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
61746e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
6175c8587f34SStefano Zampini       KSP       check_ksp;
61762b510759SStefano Zampini       KSPType   check_ksp_type;
6177c8587f34SStefano Zampini       PC        check_pc;
61786e683305SStefano Zampini       Vec       check_vec,coarse_vec;
61796a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
61802b510759SStefano Zampini       PetscInt  its;
61816e683305SStefano Zampini       PetscBool compute_eigs;
61826e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
61836e683305SStefano Zampini       PetscInt  neigs;
61848e185a42SStefano Zampini       const char *prefix;
6185c8587f34SStefano Zampini 
61862b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
61876e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
6188422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
618923ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
6190f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
6191e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
6192e4d548c7SStefano Zampini       ierr = KSPGetPC(check_ksp,&check_pc);CHKERRQ(ierr);
6193e4d548c7SStefano Zampini       ierr = PCSetType(check_pc,PCNONE);CHKERRQ(ierr);
61942b510759SStefano Zampini       if (ispreonly) {
61952b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
61966e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
61972b510759SStefano Zampini       } else {
6198cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
61996e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
6200c8587f34SStefano Zampini       }
6201c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
62026e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
62036e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
62046e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
6205a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
6206a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
6207a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
6208a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
6209c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
6210c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
6211c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
6212c8587f34SStefano Zampini       /* create random vec */
62132701bc32SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&coarse_vec,&check_vec);CHKERRQ(ierr);
6214c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
62156e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
6216c8587f34SStefano Zampini       /* solve coarse problem */
62176e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
6218cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
62196e683305SStefano Zampini       if (compute_eigs) {
6220854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
6221854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
62226e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
62231ae86dd6SStefano Zampini         if (neigs) {
62246e683305SStefano Zampini           lambda_max = eigs_r[neigs-1];
62256e683305SStefano Zampini           lambda_min = eigs_r[0];
62266e683305SStefano Zampini           if (pcbddc->use_coarse_estimates) {
62272701bc32SStefano Zampini             if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
62282701bc32SStefano Zampini               ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min);CHKERRQ(ierr);
6229cbcc2c2aSStefano Zampini               ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
6230cbcc2c2aSStefano Zampini             }
6231c8587f34SStefano Zampini           }
6232c8587f34SStefano Zampini         }
62331ae86dd6SStefano Zampini       }
6234cbcc2c2aSStefano Zampini 
6235c8587f34SStefano Zampini       /* check coarse problem residual error */
62366e683305SStefano Zampini       if (pcbddc->dbg_flag) {
62376e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
62386e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
62396e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
6240c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
62416e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
62426e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
6243779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
62446e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
62456e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
62466e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
62476e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
6248b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
6249b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
6250b0f5fe93SStefano Zampini         }
62516e683305SStefano Zampini         if (compute_eigs) {
62526e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
6253deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
6254c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
62556e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
62566e683305SStefano 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);
62576e683305SStefano Zampini           for (i=0;i<neigs;i++) {
62586e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
6259c8587f34SStefano Zampini           }
62606e683305SStefano Zampini         }
62616e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
62626e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
62636e683305SStefano Zampini       }
6264e4d548c7SStefano Zampini       ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
62652701bc32SStefano Zampini       ierr = VecDestroy(&coarse_vec);CHKERRQ(ierr);
6266c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
62676e683305SStefano Zampini       if (compute_eigs) {
62686e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
62696e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
6270c8587f34SStefano Zampini       }
62716e683305SStefano Zampini     }
62726e683305SStefano Zampini   }
6273bef83e63SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
6274cbcc2c2aSStefano Zampini   /* print additional info */
6275cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
62766e683305SStefano Zampini     /* waits until all processes reaches this point */
62776e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
6278cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
6279cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6280cbcc2c2aSStefano Zampini   }
6281cbcc2c2aSStefano Zampini 
62822b510759SStefano Zampini   /* free memory */
6283fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
6284c8587f34SStefano Zampini   PetscFunctionReturn(0);
6285c8587f34SStefano Zampini }
6286674ae819SStefano Zampini 
6287f34684f1SStefano Zampini #undef __FUNCT__
6288f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
6289f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
6290f34684f1SStefano Zampini {
6291f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
6292f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
6293f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
6294dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
6295dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
629673be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
6297dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
6298f34684f1SStefano Zampini   PetscErrorCode ierr;
6299f34684f1SStefano Zampini 
6300f34684f1SStefano Zampini   PetscFunctionBegin;
6301f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
63026c4ed002SBarry Smith   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
6303dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
63043bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
6305dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
6306dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
63076583bcc1SStefano Zampini   ierr = ISRenumber(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
6308dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
6309dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
6310dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
63116c4ed002SBarry 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);
6312dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
6313dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
6314dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
6315dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
6316dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
6317f34684f1SStefano Zampini 
6318f34684f1SStefano Zampini   /* check numbering */
6319f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
6320019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
6321dc456d91SStefano Zampini     PetscInt    i;
6322b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
6323f34684f1SStefano Zampini 
6324f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6325f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
6326f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
63271575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6328019a44ceSStefano Zampini     /* counter */
6329019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6330019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
6331019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6332019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6333019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6334019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6335f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
6336f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
6337727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
6338f34684f1SStefano Zampini     }
6339f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6340f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6341f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6342e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6343e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6344e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6345e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6346f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6347019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
6348f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
6349019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
63502c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
635175c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
6352b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
63532c66d082SStefano Zampini         ierr = ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi);CHKERRQ(ierr);
63542c66d082SStefano 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);
6355f34684f1SStefano Zampini       }
6356f34684f1SStefano Zampini     }
6357019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
6358b2566f29SBarry Smith     ierr = MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
6359f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6360f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
6361f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
6362f34684f1SStefano Zampini     }
6363f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6364f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6365e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6366e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6367f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
6368f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
6369b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
6370ca8b9ea9SStefano Zampini       PetscInt *gidxs;
6371ca8b9ea9SStefano Zampini 
6372ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
63733bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
6374f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
6375f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6376f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
6377f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
63784bc2dc4bSStefano 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);
6379f34684f1SStefano Zampini       }
6380f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6381ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
6382f34684f1SStefano Zampini     }
6383f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
63841575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6385302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
6386f34684f1SStefano Zampini   }
63878bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
6388f34684f1SStefano Zampini   /* get back data */
6389f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
6390f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
6391674ae819SStefano Zampini   PetscFunctionReturn(0);
6392674ae819SStefano Zampini }
6393674ae819SStefano Zampini 
6394e456f2a8SStefano Zampini #undef __FUNCT__
6395e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
6396a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
6397e456f2a8SStefano Zampini {
6398e456f2a8SStefano Zampini   IS             localis_t;
6399a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
6400e456f2a8SStefano Zampini   PetscScalar    *vals;
6401e456f2a8SStefano Zampini   PetscErrorCode ierr;
6402e456f2a8SStefano Zampini 
6403e456f2a8SStefano Zampini   PetscFunctionBegin;
6404a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
6405e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
6406854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
6407e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
6408e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
6409a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
6410a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
64111035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
6412a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
64131035eff8SStefano Zampini   }
6414a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
6415e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
6416e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
6417a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
6418a7dc3881SStefano Zampini   /* now compute set in local ordering */
6419a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6420a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6421a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
6422a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
6423a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
6424ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
6425e456f2a8SStefano Zampini       lsize++;
6426e456f2a8SStefano Zampini     }
6427e456f2a8SStefano Zampini   }
6428854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
6429a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
6430ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
6431e456f2a8SStefano Zampini       idxs[lsize++] = i;
6432e456f2a8SStefano Zampini     }
6433e456f2a8SStefano Zampini   }
6434a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
6435a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
6436e456f2a8SStefano Zampini   *localis = localis_t;
6437e456f2a8SStefano Zampini   PetscFunctionReturn(0);
6438e456f2a8SStefano Zampini }
6439906d46d4SStefano Zampini 
6440b96c3477SStefano Zampini #undef __FUNCT__
6441b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
644208122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
6443b96c3477SStefano Zampini {
6444a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6445b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6446b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
6447a64f4aa4SStefano Zampini   Mat                 S_j;
6448b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
6449b96c3477SStefano Zampini   PetscBool           free_used_adj;
6450b96c3477SStefano Zampini   PetscErrorCode      ierr;
6451b96c3477SStefano Zampini 
6452b96c3477SStefano Zampini   PetscFunctionBegin;
6453b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
6454b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
645508122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
6456b96c3477SStefano Zampini     used_xadj = NULL;
6457b96c3477SStefano Zampini     used_adjncy = NULL;
6458b96c3477SStefano Zampini   } else {
645908122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
646008122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
646108122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
646208122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
6463b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
6464b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
6465b96c3477SStefano Zampini     } else {
64662fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
6467b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
6468b96c3477SStefano Zampini       PetscInt       nvtxs;
6469b96c3477SStefano Zampini 
64702fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
64712fffb893SStefano Zampini       if (flg_row) {
6472b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
6473b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
6474b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
6475b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
64762fffb893SStefano Zampini       } else {
64772fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
64782fffb893SStefano Zampini         used_xadj = NULL;
64792fffb893SStefano Zampini         used_adjncy = NULL;
64802fffb893SStefano Zampini       }
64812fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
6482b96c3477SStefano Zampini     }
6483b96c3477SStefano Zampini   }
6484d5574798SStefano Zampini 
6485d5574798SStefano Zampini   /* setup sub_schurs data */
6486a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
6487df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
6488df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
6489a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
649091af6908SStefano 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);
6491a64f4aa4SStefano Zampini   } else {
64926816873aSStefano Zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
6493b7ab4a40SStefano Zampini     PetscBool isseqaij,need_change = PETSC_FALSE;;
6494a3df083aSStefano Zampini     PetscInt  benign_n;
649572b8c272SStefano Zampini     Mat       change = NULL;
64969d54b7f4SStefano Zampini     Vec       scaling = NULL;
649772b8c272SStefano Zampini     IS        change_primal = NULL;
6498a3df083aSStefano Zampini 
64995feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
65005feab87aSStefano Zampini       PetscInt n_vertices;
65015feab87aSStefano Zampini 
65025feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
65032034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
65045feab87aSStefano Zampini     }
650504708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
650604708bb6SStefano Zampini     if (!isseqaij) {
650704708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
650804708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
650904708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
651004708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
651104708bb6SStefano Zampini       } else {
6512511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
651304708bb6SStefano Zampini       }
651404708bb6SStefano Zampini     }
6515a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
6516a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
6517ca92afb2SStefano Zampini     } else {
6518a3df083aSStefano Zampini       benign_n = 0;
6519ca92afb2SStefano Zampini     }
6520b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
6521b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
6522b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
652372b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
652422db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
6525b7ab4a40SStefano Zampini       ierr = MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
652622db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
6527b7ab4a40SStefano Zampini     }
6528b7ab4a40SStefano Zampini     /* If the user defines additional constraints, we import them here.
6529b7ab4a40SStefano 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 */
6530b7ab4a40SStefano Zampini     if (need_change) {
653188c03ad3SStefano Zampini       PC_IS   *pcisf;
653288c03ad3SStefano Zampini       PC_BDDC *pcbddcf;
653388c03ad3SStefano Zampini       PC      pcf;
653488c03ad3SStefano Zampini 
6535e4d548c7SStefano Zampini       if (pcbddc->sub_schurs_rebuild) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
653688c03ad3SStefano Zampini       ierr = PCCreate(PetscObjectComm((PetscObject)pc),&pcf);CHKERRQ(ierr);
653788c03ad3SStefano Zampini       ierr = PCSetOperators(pcf,pc->mat,pc->pmat);CHKERRQ(ierr);
653888c03ad3SStefano Zampini       ierr = PCSetType(pcf,PCBDDC);CHKERRQ(ierr);
653988c03ad3SStefano Zampini       /* hacks */
654088c03ad3SStefano Zampini       pcisf = (PC_IS*)pcf->data;
654172b8c272SStefano Zampini       pcisf->is_B_local = pcis->is_B_local;
654272b8c272SStefano Zampini       pcisf->vec1_N = pcis->vec1_N;
654372b8c272SStefano Zampini       pcisf->BtoNmap = pcis->BtoNmap;
654472b8c272SStefano Zampini       pcisf->n = pcis->n;
654572b8c272SStefano Zampini       pcisf->n_B = pcis->n_B;
654688c03ad3SStefano Zampini       pcbddcf = (PC_BDDC*)pcf->data;
654788c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->mat_graph);CHKERRQ(ierr);
654888c03ad3SStefano Zampini       pcbddcf->mat_graph = pcbddc->mat_graph;
654988c03ad3SStefano Zampini       pcbddcf->use_faces = PETSC_TRUE;
655088c03ad3SStefano Zampini       pcbddcf->use_change_of_basis = PETSC_TRUE;
655188c03ad3SStefano Zampini       pcbddcf->use_change_on_faces = PETSC_TRUE;
655272b8c272SStefano Zampini       pcbddcf->use_qr_single = PETSC_TRUE;
655388c03ad3SStefano Zampini       pcbddcf->fake_change = PETSC_TRUE;
655488c03ad3SStefano Zampini       ierr = PCBDDCConstraintsSetUp(pcf);CHKERRQ(ierr);
655572b8c272SStefano Zampini       /* store information on primal vertices and change of basis (in local numbering) */
655672b8c272SStefano Zampini       sub_schurs->change_with_qr = pcbddcf->use_qr_single;
655772b8c272SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal);CHKERRQ(ierr);
655872b8c272SStefano Zampini       change = pcbddcf->ConstraintMatrix;
655972b8c272SStefano Zampini       pcbddcf->ConstraintMatrix = NULL;
656088c03ad3SStefano Zampini       /* free unneeded memory allocated in PCBDDCConstraintsSetUp */
656172b8c272SStefano Zampini       ierr = PetscFree(pcbddcf->sub_schurs);CHKERRQ(ierr);
656288c03ad3SStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddcf->onearnullspace);CHKERRQ(ierr);
656388c03ad3SStefano Zampini       ierr = PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult);CHKERRQ(ierr);
656488c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->primal_indices_local_idxs);CHKERRQ(ierr);
656588c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->onearnullvecs_state);CHKERRQ(ierr);
656688c03ad3SStefano Zampini       ierr = PetscFree(pcf->data);CHKERRQ(ierr);
656788c03ad3SStefano Zampini       pcf->ops->destroy = NULL;
656888c03ad3SStefano Zampini       ierr = PCDestroy(&pcf);CHKERRQ(ierr);
656988c03ad3SStefano Zampini     }
65709d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
657191af6908SStefano 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);
657272b8c272SStefano Zampini     ierr = MatDestroy(&change);CHKERRQ(ierr);
657372b8c272SStefano Zampini     ierr = ISDestroy(&change_primal);CHKERRQ(ierr);
6574ca92afb2SStefano Zampini   }
6575d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
6576b96c3477SStefano Zampini 
6577b96c3477SStefano Zampini   /* free adjacency */
6578b96c3477SStefano Zampini   if (free_used_adj) {
6579b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
6580b96c3477SStefano Zampini   }
6581b96c3477SStefano Zampini   PetscFunctionReturn(0);
6582b96c3477SStefano Zampini }
6583b96c3477SStefano Zampini 
6584b96c3477SStefano Zampini #undef __FUNCT__
6585b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
658608122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
6587b96c3477SStefano Zampini {
6588b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6589b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6590b96c3477SStefano Zampini   PCBDDCGraph         graph;
6591b96c3477SStefano Zampini   PetscErrorCode      ierr;
6592b96c3477SStefano Zampini 
6593b96c3477SStefano Zampini   PetscFunctionBegin;
6594b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
659508122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
65963301b35fSStefano Zampini     IS       verticesIS,verticescomm;
65973301b35fSStefano Zampini     PetscInt vsize,*idxs;
6598b96c3477SStefano Zampini 
6599b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
66003301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
66013301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
66023301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
66033301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
66043301b35fSStefano Zampini     ierr = ISDestroy(&verticesIS);CHKERRQ(ierr);
6605b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
66067fb0e2dbSStefano Zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global);CHKERRQ(ierr);
6607441e0de0SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
66083301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
6609b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
6610b96c3477SStefano Zampini   } else {
6611b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
6612b96c3477SStefano Zampini   }
6613e4d548c7SStefano Zampini   /* print some info */
6614e4d548c7SStefano Zampini   if (pcbddc->dbg_flag) {
6615e4d548c7SStefano Zampini     IS       vertices;
6616e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
6617e4d548c7SStefano Zampini     ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
6618e4d548c7SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
6619e4d548c7SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
6620e4d548c7SStefano Zampini     ierr = ISDestroy(&vertices);CHKERRQ(ierr);
6621e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6622e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
6623e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
6624e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
6625e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
6626e4d548c7SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6627e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6628e4d548c7SStefano Zampini   }
6629b96c3477SStefano Zampini 
6630b96c3477SStefano Zampini   /* sub_schurs init */
6631b334f244SStefano Zampini   if (!pcbddc->sub_schurs) {
6632b334f244SStefano Zampini     ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
6633b334f244SStefano Zampini   }
6634b334f244SStefano Zampini   ierr = PCBDDCSubSchursInit(pcbddc->sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap);CHKERRQ(ierr);
6635a64f4aa4SStefano Zampini 
6636b96c3477SStefano Zampini   /* free graph struct */
663708122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
6638b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
6639b96c3477SStefano Zampini   }
6640b96c3477SStefano Zampini   PetscFunctionReturn(0);
6641b96c3477SStefano Zampini }
6642fa34dd3eSStefano Zampini 
6643fa34dd3eSStefano Zampini #undef __FUNCT__
6644fa34dd3eSStefano Zampini #define __FUNCT__ "PCBDDCCheckOperator"
6645fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
6646fa34dd3eSStefano Zampini {
6647fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6648fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6649fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
6650fa34dd3eSStefano Zampini 
6651fa34dd3eSStefano Zampini   PetscFunctionBegin;
6652fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
6653fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
66544f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
6655fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
66564f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
665775c01103SStefano Zampini     PetscReal      norm;
6658fa34dd3eSStefano Zampini     PetscInt       i;
6659fa34dd3eSStefano Zampini 
6660fa34dd3eSStefano Zampini     /* B0 and B0_B */
6661fa34dd3eSStefano Zampini     if (zerodiag) {
6662fa34dd3eSStefano Zampini       IS       dummy;
6663fa34dd3eSStefano Zampini 
66644f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
66654f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
6666fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
6667fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
6668fa34dd3eSStefano Zampini     }
6669fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
6670fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
6671fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
6672fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6673fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6674fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6675fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6676fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
6677fa34dd3eSStefano Zampini     /* S_j */
6678fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
6679fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
6680fa34dd3eSStefano Zampini 
6681fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
6682fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
6683fa34dd3eSStefano Zampini     /* continuous in primal space */
6684fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
6685fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6686fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6687fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
66884f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
66894f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
6690fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
6691fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6692fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6693fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6694fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6695fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6696fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
6697fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
6698fa34dd3eSStefano Zampini 
6699fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
6700fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
6701fa34dd3eSStefano Zampini     /* local with Schur */
6702fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
6703fa34dd3eSStefano Zampini     if (zerodiag) {
6704fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
67054f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
6706fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
6707fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
6708fa34dd3eSStefano Zampini     }
6709fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
6710fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6711fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6712fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6713fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
6714fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
6715fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
6716fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6717fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
6718fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6719fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6720fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6721fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6722fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6723fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
6724fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
6725fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
6726fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6727fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6728fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6729fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6730fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6731fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
6732fa34dd3eSStefano Zampini     if (zerodiag) {
6733fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
6734fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
67354f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
6736fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
6737fa34dd3eSStefano Zampini     }
6738fa34dd3eSStefano Zampini     /* BDDC */
6739fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
6740fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
6741fa34dd3eSStefano Zampini 
6742fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
6743fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
6744fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
6745fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
67464f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
67474f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
6748fa34dd3eSStefano Zampini     }
67494f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
6750fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
6751fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
6752fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
6753fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
6754fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
6755fa34dd3eSStefano Zampini   }
6756fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
6757fa34dd3eSStefano Zampini }
6758