xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision fa23a32e8f1307161ceb0518631acc97039997e3)
11cf9b237SStefano Zampini #include <../src/mat/impls/aij/seq/aij.h>
2ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddc.h>
3ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddcprivate.h>
4674ae819SStefano Zampini #include <petscblaslapack.h>
5daf8a457SStefano Zampini #include <petsc/private/sfimpl.h>
6674ae819SStefano Zampini 
7669cc0f4SStefano Zampini 
8669cc0f4SStefano Zampini #undef __FUNCT__
9669cc0f4SStefano Zampini #define __FUNCT__ "PCBDDCComputeNoNetFlux"
10*fa23a32eSStefano Zampini PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp)
11669cc0f4SStefano Zampini {
12a198735bSStefano Zampini   Mat                    loc_divudotp;
13*fa23a32eSStefano Zampini   Vec                    p,v,vins,quad_vec,*quad_vecs;
14669cc0f4SStefano Zampini   ISLocalToGlobalMapping rmap;
15669cc0f4SStefano Zampini   IS                     *faces,*edges;
16669cc0f4SStefano Zampini   PetscScalar            *vals;
17669cc0f4SStefano Zampini   const PetscScalar      *array;
18669cc0f4SStefano Zampini   PetscInt               i,maxneighs,lmaxneighs,maxsize,nf,ne;
191ae86dd6SStefano Zampini   PetscMPIInt            rank;
20a198735bSStefano Zampini   PetscErrorCode         ierr;
21669cc0f4SStefano Zampini 
22669cc0f4SStefano Zampini   PetscFunctionBegin;
23669cc0f4SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(graph,&nf,&faces,&ne,&edges,NULL);CHKERRQ(ierr);
24669cc0f4SStefano Zampini   if (graph->twodim) {
25669cc0f4SStefano Zampini     lmaxneighs = 2;
26669cc0f4SStefano Zampini   } else {
27669cc0f4SStefano Zampini     lmaxneighs = 1;
28669cc0f4SStefano Zampini     for (i=0;i<ne;i++) {
29669cc0f4SStefano Zampini       const PetscInt *idxs;
30669cc0f4SStefano Zampini       ierr = ISGetIndices(edges[i],&idxs);CHKERRQ(ierr);
31669cc0f4SStefano Zampini       lmaxneighs = PetscMax(lmaxneighs,graph->count[idxs[0]]);
32669cc0f4SStefano Zampini       ierr = ISRestoreIndices(edges[i],&idxs);CHKERRQ(ierr);
33669cc0f4SStefano Zampini     }
34669cc0f4SStefano Zampini     lmaxneighs++; /* graph count does not include self */
35669cc0f4SStefano Zampini   }
36669cc0f4SStefano Zampini   ierr = MPIU_Allreduce(&lmaxneighs,&maxneighs,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
37669cc0f4SStefano Zampini   maxsize = 0;
38669cc0f4SStefano Zampini   for (i=0;i<ne;i++) {
39669cc0f4SStefano Zampini     PetscInt nn;
40669cc0f4SStefano Zampini     ierr = ISGetLocalSize(edges[i],&nn);CHKERRQ(ierr);
41669cc0f4SStefano Zampini     maxsize = PetscMax(maxsize,nn);
42669cc0f4SStefano Zampini   }
43669cc0f4SStefano Zampini   for (i=0;i<nf;i++) {
44669cc0f4SStefano Zampini     PetscInt nn;
45669cc0f4SStefano Zampini     ierr = ISGetLocalSize(faces[i],&nn);CHKERRQ(ierr);
46669cc0f4SStefano Zampini     maxsize = PetscMax(maxsize,nn);
47669cc0f4SStefano Zampini   }
48669cc0f4SStefano Zampini   ierr = PetscMalloc1(maxsize,&vals);CHKERRQ(ierr);
49669cc0f4SStefano Zampini   /* create vectors to hold quadrature weights */
50669cc0f4SStefano Zampini   ierr = MatCreateVecs(A,&quad_vec,NULL);CHKERRQ(ierr);
51669cc0f4SStefano Zampini   ierr = MatGetLocalToGlobalMapping(A,&rmap,NULL);CHKERRQ(ierr);
52669cc0f4SStefano Zampini   ierr = VecDuplicateVecs(quad_vec,maxneighs,&quad_vecs);CHKERRQ(ierr);
531ae86dd6SStefano Zampini   ierr = VecDestroy(&quad_vec);CHKERRQ(ierr);
54669cc0f4SStefano Zampini   for (i=0;i<maxneighs;i++) {
55669cc0f4SStefano Zampini     PetscInt first,last;
56669cc0f4SStefano Zampini 
57669cc0f4SStefano Zampini     ierr = VecSetLocalToGlobalMapping(quad_vecs[i],rmap);CHKERRQ(ierr);
58669cc0f4SStefano Zampini     /* the near-null space fo BDDC carries information on quadrature weights,
59669cc0f4SStefano Zampini        and these can be collinear -> so cheat with MatNullSpaceCreate
60669cc0f4SStefano Zampini        and create a suitable set of basis vectors first */
61669cc0f4SStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
62669cc0f4SStefano Zampini     if (i>=first && i < last) {
63669cc0f4SStefano Zampini       PetscScalar *data;
64669cc0f4SStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
65669cc0f4SStefano Zampini       data[i-first] = 1.;
66669cc0f4SStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
67669cc0f4SStefano Zampini     }
68669cc0f4SStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
69669cc0f4SStefano Zampini   }
70669cc0f4SStefano Zampini   ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)A),PETSC_FALSE,maxneighs,quad_vecs,nnsp);CHKERRQ(ierr);
711ae86dd6SStefano Zampini   for (i=0;i<maxneighs;i++) { /* reset vectors */
721ae86dd6SStefano Zampini     PetscInt first,last;
731ae86dd6SStefano Zampini     ierr = VecGetOwnershipRange(quad_vecs[i],&first,&last);CHKERRQ(ierr);
741ae86dd6SStefano Zampini     if (i>=first && i < last) {
751ae86dd6SStefano Zampini       PetscScalar *data;
761ae86dd6SStefano Zampini       ierr = VecGetArray(quad_vecs[i],&data);CHKERRQ(ierr);
771ae86dd6SStefano Zampini       data[i-first] = 0.;
781ae86dd6SStefano Zampini       ierr = VecRestoreArray(quad_vecs[i],&data);CHKERRQ(ierr);
791ae86dd6SStefano Zampini     }
801ae86dd6SStefano Zampini     ierr = PetscObjectStateIncrease((PetscObject)quad_vecs[i]);CHKERRQ(ierr);
811ae86dd6SStefano Zampini   }
82669cc0f4SStefano Zampini   /* compute local quad vec */
83a198735bSStefano Zampini   ierr = MatISGetLocalMat(divudotp,&loc_divudotp);CHKERRQ(ierr);
84a198735bSStefano Zampini   ierr = MatCreateVecs(loc_divudotp,&v,&p);CHKERRQ(ierr);
85669cc0f4SStefano Zampini   ierr = VecSet(p,1.);CHKERRQ(ierr);
86a198735bSStefano Zampini   ierr = MatMultTranspose(loc_divudotp,p,v);CHKERRQ(ierr);
87*fa23a32eSStefano Zampini   if (vl2l) {
88*fa23a32eSStefano Zampini     ierr = VecGetSubVector(v,vl2l,&vins);CHKERRQ(ierr);
89*fa23a32eSStefano Zampini   } else {
90*fa23a32eSStefano Zampini     vins = v;
91*fa23a32eSStefano Zampini   }
92*fa23a32eSStefano Zampini   ierr = VecGetArrayRead(vins,&array);CHKERRQ(ierr);
93669cc0f4SStefano Zampini   ierr = VecDestroy(&p);CHKERRQ(ierr);
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);
124*fa23a32eSStefano Zampini   ierr = VecRestoreArrayRead(vins,&array);CHKERRQ(ierr);
125*fa23a32eSStefano Zampini   if (vl2l) {
126*fa23a32eSStefano Zampini     ierr = VecRestoreSubVector(v,vl2l,&vins);CHKERRQ(ierr);
127*fa23a32eSStefano 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 
3611dd7afcfSStefano Zampini     if (pcbddc->benign_original_mat) {
3621dd7afcfSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Benign original mat has not been restored");
3631dd7afcfSStefano Zampini     }
3641dd7afcfSStefano Zampini     if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) {
3651dd7afcfSStefano Zampini       PetscFunctionReturn(0);
3661dd7afcfSStefano Zampini     }
367a3df083aSStefano Zampini     ierr = PetscMalloc1(pcis->n,&work);CHKERRQ(ierr);
368a3df083aSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&A_IB);CHKERRQ(ierr);
369a3df083aSStefano Zampini     ierr = MatSetSizes(A_IB,pcis->n-pcis->n_B,pcis->n_B,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
370a3df083aSStefano Zampini     ierr = MatSetType(A_IB,MATSHELL);CHKERRQ(ierr);
371a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT,(void (*)(void))PCBDDCBenignMatMult_Private);CHKERRQ(ierr);
372a3df083aSStefano Zampini     ierr = MatShellSetOperation(A_IB,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCBenignMatMultTranspose_Private);CHKERRQ(ierr);
373a3df083aSStefano Zampini     ierr = PetscNew(&ctx);CHKERRQ(ierr);
374a3df083aSStefano Zampini     ierr = MatShellSetContext(A_IB,ctx);CHKERRQ(ierr);
375a3df083aSStefano Zampini     ctx->apply_left = PETSC_TRUE;
376a3df083aSStefano Zampini     ctx->apply_right = PETSC_FALSE;
377a3df083aSStefano Zampini     ctx->apply_p0 = PETSC_FALSE;
378a3df083aSStefano Zampini     ctx->benign_n = pcbddc->benign_n;
379059032f7SStefano Zampini     if (reuse) {
380a3df083aSStefano Zampini       ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs;
3811dd7afcfSStefano Zampini       ctx->free = PETSC_FALSE;
382059032f7SStefano Zampini     } else { /* TODO: could be optimized for successive solves */
383059032f7SStefano Zampini       ISLocalToGlobalMapping N_to_D;
384059032f7SStefano Zampini       PetscInt               i;
385059032f7SStefano Zampini 
386059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(pcis->is_I_local,&N_to_D);CHKERRQ(ierr);
387059032f7SStefano Zampini       ierr = PetscMalloc1(pcbddc->benign_n,&ctx->benign_zerodiag_subs);CHKERRQ(ierr);
388059032f7SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
389059032f7SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(N_to_D,IS_GTOLM_DROP,pcbddc->benign_zerodiag_subs[i],&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
390059032f7SStefano Zampini       }
391059032f7SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&N_to_D);CHKERRQ(ierr);
3921dd7afcfSStefano Zampini       ctx->free = PETSC_TRUE;
393059032f7SStefano Zampini     }
394a3df083aSStefano Zampini     ctx->A = pcis->A_IB;
395a3df083aSStefano Zampini     ctx->work = work;
396a3df083aSStefano Zampini     ierr = MatSetUp(A_IB);CHKERRQ(ierr);
397a3df083aSStefano Zampini     ierr = MatAssemblyBegin(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
398a3df083aSStefano Zampini     ierr = MatAssemblyEnd(A_IB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
399a3df083aSStefano Zampini     pcis->A_IB = A_IB;
400a3df083aSStefano Zampini 
401a3df083aSStefano Zampini     /* A_BI as A_IB^T */
402a3df083aSStefano Zampini     ierr = MatCreateTranspose(A_IB,&A_BI);CHKERRQ(ierr);
403a3df083aSStefano Zampini     pcbddc->benign_original_mat = pcis->A_BI;
404a3df083aSStefano Zampini     pcis->A_BI = A_BI;
405a3df083aSStefano Zampini   } else {
4061dd7afcfSStefano Zampini     if (!pcbddc->benign_original_mat) {
4071dd7afcfSStefano Zampini       PetscFunctionReturn(0);
4081dd7afcfSStefano Zampini     }
409a3df083aSStefano Zampini     ierr = MatShellGetContext(pcis->A_IB,&ctx);CHKERRQ(ierr);
410a3df083aSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
411a3df083aSStefano Zampini     pcis->A_IB = ctx->A;
4121dd7afcfSStefano Zampini     ctx->A = NULL;
4131dd7afcfSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
4141dd7afcfSStefano Zampini     pcis->A_BI = pcbddc->benign_original_mat;
4151dd7afcfSStefano Zampini     pcbddc->benign_original_mat = NULL;
4161dd7afcfSStefano Zampini     if (ctx->free) {
417059032f7SStefano Zampini       PetscInt i;
4181dd7afcfSStefano Zampini       for (i=0;i<ctx->benign_n;i++) {
419059032f7SStefano Zampini         ierr = ISDestroy(&ctx->benign_zerodiag_subs[i]);CHKERRQ(ierr);
420059032f7SStefano Zampini       }
421059032f7SStefano Zampini       ierr = PetscFree(ctx->benign_zerodiag_subs);CHKERRQ(ierr);
422059032f7SStefano Zampini     }
423a3df083aSStefano Zampini     ierr = PetscFree(ctx->work);CHKERRQ(ierr);
424a3df083aSStefano Zampini     ierr = PetscFree(ctx);CHKERRQ(ierr);
425a3df083aSStefano Zampini   }
426a3df083aSStefano Zampini   PetscFunctionReturn(0);
427a3df083aSStefano Zampini }
428a3df083aSStefano Zampini 
429a3df083aSStefano Zampini /* used just in bddc debug mode */
430a3df083aSStefano Zampini #undef __FUNCT__
431a3df083aSStefano Zampini #define __FUNCT__ "PCBDDCBenignProject"
432a3df083aSStefano Zampini PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B)
433a3df083aSStefano Zampini {
434a3df083aSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
435a3df083aSStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
436a3df083aSStefano Zampini   Mat            An;
437a3df083aSStefano Zampini   PetscErrorCode ierr;
438a3df083aSStefano Zampini 
439a3df083aSStefano Zampini   PetscFunctionBegin;
440a3df083aSStefano Zampini   ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&An);CHKERRQ(ierr);
441a3df083aSStefano Zampini   ierr = MatZeroRowsColumns(An,pcbddc->benign_n,pcbddc->benign_p0_lidx,1.0,NULL,NULL);CHKERRQ(ierr);
442a3df083aSStefano Zampini   if (is1) {
443a3df083aSStefano Zampini     ierr = MatGetSubMatrix(An,is1,is2,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr);
444a3df083aSStefano Zampini     ierr = MatDestroy(&An);CHKERRQ(ierr);
445a3df083aSStefano Zampini   } else {
446a3df083aSStefano Zampini     *B = An;
447a3df083aSStefano Zampini   }
448a3df083aSStefano Zampini   PetscFunctionReturn(0);
449a3df083aSStefano Zampini }
450a3df083aSStefano Zampini 
4511cf9b237SStefano Zampini /* TODO: add reuse flag */
4521cf9b237SStefano Zampini #undef __FUNCT__
4531cf9b237SStefano Zampini #define __FUNCT__ "MatSeqAIJCompress"
4541cf9b237SStefano Zampini PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B)
4551cf9b237SStefano Zampini {
4561cf9b237SStefano Zampini   Mat            Bt;
4571cf9b237SStefano Zampini   PetscScalar    *a,*bdata;
4581cf9b237SStefano Zampini   const PetscInt *ii,*ij;
4591cf9b237SStefano Zampini   PetscInt       m,n,i,nnz,*bii,*bij;
4601cf9b237SStefano Zampini   PetscBool      flg_row;
4611cf9b237SStefano Zampini   PetscErrorCode ierr;
4621cf9b237SStefano Zampini 
4631cf9b237SStefano Zampini   PetscFunctionBegin;
4641cf9b237SStefano Zampini   ierr = MatGetSize(A,&n,&m);CHKERRQ(ierr);
4651cf9b237SStefano Zampini   ierr = MatGetRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
4661cf9b237SStefano Zampini   ierr = MatSeqAIJGetArray(A,&a);CHKERRQ(ierr);
4671cf9b237SStefano Zampini   nnz = n;
4681cf9b237SStefano Zampini   for (i=0;i<ii[n];i++) {
4691cf9b237SStefano Zampini     if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++;
4701cf9b237SStefano Zampini   }
4711cf9b237SStefano Zampini   ierr = PetscMalloc1(n+1,&bii);CHKERRQ(ierr);
4721cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bij);CHKERRQ(ierr);
4731cf9b237SStefano Zampini   ierr = PetscMalloc1(nnz,&bdata);CHKERRQ(ierr);
4741cf9b237SStefano Zampini   nnz = 0;
4751cf9b237SStefano Zampini   bii[0] = 0;
4761cf9b237SStefano Zampini   for (i=0;i<n;i++) {
4771cf9b237SStefano Zampini     PetscInt j;
4781cf9b237SStefano Zampini     for (j=ii[i];j<ii[i+1];j++) {
4791cf9b237SStefano Zampini       PetscScalar entry = a[j];
4801cf9b237SStefano Zampini       if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || ij[j] == i) {
4811cf9b237SStefano Zampini         bij[nnz] = ij[j];
4821cf9b237SStefano Zampini         bdata[nnz] = entry;
4831cf9b237SStefano Zampini         nnz++;
4841cf9b237SStefano Zampini       }
4851cf9b237SStefano Zampini     }
4861cf9b237SStefano Zampini     bii[i+1] = nnz;
4871cf9b237SStefano Zampini   }
4881cf9b237SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&a);CHKERRQ(ierr);
4891cf9b237SStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),n,m,bii,bij,bdata,&Bt);CHKERRQ(ierr);
4901cf9b237SStefano Zampini   ierr = MatRestoreRowIJ(A,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&ij,&flg_row);CHKERRQ(ierr);
4911cf9b237SStefano Zampini   {
4921cf9b237SStefano Zampini     Mat_SeqAIJ *b = (Mat_SeqAIJ*)(Bt->data);
4931cf9b237SStefano Zampini     b->free_a = PETSC_TRUE;
4941cf9b237SStefano Zampini     b->free_ij = PETSC_TRUE;
4951cf9b237SStefano Zampini   }
4961cf9b237SStefano Zampini   *B = Bt;
4971cf9b237SStefano Zampini   PetscFunctionReturn(0);
4981cf9b237SStefano Zampini }
4991cf9b237SStefano Zampini 
500674ae819SStefano Zampini #undef __FUNCT__
5014f1b2e48SStefano Zampini #define __FUNCT__ "MatDetectDisconnectedComponents"
5024f1b2e48SStefano Zampini PetscErrorCode MatDetectDisconnectedComponents(Mat A, PetscBool filter, PetscInt *ncc, IS* cc[])
5034f1b2e48SStefano Zampini {
5044f1b2e48SStefano Zampini   Mat                    B;
5054f1b2e48SStefano Zampini   IS                     is_dummy,*cc_n;
5064f1b2e48SStefano Zampini   ISLocalToGlobalMapping l2gmap_dummy;
5074f1b2e48SStefano Zampini   PCBDDCGraph            graph;
5084f1b2e48SStefano Zampini   PetscInt               i,n;
5094f1b2e48SStefano Zampini   PetscInt               *xadj,*adjncy;
5104f1b2e48SStefano Zampini   PetscInt               *xadj_filtered,*adjncy_filtered;
5114f1b2e48SStefano Zampini   PetscBool              flg_row,isseqaij;
5124f1b2e48SStefano Zampini   PetscErrorCode         ierr;
5134f1b2e48SStefano Zampini 
5144f1b2e48SStefano Zampini   PetscFunctionBegin;
51563c961adSStefano Zampini   if (!A->rmap->N || !A->cmap->N) {
51663c961adSStefano Zampini     *ncc = 0;
51763c961adSStefano Zampini     *cc = NULL;
51863c961adSStefano Zampini     PetscFunctionReturn(0);
51963c961adSStefano Zampini   }
5204f1b2e48SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
5214f1b2e48SStefano Zampini   if (!isseqaij && filter) {
5221cf9b237SStefano Zampini     PetscBool isseqdense;
5231cf9b237SStefano Zampini 
5241cf9b237SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
5251cf9b237SStefano Zampini     if (!isseqdense) {
5264f1b2e48SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
5271cf9b237SStefano Zampini     } else { /* TODO: rectangular case and LDA */
5281cf9b237SStefano Zampini       PetscScalar *array;
5291cf9b237SStefano Zampini       PetscReal   chop=1.e-6;
5301cf9b237SStefano Zampini 
5311cf9b237SStefano Zampini       ierr = MatDuplicate(A,MAT_COPY_VALUES,&B);CHKERRQ(ierr);
5321cf9b237SStefano Zampini       ierr = MatDenseGetArray(B,&array);CHKERRQ(ierr);
5331cf9b237SStefano Zampini       ierr = MatGetSize(B,&n,NULL);CHKERRQ(ierr);
5341cf9b237SStefano Zampini       for (i=0;i<n;i++) {
5351cf9b237SStefano Zampini         PetscInt j;
5361cf9b237SStefano Zampini         for (j=i+1;j<n;j++) {
5371cf9b237SStefano Zampini           PetscReal thresh = chop*(PetscAbsScalar(array[i*(n+1)])+PetscAbsScalar(array[j*(n+1)]));
5381cf9b237SStefano Zampini           if (PetscAbsScalar(array[i*n+j]) < thresh) array[i*n+j] = 0.;
5391cf9b237SStefano Zampini           if (PetscAbsScalar(array[j*n+i]) < thresh) array[j*n+i] = 0.;
5401cf9b237SStefano Zampini         }
5411cf9b237SStefano Zampini       }
5421cf9b237SStefano Zampini       ierr = MatDenseRestoreArray(B,&array);CHKERRQ(ierr);
5439d54b7f4SStefano Zampini       ierr = MatConvert(B,MATSEQAIJ,MAT_INPLACE_MATRIX,&B);CHKERRQ(ierr);
5441cf9b237SStefano Zampini     }
5454f1b2e48SStefano Zampini   } else {
5464f1b2e48SStefano Zampini     B = A;
5474f1b2e48SStefano Zampini   }
5484f1b2e48SStefano Zampini   ierr = MatGetRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
5494f1b2e48SStefano Zampini 
5504f1b2e48SStefano Zampini   /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */
5514f1b2e48SStefano Zampini   if (filter) {
5524f1b2e48SStefano Zampini     PetscScalar *data;
5534f1b2e48SStefano Zampini     PetscInt    j,cum;
5544f1b2e48SStefano Zampini 
5554f1b2e48SStefano Zampini     ierr = PetscCalloc2(n+1,&xadj_filtered,xadj[n],&adjncy_filtered);CHKERRQ(ierr);
5564f1b2e48SStefano Zampini     ierr = MatSeqAIJGetArray(B,&data);CHKERRQ(ierr);
5574f1b2e48SStefano Zampini     cum = 0;
5584f1b2e48SStefano Zampini     for (i=0;i<n;i++) {
5594f1b2e48SStefano Zampini       PetscInt t;
5604f1b2e48SStefano Zampini 
5614f1b2e48SStefano Zampini       for (j=xadj[i];j<xadj[i+1];j++) {
5624f1b2e48SStefano Zampini         if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) {
5634f1b2e48SStefano Zampini           continue;
5644f1b2e48SStefano Zampini         }
5654f1b2e48SStefano Zampini         adjncy_filtered[cum+xadj_filtered[i]++] = adjncy[j];
5664f1b2e48SStefano Zampini       }
5674f1b2e48SStefano Zampini       t = xadj_filtered[i];
5684f1b2e48SStefano Zampini       xadj_filtered[i] = cum;
5694f1b2e48SStefano Zampini       cum += t;
5704f1b2e48SStefano Zampini     }
5714f1b2e48SStefano Zampini     ierr = MatSeqAIJRestoreArray(B,&data);CHKERRQ(ierr);
5724f1b2e48SStefano Zampini   } else {
5734f1b2e48SStefano Zampini     xadj_filtered = NULL;
5744f1b2e48SStefano Zampini     adjncy_filtered = NULL;
5754f1b2e48SStefano Zampini   }
5764f1b2e48SStefano Zampini 
5774f1b2e48SStefano Zampini   /* compute local connected components using PCBDDCGraph */
5784f1b2e48SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&is_dummy);CHKERRQ(ierr);
5794f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
5804f1b2e48SStefano Zampini   ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
5814f1b2e48SStefano Zampini   ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
5824f1b2e48SStefano Zampini   ierr = PCBDDCGraphInit(graph,l2gmap_dummy,n);CHKERRQ(ierr);
5834f1b2e48SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
5844f1b2e48SStefano Zampini   if (xadj_filtered) {
5854f1b2e48SStefano Zampini     graph->xadj = xadj_filtered;
5864f1b2e48SStefano Zampini     graph->adjncy = adjncy_filtered;
5874f1b2e48SStefano Zampini   } else {
5884f1b2e48SStefano Zampini     graph->xadj = xadj;
5894f1b2e48SStefano Zampini     graph->adjncy = adjncy;
5904f1b2e48SStefano Zampini   }
5914f1b2e48SStefano Zampini   ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
5924f1b2e48SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
5934f1b2e48SStefano Zampini   /* partial clean up */
5944f1b2e48SStefano Zampini   ierr = PetscFree2(xadj_filtered,adjncy_filtered);CHKERRQ(ierr);
5954f1b2e48SStefano Zampini   ierr = MatRestoreRowIJ(B,0,PETSC_TRUE,PETSC_FALSE,&n,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
5961cf9b237SStefano Zampini   if (A != B) {
5974f1b2e48SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
5984f1b2e48SStefano Zampini   }
5994f1b2e48SStefano Zampini 
6004f1b2e48SStefano Zampini   /* get back data */
6011cf9b237SStefano Zampini   if (ncc) *ncc = graph->ncc;
6021cf9b237SStefano Zampini   if (cc) {
6034f1b2e48SStefano Zampini     ierr = PetscMalloc1(graph->ncc,&cc_n);CHKERRQ(ierr);
6044f1b2e48SStefano Zampini     for (i=0;i<graph->ncc;i++) {
6054f1b2e48SStefano 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);
6064f1b2e48SStefano Zampini     }
6074f1b2e48SStefano Zampini     *cc = cc_n;
6081cf9b237SStefano Zampini   }
6094f1b2e48SStefano Zampini   /* clean up graph */
6104f1b2e48SStefano Zampini   graph->xadj = 0;
6114f1b2e48SStefano Zampini   graph->adjncy = 0;
6124f1b2e48SStefano Zampini   ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
6134f1b2e48SStefano Zampini   PetscFunctionReturn(0);
6144f1b2e48SStefano Zampini }
6154f1b2e48SStefano Zampini 
6164f1b2e48SStefano Zampini #undef __FUNCT__
6175408967cSStefano Zampini #define __FUNCT__ "PCBDDCBenignCheck"
6185408967cSStefano Zampini PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag)
6195408967cSStefano Zampini {
6205408967cSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
6215408967cSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
622dee84bffSStefano Zampini   IS             dirIS = NULL;
6234f1b2e48SStefano Zampini   PetscInt       i;
6245408967cSStefano Zampini   PetscErrorCode ierr;
6255408967cSStefano Zampini 
6265408967cSStefano Zampini   PetscFunctionBegin;
627dee84bffSStefano Zampini   ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
6285408967cSStefano Zampini   if (zerodiag) {
6295408967cSStefano Zampini     Mat            A;
6305408967cSStefano Zampini     Vec            vec3_N;
6315408967cSStefano Zampini     PetscScalar    *vals;
6325408967cSStefano Zampini     const PetscInt *idxs;
633d12d3064SStefano Zampini     PetscInt       nz,*count;
6345408967cSStefano Zampini 
6355408967cSStefano Zampini     /* p0 */
6365408967cSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
6375408967cSStefano Zampini     ierr = PetscMalloc1(pcis->n,&vals);CHKERRQ(ierr);
6385408967cSStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
6395408967cSStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
6404f1b2e48SStefano Zampini     for (i=0;i<nz;i++) vals[i] = 1.;
6415408967cSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
6425408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6435408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6445408967cSStefano Zampini     /* v_I */
6455408967cSStefano Zampini     ierr = VecSetRandom(pcis->vec2_N,NULL);CHKERRQ(ierr);
6465408967cSStefano Zampini     for (i=0;i<nz;i++) vals[i] = 0.;
6475408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
6485408967cSStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
6495408967cSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
6505408967cSStefano Zampini     for (i=0;i<pcis->n_B;i++) vals[i] = 0.;
6515408967cSStefano Zampini     ierr = VecSetValues(pcis->vec2_N,pcis->n_B,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
6525408967cSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
6535408967cSStefano Zampini     if (dirIS) {
6545408967cSStefano Zampini       PetscInt n;
6555408967cSStefano Zampini 
6565408967cSStefano Zampini       ierr = ISGetLocalSize(dirIS,&n);CHKERRQ(ierr);
6575408967cSStefano Zampini       ierr = ISGetIndices(dirIS,&idxs);CHKERRQ(ierr);
6585408967cSStefano Zampini       for (i=0;i<n;i++) vals[i] = 0.;
6595408967cSStefano Zampini       ierr = VecSetValues(pcis->vec2_N,n,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
6605408967cSStefano Zampini       ierr = ISRestoreIndices(dirIS,&idxs);CHKERRQ(ierr);
6615408967cSStefano Zampini     }
6625408967cSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec2_N);CHKERRQ(ierr);
6635408967cSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec2_N);CHKERRQ(ierr);
6645408967cSStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&vec3_N);CHKERRQ(ierr);
6655408967cSStefano Zampini     ierr = VecSet(vec3_N,0.);CHKERRQ(ierr);
666669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
6675408967cSStefano Zampini     ierr = MatMult(A,pcis->vec1_N,vec3_N);CHKERRQ(ierr);
6685408967cSStefano Zampini     ierr = VecDot(vec3_N,pcis->vec2_N,&vals[0]);CHKERRQ(ierr);
669fbfcb133SStefano Zampini     if (PetscAbsScalar(vals[0]) > 1.e-1) {
670b9b0e38cSStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! b(v_I,p_0) = %1.6e (should be numerically 0.)",PetscAbsScalar(vals[0]));
6715408967cSStefano Zampini     }
6725408967cSStefano Zampini     ierr = PetscFree(vals);CHKERRQ(ierr);
6735408967cSStefano Zampini     ierr = VecDestroy(&vec3_N);CHKERRQ(ierr);
674d12d3064SStefano Zampini 
675d12d3064SStefano Zampini     /* there should not be any pressure dofs lying on the interface */
676d12d3064SStefano Zampini     ierr = PetscCalloc1(pcis->n,&count);CHKERRQ(ierr);
677d12d3064SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
678d12d3064SStefano Zampini     for (i=0;i<pcis->n_B;i++) count[idxs[i]]++;
679d12d3064SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
680d12d3064SStefano Zampini     ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
681d4d8cf7bSStefano Zampini     for (i=0;i<nz;i++) {
682d12d3064SStefano Zampini       if (count[idxs[i]]) {
683d12d3064SStefano Zampini         SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Benign trick can not be applied! pressure dof %d is an interface dof",idxs[i]);
684d12d3064SStefano Zampini       }
685d4d8cf7bSStefano Zampini     }
686d12d3064SStefano Zampini     ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
687d12d3064SStefano Zampini     ierr = PetscFree(count);CHKERRQ(ierr);
6885408967cSStefano Zampini   }
689dee84bffSStefano Zampini   ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
6905408967cSStefano Zampini 
6915408967cSStefano Zampini   /* check PCBDDCBenignGetOrSetP0 */
6925408967cSStefano Zampini   ierr = VecSetRandom(pcis->vec1_global,NULL);CHKERRQ(ierr);
6934f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = -PetscGlobalRank-i;
6945408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
6954f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1;
6965408967cSStefano Zampini   ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_TRUE);CHKERRQ(ierr);
6974f1b2e48SStefano Zampini   for (i=0;i<pcbddc->benign_n;i++) {
6984f1b2e48SStefano Zampini     if ((PetscInt)PetscRealPart(pcbddc->benign_p0[i]) != -PetscGlobalRank-i) {
6994f1b2e48SStefano Zampini       SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error testing PCBDDCBenignGetOrSetP0! Found %1.4e at %d instead of %1.4e\n",pcbddc->benign_p0[i],i,-PetscGlobalRank-i);CHKERRQ(ierr);
7004f1b2e48SStefano Zampini     }
7015408967cSStefano Zampini   }
7025408967cSStefano Zampini   PetscFunctionReturn(0);
7035408967cSStefano Zampini }
7045408967cSStefano Zampini 
7055408967cSStefano Zampini #undef __FUNCT__
706339f8db1SStefano Zampini #define __FUNCT__ "PCBDDCBenignDetectSaddlePoint"
707339f8db1SStefano Zampini PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, IS *zerodiaglocal)
708339f8db1SStefano Zampini {
709339f8db1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
7104f1b2e48SStefano Zampini   IS             pressures,zerodiag,*zerodiag_subs;
711b0f5fe93SStefano Zampini   PetscInt       nz,n;
7121f4df5f7SStefano Zampini   PetscInt       *interior_dofs,n_interior_dofs;
7134f1b2e48SStefano Zampini   PetscBool      sorted,have_null,has_null_pressures,recompute_zerodiag;
714339f8db1SStefano Zampini   PetscErrorCode ierr;
715339f8db1SStefano Zampini 
716339f8db1SStefano Zampini   PetscFunctionBegin;
7179f47a83aSStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
7189f47a83aSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
719a3df083aSStefano Zampini   for (n=0;n<pcbddc->benign_n;n++) {
720a3df083aSStefano Zampini     ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[n]);CHKERRQ(ierr);
721a3df083aSStefano Zampini   }
722a3df083aSStefano Zampini   ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
723a3df083aSStefano Zampini   pcbddc->benign_n = 0;
7241ae86dd6SStefano Zampini   /* if a local info on dofs is present, assumes that the last field represents  "pressures"
7254f1b2e48SStefano Zampini      otherwise, it uses only zerodiagonal dofs (ok if the pressure block is all zero; it could fail if it is not)
7264f1b2e48SStefano Zampini      Checks if all the pressure dofs in each subdomain have a zero diagonal
7274f1b2e48SStefano Zampini      If not, a change of basis on pressures is not needed
7281ae86dd6SStefano Zampini      since the local Schur complements are already SPD
7294f1b2e48SStefano Zampini   */
7304f1b2e48SStefano Zampini   has_null_pressures = PETSC_TRUE;
7314f1b2e48SStefano Zampini   have_null = PETSC_TRUE;
73240fa8d13SStefano Zampini   if (pcbddc->n_ISForDofsLocal) {
7334f1b2e48SStefano Zampini     PetscInt npl,*idxs,p = pcbddc->n_ISForDofsLocal-1;
7344f1b2e48SStefano Zampini 
7354f1b2e48SStefano Zampini     /* Dofs splitting for BDDC cannot have PETSC_COMM_SELF, so create a sequential IS */
7364f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[p],&npl);CHKERRQ(ierr);
7374f1b2e48SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
7384f1b2e48SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,npl,idxs,PETSC_COPY_VALUES,&pressures);CHKERRQ(ierr);
739ba14f8e3SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[p],(const PetscInt**)&idxs);CHKERRQ(ierr);
74040fa8d13SStefano Zampini     ierr = ISSorted(pressures,&sorted);CHKERRQ(ierr);
74140fa8d13SStefano Zampini     if (!sorted) {
74240fa8d13SStefano Zampini       ierr = ISSort(pressures);CHKERRQ(ierr);
74340fa8d13SStefano Zampini     }
74440fa8d13SStefano Zampini   } else {
74540fa8d13SStefano Zampini     pressures = NULL;
74640fa8d13SStefano Zampini   }
74797d764eeSStefano Zampini   /* pcis has not been setup yet, so get the local size from the subdomain matrix */
74897d764eeSStefano Zampini   ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
74927b6a85dSStefano Zampini   if (!n) pcbddc->benign_change_explicit = PETSC_TRUE;
75097d764eeSStefano Zampini   ierr = MatFindZeroDiagonals(pcbddc->local_mat,&zerodiag);CHKERRQ(ierr);
751339f8db1SStefano Zampini   ierr = ISSorted(zerodiag,&sorted);CHKERRQ(ierr);
752339f8db1SStefano Zampini   if (!sorted) {
753339f8db1SStefano Zampini     ierr = ISSort(zerodiag);CHKERRQ(ierr);
754339f8db1SStefano Zampini   }
755339f8db1SStefano Zampini   ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
7564f1b2e48SStefano Zampini   if (!nz) {
7574f1b2e48SStefano Zampini     if (n) have_null = PETSC_FALSE;
7584f1b2e48SStefano Zampini     has_null_pressures = PETSC_FALSE;
75940fa8d13SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
76040fa8d13SStefano Zampini   }
7614f1b2e48SStefano Zampini   recompute_zerodiag = PETSC_FALSE;
7624f1b2e48SStefano Zampini   /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */
7634f1b2e48SStefano Zampini   zerodiag_subs = NULL;
7644f1b2e48SStefano Zampini   pcbddc->benign_n = 0;
7651f4df5f7SStefano Zampini   n_interior_dofs = 0;
7661f4df5f7SStefano Zampini   interior_dofs = NULL;
7671f4df5f7SStefano Zampini   if (pcbddc->current_level) { /* need to compute interior nodes */
7681f4df5f7SStefano Zampini     PetscInt n,i,j;
7691f4df5f7SStefano Zampini     PetscInt n_neigh,*neigh,*n_shared,**shared;
7701f4df5f7SStefano Zampini     PetscInt *iwork;
7711f4df5f7SStefano Zampini 
7721f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(pc->pmat->rmap->mapping,&n);CHKERRQ(ierr);
7731f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingGetInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
7741f4df5f7SStefano Zampini     ierr = PetscCalloc1(n,&iwork);CHKERRQ(ierr);
7751f4df5f7SStefano Zampini     ierr = PetscMalloc1(n,&interior_dofs);CHKERRQ(ierr);
7761f4df5f7SStefano Zampini     for (i=0;i<n_neigh;i++)
7771f4df5f7SStefano Zampini       for (j=0;j<n_shared[i];j++)
7781f4df5f7SStefano Zampini           iwork[shared[i][j]] += 1;
7791f4df5f7SStefano Zampini     for (i=0;i<n;i++)
7801f4df5f7SStefano Zampini       if (!iwork[i])
7811f4df5f7SStefano Zampini         interior_dofs[n_interior_dofs++] = i;
7821f4df5f7SStefano Zampini     ierr = PetscFree(iwork);CHKERRQ(ierr);
7831f4df5f7SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreInfo(pc->pmat->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
7841f4df5f7SStefano Zampini   }
7854f1b2e48SStefano Zampini   if (has_null_pressures) {
7864f1b2e48SStefano Zampini     IS             *subs;
7871f4df5f7SStefano Zampini     PetscInt       nsubs,i,j,nl;
7881f4df5f7SStefano Zampini     const PetscInt *idxs;
7891f4df5f7SStefano Zampini     PetscScalar    *array;
7901f4df5f7SStefano Zampini     Vec            *work;
7911f4df5f7SStefano Zampini     Mat_IS*        matis = (Mat_IS*)(pc->pmat->data);
7924f1b2e48SStefano Zampini 
7934f1b2e48SStefano Zampini     subs = pcbddc->local_subs;
7944f1b2e48SStefano Zampini     nsubs = pcbddc->n_local_subs;
7951f4df5f7SStefano 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) */
7961f4df5f7SStefano Zampini     if (pcbddc->current_level) {
7971f4df5f7SStefano Zampini       ierr = VecDuplicateVecs(matis->y,2,&work);CHKERRQ(ierr);
7981f4df5f7SStefano Zampini       ierr = ISGetLocalSize(zerodiag,&nl);CHKERRQ(ierr);
7991f4df5f7SStefano Zampini       ierr = ISGetIndices(zerodiag,&idxs);CHKERRQ(ierr);
8001f4df5f7SStefano Zampini       /* work[0] = 1_p */
8011f4df5f7SStefano Zampini       ierr = VecSet(work[0],0.);CHKERRQ(ierr);
8021f4df5f7SStefano Zampini       ierr = VecGetArray(work[0],&array);CHKERRQ(ierr);
8031f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 1.;
8041f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[0],&array);CHKERRQ(ierr);
8051f4df5f7SStefano Zampini       /* work[0] = 1_v */
8061f4df5f7SStefano Zampini       ierr = VecSet(work[1],1.);CHKERRQ(ierr);
8071f4df5f7SStefano Zampini       ierr = VecGetArray(work[1],&array);CHKERRQ(ierr);
8081f4df5f7SStefano Zampini       for (j=0;j<nl;j++) array[idxs[j]] = 0.;
8091f4df5f7SStefano Zampini       ierr = VecRestoreArray(work[1],&array);CHKERRQ(ierr);
8101f4df5f7SStefano Zampini       ierr = ISRestoreIndices(zerodiag,&idxs);CHKERRQ(ierr);
8111f4df5f7SStefano Zampini     }
8124f1b2e48SStefano Zampini     if (nsubs > 1) {
8134f1b2e48SStefano Zampini       ierr = PetscCalloc1(nsubs,&zerodiag_subs);CHKERRQ(ierr);
8144f1b2e48SStefano Zampini       for (i=0;i<nsubs;i++) {
8154f1b2e48SStefano Zampini         ISLocalToGlobalMapping l2g;
8164f1b2e48SStefano Zampini         IS                     t_zerodiag_subs;
8174f1b2e48SStefano Zampini         PetscInt               nl;
8184f1b2e48SStefano Zampini 
8194f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(subs[i],&l2g);CHKERRQ(ierr);
8204f1b2e48SStefano Zampini         ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,zerodiag,&t_zerodiag_subs);CHKERRQ(ierr);
8214f1b2e48SStefano Zampini         ierr = ISGetLocalSize(t_zerodiag_subs,&nl);CHKERRQ(ierr);
8224f1b2e48SStefano Zampini         if (nl) {
8234f1b2e48SStefano Zampini           PetscBool valid = PETSC_TRUE;
8244f1b2e48SStefano Zampini 
8251f4df5f7SStefano Zampini           if (pcbddc->current_level) {
8261f4df5f7SStefano Zampini             ierr = VecSet(matis->x,0);CHKERRQ(ierr);
8271f4df5f7SStefano Zampini             ierr = ISGetLocalSize(subs[i],&nl);CHKERRQ(ierr);
8281f4df5f7SStefano Zampini             ierr = ISGetIndices(subs[i],&idxs);CHKERRQ(ierr);
8291f4df5f7SStefano Zampini             ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
8301f4df5f7SStefano Zampini             for (j=0;j<nl;j++) array[idxs[j]] = 1.;
8311f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
8321f4df5f7SStefano Zampini             ierr = ISRestoreIndices(subs[i],&idxs);CHKERRQ(ierr);
8331f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->x,work[0],matis->x);CHKERRQ(ierr);
8341f4df5f7SStefano Zampini             ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
8351f4df5f7SStefano Zampini             ierr = VecPointwiseMult(matis->y,work[1],matis->y);CHKERRQ(ierr);
8361f4df5f7SStefano Zampini             ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
8371f4df5f7SStefano Zampini             for (j=0;j<n_interior_dofs;j++) {
8381f4df5f7SStefano Zampini               if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
8391f4df5f7SStefano Zampini                 valid = PETSC_FALSE;
8401f4df5f7SStefano Zampini                 break;
8411f4df5f7SStefano Zampini               }
8421f4df5f7SStefano Zampini             }
8431f4df5f7SStefano Zampini             ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
8441f4df5f7SStefano Zampini           }
8451f4df5f7SStefano Zampini           if (valid && pcbddc->NeumannBoundariesLocal) {
8461f4df5f7SStefano Zampini             IS       t_bc;
8471f4df5f7SStefano Zampini             PetscInt nzb;
8481f4df5f7SStefano Zampini 
8491f4df5f7SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pcbddc->NeumannBoundariesLocal,&t_bc);CHKERRQ(ierr);
8501f4df5f7SStefano Zampini             ierr = ISGetLocalSize(t_bc,&nzb);CHKERRQ(ierr);
8511f4df5f7SStefano Zampini             ierr = ISDestroy(&t_bc);CHKERRQ(ierr);
8521f4df5f7SStefano Zampini             if (nzb) valid = PETSC_FALSE;
8531f4df5f7SStefano Zampini           }
8541f4df5f7SStefano Zampini           if (valid && pressures) {
8554f1b2e48SStefano Zampini             IS t_pressure_subs;
8564f1b2e48SStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_DROP,pressures,&t_pressure_subs);CHKERRQ(ierr);
8574f1b2e48SStefano Zampini             ierr = ISEqual(t_pressure_subs,t_zerodiag_subs,&valid);CHKERRQ(ierr);
8584f1b2e48SStefano Zampini             ierr = ISDestroy(&t_pressure_subs);CHKERRQ(ierr);
8594f1b2e48SStefano Zampini           }
8604f1b2e48SStefano Zampini           if (valid) {
8614f1b2e48SStefano Zampini             ierr = ISLocalToGlobalMappingApplyIS(l2g,t_zerodiag_subs,&zerodiag_subs[pcbddc->benign_n]);CHKERRQ(ierr);
8624f1b2e48SStefano Zampini             pcbddc->benign_n++;
8634f1b2e48SStefano Zampini           } else {
8644f1b2e48SStefano Zampini             recompute_zerodiag = PETSC_TRUE;
8654f1b2e48SStefano Zampini           }
8664f1b2e48SStefano Zampini         }
8674f1b2e48SStefano Zampini         ierr = ISDestroy(&t_zerodiag_subs);CHKERRQ(ierr);
8684f1b2e48SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
8694f1b2e48SStefano Zampini       }
8704f1b2e48SStefano Zampini     } else { /* there's just one subdomain (or zero if they have not been detected */
8714f1b2e48SStefano Zampini       PetscBool valid = PETSC_TRUE;
8721f4df5f7SStefano Zampini 
8731f4df5f7SStefano Zampini       if (pcbddc->NeumannBoundariesLocal) {
8741f4df5f7SStefano Zampini         PetscInt nzb;
8751f4df5f7SStefano Zampini         ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&nzb);CHKERRQ(ierr);
8761f4df5f7SStefano Zampini         if (nzb) valid = PETSC_FALSE;
8771f4df5f7SStefano Zampini       }
8781f4df5f7SStefano Zampini       if (valid && pressures) {
8794f1b2e48SStefano Zampini         ierr = ISEqual(pressures,zerodiag,&valid);CHKERRQ(ierr);
8804f1b2e48SStefano Zampini       }
8811f4df5f7SStefano Zampini       if (valid && pcbddc->current_level) {
8821f4df5f7SStefano Zampini         ierr = MatMult(matis->A,work[0],matis->x);CHKERRQ(ierr);
8831f4df5f7SStefano Zampini         ierr = VecPointwiseMult(matis->x,work[1],matis->x);CHKERRQ(ierr);
8841f4df5f7SStefano Zampini         ierr = VecGetArray(matis->x,&array);CHKERRQ(ierr);
8851f4df5f7SStefano Zampini         for (j=0;j<n_interior_dofs;j++) {
8861f4df5f7SStefano Zampini             if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) {
8871f4df5f7SStefano Zampini               valid = PETSC_FALSE;
8881f4df5f7SStefano Zampini               break;
8891f4df5f7SStefano Zampini           }
8901f4df5f7SStefano Zampini         }
8911f4df5f7SStefano Zampini         ierr = VecRestoreArray(matis->x,&array);CHKERRQ(ierr);
8921f4df5f7SStefano Zampini       }
8934f1b2e48SStefano Zampini       if (valid) {
8944f1b2e48SStefano Zampini         pcbddc->benign_n = 1;
895ca92afb2SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&zerodiag_subs);CHKERRQ(ierr);
8964f1b2e48SStefano Zampini         ierr = PetscObjectReference((PetscObject)zerodiag);CHKERRQ(ierr);
8974f1b2e48SStefano Zampini         zerodiag_subs[0] = zerodiag;
8984f1b2e48SStefano Zampini       }
8994f1b2e48SStefano Zampini     }
9001f4df5f7SStefano Zampini     if (pcbddc->current_level) {
9011f4df5f7SStefano Zampini       ierr = VecDestroyVecs(2,&work);CHKERRQ(ierr);
9024f1b2e48SStefano Zampini     }
9031f4df5f7SStefano Zampini   }
9041f4df5f7SStefano Zampini   ierr = PetscFree(interior_dofs);CHKERRQ(ierr);
9054f1b2e48SStefano Zampini 
9064f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
907b9b0e38cSStefano Zampini     PetscInt n;
908b9b0e38cSStefano Zampini 
9094f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
9104f1b2e48SStefano Zampini     recompute_zerodiag = PETSC_FALSE;
911b9b0e38cSStefano Zampini     ierr = MatGetLocalSize(pcbddc->local_mat,&n,NULL);CHKERRQ(ierr);
912b9b0e38cSStefano Zampini     if (n) {
9134f1b2e48SStefano Zampini       has_null_pressures = PETSC_FALSE;
9144f1b2e48SStefano Zampini       have_null = PETSC_FALSE;
9154f1b2e48SStefano Zampini     }
916b9b0e38cSStefano Zampini   }
9174f1b2e48SStefano Zampini 
9184f1b2e48SStefano Zampini   /* final check for null pressures */
9194f1b2e48SStefano Zampini   if (zerodiag && pressures) {
9204f1b2e48SStefano Zampini     PetscInt nz,np;
9214f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
9224f1b2e48SStefano Zampini     ierr = ISGetLocalSize(pressures,&np);CHKERRQ(ierr);
9234f1b2e48SStefano Zampini     if (nz != np) have_null = PETSC_FALSE;
9244f1b2e48SStefano Zampini   }
9254f1b2e48SStefano Zampini 
9264f1b2e48SStefano Zampini   if (recompute_zerodiag) {
9274f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
9284f1b2e48SStefano Zampini     if (pcbddc->benign_n == 1) {
9294f1b2e48SStefano Zampini       ierr = PetscObjectReference((PetscObject)zerodiag_subs[0]);CHKERRQ(ierr);
9304f1b2e48SStefano Zampini       zerodiag = zerodiag_subs[0];
9314f1b2e48SStefano Zampini     } else {
9324f1b2e48SStefano Zampini       PetscInt i,nzn,*new_idxs;
9334f1b2e48SStefano Zampini 
9344f1b2e48SStefano Zampini       nzn = 0;
9354f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
9364f1b2e48SStefano Zampini         PetscInt ns;
9374f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
9384f1b2e48SStefano Zampini         nzn += ns;
9394f1b2e48SStefano Zampini       }
9404f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzn,&new_idxs);CHKERRQ(ierr);
9414f1b2e48SStefano Zampini       nzn = 0;
9424f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
9434f1b2e48SStefano Zampini         PetscInt ns,*idxs;
9444f1b2e48SStefano Zampini         ierr = ISGetLocalSize(zerodiag_subs[i],&ns);CHKERRQ(ierr);
9454f1b2e48SStefano Zampini         ierr = ISGetIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
9464f1b2e48SStefano Zampini         ierr = PetscMemcpy(new_idxs+nzn,idxs,ns*sizeof(PetscInt));CHKERRQ(ierr);
9474f1b2e48SStefano Zampini         ierr = ISRestoreIndices(zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
9484f1b2e48SStefano Zampini         nzn += ns;
9494f1b2e48SStefano Zampini       }
9504f1b2e48SStefano Zampini       ierr = PetscSortInt(nzn,new_idxs);CHKERRQ(ierr);
9514f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,nzn,new_idxs,PETSC_OWN_POINTER,&zerodiag);CHKERRQ(ierr);
9524f1b2e48SStefano Zampini     }
9534f1b2e48SStefano Zampini     have_null = PETSC_FALSE;
9544f1b2e48SStefano Zampini   }
9554f1b2e48SStefano Zampini 
956669cc0f4SStefano Zampini   /* Prepare matrix to compute no-net-flux */
957a198735bSStefano Zampini   if (pcbddc->compute_nonetflux && !pcbddc->divudotp) {
958a198735bSStefano Zampini     Mat                    A,loc_divudotp;
959a198735bSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g,l2gmap;
960a198735bSStefano Zampini     IS                     row,col,isused = NULL;
961a198735bSStefano Zampini     PetscInt               M,N,n,st,n_isused;
962a198735bSStefano Zampini 
9631f4df5f7SStefano Zampini     if (pressures) {
9641f4df5f7SStefano Zampini       isused = pressures;
9651f4df5f7SStefano Zampini     } else {
9661f4df5f7SStefano Zampini       isused = zerodiag;
9671f4df5f7SStefano Zampini     }
968a198735bSStefano Zampini     ierr = MatGetLocalToGlobalMapping(pc->pmat,&l2gmap,NULL);CHKERRQ(ierr);
969669cc0f4SStefano Zampini     ierr = MatISGetLocalMat(pc->pmat,&A);CHKERRQ(ierr);
9701ae86dd6SStefano Zampini     ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
9711ae86dd6SStefano 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");
972a198735bSStefano Zampini     n_isused = 0;
973a198735bSStefano Zampini     if (isused) {
974a198735bSStefano Zampini       ierr = ISGetLocalSize(isused,&n_isused);CHKERRQ(ierr);
975a198735bSStefano Zampini     }
976a198735bSStefano Zampini     ierr = MPI_Scan(&n_isused,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
977a198735bSStefano Zampini     st = st-n_isused;
9781ae86dd6SStefano Zampini     if (n) {
979a198735bSStefano Zampini       const PetscInt *gidxs;
980a198735bSStefano Zampini 
981a198735bSStefano Zampini       ierr = MatGetSubMatrix(A,isused,NULL,MAT_INITIAL_MATRIX,&loc_divudotp);CHKERRQ(ierr);
982a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
983a198735bSStefano Zampini       /* TODO: extend ISCreateStride with st = PETSC_DECIDE */
984a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
985a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
986a198735bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
9871ae86dd6SStefano Zampini     } else {
988a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&loc_divudotp);CHKERRQ(ierr);
989a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),n_isused,st,1,&row);CHKERRQ(ierr);
990a198735bSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),0,NULL,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
991a198735bSStefano Zampini     }
992a198735bSStefano Zampini     ierr = MatGetSize(pc->pmat,NULL,&N);CHKERRQ(ierr);
993a198735bSStefano Zampini     ierr = ISGetSize(row,&M);CHKERRQ(ierr);
994a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
995a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
996a198735bSStefano Zampini     ierr = ISDestroy(&row);CHKERRQ(ierr);
997a198735bSStefano Zampini     ierr = ISDestroy(&col);CHKERRQ(ierr);
998a198735bSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->divudotp);CHKERRQ(ierr);
999a198735bSStefano Zampini     ierr = MatSetType(pcbddc->divudotp,MATIS);CHKERRQ(ierr);
1000a198735bSStefano Zampini     ierr = MatSetSizes(pcbddc->divudotp,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
1001a198735bSStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->divudotp,rl2g,cl2g);CHKERRQ(ierr);
1002a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
1003a198735bSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
1004a198735bSStefano Zampini     ierr = MatISSetLocalMat(pcbddc->divudotp,loc_divudotp);CHKERRQ(ierr);
1005a198735bSStefano Zampini     ierr = MatDestroy(&loc_divudotp);CHKERRQ(ierr);
10061ae86dd6SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10071ae86dd6SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->divudotp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10081ae86dd6SStefano Zampini   }
1009b3afcdbeSStefano Zampini 
1010b3afcdbeSStefano Zampini   /* change of basis and p0 dofs */
10114f1b2e48SStefano Zampini   if (has_null_pressures) {
10124f1b2e48SStefano Zampini     IS             zerodiagc;
10134f1b2e48SStefano Zampini     const PetscInt *idxs,*idxsc;
10144f1b2e48SStefano Zampini     PetscInt       i,s,*nnz;
10154f1b2e48SStefano Zampini 
10164f1b2e48SStefano Zampini     ierr = ISGetLocalSize(zerodiag,&nz);CHKERRQ(ierr);
1017339f8db1SStefano Zampini     ierr = ISComplement(zerodiag,0,n,&zerodiagc);CHKERRQ(ierr);
1018339f8db1SStefano Zampini     ierr = ISGetIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
1019339f8db1SStefano Zampini     /* local change of basis for pressures */
1020339f8db1SStefano Zampini     ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
102197d764eeSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_change);CHKERRQ(ierr);
1022339f8db1SStefano Zampini     ierr = MatSetType(pcbddc->benign_change,MATAIJ);CHKERRQ(ierr);
1023339f8db1SStefano Zampini     ierr = MatSetSizes(pcbddc->benign_change,n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1024339f8db1SStefano Zampini     ierr = PetscMalloc1(n,&nnz);CHKERRQ(ierr);
10254f1b2e48SStefano Zampini     for (i=0;i<n-nz;i++) nnz[idxsc[i]] = 1; /* identity on velocities plus pressure dofs for non-singular subdomains */
10264f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
10274f1b2e48SStefano Zampini       PetscInt nzs,j;
10284f1b2e48SStefano Zampini 
10294f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[i],&nzs);CHKERRQ(ierr);
10304f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
10314f1b2e48SStefano Zampini       for (j=0;j<nzs-1;j++) nnz[idxs[j]] = 2; /* change on pressures */
10324f1b2e48SStefano Zampini       nnz[idxs[nzs-1]] = nzs; /* last local pressure dof in subdomain */
10334f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[i],&idxs);CHKERRQ(ierr);
10344f1b2e48SStefano Zampini     }
1035339f8db1SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->benign_change,0,nnz);CHKERRQ(ierr);
1036339f8db1SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
1037339f8db1SStefano Zampini     /* set identity on velocities */
1038339f8db1SStefano Zampini     for (i=0;i<n-nz;i++) {
1039339f8db1SStefano Zampini       ierr = MatSetValue(pcbddc->benign_change,idxsc[i],idxsc[i],1.,INSERT_VALUES);CHKERRQ(ierr);
1040339f8db1SStefano Zampini     }
10414f1b2e48SStefano Zampini     ierr = ISRestoreIndices(zerodiagc,&idxsc);CHKERRQ(ierr);
10424f1b2e48SStefano Zampini     ierr = ISDestroy(&zerodiagc);CHKERRQ(ierr);
10439f47a83aSStefano Zampini     ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
10444f1b2e48SStefano 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);
1045339f8db1SStefano Zampini     /* set change on pressures */
10464f1b2e48SStefano Zampini     for (s=0;s<pcbddc->benign_n;s++) {
10474f1b2e48SStefano Zampini       PetscScalar *array;
10484f1b2e48SStefano Zampini       PetscInt    nzs;
10494f1b2e48SStefano Zampini 
10504f1b2e48SStefano Zampini       ierr = ISGetLocalSize(zerodiag_subs[s],&nzs);CHKERRQ(ierr);
10514f1b2e48SStefano Zampini       ierr = ISGetIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
10524f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) {
1053339f8db1SStefano Zampini         PetscScalar vals[2];
1054339f8db1SStefano Zampini         PetscInt    cols[2];
1055339f8db1SStefano Zampini 
1056339f8db1SStefano Zampini         cols[0] = idxs[i];
10574f1b2e48SStefano Zampini         cols[1] = idxs[nzs-1];
1058339f8db1SStefano Zampini         vals[0] = 1.;
1059b0f5fe93SStefano Zampini         vals[1] = 1.;
10604f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->benign_change,1,cols,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
1061339f8db1SStefano Zampini       }
10624f1b2e48SStefano Zampini       ierr = PetscMalloc1(nzs,&array);CHKERRQ(ierr);
10634f1b2e48SStefano Zampini       for (i=0;i<nzs-1;i++) array[i] = -1.;
10644f1b2e48SStefano Zampini       array[nzs-1] = 1.;
10654f1b2e48SStefano Zampini       ierr = MatSetValues(pcbddc->benign_change,1,idxs+nzs-1,nzs,idxs,array,INSERT_VALUES);CHKERRQ(ierr);
10664f1b2e48SStefano Zampini       /* store local idxs for p0 */
10674f1b2e48SStefano Zampini       pcbddc->benign_p0_lidx[s] = idxs[nzs-1];
10684f1b2e48SStefano Zampini       ierr = ISRestoreIndices(zerodiag_subs[s],&idxs);CHKERRQ(ierr);
1069339f8db1SStefano Zampini       ierr = PetscFree(array);CHKERRQ(ierr);
10704f1b2e48SStefano Zampini     }
1071339f8db1SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1072339f8db1SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->benign_change,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1073a3df083aSStefano Zampini     /* project if needed */
1074a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
10751dd7afcfSStefano Zampini       Mat M;
10761dd7afcfSStefano Zampini 
10771dd7afcfSStefano Zampini       ierr = MatPtAP(pcbddc->local_mat,pcbddc->benign_change,MAT_INITIAL_MATRIX,2.0,&M);CHKERRQ(ierr);
1078339f8db1SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
10791dd7afcfSStefano Zampini       ierr = MatSeqAIJCompress(M,&pcbddc->local_mat);CHKERRQ(ierr);
10801dd7afcfSStefano Zampini       ierr = MatDestroy(&M);CHKERRQ(ierr);
1081a3df083aSStefano Zampini     }
10824f1b2e48SStefano Zampini     /* store global idxs for p0 */
10834f1b2e48SStefano Zampini     ierr = ISLocalToGlobalMappingApply(pc->pmat->rmap->mapping,pcbddc->benign_n,pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
1084339f8db1SStefano Zampini   }
1085ca92afb2SStefano Zampini   pcbddc->benign_zerodiag_subs = zerodiag_subs;
10864f1b2e48SStefano Zampini   ierr = ISDestroy(&pressures);CHKERRQ(ierr);
1087b0f5fe93SStefano Zampini 
1088b0f5fe93SStefano Zampini   /* determines if the coarse solver will be singular or not */
1089b0f5fe93SStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_null,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
109027b6a85dSStefano Zampini   /* determines if the problem has subdomains with 0 pressure block */
109127b6a85dSStefano Zampini   ierr = MPI_Allreduce(&have_null,&pcbddc->benign_have_null,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1092339f8db1SStefano Zampini   *zerodiaglocal = zerodiag;
1093339f8db1SStefano Zampini   PetscFunctionReturn(0);
1094339f8db1SStefano Zampini }
1095339f8db1SStefano Zampini 
1096339f8db1SStefano Zampini #undef __FUNCT__
1097015636ebSStefano Zampini #define __FUNCT__ "PCBDDCBenignGetOrSetP0"
1098015636ebSStefano Zampini PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get)
1099efc2fbd9SStefano Zampini {
1100efc2fbd9SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
1101de9d7bd0SStefano Zampini   PetscScalar    *array;
1102efc2fbd9SStefano Zampini   PetscErrorCode ierr;
1103efc2fbd9SStefano Zampini 
1104efc2fbd9SStefano Zampini   PetscFunctionBegin;
1105efc2fbd9SStefano Zampini   if (!pcbddc->benign_sf) {
1106efc2fbd9SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)pc),&pcbddc->benign_sf);CHKERRQ(ierr);
11074f1b2e48SStefano Zampini     ierr = PetscSFSetGraphLayout(pcbddc->benign_sf,pc->pmat->rmap,pcbddc->benign_n,NULL,PETSC_OWN_POINTER,pcbddc->benign_p0_gidx);CHKERRQ(ierr);
1108efc2fbd9SStefano Zampini   }
1109de9d7bd0SStefano Zampini   if (get) {
1110efc2fbd9SStefano Zampini     ierr = VecGetArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
11114f1b2e48SStefano Zampini     ierr = PetscSFBcastBegin(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
11124f1b2e48SStefano Zampini     ierr = PetscSFBcastEnd(pcbddc->benign_sf,MPIU_SCALAR,array,pcbddc->benign_p0);CHKERRQ(ierr);
1113efc2fbd9SStefano Zampini     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&array);CHKERRQ(ierr);
1114de9d7bd0SStefano Zampini   } else {
1115de9d7bd0SStefano Zampini     ierr = VecGetArray(v,&array);CHKERRQ(ierr);
1116de9d7bd0SStefano Zampini     ierr = PetscSFReduceBegin(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
1117de9d7bd0SStefano Zampini     ierr = PetscSFReduceEnd(pcbddc->benign_sf,MPIU_SCALAR,pcbddc->benign_p0,array,MPIU_REPLACE);CHKERRQ(ierr);
1118de9d7bd0SStefano Zampini     ierr = VecRestoreArray(v,&array);CHKERRQ(ierr);
1119efc2fbd9SStefano Zampini   }
1120efc2fbd9SStefano Zampini   PetscFunctionReturn(0);
1121efc2fbd9SStefano Zampini }
1122efc2fbd9SStefano Zampini 
1123efc2fbd9SStefano Zampini #undef __FUNCT__
1124c263805aSStefano Zampini #define __FUNCT__ "PCBDDCBenignPopOrPushB0"
1125c263805aSStefano Zampini PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop)
1126c263805aSStefano Zampini {
1127c263805aSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
1128c263805aSStefano Zampini   PetscErrorCode ierr;
1129c263805aSStefano Zampini 
1130c263805aSStefano Zampini   PetscFunctionBegin;
1131c263805aSStefano Zampini   /* TODO: add error checking
1132c263805aSStefano Zampini     - avoid nested pop (or push) calls.
1133c263805aSStefano Zampini     - cannot push before pop.
11341c604dc7SStefano Zampini     - cannot call this if pcbddc->local_mat is NULL
1135c263805aSStefano Zampini   */
11364f1b2e48SStefano Zampini   if (!pcbddc->benign_n) {
1137efc2fbd9SStefano Zampini     PetscFunctionReturn(0);
1138efc2fbd9SStefano Zampini   }
1139c263805aSStefano Zampini   if (pop) {
1140a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
11414f1b2e48SStefano Zampini       IS       is_p0;
11424f1b2e48SStefano Zampini       MatReuse reuse;
1143c263805aSStefano Zampini 
1144c263805aSStefano Zampini       /* extract B_0 */
11454f1b2e48SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
11464f1b2e48SStefano Zampini       if (pcbddc->benign_B0) {
11474f1b2e48SStefano Zampini         reuse = MAT_REUSE_MATRIX;
11484f1b2e48SStefano Zampini       }
11494f1b2e48SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->benign_n,pcbddc->benign_p0_lidx,PETSC_COPY_VALUES,&is_p0);CHKERRQ(ierr);
11504f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_p0,NULL,reuse,&pcbddc->benign_B0);CHKERRQ(ierr);
1151c263805aSStefano Zampini       /* remove rows and cols from local problem */
1152c263805aSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE);CHKERRQ(ierr);
115397d764eeSStefano Zampini       ierr = MatSetOption(pcbddc->local_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
11544f1b2e48SStefano Zampini       ierr = MatZeroRowsColumnsIS(pcbddc->local_mat,is_p0,1.0,NULL,NULL);CHKERRQ(ierr);
11554f1b2e48SStefano Zampini       ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
1156a3df083aSStefano Zampini     } else {
1157a3df083aSStefano Zampini       Mat_IS      *matis = (Mat_IS*)pc->pmat->data;
1158a3df083aSStefano Zampini       PetscScalar *vals;
1159a3df083aSStefano Zampini       PetscInt    i,n,*idxs_ins;
1160a3df083aSStefano Zampini 
1161a3df083aSStefano Zampini       ierr = VecGetLocalSize(matis->y,&n);CHKERRQ(ierr);
1162a3df083aSStefano Zampini       ierr = PetscMalloc2(n,&idxs_ins,n,&vals);CHKERRQ(ierr);
1163a3df083aSStefano Zampini       if (!pcbddc->benign_B0) {
11640b5adadeSStefano Zampini         PetscInt *nnz;
1165a3df083aSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat),&pcbddc->benign_B0);CHKERRQ(ierr);
1166a3df083aSStefano Zampini         ierr = MatSetType(pcbddc->benign_B0,MATAIJ);CHKERRQ(ierr);
1167a3df083aSStefano Zampini         ierr = MatSetSizes(pcbddc->benign_B0,pcbddc->benign_n,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1168331e053bSStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&nnz);CHKERRQ(ierr);
1169331e053bSStefano Zampini         for (i=0;i<pcbddc->benign_n;i++) {
1170331e053bSStefano Zampini           ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nnz[i]);CHKERRQ(ierr);
1171331e053bSStefano Zampini           nnz[i] = n - nnz[i];
1172331e053bSStefano Zampini         }
1173331e053bSStefano Zampini         ierr = MatSeqAIJSetPreallocation(pcbddc->benign_B0,0,nnz);CHKERRQ(ierr);
1174331e053bSStefano Zampini         ierr = PetscFree(nnz);CHKERRQ(ierr);
1175331e053bSStefano Zampini       }
1176a3df083aSStefano Zampini 
1177a3df083aSStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
1178a3df083aSStefano Zampini         PetscScalar *array;
1179a3df083aSStefano Zampini         PetscInt    *idxs,j,nz,cum;
1180a3df083aSStefano Zampini 
1181a3df083aSStefano Zampini         ierr = VecSet(matis->x,0.);CHKERRQ(ierr);
1182a3df083aSStefano Zampini         ierr = ISGetLocalSize(pcbddc->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
1183a3df083aSStefano Zampini         ierr = ISGetIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
1184a3df083aSStefano Zampini         for (j=0;j<nz;j++) vals[j] = 1.;
1185a3df083aSStefano Zampini         ierr = VecSetValues(matis->x,nz,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
1186a3df083aSStefano Zampini         ierr = VecAssemblyBegin(matis->x);CHKERRQ(ierr);
1187a3df083aSStefano Zampini         ierr = VecAssemblyEnd(matis->x);CHKERRQ(ierr);
1188a3df083aSStefano Zampini         ierr = VecSet(matis->y,0.);CHKERRQ(ierr);
1189a3df083aSStefano Zampini         ierr = MatMult(matis->A,matis->x,matis->y);CHKERRQ(ierr);
1190a3df083aSStefano Zampini         ierr = VecGetArray(matis->y,&array);CHKERRQ(ierr);
1191a3df083aSStefano Zampini         cum = 0;
1192a3df083aSStefano Zampini         for (j=0;j<n;j++) {
119322db5ddcSStefano Zampini           if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) {
1194a3df083aSStefano Zampini             vals[cum] = array[j];
1195a3df083aSStefano Zampini             idxs_ins[cum] = j;
1196a3df083aSStefano Zampini             cum++;
1197a3df083aSStefano Zampini           }
1198a3df083aSStefano Zampini         }
1199a3df083aSStefano Zampini         ierr = MatSetValues(pcbddc->benign_B0,1,&i,cum,idxs_ins,vals,INSERT_VALUES);CHKERRQ(ierr);
1200a3df083aSStefano Zampini         ierr = VecRestoreArray(matis->y,&array);CHKERRQ(ierr);
1201a3df083aSStefano Zampini         ierr = ISRestoreIndices(pcbddc->benign_zerodiag_subs[i],(const PetscInt**)&idxs);CHKERRQ(ierr);
1202a3df083aSStefano Zampini       }
1203a3df083aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1204a3df083aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->benign_B0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1205a3df083aSStefano Zampini       ierr = PetscFree2(idxs_ins,vals);CHKERRQ(ierr);
1206a3df083aSStefano Zampini     }
1207c263805aSStefano Zampini   } else { /* push */
1208a3df083aSStefano Zampini     if (pcbddc->benign_change_explicit) {
12094f1b2e48SStefano Zampini       PetscInt i;
12104f1b2e48SStefano Zampini 
12114f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
12124f1b2e48SStefano Zampini         PetscScalar *B0_vals;
12134f1b2e48SStefano Zampini         PetscInt    *B0_cols,B0_ncol;
12144f1b2e48SStefano Zampini 
12154f1b2e48SStefano Zampini         ierr = MatGetRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
12164f1b2e48SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,1,pcbddc->benign_p0_lidx+i,B0_ncol,B0_cols,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
12177b034428SStefano Zampini         ierr = MatSetValues(pcbddc->local_mat,B0_ncol,B0_cols,1,pcbddc->benign_p0_lidx+i,B0_vals,INSERT_VALUES);CHKERRQ(ierr);
12184f1b2e48SStefano Zampini         ierr = MatSetValue(pcbddc->local_mat,pcbddc->benign_p0_lidx[i],pcbddc->benign_p0_lidx[i],0.0,INSERT_VALUES);CHKERRQ(ierr);
12194f1b2e48SStefano Zampini         ierr = MatRestoreRow(pcbddc->benign_B0,i,&B0_ncol,(const PetscInt**)&B0_cols,(const PetscScalar**)&B0_vals);CHKERRQ(ierr);
12204f1b2e48SStefano Zampini       }
1221c263805aSStefano Zampini       ierr = MatAssemblyBegin(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1222c263805aSStefano Zampini       ierr = MatAssemblyEnd(pcbddc->local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1223a3df083aSStefano Zampini     } else {
1224a3df083aSStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot push B0!\n");
1225a3df083aSStefano Zampini     }
1226c263805aSStefano Zampini   }
1227c263805aSStefano Zampini   PetscFunctionReturn(0);
1228c263805aSStefano Zampini }
1229c263805aSStefano Zampini 
1230c263805aSStefano Zampini #undef __FUNCT__
1231b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
123208122e43SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc)
1233b1b3d7a2SStefano Zampini {
1234b1b3d7a2SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
123508122e43SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
123608122e43SStefano Zampini   PetscBLASInt    B_dummyint,B_neigs,B_ierr,B_lwork;
123708122e43SStefano Zampini   PetscBLASInt    *B_iwork,*B_ifail;
123808122e43SStefano Zampini   PetscScalar     *work,lwork;
123908122e43SStefano Zampini   PetscScalar     *St,*S,*eigv;
124008122e43SStefano Zampini   PetscScalar     *Sarray,*Starray;
124108122e43SStefano Zampini   PetscReal       *eigs,thresh;
12421b968477SStefano Zampini   PetscInt        i,nmax,nmin,nv,cum,mss,cum2,cumarray,maxneigs;
1243f6f667cfSStefano Zampini   PetscBool       allocated_S_St;
124408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
124508122e43SStefano Zampini   PetscReal       *rwork;
124608122e43SStefano Zampini #endif
1247b1b3d7a2SStefano Zampini   PetscErrorCode  ierr;
1248b1b3d7a2SStefano Zampini 
1249b1b3d7a2SStefano Zampini   PetscFunctionBegin;
1250b334f244SStefano Zampini   if (!sub_schurs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Adaptive selection of constraints requires SubSchurs data");
1251af25d912SStefano Zampini   if (!sub_schurs->schur_explicit) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO");
1252af25d912SStefano 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);
125306a4e24aSStefano Zampini 
1254fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
1255fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1256fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1257fd14bc51SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check adaptive selection of constraints\n");CHKERRQ(ierr);
12581575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
1259fd14bc51SStefano Zampini   }
1260fd14bc51SStefano Zampini 
1261e496cd5dSStefano Zampini   if (pcbddc->dbg_flag) {
1262e496cd5dSStefano 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);
1263e496cd5dSStefano Zampini   }
1264e496cd5dSStefano Zampini 
126508122e43SStefano Zampini   /* max size of subsets */
126608122e43SStefano Zampini   mss = 0;
126708122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
126808122e43SStefano Zampini     PetscInt subset_size;
1269862806e4SStefano Zampini 
127008122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
127108122e43SStefano Zampini     mss = PetscMax(mss,subset_size);
127208122e43SStefano Zampini   }
127308122e43SStefano Zampini 
127408122e43SStefano Zampini   /* min/max and threshold */
127508122e43SStefano Zampini   nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss;
1276f6f667cfSStefano Zampini   nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0;
127708122e43SStefano Zampini   nmax = PetscMax(nmin,nmax);
1278f6f667cfSStefano Zampini   allocated_S_St = PETSC_FALSE;
1279f6f667cfSStefano Zampini   if (nmin) {
1280f6f667cfSStefano Zampini     allocated_S_St = PETSC_TRUE;
1281f6f667cfSStefano Zampini   }
128208122e43SStefano Zampini 
128308122e43SStefano Zampini   /* allocate lapack workspace */
128408122e43SStefano Zampini   cum = cum2 = 0;
128508122e43SStefano Zampini   maxneigs = 0;
128608122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
128708122e43SStefano Zampini     PetscInt n,subset_size;
1288f6f667cfSStefano Zampini 
128908122e43SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
129008122e43SStefano Zampini     n = PetscMin(subset_size,nmax);
12919162d606SStefano Zampini     cum += subset_size;
12929162d606SStefano Zampini     cum2 += subset_size*n;
129308122e43SStefano Zampini     maxneigs = PetscMax(maxneigs,n);
129408122e43SStefano Zampini   }
129508122e43SStefano Zampini   if (mss) {
12969ab7bb16SStefano Zampini     if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
129708122e43SStefano Zampini       PetscBLASInt B_itype = 1;
129808122e43SStefano Zampini       PetscBLASInt B_N = mss;
12994c6709b3SStefano Zampini       PetscReal    zero = 0.0;
13004c6709b3SStefano Zampini       PetscReal    eps = 0.0; /* dlamch? */
130108122e43SStefano Zampini 
130208122e43SStefano Zampini       B_lwork = -1;
130308122e43SStefano Zampini       S = NULL;
130408122e43SStefano Zampini       St = NULL;
1305a58a30b4SStefano Zampini       eigs = NULL;
1306a58a30b4SStefano Zampini       eigv = NULL;
1307a58a30b4SStefano Zampini       B_iwork = NULL;
1308a58a30b4SStefano Zampini       B_ifail = NULL;
1309d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1310d1710679SStefano Zampini       rwork = NULL;
1311d1710679SStefano Zampini #endif
13128bec7fa6SStefano Zampini       thresh = 1.0;
131308122e43SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
131408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
131508122e43SStefano 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));
131608122e43SStefano Zampini #else
131708122e43SStefano 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));
131808122e43SStefano Zampini #endif
131908122e43SStefano Zampini       if (B_ierr != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYGVX Lapack routine %d",(int)B_ierr);
132008122e43SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
132108122e43SStefano Zampini     } else {
132208122e43SStefano Zampini         /* TODO */
132308122e43SStefano Zampini     }
132408122e43SStefano Zampini   } else {
132508122e43SStefano Zampini     lwork = 0;
132608122e43SStefano Zampini   }
132708122e43SStefano Zampini 
132808122e43SStefano Zampini   nv = 0;
1329d62866d3SStefano 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) */
1330d62866d3SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_vertices,&nv);CHKERRQ(ierr);
133108122e43SStefano Zampini   }
13324c6709b3SStefano Zampini   ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lwork),&B_lwork);CHKERRQ(ierr);
1333f6f667cfSStefano Zampini   if (allocated_S_St) {
1334f6f667cfSStefano Zampini     ierr = PetscMalloc2(mss*mss,&S,mss*mss,&St);CHKERRQ(ierr);
1335f6f667cfSStefano Zampini   }
1336f6f667cfSStefano Zampini   ierr = PetscMalloc5(mss*mss,&eigv,mss,&eigs,B_lwork,&work,5*mss,&B_iwork,mss,&B_ifail);CHKERRQ(ierr);
133708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
133808122e43SStefano Zampini   ierr = PetscMalloc1(7*mss,&rwork);CHKERRQ(ierr);
133908122e43SStefano Zampini #endif
13409162d606SStefano Zampini   ierr = PetscMalloc5(nv+sub_schurs->n_subs,&pcbddc->adaptive_constraints_n,
13419162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_idxs_ptr,
13429162d606SStefano Zampini                       nv+sub_schurs->n_subs+1,&pcbddc->adaptive_constraints_data_ptr,
134308122e43SStefano Zampini                       nv+cum,&pcbddc->adaptive_constraints_idxs,
13449162d606SStefano Zampini                       nv+cum2,&pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
134508122e43SStefano Zampini   ierr = PetscMemzero(pcbddc->adaptive_constraints_n,(nv+sub_schurs->n_subs)*sizeof(PetscInt));CHKERRQ(ierr);
134608122e43SStefano Zampini 
134708122e43SStefano Zampini   maxneigs = 0;
134872b8c272SStefano Zampini   cum = cumarray = 0;
13499162d606SStefano Zampini   pcbddc->adaptive_constraints_idxs_ptr[0] = 0;
13509162d606SStefano Zampini   pcbddc->adaptive_constraints_data_ptr[0] = 0;
1351d62866d3SStefano Zampini   if (sub_schurs->is_vertices && pcbddc->use_vertices) {
135208122e43SStefano Zampini     const PetscInt *idxs;
135308122e43SStefano Zampini 
1354d62866d3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
135508122e43SStefano Zampini     for (cum=0;cum<nv;cum++) {
135608122e43SStefano Zampini       pcbddc->adaptive_constraints_n[cum] = 1;
135708122e43SStefano Zampini       pcbddc->adaptive_constraints_idxs[cum] = idxs[cum];
135808122e43SStefano Zampini       pcbddc->adaptive_constraints_data[cum] = 1.0;
13599162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum]+1;
13609162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum]+1;
136108122e43SStefano Zampini     }
1362d62866d3SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
136308122e43SStefano Zampini   }
136408122e43SStefano Zampini 
136508122e43SStefano Zampini   if (mss) { /* multilevel */
136608122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
136708122e43SStefano Zampini     ierr = MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
136808122e43SStefano Zampini   }
136908122e43SStefano Zampini 
1370ffd830a3SStefano Zampini   thresh = pcbddc->adaptive_threshold;
137108122e43SStefano Zampini   for (i=0;i<sub_schurs->n_subs;i++) {
137208122e43SStefano Zampini     const PetscInt *idxs;
13739d54b7f4SStefano Zampini     PetscReal      upper,lower;
1374862806e4SStefano Zampini     PetscInt       j,subset_size,eigs_start = 0;
137508122e43SStefano Zampini     PetscBLASInt   B_N;
1376aff50787SStefano Zampini     PetscBool      same_data = PETSC_FALSE;
137708122e43SStefano Zampini 
13789d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
13799d54b7f4SStefano Zampini       upper = PETSC_MAX_REAL;
13809d54b7f4SStefano Zampini       lower = thresh;
13819d54b7f4SStefano Zampini     } else {
13829d54b7f4SStefano Zampini       upper = 1./thresh;
13839d54b7f4SStefano Zampini       lower = 0.;
13849d54b7f4SStefano Zampini     }
1385862806e4SStefano Zampini     ierr = ISGetLocalSize(sub_schurs->is_subs[i],&subset_size);CHKERRQ(ierr);
1386ffd830a3SStefano Zampini     ierr = ISGetIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
1387f6f667cfSStefano Zampini     ierr = PetscBLASIntCast(subset_size,&B_N);CHKERRQ(ierr);
1388f6f667cfSStefano Zampini     if (allocated_S_St) { /* S and S_t should be copied since we could need them later */
13899ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian) {
1390aff50787SStefano Zampini         PetscInt j,k;
1391aff50787SStefano Zampini         if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscMemcmp later */
1392aff50787SStefano Zampini           ierr = PetscMemzero(S,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
1393aff50787SStefano Zampini           ierr = PetscMemzero(St,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
139408122e43SStefano Zampini         }
139508122e43SStefano Zampini         for (j=0;j<subset_size;j++) {
1396aff50787SStefano Zampini           for (k=j;k<subset_size;k++) {
1397aff50787SStefano Zampini             S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
1398aff50787SStefano Zampini             St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
1399aff50787SStefano Zampini           }
140008122e43SStefano Zampini         }
140108122e43SStefano Zampini       } else {
140208122e43SStefano Zampini         ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
140308122e43SStefano Zampini         ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
140408122e43SStefano Zampini       }
14058bec7fa6SStefano Zampini     } else {
1406f6f667cfSStefano Zampini       S = Sarray + cumarray;
1407f6f667cfSStefano Zampini       St = Starray + cumarray;
14088bec7fa6SStefano Zampini     }
1409aff50787SStefano Zampini     /* see if we can save some work */
1410b7ab4a40SStefano Zampini     if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) {
1411aff50787SStefano Zampini       ierr = PetscMemcmp(S,St,subset_size*subset_size*sizeof(PetscScalar),&same_data);CHKERRQ(ierr);
1412aff50787SStefano Zampini     }
1413aff50787SStefano Zampini 
1414b7ab4a40SStefano Zampini     if (same_data && !sub_schurs->change) { /* there's no need of constraints here */
1415aff50787SStefano Zampini       B_neigs = 0;
1416aff50787SStefano Zampini     } else {
14179ab7bb16SStefano Zampini       if (sub_schurs->is_hermitian && sub_schurs->is_posdef) {
141808122e43SStefano Zampini         PetscBLASInt B_itype = 1;
1419f6f667cfSStefano Zampini         PetscBLASInt B_IL, B_IU;
14204c6709b3SStefano Zampini         PetscReal    eps = -1.0; /* dlamch? */
14219552c7c7SStefano Zampini         PetscInt     nmin_s;
1422b7ab4a40SStefano Zampini         PetscBool    compute_range = PETSC_FALSE;
142308122e43SStefano Zampini 
1424fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
14258bec7fa6SStefano 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]]);
1426fd14bc51SStefano Zampini         }
1427d16cbb6bSStefano Zampini 
1428b7ab4a40SStefano Zampini         compute_range = PETSC_FALSE;
1429b7ab4a40SStefano Zampini         if (thresh > 1.+PETSC_SMALL && !same_data) {
1430b7ab4a40SStefano Zampini           compute_range = PETSC_TRUE;
1431b7ab4a40SStefano Zampini         }
1432b7ab4a40SStefano Zampini 
143308122e43SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1434b7ab4a40SStefano Zampini         if (compute_range) {
1435d16cbb6bSStefano Zampini 
1436d16cbb6bSStefano Zampini           /* ask for eigenvalues larger than thresh */
143708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
14389d54b7f4SStefano 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));
143908122e43SStefano Zampini #else
14409d54b7f4SStefano 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));
144108122e43SStefano Zampini #endif
1442b7ab4a40SStefano Zampini         } else if (!same_data) {
1443d16cbb6bSStefano Zampini           B_IU = PetscMax(1,PetscMin(B_N,nmax));
1444d16cbb6bSStefano Zampini           B_IL = 1;
1445d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX)
14469d54b7f4SStefano 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));
1447d16cbb6bSStefano Zampini #else
14489d54b7f4SStefano 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));
1449d16cbb6bSStefano Zampini #endif
1450b7ab4a40SStefano Zampini         } else { /* same_data is true, so get the adaptive function requested by the user */
1451b7ab4a40SStefano Zampini           PetscInt k;
1452b7ab4a40SStefano Zampini           if (!sub_schurs->change_primal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
1453b7ab4a40SStefano Zampini           ierr = ISGetLocalSize(sub_schurs->change_primal_sub[i],&nmax);CHKERRQ(ierr);
1454b7ab4a40SStefano Zampini           ierr = PetscBLASIntCast(nmax,&B_neigs);CHKERRQ(ierr);
1455b7ab4a40SStefano Zampini           nmin = nmax;
1456b7ab4a40SStefano Zampini           ierr = PetscMemzero(eigv,subset_size*nmax*sizeof(PetscScalar));CHKERRQ(ierr);
1457b7ab4a40SStefano Zampini           for (k=0;k<nmax;k++) {
1458b7ab4a40SStefano Zampini             eigs[k] = 1./PETSC_SMALL;
1459b7ab4a40SStefano Zampini             eigv[k*(subset_size+1)] = 1.0;
1460b7ab4a40SStefano Zampini           }
1461d16cbb6bSStefano Zampini         }
146208122e43SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
146308122e43SStefano Zampini         if (B_ierr) {
14646c4ed002SBarry 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);
14656c4ed002SBarry 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);
14666c4ed002SBarry 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);
146708122e43SStefano Zampini         }
146808122e43SStefano Zampini 
146908122e43SStefano Zampini         if (B_neigs > nmax) {
1470fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
1471fd14bc51SStefano Zampini             PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   found %d eigs, more than maximum required %d.\n",B_neigs,nmax);
1472fd14bc51SStefano Zampini           }
14739d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) eigs_start = B_neigs -nmax;
147408122e43SStefano Zampini           B_neigs = nmax;
147508122e43SStefano Zampini         }
147608122e43SStefano Zampini 
14779552c7c7SStefano Zampini         nmin_s = PetscMin(nmin,B_N);
14789552c7c7SStefano Zampini         if (B_neigs < nmin_s) {
147908122e43SStefano Zampini           PetscBLASInt B_neigs2;
148008122e43SStefano Zampini 
14819d54b7f4SStefano Zampini           if (pcbddc->use_deluxe_scaling) {
1482f6f667cfSStefano Zampini             B_IL = B_N - nmin_s + 1;
14839d54b7f4SStefano Zampini             B_IU = B_N - B_neigs;
14849d54b7f4SStefano Zampini           } else {
14859d54b7f4SStefano Zampini             B_IL = B_neigs + 1;
14869d54b7f4SStefano Zampini             B_IU = nmin_s;
14879d54b7f4SStefano Zampini           }
1488fd14bc51SStefano Zampini           if (pcbddc->dbg_flag) {
1489fd14bc51SStefano 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);
1490fd14bc51SStefano Zampini           }
14919ab7bb16SStefano Zampini           if (sub_schurs->is_hermitian) {
14921ae86dd6SStefano Zampini             PetscInt j,k;
149308122e43SStefano Zampini             for (j=0;j<subset_size;j++) {
14941ae86dd6SStefano Zampini               for (k=j;k<subset_size;k++) {
14951ae86dd6SStefano Zampini                 S [j*subset_size+k] = Sarray [cumarray+j*subset_size+k];
14961ae86dd6SStefano Zampini                 St[j*subset_size+k] = Starray[cumarray+j*subset_size+k];
149708122e43SStefano Zampini               }
149808122e43SStefano Zampini             }
149908122e43SStefano Zampini           } else {
150008122e43SStefano Zampini             ierr = PetscMemcpy(S,Sarray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
150108122e43SStefano Zampini             ierr = PetscMemcpy(St,Starray+cumarray,subset_size*subset_size*sizeof(PetscScalar));CHKERRQ(ierr);
150208122e43SStefano Zampini           }
150308122e43SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
150408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
15059d54b7f4SStefano 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));
150608122e43SStefano Zampini #else
15079d54b7f4SStefano 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));
150808122e43SStefano Zampini #endif
150908122e43SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
151008122e43SStefano Zampini           B_neigs += B_neigs2;
151108122e43SStefano Zampini         }
151208122e43SStefano Zampini         if (B_ierr) {
15136c4ed002SBarry 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);
15146c4ed002SBarry 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);
15156c4ed002SBarry 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);
151608122e43SStefano Zampini         }
1517fd14bc51SStefano Zampini         if (pcbddc->dbg_flag) {
1518ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Got %d eigs\n",B_neigs);CHKERRQ(ierr);
151908122e43SStefano Zampini           for (j=0;j<B_neigs;j++) {
152008122e43SStefano Zampini             if (eigs[j] == 0.0) {
1521ac47001eSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     Inf\n");CHKERRQ(ierr);
152208122e43SStefano Zampini             } else {
15239d54b7f4SStefano Zampini               if (pcbddc->use_deluxe_scaling) {
1524ac47001eSStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",eigs[j+eigs_start]);CHKERRQ(ierr);
15259d54b7f4SStefano Zampini               } else {
15269d54b7f4SStefano Zampini                 ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"     %1.6e\n",1./eigs[j+eigs_start]);CHKERRQ(ierr);
15279d54b7f4SStefano Zampini               }
1528fd14bc51SStefano Zampini             }
152908122e43SStefano Zampini           }
153008122e43SStefano Zampini         }
153108122e43SStefano Zampini       } else {
153208122e43SStefano Zampini           /* TODO */
153308122e43SStefano Zampini       }
1534aff50787SStefano Zampini     }
15356c3e6151SStefano Zampini     /* change the basis back to the original one */
15366c3e6151SStefano Zampini     if (sub_schurs->change) {
153772b8c272SStefano Zampini       Mat change,phi,phit;
15386c3e6151SStefano Zampini 
15396c3e6151SStefano Zampini       if (pcbddc->dbg_flag > 1) {
15406c3e6151SStefano Zampini         PetscInt ii;
15416c3e6151SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
15426c3e6151SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector (old basis) %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
15436c3e6151SStefano Zampini           for (j=0;j<B_N;j++) {
15446c3e6151SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e\n",eigv[(ii+eigs_start)*subset_size+j]);CHKERRQ(ierr);
15456c3e6151SStefano Zampini           }
15466c3e6151SStefano Zampini         }
15476c3e6151SStefano Zampini       }
154872b8c272SStefano Zampini       ierr = KSPGetOperators(sub_schurs->change[i],&change,NULL);CHKERRQ(ierr);
15496c3e6151SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,subset_size,B_neigs,eigv+eigs_start*subset_size,&phit);CHKERRQ(ierr);
155072b8c272SStefano Zampini       ierr = MatMatMult(change,phit,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&phi);CHKERRQ(ierr);
15516c3e6151SStefano Zampini       ierr = MatCopy(phi,phit,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
15526c3e6151SStefano Zampini       ierr = MatDestroy(&phit);CHKERRQ(ierr);
15536c3e6151SStefano Zampini       ierr = MatDestroy(&phi);CHKERRQ(ierr);
15546c3e6151SStefano Zampini     }
15558bec7fa6SStefano Zampini     maxneigs = PetscMax(B_neigs,maxneigs);
15568bec7fa6SStefano Zampini     pcbddc->adaptive_constraints_n[i+nv] = B_neigs;
15579162d606SStefano Zampini     if (B_neigs) {
15589162d606SStefano 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);
1559fd14bc51SStefano Zampini 
1560fd14bc51SStefano Zampini       if (pcbddc->dbg_flag > 1) {
15619552c7c7SStefano Zampini         PetscInt ii;
15629552c7c7SStefano Zampini         for (ii=0;ii<B_neigs;ii++) {
1563ac47001eSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"   -> Eigenvector %d/%d (%d)\n",ii,B_neigs,B_N);CHKERRQ(ierr);
15649552c7c7SStefano Zampini           for (j=0;j<B_N;j++) {
1565ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX)
1566ac47001eSStefano Zampini             PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
1567ac47001eSStefano Zampini             PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii*subset_size+j+pcbddc->adaptive_constraints_data_ptr[cum]]);
1568ac47001eSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"       %1.4e + %1.4e i\n",r,c);CHKERRQ(ierr);
1569ac47001eSStefano Zampini #else
1570ac47001eSStefano 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);
1571ac47001eSStefano Zampini #endif
15729552c7c7SStefano Zampini           }
15739552c7c7SStefano Zampini         }
1574fd14bc51SStefano Zampini       }
15759162d606SStefano Zampini       ierr = PetscMemcpy(pcbddc->adaptive_constraints_idxs+pcbddc->adaptive_constraints_idxs_ptr[cum],idxs,subset_size*sizeof(PetscInt));CHKERRQ(ierr);
15769162d606SStefano Zampini       pcbddc->adaptive_constraints_idxs_ptr[cum+1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size;
15779162d606SStefano Zampini       pcbddc->adaptive_constraints_data_ptr[cum+1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size*B_neigs;
15789162d606SStefano Zampini       cum++;
157908122e43SStefano Zampini     }
158008122e43SStefano Zampini     ierr = ISRestoreIndices(sub_schurs->is_subs[i],&idxs);CHKERRQ(ierr);
158108122e43SStefano Zampini     /* shift for next computation */
158208122e43SStefano Zampini     cumarray += subset_size*subset_size;
158308122e43SStefano Zampini   }
1584fd14bc51SStefano Zampini   if (pcbddc->dbg_flag) {
1585fd14bc51SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1586fd14bc51SStefano Zampini   }
158708122e43SStefano Zampini 
158808122e43SStefano Zampini   if (mss) {
158908122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all,&Sarray);CHKERRQ(ierr);
159008122e43SStefano Zampini     ierr = MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all,&Starray);CHKERRQ(ierr);
1591f6f667cfSStefano Zampini     /* destroy matrices (junk) */
1592f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_inv_all);CHKERRQ(ierr);
1593f6f667cfSStefano Zampini     ierr = MatDestroy(&sub_schurs->sum_S_Ej_tilda_all);CHKERRQ(ierr);
159408122e43SStefano Zampini   }
1595f6f667cfSStefano Zampini   if (allocated_S_St) {
1596f6f667cfSStefano Zampini     ierr = PetscFree2(S,St);CHKERRQ(ierr);
1597f6f667cfSStefano Zampini   }
1598f6f667cfSStefano Zampini   ierr = PetscFree5(eigv,eigs,work,B_iwork,B_ifail);CHKERRQ(ierr);
159908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX)
160008122e43SStefano Zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
160108122e43SStefano Zampini #endif
160208122e43SStefano Zampini   if (pcbddc->dbg_flag) {
16031b968477SStefano Zampini     PetscInt maxneigs_r;
1604b2566f29SBarry Smith     ierr = MPIU_Allreduce(&maxneigs,&maxneigs_r,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
16059b28b941SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of constraints per cc %d\n",maxneigs_r);CHKERRQ(ierr);
160608122e43SStefano Zampini   }
160708122e43SStefano Zampini   PetscFunctionReturn(0);
160808122e43SStefano Zampini }
1609b1b3d7a2SStefano Zampini 
1610674ae819SStefano Zampini #undef __FUNCT__
1611c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
1612c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
1613c8587f34SStefano Zampini {
16148629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
1615c8587f34SStefano Zampini   PetscErrorCode ierr;
1616c8587f34SStefano Zampini 
1617c8587f34SStefano Zampini   PetscFunctionBegin;
1618f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
16195e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
1620c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
1621c8587f34SStefano Zampini 
1622684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
16230fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
1624684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
1625c8587f34SStefano Zampini 
16268629588bSStefano Zampini   /*
16278629588bSStefano Zampini      Setup local correction and local part of coarse basis.
16288629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
16298629588bSStefano Zampini   */
163047f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
16318629588bSStefano Zampini 
16328629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
16338629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
16348629588bSStefano Zampini 
16358629588bSStefano Zampini   /* free */
16368629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
1637c8587f34SStefano Zampini   PetscFunctionReturn(0);
1638c8587f34SStefano Zampini }
1639c8587f34SStefano Zampini 
1640c8587f34SStefano Zampini #undef __FUNCT__
1641674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
1642674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
1643674ae819SStefano Zampini {
1644674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1645674ae819SStefano Zampini   PetscErrorCode ierr;
1646674ae819SStefano Zampini 
1647674ae819SStefano Zampini   PetscFunctionBegin;
1648674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
1649674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
165030368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
1651674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
1652785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
1653674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
1654f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
1655f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
1656785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
165763602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
165863602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
1659674ae819SStefano Zampini   PetscFunctionReturn(0);
1660674ae819SStefano Zampini }
1661674ae819SStefano Zampini 
1662674ae819SStefano Zampini #undef __FUNCT__
1663674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
1664674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
1665674ae819SStefano Zampini {
1666674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
16674f1b2e48SStefano Zampini   PetscInt       i;
1668674ae819SStefano Zampini   PetscErrorCode ierr;
1669674ae819SStefano Zampini 
1670674ae819SStefano Zampini   PetscFunctionBegin;
1671b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
1672674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
167316909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
16741dd7afcfSStefano Zampini   ierr = VecDestroy(&pcbddc->work_change);CHKERRQ(ierr);
1675674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
1676669cc0f4SStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
1677*fa23a32eSStefano Zampini   ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
1678674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
16794f1b2e48SStefano Zampini   for (i=0;i<pcbddc->n_local_subs;i++) {
16804f1b2e48SStefano Zampini     ierr = ISDestroy(&pcbddc->local_subs[i]);CHKERRQ(ierr);
16814f1b2e48SStefano Zampini   }
16824f1b2e48SStefano Zampini   ierr = PetscFree(pcbddc->local_subs);CHKERRQ(ierr);
1683b334f244SStefano Zampini   if (pcbddc->sub_schurs) {
1684b96c3477SStefano Zampini     ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
1685b334f244SStefano Zampini   }
1686674ae819SStefano Zampini   PetscFunctionReturn(0);
1687674ae819SStefano Zampini }
1688674ae819SStefano Zampini 
1689674ae819SStefano Zampini #undef __FUNCT__
1690674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
1691674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
1692674ae819SStefano Zampini {
1693674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1694674ae819SStefano Zampini   PetscErrorCode ierr;
1695674ae819SStefano Zampini 
1696674ae819SStefano Zampini   PetscFunctionBegin;
1697674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
169858da7f69SStefano Zampini   if (pcbddc->coarse_phi_B) {
1699ca92afb2SStefano Zampini     PetscScalar *array;
170006656605SStefano Zampini     ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&array);CHKERRQ(ierr);
170106656605SStefano Zampini     ierr = PetscFree(array);CHKERRQ(ierr);
170258da7f69SStefano Zampini   }
1703674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
1704674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
170515aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
170615aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
1707674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
1708674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
1709674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
171006656605SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
1711674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
1712674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
17138ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
1714674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
1715674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
1716674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
1717f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
1718f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
1719f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
1720f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
1721727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
17220e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
1723f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
172470cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
172581d14e9dSStefano Zampini   ierr = MatDestroy(&pcbddc->benign_change);CHKERRQ(ierr);
17260369aaf7SStefano Zampini   ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
17271dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
17284f1b2e48SStefano Zampini   ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
17298b9f24d4SStefano Zampini   ierr = PetscSFDestroy(&pcbddc->benign_sf);CHKERRQ(ierr);
1730ca92afb2SStefano Zampini   if (pcbddc->benign_zerodiag_subs) {
1731ca92afb2SStefano Zampini     PetscInt i;
1732ca92afb2SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
1733ca92afb2SStefano Zampini       ierr = ISDestroy(&pcbddc->benign_zerodiag_subs[i]);CHKERRQ(ierr);
1734ca92afb2SStefano Zampini     }
1735ca92afb2SStefano Zampini     ierr = PetscFree(pcbddc->benign_zerodiag_subs);CHKERRQ(ierr);
1736ca92afb2SStefano Zampini   }
17374f1b2e48SStefano Zampini   ierr = PetscFree3(pcbddc->benign_p0_lidx,pcbddc->benign_p0_gidx,pcbddc->benign_p0);CHKERRQ(ierr);
1738674ae819SStefano Zampini   PetscFunctionReturn(0);
1739674ae819SStefano Zampini }
1740674ae819SStefano Zampini 
1741674ae819SStefano Zampini #undef __FUNCT__
1742f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
1743f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
17446bfb1811SStefano Zampini {
17456bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
17466bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
17476bfb1811SStefano Zampini   VecType        impVecType;
17484f1b2e48SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
17496bfb1811SStefano Zampini   PetscErrorCode ierr;
17506bfb1811SStefano Zampini 
17516bfb1811SStefano Zampini   PetscFunctionBegin;
17526c4ed002SBarry Smith   if (!pcbddc->ConstraintMatrix) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
1753e7b262bdSStefano Zampini   /* get sizes */
17544f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices;
1755b371cd4fSStefano Zampini   n_R = pcis->n - pcbddc->n_vertices;
17566bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
1757e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
1758e7b262bdSStefano Zampini   /* R nodes */
1759e7b262bdSStefano Zampini   old_size = -1;
1760e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
1761e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
1762e7b262bdSStefano Zampini   }
1763e7b262bdSStefano Zampini   if (n_R != old_size) {
1764e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
1765e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
17666bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
17676bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
17686bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
17696bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
1770e7b262bdSStefano Zampini   }
1771e7b262bdSStefano Zampini   /* local primal dofs */
1772e7b262bdSStefano Zampini   old_size = -1;
1773e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
1774e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
1775e7b262bdSStefano Zampini   }
1776e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
1777e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
177883b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
1779e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
17806bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
1781e7b262bdSStefano Zampini   }
1782e7b262bdSStefano Zampini   /* local explicit constraints */
1783e7b262bdSStefano Zampini   old_size = -1;
1784e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
1785e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
1786e7b262bdSStefano Zampini   }
1787e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
1788e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
178983b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
179083b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
179183b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
179283b7ccabSStefano Zampini   }
17936bfb1811SStefano Zampini   PetscFunctionReturn(0);
17946bfb1811SStefano Zampini }
17956bfb1811SStefano Zampini 
17966bfb1811SStefano Zampini #undef __FUNCT__
179747f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
179847f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
179988ebb749SStefano Zampini {
180025084f0cSStefano Zampini   PetscErrorCode  ierr;
180125084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
180288ebb749SStefano Zampini   PC_IS*          pcis = (PC_IS*)pc->data;
180388ebb749SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1804d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
180525084f0cSStefano Zampini   /* submatrices of local problem */
180680677318SStefano Zampini   Mat             A_RV,A_VR,A_VV,local_auxmat2_R;
180706656605SStefano Zampini   /* submatrices of local coarse problem */
180806656605SStefano Zampini   Mat             S_VV,S_CV,S_VC,S_CC;
180925084f0cSStefano Zampini   /* working matrices */
181006656605SStefano Zampini   Mat             C_CR;
181125084f0cSStefano Zampini   /* additional working stuff */
181206656605SStefano Zampini   PC              pc_R;
18134f1b2e48SStefano Zampini   Mat             F;
18145cbda25cSStefano Zampini   Vec             dummy_vec;
1815a3df083aSStefano Zampini   PetscBool       isLU,isCHOL,isILU,need_benign_correction;
181625084f0cSStefano Zampini   PetscScalar     *coarse_submat_vals; /* TODO: use a PETSc matrix */
181706656605SStefano Zampini   PetscScalar     *work;
181806656605SStefano Zampini   PetscInt        *idx_V_B;
1819ffd830a3SStefano Zampini   PetscInt        lda_rhs,n,n_vertices,n_constraints,*p0_lidx_I;
182006656605SStefano Zampini   PetscInt        i,n_R,n_D,n_B;
1821ffd830a3SStefano Zampini 
182225084f0cSStefano Zampini   /* some shortcuts to scalars */
182306656605SStefano Zampini   PetscScalar     one=1.0,m_one=-1.0;
182488ebb749SStefano Zampini 
182588ebb749SStefano Zampini   PetscFunctionBegin;
1826ffd830a3SStefano Zampini   if (!pcbddc->symmetric_primal && pcbddc->benign_n) {
1827ffd830a3SStefano Zampini     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Non-symmetric primal basis computation with benign trick not yet implemented");
1828ffd830a3SStefano Zampini   }
1829ffd830a3SStefano Zampini 
1830ffd830a3SStefano Zampini   /* Set Non-overlapping dimensions */
1831b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
18324f1b2e48SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices;
1833b371cd4fSStefano Zampini   n_B = pcis->n_B;
1834b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
183588ebb749SStefano Zampini   n_R = pcis->n - n_vertices;
183688ebb749SStefano Zampini 
183788ebb749SStefano Zampini   /* vertices in boundary numbering */
1838785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
18390e6343abSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->local_primal_ref_node,&i,idx_V_B);CHKERRQ(ierr);
18406c4ed002SBarry 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);
184188ebb749SStefano Zampini 
184206656605SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
1843019a44ceSStefano Zampini   ierr = PetscCalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
184406656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_vertices,coarse_submat_vals,&S_VV);CHKERRQ(ierr);
184506656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VV,pcbddc->local_primal_size);CHKERRQ(ierr);
184606656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_vertices,coarse_submat_vals+n_vertices,&S_CV);CHKERRQ(ierr);
184706656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CV,pcbddc->local_primal_size);CHKERRQ(ierr);
184806656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_vertices,n_constraints,coarse_submat_vals+pcbddc->local_primal_size*n_vertices,&S_VC);CHKERRQ(ierr);
184906656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_VC,pcbddc->local_primal_size);CHKERRQ(ierr);
185006656605SStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_constraints,n_constraints,coarse_submat_vals+(pcbddc->local_primal_size+1)*n_vertices,&S_CC);CHKERRQ(ierr);
185106656605SStefano Zampini   ierr = MatSeqDenseSetLDA(S_CC,pcbddc->local_primal_size);CHKERRQ(ierr);
185206656605SStefano Zampini 
185306656605SStefano Zampini   /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */
185406656605SStefano Zampini   ierr = KSPGetPC(pcbddc->ksp_R,&pc_R);CHKERRQ(ierr);
185506656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCLU,&isLU);CHKERRQ(ierr);
185606656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCILU,&isILU);CHKERRQ(ierr);
185706656605SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc_R,PCCHOLESKY,&isCHOL);CHKERRQ(ierr);
1858ffd830a3SStefano Zampini   lda_rhs = n_R;
1859a3df083aSStefano Zampini   need_benign_correction = PETSC_FALSE;
186006656605SStefano Zampini   if (isLU || isILU || isCHOL) {
186106656605SStefano Zampini     ierr = PCFactorGetMatrix(pc_R,&F);CHKERRQ(ierr);
1862b334f244SStefano Zampini   } else if (sub_schurs && sub_schurs->reuse_solver) {
1863df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1864d62866d3SStefano Zampini     MatFactorType      type;
1865d62866d3SStefano Zampini 
1866df4d28bfSStefano Zampini     F = reuse_solver->F;
18676816873aSStefano Zampini     ierr = MatGetFactorType(F,&type);CHKERRQ(ierr);
1868d62866d3SStefano Zampini     if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE;
1869ffd830a3SStefano Zampini     ierr = MatGetSize(F,&lda_rhs,NULL);CHKERRQ(ierr);
187022db5ddcSStefano Zampini     need_benign_correction = (PetscBool)(!!reuse_solver->benign_n);
187106656605SStefano Zampini   } else {
187206656605SStefano Zampini     F = NULL;
187306656605SStefano Zampini   }
187406656605SStefano Zampini 
1875ffd830a3SStefano Zampini   /* allocate workspace */
1876ffd830a3SStefano Zampini   n = 0;
1877ffd830a3SStefano Zampini   if (n_constraints) {
1878ffd830a3SStefano Zampini     n += lda_rhs*n_constraints;
1879ffd830a3SStefano Zampini   }
1880ffd830a3SStefano Zampini   if (n_vertices) {
1881ffd830a3SStefano Zampini     n = PetscMax(2*lda_rhs*n_vertices,n);
1882ffd830a3SStefano Zampini     n = PetscMax((lda_rhs+n_B)*n_vertices,n);
1883ffd830a3SStefano Zampini   }
1884ffd830a3SStefano Zampini   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
1885ffd830a3SStefano Zampini 
18865cbda25cSStefano Zampini   /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */
18875cbda25cSStefano Zampini   dummy_vec = NULL;
18885cbda25cSStefano Zampini   if (need_benign_correction && lda_rhs != n_R && F) {
18895cbda25cSStefano Zampini     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,lda_rhs,work,&dummy_vec);CHKERRQ(ierr);
18905cbda25cSStefano Zampini   }
18915cbda25cSStefano Zampini 
189288ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
189388ebb749SStefano Zampini   if (n_constraints) {
189472b8c272SStefano Zampini     Mat         M1,M2,M3,C_B;
189506656605SStefano Zampini     IS          is_aux;
189680677318SStefano Zampini     PetscScalar *array,*array2;
189706656605SStefano Zampini 
1898f4ddd8eeSStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
189980677318SStefano Zampini     ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
190088ebb749SStefano Zampini 
190125084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
190225084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
19038ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
190472b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
190588ebb749SStefano Zampini 
190680677318SStefano Zampini     /* Assemble         local_auxmat2_R =        (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */
190780677318SStefano Zampini     /* Assemble pcbddc->local_auxmat2   = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */
1908ffd830a3SStefano Zampini     ierr = PetscMemzero(work,lda_rhs*n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
190988ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
191006656605SStefano Zampini       const PetscScalar *row_cmat_values;
191106656605SStefano Zampini       const PetscInt    *row_cmat_indices;
191206656605SStefano Zampini       PetscInt          size_of_constraint,j;
191388ebb749SStefano Zampini 
191406656605SStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
191506656605SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
1916ffd830a3SStefano Zampini         work[row_cmat_indices[j]+i*lda_rhs] = -row_cmat_values[j];
191706656605SStefano Zampini       }
191806656605SStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
191906656605SStefano Zampini     }
1920ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,NULL,&local_auxmat2_R);CHKERRQ(ierr);
192106656605SStefano Zampini     if (F) {
192206656605SStefano Zampini       Mat B;
192306656605SStefano Zampini 
1924ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
1925a3df083aSStefano Zampini       if (need_benign_correction) {
1926df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1927a3df083aSStefano Zampini 
192872b8c272SStefano Zampini         /* rhs is already zero on interior dofs, no need to change the rhs */
192972b8c272SStefano Zampini         ierr = PetscMemzero(reuse_solver->benign_save_vals,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
1930a3df083aSStefano Zampini       }
193180677318SStefano Zampini       ierr = MatMatSolve(F,B,local_auxmat2_R);CHKERRQ(ierr);
1932a3df083aSStefano Zampini       if (need_benign_correction) {
1933a3df083aSStefano Zampini         PetscScalar        *marr;
1934df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
1935a3df083aSStefano Zampini 
1936a3df083aSStefano Zampini         ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
19375cbda25cSStefano Zampini         if (lda_rhs != n_R) {
19385cbda25cSStefano Zampini           for (i=0;i<n_constraints;i++) {
19395cbda25cSStefano Zampini             ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
19405cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
19415cbda25cSStefano Zampini             ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
19425cbda25cSStefano Zampini           }
19435cbda25cSStefano Zampini         } else {
1944a3df083aSStefano Zampini           for (i=0;i<n_constraints;i++) {
1945a3df083aSStefano Zampini             ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
19465cbda25cSStefano Zampini             ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
1947a3df083aSStefano Zampini             ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
1948a3df083aSStefano Zampini           }
19495cbda25cSStefano Zampini         }
1950a3df083aSStefano Zampini         ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
1951a3df083aSStefano Zampini       }
195206656605SStefano Zampini       ierr = MatDestroy(&B);CHKERRQ(ierr);
195306656605SStefano Zampini     } else {
195480677318SStefano Zampini       PetscScalar *marr;
195580677318SStefano Zampini 
195680677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
195706656605SStefano Zampini       for (i=0;i<n_constraints;i++) {
1958ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
1959ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,marr+i*lda_rhs);CHKERRQ(ierr);
196006656605SStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
196106656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
196206656605SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
196306656605SStefano Zampini       }
196480677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&marr);CHKERRQ(ierr);
196506656605SStefano Zampini     }
196680677318SStefano Zampini     if (!pcbddc->switch_static) {
196780677318SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_constraints,NULL,&pcbddc->local_auxmat2);CHKERRQ(ierr);
196880677318SStefano Zampini       ierr = MatDenseGetArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
196980677318SStefano Zampini       ierr = MatDenseGetArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
197080677318SStefano Zampini       for (i=0;i<n_constraints;i++) {
1971ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,array2+i*lda_rhs);CHKERRQ(ierr);
197280677318SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_B,array+i*n_B);CHKERRQ(ierr);
197380677318SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
197480677318SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
197580677318SStefano Zampini         ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
197680677318SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
197780677318SStefano Zampini       }
197880677318SStefano Zampini       ierr = MatDenseRestoreArray(local_auxmat2_R,&array2);CHKERRQ(ierr);
197980677318SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->local_auxmat2,&array);CHKERRQ(ierr);
198072b8c272SStefano Zampini       ierr = MatMatMult(C_B,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
198180677318SStefano Zampini     } else {
1982ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
1983ffd830a3SStefano Zampini         IS dummy;
1984ffd830a3SStefano Zampini 
1985ffd830a3SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,n_R,0,1,&dummy);CHKERRQ(ierr);
198672b8c272SStefano Zampini         ierr = MatGetSubMatrix(local_auxmat2_R,dummy,NULL,MAT_INITIAL_MATRIX,&pcbddc->local_auxmat2);CHKERRQ(ierr);
1987ffd830a3SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
1988ffd830a3SStefano Zampini       } else {
198980677318SStefano Zampini         ierr = PetscObjectReference((PetscObject)local_auxmat2_R);CHKERRQ(ierr);
199080677318SStefano Zampini         pcbddc->local_auxmat2 = local_auxmat2_R;
1991ffd830a3SStefano Zampini       }
199225084f0cSStefano Zampini       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
199380677318SStefano Zampini     }
199480677318SStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
199580677318SStefano Zampini     /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1}  */
199680677318SStefano Zampini     ierr = MatScale(M3,m_one);CHKERRQ(ierr);
199706656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M1);CHKERRQ(ierr);
199806656605SStefano Zampini     ierr = MatDuplicate(M3,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
199980677318SStefano Zampini     if (isCHOL) {
200080677318SStefano Zampini       ierr = MatCholeskyFactor(M3,NULL,NULL);CHKERRQ(ierr);
200180677318SStefano Zampini     } else {
200225084f0cSStefano Zampini       ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
200380677318SStefano Zampini     }
200480677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_C,one);CHKERRQ(ierr);
200506656605SStefano Zampini     ierr = MatDiagonalSet(M2,pcbddc->vec1_C,INSERT_VALUES);CHKERRQ(ierr);
200625084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
200725084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
200825084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
200980677318SStefano Zampini     /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */
201072b8c272SStefano Zampini     ierr = MatMatMult(M1,C_B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
201172b8c272SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
201206656605SStefano Zampini     ierr = MatCopy(M1,S_CC,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* S_CC can have a different LDA, MatMatSolve doesn't support it */
201306656605SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
2014f4ddd8eeSStefano Zampini   }
2015fc227af8SStefano Zampini 
2016fc227af8SStefano Zampini   /* Get submatrices from subdomain matrix */
201788ebb749SStefano Zampini   if (n_vertices) {
201806656605SStefano Zampini     IS is_aux;
20193a50541eSStefano Zampini 
2020b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */
20216816873aSStefano Zampini       IS tis;
20226816873aSStefano Zampini 
20236816873aSStefano Zampini       ierr = ISDuplicate(pcbddc->is_R_local,&tis);CHKERRQ(ierr);
20246816873aSStefano Zampini       ierr = ISSort(tis);CHKERRQ(ierr);
20256816873aSStefano Zampini       ierr = ISComplement(tis,0,pcis->n,&is_aux);CHKERRQ(ierr);
20266816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
20276816873aSStefano Zampini     } else {
20283a50541eSStefano Zampini       ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
20296816873aSStefano Zampini     }
20309577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
20319577ea80SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
203204708bb6SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
203325084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
203488ebb749SStefano Zampini   }
203588ebb749SStefano Zampini 
203688ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
2037f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
203806656605SStefano Zampini     PetscInt on_B,on_primal,on_D=n_D;
203906656605SStefano Zampini     if (pcbddc->coarse_phi_D) {
204006656605SStefano Zampini       ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,NULL);CHKERRQ(ierr);
204106656605SStefano Zampini     }
2042f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
204306656605SStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) {
204406656605SStefano Zampini       PetscScalar *marray;
204506656605SStefano Zampini 
204606656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&marray);CHKERRQ(ierr);
204706656605SStefano Zampini       ierr = PetscFree(marray);CHKERRQ(ierr);
2048f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
2049f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
2050f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
2051f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
2052f4ddd8eeSStefano Zampini     }
2053f4ddd8eeSStefano Zampini   }
205406656605SStefano Zampini 
2055f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
205606656605SStefano Zampini     PetscScalar *marray;
205788ebb749SStefano Zampini 
205806656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
20598eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
206006656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
206188ebb749SStefano Zampini     }
20623301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
206306656605SStefano Zampini       n *= 2;
206488ebb749SStefano Zampini     }
206506656605SStefano Zampini     ierr = PetscCalloc1(n,&marray);CHKERRQ(ierr);
206606656605SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
206706656605SStefano Zampini     n = n_B*pcbddc->local_primal_size;
20688eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
206906656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
207006656605SStefano Zampini       n += n_D*pcbddc->local_primal_size;
207188ebb749SStefano Zampini     }
20723301b35fSStefano Zampini     if (!pcbddc->symmetric_primal) {
207306656605SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
20748eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
207506656605SStefano Zampini         n = n_B*pcbddc->local_primal_size;
207606656605SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_D,pcbddc->local_primal_size,marray+n,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
207788ebb749SStefano Zampini       }
207888ebb749SStefano Zampini     } else {
2079c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
2080c0553b1fSStefano Zampini       pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
20811b968477SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
2082c0553b1fSStefano Zampini         ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
2083c0553b1fSStefano Zampini         pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
2084c0553b1fSStefano Zampini       }
208588ebb749SStefano Zampini     }
208606656605SStefano Zampini   }
2087019a44ceSStefano Zampini 
208806656605SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
20894f1b2e48SStefano Zampini   p0_lidx_I = NULL;
20904f1b2e48SStefano Zampini   if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) {
2091d12edf2fSStefano Zampini     const PetscInt *idxs;
2092d12edf2fSStefano Zampini 
2093d12edf2fSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
20944f1b2e48SStefano Zampini     ierr = PetscMalloc1(pcbddc->benign_n,&p0_lidx_I);CHKERRQ(ierr);
20954f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
20964f1b2e48SStefano Zampini       ierr = PetscFindInt(pcbddc->benign_p0_lidx[i],pcis->n-pcis->n_B,idxs,&p0_lidx_I[i]);CHKERRQ(ierr);
20974f1b2e48SStefano Zampini     }
2098d12edf2fSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,&idxs);CHKERRQ(ierr);
2099d12edf2fSStefano Zampini   }
2100d16cbb6bSStefano Zampini 
210106656605SStefano Zampini   /* vertices */
210206656605SStefano Zampini   if (n_vertices) {
210316f15bc4SStefano Zampini 
2104af25d912SStefano Zampini     ierr = MatConvert(A_VV,MATDENSE,MAT_INPLACE_MATRIX,&A_VV);CHKERRQ(ierr);
210504708bb6SStefano Zampini 
210616f15bc4SStefano Zampini     if (n_R) {
210714393ed6SStefano Zampini       Mat          A_RRmA_RV,A_RV_bcorr=NULL,S_VVt; /* S_VVt with LDA=N */
210806656605SStefano Zampini       PetscBLASInt B_N,B_one = 1;
210916f15bc4SStefano Zampini       PetscScalar  *x,*y;
211004708bb6SStefano Zampini       PetscBool    isseqaij;
211106656605SStefano Zampini 
211221eccb56SStefano Zampini       ierr = MatScale(A_RV,m_one);CHKERRQ(ierr);
211314393ed6SStefano Zampini       if (need_benign_correction) {
211414393ed6SStefano Zampini         ISLocalToGlobalMapping RtoN;
211514393ed6SStefano Zampini         IS                     is_p0;
211614393ed6SStefano Zampini         PetscInt               *idxs_p0,n;
211714393ed6SStefano Zampini 
211814393ed6SStefano Zampini         ierr = PetscMalloc1(pcbddc->benign_n,&idxs_p0);CHKERRQ(ierr);
211914393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local,&RtoN);CHKERRQ(ierr);
212014393ed6SStefano Zampini         ierr = ISGlobalToLocalMappingApply(RtoN,IS_GTOLM_DROP,pcbddc->benign_n,pcbddc->benign_p0_lidx,&n,idxs_p0);CHKERRQ(ierr);
2121af25d912SStefano 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);
212214393ed6SStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&RtoN);CHKERRQ(ierr);
212314393ed6SStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxs_p0,PETSC_OWN_POINTER,&is_p0);CHKERRQ(ierr);
212414393ed6SStefano Zampini         ierr = MatGetSubMatrix(A_RV,is_p0,NULL,MAT_INITIAL_MATRIX,&A_RV_bcorr);CHKERRQ(ierr);
212514393ed6SStefano Zampini         ierr = ISDestroy(&is_p0);CHKERRQ(ierr);
212614393ed6SStefano Zampini       }
212714393ed6SStefano Zampini 
2128ffd830a3SStefano Zampini       if (lda_rhs == n_R) {
2129af25d912SStefano Zampini         ierr = MatConvert(A_RV,MATDENSE,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
2130ffd830a3SStefano Zampini       } else {
2131ca92afb2SStefano Zampini         PetscScalar    *av,*array;
2132ca92afb2SStefano Zampini         const PetscInt *xadj,*adjncy;
2133ca92afb2SStefano Zampini         PetscInt       n;
2134ca92afb2SStefano Zampini         PetscBool      flg_row;
2135ffd830a3SStefano Zampini 
2136ca92afb2SStefano Zampini         array = work+lda_rhs*n_vertices;
2137ca92afb2SStefano Zampini         ierr = PetscMemzero(array,lda_rhs*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
21389d54b7f4SStefano Zampini         ierr = MatConvert(A_RV,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_RV);CHKERRQ(ierr);
2139ca92afb2SStefano Zampini         ierr = MatGetRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2140ca92afb2SStefano Zampini         ierr = MatSeqAIJGetArray(A_RV,&av);CHKERRQ(ierr);
2141ca92afb2SStefano Zampini         for (i=0;i<n;i++) {
2142ca92afb2SStefano Zampini           PetscInt j;
2143ca92afb2SStefano Zampini           for (j=xadj[i];j<xadj[i+1];j++) array[lda_rhs*adjncy[j]+i] = av[j];
2144ffd830a3SStefano Zampini         }
2145ca92afb2SStefano Zampini         ierr = MatRestoreRowIJ(A_RV,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2146ca92afb2SStefano Zampini         ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
2147ca92afb2SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,array,&A_RV);CHKERRQ(ierr);
2148ffd830a3SStefano Zampini       }
2149ffd830a3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
2150a3df083aSStefano Zampini       if (need_benign_correction) {
2151df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2152a3df083aSStefano Zampini         PetscScalar        *marr;
2153a3df083aSStefano Zampini 
2154a3df083aSStefano Zampini         ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
215514393ed6SStefano Zampini         /* need \Phi^T A_RV = (I+L)A_RV, L given by
215614393ed6SStefano Zampini 
215714393ed6SStefano Zampini                | 0 0  0 | (V)
215814393ed6SStefano Zampini            L = | 0 0 -1 | (P-p0)
215914393ed6SStefano Zampini                | 0 0 -1 | (p0)
216014393ed6SStefano Zampini 
216114393ed6SStefano Zampini         */
2162df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
216314393ed6SStefano Zampini           const PetscScalar *vals;
216414393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
216514393ed6SStefano Zampini           PetscInt          n,j,nz;
216614393ed6SStefano Zampini 
2167df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2168df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
216914393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
217014393ed6SStefano Zampini           for (j=0;j<n;j++) {
217114393ed6SStefano Zampini             PetscScalar val = vals[j];
217214393ed6SStefano Zampini             PetscInt    k,col = idxs[j];
217314393ed6SStefano Zampini             for (k=0;k<nz;k++) marr[idxs_zero[k]+lda_rhs*col] -= val;
217414393ed6SStefano Zampini           }
217514393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
2176df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
217714393ed6SStefano Zampini         }
217872b8c272SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
217972b8c272SStefano Zampini       }
218072b8c272SStefano Zampini       if (F) {
218114393ed6SStefano Zampini         /* need to correct the rhs */
218272b8c272SStefano Zampini         if (need_benign_correction) {
218372b8c272SStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
218472b8c272SStefano Zampini           PetscScalar        *marr;
218572b8c272SStefano Zampini 
218672b8c272SStefano Zampini           ierr = MatDenseGetArray(A_RV,&marr);CHKERRQ(ierr);
21875cbda25cSStefano Zampini           if (lda_rhs != n_R) {
21885cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
21895cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
21905cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
21915cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
21925cbda25cSStefano Zampini             }
21935cbda25cSStefano Zampini           } else {
2194a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
2195a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
21965cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
2197a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
2198a3df083aSStefano Zampini             }
21995cbda25cSStefano Zampini           }
2200a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RV,&marr);CHKERRQ(ierr);
2201a3df083aSStefano Zampini         }
220206656605SStefano Zampini         ierr = MatMatSolve(F,A_RV,A_RRmA_RV);CHKERRQ(ierr);
220314393ed6SStefano Zampini         /* need to correct the solution */
2204a3df083aSStefano Zampini         if (need_benign_correction) {
2205df4d28bfSStefano Zampini           PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
2206a3df083aSStefano Zampini           PetscScalar        *marr;
2207a3df083aSStefano Zampini 
2208a3df083aSStefano Zampini           ierr = MatDenseGetArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
22095cbda25cSStefano Zampini           if (lda_rhs != n_R) {
22105cbda25cSStefano Zampini             for (i=0;i<n_vertices;i++) {
22115cbda25cSStefano Zampini               ierr = VecPlaceArray(dummy_vec,marr+i*lda_rhs);CHKERRQ(ierr);
22125cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,dummy_vec,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
22135cbda25cSStefano Zampini               ierr = VecResetArray(dummy_vec);CHKERRQ(ierr);
22145cbda25cSStefano Zampini             }
22155cbda25cSStefano Zampini           } else {
2216a3df083aSStefano Zampini             for (i=0;i<n_vertices;i++) {
2217a3df083aSStefano Zampini               ierr = VecPlaceArray(pcbddc->vec1_R,marr+i*lda_rhs);CHKERRQ(ierr);
22185cbda25cSStefano Zampini               ierr = PCBDDCReuseSolversBenignAdapt(reuse_solver,pcbddc->vec1_R,NULL,PETSC_TRUE,PETSC_TRUE);CHKERRQ(ierr);
2219a3df083aSStefano Zampini               ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
2220a3df083aSStefano Zampini             }
22215cbda25cSStefano Zampini           }
2222a3df083aSStefano Zampini           ierr = MatDenseRestoreArray(A_RRmA_RV,&marr);CHKERRQ(ierr);
2223a3df083aSStefano Zampini         }
222406656605SStefano Zampini       } else {
222506656605SStefano Zampini         ierr = MatDenseGetArray(A_RV,&y);CHKERRQ(ierr);
222606656605SStefano Zampini         for (i=0;i<n_vertices;i++) {
2227ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,y+i*lda_rhs);CHKERRQ(ierr);
2228ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec2_R,work+i*lda_rhs);CHKERRQ(ierr);
222906656605SStefano Zampini           ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
223006656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
223106656605SStefano Zampini           ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
223206656605SStefano Zampini         }
223306656605SStefano Zampini         ierr = MatDenseRestoreArray(A_RV,&y);CHKERRQ(ierr);
223406656605SStefano Zampini       }
223580677318SStefano Zampini       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
2236ffd830a3SStefano Zampini       /* S_VV and S_CV */
223706656605SStefano Zampini       if (n_constraints) {
223806656605SStefano Zampini         Mat B;
223980677318SStefano Zampini 
2240ffd830a3SStefano Zampini         ierr = PetscMemzero(work+lda_rhs*n_vertices,n_B*n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
224180677318SStefano Zampini         for (i=0;i<n_vertices;i++) {
2242ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcbddc->vec1_R,work+i*lda_rhs);CHKERRQ(ierr);
2243ffd830a3SStefano Zampini           ierr = VecPlaceArray(pcis->vec1_B,work+lda_rhs*n_vertices+i*n_B);CHKERRQ(ierr);
224480677318SStefano Zampini           ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
224580677318SStefano Zampini           ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
224680677318SStefano Zampini           ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
224780677318SStefano Zampini           ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
224880677318SStefano Zampini         }
2249ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_B,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
225080677318SStefano Zampini         ierr = MatMatMult(pcbddc->local_auxmat1,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&S_CV);CHKERRQ(ierr);
225180677318SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
2252ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_vertices,work+lda_rhs*n_vertices,&B);CHKERRQ(ierr);
225380677318SStefano Zampini         ierr = MatMatMult(local_auxmat2_R,S_CV,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
225406656605SStefano Zampini         ierr = MatScale(S_CV,m_one);CHKERRQ(ierr);
2255ffd830a3SStefano Zampini         ierr = PetscBLASIntCast(lda_rhs*n_vertices,&B_N);CHKERRQ(ierr);
2256ffd830a3SStefano Zampini         PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,work+lda_rhs*n_vertices,&B_one,work,&B_one));
225706656605SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
225806656605SStefano Zampini       }
225904708bb6SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_VR,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
226004708bb6SStefano Zampini       if (!isseqaij) { /* MatMatMult with SEQ(S)BAIJ below will raise an error */
2261511c6705SHong Zhang         ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
226204708bb6SStefano Zampini       }
2263ffd830a3SStefano Zampini       if (lda_rhs != n_R) {
2264ffd830a3SStefano Zampini         ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
2265ffd830a3SStefano Zampini         ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,work,&A_RRmA_RV);CHKERRQ(ierr);
2266ffd830a3SStefano Zampini         ierr = MatSeqDenseSetLDA(A_RRmA_RV,lda_rhs);CHKERRQ(ierr);
2267ffd830a3SStefano Zampini       }
226806656605SStefano Zampini       ierr = MatMatMult(A_VR,A_RRmA_RV,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VVt);CHKERRQ(ierr);
226914393ed6SStefano Zampini       /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */
227014393ed6SStefano Zampini       if (need_benign_correction) {
2271df4d28bfSStefano Zampini         PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
227214393ed6SStefano Zampini         PetscScalar      *marr,*sums;
227314393ed6SStefano Zampini 
227414393ed6SStefano Zampini         ierr = PetscMalloc1(n_vertices,&sums);CHKERRQ(ierr);
227514393ed6SStefano Zampini         ierr = MatDenseGetArray(S_VVt,&marr);
2276df4d28bfSStefano Zampini         for (i=0;i<reuse_solver->benign_n;i++) {
227714393ed6SStefano Zampini           const PetscScalar *vals;
227814393ed6SStefano Zampini           const PetscInt    *idxs,*idxs_zero;
227914393ed6SStefano Zampini           PetscInt          n,j,nz;
228014393ed6SStefano Zampini 
2281df4d28bfSStefano Zampini           ierr = ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i],&nz);CHKERRQ(ierr);
2282df4d28bfSStefano Zampini           ierr = ISGetIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
228314393ed6SStefano Zampini           for (j=0;j<n_vertices;j++) {
228414393ed6SStefano Zampini             PetscInt k;
228514393ed6SStefano Zampini             sums[j] = 0.;
228614393ed6SStefano Zampini             for (k=0;k<nz;k++) sums[j] += work[idxs_zero[k]+j*lda_rhs];
228714393ed6SStefano Zampini           }
228814393ed6SStefano Zampini           ierr = MatGetRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
228914393ed6SStefano Zampini           for (j=0;j<n;j++) {
229014393ed6SStefano Zampini             PetscScalar val = vals[j];
229114393ed6SStefano Zampini             PetscInt k;
229214393ed6SStefano Zampini             for (k=0;k<n_vertices;k++) {
229314393ed6SStefano Zampini               marr[idxs[j]+k*n_vertices] += val*sums[k];
229414393ed6SStefano Zampini             }
229514393ed6SStefano Zampini           }
229614393ed6SStefano Zampini           ierr = MatRestoreRow(A_RV_bcorr,i,&n,&idxs,&vals);CHKERRQ(ierr);
2297df4d28bfSStefano Zampini           ierr = ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i],&idxs_zero);CHKERRQ(ierr);
229814393ed6SStefano Zampini         }
229914393ed6SStefano Zampini         ierr = PetscFree(sums);CHKERRQ(ierr);
230014393ed6SStefano Zampini         ierr = MatDenseRestoreArray(S_VVt,&marr);
230114393ed6SStefano Zampini         ierr = MatDestroy(&A_RV_bcorr);CHKERRQ(ierr);
230214393ed6SStefano Zampini       }
230380677318SStefano Zampini       ierr = MatDestroy(&A_RRmA_RV);CHKERRQ(ierr);
230406656605SStefano Zampini       ierr = PetscBLASIntCast(n_vertices*n_vertices,&B_N);CHKERRQ(ierr);
230506656605SStefano Zampini       ierr = MatDenseGetArray(A_VV,&x);CHKERRQ(ierr);
230606656605SStefano Zampini       ierr = MatDenseGetArray(S_VVt,&y);CHKERRQ(ierr);
230706656605SStefano Zampini       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&B_N,&one,x,&B_one,y,&B_one));
230806656605SStefano Zampini       ierr = MatDenseRestoreArray(A_VV,&x);CHKERRQ(ierr);
230906656605SStefano Zampini       ierr = MatDenseRestoreArray(S_VVt,&y);CHKERRQ(ierr);
231006656605SStefano Zampini       ierr = MatCopy(S_VVt,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
2311d16cbb6bSStefano Zampini       ierr = MatDestroy(&S_VVt);CHKERRQ(ierr);
2312019a44ceSStefano Zampini     } else {
2313d16cbb6bSStefano Zampini       ierr = MatCopy(A_VV,S_VV,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
2314d16cbb6bSStefano Zampini     }
231521eccb56SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
2316d16cbb6bSStefano Zampini 
231706656605SStefano Zampini     /* coarse basis functions */
231806656605SStefano Zampini     for (i=0;i<n_vertices;i++) {
231916f15bc4SStefano Zampini       PetscScalar *y;
232016f15bc4SStefano Zampini 
2321ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
232206656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
232306656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
232406656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
232506656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
232606656605SStefano Zampini       y[n_B*i+idx_V_B[i]] = 1.0;
232706656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
232806656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
232906656605SStefano Zampini 
233006656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
23314f1b2e48SStefano Zampini         PetscInt j;
23324f1b2e48SStefano Zampini 
233306656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
233406656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
233506656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
233606656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
233706656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
23384f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
233906656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
234006656605SStefano Zampini       }
234106656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
234206656605SStefano Zampini     }
234304708bb6SStefano Zampini     /* if n_R == 0 the object is not destroyed */
234404708bb6SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
234506656605SStefano Zampini   }
23465cbda25cSStefano Zampini   ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
234706656605SStefano Zampini 
234806656605SStefano Zampini   if (n_constraints) {
234906656605SStefano Zampini     Mat B;
235006656605SStefano Zampini 
2351ffd830a3SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,lda_rhs,n_constraints,work,&B);CHKERRQ(ierr);
235206656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
235380677318SStefano Zampini     ierr = MatMatMult(local_auxmat2_R,S_CC,MAT_REUSE_MATRIX,PETSC_DEFAULT,&B);CHKERRQ(ierr);
235406656605SStefano Zampini     ierr = MatScale(S_CC,m_one);CHKERRQ(ierr);
235506656605SStefano Zampini     if (n_vertices) {
235680677318SStefano Zampini       if (isCHOL) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */
235780677318SStefano Zampini         ierr = MatTranspose(S_CV,MAT_REUSE_MATRIX,&S_VC);CHKERRQ(ierr);
235880677318SStefano Zampini       } else {
235980677318SStefano Zampini         Mat S_VCt;
236080677318SStefano Zampini 
2361ffd830a3SStefano Zampini         if (lda_rhs != n_R) {
2362ffd830a3SStefano Zampini           ierr = MatDestroy(&B);CHKERRQ(ierr);
236372b8c272SStefano Zampini           ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_constraints,work,&B);CHKERRQ(ierr);
2364ffd830a3SStefano Zampini           ierr = MatSeqDenseSetLDA(B,lda_rhs);CHKERRQ(ierr);
2365ffd830a3SStefano Zampini         }
236680677318SStefano Zampini         ierr = MatMatMult(A_VR,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&S_VCt);CHKERRQ(ierr);
236780677318SStefano Zampini         ierr = MatCopy(S_VCt,S_VC,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
236880677318SStefano Zampini         ierr = MatDestroy(&S_VCt);CHKERRQ(ierr);
236980677318SStefano Zampini       }
237006656605SStefano Zampini     }
237106656605SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
237206656605SStefano Zampini     /* coarse basis functions */
237306656605SStefano Zampini     for (i=0;i<n_constraints;i++) {
237406656605SStefano Zampini       PetscScalar *y;
237506656605SStefano Zampini 
2376ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+lda_rhs*i);CHKERRQ(ierr);
237706656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
237806656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*(i+n_vertices));CHKERRQ(ierr);
237906656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
238006656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
238106656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&y);CHKERRQ(ierr);
238206656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
238306656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
23844f1b2e48SStefano Zampini         PetscInt j;
23854f1b2e48SStefano Zampini 
238606656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
238706656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*(i+n_vertices));CHKERRQ(ierr);
238806656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
238906656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
239006656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
23914f1b2e48SStefano Zampini         for (j=0;j<pcbddc->benign_n;j++) y[n_D*i+p0_lidx_I[j]] = 0.0;
239206656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_phi_D,&y);CHKERRQ(ierr);
239306656605SStefano Zampini       }
239406656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
239506656605SStefano Zampini     }
239606656605SStefano Zampini   }
239780677318SStefano Zampini   if (n_constraints) {
239880677318SStefano Zampini     ierr = MatDestroy(&local_auxmat2_R);CHKERRQ(ierr);
239980677318SStefano Zampini   }
24004f1b2e48SStefano Zampini   ierr = PetscFree(p0_lidx_I);CHKERRQ(ierr);
240172b8c272SStefano Zampini 
240272b8c272SStefano Zampini   /* coarse matrix entries relative to B_0 */
240372b8c272SStefano Zampini   if (pcbddc->benign_n) {
240472b8c272SStefano Zampini     Mat         B0_B,B0_BPHI;
240572b8c272SStefano Zampini     IS          is_dummy;
240672b8c272SStefano Zampini     PetscScalar *data;
240772b8c272SStefano Zampini     PetscInt    j;
240872b8c272SStefano Zampini 
240972b8c272SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
241072b8c272SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
241172b8c272SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
241272b8c272SStefano Zampini     ierr = MatMatMult(B0_B,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
241386c38910SStefano Zampini     ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
241472b8c272SStefano Zampini     ierr = MatDenseGetArray(B0_BPHI,&data);CHKERRQ(ierr);
241572b8c272SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) {
241672b8c272SStefano Zampini       PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
241772b8c272SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
241872b8c272SStefano Zampini         coarse_submat_vals[primal_idx*pcbddc->local_primal_size+i] = data[i*pcbddc->benign_n+j];
241972b8c272SStefano Zampini         coarse_submat_vals[i*pcbddc->local_primal_size+primal_idx] = data[i*pcbddc->benign_n+j];
242072b8c272SStefano Zampini       }
242172b8c272SStefano Zampini     }
242272b8c272SStefano Zampini     ierr = MatDenseRestoreArray(B0_BPHI,&data);CHKERRQ(ierr);
242372b8c272SStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
242472b8c272SStefano Zampini     ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
242572b8c272SStefano Zampini   }
2426019a44ceSStefano Zampini 
242706656605SStefano Zampini   /* compute other basis functions for non-symmetric problems */
24283301b35fSStefano Zampini   if (!pcbddc->symmetric_primal) {
2429ffd830a3SStefano Zampini     Mat         B_V=NULL,B_C=NULL;
2430ffd830a3SStefano Zampini     PetscScalar *marray;
243106656605SStefano Zampini 
243206656605SStefano Zampini     if (n_constraints) {
2433ffd830a3SStefano Zampini       Mat S_CCT,C_CRT;
243406656605SStefano Zampini 
2435af25d912SStefano Zampini       ierr = MatTranspose(C_CR,MAT_INPLACE_MATRIX,&C_CRT);CHKERRQ(ierr);
243606656605SStefano Zampini       ierr = MatTranspose(S_CC,MAT_INITIAL_MATRIX,&S_CCT);CHKERRQ(ierr);
2437ffd830a3SStefano Zampini       ierr = MatMatMult(C_CRT,S_CCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_C);CHKERRQ(ierr);
243816f15bc4SStefano Zampini       ierr = MatDestroy(&S_CCT);CHKERRQ(ierr);
243906656605SStefano Zampini       if (n_vertices) {
2440ffd830a3SStefano Zampini         Mat S_VCT;
244106656605SStefano Zampini 
244206656605SStefano Zampini         ierr = MatTranspose(S_VC,MAT_INITIAL_MATRIX,&S_VCT);CHKERRQ(ierr);
2443ffd830a3SStefano Zampini         ierr = MatMatMult(C_CRT,S_VCT,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&B_V);CHKERRQ(ierr);
244416f15bc4SStefano Zampini         ierr = MatDestroy(&S_VCT);CHKERRQ(ierr);
244506656605SStefano Zampini       }
2446ffd830a3SStefano Zampini       ierr = MatDestroy(&C_CRT);CHKERRQ(ierr);
24475b782168SStefano Zampini     } else {
24485b782168SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,n_R,n_vertices,NULL,&B_V);CHKERRQ(ierr);
244906656605SStefano Zampini     }
245016f15bc4SStefano Zampini     if (n_vertices && n_R) {
2451ffd830a3SStefano Zampini       PetscScalar    *av,*marray;
2452ffd830a3SStefano Zampini       const PetscInt *xadj,*adjncy;
2453ffd830a3SStefano Zampini       PetscInt       n;
2454ffd830a3SStefano Zampini       PetscBool      flg_row;
245506656605SStefano Zampini 
2456ffd830a3SStefano Zampini       /* B_V = B_V - A_VR^T */
2457af25d912SStefano Zampini       ierr = MatConvert(A_VR,MATSEQAIJ,MAT_INPLACE_MATRIX,&A_VR);CHKERRQ(ierr);
2458ffd830a3SStefano Zampini       ierr = MatGetRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2459ffd830a3SStefano Zampini       ierr = MatSeqAIJGetArray(A_VR,&av);CHKERRQ(ierr);
2460ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
2461ffd830a3SStefano Zampini       for (i=0;i<n;i++) {
2462ffd830a3SStefano Zampini         PetscInt j;
2463ffd830a3SStefano Zampini         for (j=xadj[i];j<xadj[i+1];j++) marray[i*n_R + adjncy[j]] -= av[j];
2464ffd830a3SStefano Zampini       }
2465ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
2466ffd830a3SStefano Zampini       ierr = MatRestoreRowIJ(A_VR,0,PETSC_FALSE,PETSC_FALSE,&n,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
2467ffd830a3SStefano Zampini       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
246806656605SStefano Zampini     }
246906656605SStefano Zampini 
2470ffd830a3SStefano Zampini     /* currently there's no support for MatTransposeMatSolve(F,B,X) */
2471ffd830a3SStefano Zampini     ierr = MatDenseGetArray(B_V,&marray);CHKERRQ(ierr);
2472ffd830a3SStefano Zampini     for (i=0;i<n_vertices;i++) {
2473ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+i*n_R);CHKERRQ(ierr);
2474ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
247506656605SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
247606656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
247706656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
247806656605SStefano Zampini     }
2479ffd830a3SStefano Zampini     ierr = MatDenseRestoreArray(B_V,&marray);CHKERRQ(ierr);
24805b782168SStefano Zampini     if (B_C) {
2481ffd830a3SStefano Zampini       ierr = MatDenseGetArray(B_C,&marray);CHKERRQ(ierr);
2482ffd830a3SStefano Zampini       for (i=n_vertices;i<n_constraints+n_vertices;i++) {
2483ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
2484ffd830a3SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
2485ffd830a3SStefano Zampini         ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
2486ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
2487ffd830a3SStefano Zampini         ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
248806656605SStefano Zampini       }
2489ffd830a3SStefano Zampini       ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
24905b782168SStefano Zampini     }
24915b782168SStefano Zampini     for (i=n_vertices;i<n_constraints+n_vertices;i++) {
24925b782168SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,marray+(i-n_vertices)*n_R);CHKERRQ(ierr);
24935b782168SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec2_R,work+i*n_R);CHKERRQ(ierr);
24945b782168SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
24955b782168SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
24965b782168SStefano Zampini       ierr = VecResetArray(pcbddc->vec2_R);CHKERRQ(ierr);
24975b782168SStefano Zampini     }
24985b782168SStefano Zampini     ierr = MatDenseRestoreArray(B_C,&marray);CHKERRQ(ierr);
249906656605SStefano Zampini     /* coarse basis functions */
250006656605SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
250106656605SStefano Zampini       PetscScalar *y;
250206656605SStefano Zampini 
2503ffd830a3SStefano Zampini       ierr = VecPlaceArray(pcbddc->vec1_R,work+i*n_R);CHKERRQ(ierr);
250406656605SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
250506656605SStefano Zampini       ierr = VecPlaceArray(pcis->vec1_B,y+n_B*i);CHKERRQ(ierr);
250606656605SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
250706656605SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
250806656605SStefano Zampini       if (i<n_vertices) {
250906656605SStefano Zampini         y[n_B*i+idx_V_B[i]] = 1.0;
251006656605SStefano Zampini       }
251106656605SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_psi_B,&y);CHKERRQ(ierr);
251206656605SStefano Zampini       ierr = VecResetArray(pcis->vec1_B);CHKERRQ(ierr);
251306656605SStefano Zampini 
251406656605SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
251506656605SStefano Zampini         ierr = MatDenseGetArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
251606656605SStefano Zampini         ierr = VecPlaceArray(pcis->vec1_D,y+n_D*i);CHKERRQ(ierr);
251706656605SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
251806656605SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
251906656605SStefano Zampini         ierr = VecResetArray(pcis->vec1_D);CHKERRQ(ierr);
252006656605SStefano Zampini         ierr = MatDenseRestoreArray(pcbddc->coarse_psi_D,&y);CHKERRQ(ierr);
252106656605SStefano Zampini       }
252206656605SStefano Zampini       ierr = VecResetArray(pcbddc->vec1_R);CHKERRQ(ierr);
252306656605SStefano Zampini     }
2524ffd830a3SStefano Zampini     ierr = MatDestroy(&B_V);CHKERRQ(ierr);
2525ffd830a3SStefano Zampini     ierr = MatDestroy(&B_C);CHKERRQ(ierr);
252606656605SStefano Zampini   }
2527d62866d3SStefano Zampini   /* free memory */
252888ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
252906656605SStefano Zampini   ierr = MatDestroy(&S_VV);CHKERRQ(ierr);
253006656605SStefano Zampini   ierr = MatDestroy(&S_CV);CHKERRQ(ierr);
253106656605SStefano Zampini   ierr = MatDestroy(&S_VC);CHKERRQ(ierr);
253206656605SStefano Zampini   ierr = MatDestroy(&S_CC);CHKERRQ(ierr);
2533d62866d3SStefano Zampini   ierr = PetscFree(work);CHKERRQ(ierr);
2534d62866d3SStefano Zampini   if (n_vertices) {
2535d62866d3SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
2536d62866d3SStefano Zampini   }
2537d62866d3SStefano Zampini   if (n_constraints) {
2538d62866d3SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
2539d62866d3SStefano Zampini   }
254088ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
254188ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
254288ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
2543d12edf2fSStefano Zampini   if (pcbddc->dbg_flag) {
254488ebb749SStefano Zampini     Mat         coarse_sub_mat;
254525084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
254688ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
254788ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
254888ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
25498bec7fa6SStefano Zampini     Mat         C_B,CPHI;
25508bec7fa6SStefano Zampini     IS          is_dummy;
25518bec7fa6SStefano Zampini     Vec         mones;
255288ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
255388ebb749SStefano Zampini     PetscReal   real_value;
255488ebb749SStefano Zampini 
2555a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
2556a3df083aSStefano Zampini       Mat A;
2557a3df083aSStefano Zampini       ierr = PCBDDCBenignProject(pc,NULL,NULL,&A);CHKERRQ(ierr);
2558a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
2559a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
2560a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
2561a3df083aSStefano Zampini       ierr = MatGetSubMatrix(A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
2562a3df083aSStefano Zampini       ierr = MatDestroy(&A);CHKERRQ(ierr);
2563a3df083aSStefano Zampini     } else {
256488ebb749SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
256588ebb749SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
256688ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
256788ebb749SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
2568a3df083aSStefano Zampini     }
256988ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
257088ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
2571ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
257288ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
257388ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
257488ebb749SStefano Zampini     }
257588ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
257688ebb749SStefano Zampini 
257725084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
25783301b35fSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat computation (symmetric %d)\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
257925084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2580ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
258188ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
258288ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
258388ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
258488ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
258588ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
258688ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
258788ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
258888ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
258988ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
259088ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
259188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
259288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
259388ebb749SStefano Zampini     } else {
259488ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
259588ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
259688ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
259788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
259888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
259988ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
260088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
260188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
260288ebb749SStefano Zampini     }
260388ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
260488ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
260588ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
2606511c6705SHong Zhang     ierr = MatConvert(TM1,MATSEQDENSE,MAT_INPLACE_MATRIX,&TM1);CHKERRQ(ierr);
26074f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
2608fc227af8SStefano Zampini       Mat         B0_B,B0_BPHI;
2609d12edf2fSStefano Zampini       PetscScalar *data,*data2;
26104f1b2e48SStefano Zampini       PetscInt    j;
2611d12edf2fSStefano Zampini 
26124f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
2613fc227af8SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
2614d12edf2fSStefano Zampini       ierr = MatMatMult(B0_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&B0_BPHI);CHKERRQ(ierr);
261586c38910SStefano Zampini       ierr = MatConvert(B0_BPHI,MATSEQDENSE,MAT_INPLACE_MATRIX,&B0_BPHI);CHKERRQ(ierr);
2616d12edf2fSStefano Zampini       ierr = MatDenseGetArray(TM1,&data);CHKERRQ(ierr);
2617d12edf2fSStefano Zampini       ierr = MatDenseGetArray(B0_BPHI,&data2);CHKERRQ(ierr);
26184f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) {
26194f1b2e48SStefano Zampini         PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j;
2620d12edf2fSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
26214f1b2e48SStefano Zampini           data[primal_idx*pcbddc->local_primal_size+i] += data2[i*pcbddc->benign_n+j];
26224f1b2e48SStefano Zampini           data[i*pcbddc->local_primal_size+primal_idx] += data2[i*pcbddc->benign_n+j];
26234f1b2e48SStefano Zampini         }
2624d12edf2fSStefano Zampini       }
2625d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(TM1,&data);CHKERRQ(ierr);
2626d12edf2fSStefano Zampini       ierr = MatDenseRestoreArray(B0_BPHI,&data2);CHKERRQ(ierr);
2627d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
2628d12edf2fSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
2629d12edf2fSStefano Zampini       ierr = MatDestroy(&B0_BPHI);CHKERRQ(ierr);
2630d12edf2fSStefano Zampini     }
2631d12edf2fSStefano Zampini #if 0
2632d12edf2fSStefano Zampini   {
2633d12edf2fSStefano Zampini     PetscViewer viewer;
2634d12edf2fSStefano Zampini     char filename[256];
2635ffd830a3SStefano Zampini     sprintf(filename,"details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level);
2636d12edf2fSStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
2637d12edf2fSStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2638ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)coarse_sub_mat,"computed");CHKERRQ(ierr);
2639ffd830a3SStefano Zampini     ierr = MatView(coarse_sub_mat,viewer);CHKERRQ(ierr);
2640ffd830a3SStefano Zampini     ierr = PetscObjectSetName((PetscObject)TM1,"projected");CHKERRQ(ierr);
2641d12edf2fSStefano Zampini     ierr = MatView(TM1,viewer);CHKERRQ(ierr);
264272b8c272SStefano Zampini     if (save_change) {
264372b8c272SStefano Zampini       Mat phi_B;
264472b8c272SStefano Zampini       ierr = MatMatMult(save_change,pcbddc->coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&phi_B);CHKERRQ(ierr);
264572b8c272SStefano Zampini       ierr = PetscObjectSetName((PetscObject)phi_B,"phi_B");CHKERRQ(ierr);
264672b8c272SStefano Zampini       ierr = MatView(phi_B,viewer);CHKERRQ(ierr);
264772b8c272SStefano Zampini       ierr = MatDestroy(&phi_B);CHKERRQ(ierr);
264872b8c272SStefano Zampini     } else {
2649ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B");CHKERRQ(ierr);
2650ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_B,viewer);CHKERRQ(ierr);
265172b8c272SStefano Zampini     }
2652ffd830a3SStefano Zampini     if (pcbddc->coarse_phi_D) {
2653ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D");CHKERRQ(ierr);
2654ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_phi_D,viewer);CHKERRQ(ierr);
2655ffd830a3SStefano Zampini     }
2656ffd830a3SStefano Zampini     if (pcbddc->coarse_psi_B) {
2657ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B");CHKERRQ(ierr);
2658ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_B,viewer);CHKERRQ(ierr);
2659ffd830a3SStefano Zampini     }
266072b8c272SStefano Zampini     if (pcbddc->coarse_psi_D) {
2661ffd830a3SStefano Zampini       ierr = PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D");CHKERRQ(ierr);
2662ffd830a3SStefano Zampini       ierr = MatView(pcbddc->coarse_psi_D,viewer);CHKERRQ(ierr);
2663ffd830a3SStefano Zampini     }
2664d12edf2fSStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
2665d12edf2fSStefano Zampini   }
2666d12edf2fSStefano Zampini #endif
266781d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
26688bec7fa6SStefano Zampini     ierr = MatNorm(TM1,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
26691575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
267006656605SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d          matrix error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
26718bec7fa6SStefano Zampini 
26728bec7fa6SStefano Zampini     /* check constraints */
2673a00504b5SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size-pcbddc->benign_n,0,1,&is_dummy);CHKERRQ(ierr);
2674a00504b5SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&C_B);CHKERRQ(ierr);
26754f1b2e48SStefano Zampini     if (!pcbddc->benign_n) { /* TODO: add benign case */
26768bec7fa6SStefano Zampini       ierr = MatMatMult(C_B,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
2677a00504b5SStefano Zampini     } else {
2678a00504b5SStefano Zampini       PetscScalar *data;
2679a00504b5SStefano Zampini       Mat         tmat;
2680a00504b5SStefano Zampini       ierr = MatDenseGetArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
2681a00504b5SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcis->n_B,pcbddc->local_primal_size-pcbddc->benign_n,data,&tmat);CHKERRQ(ierr);
2682a00504b5SStefano Zampini       ierr = MatDenseRestoreArray(pcbddc->coarse_phi_B,&data);CHKERRQ(ierr);
2683a00504b5SStefano Zampini       ierr = MatMatMult(C_B,tmat,MAT_INITIAL_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
2684a00504b5SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
2685a00504b5SStefano Zampini     }
26868bec7fa6SStefano Zampini     ierr = MatCreateVecs(CPHI,&mones,NULL);CHKERRQ(ierr);
26878bec7fa6SStefano Zampini     ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
26888bec7fa6SStefano Zampini     ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
26898bec7fa6SStefano Zampini     ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
2690bdae7319SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d phi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
2691ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
2692bdae7319SStefano Zampini       ierr = MatMatMult(C_B,coarse_psi_B,MAT_REUSE_MATRIX,1.0,&CPHI);CHKERRQ(ierr);
2693bdae7319SStefano Zampini       ierr = VecSet(mones,-1.0);CHKERRQ(ierr);
2694bdae7319SStefano Zampini       ierr = MatDiagonalSet(CPHI,mones,ADD_VALUES);CHKERRQ(ierr);
2695bdae7319SStefano Zampini       ierr = MatNorm(CPHI,NORM_FROBENIUS,&real_value);CHKERRQ(ierr);
2696bdae7319SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d psi constraints error % 1.14e\n",PetscGlobalRank,real_value);CHKERRQ(ierr);
269788ebb749SStefano Zampini     }
26988bec7fa6SStefano Zampini     ierr = MatDestroy(&C_B);CHKERRQ(ierr);
26998bec7fa6SStefano Zampini     ierr = MatDestroy(&CPHI);CHKERRQ(ierr);
27008bec7fa6SStefano Zampini     ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
27018bec7fa6SStefano Zampini     ierr = VecDestroy(&mones);CHKERRQ(ierr);
270225084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
270388ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
270488ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
270588ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
270688ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
270788ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
270888ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
270988ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
271088ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
271188ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
271288ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
2713ffd830a3SStefano Zampini     if (!pcbddc->symmetric_primal) {
271488ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
271588ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
271688ebb749SStefano Zampini     }
271788ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
271888ebb749SStefano Zampini   }
27198629588bSStefano Zampini   /* get back data */
27208629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
272188ebb749SStefano Zampini   PetscFunctionReturn(0);
272288ebb749SStefano Zampini }
272388ebb749SStefano Zampini 
272488ebb749SStefano Zampini #undef __FUNCT__
2725d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
2726d648f858SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
2727aa0d41d4SStefano Zampini {
2728d65f70fdSStefano Zampini   Mat            *work_mat;
2729d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
2730d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
2731c43ebad9SStefano Zampini   PetscInt       rsize,*idxs_perm_r=NULL,csize,*idxs_perm_c=NULL;
2732aa0d41d4SStefano Zampini   PetscErrorCode ierr;
2733aa0d41d4SStefano Zampini 
2734aa0d41d4SStefano Zampini   PetscFunctionBegin;
2735d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
2736d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
2737d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
2738d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
2739aa0d41d4SStefano Zampini 
2740d65f70fdSStefano Zampini   if (!rsorted) {
2741906d46d4SStefano Zampini     const PetscInt *idxs;
2742906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
2743aa0d41d4SStefano Zampini 
2744d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
2745d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
2746d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
2747d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
2748aa0d41d4SStefano Zampini     }
2749d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
2750d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
2751d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
2752d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
2753aa0d41d4SStefano Zampini     }
2754d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
2755d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
2756d65f70fdSStefano Zampini   } else {
2757d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
2758d65f70fdSStefano Zampini     isrow_s = isrow;
2759aa0d41d4SStefano Zampini   }
2760906d46d4SStefano Zampini 
2761d65f70fdSStefano Zampini   if (!csorted) {
2762d65f70fdSStefano Zampini     if (isrow == iscol) {
2763d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
2764d65f70fdSStefano Zampini       iscol_s = isrow_s;
2765d65f70fdSStefano Zampini     } else {
2766d65f70fdSStefano Zampini       const PetscInt *idxs;
2767d65f70fdSStefano Zampini       PetscInt       *idxs_sorted,i;
2768906d46d4SStefano Zampini 
2769d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
2770d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
2771d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
2772d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
2773d65f70fdSStefano Zampini       }
2774d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
2775d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
2776d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
2777d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
2778d65f70fdSStefano Zampini       }
2779d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
2780d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
2781d65f70fdSStefano Zampini     }
2782d65f70fdSStefano Zampini   } else {
2783d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
2784d65f70fdSStefano Zampini     iscol_s = iscol;
2785d65f70fdSStefano Zampini   }
2786d65f70fdSStefano Zampini 
2787d648f858SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
2788d65f70fdSStefano Zampini 
2789d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
2790906d46d4SStefano Zampini     Mat      new_mat;
2791d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
2792906d46d4SStefano Zampini 
2793d65f70fdSStefano Zampini     if (!rsorted) {
2794d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
2795d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
2796d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
2797d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
2798906d46d4SStefano Zampini       }
2799d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
2800d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
2801d65f70fdSStefano Zampini     } else {
2802d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
2803906d46d4SStefano Zampini     }
2804d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
2805d65f70fdSStefano Zampini 
2806d65f70fdSStefano Zampini     if (!csorted) {
2807d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
2808d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
2809d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
2810d65f70fdSStefano Zampini       } else {
2811d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
2812d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
2813d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
2814d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
2815d65f70fdSStefano Zampini         }
2816d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
2817d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
2818d65f70fdSStefano Zampini       }
2819d65f70fdSStefano Zampini     } else {
2820d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
2821d65f70fdSStefano Zampini     }
2822d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
2823d65f70fdSStefano Zampini 
2824d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
2825d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
2826d65f70fdSStefano Zampini     work_mat[0] = new_mat;
2827d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
2828d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
2829d65f70fdSStefano Zampini   }
2830d65f70fdSStefano Zampini 
2831d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
2832d65f70fdSStefano Zampini   *B = work_mat[0];
2833d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
2834d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
2835d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
2836d65f70fdSStefano Zampini   PetscFunctionReturn(0);
2837d65f70fdSStefano Zampini }
2838d65f70fdSStefano Zampini 
2839d65f70fdSStefano Zampini #undef __FUNCT__
28405e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
28415e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
2842aa0d41d4SStefano Zampini {
2843aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
28445e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
2845d65f70fdSStefano Zampini   Mat            new_mat;
28465e8657edSStefano Zampini   IS             is_local,is_global;
2847d65f70fdSStefano Zampini   PetscInt       local_size;
2848d65f70fdSStefano Zampini   PetscBool      isseqaij;
2849aa0d41d4SStefano Zampini   PetscErrorCode ierr;
2850aa0d41d4SStefano Zampini 
2851aa0d41d4SStefano Zampini   PetscFunctionBegin;
2852aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
28535e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
28545e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
2855b087196eSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pc->pmat->rmap->mapping,is_local,&is_global);CHKERRQ(ierr);
2856aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
2857d648f858SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
2858aa0d41d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
2859906d46d4SStefano Zampini 
2860906d46d4SStefano Zampini   /* check */
2861906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
2862906d46d4SStefano Zampini     Vec       x,x_change;
2863906d46d4SStefano Zampini     PetscReal error;
2864906d46d4SStefano Zampini 
28655e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
2866906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
28675e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
2868e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2869e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->cctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2870d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
2871e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2872e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2873906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
2874906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
2875906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2876906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
2877906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
2878906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
2879906d46d4SStefano Zampini   }
2880906d46d4SStefano Zampini 
288122d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
28829b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
288322d5777bSStefano Zampini   if (isseqaij) {
2884a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
2885a00504b5SStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
2886aa0d41d4SStefano Zampini   } else {
2887a00504b5SStefano Zampini     Mat work_mat;
28881cf9b237SStefano Zampini 
2889a00504b5SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
2890aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
2891a00504b5SStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
28921d82a3b6SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
2893aa0d41d4SStefano Zampini   }
28943301b35fSStefano Zampini   if (matis->A->symmetric_set) {
28953301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
2896e496cd5dSStefano Zampini #if !defined(PETSC_USE_COMPLEX)
28973301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
2898e496cd5dSStefano Zampini #endif
28993301b35fSStefano Zampini   }
2900d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
2901aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
2902aa0d41d4SStefano Zampini }
2903aa0d41d4SStefano Zampini 
2904aa0d41d4SStefano Zampini #undef __FUNCT__
2905a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
29068ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
2907a64d13efSStefano Zampini {
2908a64d13efSStefano Zampini   PC_IS*          pcis = (PC_IS*)(pc->data);
2909a64d13efSStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
2910d62866d3SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
291153892102SStefano Zampini   PetscInt        *idx_R_local=NULL;
29123a50541eSStefano Zampini   PetscInt        n_vertices,i,j,n_R,n_D,n_B;
29133a50541eSStefano Zampini   PetscInt        vbs,bs;
29146816873aSStefano Zampini   PetscBT         bitmask=NULL;
2915a64d13efSStefano Zampini   PetscErrorCode  ierr;
2916a64d13efSStefano Zampini 
2917a64d13efSStefano Zampini   PetscFunctionBegin;
2918b23d619eSStefano Zampini   /*
2919b23d619eSStefano Zampini     No need to setup local scatters if
2920b23d619eSStefano Zampini       - primal space is unchanged
2921b23d619eSStefano Zampini         AND
2922b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
2923b23d619eSStefano Zampini         AND
2924b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
2925b23d619eSStefano Zampini   */
2926b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
2927f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
2928f4ddd8eeSStefano Zampini   }
2929f4ddd8eeSStefano Zampini   /* destroy old objects */
2930f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
2931f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
2932f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
2933a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
2934b371cd4fSStefano Zampini   n_B = pcis->n_B;
2935b371cd4fSStefano Zampini   n_D = pcis->n - n_B;
2936b371cd4fSStefano Zampini   n_vertices = pcbddc->n_vertices;
29373a50541eSStefano Zampini 
2938a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
29396816873aSStefano Zampini 
294053892102SStefano Zampini   /* create auxiliary bitmask and allocate workspace */
2941b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
2942854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
2943a64d13efSStefano Zampini     ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
2944a64d13efSStefano Zampini     for (i=0;i<n_vertices;i++) {
29450e6343abSStefano Zampini       ierr = PetscBTSet(bitmask,pcbddc->local_primal_ref_node[i]);CHKERRQ(ierr);
2946a64d13efSStefano Zampini     }
2947a64d13efSStefano Zampini 
2948a64d13efSStefano Zampini     for (i=0, n_R=0; i<pcis->n; i++) {
29494641a718SStefano Zampini       if (!PetscBTLookup(bitmask,i)) {
29506816873aSStefano Zampini         idx_R_local[n_R++] = i;
2951a64d13efSStefano Zampini       }
2952a64d13efSStefano Zampini     }
2953df4d28bfSStefano Zampini   } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */
2954df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
29556816873aSStefano Zampini 
2956df4d28bfSStefano Zampini     ierr = ISGetIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
2957df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_R,&n_R);CHKERRQ(ierr);
29586816873aSStefano Zampini   }
29593a50541eSStefano Zampini 
29603a50541eSStefano Zampini   /* Block code */
29613a50541eSStefano Zampini   vbs = 1;
29623a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
29633a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
29643a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
29653a50541eSStefano Zampini     PetscInt  *vary;
2966b334f244SStefano Zampini     if (!sub_schurs || !sub_schurs->reuse_solver) {
2967785e854fSJed Brown       ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
29683a50541eSStefano Zampini       ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
2969d3df7717SStefano Zampini       /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
2970d3df7717SStefano 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 */
29710e6343abSStefano Zampini       for (i=0; i<n_vertices; i++) vary[pcbddc->local_primal_ref_node[i]/bs]++;
2972d3df7717SStefano Zampini       for (i=0; i<pcis->n/bs; i++) {
29733a50541eSStefano Zampini         if (vary[i]!=0 && vary[i]!=bs) {
29743a50541eSStefano Zampini           is_blocked = PETSC_FALSE;
29753a50541eSStefano Zampini           break;
29763a50541eSStefano Zampini         }
29773a50541eSStefano Zampini       }
2978d3df7717SStefano Zampini       ierr = PetscFree(vary);CHKERRQ(ierr);
2979d3df7717SStefano Zampini     } else {
2980d3df7717SStefano Zampini       /* Verify directly the R set */
2981d3df7717SStefano Zampini       for (i=0; i<n_R/bs; i++) {
2982d3df7717SStefano Zampini         PetscInt j,node=idx_R_local[bs*i];
2983d3df7717SStefano Zampini         for (j=1; j<bs; j++) {
2984d3df7717SStefano Zampini           if (node != idx_R_local[bs*i+j]-j) {
2985d3df7717SStefano Zampini             is_blocked = PETSC_FALSE;
2986d3df7717SStefano Zampini             break;
2987d3df7717SStefano Zampini           }
2988d3df7717SStefano Zampini         }
2989d3df7717SStefano Zampini       }
2990d3df7717SStefano Zampini     }
29913a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
29923a50541eSStefano Zampini       vbs = bs;
29933a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
29943a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
29953a50541eSStefano Zampini       }
29963a50541eSStefano Zampini     }
29973a50541eSStefano Zampini   }
29983a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
2999b334f244SStefano Zampini   if (sub_schurs && sub_schurs->reuse_solver) {
3000df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
300153892102SStefano Zampini 
3002df4d28bfSStefano Zampini     ierr = ISRestoreIndices(reuse_solver->is_R,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
3003df4d28bfSStefano Zampini     ierr = ISDestroy(&reuse_solver->is_R);CHKERRQ(ierr);
300453892102SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->is_R_local);CHKERRQ(ierr);
3005df4d28bfSStefano Zampini     reuse_solver->is_R = pcbddc->is_R_local;
300653892102SStefano Zampini   } else {
30073a50541eSStefano Zampini     ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
300853892102SStefano Zampini   }
3009a64d13efSStefano Zampini 
3010a64d13efSStefano Zampini   /* print some info if requested */
3011a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
3012a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
3013a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
30141575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3015a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
3016a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
30174f1b2e48SStefano 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);
3018a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3019a64d13efSStefano Zampini   }
3020a64d13efSStefano Zampini 
3021a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
3022b334f244SStefano Zampini   if (!sub_schurs || !sub_schurs->reuse_solver) {
30236816873aSStefano Zampini     IS       is_aux1,is_aux2;
30246816873aSStefano Zampini     PetscInt *aux_array1,*aux_array2,*is_indices,*idx_R_local;
30256816873aSStefano Zampini 
30263a50541eSStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
3027854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
3028854ce69bSBarry Smith     ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
3029a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
30304641a718SStefano Zampini     for (i=0; i<n_D; i++) {
30314641a718SStefano Zampini       ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
30324641a718SStefano Zampini     }
3033a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3034a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
30354641a718SStefano Zampini       if (!PetscBTLookup(bitmask,idx_R_local[i])) {
30364641a718SStefano Zampini         aux_array1[j++] = i;
3037a64d13efSStefano Zampini       }
3038a64d13efSStefano Zampini     }
3039a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
3040a64d13efSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3041a64d13efSStefano Zampini     for (i=0, j=0; i<n_B; i++) {
30424641a718SStefano Zampini       if (!PetscBTLookup(bitmask,is_indices[i])) {
30434641a718SStefano Zampini         aux_array2[j++] = i;
3044a64d13efSStefano Zampini       }
3045a64d13efSStefano Zampini     }
3046a64d13efSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3047a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
3048a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
3049a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
3050a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
3051a64d13efSStefano Zampini 
30528eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
3053785e854fSJed Brown       ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
3054a64d13efSStefano Zampini       for (i=0, j=0; i<n_R; i++) {
30554641a718SStefano Zampini         if (PetscBTLookup(bitmask,idx_R_local[i])) {
30564641a718SStefano Zampini           aux_array1[j++] = i;
3057a64d13efSStefano Zampini         }
3058a64d13efSStefano Zampini       }
3059a64d13efSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
3060a64d13efSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
3061a64d13efSStefano Zampini       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
3062a64d13efSStefano Zampini     }
30634641a718SStefano Zampini     ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
30643a50541eSStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
3065d62866d3SStefano Zampini   } else {
3066df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
30676816873aSStefano Zampini     IS                 tis;
30686816873aSStefano Zampini     PetscInt           schur_size;
30696816873aSStefano Zampini 
3070df4d28bfSStefano Zampini     ierr = ISGetLocalSize(reuse_solver->is_B,&schur_size);CHKERRQ(ierr);
30716816873aSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,schur_size,n_D,1,&tis);CHKERRQ(ierr);
3072df4d28bfSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_B,reuse_solver->is_B,&pcbddc->R_to_B);CHKERRQ(ierr);
30736816873aSStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
30746816873aSStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
30756816873aSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_D,0,1,&tis);CHKERRQ(ierr);
30766816873aSStefano Zampini       ierr = VecScatterCreate(pcbddc->vec1_R,tis,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
30776816873aSStefano Zampini       ierr = ISDestroy(&tis);CHKERRQ(ierr);
3078d62866d3SStefano Zampini     }
3079d62866d3SStefano Zampini   }
3080a64d13efSStefano Zampini   PetscFunctionReturn(0);
3081a64d13efSStefano Zampini }
3082a64d13efSStefano Zampini 
3083304d26faSStefano Zampini 
3084304d26faSStefano Zampini #undef __FUNCT__
3085304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
3086684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
3087304d26faSStefano Zampini {
3088304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3089304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
3090304d26faSStefano Zampini   PC             pc_temp;
3091304d26faSStefano Zampini   Mat            A_RR;
3092f4ddd8eeSStefano Zampini   MatReuse       reuse;
3093304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
3094304d26faSStefano Zampini   PetscReal      value;
309504708bb6SStefano Zampini   PetscInt       n_D,n_R;
3096c7017625SStefano Zampini   PetscBool      check_corr[2],issbaij;
3097304d26faSStefano Zampini   PetscErrorCode ierr;
3098e604994aSStefano Zampini   /* prefixes stuff */
3099312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
3100e604994aSStefano Zampini   size_t         len;
3101304d26faSStefano Zampini 
3102304d26faSStefano Zampini   PetscFunctionBegin;
3103304d26faSStefano Zampini 
3104e604994aSStefano Zampini   /* compute prefixes */
3105e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
3106e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
3107e604994aSStefano Zampini   if (!pcbddc->current_level) {
3108e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
3109e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
3110e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
3111e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
3112e604994aSStefano Zampini   } else {
3113e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
3114312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
3115e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
3116e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
3117312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
3118312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
311934d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
312034d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
3121e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
3122e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
3123e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
3124e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
3125e604994aSStefano Zampini   }
3126e604994aSStefano Zampini 
3127304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
3128684f6988SStefano Zampini   if (dirichlet) {
3129d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
3130450f8f5eSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
3131b334f244SStefano Zampini       if (!sub_schurs || !sub_schurs->reuse_solver) {
3132450f8f5eSStefano Zampini         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not yet implemented\n");
3133450f8f5eSStefano Zampini       }
3134450f8f5eSStefano Zampini       if (pcbddc->dbg_flag) {
3135a3df083aSStefano Zampini         Mat    A_IIn;
3136a3df083aSStefano Zampini 
3137a3df083aSStefano Zampini         ierr = PCBDDCBenignProject(pc,pcis->is_I_local,pcis->is_I_local,&A_IIn);CHKERRQ(ierr);
3138a3df083aSStefano Zampini         ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
3139a3df083aSStefano Zampini         pcis->A_II = A_IIn;
3140a3df083aSStefano Zampini       }
3141450f8f5eSStefano Zampini     }
31423301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
31433301b35fSStefano Zampini       ierr = MatSetOption(pcis->A_II,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
3144964fefecSStefano Zampini     }
3145ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
3146964fefecSStefano Zampini     n_D = pcis->n - pcis->n_B;
3147304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
3148304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
3149304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
3150304d26faSStefano Zampini       /* default */
3151304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
3152e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
31539577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
3154304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
31559577ea80SStefano Zampini       if (issbaij) {
31569577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
31579577ea80SStefano Zampini       } else {
3158304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
31599577ea80SStefano Zampini       }
3160304d26faSStefano Zampini       /* Allow user's customization */
3161304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
3162304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
3163304d26faSStefano Zampini     }
3164d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
3165b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
3166df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3167d62866d3SStefano Zampini 
3168df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_D,reuse_solver->interior_solver);CHKERRQ(ierr);
3169d5574798SStefano Zampini     }
3170304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
3171304d26faSStefano Zampini     if (!n_D) {
3172304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
3173304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
3174304d26faSStefano Zampini     }
3175304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
3176304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
3177304d26faSStefano Zampini     /* set ksp_D into pcis data */
3178304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
3179304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
3180304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
3181684f6988SStefano Zampini   }
3182304d26faSStefano Zampini 
3183304d26faSStefano Zampini   /* NEUMANN PROBLEM */
3184684f6988SStefano Zampini   A_RR = 0;
3185684f6988SStefano Zampini   if (neumann) {
3186d62866d3SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
318704708bb6SStefano Zampini     PetscInt        ibs,mbs;
318804708bb6SStefano Zampini     PetscBool       issbaij;
318904708bb6SStefano Zampini     Mat_IS*         matis = (Mat_IS*)pc->pmat->data;
3190f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
31918ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
3192f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
3193f4ddd8eeSStefano Zampini       PetscInt nn_R;
319481d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
3195f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
3196f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
3197f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
3198f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
3199f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3200f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
3201f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
3202727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
3203f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3204f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
3205f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
3206f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
3207f4ddd8eeSStefano Zampini         }
3208f4ddd8eeSStefano Zampini       }
3209f4ddd8eeSStefano Zampini       /* last check */
3210d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
3211f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3212f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
3213f4ddd8eeSStefano Zampini       }
3214f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
3215f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
3216f4ddd8eeSStefano Zampini     }
3217a00504b5SStefano Zampini     /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection */
3218af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
3219af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
322004708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
322104708bb6SStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */
322204708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
322304708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
322404708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
3225af732b37SStefano Zampini       } else {
3226511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
32276816873aSStefano Zampini       }
322804708bb6SStefano Zampini     } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
322904708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
323004708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
323104708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
323204708bb6SStefano Zampini       } else {
3233511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
323404708bb6SStefano Zampini       }
323504708bb6SStefano Zampini     }
3236a00504b5SStefano Zampini     /* extract A_RR */
3237b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
3238a00504b5SStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3239a00504b5SStefano Zampini 
3240a00504b5SStefano Zampini       if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */
324116e386b8SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3242a00504b5SStefano Zampini         if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */
324316e386b8SStefano Zampini           ierr = PCBDDCBenignProject(pc,pcbddc->is_R_local,pcbddc->is_R_local,&A_RR);CHKERRQ(ierr);
324416e386b8SStefano Zampini         } else {
3245a00504b5SStefano Zampini           ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
3246a00504b5SStefano Zampini         }
3247a00504b5SStefano Zampini       } else {
3248a00504b5SStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3249a00504b5SStefano Zampini         ierr = PCGetOperators(reuse_solver->correction_solver,&A_RR,NULL);CHKERRQ(ierr);
3250a00504b5SStefano Zampini         ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
3251a00504b5SStefano Zampini       }
3252a00504b5SStefano Zampini     } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */
3253f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
325416e386b8SStefano Zampini     }
32553301b35fSStefano Zampini     if (pcbddc->local_mat->symmetric_set) {
32563301b35fSStefano Zampini       ierr = MatSetOption(A_RR,MAT_SYMMETRIC,pcbddc->local_mat->symmetric_set);CHKERRQ(ierr);
32576816873aSStefano Zampini     }
3258f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
3259304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
3260304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
3261304d26faSStefano Zampini       /* default */
3262304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
3263e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
3264304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
32659577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
32669577ea80SStefano Zampini       if (issbaij) {
32679577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
32689577ea80SStefano Zampini       } else {
3269304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
32709577ea80SStefano Zampini       }
3271304d26faSStefano Zampini       /* Allow user's customization */
3272304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
3273304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
3274304d26faSStefano Zampini     }
3275304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
3276304d26faSStefano Zampini     if (!n_R) {
3277304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
3278304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
3279304d26faSStefano Zampini     }
32805cbda25cSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
3281df4d28bfSStefano Zampini     /* Reuse solver if it is present */
3282b334f244SStefano Zampini     if (sub_schurs && sub_schurs->reuse_solver) {
3283df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3284d62866d3SStefano Zampini 
3285df4d28bfSStefano Zampini       ierr = KSPSetPC(pcbddc->ksp_R,reuse_solver->correction_solver);CHKERRQ(ierr);
3286d62866d3SStefano Zampini     }
3287304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
3288304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
3289684f6988SStefano Zampini   }
3290304d26faSStefano Zampini 
3291684f6988SStefano Zampini   if (pcbddc->dbg_flag) {
3292684f6988SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
32931575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3294684f6988SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
3295684f6988SStefano Zampini   }
3296c7017625SStefano Zampini 
3297c7017625SStefano Zampini   /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */
3298c7017625SStefano Zampini   check_corr[0] = check_corr[1] = PETSC_FALSE;
3299c7017625SStefano Zampini   if (pcbddc->NullSpace_corr[0]) {
3300c7017625SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
3301c7017625SStefano Zampini   }
3302c7017625SStefano Zampini   if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) {
3303c7017625SStefano Zampini     check_corr[0] = PETSC_TRUE;
3304c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_TRUE,pcbddc->NullSpace_corr[1]);CHKERRQ(ierr);
3305c7017625SStefano Zampini   }
3306c7017625SStefano Zampini   if (neumann && pcbddc->NullSpace_corr[2]) {
3307c7017625SStefano Zampini     check_corr[1] = PETSC_TRUE;
3308c7017625SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,PETSC_FALSE,pcbddc->NullSpace_corr[3]);CHKERRQ(ierr);
3309c7017625SStefano Zampini   }
3310c7017625SStefano Zampini 
3311c7017625SStefano Zampini   /* check Dirichlet and Neumann solvers */
3312c7017625SStefano Zampini   if (pcbddc->dbg_flag) {
3313684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
33140fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
33150fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
33160fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
33170fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
33180fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
3319e604994aSStefano 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);
3320c7017625SStefano Zampini       if (check_corr[0]) {
3321c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_TRUE);CHKERRQ(ierr);
3322c7017625SStefano Zampini       }
3323304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3324304d26faSStefano Zampini     }
3325684f6988SStefano Zampini     if (neumann) { /* Neumann */
33260fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
33270fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
33280fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
33290fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
33300fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
3331e604994aSStefano 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);
3332c7017625SStefano Zampini       if (check_corr[1]) {
3333c7017625SStefano Zampini         ierr = PCBDDCNullSpaceCheckCorrection(pc,PETSC_FALSE);CHKERRQ(ierr);
3334c7017625SStefano Zampini       }
3335304d26faSStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3336304d26faSStefano Zampini     }
3337684f6988SStefano Zampini   }
33385cbda25cSStefano Zampini   /* free Neumann problem's matrix */
33395cbda25cSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
3340304d26faSStefano Zampini   PetscFunctionReturn(0);
3341304d26faSStefano Zampini }
3342304d26faSStefano Zampini 
3343304d26faSStefano Zampini #undef __FUNCT__
3344ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
334580677318SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose)
3346674ae819SStefano Zampini {
3347674ae819SStefano Zampini   PetscErrorCode  ierr;
3348674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
3349be83ff47SStefano Zampini   PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
3350b334f244SStefano Zampini   PetscBool       reuse_solver = sub_schurs ? ( sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE ) : PETSC_FALSE;
3351674ae819SStefano Zampini 
3352674ae819SStefano Zampini   PetscFunctionBegin;
3353b334f244SStefano Zampini   if (!reuse_solver) {
335480677318SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,0.);CHKERRQ(ierr);
335520c7b377SStefano Zampini   }
335680677318SStefano Zampini   if (!pcbddc->switch_static) {
335780677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
335880677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
335980677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
336020c7b377SStefano Zampini     }
3361b334f244SStefano Zampini     if (!reuse_solver) {
336280677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
336380677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
336420c7b377SStefano Zampini     } else {
3365df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3366be83ff47SStefano Zampini 
3367df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3368df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,inout_B,reuse_solver->rhs_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
336920c7b377SStefano Zampini     }
3370be83ff47SStefano Zampini   } else {
337180677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
337280677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
337380677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
337480677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,inout_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
337580677318SStefano Zampini     if (applytranspose && pcbddc->local_auxmat1) {
337680677318SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,pcbddc->vec1_R,pcbddc->vec1_C);CHKERRQ(ierr);
337780677318SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
337880677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
337980677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,inout_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3380674ae819SStefano Zampini     }
3381674ae819SStefano Zampini   }
3382b334f244SStefano Zampini   if (!reuse_solver || pcbddc->switch_static) {
338380677318SStefano Zampini     if (applytranspose) {
338480677318SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
338580677318SStefano Zampini     } else {
338680677318SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
338780677318SStefano Zampini     }
3388be83ff47SStefano Zampini   } else {
3389df4d28bfSStefano Zampini     PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3390be83ff47SStefano Zampini 
3391be83ff47SStefano Zampini     if (applytranspose) {
3392df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplementTranspose(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
3393be83ff47SStefano Zampini     } else {
3394df4d28bfSStefano Zampini       ierr = MatFactorSolveSchurComplement(reuse_solver->F,reuse_solver->rhs_B,reuse_solver->sol_B);CHKERRQ(ierr);
3395be83ff47SStefano Zampini     }
3396be83ff47SStefano Zampini   }
339780677318SStefano Zampini   ierr = VecSet(inout_B,0.);CHKERRQ(ierr);
339880677318SStefano Zampini   if (!pcbddc->switch_static) {
3399b334f244SStefano Zampini     if (!reuse_solver) {
340080677318SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
340180677318SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3402be83ff47SStefano Zampini     } else {
3403df4d28bfSStefano Zampini       PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver;
3404be83ff47SStefano Zampini 
3405df4d28bfSStefano Zampini       ierr = VecScatterBegin(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3406df4d28bfSStefano Zampini       ierr = VecScatterEnd(reuse_solver->correction_scatter_B,reuse_solver->sol_B,inout_B,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3407be83ff47SStefano Zampini     }
340880677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
340980677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
341080677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,inout_B,inout_B);CHKERRQ(ierr);
341180677318SStefano Zampini     }
341280677318SStefano Zampini   } else {
341380677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
341480677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
341580677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
341680677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
341780677318SStefano Zampini     if (!applytranspose && pcbddc->local_auxmat1) {
341880677318SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,inout_B,pcbddc->vec1_C);CHKERRQ(ierr);
341980677318SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
342080677318SStefano Zampini     }
342180677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
342280677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,inout_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
342380677318SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
342480677318SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,inout_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3425674ae819SStefano Zampini   }
3426674ae819SStefano Zampini   PetscFunctionReturn(0);
3427674ae819SStefano Zampini }
3428674ae819SStefano Zampini 
3429dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
3430674ae819SStefano Zampini #undef __FUNCT__
3431674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
3432dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
3433674ae819SStefano Zampini {
3434674ae819SStefano Zampini   PetscErrorCode ierr;
3435674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
3436674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
3437674ae819SStefano Zampini   const PetscScalar zero = 0.0;
3438674ae819SStefano Zampini 
3439674ae819SStefano Zampini   PetscFunctionBegin;
3440dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
34414fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
3442dc359a40SStefano Zampini     if (applytranspose) {
3443674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
34448eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
3445dc359a40SStefano Zampini     } else {
3446674ae819SStefano Zampini       ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
3447674ae819SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
344815aaf578SStefano Zampini     }
34494fee134fSStefano Zampini   } else {
34504fee134fSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
34514fee134fSStefano Zampini   }
3452efc2fbd9SStefano Zampini 
3453efc2fbd9SStefano Zampini   /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */
34544f1b2e48SStefano Zampini   if (pcbddc->benign_n) {
3455efc2fbd9SStefano Zampini     PetscScalar *array;
34564f1b2e48SStefano Zampini     PetscInt    j;
3457efc2fbd9SStefano Zampini 
3458efc2fbd9SStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
34594f1b2e48SStefano Zampini     for (j=0;j<pcbddc->benign_n;j++) array[pcbddc->local_primal_size-pcbddc->benign_n+j] += pcbddc->benign_p0[j];
3460efc2fbd9SStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
3461efc2fbd9SStefano Zampini   }
3462efc2fbd9SStefano Zampini 
346312edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
346412edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
346512edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
346612edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
346712edc857SStefano Zampini 
34689f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
346912edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
347051694757SStefano Zampini     Mat          coarse_mat;
3471964fefecSStefano Zampini     Vec          rhs,sol;
347251694757SStefano Zampini     MatNullSpace nullsp;
347327b6a85dSStefano Zampini     PetscBool    isbddc = PETSC_FALSE;
3474964fefecSStefano Zampini 
347527b6a85dSStefano Zampini     if (pcbddc->benign_have_null) {
347627b6a85dSStefano Zampini       PC        coarse_pc;
347727b6a85dSStefano Zampini 
347827b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
347927b6a85dSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)coarse_pc,PCBDDC,&isbddc);CHKERRQ(ierr);
348027b6a85dSStefano Zampini       /* we need to propagate to coarser levels the need for a possible benign correction */
348127b6a85dSStefano Zampini       if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) {
348227b6a85dSStefano Zampini         PC_BDDC* coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
348327b6a85dSStefano Zampini         coarsepcbddc->benign_skip_correction = PETSC_FALSE;
34843bca92a6SStefano Zampini         coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE;
348527b6a85dSStefano Zampini       }
348627b6a85dSStefano Zampini     }
3487964fefecSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&rhs);CHKERRQ(ierr);
3488964fefecSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&sol);CHKERRQ(ierr);
348951694757SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
349051694757SStefano Zampini     ierr = MatGetNullSpace(coarse_mat,&nullsp);CHKERRQ(ierr);
349151694757SStefano Zampini     if (nullsp) {
349251694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,rhs);CHKERRQ(ierr);
349351694757SStefano Zampini     }
349412edc857SStefano Zampini     if (applytranspose) {
34951f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only) {
34961f4df5f7SStefano Zampini         SETERRQ(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),PETSC_ERR_SUP,"Not yet implemented");
34972701bc32SStefano Zampini       } else {
3498964fefecSStefano Zampini         ierr = KSPSolveTranspose(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
34992701bc32SStefano Zampini       }
35002701bc32SStefano Zampini     } else {
35011f4df5f7SStefano Zampini       if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */
35022701bc32SStefano Zampini         PC        coarse_pc;
35032701bc32SStefano Zampini 
35042701bc32SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
35052701bc32SStefano Zampini         ierr = PCPreSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
35063e589ea0SStefano Zampini         ierr = PCBDDCBenignRemoveInterior(coarse_pc,rhs,sol);CHKERRQ(ierr);
35072701bc32SStefano Zampini         ierr = PCPostSolve(coarse_pc,pcbddc->coarse_ksp);CHKERRQ(ierr);
350812edc857SStefano Zampini       } else {
3509964fefecSStefano Zampini         ierr = KSPSolve(pcbddc->coarse_ksp,rhs,sol);CHKERRQ(ierr);
351012edc857SStefano Zampini       }
35112701bc32SStefano Zampini     }
35121d82a3b6SStefano Zampini     /* we don't need the benign correction at coarser levels anymore */
351327b6a85dSStefano Zampini     if (pcbddc->benign_have_null && isbddc) {
351427b6a85dSStefano Zampini       PC        coarse_pc;
351527b6a85dSStefano Zampini       PC_BDDC*  coarsepcbddc;
351627b6a85dSStefano Zampini 
351727b6a85dSStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&coarse_pc);CHKERRQ(ierr);
351827b6a85dSStefano Zampini       coarsepcbddc = (PC_BDDC*)(coarse_pc->data);
351927b6a85dSStefano Zampini       coarsepcbddc->benign_skip_correction = PETSC_TRUE;
35203bca92a6SStefano Zampini       coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE;
352127b6a85dSStefano Zampini     }
352251694757SStefano Zampini     if (nullsp) {
352351694757SStefano Zampini       ierr = MatNullSpaceRemove(nullsp,sol);CHKERRQ(ierr);
352451694757SStefano Zampini     }
352512edc857SStefano Zampini   }
3526674ae819SStefano Zampini 
3527674ae819SStefano Zampini   /* Local solution on R nodes */
35284fee134fSStefano Zampini   if (pcis->n && !pcbddc->benign_apply_coarse_only) {
352980677318SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcis->vec1_B,pcis->vec1_D,applytranspose);CHKERRQ(ierr);
35309f00e9b4SStefano Zampini   }
35319f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
35329f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
353312edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3534674ae819SStefano Zampini 
35354fee134fSStefano Zampini   /* Sum contributions from the two levels */
35364fee134fSStefano Zampini   if (!pcbddc->benign_apply_coarse_only) {
3537dc359a40SStefano Zampini     if (applytranspose) {
3538dc359a40SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
3539dc359a40SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
3540dc359a40SStefano Zampini     } else {
3541674ae819SStefano Zampini       ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
35428eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
3543dc359a40SStefano Zampini     }
3544efc2fbd9SStefano Zampini     /* store p0 */
35454f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
3546efc2fbd9SStefano Zampini       PetscScalar *array;
35474f1b2e48SStefano Zampini       PetscInt    j;
3548efc2fbd9SStefano Zampini 
3549efc2fbd9SStefano Zampini       ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
35504f1b2e48SStefano Zampini       for (j=0;j<pcbddc->benign_n;j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size-pcbddc->benign_n+j];
3551efc2fbd9SStefano Zampini       ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
3552efc2fbd9SStefano Zampini     }
35534fee134fSStefano Zampini   } else { /* expand the coarse solution */
35544fee134fSStefano Zampini     if (applytranspose) {
35554fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
35564fee134fSStefano Zampini     } else {
35574fee134fSStefano Zampini       ierr = MatMult(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B);CHKERRQ(ierr);
35584fee134fSStefano Zampini     }
35594fee134fSStefano Zampini   }
3560674ae819SStefano Zampini   PetscFunctionReturn(0);
3561674ae819SStefano Zampini }
3562674ae819SStefano Zampini 
3563674ae819SStefano Zampini #undef __FUNCT__
3564674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
356512edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
3566674ae819SStefano Zampini {
3567674ae819SStefano Zampini   PetscErrorCode ierr;
3568674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
356958da7f69SStefano Zampini   PetscScalar    *array;
357012edc857SStefano Zampini   Vec            from,to;
3571674ae819SStefano Zampini 
3572674ae819SStefano Zampini   PetscFunctionBegin;
357312edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
357412edc857SStefano Zampini     from = pcbddc->coarse_vec;
357512edc857SStefano Zampini     to = pcbddc->vec1_P;
357612edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
357712edc857SStefano Zampini       Vec tvec;
357858da7f69SStefano Zampini 
357958da7f69SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
358058da7f69SStefano Zampini       ierr = VecResetArray(tvec);CHKERRQ(ierr);
358112edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
358258da7f69SStefano Zampini       ierr = VecGetArray(tvec,&array);CHKERRQ(ierr);
358358da7f69SStefano Zampini       ierr = VecPlaceArray(from,array);CHKERRQ(ierr);
358458da7f69SStefano Zampini       ierr = VecRestoreArray(tvec,&array);CHKERRQ(ierr);
358512edc857SStefano Zampini     }
358612edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
358712edc857SStefano Zampini     from = pcbddc->vec1_P;
358812edc857SStefano Zampini     to = pcbddc->coarse_vec;
358912edc857SStefano Zampini   }
359012edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
3591674ae819SStefano Zampini   PetscFunctionReturn(0);
3592674ae819SStefano Zampini }
3593674ae819SStefano Zampini 
3594674ae819SStefano Zampini #undef __FUNCT__
3595674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
359612edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
3597674ae819SStefano Zampini {
3598674ae819SStefano Zampini   PetscErrorCode ierr;
3599674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
360058da7f69SStefano Zampini   PetscScalar    *array;
360112edc857SStefano Zampini   Vec            from,to;
3602674ae819SStefano Zampini 
3603674ae819SStefano Zampini   PetscFunctionBegin;
360412edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
360512edc857SStefano Zampini     from = pcbddc->coarse_vec;
360612edc857SStefano Zampini     to = pcbddc->vec1_P;
360712edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
360812edc857SStefano Zampini     from = pcbddc->vec1_P;
360912edc857SStefano Zampini     to = pcbddc->coarse_vec;
361012edc857SStefano Zampini   }
361112edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
361212edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
361312edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
361412edc857SStefano Zampini       Vec tvec;
361558da7f69SStefano Zampini 
361612edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
361758da7f69SStefano Zampini       ierr = VecGetArray(to,&array);CHKERRQ(ierr);
361858da7f69SStefano Zampini       ierr = VecPlaceArray(tvec,array);CHKERRQ(ierr);
361958da7f69SStefano Zampini       ierr = VecRestoreArray(to,&array);CHKERRQ(ierr);
362058da7f69SStefano Zampini     }
362158da7f69SStefano Zampini   } else {
362258da7f69SStefano Zampini     if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */
362358da7f69SStefano Zampini      ierr = VecResetArray(from);CHKERRQ(ierr);
362412edc857SStefano Zampini     }
362512edc857SStefano Zampini   }
3626674ae819SStefano Zampini   PetscFunctionReturn(0);
3627674ae819SStefano Zampini }
3628674ae819SStefano Zampini 
3629984c4197SStefano Zampini /* uncomment for testing purposes */
3630984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
3631674ae819SStefano Zampini #undef __FUNCT__
3632674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
3633674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
3634674ae819SStefano Zampini {
3635674ae819SStefano Zampini   PetscErrorCode    ierr;
3636674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
3637674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
3638674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
3639984c4197SStefano Zampini   /* one and zero */
3640984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
3641984c4197SStefano Zampini   /* space to store constraints and their local indices */
36429162d606SStefano Zampini   PetscScalar       *constraints_data;
36439162d606SStefano Zampini   PetscInt          *constraints_idxs,*constraints_idxs_B;
36449162d606SStefano Zampini   PetscInt          *constraints_idxs_ptr,*constraints_data_ptr;
36459162d606SStefano Zampini   PetscInt          *constraints_n;
3646984c4197SStefano Zampini   /* iterators */
3647b3d85658SStefano Zampini   PetscInt          i,j,k,total_counts,total_counts_cc,cum;
3648984c4197SStefano Zampini   /* BLAS integers */
3649e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
3650e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
3651c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
3652727cdba6SStefano Zampini   /* reuse */
36530e6343abSStefano Zampini   PetscInt          olocal_primal_size,olocal_primal_size_cc;
36540e6343abSStefano Zampini   PetscInt          *olocal_primal_ref_node,*olocal_primal_ref_mult;
3655984c4197SStefano Zampini   /* change of basis */
3656b3d85658SStefano Zampini   PetscBool         qr_needed;
36579162d606SStefano Zampini   PetscBT           change_basis,qr_needed_idx;
3658984c4197SStefano Zampini   /* auxiliary stuff */
365964efe560SStefano Zampini   PetscInt          *nnz,*is_indices;
36608a0068c3SStefano Zampini   PetscInt          ncc;
3661984c4197SStefano Zampini   /* some quantities */
366245a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
3663a58a30b4SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint=0,max_constraints,temp_constraints;
3664984c4197SStefano Zampini 
3665674ae819SStefano Zampini   PetscFunctionBegin;
36668e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
36678e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
36688e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
366916909a7fSStefano Zampini   ierr = MatDestroy(&pcbddc->switch_static_change);CHKERRQ(ierr);
3670088faed8SStefano Zampini   /* save info on constraints from previous setup (if any) */
3671088faed8SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
36720e6343abSStefano Zampini   olocal_primal_size_cc = pcbddc->local_primal_size_cc;
36730e6343abSStefano Zampini   ierr = PetscMalloc2(olocal_primal_size_cc,&olocal_primal_ref_node,olocal_primal_size_cc,&olocal_primal_ref_mult);CHKERRQ(ierr);
36740e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_node,pcbddc->local_primal_ref_node,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
36750e6343abSStefano Zampini   ierr = PetscMemcpy(olocal_primal_ref_mult,pcbddc->local_primal_ref_mult,olocal_primal_size_cc*sizeof(PetscInt));CHKERRQ(ierr);
36760e6343abSStefano Zampini   ierr = PetscFree2(pcbddc->local_primal_ref_node,pcbddc->local_primal_ref_mult);CHKERRQ(ierr);
3677088faed8SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
3678cf5a6209SStefano Zampini 
3679cf5a6209SStefano Zampini   if (!pcbddc->adaptive_selection) {
36809162d606SStefano Zampini     IS           ISForVertices,*ISForFaces,*ISForEdges;
3681cf5a6209SStefano Zampini     MatNullSpace nearnullsp;
3682cf5a6209SStefano Zampini     const Vec    *nearnullvecs;
3683cf5a6209SStefano Zampini     Vec          *localnearnullsp;
3684cf5a6209SStefano Zampini     PetscScalar  *array;
3685cf5a6209SStefano Zampini     PetscInt     n_ISForFaces,n_ISForEdges,nnsp_size;
3686cf5a6209SStefano Zampini     PetscBool    nnsp_has_cnst;
3687674ae819SStefano Zampini     /* LAPACK working arrays for SVD or POD */
3688b3d85658SStefano Zampini     PetscBool    skip_lapack,boolforchange;
3689674ae819SStefano Zampini     PetscScalar  *work;
3690674ae819SStefano Zampini     PetscReal    *singular_vals;
3691674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3692674ae819SStefano Zampini     PetscReal    *rwork;
3693674ae819SStefano Zampini #endif
3694674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3695674ae819SStefano Zampini     PetscScalar  *temp_basis,*correlation_mat;
3696674ae819SStefano Zampini #else
3697964fefecSStefano Zampini     PetscBLASInt dummy_int=1;
3698964fefecSStefano Zampini     PetscScalar  dummy_scalar=1.;
3699674ae819SStefano Zampini #endif
3700674ae819SStefano Zampini 
3701674ae819SStefano Zampini     /* Get index sets for faces, edges and vertices from graph */
3702d06fc5fdSStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
3703e4d548c7SStefano Zampini     /* print some info */
37041f4df5f7SStefano Zampini     if (pcbddc->dbg_flag && !pcbddc->sub_schurs) {
3705e4d548c7SStefano Zampini       PetscInt nv;
3706e4d548c7SStefano Zampini 
3707e4d548c7SStefano Zampini       ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
3708e4d548c7SStefano Zampini       ierr = ISGetSize(ISForVertices,&nv);CHKERRQ(ierr);
3709e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3710e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3711e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
3712e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,n_ISForEdges,pcbddc->use_edges);CHKERRQ(ierr);
3713e4d548c7SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,n_ISForFaces,pcbddc->use_faces);CHKERRQ(ierr);
3714e4d548c7SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3715e4d548c7SStefano Zampini       ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
3716e4d548c7SStefano Zampini     }
3717e4d548c7SStefano Zampini 
3718d06fc5fdSStefano Zampini     /* free unneeded index sets */
3719d06fc5fdSStefano Zampini     if (!pcbddc->use_vertices) {
3720d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
3721674ae819SStefano Zampini     }
3722d06fc5fdSStefano Zampini     if (!pcbddc->use_edges) {
3723d06fc5fdSStefano Zampini       for (i=0;i<n_ISForEdges;i++) {
3724d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
3725d06fc5fdSStefano Zampini       }
3726d06fc5fdSStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
3727d06fc5fdSStefano Zampini       n_ISForEdges = 0;
3728d06fc5fdSStefano Zampini     }
3729d06fc5fdSStefano Zampini     if (!pcbddc->use_faces) {
3730d06fc5fdSStefano Zampini       for (i=0;i<n_ISForFaces;i++) {
3731d06fc5fdSStefano Zampini         ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
3732d06fc5fdSStefano Zampini       }
3733d06fc5fdSStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
3734d06fc5fdSStefano Zampini       n_ISForFaces = 0;
3735d06fc5fdSStefano Zampini     }
373670022509SStefano Zampini 
3737674ae819SStefano Zampini     /* check if near null space is attached to global mat */
3738674ae819SStefano Zampini     ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
3739674ae819SStefano Zampini     if (nearnullsp) {
3740674ae819SStefano Zampini       ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
3741f4ddd8eeSStefano Zampini       /* remove any stored info */
3742f4ddd8eeSStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
3743f4ddd8eeSStefano Zampini       ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3744f4ddd8eeSStefano Zampini       /* store information for BDDC solver reuse */
3745f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
3746f4ddd8eeSStefano Zampini       pcbddc->onearnullspace = nearnullsp;
3747473ba861SJed Brown       ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
3748f4ddd8eeSStefano Zampini       for (i=0;i<nnsp_size;i++) {
3749f4ddd8eeSStefano Zampini         ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
3750f4ddd8eeSStefano Zampini       }
3751984c4197SStefano Zampini     } else { /* if near null space is not provided BDDC uses constants by default */
3752984c4197SStefano Zampini       nnsp_size = 0;
3753674ae819SStefano Zampini       nnsp_has_cnst = PETSC_TRUE;
3754674ae819SStefano Zampini     }
3755984c4197SStefano Zampini     /* get max number of constraints on a single cc */
3756984c4197SStefano Zampini     max_constraints = nnsp_size;
3757984c4197SStefano Zampini     if (nnsp_has_cnst) max_constraints++;
3758984c4197SStefano Zampini 
3759674ae819SStefano Zampini     /*
3760674ae819SStefano Zampini          Evaluate maximum storage size needed by the procedure
37619162d606SStefano Zampini          - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]"
37629162d606SStefano Zampini          - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]"
37639162d606SStefano Zampini          There can be multiple constraints per connected component
3764674ae819SStefano Zampini                                                                                                                                                            */
3765674ae819SStefano Zampini     n_vertices = 0;
3766674ae819SStefano Zampini     if (ISForVertices) {
3767674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
3768674ae819SStefano Zampini     }
37699162d606SStefano Zampini     ncc = n_vertices+n_ISForFaces+n_ISForEdges;
37709162d606SStefano Zampini     ierr = PetscMalloc3(ncc+1,&constraints_idxs_ptr,ncc+1,&constraints_data_ptr,ncc,&constraints_n);CHKERRQ(ierr);
37719162d606SStefano Zampini 
37729162d606SStefano Zampini     total_counts = n_ISForFaces+n_ISForEdges;
37739162d606SStefano Zampini     total_counts *= max_constraints;
3774674ae819SStefano Zampini     total_counts += n_vertices;
37754641a718SStefano Zampini     ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
37769162d606SStefano Zampini 
3777674ae819SStefano Zampini     total_counts = 0;
3778674ae819SStefano Zampini     max_size_of_constraint = 0;
3779674ae819SStefano Zampini     for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
37809162d606SStefano Zampini       IS used_is;
3781674ae819SStefano Zampini       if (i<n_ISForEdges) {
37829162d606SStefano Zampini         used_is = ISForEdges[i];
3783674ae819SStefano Zampini       } else {
37849162d606SStefano Zampini         used_is = ISForFaces[i-n_ISForEdges];
3785674ae819SStefano Zampini       }
37869162d606SStefano Zampini       ierr = ISGetSize(used_is,&j);CHKERRQ(ierr);
3787674ae819SStefano Zampini       total_counts += j;
3788674ae819SStefano Zampini       max_size_of_constraint = PetscMax(j,max_size_of_constraint);
3789674ae819SStefano Zampini     }
37909162d606SStefano 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);
37919162d606SStefano Zampini 
3792984c4197SStefano Zampini     /* get local part of global near null space vectors */
3793785e854fSJed Brown     ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
3794984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
3795984c4197SStefano Zampini       ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
3796e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3797e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3798984c4197SStefano Zampini     }
3799674ae819SStefano Zampini 
3800242a89d7SStefano Zampini     /* whether or not to skip lapack calls */
3801242a89d7SStefano Zampini     skip_lapack = PETSC_TRUE;
3802a773dcb8SStefano Zampini     if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
3803242a89d7SStefano Zampini 
3804984c4197SStefano Zampini     /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
3805a773dcb8SStefano Zampini     if (!skip_lapack) {
3806674ae819SStefano Zampini       PetscScalar temp_work;
3807911cabfeSStefano Zampini 
3808674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3809984c4197SStefano Zampini       /* Proper Orthogonal Decomposition (POD) using the snapshot method */
3810785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
3811785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
3812785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
3813674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3814785e854fSJed Brown       ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
3815674ae819SStefano Zampini #endif
3816674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
3817c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
3818c8244a33SStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
3819674ae819SStefano Zampini       lwork = -1;
3820674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3821674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
3822c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
3823674ae819SStefano Zampini #else
3824c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
3825674ae819SStefano Zampini #endif
3826674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3827984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
3828674ae819SStefano Zampini #else /* on missing GESVD */
3829674ae819SStefano Zampini       /* SVD */
3830674ae819SStefano Zampini       PetscInt max_n,min_n;
3831674ae819SStefano Zampini       max_n = max_size_of_constraint;
3832984c4197SStefano Zampini       min_n = max_constraints;
3833984c4197SStefano Zampini       if (max_size_of_constraint < max_constraints) {
3834674ae819SStefano Zampini         min_n = max_size_of_constraint;
3835984c4197SStefano Zampini         max_n = max_constraints;
3836674ae819SStefano Zampini       }
3837785e854fSJed Brown       ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
3838674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
3839785e854fSJed Brown       ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
3840674ae819SStefano Zampini #endif
3841674ae819SStefano Zampini       /* now we evaluate the optimal workspace using query with lwork=-1 */
3842674ae819SStefano Zampini       lwork = -1;
3843e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
3844e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
3845b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
3846674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3847674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
38489162d606SStefano 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));
3849674ae819SStefano Zampini #else
38509162d606SStefano 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));
3851674ae819SStefano Zampini #endif
3852674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
3853984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
3854984c4197SStefano Zampini #endif /* on missing GESVD */
3855674ae819SStefano Zampini       /* Allocate optimal workspace */
3856674ae819SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
3857854ce69bSBarry Smith       ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
3858674ae819SStefano Zampini     }
3859674ae819SStefano Zampini     /* Now we can loop on constraining sets */
3860674ae819SStefano Zampini     total_counts = 0;
38619162d606SStefano Zampini     constraints_idxs_ptr[0] = 0;
38629162d606SStefano Zampini     constraints_data_ptr[0] = 0;
3863674ae819SStefano Zampini     /* vertices */
38649162d606SStefano Zampini     if (n_vertices) {
3865674ae819SStefano Zampini       ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
38669162d606SStefano Zampini       ierr = PetscMemcpy(constraints_idxs,is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
3867674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
38689162d606SStefano Zampini         constraints_n[total_counts] = 1;
38699162d606SStefano Zampini         constraints_data[total_counts] = 1.0;
38709162d606SStefano Zampini         constraints_idxs_ptr[total_counts+1] = constraints_idxs_ptr[total_counts]+1;
38719162d606SStefano Zampini         constraints_data_ptr[total_counts+1] = constraints_data_ptr[total_counts]+1;
3872674ae819SStefano Zampini         total_counts++;
3873674ae819SStefano Zampini       }
3874674ae819SStefano Zampini       ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3875674ae819SStefano Zampini       n_vertices = total_counts;
3876674ae819SStefano Zampini     }
3877984c4197SStefano Zampini 
3878674ae819SStefano Zampini     /* edges and faces */
38799162d606SStefano Zampini     total_counts_cc = total_counts;
3880911cabfeSStefano Zampini     for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
38819162d606SStefano Zampini       IS        used_is;
38829162d606SStefano Zampini       PetscBool idxs_copied = PETSC_FALSE;
38839162d606SStefano Zampini 
3884911cabfeSStefano Zampini       if (ncc<n_ISForEdges) {
38859162d606SStefano Zampini         used_is = ISForEdges[ncc];
3886984c4197SStefano Zampini         boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
3887674ae819SStefano Zampini       } else {
38889162d606SStefano Zampini         used_is = ISForFaces[ncc-n_ISForEdges];
3889984c4197SStefano Zampini         boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
3890674ae819SStefano Zampini       }
3891674ae819SStefano Zampini       temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
38929162d606SStefano Zampini 
38939162d606SStefano Zampini       ierr = ISGetSize(used_is,&size_of_constraint);CHKERRQ(ierr);
38949162d606SStefano Zampini       ierr = ISGetIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3895984c4197SStefano Zampini       /* change of basis should not be performed on local periodic nodes */
3896984c4197SStefano Zampini       if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
3897674ae819SStefano Zampini       if (nnsp_has_cnst) {
38985b08dc53SStefano Zampini         PetscScalar quad_value;
38999162d606SStefano Zampini 
39009162d606SStefano Zampini         ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
39019162d606SStefano Zampini         idxs_copied = PETSC_TRUE;
39029162d606SStefano Zampini 
3903a773dcb8SStefano Zampini         if (!pcbddc->use_nnsp_true) {
3904674ae819SStefano Zampini           quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
3905a773dcb8SStefano Zampini         } else {
3906a773dcb8SStefano Zampini           quad_value = 1.0;
3907a773dcb8SStefano Zampini         }
3908674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
39099162d606SStefano Zampini           constraints_data[constraints_data_ptr[total_counts_cc]+j] = quad_value;
3910674ae819SStefano Zampini         }
39119162d606SStefano Zampini         temp_constraints++;
3912674ae819SStefano Zampini         total_counts++;
3913674ae819SStefano Zampini       }
3914674ae819SStefano Zampini       for (k=0;k<nnsp_size;k++) {
3915984c4197SStefano Zampini         PetscReal real_value;
39169162d606SStefano Zampini         PetscScalar *ptr_to_data;
39179162d606SStefano Zampini 
3918984c4197SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
39199162d606SStefano Zampini         ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]+temp_constraints*size_of_constraint];
3920674ae819SStefano Zampini         for (j=0;j<size_of_constraint;j++) {
39219162d606SStefano Zampini           ptr_to_data[j] = array[is_indices[j]];
3922674ae819SStefano Zampini         }
3923984c4197SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
3924984c4197SStefano Zampini         /* check if array is null on the connected component */
3925e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
39269162d606SStefano Zampini         PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,ptr_to_data,&Blas_one));
39275b08dc53SStefano Zampini         if (real_value > 0.0) { /* keep indices and values */
3928674ae819SStefano Zampini           temp_constraints++;
3929674ae819SStefano Zampini           total_counts++;
39309162d606SStefano Zampini           if (!idxs_copied) {
39319162d606SStefano Zampini             ierr = PetscMemcpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
39329162d606SStefano Zampini             idxs_copied = PETSC_TRUE;
3933674ae819SStefano Zampini           }
3934674ae819SStefano Zampini         }
39359162d606SStefano Zampini       }
39369162d606SStefano Zampini       ierr = ISRestoreIndices(used_is,(const PetscInt**)&is_indices);CHKERRQ(ierr);
393745a1bb75SStefano Zampini       valid_constraints = temp_constraints;
3938eb97c9d2SStefano Zampini       if (!pcbddc->use_nnsp_true && temp_constraints) {
3939a773dcb8SStefano Zampini         if (temp_constraints == 1) { /* just normalize the constraint */
39409162d606SStefano Zampini           PetscScalar norm,*ptr_to_data;
39419162d606SStefano Zampini 
39429162d606SStefano Zampini           ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
3943a773dcb8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
39449162d606SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,ptr_to_data,&Blas_one,ptr_to_data,&Blas_one));
3945a773dcb8SStefano Zampini           norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
39469162d606SStefano Zampini           PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,ptr_to_data,&Blas_one));
3947a773dcb8SStefano Zampini         } else { /* perform SVD */
3948984c4197SStefano Zampini           PetscReal   tol = 1.0e-8; /* tolerance for retaining eigenmodes */
39499162d606SStefano Zampini           PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]];
3950674ae819SStefano Zampini 
3951674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
3952984c4197SStefano Zampini           /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
3953984c4197SStefano Zampini              POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
3954984c4197SStefano Zampini              -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
3955984c4197SStefano Zampini                 the constraints basis will differ (by a complex factor with absolute value equal to 1)
3956984c4197SStefano Zampini                 from that computed using LAPACKgesvd
3957984c4197SStefano Zampini              -> This is due to a different computation of eigenvectors in LAPACKheev
3958984c4197SStefano Zampini              -> The quality of the POD-computed basis will be the same */
3959984c4197SStefano Zampini           ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
3960674ae819SStefano Zampini           /* Store upper triangular part of correlation matrix */
3961e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
3962984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
3963674ae819SStefano Zampini           for (j=0;j<temp_constraints;j++) {
3964674ae819SStefano Zampini             for (k=0;k<j+1;k++) {
39659162d606SStefano 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));
3966674ae819SStefano Zampini             }
3967674ae819SStefano Zampini           }
3968e310c8b4SStefano Zampini           /* compute eigenvalues and eigenvectors of correlation matrix */
3969e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3970e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
3971674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
3972c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
3973674ae819SStefano Zampini #else
3974c8244a33SStefano Zampini           PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
3975674ae819SStefano Zampini #endif
3976674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
3977984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
3978984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
3979674ae819SStefano Zampini           j = 0;
3980984c4197SStefano Zampini           while (j < temp_constraints && singular_vals[j] < tol) j++;
3981674ae819SStefano Zampini           total_counts = total_counts-j;
398245a1bb75SStefano Zampini           valid_constraints = temp_constraints-j;
3983e310c8b4SStefano Zampini           /* scale and copy POD basis into used quadrature memory */
3984c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
3985c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
3986c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
3987c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
3988c4303822SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
3989c4303822SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
3990674ae819SStefano Zampini           if (j<temp_constraints) {
3991984c4197SStefano Zampini             PetscInt ii;
3992984c4197SStefano Zampini             for (k=j;k<temp_constraints;k++) singular_vals[k] = 1.0/PetscSqrtReal(singular_vals[k]);
3993674ae819SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
39949162d606SStefano 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));
3995674ae819SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
3996984c4197SStefano Zampini             for (k=0;k<temp_constraints-j;k++) {
3997674ae819SStefano Zampini               for (ii=0;ii<size_of_constraint;ii++) {
39989162d606SStefano 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];
3999674ae819SStefano Zampini               }
4000674ae819SStefano Zampini             }
4001674ae819SStefano Zampini           }
4002674ae819SStefano Zampini #else  /* on missing GESVD */
4003e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
4004e310c8b4SStefano Zampini           ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
4005b7d8b9f8SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4006674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
4007674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
40089162d606SStefano 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));
4009674ae819SStefano Zampini #else
40109162d606SStefano 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));
4011674ae819SStefano Zampini #endif
4012984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
4013674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4014984c4197SStefano Zampini           /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
4015e310c8b4SStefano Zampini           k = temp_constraints;
4016e310c8b4SStefano Zampini           if (k > size_of_constraint) k = size_of_constraint;
4017674ae819SStefano Zampini           j = 0;
4018e310c8b4SStefano Zampini           while (j < k && singular_vals[k-j-1] < tol) j++;
401945a1bb75SStefano Zampini           valid_constraints = k-j;
4020911cabfeSStefano Zampini           total_counts = total_counts-temp_constraints+valid_constraints;
4021984c4197SStefano Zampini #endif /* on missing GESVD */
4022674ae819SStefano Zampini         }
4023a773dcb8SStefano Zampini       }
40249162d606SStefano Zampini       /* update pointers information */
40259162d606SStefano Zampini       if (valid_constraints) {
40269162d606SStefano Zampini         constraints_n[total_counts_cc] = valid_constraints;
40279162d606SStefano Zampini         constraints_idxs_ptr[total_counts_cc+1] = constraints_idxs_ptr[total_counts_cc]+size_of_constraint;
40289162d606SStefano Zampini         constraints_data_ptr[total_counts_cc+1] = constraints_data_ptr[total_counts_cc]+size_of_constraint*valid_constraints;
40299162d606SStefano Zampini         /* set change_of_basis flag */
403045a1bb75SStefano Zampini         if (boolforchange) {
4031b3d85658SStefano Zampini           PetscBTSet(change_basis,total_counts_cc);
40329162d606SStefano Zampini         }
4033b3d85658SStefano Zampini         total_counts_cc++;
403445a1bb75SStefano Zampini       }
403545a1bb75SStefano Zampini     }
4036984c4197SStefano Zampini     /* free workspace */
40378f1c130eSStefano Zampini     if (!skip_lapack) {
4038984c4197SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
4039984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
4040984c4197SStefano Zampini       ierr = PetscFree(rwork);CHKERRQ(ierr);
4041984c4197SStefano Zampini #endif
4042984c4197SStefano Zampini       ierr = PetscFree(singular_vals);CHKERRQ(ierr);
4043984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
4044984c4197SStefano Zampini       ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
4045984c4197SStefano Zampini       ierr = PetscFree(temp_basis);CHKERRQ(ierr);
4046984c4197SStefano Zampini #endif
4047984c4197SStefano Zampini     }
4048984c4197SStefano Zampini     for (k=0;k<nnsp_size;k++) {
4049984c4197SStefano Zampini       ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
4050984c4197SStefano Zampini     }
4051984c4197SStefano Zampini     ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
4052cf5a6209SStefano Zampini     /* free index sets of faces, edges and vertices */
4053cf5a6209SStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
4054cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
4055cf5a6209SStefano Zampini     }
4056cf5a6209SStefano Zampini     if (n_ISForFaces) {
4057cf5a6209SStefano Zampini       ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
4058cf5a6209SStefano Zampini     }
4059cf5a6209SStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
4060cf5a6209SStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
4061cf5a6209SStefano Zampini     }
4062cf5a6209SStefano Zampini     if (n_ISForEdges) {
4063cf5a6209SStefano Zampini       ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
4064cf5a6209SStefano Zampini     }
4065cf5a6209SStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
406608122e43SStefano Zampini   } else {
406708122e43SStefano Zampini     PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs;
4068984c4197SStefano Zampini 
406908122e43SStefano Zampini     total_counts = 0;
407008122e43SStefano Zampini     n_vertices = 0;
4071d62866d3SStefano Zampini     if (sub_schurs->is_vertices && pcbddc->use_vertices) {
4072d62866d3SStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
407308122e43SStefano Zampini     }
407408122e43SStefano Zampini     max_constraints = 0;
40759162d606SStefano Zampini     total_counts_cc = 0;
407608122e43SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
407708122e43SStefano Zampini       total_counts += pcbddc->adaptive_constraints_n[i];
40789162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++;
407908122e43SStefano Zampini       max_constraints = PetscMax(max_constraints,pcbddc->adaptive_constraints_n[i]);
408008122e43SStefano Zampini     }
40819162d606SStefano Zampini     constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr;
40829162d606SStefano Zampini     constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr;
40839162d606SStefano Zampini     constraints_idxs = pcbddc->adaptive_constraints_idxs;
40849162d606SStefano Zampini     constraints_data = pcbddc->adaptive_constraints_data;
408574d5cdf7SStefano Zampini     /* constraints_n differs from pcbddc->adaptive_constraints_n */
40869162d606SStefano Zampini     ierr = PetscMalloc1(total_counts_cc,&constraints_n);CHKERRQ(ierr);
40879162d606SStefano Zampini     total_counts_cc = 0;
40889162d606SStefano Zampini     for (i=0;i<sub_schurs->n_subs+n_vertices;i++) {
40899162d606SStefano Zampini       if (pcbddc->adaptive_constraints_n[i]) {
40909162d606SStefano Zampini         constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i];
409108122e43SStefano Zampini       }
409208122e43SStefano Zampini     }
40939162d606SStefano Zampini #if 0
40949162d606SStefano Zampini     printf("Found %d totals (%d)\n",total_counts_cc,total_counts);
40959162d606SStefano Zampini     for (i=0;i<total_counts_cc;i++) {
40969162d606SStefano Zampini       printf("const %d, start %d",i,constraints_idxs_ptr[i]);
40979162d606SStefano Zampini       printf(" end %d:\n",constraints_idxs_ptr[i+1]);
40989162d606SStefano Zampini       for (j=constraints_idxs_ptr[i];j<constraints_idxs_ptr[i+1];j++) {
40999162d606SStefano Zampini         printf(" %d",constraints_idxs[j]);
41009162d606SStefano Zampini       }
41019162d606SStefano Zampini       printf("\n");
41029162d606SStefano Zampini       printf("number of cc: %d\n",constraints_n[i]);
41039162d606SStefano Zampini     }
41041b968477SStefano Zampini     for (i=0;i<n_vertices;i++) {
41058bec7fa6SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] vertex %d, n %d\n",PetscGlobalRank,i,pcbddc->adaptive_constraints_n[i]);
41061b968477SStefano Zampini     }
41071b968477SStefano Zampini     for (i=0;i<sub_schurs->n_subs;i++) {
41088bec7fa6SStefano 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]);
41091b968477SStefano Zampini     }
411008122e43SStefano Zampini #endif
411108122e43SStefano Zampini 
41128bec7fa6SStefano Zampini     max_size_of_constraint = 0;
41139162d606SStefano 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]);
41149162d606SStefano Zampini     ierr = PetscMalloc1(constraints_idxs_ptr[total_counts_cc],&constraints_idxs_B);CHKERRQ(ierr);
411508122e43SStefano Zampini     /* Change of basis */
4116b3d85658SStefano Zampini     ierr = PetscBTCreate(total_counts_cc,&change_basis);CHKERRQ(ierr);
411708122e43SStefano Zampini     if (pcbddc->use_change_of_basis) {
411808122e43SStefano Zampini       for (i=0;i<sub_schurs->n_subs;i++) {
411908122e43SStefano Zampini         if (PetscBTLookup(sub_schurs->is_edge,i) || pcbddc->use_change_on_faces) {
4120b3d85658SStefano Zampini           ierr = PetscBTSet(change_basis,i+n_vertices);CHKERRQ(ierr);
412108122e43SStefano Zampini         }
412208122e43SStefano Zampini       }
412308122e43SStefano Zampini     }
412408122e43SStefano Zampini   }
4125984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
41264f1b2e48SStefano Zampini   ierr = PetscMalloc1(pcbddc->local_primal_size+pcbddc->benign_n,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
412708122e43SStefano Zampini 
41289162d606SStefano Zampini   /* map constraints_idxs in boundary numbering */
41299162d606SStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,constraints_idxs_ptr[total_counts_cc],constraints_idxs,&i,constraints_idxs_B);CHKERRQ(ierr);
41306c4ed002SBarry 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);
4131674ae819SStefano Zampini 
4132674ae819SStefano Zampini   /* Create constraint matrix */
4133674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
413416f15bc4SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,MATAIJ);CHKERRQ(ierr);
4135984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
4136984c4197SStefano Zampini 
4137984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
4138a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
4139a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
414074d5cdf7SStefano Zampini   ierr = PetscBTCreate(total_counts_cc,&qr_needed_idx);CHKERRQ(ierr);
4141984c4197SStefano Zampini   total_primal_vertices=0;
4142b3d85658SStefano Zampini   pcbddc->local_primal_size_cc = 0;
41439162d606SStefano Zampini   for (i=0;i<total_counts_cc;i++) {
41449162d606SStefano Zampini     size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
414572b8c272SStefano Zampini     if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) {
41469162d606SStefano Zampini       pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]];
4147b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
414864efe560SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) {
41499162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
41509162d606SStefano Zampini         pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]+k];
4151a717540cSStefano Zampini       }
4152b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += constraints_n[i];
415391af6908SStefano Zampini       if (constraints_n[i] > 1 || pcbddc->use_qr_single) {
4154a717540cSStefano Zampini         PetscBTSet(qr_needed_idx,i);
4155a717540cSStefano Zampini         qr_needed = PETSC_TRUE;
4156a717540cSStefano Zampini       }
4157fa434743SStefano Zampini     } else {
4158b3d85658SStefano Zampini       pcbddc->local_primal_size_cc += 1;
4159fa434743SStefano Zampini     }
4160a717540cSStefano Zampini   }
4161b371cd4fSStefano Zampini   /* note that the local variable n_vertices used below stores the number of pointwise constraints */
4162b371cd4fSStefano Zampini   pcbddc->n_vertices = total_primal_vertices;
4163674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
416470022509SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
4165b3d85658SStefano Zampini 
41664f1b2e48SStefano 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);
41670e6343abSStefano Zampini   ierr = PetscMemcpy(pcbddc->local_primal_ref_node,pcbddc->primal_indices_local_idxs,total_primal_vertices*sizeof(PetscInt));CHKERRQ(ierr);
41680e6343abSStefano Zampini   for (i=0;i<total_primal_vertices;i++) pcbddc->local_primal_ref_mult[i] = 1;
4169984c4197SStefano Zampini 
4170984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
417174d5cdf7SStefano Zampini   /* and get reference dof for local constraints */
4172785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
4173984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i] = 1;
417474d5cdf7SStefano Zampini 
4175984c4197SStefano Zampini   j = total_primal_vertices;
417674d5cdf7SStefano Zampini   total_counts = total_primal_vertices;
4177b3d85658SStefano Zampini   cum = total_primal_vertices;
41789162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
41794641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
4180b3d85658SStefano Zampini       pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]];
4181b3d85658SStefano Zampini       pcbddc->local_primal_ref_mult[cum] = constraints_n[i];
4182b3d85658SStefano Zampini       cum++;
41839162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
418474d5cdf7SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
418574d5cdf7SStefano Zampini         pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i]+k];
418674d5cdf7SStefano Zampini         nnz[j+k] = size_of_constraint;
418774d5cdf7SStefano Zampini       }
41889162d606SStefano Zampini       j += constraints_n[i];
4189674ae819SStefano Zampini     }
4190674ae819SStefano Zampini   }
4191674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
4192674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
4193088faed8SStefano Zampini 
4194674ae819SStefano Zampini   /* set values in constraint matrix */
4195984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
41960e6343abSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,pcbddc->local_primal_ref_node[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
4197674ae819SStefano Zampini   }
4198984c4197SStefano Zampini   total_counts = total_primal_vertices;
41999162d606SStefano Zampini   for (i=n_vertices;i<total_counts_cc;i++) {
42004641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
42019162d606SStefano Zampini       PetscInt *cols;
42029162d606SStefano Zampini 
42039162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
42049162d606SStefano Zampini       cols = constraints_idxs+constraints_idxs_ptr[i];
42059162d606SStefano Zampini       for (k=0;k<constraints_n[i];k++) {
42069162d606SStefano Zampini         PetscInt    row = total_counts+k;
42079162d606SStefano Zampini         PetscScalar *vals;
42089162d606SStefano Zampini 
42099162d606SStefano Zampini         vals = constraints_data+constraints_data_ptr[i]+k*size_of_constraint;
42109162d606SStefano Zampini         ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&row,size_of_constraint,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
42119162d606SStefano Zampini       }
42129162d606SStefano Zampini       total_counts += constraints_n[i];
4213674ae819SStefano Zampini     }
4214674ae819SStefano Zampini   }
4215674ae819SStefano Zampini   /* assembling */
4216674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4217674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4218088faed8SStefano Zampini 
4219984c4197SStefano Zampini   /*
42206a9046bcSBarry Smith   ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4221984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
4222f159cad9SBarry Smith   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
4223984c4197SStefano Zampini   */
4224674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
4225674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
4226026de310SStefano Zampini     /* dual and primal dofs on a single cc */
4227984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
4228984c4197SStefano Zampini     /* working stuff for GEQRF */
422981d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
4230984c4197SStefano Zampini     PetscBLASInt lqr_work;
4231984c4197SStefano Zampini     /* working stuff for UNGQR */
4232984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
4233984c4197SStefano Zampini     PetscBLASInt lgqr_work;
4234984c4197SStefano Zampini     /* working stuff for TRTRS */
4235984c4197SStefano Zampini     PetscScalar  *trs_rhs;
42363f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
4237984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
4238984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
4239984c4197SStefano Zampini     PetscScalar  *start_vals;
4240984c4197SStefano Zampini     /* working stuff for values insertion */
42414641a718SStefano Zampini     PetscBT      is_primal;
424264efe560SStefano Zampini     PetscInt     *aux_primal_numbering_B;
4243906d46d4SStefano Zampini     /* matrix sizes */
4244906d46d4SStefano Zampini     PetscInt     global_size,local_size;
4245906d46d4SStefano Zampini     /* temporary change of basis */
4246906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
4247cf5a6209SStefano Zampini     /* extra space for debugging */
4248cf5a6209SStefano Zampini     PetscScalar  *dbg_work;
4249984c4197SStefano Zampini 
4250906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
4251906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
425216f15bc4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
4253bbb9e6c6SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
4254906d46d4SStefano Zampini     /* nonzeros for local mat */
4255bbb9e6c6SStefano Zampini     ierr = PetscMalloc1(pcis->n,&nnz);CHKERRQ(ierr);
42561dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
4257bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) nnz[i]=1;
42581dd7afcfSStefano Zampini     } else {
42591dd7afcfSStefano Zampini       const PetscInt *ii;
42601dd7afcfSStefano Zampini       PetscInt       n;
42611dd7afcfSStefano Zampini       PetscBool      flg_row;
42621dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
42631dd7afcfSStefano Zampini       for (i=0;i<n;i++) nnz[i] = ii[i+1]-ii[i];
42641dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,NULL,&flg_row);CHKERRQ(ierr);
42651dd7afcfSStefano Zampini     }
42669162d606SStefano Zampini     for (i=n_vertices;i<total_counts_cc;i++) {
4267a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
42689162d606SStefano Zampini         size_of_constraint = constraints_idxs_ptr[i+1]-constraints_idxs_ptr[i];
4269a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
42709162d606SStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = size_of_constraint;
4271a717540cSStefano Zampini         } else {
42729162d606SStefano Zampini           nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint;
42739162d606SStefano Zampini           for (j=1;j<size_of_constraint;j++) nnz[constraints_idxs[constraints_idxs_ptr[i]+j]] = 2;
4274a717540cSStefano Zampini         }
4275a717540cSStefano Zampini       }
4276a717540cSStefano Zampini     }
4277906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
4278bbb9e6c6SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
42791dd7afcfSStefano Zampini     /* Set interior change in the matrix */
42801dd7afcfSStefano Zampini     if (!pcbddc->benign_change || pcbddc->fake_change) {
4281bbb9e6c6SStefano Zampini       for (i=0;i<pcis->n;i++) {
4282906d46d4SStefano Zampini         ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
4283a717540cSStefano Zampini       }
42841dd7afcfSStefano Zampini     } else {
42851dd7afcfSStefano Zampini       const PetscInt *ii,*jj;
42861dd7afcfSStefano Zampini       PetscScalar    *aa;
42871dd7afcfSStefano Zampini       PetscInt       n;
42881dd7afcfSStefano Zampini       PetscBool      flg_row;
42891dd7afcfSStefano Zampini       ierr = MatGetRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
42901dd7afcfSStefano Zampini       ierr = MatSeqAIJGetArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
42911dd7afcfSStefano Zampini       for (i=0;i<n;i++) {
42921dd7afcfSStefano Zampini         ierr = MatSetValues(localChangeOfBasisMatrix,1,&i,ii[i+1]-ii[i],jj+ii[i],aa+ii[i],INSERT_VALUES);CHKERRQ(ierr);
42931dd7afcfSStefano Zampini       }
42941dd7afcfSStefano Zampini       ierr = MatSeqAIJRestoreArray(pcbddc->benign_change,&aa);CHKERRQ(ierr);
42951dd7afcfSStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->benign_change,0,PETSC_FALSE,PETSC_FALSE,&n,&ii,&jj,&flg_row);CHKERRQ(ierr);
42961dd7afcfSStefano Zampini     }
4297a717540cSStefano Zampini 
4298a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
4299a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
4300a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
4301a717540cSStefano Zampini     }
4302a717540cSStefano Zampini 
4303a717540cSStefano Zampini 
4304a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
4305a717540cSStefano Zampini     /*
4306a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
4307a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
4308a717540cSStefano Zampini 
4309a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
4310a717540cSStefano Zampini 
4311a6b551f4SStefano 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)
4312a6b551f4SStefano Zampini 
4313a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
4314a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
4315a717540cSStefano Zampini             |              ...                        |
4316a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
4317a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
4318a717540cSStefano Zampini 
4319a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
4320a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
4321a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
4322a6b551f4SStefano Zampini 
4323a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
4324a717540cSStefano Zampini     */
4325a717540cSStefano Zampini     if (qr_needed) {
4326984c4197SStefano Zampini       /* space to store Q */
4327854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
4328984c4197SStefano Zampini       /* first we issue queries for optimal work */
43293f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
43303f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
43313f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4332984c4197SStefano Zampini       lqr_work = -1;
43333f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
4334984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
4335984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
4336785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
4337984c4197SStefano Zampini       lgqr_work = -1;
43383f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
43393f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
43403f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
43413f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
43423f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
43433f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
4344984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
4345984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
4346785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
4347984c4197SStefano Zampini       /* array to store scaling factors for reflectors */
4348785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
4349984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
4350785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
4351a717540cSStefano Zampini       /* allocating workspace for check */
4352a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
4353cf5a6209SStefano Zampini         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&dbg_work);CHKERRQ(ierr);
4354a717540cSStefano Zampini       }
4355a717540cSStefano Zampini     }
4356984c4197SStefano Zampini     /* array to store whether a node is primal or not */
43574641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
4358473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
43590e6343abSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,pcbddc->local_primal_ref_node,&i,aux_primal_numbering_B);CHKERRQ(ierr);
43606c4ed002SBarry 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);
436139e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
436239e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
436339e2fb2aSStefano Zampini     }
436439e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
4365984c4197SStefano Zampini 
4366a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
43679162d606SStefano Zampini     for (total_counts=n_vertices;total_counts<total_counts_cc;total_counts++) {
43689162d606SStefano Zampini       size_of_constraint = constraints_idxs_ptr[total_counts+1]-constraints_idxs_ptr[total_counts];
43694641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
4370984c4197SStefano Zampini         /* get constraint info */
43719162d606SStefano Zampini         primal_dofs = constraints_n[total_counts];
4372984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
4373984c4197SStefano Zampini 
4374984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
43759162d606SStefano 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);
4376674ae819SStefano Zampini         }
4377984c4197SStefano Zampini 
4378fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
4379a717540cSStefano Zampini 
4380a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
4381a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
43829162d606SStefano Zampini             ierr = PetscMemcpy(dbg_work,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
4383a717540cSStefano Zampini           }
4384984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
43859162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
4386984c4197SStefano Zampini 
4387984c4197SStefano Zampini           /* compute QR decomposition of constraints */
43883f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
43893f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
43903f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4391674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
43923f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
4393984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
4394674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4395984c4197SStefano Zampini 
4396984c4197SStefano Zampini           /* explictly compute R^-T */
4397984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
4398984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
43993f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
44003f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
44013f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
44023f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
4403984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
44043f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
4405984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
4406984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4407984c4197SStefano Zampini 
4408a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
44093f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
44103f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
44113f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
44123f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4413984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
44143f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
4415984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
4416984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
4417984c4197SStefano Zampini 
4418984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
4419984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
4420984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
44213f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
44223f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
44233f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
44243f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
44253f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
44263f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
4427984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
44289162d606SStefano 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));
4429984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
44309162d606SStefano Zampini           ierr = PetscMemcpy(qr_basis,&constraints_data[constraints_data_ptr[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
4431984c4197SStefano Zampini 
4432984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
44339162d606SStefano Zampini           start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]];
4434984c4197SStefano Zampini           /* insert cols for primal dofs */
4435984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
4436984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
44379162d606SStefano Zampini             start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+j];
4438906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
4439984c4197SStefano Zampini           }
4440984c4197SStefano Zampini           /* insert cols for dual dofs */
4441984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
44429162d606SStefano Zampini             if (!PetscBTLookup(is_primal,constraints_idxs_B[constraints_idxs_ptr[total_counts]+k])) {
4443984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
44449162d606SStefano Zampini               start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts]+k];
4445906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
4446984c4197SStefano Zampini               j++;
4447674ae819SStefano Zampini             }
4448674ae819SStefano Zampini           }
4449984c4197SStefano Zampini 
4450984c4197SStefano Zampini           /* check change of basis */
4451984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
4452984c4197SStefano Zampini             PetscInt   ii,jj;
4453984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
4454c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
4455c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
4456c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
4457c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
4458c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
4459c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
4460984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
4461cf5a6209SStefano 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));
4462984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
4463984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
4464984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
4465cf5a6209SStefano Zampini                 if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
4466cf5a6209SStefano 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;
4467674ae819SStefano Zampini               }
4468674ae819SStefano Zampini             }
4469984c4197SStefano Zampini             if (!valid_qr) {
447022d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
4471984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
4472984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
4473cf5a6209SStefano Zampini                   if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
4474cf5a6209SStefano 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]));
4475674ae819SStefano Zampini                   }
4476cf5a6209SStefano Zampini                   if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
4477cf5a6209SStefano 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]));
4478984c4197SStefano Zampini                   }
4479984c4197SStefano Zampini                 }
4480984c4197SStefano Zampini               }
4481674ae819SStefano Zampini             } else {
448222d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
4483674ae819SStefano Zampini             }
4484674ae819SStefano Zampini           }
4485a717540cSStefano Zampini         } else { /* simple transformation block */
4486a717540cSStefano Zampini           PetscInt    row,col;
4487a6b551f4SStefano Zampini           PetscScalar val,norm;
4488a6b551f4SStefano Zampini 
4489a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
44909162d606SStefano 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));
4491a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
44929162d606SStefano Zampini             PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts]+j];
44939162d606SStefano Zampini             row = constraints_idxs[constraints_idxs_ptr[total_counts]+j];
4494bbb9e6c6SStefano Zampini             if (!PetscBTLookup(is_primal,row_B)) {
44959162d606SStefano Zampini               col = constraints_idxs[constraints_idxs_ptr[total_counts]];
4496906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
44979162d606SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,constraints_data[constraints_data_ptr[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
4498a717540cSStefano Zampini             } else {
4499a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
45009162d606SStefano Zampini                 col = constraints_idxs[constraints_idxs_ptr[total_counts]+k];
4501a717540cSStefano Zampini                 if (row != col) {
45029162d606SStefano Zampini                   val = -constraints_data[constraints_data_ptr[total_counts]+k]/constraints_data[constraints_data_ptr[total_counts]];
4503a717540cSStefano Zampini                 } else {
45049162d606SStefano Zampini                   val = constraints_data[constraints_data_ptr[total_counts]]/norm;
4505a717540cSStefano Zampini                 }
4506906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
4507a717540cSStefano Zampini               }
4508a717540cSStefano Zampini             }
4509a717540cSStefano Zampini           }
451098a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
451122d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
4512a717540cSStefano Zampini           }
4513674ae819SStefano Zampini         }
4514984c4197SStefano Zampini       } else {
4515984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
45169162d606SStefano 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);
4517674ae819SStefano Zampini         }
4518674ae819SStefano Zampini       }
4519674ae819SStefano Zampini     }
4520a717540cSStefano Zampini 
4521a717540cSStefano Zampini     /* free workspace */
4522a717540cSStefano Zampini     if (qr_needed) {
4523984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
4524cf5a6209SStefano Zampini         ierr = PetscFree(dbg_work);CHKERRQ(ierr);
4525984c4197SStefano Zampini       }
4526984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
4527984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
4528984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
4529984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
4530984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
4531674ae819SStefano Zampini     }
4532a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
4533906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4534906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4535906d46d4SStefano Zampini 
4536906d46d4SStefano Zampini     /* assembling of global change of variable */
453788c03ad3SStefano Zampini     if (!pcbddc->fake_change) {
4538bbb9e6c6SStefano Zampini       Mat      tmat;
453916f15bc4SStefano Zampini       PetscInt bs;
454016f15bc4SStefano Zampini 
4541906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
4542906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
4543bbb9e6c6SStefano Zampini       ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
4544bbb9e6c6SStefano Zampini       ierr = MatISSetLocalMat(tmat,localChangeOfBasisMatrix);CHKERRQ(ierr);
4545bbb9e6c6SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
4546bbb9e6c6SStefano Zampini       ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
454716f15bc4SStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr);
454816f15bc4SStefano Zampini       ierr = MatSetBlockSize(pcbddc->ChangeOfBasisMatrix,bs);CHKERRQ(ierr);
4549906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
4550bbb9e6c6SStefano Zampini       ierr = MatISSetMPIXAIJPreallocation_Private(tmat,pcbddc->ChangeOfBasisMatrix,PETSC_TRUE);CHKERRQ(ierr);
4551bbb9e6c6SStefano Zampini       ierr = MatISGetMPIXAIJ(tmat,MAT_REUSE_MATRIX,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
4552bbb9e6c6SStefano Zampini       ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4553bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4554bbb9e6c6SStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
4555e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4556e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4557bbb9e6c6SStefano Zampini       ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
4558bbb9e6c6SStefano Zampini       ierr = MatDiagonalScale(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,NULL);CHKERRQ(ierr);
455988c03ad3SStefano Zampini 
4560906d46d4SStefano Zampini       /* check */
4561906d46d4SStefano Zampini       if (pcbddc->dbg_flag) {
4562906d46d4SStefano Zampini         PetscReal error;
4563906d46d4SStefano Zampini         Vec       x,x_change;
4564906d46d4SStefano Zampini 
4565906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
4566906d46d4SStefano Zampini         ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
4567906d46d4SStefano Zampini         ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
4568906d46d4SStefano Zampini         ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
4569e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4570e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4571bbb9e6c6SStefano Zampini         ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
4572e176bc59SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4573e176bc59SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4574906d46d4SStefano Zampini         ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
4575906d46d4SStefano Zampini         ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
4576906d46d4SStefano Zampini         ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
4577906d46d4SStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4578bbb9e6c6SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change: %1.6e\n",error);CHKERRQ(ierr);
4579906d46d4SStefano Zampini         ierr = VecDestroy(&x);CHKERRQ(ierr);
4580906d46d4SStefano Zampini         ierr = VecDestroy(&x_change);CHKERRQ(ierr);
4581906d46d4SStefano Zampini       }
4582b96c3477SStefano Zampini       /* adapt sub_schurs computed (if any) */
4583b96c3477SStefano Zampini       if (pcbddc->use_deluxe_scaling) {
4584b96c3477SStefano Zampini         PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
4585bf3a8328SStefano Zampini 
4586bf3a8328SStefano Zampini         if (pcbddc->use_change_of_basis && pcbddc->adaptive_userdefined) {
4587bf3a8328SStefano Zampini           SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot mix automatic change of basis, adaptive selection and user-defined constraints");CHKERRQ(ierr);
4588bf3a8328SStefano Zampini         }
4589b334f244SStefano Zampini         if (sub_schurs && sub_schurs->S_Ej_all) {
4590ac632422SStefano Zampini           Mat                    S_new,tmat;
4591bf3a8328SStefano Zampini           IS                     is_all_N,is_V_Sall = NULL;
4592bbb9e6c6SStefano Zampini 
4593bbb9e6c6SStefano Zampini           ierr = ISLocalToGlobalMappingApplyIS(pcis->BtoNmap,sub_schurs->is_Ej_all,&is_all_N);CHKERRQ(ierr);
45946816873aSStefano Zampini           ierr = MatGetSubMatrix(localChangeOfBasisMatrix,is_all_N,is_all_N,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
4595bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
4596bf3a8328SStefano Zampini             ISLocalToGlobalMapping NtoSall;
4597bf3a8328SStefano Zampini             IS                     is_V;
4598b087196eSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&is_V);CHKERRQ(ierr);
4599b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingCreateIS(is_all_N,&NtoSall);CHKERRQ(ierr);
4600b087196eSStefano Zampini             ierr = ISGlobalToLocalMappingApplyIS(NtoSall,IS_GTOLM_DROP,is_V,&is_V_Sall);CHKERRQ(ierr);
4601b087196eSStefano Zampini             ierr = ISLocalToGlobalMappingDestroy(&NtoSall);CHKERRQ(ierr);
4602b087196eSStefano Zampini             ierr = ISDestroy(&is_V);CHKERRQ(ierr);
4603bf3a8328SStefano Zampini           }
4604bf3a8328SStefano Zampini           ierr = ISDestroy(&is_all_N);CHKERRQ(ierr);
4605ac632422SStefano Zampini           ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
4606b96c3477SStefano Zampini           ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
4607ac632422SStefano Zampini           ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
4608bf3a8328SStefano Zampini           if (pcbddc->deluxe_zerorows) {
4609bf3a8328SStefano Zampini             const PetscScalar *array;
4610bf3a8328SStefano Zampini             const PetscInt    *idxs_V,*idxs_all;
4611bf3a8328SStefano Zampini             PetscInt          i,n_V;
4612bf3a8328SStefano Zampini 
4613b087196eSStefano Zampini             ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
4614b087196eSStefano Zampini             ierr = ISGetLocalSize(is_V_Sall,&n_V);CHKERRQ(ierr);
4615b087196eSStefano Zampini             ierr = ISGetIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
4616b087196eSStefano Zampini             ierr = ISGetIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
4617b087196eSStefano Zampini             ierr = VecGetArrayRead(pcis->D,&array);CHKERRQ(ierr);
4618b087196eSStefano Zampini             for (i=0;i<n_V;i++) {
4619b087196eSStefano Zampini               PetscScalar val;
4620b087196eSStefano Zampini               PetscInt    idx;
4621b087196eSStefano Zampini 
4622b087196eSStefano Zampini               idx = idxs_V[i];
4623b087196eSStefano Zampini               val = array[idxs_all[idxs_V[i]]];
4624b087196eSStefano Zampini               ierr = MatSetValue(S_new,idx,idx,val,INSERT_VALUES);CHKERRQ(ierr);
4625b087196eSStefano Zampini             }
4626b087196eSStefano Zampini             ierr = MatAssemblyBegin(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4627b087196eSStefano Zampini             ierr = MatAssemblyEnd(S_new,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4628bf3a8328SStefano Zampini             ierr = VecRestoreArrayRead(pcis->D,&array);CHKERRQ(ierr);
4629bf3a8328SStefano Zampini             ierr = ISRestoreIndices(sub_schurs->is_Ej_all,&idxs_all);CHKERRQ(ierr);
4630bf3a8328SStefano Zampini             ierr = ISRestoreIndices(is_V_Sall,&idxs_V);CHKERRQ(ierr);
4631bf3a8328SStefano Zampini           }
4632ac632422SStefano Zampini           sub_schurs->S_Ej_all = S_new;
4633ac632422SStefano Zampini           ierr = MatDestroy(&S_new);CHKERRQ(ierr);
4634ac632422SStefano Zampini           if (sub_schurs->sum_S_Ej_all) {
4635ac632422SStefano Zampini             ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_new);CHKERRQ(ierr);
4636b96c3477SStefano Zampini             ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
4637ac632422SStefano Zampini             ierr = PetscObjectReference((PetscObject)S_new);CHKERRQ(ierr);
4638bf3a8328SStefano Zampini             if (pcbddc->deluxe_zerorows) {
4639b087196eSStefano Zampini               ierr = MatZeroRowsColumnsIS(S_new,is_V_Sall,1.,NULL,NULL);CHKERRQ(ierr);
4640bf3a8328SStefano Zampini             }
4641ac632422SStefano Zampini             sub_schurs->sum_S_Ej_all = S_new;
4642ac632422SStefano Zampini             ierr = MatDestroy(&S_new);CHKERRQ(ierr);
4643ac632422SStefano Zampini           }
4644b087196eSStefano Zampini           ierr = ISDestroy(&is_V_Sall);CHKERRQ(ierr);
464588c03ad3SStefano Zampini           ierr = MatDestroy(&tmat);CHKERRQ(ierr);
4646b96c3477SStefano Zampini         }
4647c9db6a07SStefano Zampini         /* destroy any change of basis context in sub_schurs */
4648b334f244SStefano Zampini         if (sub_schurs && sub_schurs->change) {
4649c9db6a07SStefano Zampini           PetscInt i;
4650c9db6a07SStefano Zampini 
4651c9db6a07SStefano Zampini           for (i=0;i<sub_schurs->n_subs;i++) {
4652c9db6a07SStefano Zampini             ierr = KSPDestroy(&sub_schurs->change[i]);CHKERRQ(ierr);
4653c9db6a07SStefano Zampini           }
4654c9db6a07SStefano Zampini           ierr = PetscFree(sub_schurs->change);CHKERRQ(ierr);
4655c9db6a07SStefano Zampini         }
4656b96c3477SStefano Zampini       }
465716909a7fSStefano Zampini       if (pcbddc->switch_static) { /* need to save the local change */
465816909a7fSStefano Zampini         pcbddc->switch_static_change = localChangeOfBasisMatrix;
465916909a7fSStefano Zampini       } else {
4660906d46d4SStefano Zampini         ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
466116909a7fSStefano Zampini       }
46621dd7afcfSStefano Zampini       /* determine if any process has changed the pressures locally */
466327b6a85dSStefano Zampini       pcbddc->change_interior = pcbddc->benign_have_null;
466472b8c272SStefano Zampini     } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */
466572b8c272SStefano Zampini       ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
466672b8c272SStefano Zampini       pcbddc->ConstraintMatrix = localChangeOfBasisMatrix;
466772b8c272SStefano Zampini       pcbddc->use_qr_single = qr_needed;
466872b8c272SStefano Zampini     }
46691dd7afcfSStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) {
467027b6a85dSStefano Zampini     if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) {
4671b9b85e73SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
4672b9b85e73SStefano Zampini       pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
4673906d46d4SStefano Zampini     } else {
46741dd7afcfSStefano Zampini       Mat benign_global = NULL;
467527b6a85dSStefano Zampini       if (pcbddc->benign_have_null) {
46761dd7afcfSStefano Zampini         Mat tmat;
46771dd7afcfSStefano Zampini 
46781dd7afcfSStefano Zampini         pcbddc->change_interior = PETSC_TRUE;
46791dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
46801dd7afcfSStefano Zampini         ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
46811dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
46821dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
46831dd7afcfSStefano Zampini         ierr = VecReciprocal(pcis->vec1_global);CHKERRQ(ierr);
46841dd7afcfSStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
46851dd7afcfSStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
46861dd7afcfSStefano Zampini         ierr = MatDuplicate(pc->pmat,MAT_DO_NOT_COPY_VALUES,&tmat);CHKERRQ(ierr);
46871dd7afcfSStefano Zampini         if (pcbddc->benign_change) {
46881dd7afcfSStefano Zampini           Mat M;
46891dd7afcfSStefano Zampini 
46901dd7afcfSStefano Zampini           ierr = MatDuplicate(pcbddc->benign_change,MAT_COPY_VALUES,&M);CHKERRQ(ierr);
46911dd7afcfSStefano Zampini           ierr = MatDiagonalScale(M,pcis->vec1_N,NULL);CHKERRQ(ierr);
46921dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,M);CHKERRQ(ierr);
46931dd7afcfSStefano Zampini           ierr = MatDestroy(&M);CHKERRQ(ierr);
4694906d46d4SStefano Zampini         } else {
46951dd7afcfSStefano Zampini           Mat         eye;
46961dd7afcfSStefano Zampini           PetscScalar *array;
46971dd7afcfSStefano Zampini 
46981dd7afcfSStefano Zampini           ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
46991dd7afcfSStefano Zampini           ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,pcis->n,pcis->n,1,NULL,&eye);CHKERRQ(ierr);
47001dd7afcfSStefano Zampini           for (i=0;i<pcis->n;i++) {
47011dd7afcfSStefano Zampini             ierr = MatSetValue(eye,i,i,array[i],INSERT_VALUES);CHKERRQ(ierr);
4702906d46d4SStefano Zampini           }
47031dd7afcfSStefano Zampini           ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
47041dd7afcfSStefano Zampini           ierr = MatAssemblyBegin(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
47051dd7afcfSStefano Zampini           ierr = MatAssemblyEnd(eye,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
47061dd7afcfSStefano Zampini           ierr = MatISSetLocalMat(tmat,eye);CHKERRQ(ierr);
47071dd7afcfSStefano Zampini           ierr = MatDestroy(&eye);CHKERRQ(ierr);
47081dd7afcfSStefano Zampini         }
47091dd7afcfSStefano Zampini         ierr = MatISGetMPIXAIJ(tmat,MAT_INITIAL_MATRIX,&benign_global);CHKERRQ(ierr);
47101dd7afcfSStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
47111dd7afcfSStefano Zampini       }
47121dd7afcfSStefano Zampini       if (pcbddc->user_ChangeOfBasisMatrix) {
47131dd7afcfSStefano Zampini         ierr = MatMatMult(pcbddc->user_ChangeOfBasisMatrix,benign_global,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
47141dd7afcfSStefano Zampini         ierr = MatDestroy(&benign_global);CHKERRQ(ierr);
471527b6a85dSStefano Zampini       } else if (pcbddc->benign_have_null) {
47161dd7afcfSStefano Zampini         pcbddc->ChangeOfBasisMatrix = benign_global;
47171dd7afcfSStefano Zampini       }
47181dd7afcfSStefano Zampini     }
471916909a7fSStefano Zampini     if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */
472016909a7fSStefano Zampini       IS             is_global;
472116909a7fSStefano Zampini       const PetscInt *gidxs;
472216909a7fSStefano Zampini 
472316909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingGetIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
472416909a7fSStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcis->n,gidxs,PETSC_COPY_VALUES,&is_global);CHKERRQ(ierr);
472516909a7fSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreIndices(pc->pmat->rmap->mapping,&gidxs);CHKERRQ(ierr);
472616909a7fSStefano Zampini       ierr = MatGetSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix,is_global,is_global,&pcbddc->switch_static_change);CHKERRQ(ierr);
472716909a7fSStefano Zampini       ierr = ISDestroy(&is_global);CHKERRQ(ierr);
472816909a7fSStefano Zampini     }
47291dd7afcfSStefano Zampini   }
47301dd7afcfSStefano Zampini   if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) {
47311dd7afcfSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->work_change);CHKERRQ(ierr);
4732b9b85e73SStefano Zampini   }
4733a717540cSStefano Zampini 
473472b8c272SStefano Zampini   if (!pcbddc->fake_change) {
47354f1b2e48SStefano Zampini     /* add pressure dofs to set of primal nodes for numbering purposes */
47364f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
47374f1b2e48SStefano Zampini       pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i];
47384f1b2e48SStefano Zampini       pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i];
4739019a44ceSStefano Zampini       pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1;
4740019a44ceSStefano Zampini       pcbddc->local_primal_size_cc++;
4741019a44ceSStefano Zampini       pcbddc->local_primal_size++;
4742019a44ceSStefano Zampini     }
4743019a44ceSStefano Zampini 
4744019a44ceSStefano Zampini     /* check if a new primal space has been introduced (also take into account benign trick) */
4745727cdba6SStefano Zampini     pcbddc->new_primal_space_local = PETSC_TRUE;
4746727cdba6SStefano Zampini     if (olocal_primal_size == pcbddc->local_primal_size) {
47479f47a83aSStefano 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);
4748c1c8e736SStefano Zampini       pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
47490e6343abSStefano Zampini       if (!pcbddc->new_primal_space_local) {
47509f47a83aSStefano 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);
4751727cdba6SStefano Zampini         pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
4752727cdba6SStefano Zampini       }
47530e6343abSStefano Zampini     }
4754727cdba6SStefano Zampini     /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
4755b2566f29SBarry Smith     ierr = MPIU_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
475672b8c272SStefano Zampini   }
475772b8c272SStefano Zampini   ierr = PetscFree2(olocal_primal_ref_node,olocal_primal_ref_mult);CHKERRQ(ierr);
4758727cdba6SStefano Zampini 
4759a717540cSStefano Zampini   /* flush dbg viewer */
4760b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
4761b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4762b8ffe317SStefano Zampini   }
4763a717540cSStefano Zampini 
4764e310c8b4SStefano Zampini   /* free workspace */
4765a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
47664641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
476708122e43SStefano Zampini   if (!pcbddc->adaptive_selection) {
47689162d606SStefano Zampini     ierr = PetscFree3(constraints_idxs_ptr,constraints_data_ptr,constraints_n);CHKERRQ(ierr);
47699162d606SStefano Zampini     ierr = PetscFree3(constraints_data,constraints_idxs,constraints_idxs_B);CHKERRQ(ierr);
477008122e43SStefano Zampini   } else {
47719162d606SStefano Zampini     ierr = PetscFree5(pcbddc->adaptive_constraints_n,
47729162d606SStefano Zampini                       pcbddc->adaptive_constraints_idxs_ptr,
47739162d606SStefano Zampini                       pcbddc->adaptive_constraints_data_ptr,
477408122e43SStefano Zampini                       pcbddc->adaptive_constraints_idxs,
477508122e43SStefano Zampini                       pcbddc->adaptive_constraints_data);CHKERRQ(ierr);
47769162d606SStefano Zampini     ierr = PetscFree(constraints_n);CHKERRQ(ierr);
47779162d606SStefano Zampini     ierr = PetscFree(constraints_idxs_B);CHKERRQ(ierr);
477808122e43SStefano Zampini   }
4779674ae819SStefano Zampini   PetscFunctionReturn(0);
4780674ae819SStefano Zampini }
4781674ae819SStefano Zampini 
4782674ae819SStefano Zampini #undef __FUNCT__
4783674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
4784674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
4785674ae819SStefano Zampini {
4786674ae819SStefano Zampini   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
4787674ae819SStefano Zampini   PC_IS       *pcis = (PC_IS*)pc->data;
4788674ae819SStefano Zampini   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
478914f95afaSStefano Zampini   PetscInt    ierr,i,N;
4790674ae819SStefano Zampini 
4791674ae819SStefano Zampini   PetscFunctionBegin;
47928e61c736SStefano Zampini   /* Reset previously computed graph */
47938e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
4794674ae819SStefano Zampini   /* Init local Graph struct */
47957fb0e2dbSStefano Zampini   ierr = MatGetSize(pc->pmat,&N,NULL);CHKERRQ(ierr);
47963bbff08aSStefano Zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,pcis->mapping,N);CHKERRQ(ierr);
4797674ae819SStefano Zampini 
4798575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
47995099eff2SStefano Zampini   if (pcbddc->mat_graph->nvtxs_csr && pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) {
48005099eff2SStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid size of local CSR graph! Found %d, expected %d\n",pcbddc->mat_graph->nvtxs_csr,pcbddc->mat_graph->nvtxs);
4801575ad6abSStefano Zampini   }
48029577ea80SStefano Zampini 
4803674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
4804d4d8cf7bSStefano Zampini   if ( (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) && pcbddc->use_local_adj) {
48054d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
48064d379d7bSStefano Zampini     PetscInt  nvtxs;
4807e496cd5dSStefano Zampini     PetscBool flg_row=PETSC_FALSE;
4808674ae819SStefano Zampini 
48092fffb893SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
48102fffb893SStefano Zampini     if (flg_row) {
48114d379d7bSStefano Zampini       ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
4812b96c3477SStefano Zampini       pcbddc->computed_rowadj = PETSC_TRUE;
48132fffb893SStefano Zampini     }
48142fffb893SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
4815674ae819SStefano Zampini   }
48169b28b941SStefano Zampini   if (pcbddc->dbg_flag) {
48179b28b941SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4818674ae819SStefano Zampini   }
4819674ae819SStefano Zampini 
4820674ae819SStefano Zampini   /* Setup of Graph */
48214b2aedd3SStefano Zampini   pcbddc->mat_graph->commsizelimit = 0; /* don't use the COMM_SELF variant of the graph */
482214f95afaSStefano 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);
4823674ae819SStefano Zampini 
48244f1b2e48SStefano Zampini   /* attach info on disconnected subdomains if present */
48254f1b2e48SStefano Zampini   if (pcbddc->n_local_subs) {
48264f1b2e48SStefano Zampini     PetscInt *local_subs;
48274f1b2e48SStefano Zampini 
48284f1b2e48SStefano Zampini     ierr = PetscMalloc1(N,&local_subs);CHKERRQ(ierr);
48294f1b2e48SStefano Zampini     for (i=0;i<pcbddc->n_local_subs;i++) {
48304f1b2e48SStefano Zampini       const PetscInt *idxs;
48314f1b2e48SStefano Zampini       PetscInt       nl,j;
48324f1b2e48SStefano Zampini 
48334f1b2e48SStefano Zampini       ierr = ISGetLocalSize(pcbddc->local_subs[i],&nl);CHKERRQ(ierr);
48344f1b2e48SStefano Zampini       ierr = ISGetIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
48354f1b2e48SStefano Zampini       for (j=0;j<nl;j++) {
48364f1b2e48SStefano Zampini         local_subs[idxs[j]] = i;
48374f1b2e48SStefano Zampini       }
48384f1b2e48SStefano Zampini       ierr = ISRestoreIndices(pcbddc->local_subs[i],&idxs);CHKERRQ(ierr);
48394f1b2e48SStefano Zampini     }
48404f1b2e48SStefano Zampini     pcbddc->mat_graph->n_local_subs = pcbddc->n_local_subs;
48414f1b2e48SStefano Zampini     pcbddc->mat_graph->local_subs = local_subs;
48424f1b2e48SStefano Zampini   }
48434f1b2e48SStefano Zampini 
4844674ae819SStefano Zampini   /* Graph's connected components analysis */
4845674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
4846674ae819SStefano Zampini   PetscFunctionReturn(0);
4847674ae819SStefano Zampini }
4848674ae819SStefano Zampini 
4849dc456d91SStefano Zampini /* given an index sets possibly with holes, renumbers the indexes removing the holes */
4850674ae819SStefano Zampini #undef __FUNCT__
4851674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSubsetNumbering"
4852dc456d91SStefano Zampini PetscErrorCode PCBDDCSubsetNumbering(IS subset, IS subset_mult, PetscInt *N_n, IS *subset_n)
4853674ae819SStefano Zampini {
4854dc456d91SStefano Zampini   PetscSF        sf;
4855dc456d91SStefano Zampini   PetscLayout    map;
4856dc456d91SStefano Zampini   const PetscInt *idxs;
4857dc456d91SStefano Zampini   PetscInt       *leaf_data,*root_data,*gidxs;
4858dc456d91SStefano Zampini   PetscInt       N,n,i,lbounds[2],gbounds[2],Nl;
4859dc456d91SStefano Zampini   PetscInt       n_n,nlocals,start,first_index;
4860dc456d91SStefano Zampini   PetscMPIInt    commsize;
4861674ae819SStefano Zampini   PetscBool      first_found;
4862674ae819SStefano Zampini   PetscErrorCode ierr;
4863674ae819SStefano Zampini 
4864674ae819SStefano Zampini   PetscFunctionBegin;
4865dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset,&n);CHKERRQ(ierr);
4866dc456d91SStefano Zampini   if (subset_mult) {
4867dc456d91SStefano Zampini     PetscCheckSameComm(subset,1,subset_mult,2);
4868dc456d91SStefano Zampini     ierr = ISGetLocalSize(subset,&i);CHKERRQ(ierr);
4869dc456d91SStefano Zampini     if (i != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local subset and multiplicity sizes don't match! %d != %d",n,i);
4870674ae819SStefano Zampini   }
4871dc456d91SStefano Zampini   /* create workspace layout for computing global indices of subset */
4872dc456d91SStefano Zampini   ierr = ISGetIndices(subset,&idxs);CHKERRQ(ierr);
4873dc456d91SStefano Zampini   lbounds[0] = lbounds[1] = 0;
4874dc456d91SStefano Zampini   for (i=0;i<n;i++) {
4875dc456d91SStefano Zampini     if (idxs[i] < lbounds[0]) lbounds[0] = idxs[i];
4876dc456d91SStefano Zampini     else if (idxs[i] > lbounds[1]) lbounds[1] = idxs[i];
4877674ae819SStefano Zampini   }
4878dc456d91SStefano Zampini   lbounds[0] = -lbounds[0];
4879b2566f29SBarry Smith   ierr = MPIU_Allreduce(lbounds,gbounds,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
4880dc456d91SStefano Zampini   gbounds[0] = -gbounds[0];
4881dc456d91SStefano Zampini   N = gbounds[1] - gbounds[0] + 1;
4882dc456d91SStefano Zampini   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)subset),&map);CHKERRQ(ierr);
4883dc456d91SStefano Zampini   ierr = PetscLayoutSetBlockSize(map,1);CHKERRQ(ierr);
4884dc456d91SStefano Zampini   ierr = PetscLayoutSetSize(map,N);CHKERRQ(ierr);
4885dc456d91SStefano Zampini   ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
4886dc456d91SStefano Zampini   ierr = PetscLayoutGetLocalSize(map,&Nl);CHKERRQ(ierr);
4887dc456d91SStefano Zampini 
4888dc456d91SStefano Zampini   /* create sf : leaf_data == multiplicity of indexes, root data == global index in layout */
4889dc456d91SStefano Zampini   ierr = PetscMalloc2(n,&leaf_data,Nl,&root_data);CHKERRQ(ierr);
4890dc456d91SStefano Zampini   if (subset_mult) {
4891dc456d91SStefano Zampini     const PetscInt* idxs_mult;
4892dc456d91SStefano Zampini 
4893dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4894dc456d91SStefano Zampini     ierr = PetscMemcpy(leaf_data,idxs_mult,n*sizeof(PetscInt));CHKERRQ(ierr);
4895dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4896674ae819SStefano Zampini   } else {
4897dc456d91SStefano Zampini     for (i=0;i<n;i++) leaf_data[i] = 1;
4898674ae819SStefano Zampini   }
4899dc456d91SStefano Zampini   /* local size of new subset */
4900dc456d91SStefano Zampini   n_n = 0;
4901dc456d91SStefano Zampini   for (i=0;i<n;i++) n_n += leaf_data[i];
4902dc456d91SStefano Zampini 
4903dc456d91SStefano Zampini   /* global indexes in layout */
4904dc456d91SStefano Zampini   ierr = PetscMalloc1(n_n,&gidxs);CHKERRQ(ierr); /* allocating possibly extra space in gidxs which will be used later */
4905dc456d91SStefano Zampini   for (i=0;i<n;i++) gidxs[i] = idxs[i] - gbounds[0];
4906dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset,&idxs);CHKERRQ(ierr);
4907dc456d91SStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)subset),&sf);CHKERRQ(ierr);
4908dc456d91SStefano Zampini   ierr = PetscSFSetGraphLayout(sf,map,n,NULL,PETSC_COPY_VALUES,gidxs);CHKERRQ(ierr);
4909dc456d91SStefano Zampini   ierr = PetscLayoutDestroy(&map);CHKERRQ(ierr);
4910dc456d91SStefano Zampini 
4911dc456d91SStefano Zampini   /* reduce from leaves to roots */
4912dc456d91SStefano Zampini   ierr = PetscMemzero(root_data,Nl*sizeof(PetscInt));CHKERRQ(ierr);
491364a8e5bcSStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
491464a8e5bcSStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,leaf_data,root_data,MPI_MAX);CHKERRQ(ierr);
4915dc456d91SStefano Zampini 
4916dc456d91SStefano Zampini   /* count indexes in local part of layout */
4917674ae819SStefano Zampini   nlocals = 0;
4918674ae819SStefano Zampini   first_index = -1;
4919674ae819SStefano Zampini   first_found = PETSC_FALSE;
4920dc456d91SStefano Zampini   for (i=0;i<Nl;i++) {
4921dc456d91SStefano Zampini     if (!first_found && root_data[i]) {
4922674ae819SStefano Zampini       first_found = PETSC_TRUE;
4923674ae819SStefano Zampini       first_index = i;
4924674ae819SStefano Zampini     }
4925dc456d91SStefano Zampini     nlocals += root_data[i];
4926674ae819SStefano Zampini   }
4927dc456d91SStefano Zampini 
4928dc456d91SStefano Zampini   /* cumulative of number of indexes and size of subset without holes */
49295fa240b1SStefano Zampini #if defined(PETSC_HAVE_MPI_EXSCAN)
4930dc456d91SStefano Zampini   start = 0;
493164a8e5bcSStefano Zampini   ierr = MPI_Exscan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
49325fa240b1SStefano Zampini #else
493364a8e5bcSStefano Zampini   ierr = MPI_Scan(&nlocals,&start,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
49345fa240b1SStefano Zampini   start = start-nlocals;
49355fa240b1SStefano Zampini #endif
49365fa240b1SStefano Zampini 
4937dc456d91SStefano Zampini   if (N_n) { /* compute total size of new subset if requested */
4938dc456d91SStefano Zampini     *N_n = start + nlocals;
4939dc456d91SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)subset),&commsize);CHKERRQ(ierr);
4940dc456d91SStefano Zampini     ierr = MPI_Bcast(N_n,1,MPIU_INT,commsize-1,PetscObjectComm((PetscObject)subset));CHKERRQ(ierr);
4941674ae819SStefano Zampini   }
49425fa240b1SStefano Zampini 
49435fa240b1SStefano Zampini   /* adapt root data with cumulative */
4944674ae819SStefano Zampini   if (first_found) {
4945dc456d91SStefano Zampini     PetscInt old_index;
4946dc456d91SStefano Zampini 
4947dc456d91SStefano Zampini     root_data[first_index] += start;
4948674ae819SStefano Zampini     old_index = first_index;
4949dc456d91SStefano Zampini     for (i=first_index+1;i<Nl;i++) {
4950dc456d91SStefano Zampini       if (root_data[i]) {
4951dc456d91SStefano Zampini         root_data[i] += root_data[old_index];
4952674ae819SStefano Zampini         old_index = i;
4953674ae819SStefano Zampini       }
4954674ae819SStefano Zampini     }
4955674ae819SStefano Zampini   }
4956dc456d91SStefano Zampini 
4957dc456d91SStefano Zampini   /* from roots to leaves */
4958dc456d91SStefano Zampini   ierr = PetscSFBcastBegin(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
4959dc456d91SStefano Zampini   ierr = PetscSFBcastEnd(sf,MPIU_INT,root_data,leaf_data);CHKERRQ(ierr);
4960dc456d91SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
4961dc456d91SStefano Zampini 
4962dc456d91SStefano Zampini   /* create new IS with global indexes without holes */
4963dc456d91SStefano Zampini   if (subset_mult) {
4964dc456d91SStefano Zampini     const PetscInt* idxs_mult;
4965dc456d91SStefano Zampini     PetscInt        cum;
4966dc456d91SStefano Zampini 
4967dc456d91SStefano Zampini     cum = 0;
4968dc456d91SStefano Zampini     ierr = ISGetIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4969dc456d91SStefano Zampini     for (i=0;i<n;i++) {
4970dc456d91SStefano Zampini       PetscInt j;
4971dc456d91SStefano Zampini       for (j=0;j<idxs_mult[i];j++) gidxs[cum++] = leaf_data[i] - idxs_mult[i] + j;
4972674ae819SStefano Zampini     }
4973dc456d91SStefano Zampini     ierr = ISRestoreIndices(subset_mult,&idxs_mult);CHKERRQ(ierr);
4974674ae819SStefano Zampini   } else {
4975dc456d91SStefano Zampini     for (i=0;i<n;i++) {
4976dc456d91SStefano Zampini       gidxs[i] = leaf_data[i]-1;
4977674ae819SStefano Zampini     }
4978674ae819SStefano Zampini   }
4979dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)subset),n_n,gidxs,PETSC_OWN_POINTER,subset_n);CHKERRQ(ierr);
4980dc456d91SStefano Zampini   ierr = PetscFree2(leaf_data,root_data);CHKERRQ(ierr);
4981674ae819SStefano Zampini   PetscFunctionReturn(0);
4982674ae819SStefano Zampini }
49839a7d3425SStefano Zampini 
4984669cc0f4SStefano Zampini /* this implements stabilized Gram-Schmidt */
49859a7d3425SStefano Zampini #undef __FUNCT__
49869a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
49879a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
49889a7d3425SStefano Zampini {
49899a7d3425SStefano Zampini   PetscInt       i,j;
49909a7d3425SStefano Zampini   PetscScalar    *alphas;
49919a7d3425SStefano Zampini   PetscErrorCode ierr;
49929a7d3425SStefano Zampini 
49939a7d3425SStefano Zampini   PetscFunctionBegin;
4994785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
49959a7d3425SStefano Zampini   for (i=0;i<n;i++) {
49969a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
4997669cc0f4SStefano Zampini     ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],alphas);CHKERRQ(ierr);
4998669cc0f4SStefano Zampini     for (j=0;j<n-i-1;j++) alphas[j] = PetscConj(-alphas[j]);
4999669cc0f4SStefano Zampini     ierr = VecMAXPY(vecs[j],n-i-1,alphas,vecs+i);CHKERRQ(ierr);
50009a7d3425SStefano Zampini   }
50019a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
50029a7d3425SStefano Zampini   PetscFunctionReturn(0);
50039a7d3425SStefano Zampini }
50049a7d3425SStefano Zampini 
5005e7931f94SStefano Zampini #undef __FUNCT__
500670cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
500757de7509SStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS* is_sends, PetscBool *have_void)
5008e7931f94SStefano Zampini {
500957de7509SStefano Zampini   Mat            A;
5010e7931f94SStefano Zampini   PetscInt       n_neighs,*neighs,*n_shared,**shared;
5011e7931f94SStefano Zampini   PetscMPIInt    size,rank,color;
501252e5ac9dSStefano Zampini   PetscInt       *xadj,*adjncy;
501352e5ac9dSStefano Zampini   PetscInt       *adjncy_wgt,*v_wgt,*ranks_send_to_idx;
501427b6a85dSStefano Zampini   PetscInt       im_active,active_procs,n,i,j,local_size,threshold = 2;
501557de7509SStefano Zampini   PetscInt       void_procs,*procs_candidates = NULL;
501627b6a85dSStefano Zampini   PetscInt       xadj_count, *count;
501727b6a85dSStefano Zampini   PetscBool      ismatis,use_vwgt=PETSC_FALSE;
501827b6a85dSStefano Zampini   PetscSubcomm   psubcomm;
501927b6a85dSStefano Zampini   MPI_Comm       subcomm;
502052e5ac9dSStefano Zampini   PetscErrorCode ierr;
5021a57a6d2fSStefano Zampini 
5022e7931f94SStefano Zampini   PetscFunctionBegin;
502357de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
502457de7509SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
502557de7509SStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
502657de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,*n_subdomains,2);
502757de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,redprocs,3);
502857de7509SStefano Zampini   if (*n_subdomains <=0) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONG,"Invalid number of subdomains requested %d\n",*n_subdomains);
502957de7509SStefano Zampini 
503057de7509SStefano Zampini   if (have_void) *have_void = PETSC_FALSE;
503157de7509SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
503257de7509SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
503357de7509SStefano Zampini   ierr = MatISGetLocalMat(mat,&A);CHKERRQ(ierr);
503457de7509SStefano Zampini   ierr = MatGetLocalSize(A,&n,NULL);CHKERRQ(ierr);
503557de7509SStefano Zampini   im_active = !!(n);
503657de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
503757de7509SStefano Zampini   void_procs = size - active_procs;
503857de7509SStefano Zampini   /* get ranks of of non-active processes in mat communicator */
503957de7509SStefano Zampini   if (void_procs) {
504057de7509SStefano Zampini     PetscInt ncand;
504157de7509SStefano Zampini 
504257de7509SStefano Zampini     if (have_void) *have_void = PETSC_TRUE;
504357de7509SStefano Zampini     ierr = PetscMalloc1(size,&procs_candidates);CHKERRQ(ierr);
504457de7509SStefano Zampini     ierr = MPI_Allgather(&im_active,1,MPIU_INT,procs_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
504557de7509SStefano Zampini     for (i=0,ncand=0;i<size;i++) {
504657de7509SStefano Zampini       if (!procs_candidates[i]) {
504757de7509SStefano Zampini         procs_candidates[ncand++] = i;
504857de7509SStefano Zampini       }
504957de7509SStefano Zampini     }
505057de7509SStefano Zampini     /* force n_subdomains to be not greater that the number of non-active processes */
505157de7509SStefano Zampini     *n_subdomains = PetscMin(void_procs,*n_subdomains);
505257de7509SStefano Zampini   }
505357de7509SStefano Zampini 
505457de7509SStefano Zampini   /* number of subdomains requested greater than active processes -> just shift the matrix */
505557de7509SStefano Zampini   if (active_procs < *n_subdomains) {
505657de7509SStefano Zampini     PetscInt issize,isidx;
505757de7509SStefano Zampini     if (im_active) {
505857de7509SStefano Zampini       issize = 1;
505957de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
506057de7509SStefano Zampini         isidx = procs_candidates[rank];
506157de7509SStefano Zampini       } else {
506257de7509SStefano Zampini         isidx = rank;
506357de7509SStefano Zampini       }
506457de7509SStefano Zampini     } else {
506557de7509SStefano Zampini       issize = 0;
506657de7509SStefano Zampini       isidx = -1;
506757de7509SStefano Zampini     }
506857de7509SStefano Zampini     *n_subdomains = active_procs;
506957de7509SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),issize,&isidx,PETSC_COPY_VALUES,is_sends);CHKERRQ(ierr);
5070daf8a457SStefano Zampini     ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
507157de7509SStefano Zampini     PetscFunctionReturn(0);
507257de7509SStefano Zampini   }
5073c5929fdfSBarry Smith   ierr = PetscOptionsGetBool(NULL,NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
5074c5929fdfSBarry Smith   ierr = PetscOptionsGetInt(NULL,NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
507527b6a85dSStefano Zampini   threshold = PetscMax(threshold,2);
5076e7931f94SStefano Zampini 
5077e7931f94SStefano Zampini   /* Get info on mapping */
50783bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&local_size);CHKERRQ(ierr);
50793bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
5080e7931f94SStefano Zampini 
5081e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
5082785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
5083e7931f94SStefano Zampini   xadj[0] = 0;
5084e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
5085785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
5086785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
508727b6a85dSStefano Zampini   ierr = PetscCalloc1(local_size,&count);CHKERRQ(ierr);
508827b6a85dSStefano Zampini   for (i=1;i<n_neighs;i++)
508927b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++)
509027b6a85dSStefano Zampini       count[shared[i][j]] += 1;
5091e7931f94SStefano Zampini 
509227b6a85dSStefano Zampini   xadj_count = 0;
50932b510759SStefano Zampini   for (i=1;i<n_neighs;i++) {
509427b6a85dSStefano Zampini     for (j=0;j<n_shared[i];j++) {
509527b6a85dSStefano Zampini       if (count[shared[i][j]] < threshold) {
5096d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
5097d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
5098d023bfaeSStefano Zampini         xadj_count++;
509927b6a85dSStefano Zampini         break;
510027b6a85dSStefano Zampini       }
5101e7931f94SStefano Zampini     }
5102e7931f94SStefano Zampini   }
5103d023bfaeSStefano Zampini   xadj[1] = xadj_count;
510427b6a85dSStefano Zampini   ierr = PetscFree(count);CHKERRQ(ierr);
51053bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(mat->rmap->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
5106e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
5107e7931f94SStefano Zampini 
51083837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
5109e7931f94SStefano Zampini 
511027b6a85dSStefano Zampini   /* Restrict work on active processes only */
511127b6a85dSStefano Zampini   ierr = PetscMPIIntCast(im_active,&color);CHKERRQ(ierr);
511227b6a85dSStefano Zampini   if (void_procs) {
511327b6a85dSStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&psubcomm);CHKERRQ(ierr);
511427b6a85dSStefano Zampini     ierr = PetscSubcommSetNumber(psubcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
511527b6a85dSStefano Zampini     ierr = PetscSubcommSetTypeGeneral(psubcomm,color,rank);CHKERRQ(ierr);
511627b6a85dSStefano Zampini     subcomm = PetscSubcommChild(psubcomm);
511727b6a85dSStefano Zampini   } else {
511827b6a85dSStefano Zampini     psubcomm = NULL;
511927b6a85dSStefano Zampini     subcomm = PetscObjectComm((PetscObject)mat);
512027b6a85dSStefano Zampini   }
512127b6a85dSStefano Zampini 
512227b6a85dSStefano Zampini   v_wgt = NULL;
512327b6a85dSStefano Zampini   if (!color) {
5124e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
5125e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
5126e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
5127c8587f34SStefano Zampini   } else {
512852e5ac9dSStefano Zampini     Mat             subdomain_adj;
512952e5ac9dSStefano Zampini     IS              new_ranks,new_ranks_contig;
513052e5ac9dSStefano Zampini     MatPartitioning partitioner;
513127b6a85dSStefano Zampini     PetscInt        rstart=0,rend=0;
513252e5ac9dSStefano Zampini     PetscInt        *is_indices,*oldranks;
513357de7509SStefano Zampini     PetscMPIInt     size;
5134b0c7d250SStefano Zampini     PetscBool       aggregate;
5135b0c7d250SStefano Zampini 
513627b6a85dSStefano Zampini     ierr = MPI_Comm_size(subcomm,&size);CHKERRQ(ierr);
513727b6a85dSStefano Zampini     if (void_procs) {
513827b6a85dSStefano Zampini       PetscInt prank = rank;
5139785e854fSJed Brown       ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
514027b6a85dSStefano Zampini       ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm);CHKERRQ(ierr);
5141e7931f94SStefano Zampini       for (i=0;i<xadj[1];i++) {
5142e7931f94SStefano Zampini         ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
5143c8587f34SStefano Zampini       }
5144e7931f94SStefano Zampini       ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
514527b6a85dSStefano Zampini     } else {
514627b6a85dSStefano Zampini       oldranks = NULL;
514727b6a85dSStefano Zampini     }
5148b0c7d250SStefano Zampini     aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE);
514927b6a85dSStefano Zampini     if (aggregate) { /* TODO: all this part could be made more efficient */
5150b0c7d250SStefano Zampini       PetscInt    lrows,row,ncols,*cols;
5151b0c7d250SStefano Zampini       PetscMPIInt nrank;
5152b0c7d250SStefano Zampini       PetscScalar *vals;
5153b0c7d250SStefano Zampini 
515427b6a85dSStefano Zampini       ierr = MPI_Comm_rank(subcomm,&nrank);CHKERRQ(ierr);
5155b0c7d250SStefano Zampini       lrows = 0;
5156b0c7d250SStefano Zampini       if (nrank<redprocs) {
5157b0c7d250SStefano Zampini         lrows = size/redprocs;
5158b0c7d250SStefano Zampini         if (nrank<size%redprocs) lrows++;
5159b0c7d250SStefano Zampini       }
516027b6a85dSStefano Zampini       ierr = MatCreateAIJ(subcomm,lrows,lrows,size,size,50,NULL,50,NULL,&subdomain_adj);CHKERRQ(ierr);
5161b0c7d250SStefano Zampini       ierr = MatGetOwnershipRange(subdomain_adj,&rstart,&rend);CHKERRQ(ierr);
5162b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
5163b0c7d250SStefano Zampini       ierr = MatSetOption(subdomain_adj,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
5164b0c7d250SStefano Zampini       row = nrank;
5165b0c7d250SStefano Zampini       ncols = xadj[1]-xadj[0];
5166b0c7d250SStefano Zampini       cols = adjncy;
5167b0c7d250SStefano Zampini       ierr = PetscMalloc1(ncols,&vals);CHKERRQ(ierr);
5168b0c7d250SStefano Zampini       for (i=0;i<ncols;i++) vals[i] = adjncy_wgt[i];
5169b0c7d250SStefano Zampini       ierr = MatSetValues(subdomain_adj,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
5170b0c7d250SStefano Zampini       ierr = MatAssemblyBegin(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5171b0c7d250SStefano Zampini       ierr = MatAssemblyEnd(subdomain_adj,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
517252e5ac9dSStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
517352e5ac9dSStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
517452e5ac9dSStefano Zampini       ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
5175b0c7d250SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
517627b6a85dSStefano Zampini       if (use_vwgt) {
517727b6a85dSStefano Zampini         Vec               v;
517827b6a85dSStefano Zampini         const PetscScalar *array;
517927b6a85dSStefano Zampini         PetscInt          nl;
518027b6a85dSStefano Zampini 
518127b6a85dSStefano Zampini         ierr = MatCreateVecs(subdomain_adj,&v,NULL);CHKERRQ(ierr);
518227b6a85dSStefano Zampini         ierr = VecSetValue(v,row,(PetscScalar)local_size,INSERT_VALUES);CHKERRQ(ierr);
518327b6a85dSStefano Zampini         ierr = VecAssemblyBegin(v);CHKERRQ(ierr);
518427b6a85dSStefano Zampini         ierr = VecAssemblyEnd(v);CHKERRQ(ierr);
518527b6a85dSStefano Zampini         ierr = VecGetLocalSize(v,&nl);CHKERRQ(ierr);
518627b6a85dSStefano Zampini         ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
518727b6a85dSStefano Zampini         ierr = PetscMalloc1(nl,&v_wgt);CHKERRQ(ierr);
518822db5ddcSStefano Zampini         for (i=0;i<nl;i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]);
518927b6a85dSStefano Zampini         ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
519027b6a85dSStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
519127b6a85dSStefano Zampini       }
5192b0c7d250SStefano Zampini     } else {
519327b6a85dSStefano Zampini       ierr = MatCreateMPIAdj(subcomm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
519427b6a85dSStefano Zampini       if (use_vwgt) {
519527b6a85dSStefano Zampini         ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
519627b6a85dSStefano Zampini         v_wgt[0] = local_size;
519727b6a85dSStefano Zampini       }
5198b0c7d250SStefano Zampini     }
519922b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
5200e7931f94SStefano Zampini 
5201e7931f94SStefano Zampini     /* Partition */
520227b6a85dSStefano Zampini     ierr = MatPartitioningCreate(subcomm,&partitioner);CHKERRQ(ierr);
5203e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
520427b6a85dSStefano Zampini     if (v_wgt) {
5205e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
5206c8587f34SStefano Zampini     }
520757de7509SStefano Zampini     *n_subdomains = PetscMin((PetscInt)size,*n_subdomains);
520857de7509SStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,*n_subdomains);CHKERRQ(ierr);
5209e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
5210e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
521122b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
5212e7931f94SStefano Zampini 
521352e5ac9dSStefano Zampini     /* renumber new_ranks to avoid "holes" in new set of processors */
521452e5ac9dSStefano Zampini     ierr = PCBDDCSubsetNumbering(new_ranks,NULL,NULL,&new_ranks_contig);CHKERRQ(ierr);
521552e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
521652e5ac9dSStefano Zampini     ierr = ISGetIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
521757de7509SStefano Zampini     if (!aggregate) {
521857de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
521927b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
522027b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
522127b6a85dSStefano Zampini #endif
522257de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]];
522327b6a85dSStefano Zampini       } else if (oldranks) {
5224b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[is_indices[0]];
522527b6a85dSStefano Zampini       } else {
522627b6a85dSStefano Zampini         ranks_send_to_idx[0] = is_indices[0];
522757de7509SStefano Zampini       }
522828143c3dSStefano Zampini     } else {
5229b0c7d250SStefano Zampini       PetscInt    idxs[1];
5230b0c7d250SStefano Zampini       PetscMPIInt tag;
5231b0c7d250SStefano Zampini       MPI_Request *reqs;
5232b0c7d250SStefano Zampini 
5233b0c7d250SStefano Zampini       ierr = PetscObjectGetNewTag((PetscObject)subdomain_adj,&tag);CHKERRQ(ierr);
5234b0c7d250SStefano Zampini       ierr = PetscMalloc1(rend-rstart,&reqs);CHKERRQ(ierr);
5235b0c7d250SStefano Zampini       for (i=rstart;i<rend;i++) {
523627b6a85dSStefano Zampini         ierr = MPI_Isend(is_indices+i-rstart,1,MPIU_INT,i,tag,subcomm,&reqs[i-rstart]);CHKERRQ(ierr);
523728143c3dSStefano Zampini       }
523827b6a85dSStefano Zampini       ierr = MPI_Recv(idxs,1,MPIU_INT,MPI_ANY_SOURCE,tag,subcomm,MPI_STATUS_IGNORE);CHKERRQ(ierr);
5239b0c7d250SStefano Zampini       ierr = MPI_Waitall(rend-rstart,reqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5240b0c7d250SStefano Zampini       ierr = PetscFree(reqs);CHKERRQ(ierr);
524157de7509SStefano Zampini       if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */
524227b6a85dSStefano Zampini #if defined(PETSC_USE_DEBUG)
524327b6a85dSStefano Zampini         if (!oldranks) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
524427b6a85dSStefano Zampini #endif
524557de7509SStefano Zampini         ranks_send_to_idx[0] = procs_candidates[oldranks[idxs[0]]];
524627b6a85dSStefano Zampini       } else if (oldranks) {
5247b0c7d250SStefano Zampini         ranks_send_to_idx[0] = oldranks[idxs[0]];
524827b6a85dSStefano Zampini       } else {
524927b6a85dSStefano Zampini         ranks_send_to_idx[0] = idxs[0];
5250e7931f94SStefano Zampini       }
525157de7509SStefano Zampini     }
525252e5ac9dSStefano Zampini     ierr = ISRestoreIndices(new_ranks_contig,(const PetscInt**)&is_indices);CHKERRQ(ierr);
5253e7931f94SStefano Zampini     /* clean up */
5254e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
525552e5ac9dSStefano Zampini     ierr = ISDestroy(&new_ranks_contig);CHKERRQ(ierr);
5256e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
5257e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
5258e7931f94SStefano Zampini   }
525927b6a85dSStefano Zampini   ierr = PetscSubcommDestroy(&psubcomm);CHKERRQ(ierr);
526057de7509SStefano Zampini   ierr = PetscFree(procs_candidates);CHKERRQ(ierr);
5261e7931f94SStefano Zampini 
5262e7931f94SStefano Zampini   /* assemble parallel IS for sends */
5263e7931f94SStefano Zampini   i = 1;
526427b6a85dSStefano Zampini   if (!color) i=0;
526557de7509SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,is_sends);CHKERRQ(ierr);
5266e7931f94SStefano Zampini   PetscFunctionReturn(0);
5267e7931f94SStefano Zampini }
5268e7931f94SStefano Zampini 
5269e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
5270e7931f94SStefano Zampini 
5271e7931f94SStefano Zampini #undef __FUNCT__
5272e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
52731ae86dd6SStefano 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[])
5274e7931f94SStefano Zampini {
527570cf5478SStefano Zampini   Mat                    local_mat;
5276e7931f94SStefano Zampini   IS                     is_sends_internal;
52779d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
52781ae86dd6SStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals,buf_size_vecs;
52799d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
5280e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
5281e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
5282e7931f94SStefano Zampini   const PetscInt*        is_indices;
5283e7931f94SStefano Zampini   MatType                new_local_type;
5284e7931f94SStefano Zampini   /* buffers */
5285e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
528628143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
52879d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
5288e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
52891ae86dd6SStefano Zampini   PetscScalar            *ptr_vecs,*send_buffer_vecs,*recv_buffer_vecs;
5290e7931f94SStefano Zampini   /* MPI */
529128143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
529228143c3dSStefano Zampini   PetscSubcomm           subcomm;
5293e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
529428143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
529528143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
52961ae86dd6SStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,tag_vecs,source_dest;
52971ae86dd6SStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals,*send_req_vecs;
52981ae86dd6SStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals,*recv_req_vecs;
5299e7931f94SStefano Zampini   PetscErrorCode         ierr;
5300e7931f94SStefano Zampini 
5301e7931f94SStefano Zampini   PetscFunctionBegin;
530257de7509SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5303e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
530428143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
530557de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
530657de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
530757de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_full,5);
530857de7509SStefano Zampini   PetscValidLogicalCollectiveBool(mat,reuse,6);
530957de7509SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,8);
53101ae86dd6SStefano Zampini   PetscValidLogicalCollectiveInt(mat,nvecs,10);
53111ae86dd6SStefano Zampini   if (nvecs) {
53121ae86dd6SStefano Zampini     if (nvecs > 1) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Just 1 vector supported");
53131ae86dd6SStefano Zampini     PetscValidHeaderSpecific(nnsp_vec[0],VEC_CLASSID,11);
53141ae86dd6SStefano Zampini   }
531557de7509SStefano Zampini   /* further checks */
5316e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
5317e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
5318e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
5319e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
5320e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
532157de7509SStefano Zampini   if (reuse && *mat_n) {
532270cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
532357de7509SStefano Zampini     PetscValidHeaderSpecific(*mat_n,MAT_CLASSID,7);
532470cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
532528143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
532670cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
532770cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
532870cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
532970cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
533070cf5478SStefano Zampini   }
5331e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
5332e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
533357de7509SStefano Zampini 
5334e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
5335e7931f94SStefano Zampini   if (!is_sends) {
533628143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
533757de7509SStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,&n_subdomains,0,&is_sends_internal,NULL);CHKERRQ(ierr);
5338c8587f34SStefano Zampini   } else {
5339e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
5340e7931f94SStefano Zampini     is_sends_internal = is_sends;
5341c8587f34SStefano Zampini   }
5342e7931f94SStefano Zampini 
5343e7931f94SStefano Zampini   /* get comm */
5344a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
5345e7931f94SStefano Zampini 
5346e7931f94SStefano Zampini   /* compute number of sends */
5347e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
5348e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
5349e7931f94SStefano Zampini 
5350e7931f94SStefano Zampini   /* compute number of receives */
5351e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
5352785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
5353e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
5354e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
5355e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
5356e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
5357e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
5358e7931f94SStefano Zampini 
535928143c3dSStefano Zampini   /* restrict comm if requested */
536028143c3dSStefano Zampini   subcomm = 0;
536128143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
536228143c3dSStefano Zampini   if (restrict_comm) {
5363779c1cceSStefano Zampini     PetscMPIInt color,subcommsize;
5364779c1cceSStefano Zampini 
536528143c3dSStefano Zampini     color = 0;
536653a05cb3SStefano Zampini     if (restrict_full) {
536753a05cb3SStefano Zampini       if (!n_recvs) color = 1; /* processes not receiving anything will not partecipate in new comm (full restriction) */
536853a05cb3SStefano Zampini     } else {
536953a05cb3SStefano Zampini       if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not partecipate in new comm */
537053a05cb3SStefano Zampini     }
5371b2566f29SBarry Smith     ierr = MPIU_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
537228143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
537328143c3dSStefano Zampini     /* check if reuse has been requested */
537457de7509SStefano Zampini     if (reuse) {
537528143c3dSStefano Zampini       if (*mat_n) {
537628143c3dSStefano Zampini         PetscMPIInt subcommsize2;
537728143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
537828143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
537928143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
538028143c3dSStefano Zampini       } else {
538128143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
538228143c3dSStefano Zampini       }
538328143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
5384779c1cceSStefano Zampini       PetscMPIInt rank;
5385779c1cceSStefano Zampini 
5386779c1cceSStefano Zampini       ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
538728143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
538828143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
538928143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
5390306c2d5bSBarry Smith       comm_n = PetscSubcommChild(subcomm);
539128143c3dSStefano Zampini     }
539228143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
539328143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
539428143c3dSStefano Zampini   } else {
539528143c3dSStefano Zampini     comm_n = comm;
539628143c3dSStefano Zampini   }
539728143c3dSStefano Zampini 
5398e7931f94SStefano Zampini   /* prepare send/receive buffers */
5399785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
5400e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
5401785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
5402e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
540328143c3dSStefano Zampini   if (nis) {
5404854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
540528143c3dSStefano Zampini   }
5406e7931f94SStefano Zampini 
540728143c3dSStefano Zampini   /* Get data from local matrices */
54086c4ed002SBarry Smith   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
5409e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
5410e7931f94SStefano Zampini     /*
5411e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
5412e7931f94SStefano Zampini        send_buffer_idxs should contain:
5413e7931f94SStefano Zampini        - MatType_PRIVATE type
5414e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
5415e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
5416e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
5417e7931f94SStefano Zampini     */
54186c4ed002SBarry Smith   else {
5419e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
54203bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&i);CHKERRQ(ierr);
5421854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
5422e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
5423e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
54243bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
5425e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
54263bbff08aSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
5427e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
5428e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
5429e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
5430e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
5431c8587f34SStefano Zampini     }
5432c8587f34SStefano Zampini   }
5433e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
543428143c3dSStefano Zampini   /* additional is (if any) */
543528143c3dSStefano Zampini   if (nis) {
543628143c3dSStefano Zampini     PetscMPIInt psum;
543728143c3dSStefano Zampini     PetscInt j;
543828143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
543928143c3dSStefano Zampini       PetscInt plen;
544028143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
544128143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
544228143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
544328143c3dSStefano Zampini     }
5444854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
544528143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
544628143c3dSStefano Zampini       PetscInt plen;
544728143c3dSStefano Zampini       const PetscInt *is_array_idxs;
544828143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
544928143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
545028143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
545128143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
545228143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
545328143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
545428143c3dSStefano Zampini     }
545528143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
545628143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
545728143c3dSStefano Zampini     }
545828143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
545928143c3dSStefano Zampini   }
546028143c3dSStefano Zampini 
5461e7931f94SStefano Zampini   buf_size_idxs = 0;
5462e7931f94SStefano Zampini   buf_size_vals = 0;
546328143c3dSStefano Zampini   buf_size_idxs_is = 0;
54641ae86dd6SStefano Zampini   buf_size_vecs = 0;
5465e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
5466e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
5467e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
546828143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
54691ae86dd6SStefano Zampini     if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i];
5470e7931f94SStefano Zampini   }
5471785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
5472785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
547395ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
54741ae86dd6SStefano Zampini   ierr = PetscMalloc1(buf_size_vecs,&recv_buffer_vecs);CHKERRQ(ierr);
5475e7931f94SStefano Zampini 
5476e7931f94SStefano Zampini   /* get new tags for clean communications */
5477e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
5478e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
547928143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
54801ae86dd6SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vecs);CHKERRQ(ierr);
5481e7931f94SStefano Zampini 
5482e7931f94SStefano Zampini   /* allocate for requests */
5483785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
5484785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
548595ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
54861ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_vecs);CHKERRQ(ierr);
5487785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
5488785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
548995ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
54901ae86dd6SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_vecs);CHKERRQ(ierr);
5491e7931f94SStefano Zampini 
5492e7931f94SStefano Zampini   /* communications */
5493e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
5494e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
549528143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
54961ae86dd6SStefano Zampini   ptr_vecs = recv_buffer_vecs;
5497e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
5498e7931f94SStefano Zampini     source_dest = onodes[i];
5499e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
5500e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
5501e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5502e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
550328143c3dSStefano Zampini     if (nis) {
550457de7509SStefano Zampini       source_dest = onodes_is[i];
550528143c3dSStefano 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);
550628143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
550728143c3dSStefano Zampini     }
55081ae86dd6SStefano Zampini     if (nvecs) {
55091ae86dd6SStefano Zampini       source_dest = onodes[i];
55101ae86dd6SStefano Zampini       ierr = MPI_Irecv(ptr_vecs,olengths_idxs[i]-2,MPIU_SCALAR,source_dest,tag_vecs,comm,&recv_req_vecs[i]);CHKERRQ(ierr);
55111ae86dd6SStefano Zampini       ptr_vecs += olengths_idxs[i]-2;
55121ae86dd6SStefano Zampini     }
5513e7931f94SStefano Zampini   }
5514e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
5515e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
5516e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
5517e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
551828143c3dSStefano Zampini     if (nis) {
551928143c3dSStefano 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);
552028143c3dSStefano Zampini     }
55211ae86dd6SStefano Zampini     if (nvecs) {
55221ae86dd6SStefano Zampini       ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
55231ae86dd6SStefano 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);
55241ae86dd6SStefano Zampini     }
5525e7931f94SStefano Zampini   }
5526e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
5527e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
5528e7931f94SStefano Zampini 
5529e7931f94SStefano Zampini   /* assemble new l2g map */
5530e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5531e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
55329d30be91SStefano Zampini   new_local_rows = 0;
5533e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
55349d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
5535e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5536e7931f94SStefano Zampini   }
55379d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
5538e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
55399d30be91SStefano Zampini   new_local_rows = 0;
5540e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
55419d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
55429d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
5543e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5544e7931f94SStefano Zampini   }
55459d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
55469d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
5547e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
5548e7931f94SStefano Zampini 
5549e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
5550e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
5551e7931f94SStefano 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) */
5552e7931f94SStefano Zampini   if (n_recvs) {
555328143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
5554e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
5555e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
5556e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
5557e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
5558e7931f94SStefano Zampini         break;
5559e7931f94SStefano Zampini       }
5560e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
5561e7931f94SStefano Zampini     }
5562e7931f94SStefano Zampini     switch (new_local_type_private) {
556328143c3dSStefano Zampini       case MATDENSE_PRIVATE:
556428143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
5565e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
5566e7931f94SStefano Zampini           bs = 1;
556728143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
556828143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
556928143c3dSStefano Zampini           bs = 1;
557028143c3dSStefano Zampini         }
5571e7931f94SStefano Zampini         break;
5572e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
5573e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
5574e7931f94SStefano Zampini         bs = 1;
5575e7931f94SStefano Zampini         break;
5576e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
5577e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
5578e7931f94SStefano Zampini         break;
5579e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
5580e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
5581e7931f94SStefano Zampini         break;
5582e7931f94SStefano Zampini       default:
55839d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
5584e7931f94SStefano Zampini         break;
5585e7931f94SStefano Zampini     }
558628143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
558728143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
558828143c3dSStefano Zampini     bs = 1;
5589e7931f94SStefano Zampini   }
5590e7931f94SStefano Zampini 
559170cf5478SStefano Zampini   /* create MATIS object if needed */
559257de7509SStefano Zampini   if (!reuse) {
5593e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
5594e176bc59SStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
559570cf5478SStefano Zampini   } else {
559670cf5478SStefano Zampini     /* it also destroys the local matrices */
559757de7509SStefano Zampini     if (*mat_n) {
559870cf5478SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
559957de7509SStefano Zampini     } else { /* this is a fake object */
560057de7509SStefano Zampini       ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,NULL,mat_n);CHKERRQ(ierr);
560157de7509SStefano Zampini     }
560270cf5478SStefano Zampini   }
560370cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
5604e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
56059d30be91SStefano Zampini 
56069d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
56079d30be91SStefano Zampini 
56089d30be91SStefano Zampini   /* Global to local map of received indices */
56099d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
56109d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
56119d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
56129d30be91SStefano Zampini 
56139d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
56149d30be91SStefano Zampini   buf_size_idxs = 0;
56159d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
56169d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
56179d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
56189d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
56199d30be91SStefano Zampini   }
56209d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
56219d30be91SStefano Zampini 
56229d30be91SStefano Zampini   /* set preallocation */
56239d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
56249d30be91SStefano Zampini   if (!newisdense) {
56259d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
56269d30be91SStefano Zampini 
56279d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
56289d30be91SStefano Zampini     if (n_recvs) {
56299d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
56309d30be91SStefano Zampini     }
56319d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
56329d30be91SStefano Zampini       PetscInt j;
56339d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
56349d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
56359d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
56369d30be91SStefano Zampini         }
56379d30be91SStefano Zampini       } else {
56389d30be91SStefano Zampini         /* TODO */
56399d30be91SStefano Zampini       }
56409d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
56419d30be91SStefano Zampini     }
56429d30be91SStefano Zampini     if (new_local_nnz) {
56439d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
56449d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
56459d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
56469d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
56479d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
56489d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
56499d30be91SStefano Zampini     } else {
56509d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
56519d30be91SStefano Zampini     }
56529d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
56539d30be91SStefano Zampini   } else {
56549d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
56559d30be91SStefano Zampini   }
5656e7931f94SStefano Zampini 
5657e7931f94SStefano Zampini   /* set values */
5658e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
56599d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
5660e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
5661e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
5662e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
56639d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
5664e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
5665e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
5666e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
566728143c3dSStefano Zampini     } else {
566828143c3dSStefano Zampini       /* TODO */
5669e7931f94SStefano Zampini     }
5670e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
5671e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
5672e7931f94SStefano Zampini   }
5673e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5674e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
567570cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
567670cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
56779d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
5678e7931f94SStefano Zampini 
5679dfd14d43SStefano Zampini #if 0
568028143c3dSStefano Zampini   if (!restrict_comm) { /* check */
5681e7931f94SStefano Zampini     Vec       lvec,rvec;
5682e7931f94SStefano Zampini     PetscReal infty_error;
5683e7931f94SStefano Zampini 
56842a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
5685e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
5686e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
5687e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
568870cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
5689e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
5690e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
5691e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
5692e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
5693e7931f94SStefano Zampini   }
569428143c3dSStefano Zampini #endif
5695e7931f94SStefano Zampini 
569628143c3dSStefano Zampini   /* assemble new additional is (if any) */
569728143c3dSStefano Zampini   if (nis) {
569828143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
569928143c3dSStefano Zampini 
570028143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5701854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
570228143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
570328143c3dSStefano Zampini     psum = 0;
570428143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
570528143c3dSStefano Zampini       for (j=0;j<nis;j++) {
570628143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
570728143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
570828143c3dSStefano Zampini         psum += plen;
570928143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
571028143c3dSStefano Zampini       }
571128143c3dSStefano Zampini     }
5712854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
5713854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
571428143c3dSStefano Zampini     for (i=1;i<nis;i++) {
571528143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
571628143c3dSStefano Zampini     }
571728143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
571828143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
571928143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
572028143c3dSStefano Zampini       for (j=0;j<nis;j++) {
572128143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
572228143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
572328143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
572428143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
572528143c3dSStefano Zampini       }
572628143c3dSStefano Zampini     }
572728143c3dSStefano Zampini     for (i=0;i<nis;i++) {
572828143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
572928143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
573028143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
573128143c3dSStefano Zampini     }
573228143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
573328143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
573428143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
573528143c3dSStefano Zampini   }
5736e7931f94SStefano Zampini   /* free workspace */
573728143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
5738e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5739e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
5740e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5741e7931f94SStefano Zampini   if (isdense) {
5742e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
5743e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
5744e7931f94SStefano Zampini   } else {
5745e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
5746e7931f94SStefano Zampini   }
574728143c3dSStefano Zampini   if (nis) {
574828143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
574928143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
575028143c3dSStefano Zampini   }
57511ae86dd6SStefano Zampini 
57521ae86dd6SStefano Zampini   if (nvecs) {
57531ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
57541ae86dd6SStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_vecs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
57551ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
57561ae86dd6SStefano Zampini     ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
57571ae86dd6SStefano Zampini     ierr = VecCreate(comm_n,&nnsp_vec[0]);CHKERRQ(ierr);
57581ae86dd6SStefano Zampini     ierr = VecSetSizes(nnsp_vec[0],new_local_rows,PETSC_DECIDE);CHKERRQ(ierr);
57591ae86dd6SStefano Zampini     ierr = VecSetType(nnsp_vec[0],VECSTANDARD);CHKERRQ(ierr);
57601ae86dd6SStefano Zampini     /* set values */
57611ae86dd6SStefano Zampini     ptr_vals = recv_buffer_vecs;
57621ae86dd6SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
57631ae86dd6SStefano Zampini     ierr = VecGetArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
57641ae86dd6SStefano Zampini     for (i=0;i<n_recvs;i++) {
57651ae86dd6SStefano Zampini       PetscInt j;
57661ae86dd6SStefano Zampini       for (j=0;j<*(ptr_idxs+1);j++) {
57671ae86dd6SStefano Zampini         send_buffer_vecs[*(ptr_idxs+2+j)] += *(ptr_vals + j);
57681ae86dd6SStefano Zampini       }
57691ae86dd6SStefano Zampini       ptr_idxs += olengths_idxs[i];
57701ae86dd6SStefano Zampini       ptr_vals += olengths_idxs[i]-2;
57711ae86dd6SStefano Zampini     }
57721ae86dd6SStefano Zampini     ierr = VecRestoreArray(nnsp_vec[0],&send_buffer_vecs);CHKERRQ(ierr);
57731ae86dd6SStefano Zampini     ierr = VecAssemblyBegin(nnsp_vec[0]);CHKERRQ(ierr);
57741ae86dd6SStefano Zampini     ierr = VecAssemblyEnd(nnsp_vec[0]);CHKERRQ(ierr);
57751ae86dd6SStefano Zampini   }
57761ae86dd6SStefano Zampini 
57771ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_vecs);CHKERRQ(ierr);
57781ae86dd6SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
5779e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
5780e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
57811ae86dd6SStefano Zampini   ierr = PetscFree(recv_req_vecs);CHKERRQ(ierr);
578228143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
5783e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
5784e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
57851ae86dd6SStefano Zampini   ierr = PetscFree(send_req_vecs);CHKERRQ(ierr);
578628143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
5787e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
5788e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
5789e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
5790e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
5791e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
579228143c3dSStefano Zampini   if (nis) {
579328143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
579428143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
579528143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
579628143c3dSStefano Zampini   }
579728143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
579828143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
579928143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
580028143c3dSStefano Zampini     for (i=0;i<nis;i++) {
580128143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
580228143c3dSStefano Zampini     }
58031ae86dd6SStefano Zampini     if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */
58041ae86dd6SStefano Zampini       ierr = VecDestroy(&nnsp_vec[0]);CHKERRQ(ierr);
58051ae86dd6SStefano Zampini     }
580653a05cb3SStefano Zampini     *mat_n = NULL;
580728143c3dSStefano Zampini   }
5808e7931f94SStefano Zampini   PetscFunctionReturn(0);
5809e7931f94SStefano Zampini }
5810a57a6d2fSStefano Zampini 
581112edc857SStefano Zampini /* temporary hack into ksp private data structure */
5812af0996ceSBarry Smith #include <petsc/private/kspimpl.h>
581312edc857SStefano Zampini 
5814c8587f34SStefano Zampini #undef __FUNCT__
5815c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
5816c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
5817c8587f34SStefano Zampini {
5818c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
5819c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
582020a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
58211ae86dd6SStefano Zampini   Mat                    coarsedivudotp = NULL;
58229881197aSStefano Zampini   MatNullSpace           CoarseNullSpace = NULL;
582320a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
58246e683305SStefano Zampini   IS                     coarse_is,*isarray;
58256e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
582630368db7SStefano Zampini   PetscInt               nis,nisdofs,nisneu,nisvert;
5827f9eb5b7dSStefano Zampini   PC                     pc_temp;
5828c8587f34SStefano Zampini   PCType                 coarse_pc_type;
5829c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
5830f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
58314f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
58326e683305SStefano Zampini   Mat                    t_coarse_mat_is;
583357de7509SStefano Zampini   PetscInt               ncoarse;
583468457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
583522bc73bbSStefano Zampini   PetscScalar            *array;
583657de7509SStefano Zampini   MatReuse               coarse_mat_reuse;
583757de7509SStefano Zampini   PetscBool              restr, full_restr, have_void;
58389881197aSStefano Zampini   PetscErrorCode         ierr;
5839fdc09c96SStefano Zampini 
5840c8587f34SStefano Zampini   PetscFunctionBegin;
5841c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
584268457ee5SStefano 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 */
5843fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
58445a75c04eSSatish Balay     compute_vecs = PETSC_TRUE;
5845fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
5846f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
5847f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
5848f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
5849fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
585051bea450SStefano Zampini       /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */
585151bea450SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) {
5852dc4bcba2SStefano Zampini         PC        pc;
5853dc4bcba2SStefano Zampini         PetscBool isbddc;
5854dc4bcba2SStefano Zampini 
5855dc4bcba2SStefano Zampini         /* temporary workaround since PCBDDC does not have a reset method so far */
5856dc4bcba2SStefano Zampini         ierr = KSPGetPC(pcbddc->coarse_ksp,&pc);CHKERRQ(ierr);
5857dc4bcba2SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBDDC,&isbddc);CHKERRQ(ierr);
5858dc4bcba2SStefano Zampini         if (isbddc) {
585963c961adSStefano Zampini           ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
586063c961adSStefano Zampini         } else {
5861727cdba6SStefano Zampini           ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
586263c961adSStefano Zampini         }
5863fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
5864fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
5865fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
5866f4ddd8eeSStefano Zampini       }
5867fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
5868fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
5869f4ddd8eeSStefano Zampini     }
587070cf5478SStefano Zampini     /* reset any subassembling information */
587157de7509SStefano Zampini     if (!coarse_reuse || pcbddc->recompute_topography) {
587270cf5478SStefano Zampini       ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
587357de7509SStefano Zampini     }
58746e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
5875fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
5876f4ddd8eeSStefano Zampini   }
587757de7509SStefano Zampini   /* assemble coarse matrix */
587857de7509SStefano Zampini   if (coarse_reuse && pcbddc->coarse_ksp) {
587957de7509SStefano Zampini     ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
588057de7509SStefano Zampini     ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
588157de7509SStefano Zampini     coarse_mat_reuse = MAT_REUSE_MATRIX;
588218a45a71SStefano Zampini   } else {
588357de7509SStefano Zampini     coarse_mat = NULL;
588457de7509SStefano Zampini     coarse_mat_reuse = MAT_INITIAL_MATRIX;
58856e683305SStefano Zampini   }
5886e7931f94SStefano Zampini 
5887abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
5888abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
5889abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
5890abbbba34SStefano Zampini 
5891abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
589222bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
589322bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
589422bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
589522bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
5896e176bc59SStefano 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);
58976e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
58986e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
58996e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5900abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
5901abbbba34SStefano Zampini 
590257de7509SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
590357de7509SStefano Zampini   im_active = !!(pcis->n);
590457de7509SStefano Zampini   ierr = MPIU_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
590557de7509SStefano Zampini 
590657de7509SStefano Zampini   /* determine number of process partecipating to coarse solver and compute subassembling pattern */
590757de7509SStefano Zampini   /* restr : whether if we want to exclude senders (which are not receivers) from the subassembling pattern */
590857de7509SStefano Zampini   /* full_restr : just use the receivers from the subassembling pattern */
590957de7509SStefano Zampini   coarse_mat_is = NULL;
591057de7509SStefano Zampini   multilevel_allowed = PETSC_FALSE;
591157de7509SStefano Zampini   multilevel_requested = PETSC_FALSE;
591257de7509SStefano Zampini   full_restr = PETSC_TRUE;
59131ae86dd6SStefano Zampini   pcbddc->coarse_eqs_per_proc = PetscMin(PetscMax(pcbddc->coarse_size,1),pcbddc->coarse_eqs_per_proc);
591457de7509SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE;
591557de7509SStefano Zampini   if (multilevel_requested) {
591657de7509SStefano Zampini     ncoarse = active_procs/pcbddc->coarsening_ratio;
591757de7509SStefano Zampini     restr = PETSC_FALSE;
591857de7509SStefano Zampini     full_restr = PETSC_FALSE;
591957de7509SStefano Zampini   } else {
592057de7509SStefano Zampini     ncoarse = pcbddc->coarse_size/pcbddc->coarse_eqs_per_proc;
592157de7509SStefano Zampini     restr = PETSC_TRUE;
592257de7509SStefano Zampini     full_restr = PETSC_TRUE;
592357de7509SStefano Zampini   }
59244b2aedd3SStefano Zampini   if (!pcbddc->coarse_size) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE;
592557de7509SStefano Zampini   ncoarse = PetscMax(1,ncoarse);
592657de7509SStefano Zampini   if (!pcbddc->coarse_subassembling) {
5927a198735bSStefano Zampini     if (pcbddc->coarsening_ratio > 1) {
592857de7509SStefano Zampini       ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,&ncoarse,pcbddc->coarse_adj_red,&pcbddc->coarse_subassembling,&have_void);CHKERRQ(ierr);
5929a198735bSStefano Zampini     } else {
5930a198735bSStefano Zampini       PetscMPIInt size,rank;
5931a198735bSStefano Zampini       ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
5932a198735bSStefano Zampini       ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
5933a198735bSStefano Zampini       have_void = (active_procs == (PetscInt)size) ? PETSC_FALSE : PETSC_TRUE;
5934a198735bSStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),1,rank,1,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
5935a198735bSStefano Zampini     }
593657de7509SStefano Zampini   } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */
593757de7509SStefano Zampini     PetscInt    psum;
593857de7509SStefano Zampini     PetscMPIInt size;
593957de7509SStefano Zampini     if (pcbddc->coarse_ksp) psum = 1;
594057de7509SStefano Zampini     else psum = 0;
594157de7509SStefano Zampini     ierr = MPIU_Allreduce(&psum,&ncoarse,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
594257de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
594357de7509SStefano Zampini     if (ncoarse < size) have_void = PETSC_TRUE;
594457de7509SStefano Zampini   }
594557de7509SStefano Zampini   /* determine if we can go multilevel */
594657de7509SStefano Zampini   if (multilevel_requested) {
594757de7509SStefano Zampini     if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */
594857de7509SStefano Zampini     else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */
594957de7509SStefano Zampini   }
595057de7509SStefano Zampini   if (multilevel_allowed && have_void) restr = PETSC_TRUE;
595157de7509SStefano Zampini 
5952e4d548c7SStefano Zampini   /* dump subassembling pattern */
5953e4d548c7SStefano Zampini   if (pcbddc->dbg_flag && multilevel_allowed) {
5954e4d548c7SStefano Zampini     ierr = ISView(pcbddc->coarse_subassembling,pcbddc->dbg_viewer);CHKERRQ(ierr);
5955e4d548c7SStefano Zampini   }
5956e4d548c7SStefano Zampini 
59576e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
595827b6a85dSStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal)) { /* protects from unneded computations */
59596e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
59606e683305SStefano Zampini     const PetscInt         *idxs;
59616e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
59626e683305SStefano Zampini 
59636e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
59640be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
59656e683305SStefano Zampini     /* allocate space for temporary storage */
5966854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
5967854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
59686e683305SStefano Zampini     /* allocate for IS array */
59696e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
59706e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
597127b6a85dSStefano Zampini     nisvert = 0; /* nisvert is not used */
597230368db7SStefano Zampini     nis = nisdofs + nisneu + nisvert;
5973854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
59746e683305SStefano Zampini     /* dofs splitting */
59756e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
59766e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
59776e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
59786e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
59796e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
59806e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
59816e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
598230368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
59836e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
59846e683305SStefano Zampini     }
59856e683305SStefano Zampini     /* neumann boundaries */
59866e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
59876e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
59886e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
59896e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
59906e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
59916e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
59926e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
599330368db7SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
59946e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
59956e683305SStefano Zampini     }
59966e683305SStefano Zampini     /* free memory */
59976e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
59986e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
59996e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
60006e683305SStefano Zampini   } else {
60016e683305SStefano Zampini     nis = 0;
60026e683305SStefano Zampini     nisdofs = 0;
60036e683305SStefano Zampini     nisneu = 0;
600430368db7SStefano Zampini     nisvert = 0;
60056e683305SStefano Zampini     isarray = NULL;
60066e683305SStefano Zampini   }
60076e683305SStefano Zampini   /* destroy no longer needed map */
60086e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
60096e683305SStefano Zampini 
601057de7509SStefano Zampini   /* subassemble */
601157de7509SStefano Zampini   if (multilevel_allowed) {
60121ae86dd6SStefano Zampini     Vec       vp[1];
60131ae86dd6SStefano Zampini     PetscInt  nvecs = 0;
601457de7509SStefano Zampini     PetscBool reuse,reuser;
60151ae86dd6SStefano Zampini 
601657de7509SStefano Zampini     if (coarse_mat) reuse = PETSC_TRUE;
601757de7509SStefano Zampini     else reuse = PETSC_FALSE;
601857de7509SStefano Zampini     ierr = MPIU_Allreduce(&reuse,&reuser,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
60191ae86dd6SStefano Zampini     vp[0] = NULL;
60201ae86dd6SStefano Zampini     if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */
60211ae86dd6SStefano Zampini       ierr = VecCreate(PetscObjectComm((PetscObject)pc),&vp[0]);CHKERRQ(ierr);
60221ae86dd6SStefano Zampini       ierr = VecSetSizes(vp[0],pcbddc->local_primal_size,PETSC_DECIDE);CHKERRQ(ierr);
60231ae86dd6SStefano Zampini       ierr = VecSetType(vp[0],VECSTANDARD);CHKERRQ(ierr);
60241ae86dd6SStefano Zampini       nvecs = 1;
60251ae86dd6SStefano Zampini 
60261ae86dd6SStefano Zampini       if (pcbddc->divudotp) {
6027a198735bSStefano Zampini         Mat      B,loc_divudotp;
60281ae86dd6SStefano Zampini         Vec      v,p;
60291ae86dd6SStefano Zampini         IS       dummy;
60301ae86dd6SStefano Zampini         PetscInt np;
60311ae86dd6SStefano Zampini 
6032a198735bSStefano Zampini         ierr = MatISGetLocalMat(pcbddc->divudotp,&loc_divudotp);CHKERRQ(ierr);
6033a198735bSStefano Zampini         ierr = MatGetSize(loc_divudotp,&np,NULL);CHKERRQ(ierr);
60341ae86dd6SStefano Zampini         ierr = ISCreateStride(PETSC_COMM_SELF,np,0,1,&dummy);CHKERRQ(ierr);
6035a198735bSStefano Zampini         ierr = MatGetSubMatrix(loc_divudotp,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
60361ae86dd6SStefano Zampini         ierr = MatCreateVecs(B,&v,&p);CHKERRQ(ierr);
60371ae86dd6SStefano Zampini         ierr = VecSet(p,1.);CHKERRQ(ierr);
60381ae86dd6SStefano Zampini         ierr = MatMultTranspose(B,p,v);CHKERRQ(ierr);
60391ae86dd6SStefano Zampini         ierr = VecDestroy(&p);CHKERRQ(ierr);
60401ae86dd6SStefano Zampini         ierr = MatDestroy(&B);CHKERRQ(ierr);
60411ae86dd6SStefano Zampini         ierr = VecGetArray(vp[0],&array);CHKERRQ(ierr);
60421ae86dd6SStefano Zampini         ierr = VecPlaceArray(pcbddc->vec1_P,array);CHKERRQ(ierr);
60431ae86dd6SStefano Zampini         ierr = VecRestoreArray(vp[0],&array);CHKERRQ(ierr);
60441ae86dd6SStefano Zampini         ierr = MatMultTranspose(pcbddc->coarse_phi_B,v,pcbddc->vec1_P);CHKERRQ(ierr);
60451ae86dd6SStefano Zampini         ierr = VecResetArray(pcbddc->vec1_P);CHKERRQ(ierr);
60461ae86dd6SStefano Zampini         ierr = ISDestroy(&dummy);CHKERRQ(ierr);
60471ae86dd6SStefano Zampini         ierr = VecDestroy(&v);CHKERRQ(ierr);
604874e2c79eSStefano Zampini       }
60491ae86dd6SStefano Zampini     }
60501ae86dd6SStefano Zampini     if (reuser) {
60511ae86dd6SStefano Zampini       ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling,0,restr,full_restr,PETSC_TRUE,&coarse_mat,nis,isarray,nvecs,vp);CHKERRQ(ierr);
605274e2c79eSStefano Zampini     } else {
60531ae86dd6SStefano 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);
60541ae86dd6SStefano Zampini     }
60551ae86dd6SStefano Zampini     if (vp[0]) { /* vp[0] could have been placed on a different set of processes */
60561ae86dd6SStefano Zampini       PetscScalar *arraym,*arrayv;
60571ae86dd6SStefano Zampini       PetscInt    nl;
60581ae86dd6SStefano Zampini       ierr = VecGetLocalSize(vp[0],&nl);CHKERRQ(ierr);
60591ae86dd6SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,1,nl,NULL,&coarsedivudotp);CHKERRQ(ierr);
60601ae86dd6SStefano Zampini       ierr = MatDenseGetArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
60611ae86dd6SStefano Zampini       ierr = VecGetArray(vp[0],&arrayv);CHKERRQ(ierr);
60621ae86dd6SStefano Zampini       ierr = PetscMemcpy(arraym,arrayv,nl*sizeof(PetscScalar));CHKERRQ(ierr);
60631ae86dd6SStefano Zampini       ierr = VecRestoreArray(vp[0],&arrayv);CHKERRQ(ierr);
60641ae86dd6SStefano Zampini       ierr = MatDenseRestoreArray(coarsedivudotp,&arraym);CHKERRQ(ierr);
60651ae86dd6SStefano Zampini       ierr = VecDestroy(&vp[0]);CHKERRQ(ierr);
6066a198735bSStefano Zampini     } else {
6067a198735bSStefano Zampini       ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,0,0,1,NULL,&coarsedivudotp);CHKERRQ(ierr);
60681ae86dd6SStefano Zampini     }
60691ae86dd6SStefano Zampini   } else {
60701ae86dd6SStefano 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);
60716e683305SStefano Zampini   }
607257de7509SStefano Zampini   if (coarse_mat_is || coarse_mat) {
607357de7509SStefano Zampini     PetscMPIInt size;
607457de7509SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)coarse_mat_is),&size);
607557de7509SStefano Zampini     if (!multilevel_allowed) {
607657de7509SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
60776e683305SStefano Zampini     } else {
607857de7509SStefano Zampini       Mat A;
6079779c1cceSStefano Zampini 
608057de7509SStefano Zampini       /* if this matrix is present, it means we are not reusing the coarse matrix */
608157de7509SStefano Zampini       if (coarse_mat_is) {
608257de7509SStefano Zampini         if (coarse_mat) SETERRQ(PetscObjectComm((PetscObject)coarse_mat_is),PETSC_ERR_PLIB,"This should not happen");
608357de7509SStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
608457de7509SStefano Zampini         coarse_mat = coarse_mat_is;
608557de7509SStefano Zampini       }
608657de7509SStefano Zampini       /* be sure we don't have MatSeqDENSE as local mat */
608757de7509SStefano Zampini       ierr = MatISGetLocalMat(coarse_mat,&A);CHKERRQ(ierr);
608857de7509SStefano Zampini       ierr = MatConvert(A,MATSEQAIJ,MAT_INPLACE_MATRIX,&A);CHKERRQ(ierr);
6089779c1cceSStefano Zampini     }
6090779c1cceSStefano Zampini   }
609157de7509SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
609257de7509SStefano Zampini   ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
60936e683305SStefano Zampini 
60946e683305SStefano Zampini   /* create local to global scatters for coarse problem */
609568457ee5SStefano Zampini   if (compute_vecs) {
60966e683305SStefano Zampini     PetscInt lrows;
60976e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
609857de7509SStefano Zampini     if (coarse_mat) {
609957de7509SStefano Zampini       ierr = MatGetLocalSize(coarse_mat,&lrows,NULL);CHKERRQ(ierr);
61006e683305SStefano Zampini     } else {
61016e683305SStefano Zampini       lrows = 0;
61026e683305SStefano Zampini     }
61036e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
61046e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
61056e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
61066e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
61076e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
61086e683305SStefano Zampini   }
61096e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
6110c8587f34SStefano Zampini 
6111f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
6112f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
6113f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
6114f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
6115f9eb5b7dSStefano Zampini   } else {
6116f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
6117f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
6118c8587f34SStefano Zampini   }
6119c8587f34SStefano Zampini 
61206e683305SStefano Zampini   /* print some info if requested */
61216e683305SStefano Zampini   if (pcbddc->dbg_flag) {
61226e683305SStefano Zampini     if (!multilevel_allowed) {
61236e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
61246e683305SStefano Zampini       if (multilevel_requested) {
61256e683305SStefano 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);
61266e683305SStefano Zampini       } else if (pcbddc->max_levels) {
61276e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
61286e683305SStefano Zampini       }
61296e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
61306e683305SStefano Zampini     }
61316e683305SStefano Zampini   }
61326e683305SStefano Zampini 
6133f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
613457de7509SStefano Zampini   if (coarse_mat) {
61356a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
61366e683305SStefano Zampini     if (pcbddc->dbg_flag) {
613757de7509SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
61386e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
61396e683305SStefano Zampini     }
6140f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
6141312be037SStefano Zampini       char prefix[256],str_level[16];
6142e604994aSStefano Zampini       size_t len;
614357de7509SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat),&pcbddc->coarse_ksp);CHKERRQ(ierr);
6144422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
6145c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
6146f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
614757de7509SStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
6148c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
61496e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
6150c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
6151c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
6152e604994aSStefano Zampini       /* prefix */
6153e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
6154e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
6155e604994aSStefano Zampini       if (!pcbddc->current_level) {
6156e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
6157e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
6158c8587f34SStefano Zampini       } else {
6159e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
6160312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
6161312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
616234d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
6163312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
6164e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
6165e604994aSStefano Zampini       }
6166e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
61673e3c6dadSStefano Zampini       /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
61683e3c6dadSStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
61693e3c6dadSStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
61703e3c6dadSStefano Zampini       ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
6171f9eb5b7dSStefano Zampini       /* allow user customization */
6172f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
61733e3c6dadSStefano Zampini     }
61743e3c6dadSStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
617551bea450SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
61763e3c6dadSStefano Zampini     if (nisdofs) {
61773e3c6dadSStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
61783e3c6dadSStefano Zampini       for (i=0;i<nisdofs;i++) {
61793e3c6dadSStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
61803e3c6dadSStefano Zampini       }
61813e3c6dadSStefano Zampini     }
61823e3c6dadSStefano Zampini     if (nisneu) {
61833e3c6dadSStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
61843e3c6dadSStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
6185312be037SStefano Zampini     }
618630368db7SStefano Zampini     if (nisvert) {
618730368db7SStefano Zampini       ierr = PCBDDCSetPrimalVerticesIS(pc_temp,isarray[nis-1]);CHKERRQ(ierr);
618830368db7SStefano Zampini       ierr = ISDestroy(&isarray[nis-1]);CHKERRQ(ierr);
618930368db7SStefano Zampini     }
6190f9eb5b7dSStefano Zampini 
6191f9eb5b7dSStefano Zampini     /* get some info after set from options */
6192f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
6193f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
61944f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
61956e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
6196f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
6197f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
6198f9eb5b7dSStefano Zampini     }
619939f0f02cSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
62004f3a063dSStefano Zampini     if (isredundant) {
62014f3a063dSStefano Zampini       KSP inner_ksp;
62024f3a063dSStefano Zampini       PC  inner_pc;
62034f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
62044f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
62054f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
62064f3a063dSStefano Zampini     }
6207f9eb5b7dSStefano Zampini 
620857de7509SStefano Zampini     /* parameters which miss an API */
620957de7509SStefano Zampini     if (isbddc) {
6210720d30f9SStefano Zampini       PC_BDDC* pcbddc_coarse = (PC_BDDC*)pc_temp->data;
6211720d30f9SStefano Zampini       pcbddc_coarse->detect_disconnected = PETSC_TRUE;
621257de7509SStefano Zampini       pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc;
621327b6a85dSStefano Zampini       pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null;
621427b6a85dSStefano Zampini       if (pcbddc_coarse->benign_saddle_point) {
6215a198735bSStefano Zampini         Mat                    coarsedivudotp_is;
6216a198735bSStefano Zampini         ISLocalToGlobalMapping l2gmap,rl2g,cl2g;
6217a198735bSStefano Zampini         IS                     row,col;
6218a198735bSStefano Zampini         const PetscInt         *gidxs;
6219a198735bSStefano Zampini         PetscInt               n,st,M,N;
6220a198735bSStefano Zampini 
6221a198735bSStefano Zampini         ierr = MatGetSize(coarsedivudotp,&n,NULL);CHKERRQ(ierr);
6222a198735bSStefano Zampini         ierr = MPI_Scan(&n,&st,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)coarse_mat));CHKERRQ(ierr);
6223a198735bSStefano Zampini         st = st-n;
6224a198735bSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)coarse_mat),1,st,1,&row);CHKERRQ(ierr);
6225a198735bSStefano Zampini         ierr = MatGetLocalToGlobalMapping(coarse_mat,&l2gmap,NULL);CHKERRQ(ierr);
6226a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(l2gmap,&n);CHKERRQ(ierr);
6227a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(l2gmap,&gidxs);CHKERRQ(ierr);
6228a198735bSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat),n,gidxs,PETSC_COPY_VALUES,&col);CHKERRQ(ierr);
6229a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(l2gmap,&gidxs);CHKERRQ(ierr);
6230a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(row,&rl2g);CHKERRQ(ierr);
6231a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingCreateIS(col,&cl2g);CHKERRQ(ierr);
6232a198735bSStefano Zampini         ierr = ISGetSize(row,&M);CHKERRQ(ierr);
6233a198735bSStefano Zampini         ierr = MatGetSize(coarse_mat,&N,NULL);CHKERRQ(ierr);
6234a198735bSStefano Zampini         ierr = ISDestroy(&row);CHKERRQ(ierr);
6235a198735bSStefano Zampini         ierr = ISDestroy(&col);CHKERRQ(ierr);
6236a198735bSStefano Zampini         ierr = MatCreate(PetscObjectComm((PetscObject)coarse_mat),&coarsedivudotp_is);CHKERRQ(ierr);
6237a198735bSStefano Zampini         ierr = MatSetType(coarsedivudotp_is,MATIS);CHKERRQ(ierr);
6238a198735bSStefano Zampini         ierr = MatSetSizes(coarsedivudotp_is,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
6239a198735bSStefano Zampini         ierr = MatSetLocalToGlobalMapping(coarsedivudotp_is,rl2g,cl2g);CHKERRQ(ierr);
6240a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
6241a198735bSStefano Zampini         ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
6242a198735bSStefano Zampini         ierr = MatISSetLocalMat(coarsedivudotp_is,coarsedivudotp);CHKERRQ(ierr);
6243a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
6244a198735bSStefano Zampini         ierr = PCBDDCSetDivergenceMat(pc_temp,coarsedivudotp_is,NULL);CHKERRQ(ierr);
6245a198735bSStefano Zampini         ierr = MatDestroy(&coarsedivudotp_is);CHKERRQ(ierr);
6246720d30f9SStefano Zampini         pcbddc_coarse->adaptive_userdefined = PETSC_TRUE;
624759e48ca4SStefano Zampini         if (pcbddc->adaptive_threshold < 1.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE;
6248720d30f9SStefano Zampini       }
6249d4d8cf7bSStefano Zampini     }
62509881197aSStefano Zampini 
62513301b35fSStefano Zampini     /* propagate symmetry info of coarse matrix */
62525a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
62533301b35fSStefano Zampini     if (pc->pmat->symmetric_set) {
62543301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pc->pmat->symmetric);CHKERRQ(ierr);
62553301b35fSStefano Zampini     }
62563301b35fSStefano Zampini     if (pc->pmat->hermitian_set) {
62573301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_HERMITIAN,pc->pmat->hermitian);CHKERRQ(ierr);
62583301b35fSStefano Zampini     }
62593301b35fSStefano Zampini     if (pc->pmat->spd_set) {
62603301b35fSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,pc->pmat->spd);CHKERRQ(ierr);
62613301b35fSStefano Zampini     }
626227b6a85dSStefano Zampini     if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) {
626327b6a85dSStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SPD,PETSC_TRUE);CHKERRQ(ierr);
626427b6a85dSStefano Zampini     }
62656e683305SStefano Zampini     /* set operators */
62665f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
62676e683305SStefano Zampini     if (pcbddc->dbg_flag) {
62686e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
62696e683305SStefano Zampini     }
62706e683305SStefano Zampini   }
62716e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
6272b1ecc7b1SStefano Zampini #if 0
6273b9b85e73SStefano Zampini   {
6274b9b85e73SStefano Zampini     PetscViewer viewer;
6275b9b85e73SStefano Zampini     char filename[256];
6276b1ecc7b1SStefano Zampini     sprintf(filename,"coarse_mat_level%d.m",pcbddc->current_level);
6277b1ecc7b1SStefano Zampini     ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer);CHKERRQ(ierr);
62786a9046bcSBarry Smith     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
6279b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
6280f159cad9SBarry Smith     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
6281b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
6282b9b85e73SStefano Zampini   }
6283b9b85e73SStefano Zampini #endif
6284f9eb5b7dSStefano Zampini 
628598a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
628698a51de6SStefano Zampini     Vec crhs,csol;
628704708bb6SStefano Zampini 
6288f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
6289f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
6290f347579bSStefano Zampini     if (!csol) {
62912a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
6292f9eb5b7dSStefano Zampini     }
6293f347579bSStefano Zampini     if (!crhs) {
62942a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
6295f347579bSStefano Zampini     }
6296b0f5fe93SStefano Zampini   }
62971ae86dd6SStefano Zampini   ierr = MatDestroy(&coarsedivudotp);CHKERRQ(ierr);
6298b0f5fe93SStefano Zampini 
6299b0f5fe93SStefano Zampini   /* compute null space for coarse solver if the benign trick has been requested */
6300b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
6301b0f5fe93SStefano Zampini 
6302b0f5fe93SStefano Zampini     ierr = VecSet(pcbddc->vec1_P,0.);CHKERRQ(ierr);
63034f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
63044f1b2e48SStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,pcbddc->local_primal_size-pcbddc->benign_n+i,1.0,INSERT_VALUES);CHKERRQ(ierr);
63054f1b2e48SStefano Zampini     }
6306b0f5fe93SStefano Zampini     ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
6307b0f5fe93SStefano Zampini     ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
6308b0f5fe93SStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6309b0f5fe93SStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6310b0f5fe93SStefano Zampini     if (coarse_mat) {
6311b0f5fe93SStefano Zampini       Vec         nullv;
6312b0f5fe93SStefano Zampini       PetscScalar *array,*array2;
6313b0f5fe93SStefano Zampini       PetscInt    nl;
6314b0f5fe93SStefano Zampini 
6315b0f5fe93SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&nullv,NULL);CHKERRQ(ierr);
6316b0f5fe93SStefano Zampini       ierr = VecGetLocalSize(nullv,&nl);CHKERRQ(ierr);
6317b0f5fe93SStefano Zampini       ierr = VecGetArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
6318b0f5fe93SStefano Zampini       ierr = VecGetArray(nullv,&array2);CHKERRQ(ierr);
6319b0f5fe93SStefano Zampini       ierr = PetscMemcpy(array2,array,nl*sizeof(*array));CHKERRQ(ierr);
6320b0f5fe93SStefano Zampini       ierr = VecRestoreArray(nullv,&array2);CHKERRQ(ierr);
6321b0f5fe93SStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,(const PetscScalar**)&array);CHKERRQ(ierr);
6322b0f5fe93SStefano Zampini       ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
6323b0f5fe93SStefano Zampini       ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,1,&nullv,&CoarseNullSpace);CHKERRQ(ierr);
6324b0f5fe93SStefano Zampini       ierr = VecDestroy(&nullv);CHKERRQ(ierr);
6325b0f5fe93SStefano Zampini     }
6326b0f5fe93SStefano Zampini   }
6327b0f5fe93SStefano Zampini 
6328b0f5fe93SStefano Zampini   if (pcbddc->coarse_ksp) {
6329b0f5fe93SStefano Zampini     PetscBool ispreonly;
6330b0f5fe93SStefano Zampini 
6331b0f5fe93SStefano Zampini     if (CoarseNullSpace) {
6332b0f5fe93SStefano Zampini       PetscBool isnull;
6333b0f5fe93SStefano Zampini       ierr = MatNullSpaceTest(CoarseNullSpace,coarse_mat,&isnull);CHKERRQ(ierr);
6334bef83e63SStefano Zampini       if (isnull) {
6335b0f5fe93SStefano Zampini         ierr = MatSetNullSpace(coarse_mat,CoarseNullSpace);CHKERRQ(ierr);
6336b0f5fe93SStefano Zampini       }
6337bef83e63SStefano Zampini       /* TODO: add local nullspaces (if any) */
6338b0f5fe93SStefano Zampini     }
6339b0f5fe93SStefano Zampini     /* setup coarse ksp */
6340b0f5fe93SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
6341cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
6342cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
63436e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
6344c8587f34SStefano Zampini       KSP       check_ksp;
63452b510759SStefano Zampini       KSPType   check_ksp_type;
6346c8587f34SStefano Zampini       PC        check_pc;
63476e683305SStefano Zampini       Vec       check_vec,coarse_vec;
63486a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
63492b510759SStefano Zampini       PetscInt  its;
63506e683305SStefano Zampini       PetscBool compute_eigs;
63516e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
63526e683305SStefano Zampini       PetscInt  neigs;
63538e185a42SStefano Zampini       const char *prefix;
6354c8587f34SStefano Zampini 
63552b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
63566e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
6357422a814eSBarry Smith       ierr = KSPSetErrorIfNotConverged(pcbddc->coarse_ksp,pc->erroriffailure);CHKERRQ(ierr);
635823ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
6359f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
6360e4d548c7SStefano Zampini       /* prevent from setup unneeded object */
6361e4d548c7SStefano Zampini       ierr = KSPGetPC(check_ksp,&check_pc);CHKERRQ(ierr);
6362e4d548c7SStefano Zampini       ierr = PCSetType(check_pc,PCNONE);CHKERRQ(ierr);
63632b510759SStefano Zampini       if (ispreonly) {
63642b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
63656e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
63662b510759SStefano Zampini       } else {
6367cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
63686e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
6369c8587f34SStefano Zampini       }
6370c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
63716e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
63726e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
63736e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
6374a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
6375a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
6376a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
6377a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
6378c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
6379c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
6380c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
6381c8587f34SStefano Zampini       /* create random vec */
63822701bc32SStefano Zampini       ierr = MatCreateVecs(coarse_mat,&coarse_vec,&check_vec);CHKERRQ(ierr);
6383c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
63846e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
6385c8587f34SStefano Zampini       /* solve coarse problem */
63866e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
6387cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
63886e683305SStefano Zampini       if (compute_eigs) {
6389854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
6390854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
63916e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
63921ae86dd6SStefano Zampini         if (neigs) {
63936e683305SStefano Zampini           lambda_max = eigs_r[neigs-1];
63946e683305SStefano Zampini           lambda_min = eigs_r[0];
63956e683305SStefano Zampini           if (pcbddc->use_coarse_estimates) {
63962701bc32SStefano Zampini             if (lambda_max>=lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */
63972701bc32SStefano Zampini               ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max+PETSC_SMALL,lambda_min);CHKERRQ(ierr);
6398cbcc2c2aSStefano Zampini               ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
6399cbcc2c2aSStefano Zampini             }
6400c8587f34SStefano Zampini           }
6401c8587f34SStefano Zampini         }
64021ae86dd6SStefano Zampini       }
6403cbcc2c2aSStefano Zampini 
6404c8587f34SStefano Zampini       /* check coarse problem residual error */
64056e683305SStefano Zampini       if (pcbddc->dbg_flag) {
64066e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
64076e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
64086e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
6409c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
64106e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
64116e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
6412779c1cceSStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (use estimates %d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
64136e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
64146e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
64156e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
64166e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
6417b0f5fe93SStefano Zampini         if (CoarseNullSpace) {
6418b0f5fe93SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem is singular\n");CHKERRQ(ierr);
6419b0f5fe93SStefano Zampini         }
64206e683305SStefano Zampini         if (compute_eigs) {
64216e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
6422deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
6423c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
64246e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
64256e683305SStefano 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);
64266e683305SStefano Zampini           for (i=0;i<neigs;i++) {
64276e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
6428c8587f34SStefano Zampini           }
64296e683305SStefano Zampini         }
64306e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
64316e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
64326e683305SStefano Zampini       }
6433e4d548c7SStefano Zampini       ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
64342701bc32SStefano Zampini       ierr = VecDestroy(&coarse_vec);CHKERRQ(ierr);
6435c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
64366e683305SStefano Zampini       if (compute_eigs) {
64376e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
64386e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
6439c8587f34SStefano Zampini       }
64406e683305SStefano Zampini     }
64416e683305SStefano Zampini   }
6442bef83e63SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
6443cbcc2c2aSStefano Zampini   /* print additional info */
6444cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
64456e683305SStefano Zampini     /* waits until all processes reaches this point */
64466e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
6447cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
6448cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6449cbcc2c2aSStefano Zampini   }
6450cbcc2c2aSStefano Zampini 
64512b510759SStefano Zampini   /* free memory */
6452fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
6453c8587f34SStefano Zampini   PetscFunctionReturn(0);
6454c8587f34SStefano Zampini }
6455674ae819SStefano Zampini 
6456f34684f1SStefano Zampini #undef __FUNCT__
6457f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
6458f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
6459f34684f1SStefano Zampini {
6460f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
6461f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
6462f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
6463dc456d91SStefano Zampini   IS             subset,subset_mult,subset_n;
6464dc456d91SStefano Zampini   PetscInt       local_size,coarse_size=0;
646573be2a3aSStefano Zampini   PetscInt       *local_primal_indices=NULL;
6466dc456d91SStefano Zampini   const PetscInt *t_local_primal_indices;
6467f34684f1SStefano Zampini   PetscErrorCode ierr;
6468f34684f1SStefano Zampini 
6469f34684f1SStefano Zampini   PetscFunctionBegin;
6470f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
64716c4ed002SBarry Smith   if (pcbddc->local_primal_size && !pcbddc->local_primal_ref_node) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"BDDC ConstraintsSetUp should be called first");
6472dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_node,PETSC_COPY_VALUES,&subset_n);CHKERRQ(ierr);
64733bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(pcis->mapping,subset_n,&subset);CHKERRQ(ierr);
6474dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
6475dc456d91SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)),pcbddc->local_primal_size_cc,pcbddc->local_primal_ref_mult,PETSC_COPY_VALUES,&subset_mult);CHKERRQ(ierr);
6476dc456d91SStefano Zampini   ierr = PCBDDCSubsetNumbering(subset,subset_mult,&coarse_size,&subset_n);CHKERRQ(ierr);
6477dc456d91SStefano Zampini   ierr = ISDestroy(&subset);CHKERRQ(ierr);
6478dc456d91SStefano Zampini   ierr = ISDestroy(&subset_mult);CHKERRQ(ierr);
6479dc456d91SStefano Zampini   ierr = ISGetLocalSize(subset_n,&local_size);CHKERRQ(ierr);
64806c4ed002SBarry 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);
6481dc456d91SStefano Zampini   ierr = PetscMalloc1(local_size,&local_primal_indices);CHKERRQ(ierr);
6482dc456d91SStefano Zampini   ierr = ISGetIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
6483dc456d91SStefano Zampini   ierr = PetscMemcpy(local_primal_indices,t_local_primal_indices,local_size*sizeof(PetscInt));CHKERRQ(ierr);
6484dc456d91SStefano Zampini   ierr = ISRestoreIndices(subset_n,&t_local_primal_indices);CHKERRQ(ierr);
6485dc456d91SStefano Zampini   ierr = ISDestroy(&subset_n);CHKERRQ(ierr);
6486f34684f1SStefano Zampini 
6487f34684f1SStefano Zampini   /* check numbering */
6488f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
6489019a44ceSStefano Zampini     PetscScalar coarsesum,*array,*array2;
6490dc456d91SStefano Zampini     PetscInt    i;
6491b9b85e73SStefano Zampini     PetscBool   set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
6492f34684f1SStefano Zampini 
6493f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6494f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
6495f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
64961575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6497019a44ceSStefano Zampini     /* counter */
6498019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6499019a44ceSStefano Zampini     ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
6500019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6501019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6502019a44ceSStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6503019a44ceSStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6504f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
6505f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
6506727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
6507f34684f1SStefano Zampini     }
6508f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6509f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6510f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6511e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6512e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6513e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6514e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6515f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6516019a44ceSStefano Zampini     ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
6517f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
6518019a44ceSStefano Zampini       if (array[i] != 0.0 && array[i] != array2[i]) {
65192c66d082SStefano Zampini         PetscInt owned = (PetscInt)PetscRealPart(array[i]),gi;
652075c01103SStefano Zampini         PetscInt neigh = (PetscInt)PetscRealPart(array2[i]);
6521b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
65222c66d082SStefano Zampini         ierr = ISLocalToGlobalMappingApply(pcis->mapping,1,&i,&gi);CHKERRQ(ierr);
65232c66d082SStefano 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);
6524f34684f1SStefano Zampini       }
6525f34684f1SStefano Zampini     }
6526019a44ceSStefano Zampini     ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
6527b2566f29SBarry Smith     ierr = MPIU_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
6528f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6529f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
6530f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
6531f34684f1SStefano Zampini     }
6532f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6533f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
6534e176bc59SStefano Zampini     ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6535e176bc59SStefano Zampini     ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6536f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
6537f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
6538b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
6539ca8b9ea9SStefano Zampini       PetscInt *gidxs;
6540ca8b9ea9SStefano Zampini 
6541ca8b9ea9SStefano Zampini       ierr = PetscMalloc1(pcbddc->local_primal_size,&gidxs);CHKERRQ(ierr);
65423bbff08aSStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,gidxs);CHKERRQ(ierr);
6543f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
6544f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6545f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
6546f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
65474bc2dc4bSStefano 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);
6548f34684f1SStefano Zampini       }
6549f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6550ca8b9ea9SStefano Zampini       ierr = PetscFree(gidxs);CHKERRQ(ierr);
6551f34684f1SStefano Zampini     }
6552f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
65531575c14dSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6554302440fdSBarry Smith     if (set_error_reduced) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
6555f34684f1SStefano Zampini   }
65568bec7fa6SStefano Zampini   /* ierr = PetscPrintf(PetscObjectComm((PetscObject)pc),"Size of coarse problem is %d\n",coarse_size);CHKERRQ(ierr); */
6557f34684f1SStefano Zampini   /* get back data */
6558f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
6559f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
6560674ae819SStefano Zampini   PetscFunctionReturn(0);
6561674ae819SStefano Zampini }
6562674ae819SStefano Zampini 
6563e456f2a8SStefano Zampini #undef __FUNCT__
6564e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
6565a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
6566e456f2a8SStefano Zampini {
6567e456f2a8SStefano Zampini   IS             localis_t;
6568a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
6569e456f2a8SStefano Zampini   PetscScalar    *vals;
6570e456f2a8SStefano Zampini   PetscErrorCode ierr;
6571e456f2a8SStefano Zampini 
6572e456f2a8SStefano Zampini   PetscFunctionBegin;
6573a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
6574e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
6575854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
6576e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
6577e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
6578a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
6579a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
65801035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
6581a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
65821035eff8SStefano Zampini   }
6583a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
6584e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
6585e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
6586a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
6587a7dc3881SStefano Zampini   /* now compute set in local ordering */
6588a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6589a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6590a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
6591a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
6592a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
6593ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
6594e456f2a8SStefano Zampini       lsize++;
6595e456f2a8SStefano Zampini     }
6596e456f2a8SStefano Zampini   }
6597854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
6598a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
6599ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
6600e456f2a8SStefano Zampini       idxs[lsize++] = i;
6601e456f2a8SStefano Zampini     }
6602e456f2a8SStefano Zampini   }
6603a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
6604a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
6605e456f2a8SStefano Zampini   *localis = localis_t;
6606e456f2a8SStefano Zampini   PetscFunctionReturn(0);
6607e456f2a8SStefano Zampini }
6608906d46d4SStefano Zampini 
6609b96c3477SStefano Zampini #undef __FUNCT__
6610b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
661108122e43SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc)
6612b96c3477SStefano Zampini {
6613a64f4aa4SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6614b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6615b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
6616a64f4aa4SStefano Zampini   Mat                 S_j;
6617b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
6618b96c3477SStefano Zampini   PetscBool           free_used_adj;
6619b96c3477SStefano Zampini   PetscErrorCode      ierr;
6620b96c3477SStefano Zampini 
6621b96c3477SStefano Zampini   PetscFunctionBegin;
6622b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
6623b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
662408122e43SStefano Zampini   if (pcbddc->sub_schurs_layers == -1) {
6625b96c3477SStefano Zampini     used_xadj = NULL;
6626b96c3477SStefano Zampini     used_adjncy = NULL;
6627b96c3477SStefano Zampini   } else {
662808122e43SStefano Zampini     if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) {
662908122e43SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
663008122e43SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
663108122e43SStefano Zampini     } else if (pcbddc->computed_rowadj) {
6632b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
6633b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
6634b96c3477SStefano Zampini     } else {
66352fffb893SStefano Zampini       PetscBool      flg_row=PETSC_FALSE;
6636b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
6637b96c3477SStefano Zampini       PetscInt       nvtxs;
6638b96c3477SStefano Zampini 
66392fffb893SStefano Zampini       ierr = MatGetRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
66402fffb893SStefano Zampini       if (flg_row) {
6641b96c3477SStefano Zampini         ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
6642b96c3477SStefano Zampini         ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
6643b96c3477SStefano Zampini         ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
6644b96c3477SStefano Zampini         free_used_adj = PETSC_TRUE;
66452fffb893SStefano Zampini       } else {
66462fffb893SStefano Zampini         pcbddc->sub_schurs_layers = -1;
66472fffb893SStefano Zampini         used_xadj = NULL;
66482fffb893SStefano Zampini         used_adjncy = NULL;
66492fffb893SStefano Zampini       }
66502fffb893SStefano Zampini       ierr = MatRestoreRowIJ(pcbddc->local_mat,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
6651b96c3477SStefano Zampini     }
6652b96c3477SStefano Zampini   }
6653d5574798SStefano Zampini 
6654d5574798SStefano Zampini   /* setup sub_schurs data */
6655a64f4aa4SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
6656df4d28bfSStefano Zampini   if (!sub_schurs->schur_explicit) {
6657df4d28bfSStefano Zampini     /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */
6658a64f4aa4SStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
665991af6908SStefano 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);
6660a64f4aa4SStefano Zampini   } else {
66616816873aSStefano Zampini     PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis;
6662b7ab4a40SStefano Zampini     PetscBool isseqaij,need_change = PETSC_FALSE;;
6663a3df083aSStefano Zampini     PetscInt  benign_n;
666472b8c272SStefano Zampini     Mat       change = NULL;
66659d54b7f4SStefano Zampini     Vec       scaling = NULL;
666672b8c272SStefano Zampini     IS        change_primal = NULL;
6667a3df083aSStefano Zampini 
66685feab87aSStefano Zampini     if (!pcbddc->use_vertices && reuse_solvers) {
66695feab87aSStefano Zampini       PetscInt n_vertices;
66705feab87aSStefano Zampini 
66715feab87aSStefano Zampini       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_vertices);CHKERRQ(ierr);
66722034aafcSStefano Zampini       reuse_solvers = (PetscBool)!n_vertices;
66735feab87aSStefano Zampini     }
667404708bb6SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
667504708bb6SStefano Zampini     if (!isseqaij) {
667604708bb6SStefano Zampini       Mat_IS* matis = (Mat_IS*)pc->pmat->data;
667704708bb6SStefano Zampini       if (matis->A == pcbddc->local_mat) {
667804708bb6SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
667904708bb6SStefano Zampini         ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
668004708bb6SStefano Zampini       } else {
6681511c6705SHong Zhang         ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INPLACE_MATRIX,&pcbddc->local_mat);CHKERRQ(ierr);
668204708bb6SStefano Zampini       }
668304708bb6SStefano Zampini     }
6684a3df083aSStefano Zampini     if (!pcbddc->benign_change_explicit) {
6685a3df083aSStefano Zampini       benign_n = pcbddc->benign_n;
6686ca92afb2SStefano Zampini     } else {
6687a3df083aSStefano Zampini       benign_n = 0;
6688ca92afb2SStefano Zampini     }
6689b7ab4a40SStefano Zampini     /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc.
6690b7ab4a40SStefano Zampini        We need a global reduction to avoid possible deadlocks.
6691b7ab4a40SStefano Zampini        We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */
669272b8c272SStefano Zampini     if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) {
669322db5ddcSStefano Zampini       PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change);
6694b7ab4a40SStefano Zampini       ierr = MPIU_Allreduce(&have_loc_change,&need_change,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
669522db5ddcSStefano Zampini       need_change = (PetscBool)(!need_change);
6696b7ab4a40SStefano Zampini     }
6697b7ab4a40SStefano Zampini     /* If the user defines additional constraints, we import them here.
6698b7ab4a40SStefano 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 */
6699b7ab4a40SStefano Zampini     if (need_change) {
670088c03ad3SStefano Zampini       PC_IS   *pcisf;
670188c03ad3SStefano Zampini       PC_BDDC *pcbddcf;
670288c03ad3SStefano Zampini       PC      pcf;
670388c03ad3SStefano Zampini 
6704e4d548c7SStefano Zampini       if (pcbddc->sub_schurs_rebuild) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot compute change of basis with a different graph");
670588c03ad3SStefano Zampini       ierr = PCCreate(PetscObjectComm((PetscObject)pc),&pcf);CHKERRQ(ierr);
670688c03ad3SStefano Zampini       ierr = PCSetOperators(pcf,pc->mat,pc->pmat);CHKERRQ(ierr);
670788c03ad3SStefano Zampini       ierr = PCSetType(pcf,PCBDDC);CHKERRQ(ierr);
670888c03ad3SStefano Zampini       /* hacks */
670988c03ad3SStefano Zampini       pcisf = (PC_IS*)pcf->data;
671072b8c272SStefano Zampini       pcisf->is_B_local = pcis->is_B_local;
671172b8c272SStefano Zampini       pcisf->vec1_N = pcis->vec1_N;
671272b8c272SStefano Zampini       pcisf->BtoNmap = pcis->BtoNmap;
671372b8c272SStefano Zampini       pcisf->n = pcis->n;
671472b8c272SStefano Zampini       pcisf->n_B = pcis->n_B;
671588c03ad3SStefano Zampini       pcbddcf = (PC_BDDC*)pcf->data;
671688c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->mat_graph);CHKERRQ(ierr);
671788c03ad3SStefano Zampini       pcbddcf->mat_graph = pcbddc->mat_graph;
671888c03ad3SStefano Zampini       pcbddcf->use_faces = PETSC_TRUE;
671988c03ad3SStefano Zampini       pcbddcf->use_change_of_basis = PETSC_TRUE;
672088c03ad3SStefano Zampini       pcbddcf->use_change_on_faces = PETSC_TRUE;
672172b8c272SStefano Zampini       pcbddcf->use_qr_single = PETSC_TRUE;
672288c03ad3SStefano Zampini       pcbddcf->fake_change = PETSC_TRUE;
672388c03ad3SStefano Zampini       ierr = PCBDDCConstraintsSetUp(pcf);CHKERRQ(ierr);
672472b8c272SStefano Zampini       /* store information on primal vertices and change of basis (in local numbering) */
672572b8c272SStefano Zampini       sub_schurs->change_with_qr = pcbddcf->use_qr_single;
672672b8c272SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddcf->n_vertices,pcbddcf->local_primal_ref_node,PETSC_COPY_VALUES,&change_primal);CHKERRQ(ierr);
672772b8c272SStefano Zampini       change = pcbddcf->ConstraintMatrix;
672872b8c272SStefano Zampini       pcbddcf->ConstraintMatrix = NULL;
672988c03ad3SStefano Zampini       /* free unneeded memory allocated in PCBDDCConstraintsSetUp */
673072b8c272SStefano Zampini       ierr = PetscFree(pcbddcf->sub_schurs);CHKERRQ(ierr);
673188c03ad3SStefano Zampini       ierr = MatNullSpaceDestroy(&pcbddcf->onearnullspace);CHKERRQ(ierr);
673288c03ad3SStefano Zampini       ierr = PetscFree2(pcbddcf->local_primal_ref_node,pcbddcf->local_primal_ref_mult);CHKERRQ(ierr);
673388c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->primal_indices_local_idxs);CHKERRQ(ierr);
673488c03ad3SStefano Zampini       ierr = PetscFree(pcbddcf->onearnullvecs_state);CHKERRQ(ierr);
673588c03ad3SStefano Zampini       ierr = PetscFree(pcf->data);CHKERRQ(ierr);
673688c03ad3SStefano Zampini       pcf->ops->destroy = NULL;
673788c03ad3SStefano Zampini       ierr = PCDestroy(&pcf);CHKERRQ(ierr);
673888c03ad3SStefano Zampini     }
67399d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) scaling = pcis->D;
674091af6908SStefano 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);
674172b8c272SStefano Zampini     ierr = MatDestroy(&change);CHKERRQ(ierr);
674272b8c272SStefano Zampini     ierr = ISDestroy(&change_primal);CHKERRQ(ierr);
6743ca92afb2SStefano Zampini   }
6744d12d3064SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
6745b96c3477SStefano Zampini 
6746b96c3477SStefano Zampini   /* free adjacency */
6747b96c3477SStefano Zampini   if (free_used_adj) {
6748b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
6749b96c3477SStefano Zampini   }
6750b96c3477SStefano Zampini   PetscFunctionReturn(0);
6751b96c3477SStefano Zampini }
6752b96c3477SStefano Zampini 
6753b96c3477SStefano Zampini #undef __FUNCT__
6754b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
675508122e43SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc)
6756b96c3477SStefano Zampini {
6757b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6758b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6759b96c3477SStefano Zampini   PCBDDCGraph         graph;
6760b96c3477SStefano Zampini   PetscErrorCode      ierr;
6761b96c3477SStefano Zampini 
6762b96c3477SStefano Zampini   PetscFunctionBegin;
6763b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
676408122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
67653301b35fSStefano Zampini     IS       verticesIS,verticescomm;
67663301b35fSStefano Zampini     PetscInt vsize,*idxs;
6767b96c3477SStefano Zampini 
6768b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
67693301b35fSStefano Zampini     ierr = ISGetSize(verticesIS,&vsize);CHKERRQ(ierr);
67703301b35fSStefano Zampini     ierr = ISGetIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
67713301b35fSStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),vsize,idxs,PETSC_COPY_VALUES,&verticescomm);CHKERRQ(ierr);
67723301b35fSStefano Zampini     ierr = ISRestoreIndices(verticesIS,(const PetscInt**)&idxs);CHKERRQ(ierr);
67733301b35fSStefano Zampini     ierr = ISDestroy(&verticesIS);CHKERRQ(ierr);
6774b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
67757fb0e2dbSStefano Zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap,pcbddc->mat_graph->nvtxs_global);CHKERRQ(ierr);
6776441e0de0SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,pcbddc->mat_graph->custom_minimal_size,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticescomm);CHKERRQ(ierr);
67773301b35fSStefano Zampini     ierr = ISDestroy(&verticescomm);CHKERRQ(ierr);
6778b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
6779b96c3477SStefano Zampini   } else {
6780b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
6781b96c3477SStefano Zampini   }
6782e4d548c7SStefano Zampini   /* print some info */
6783e4d548c7SStefano Zampini   if (pcbddc->dbg_flag) {
6784e4d548c7SStefano Zampini     IS       vertices;
6785e4d548c7SStefano Zampini     PetscInt nv,nedges,nfaces;
6786e4d548c7SStefano Zampini     ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
6787e4d548c7SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(graph,&nfaces,NULL,&nedges,NULL,&vertices);CHKERRQ(ierr);
6788e4d548c7SStefano Zampini     ierr = ISGetSize(vertices,&nv);CHKERRQ(ierr);
6789e4d548c7SStefano Zampini     ierr = ISDestroy(&vertices);CHKERRQ(ierr);
6790e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6791e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
6792e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices (%d)\n",PetscGlobalRank,nv,pcbddc->use_vertices);CHKERRQ(ierr);
6793e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges    (%d)\n",PetscGlobalRank,nedges,pcbddc->use_edges);CHKERRQ(ierr);
6794e4d548c7SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces    (%d)\n",PetscGlobalRank,nfaces,pcbddc->use_faces);CHKERRQ(ierr);
6795e4d548c7SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
6796e4d548c7SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
6797e4d548c7SStefano Zampini   }
6798b96c3477SStefano Zampini 
6799b96c3477SStefano Zampini   /* sub_schurs init */
6800b334f244SStefano Zampini   if (!pcbddc->sub_schurs) {
6801b334f244SStefano Zampini     ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
6802b334f244SStefano Zampini   }
6803b334f244SStefano Zampini   ierr = PCBDDCSubSchursInit(pcbddc->sub_schurs,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap);CHKERRQ(ierr);
6804a64f4aa4SStefano Zampini 
6805b96c3477SStefano Zampini   /* free graph struct */
680608122e43SStefano Zampini   if (pcbddc->sub_schurs_rebuild) {
6807b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
6808b96c3477SStefano Zampini   }
6809b96c3477SStefano Zampini   PetscFunctionReturn(0);
6810b96c3477SStefano Zampini }
6811fa34dd3eSStefano Zampini 
6812fa34dd3eSStefano Zampini #undef __FUNCT__
6813fa34dd3eSStefano Zampini #define __FUNCT__ "PCBDDCCheckOperator"
6814fa34dd3eSStefano Zampini PetscErrorCode PCBDDCCheckOperator(PC pc)
6815fa34dd3eSStefano Zampini {
6816fa34dd3eSStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
6817fa34dd3eSStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
6818fa34dd3eSStefano Zampini   PetscErrorCode      ierr;
6819fa34dd3eSStefano Zampini 
6820fa34dd3eSStefano Zampini   PetscFunctionBegin;
6821fa34dd3eSStefano Zampini   if (pcbddc->n_vertices == pcbddc->local_primal_size) {
6822fa34dd3eSStefano Zampini     IS             zerodiag = NULL;
68234f1b2e48SStefano Zampini     Mat            S_j,B0_B=NULL;
6824fa34dd3eSStefano Zampini     Vec            dummy_vec=NULL,vec_check_B,vec_scale_P;
68254f1b2e48SStefano Zampini     PetscScalar    *p0_check,*array,*array2;
682675c01103SStefano Zampini     PetscReal      norm;
6827fa34dd3eSStefano Zampini     PetscInt       i;
6828fa34dd3eSStefano Zampini 
6829fa34dd3eSStefano Zampini     /* B0 and B0_B */
6830fa34dd3eSStefano Zampini     if (zerodiag) {
6831fa34dd3eSStefano Zampini       IS       dummy;
6832fa34dd3eSStefano Zampini 
68334f1b2e48SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->benign_n,0,1,&dummy);CHKERRQ(ierr);
68344f1b2e48SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->benign_B0,dummy,pcis->is_B_local,MAT_INITIAL_MATRIX,&B0_B);CHKERRQ(ierr);
6835fa34dd3eSStefano Zampini       ierr = MatCreateVecs(B0_B,NULL,&dummy_vec);CHKERRQ(ierr);
6836fa34dd3eSStefano Zampini       ierr = ISDestroy(&dummy);CHKERRQ(ierr);
6837fa34dd3eSStefano Zampini     }
6838fa34dd3eSStefano Zampini     /* I need a primal vector to scale primal nodes since BDDC sums contibutions */
6839fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_P,&vec_scale_P);CHKERRQ(ierr);
6840fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->vec1_P,1.0);CHKERRQ(ierr);
6841fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6842fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6843fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6844fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,vec_scale_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6845fa34dd3eSStefano Zampini     ierr = VecReciprocal(vec_scale_P);CHKERRQ(ierr);
6846fa34dd3eSStefano Zampini     /* S_j */
6847fa34dd3eSStefano Zampini     ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
6848fa34dd3eSStefano Zampini     ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
6849fa34dd3eSStefano Zampini 
6850fa34dd3eSStefano Zampini     /* mimic vector in \widetilde{W}_\Gamma */
6851fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcis->vec1_N,NULL);CHKERRQ(ierr);
6852fa34dd3eSStefano Zampini     /* continuous in primal space */
6853fa34dd3eSStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_vec,NULL);CHKERRQ(ierr);
6854fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6855fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6856fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
68574f1b2e48SStefano Zampini     ierr = PetscCalloc1(pcbddc->benign_n,&p0_check);CHKERRQ(ierr);
68584f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) p0_check[i] = array[pcbddc->local_primal_size-pcbddc->benign_n+i];
6859fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
6860fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6861fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6862fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6863fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6864fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec2_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6865fa34dd3eSStefano Zampini     ierr = VecDuplicate(pcis->vec2_B,&vec_check_B);CHKERRQ(ierr);
6866fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec2_B,vec_check_B);CHKERRQ(ierr);
6867fa34dd3eSStefano Zampini 
6868fa34dd3eSStefano Zampini     /* assemble rhs for coarse problem */
6869fa34dd3eSStefano Zampini     /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */
6870fa34dd3eSStefano Zampini     /* local with Schur */
6871fa34dd3eSStefano Zampini     ierr = MatMult(S_j,pcis->vec2_B,pcis->vec1_B);CHKERRQ(ierr);
6872fa34dd3eSStefano Zampini     if (zerodiag) {
6873fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
68744f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) array[i] = p0_check[i];
6875fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
6876fa34dd3eSStefano Zampini       ierr = MatMultTransposeAdd(B0_B,dummy_vec,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
6877fa34dd3eSStefano Zampini     }
6878fa34dd3eSStefano Zampini     /* sum on primal nodes the local contributions */
6879fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6880fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6881fa34dd3eSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6882fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
6883fa34dd3eSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) array2[i] = array[pcbddc->local_primal_ref_node[i]];
6884fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
6885fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
6886fa34dd3eSStefano Zampini     ierr = VecSet(pcbddc->coarse_vec,0.);CHKERRQ(ierr);
6887fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6888fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->vec1_P,pcbddc->coarse_vec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6889fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6890fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6891fa34dd3eSStefano Zampini     ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6892fa34dd3eSStefano Zampini     /* scale primal nodes (BDDC sums contibutions) */
6893fa34dd3eSStefano Zampini     ierr = VecPointwiseMult(pcbddc->vec1_P,vec_scale_P,pcbddc->vec1_P);CHKERRQ(ierr);
6894fa34dd3eSStefano Zampini     ierr = VecSetValues(pcis->vec1_N,pcbddc->local_primal_size,pcbddc->local_primal_ref_node,array,INSERT_VALUES);CHKERRQ(ierr);
6895fa34dd3eSStefano Zampini     ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
6896fa34dd3eSStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
6897fa34dd3eSStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
6898fa34dd3eSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6899fa34dd3eSStefano Zampini     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6900fa34dd3eSStefano Zampini     /* global: \widetilde{B0}_B w_\Gamma */
6901fa34dd3eSStefano Zampini     if (zerodiag) {
6902fa34dd3eSStefano Zampini       ierr = MatMult(B0_B,pcis->vec2_B,dummy_vec);CHKERRQ(ierr);
6903fa34dd3eSStefano Zampini       ierr = VecGetArray(dummy_vec,&array);CHKERRQ(ierr);
69044f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[i];
6905fa34dd3eSStefano Zampini       ierr = VecRestoreArray(dummy_vec,&array);CHKERRQ(ierr);
6906fa34dd3eSStefano Zampini     }
6907fa34dd3eSStefano Zampini     /* BDDC */
6908fa34dd3eSStefano Zampini     ierr = VecSet(pcis->vec1_D,0.);CHKERRQ(ierr);
6909fa34dd3eSStefano Zampini     ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
6910fa34dd3eSStefano Zampini 
6911fa34dd3eSStefano Zampini     ierr = VecCopy(pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
6912fa34dd3eSStefano Zampini     ierr = VecAXPY(pcis->vec1_B,-1.0,vec_check_B);CHKERRQ(ierr);
6913fa34dd3eSStefano Zampini     ierr = VecNorm(pcis->vec1_B,NORM_INFINITY,&norm);CHKERRQ(ierr);
6914fa34dd3eSStefano Zampini     PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC local error is %1.4e\n",PetscGlobalRank,norm);
69154f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) {
69164f1b2e48SStefano Zampini       PetscPrintf(PETSC_COMM_SELF,"[%d] BDDC p0[%d] error is %1.4e\n",PetscGlobalRank,i,PetscAbsScalar(pcbddc->benign_p0[i]-p0_check[i]));
6917fa34dd3eSStefano Zampini     }
69184f1b2e48SStefano Zampini     ierr = PetscFree(p0_check);CHKERRQ(ierr);
6919fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_scale_P);CHKERRQ(ierr);
6920fa34dd3eSStefano Zampini     ierr = VecDestroy(&vec_check_B);CHKERRQ(ierr);
6921fa34dd3eSStefano Zampini     ierr = VecDestroy(&dummy_vec);CHKERRQ(ierr);
6922fa34dd3eSStefano Zampini     ierr = MatDestroy(&S_j);CHKERRQ(ierr);
6923fa34dd3eSStefano Zampini     ierr = MatDestroy(&B0_B);CHKERRQ(ierr);
6924fa34dd3eSStefano Zampini   }
6925fa34dd3eSStefano Zampini   PetscFunctionReturn(0);
6926fa34dd3eSStefano Zampini }
6927