11cf9b237SStefano Zampini #include <../src/mat/impls/aij/seq/aij.h> 25e5bbd0aSStefano Zampini #include <petsc/private/pcbddcimpl.h> 35e5bbd0aSStefano Zampini #include <petsc/private/pcbddcprivateimpl.h> 4837cedc9SStefano Zampini #include <../src/mat/impls/dense/seq/dense.h> 5c80a6c00SStefano Zampini #include <petscdmplex.h> 6674ae819SStefano Zampini #include <petscblaslapack.h> 7daf8a457SStefano Zampini #include <petsc/private/sfimpl.h> 8c80a6c00SStefano Zampini #include <petsc/private/dmpleximpl.h> 97620a527SStefano Zampini #include <petscdmda.h> 10674ae819SStefano Zampini 111e0482f5SStefano Zampini static PetscErrorCode MatMPIAIJRestrict(Mat, MPI_Comm, Mat *); 121e0482f5SStefano Zampini 13f498cd09SStefano Zampini /* if range is true, it returns B s.t. span{B} = range(A) 14f498cd09SStefano Zampini if range is false, it returns B s.t. range(B) _|_ range(A) */ 15d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDenseOrthogonalRangeOrComplement(Mat A, PetscBool range, PetscInt lw, PetscScalar *work, PetscReal *rwork, Mat *B) 16d71ae5a4SJacob Faibussowitsch { 17a13144ffSStefano Zampini PetscScalar *uwork, *data, *U, ds = 0.; 18a13144ffSStefano Zampini PetscReal *sing; 19a13144ffSStefano Zampini PetscBLASInt bM, bN, lwork, lierr, di = 1; 20a13144ffSStefano Zampini PetscInt ulw, i, nr, nc, n; 21abee2b68SSebastian Grimberg #if defined(PETSC_USE_COMPLEX) 22abee2b68SSebastian Grimberg PetscReal *rwork2; 23abee2b68SSebastian Grimberg #endif 24a13144ffSStefano Zampini 25a13144ffSStefano Zampini PetscFunctionBegin; 269566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &nr, &nc)); 273ba16761SJacob Faibussowitsch if (!nr || !nc) PetscFunctionReturn(PETSC_SUCCESS); 28a13144ffSStefano Zampini 29a13144ffSStefano Zampini /* workspace */ 30a13144ffSStefano Zampini if (!work) { 31a13144ffSStefano Zampini ulw = PetscMax(PetscMax(1, 5 * PetscMin(nr, nc)), 3 * PetscMin(nr, nc) + PetscMax(nr, nc)); 329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ulw, &uwork)); 33a13144ffSStefano Zampini } else { 34a13144ffSStefano Zampini ulw = lw; 35a13144ffSStefano Zampini uwork = work; 36a13144ffSStefano Zampini } 37a13144ffSStefano Zampini n = PetscMin(nr, nc); 38a13144ffSStefano Zampini if (!rwork) { 399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &sing)); 40a13144ffSStefano Zampini } else { 41a13144ffSStefano Zampini sing = rwork; 42a13144ffSStefano Zampini } 43a13144ffSStefano Zampini 44a13144ffSStefano Zampini /* SVD */ 459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nr * nr, &U)); 469566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(nr, &bM)); 479566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(nc, &bN)); 489566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(ulw, &lwork)); 499566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(A, &data)); 509566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 51abee2b68SSebastian Grimberg #if !defined(PETSC_USE_COMPLEX) 52792fecdfSBarry Smith PetscCallBLAS("LAPACKgesvd", LAPACKgesvd_("A", "N", &bM, &bN, data, &bM, sing, U, &bM, &ds, &di, uwork, &lwork, &lierr)); 53abee2b68SSebastian Grimberg #else 549566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(5 * n, &rwork2)); 55792fecdfSBarry Smith PetscCallBLAS("LAPACKgesvd", LAPACKgesvd_("A", "N", &bM, &bN, data, &bM, sing, U, &bM, &ds, &di, uwork, &lwork, rwork2, &lierr)); 569566063dSJacob Faibussowitsch PetscCall(PetscFree(rwork2)); 57abee2b68SSebastian Grimberg #endif 589566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 5928b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in GESVD Lapack routine %d", (int)lierr); 609566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(A, &data)); 619371c9d4SSatish Balay for (i = 0; i < n; i++) 629371c9d4SSatish Balay if (sing[i] < PETSC_SMALL) break; 6348a46eb9SPierre Jolivet if (!rwork) PetscCall(PetscFree(sing)); 6448a46eb9SPierre Jolivet if (!work) PetscCall(PetscFree(uwork)); 65a13144ffSStefano Zampini /* create B */ 66f498cd09SStefano Zampini if (!range) { 679566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, nr, nr - i, NULL, B)); 689566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(*B, &data)); 699566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data, U + nr * i, (nr - i) * nr)); 70f498cd09SStefano Zampini } else { 719566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, nr, i, NULL, B)); 729566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(*B, &data)); 739566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data, U, i * nr)); 74f498cd09SStefano Zampini } 759566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(*B, &data)); 769566063dSJacob Faibussowitsch PetscCall(PetscFree(U)); 773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 78a13144ffSStefano Zampini } 79a13144ffSStefano Zampini 801e0482f5SStefano Zampini /* TODO REMOVE */ 811e0482f5SStefano Zampini #if defined(PRINT_GDET) 821e0482f5SStefano Zampini static int inc = 0; 831e0482f5SStefano Zampini static int lev = 0; 841e0482f5SStefano Zampini #endif 851e0482f5SStefano Zampini 86d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCComputeNedelecChangeEdge(Mat lG, IS edge, IS extrow, IS extcol, IS corners, Mat *Gins, Mat *GKins, PetscScalar cvals[2], PetscScalar *work, PetscReal *rwork) 87d71ae5a4SJacob Faibussowitsch { 88a13144ffSStefano Zampini Mat GE, GEd; 89a13144ffSStefano Zampini PetscInt rsize, csize, esize; 90a13144ffSStefano Zampini PetscScalar *ptr; 91a13144ffSStefano Zampini 92a13144ffSStefano Zampini PetscFunctionBegin; 939566063dSJacob Faibussowitsch PetscCall(ISGetSize(edge, &esize)); 943ba16761SJacob Faibussowitsch if (!esize) PetscFunctionReturn(PETSC_SUCCESS); 959566063dSJacob Faibussowitsch PetscCall(ISGetSize(extrow, &rsize)); 969566063dSJacob Faibussowitsch PetscCall(ISGetSize(extcol, &csize)); 97a13144ffSStefano Zampini 98a13144ffSStefano Zampini /* gradients */ 99a13144ffSStefano Zampini ptr = work + 5 * esize; 1009566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lG, extrow, extcol, MAT_INITIAL_MATRIX, &GE)); 1019566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, rsize, csize, ptr, Gins)); 1029566063dSJacob Faibussowitsch PetscCall(MatConvert(GE, MATSEQDENSE, MAT_REUSE_MATRIX, Gins)); 1039566063dSJacob Faibussowitsch PetscCall(MatDestroy(&GE)); 104a13144ffSStefano Zampini 105a13144ffSStefano Zampini /* constants */ 106a13144ffSStefano Zampini ptr += rsize * csize; 1079566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, esize, csize, ptr, &GEd)); 1089566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lG, edge, extcol, MAT_INITIAL_MATRIX, &GE)); 1099566063dSJacob Faibussowitsch PetscCall(MatConvert(GE, MATSEQDENSE, MAT_REUSE_MATRIX, &GEd)); 1109566063dSJacob Faibussowitsch PetscCall(MatDestroy(&GE)); 1119566063dSJacob Faibussowitsch PetscCall(MatDenseOrthogonalRangeOrComplement(GEd, PETSC_FALSE, 5 * esize, work, rwork, GKins)); 1129566063dSJacob Faibussowitsch PetscCall(MatDestroy(&GEd)); 1131e0482f5SStefano Zampini 1141e0482f5SStefano Zampini if (corners) { 1151e0482f5SStefano Zampini Mat GEc; 1161683a169SBarry Smith const PetscScalar *vals; 1171683a169SBarry Smith PetscScalar v; 1181e0482f5SStefano Zampini 1199566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lG, edge, corners, MAT_INITIAL_MATRIX, &GEc)); 1209566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(GEc, *GKins, MAT_INITIAL_MATRIX, 1.0, &GEd)); 1219566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(GEd, &vals)); 122637e8532SStefano Zampini /* v = PetscAbsScalar(vals[0]) */; 123637e8532SStefano Zampini v = 1.; 1241e0482f5SStefano Zampini cvals[0] = vals[0] / v; 1251e0482f5SStefano Zampini cvals[1] = vals[1] / v; 1269566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(GEd, &vals)); 1279566063dSJacob Faibussowitsch PetscCall(MatScale(*GKins, 1. / v)); 1281e0482f5SStefano Zampini #if defined(PRINT_GDET) 1291e0482f5SStefano Zampini { 1301e0482f5SStefano Zampini PetscViewer viewer; 1311e0482f5SStefano Zampini char filename[256]; 132a364092eSJacob Faibussowitsch PetscCall(PetscSNPrintf(filename, PETSC_STATIC_ARRAY_LENGTH(filename), "Gdet_l%d_r%d_cc%d.m", lev, PetscGlobalRank, inc++)); 1339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF, filename, &viewer)); 1349566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_MATLAB)); 1359566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)GEc, "GEc")); 1369566063dSJacob Faibussowitsch PetscCall(MatView(GEc, viewer)); 1379566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)(*GKins), "GK")); 1389566063dSJacob Faibussowitsch PetscCall(MatView(*GKins, viewer)); 1399566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)GEd, "Gproj")); 1409566063dSJacob Faibussowitsch PetscCall(MatView(GEd, viewer)); 1419566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 1421e0482f5SStefano Zampini } 1431e0482f5SStefano Zampini #endif 1449566063dSJacob Faibussowitsch PetscCall(MatDestroy(&GEd)); 1459566063dSJacob Faibussowitsch PetscCall(MatDestroy(&GEc)); 1461e0482f5SStefano Zampini } 1471e0482f5SStefano Zampini 1483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 149a13144ffSStefano Zampini } 150a13144ffSStefano Zampini 151d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCNedelecSupport(PC pc) 152d71ae5a4SJacob Faibussowitsch { 153a13144ffSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 154a13144ffSStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 1550569b399SStefano Zampini Mat G, T, conn, lG, lGt, lGis, lGall, lGe, lGinit; 156eee23b56SStefano Zampini Vec tvec; 157a13144ffSStefano Zampini PetscSF sfv; 1581e0482f5SStefano Zampini ISLocalToGlobalMapping el2g, vl2g, fl2g, al2g; 159a13144ffSStefano Zampini MPI_Comm comm; 160c2151214SStefano Zampini IS lned, primals, allprimals, nedfieldlocal; 161c2151214SStefano Zampini IS *eedges, *extrows, *extcols, *alleedges; 1627d871cd7SStefano Zampini PetscBT btv, bte, btvc, btb, btbd, btvcand, btvi, btee, bter; 163a13144ffSStefano Zampini PetscScalar *vals, *work; 164a13144ffSStefano Zampini PetscReal *rwork; 165a13144ffSStefano Zampini const PetscInt *idxs, *ii, *jj, *iit, *jjt; 1661e0482f5SStefano Zampini PetscInt ne, nv, Lv, order, n, field; 167a13144ffSStefano Zampini PetscInt n_neigh, *neigh, *n_shared, **shared; 168eee23b56SStefano Zampini PetscInt i, j, extmem, cum, maxsize, nee; 169b03ebc13SStefano Zampini PetscInt *extrow, *extrowcum, *marks, *vmarks, *gidxs; 170a13144ffSStefano Zampini PetscInt *sfvleaves, *sfvroots; 171b03ebc13SStefano Zampini PetscInt *corners, *cedges; 172637e8532SStefano Zampini PetscInt *ecount, **eneighs, *vcount, **vneighs; 173b03ebc13SStefano Zampini PetscInt *emarks; 174213b8bfaSStefano Zampini PetscBool print, eerr, done, lrc[2], conforming, global, singular, setprimal; 175a13144ffSStefano Zampini 176a13144ffSStefano Zampini PetscFunctionBegin; 177213b8bfaSStefano Zampini /* If the discrete gradient is defined for a subset of dofs and global is true, 178213b8bfaSStefano Zampini it assumes G is given in global ordering for all the dofs. 179213b8bfaSStefano Zampini Otherwise, the ordering is global for the Nedelec field */ 180213b8bfaSStefano Zampini order = pcbddc->nedorder; 181213b8bfaSStefano Zampini conforming = pcbddc->conforming; 182213b8bfaSStefano Zampini field = pcbddc->nedfield; 183213b8bfaSStefano Zampini global = pcbddc->nedglobal; 184213b8bfaSStefano Zampini setprimal = PETSC_FALSE; 185a13144ffSStefano Zampini print = PETSC_FALSE; 186213b8bfaSStefano Zampini singular = PETSC_FALSE; 187a13144ffSStefano Zampini 188213b8bfaSStefano Zampini /* Command line customization */ 189d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)pc), ((PetscObject)pc)->prefix, "BDDC Nedelec options", "PC"); 1909566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_nedelec_field_primal", "All edge dofs set as primals: Toselli's algorithm C", NULL, setprimal, &setprimal, NULL)); 1919566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_nedelec_singular", "Infer nullspace from discrete gradient", NULL, singular, &singular, NULL)); 1929566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_nedelec_order", "Test variable order code (to be removed)", NULL, order, &order, NULL)); 193213b8bfaSStefano Zampini /* print debug info TODO: to be removed */ 1949566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_nedelec_print", "Print debug info", NULL, print, &print, NULL)); 195d0609cedSBarry Smith PetscOptionsEnd(); 196213b8bfaSStefano Zampini 197213b8bfaSStefano Zampini /* Return if there are no edges in the decomposition and the problem is not singular */ 1989566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(pc->pmat, &al2g, NULL)); 1999566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(al2g, &n)); 2009566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)pc, &comm)); 201213b8bfaSStefano Zampini if (!singular) { 2029566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(matis->counter, (const PetscScalar **)&vals)); 203a13144ffSStefano Zampini lrc[0] = PETSC_FALSE; 204c2151214SStefano Zampini for (i = 0; i < n; i++) { 205a13144ffSStefano Zampini if (PetscRealPart(vals[i]) > 2.) { 206a13144ffSStefano Zampini lrc[0] = PETSC_TRUE; 207a13144ffSStefano Zampini break; 208a13144ffSStefano Zampini } 209a13144ffSStefano Zampini } 2109566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(matis->counter, (const PetscScalar **)&vals)); 2111c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&lrc[0], &lrc[1], 1, MPIU_BOOL, MPI_LOR, comm)); 2123ba16761SJacob Faibussowitsch if (!lrc[1]) PetscFunctionReturn(PETSC_SUCCESS); 213213b8bfaSStefano Zampini } 214a13144ffSStefano Zampini 215213b8bfaSStefano Zampini /* Get Nedelec field */ 21663a3b9bcSJacob Faibussowitsch PetscCheck(!pcbddc->n_ISForDofsLocal || field < pcbddc->n_ISForDofsLocal, comm, PETSC_ERR_USER, "Invalid field for Nedelec %" PetscInt_FMT ": number of fields is %" PetscInt_FMT, field, pcbddc->n_ISForDofsLocal); 217213b8bfaSStefano Zampini if (pcbddc->n_ISForDofsLocal && field >= 0) { 2189566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->ISForDofsLocal[field])); 219c2151214SStefano Zampini nedfieldlocal = pcbddc->ISForDofsLocal[field]; 2209566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(nedfieldlocal, &ne)); 221213b8bfaSStefano Zampini } else if (!pcbddc->n_ISForDofsLocal && field != PETSC_DECIDE) { 222213b8bfaSStefano Zampini ne = n; 223213b8bfaSStefano Zampini nedfieldlocal = NULL; 224213b8bfaSStefano Zampini global = PETSC_TRUE; 225213b8bfaSStefano Zampini } else if (field == PETSC_DECIDE) { 226213b8bfaSStefano Zampini PetscInt rst, ren, *idx; 227213b8bfaSStefano Zampini 2289566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_leafdata, n)); 2299566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_rootdata, pc->pmat->rmap->n)); 2309566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(pcbddc->discretegradient, &rst, &ren)); 231213b8bfaSStefano Zampini for (i = rst; i < ren; i++) { 232213b8bfaSStefano Zampini PetscInt nc; 233213b8bfaSStefano Zampini 2349566063dSJacob Faibussowitsch PetscCall(MatGetRow(pcbddc->discretegradient, i, &nc, NULL, NULL)); 235213b8bfaSStefano Zampini if (nc > 1) matis->sf_rootdata[i - rst] = 1; 2369566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(pcbddc->discretegradient, i, &nc, NULL, NULL)); 237213b8bfaSStefano Zampini } 2389566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 2399566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 2409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &idx)); 2419371c9d4SSatish Balay for (i = 0, ne = 0; i < n; i++) 2429371c9d4SSatish Balay if (matis->sf_leafdata[i]) idx[ne++] = i; 2439566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, ne, idx, PETSC_OWN_POINTER, &nedfieldlocal)); 244213b8bfaSStefano Zampini } else { 245213b8bfaSStefano Zampini SETERRQ(comm, PETSC_ERR_USER, "When multiple fields are present, the Nedelec field has to be specified"); 246213b8bfaSStefano Zampini } 247213b8bfaSStefano Zampini 248213b8bfaSStefano Zampini /* Sanity checks */ 2497827d75bSBarry Smith PetscCheck(order || conforming, comm, PETSC_ERR_SUP, "Variable order and non-conforming spaces are not supported at the same time"); 25028b400f6SJacob Faibussowitsch PetscCheck(!pcbddc->user_ChangeOfBasisMatrix, comm, PETSC_ERR_SUP, "Cannot generate Nedelec support with user defined change of basis"); 25163a3b9bcSJacob Faibussowitsch PetscCheck(!order || (ne % order == 0), PETSC_COMM_SELF, PETSC_ERR_USER, "The number of local edge dofs %" PetscInt_FMT " is not a multiple of the order %" PetscInt_FMT, ne, order); 252213b8bfaSStefano Zampini 253213b8bfaSStefano Zampini /* Just set primal dofs and return */ 2541e0482f5SStefano Zampini if (setprimal) { 255eee23b56SStefano Zampini IS enedfieldlocal; 256eee23b56SStefano Zampini PetscInt *eidxs; 257eee23b56SStefano Zampini 2589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ne, &eidxs)); 2599566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(matis->counter, (const PetscScalar **)&vals)); 260213b8bfaSStefano Zampini if (nedfieldlocal) { 2619566063dSJacob Faibussowitsch PetscCall(ISGetIndices(nedfieldlocal, &idxs)); 262eee23b56SStefano Zampini for (i = 0, cum = 0; i < ne; i++) { 263ad540459SPierre Jolivet if (PetscRealPart(vals[idxs[i]]) > 2.) eidxs[cum++] = idxs[i]; 264eee23b56SStefano Zampini } 2659566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(nedfieldlocal, &idxs)); 266213b8bfaSStefano Zampini } else { 267213b8bfaSStefano Zampini for (i = 0, cum = 0; i < ne; i++) { 268ad540459SPierre Jolivet if (PetscRealPart(vals[i]) > 2.) eidxs[cum++] = i; 269213b8bfaSStefano Zampini } 270213b8bfaSStefano Zampini } 2719566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(matis->counter, (const PetscScalar **)&vals)); 2729566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, cum, eidxs, PETSC_COPY_VALUES, &enedfieldlocal)); 2739566063dSJacob Faibussowitsch PetscCall(PCBDDCSetPrimalVerticesLocalIS(pc, enedfieldlocal)); 2749566063dSJacob Faibussowitsch PetscCall(PetscFree(eidxs)); 2759566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nedfieldlocal)); 2769566063dSJacob Faibussowitsch PetscCall(ISDestroy(&enedfieldlocal)); 2773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2781e0482f5SStefano Zampini } 279a13144ffSStefano Zampini 280213b8bfaSStefano Zampini /* Compute some l2g maps */ 281213b8bfaSStefano Zampini if (nedfieldlocal) { 282c2151214SStefano Zampini IS is; 283c2151214SStefano Zampini 284c2151214SStefano Zampini /* need to map from the local Nedelec field to local numbering */ 2859566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(nedfieldlocal, &fl2g)); 2861e0482f5SStefano Zampini /* need to map from the local Nedelec field to global numbering for the whole dofs*/ 2879566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(al2g, nedfieldlocal, &is)); 2889566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &al2g)); 2891e0482f5SStefano Zampini /* need to map from the local Nedelec field to global numbering (for Nedelec only) */ 2901e0482f5SStefano Zampini if (global) { 2919566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)al2g)); 2921e0482f5SStefano Zampini el2g = al2g; 2931e0482f5SStefano Zampini } else { 2941e0482f5SStefano Zampini IS gis; 2951e0482f5SStefano Zampini 2969566063dSJacob Faibussowitsch PetscCall(ISRenumber(is, NULL, NULL, &gis)); 2979566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(gis, &el2g)); 2989566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gis)); 2991e0482f5SStefano Zampini } 3009566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 301c2151214SStefano Zampini } else { 3021e0482f5SStefano Zampini /* restore default */ 3031e0482f5SStefano Zampini pcbddc->nedfield = -1; 3041e0482f5SStefano Zampini /* one ref for the destruction of al2g, one for el2g */ 3059566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)al2g)); 3069566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)al2g)); 3071e0482f5SStefano Zampini el2g = al2g; 308c2151214SStefano Zampini fl2g = NULL; 309c2151214SStefano Zampini } 310a13144ffSStefano Zampini 311213b8bfaSStefano Zampini /* Start communication to drop connections for interior edges (for cc analysis only) */ 3129566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_leafdata, n)); 3139566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_rootdata, pc->pmat->rmap->n)); 314c2151214SStefano Zampini if (nedfieldlocal) { 3159566063dSJacob Faibussowitsch PetscCall(ISGetIndices(nedfieldlocal, &idxs)); 316c2151214SStefano Zampini for (i = 0; i < ne; i++) matis->sf_leafdata[idxs[i]] = 1; 3179566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(nedfieldlocal, &idxs)); 318c2151214SStefano Zampini } else { 319c2151214SStefano Zampini for (i = 0; i < ne; i++) matis->sf_leafdata[i] = 1; 320c2151214SStefano Zampini } 3219566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, matis->sf_leafdata, matis->sf_rootdata, MPI_SUM)); 3229566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, matis->sf_leafdata, matis->sf_rootdata, MPI_SUM)); 323213b8bfaSStefano Zampini 324213b8bfaSStefano Zampini if (!singular) { /* drop connections with interior edges to avoid unneeded communications and memory movements */ 3259566063dSJacob Faibussowitsch PetscCall(MatDuplicate(pcbddc->discretegradient, MAT_COPY_VALUES, &G)); 3269566063dSJacob Faibussowitsch PetscCall(MatSetOption(G, MAT_KEEP_NONZERO_PATTERN, PETSC_FALSE)); 3271e0482f5SStefano Zampini if (global) { 3281e0482f5SStefano Zampini PetscInt rst; 3291e0482f5SStefano Zampini 3309566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(G, &rst, NULL)); 331c2151214SStefano Zampini for (i = 0, cum = 0; i < pc->pmat->rmap->n; i++) { 332ad540459SPierre Jolivet if (matis->sf_rootdata[i] < 2) matis->sf_rootdata[cum++] = i + rst; 333c2151214SStefano Zampini } 3349566063dSJacob Faibussowitsch PetscCall(MatSetOption(G, MAT_NO_OFF_PROC_ZERO_ROWS, PETSC_TRUE)); 3359566063dSJacob Faibussowitsch PetscCall(MatZeroRows(G, cum, matis->sf_rootdata, 0., NULL, NULL)); 3361e0482f5SStefano Zampini } else { 3371e0482f5SStefano Zampini PetscInt *tbz; 3381e0482f5SStefano Zampini 3399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ne, &tbz)); 3409566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 3419566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 3429566063dSJacob Faibussowitsch PetscCall(ISGetIndices(nedfieldlocal, &idxs)); 3431e0482f5SStefano Zampini for (i = 0, cum = 0; i < ne; i++) 3449371c9d4SSatish Balay if (matis->sf_leafdata[idxs[i]] == 1) tbz[cum++] = i; 3459566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(nedfieldlocal, &idxs)); 3469566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(el2g, cum, tbz, tbz)); 3479566063dSJacob Faibussowitsch PetscCall(MatZeroRows(G, cum, tbz, 0., NULL, NULL)); 3489566063dSJacob Faibussowitsch PetscCall(PetscFree(tbz)); 3491e0482f5SStefano Zampini } 350213b8bfaSStefano Zampini } else { /* we need the entire G to infer the nullspace */ 3519566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->discretegradient)); 352213b8bfaSStefano Zampini G = pcbddc->discretegradient; 353213b8bfaSStefano Zampini } 354a13144ffSStefano Zampini 355a13144ffSStefano Zampini /* Extract subdomain relevant rows of G */ 3569566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(el2g, &idxs)); 3579566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, ne, idxs, PETSC_USE_POINTER, &lned)); 3589566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(G, lned, NULL, MAT_INITIAL_MATRIX, &lGall)); 3599566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(el2g, &idxs)); 3609566063dSJacob Faibussowitsch PetscCall(ISDestroy(&lned)); 3619566063dSJacob Faibussowitsch PetscCall(MatConvert(lGall, MATIS, MAT_INITIAL_MATRIX, &lGis)); 3629566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGall)); 3639566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(lGis, &lG)); 364a13144ffSStefano Zampini 365213b8bfaSStefano Zampini /* SF for nodal dofs communications */ 3669566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(G, NULL, &Lv)); 3679566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(lGis, NULL, &vl2g)); 3689566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)vl2g)); 3699566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(vl2g, &nv)); 3709566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &sfv)); 3719566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(vl2g, &idxs)); 3729566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(sfv, lGis->cmap, nv, NULL, PETSC_OWN_POINTER, idxs)); 3739566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(vl2g, &idxs)); 374213b8bfaSStefano Zampini i = singular ? 2 : 1; 3759566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(i * nv, &sfvleaves, i * Lv, &sfvroots)); 376a13144ffSStefano Zampini 3771e0482f5SStefano Zampini /* Destroy temporary G created in MATIS format and modified G */ 3789566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)lG)); 3799566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGis)); 3809566063dSJacob Faibussowitsch PetscCall(MatDestroy(&G)); 381a13144ffSStefano Zampini 382213b8bfaSStefano Zampini if (print) { 3839566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)lG, "initial_lG")); 3849566063dSJacob Faibussowitsch PetscCall(MatView(lG, NULL)); 385213b8bfaSStefano Zampini } 386213b8bfaSStefano Zampini 387213b8bfaSStefano Zampini /* Save lG for values insertion in change of basis */ 3889566063dSJacob Faibussowitsch PetscCall(MatDuplicate(lG, MAT_COPY_VALUES, &lGinit)); 3890569b399SStefano Zampini 390a13144ffSStefano Zampini /* Analyze the edge-nodes connections (duplicate lG) */ 3919566063dSJacob Faibussowitsch PetscCall(MatDuplicate(lG, MAT_COPY_VALUES, &lGe)); 3929566063dSJacob Faibussowitsch PetscCall(MatSetOption(lGe, MAT_KEEP_NONZERO_PATTERN, PETSC_FALSE)); 3939566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(nv, &btv)); 3949566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(ne, &bte)); 3959566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(ne, &btb)); 3969566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(ne, &btbd)); 3979566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(nv, &btvcand)); 398a13144ffSStefano Zampini /* need to import the boundary specification to ensure the 399a13144ffSStefano Zampini proper detection of coarse edges' endpoints */ 400a13144ffSStefano Zampini if (pcbddc->DirichletBoundariesLocal) { 401c2151214SStefano Zampini IS is; 402c2151214SStefano Zampini 403c2151214SStefano Zampini if (fl2g) { 4049566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(fl2g, IS_GTOLM_MASK, pcbddc->DirichletBoundariesLocal, &is)); 405c2151214SStefano Zampini } else { 406c2151214SStefano Zampini is = pcbddc->DirichletBoundariesLocal; 407c2151214SStefano Zampini } 4089566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &cum)); 4099566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, &idxs)); 410a13144ffSStefano Zampini for (i = 0; i < cum; i++) { 411a13144ffSStefano Zampini if (idxs[i] >= 0) { 4129566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btb, idxs[i])); 4139566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btbd, idxs[i])); 414a13144ffSStefano Zampini } 415a13144ffSStefano Zampini } 4169566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, &idxs)); 41748a46eb9SPierre Jolivet if (fl2g) PetscCall(ISDestroy(&is)); 418a13144ffSStefano Zampini } 419a13144ffSStefano Zampini if (pcbddc->NeumannBoundariesLocal) { 420c2151214SStefano Zampini IS is; 421c2151214SStefano Zampini 422c2151214SStefano Zampini if (fl2g) { 4239566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(fl2g, IS_GTOLM_MASK, pcbddc->NeumannBoundariesLocal, &is)); 424c2151214SStefano Zampini } else { 425c2151214SStefano Zampini is = pcbddc->NeumannBoundariesLocal; 426c2151214SStefano Zampini } 4279566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &cum)); 4289566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, &idxs)); 429a13144ffSStefano Zampini for (i = 0; i < cum; i++) { 43048a46eb9SPierre Jolivet if (idxs[i] >= 0) PetscCall(PetscBTSet(btb, idxs[i])); 431a13144ffSStefano Zampini } 4329566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, &idxs)); 43348a46eb9SPierre Jolivet if (fl2g) PetscCall(ISDestroy(&is)); 434c2151214SStefano Zampini } 435c2151214SStefano Zampini 436213b8bfaSStefano Zampini /* Count neighs per dof */ 4379566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetNodeInfo(el2g, NULL, &ecount, &eneighs)); 4389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetNodeInfo(vl2g, NULL, &vcount, &vneighs)); 439637e8532SStefano Zampini 4407d871cd7SStefano Zampini /* need to remove coarse faces' dofs and coarse edges' dirichlet dofs 4417d871cd7SStefano Zampini for proper detection of coarse edges' endpoints */ 4429566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(ne, &btee)); 44362b0c6f7SStefano Zampini for (i = 0; i < ne; i++) { 44448a46eb9SPierre Jolivet if ((ecount[i] > 2 && !PetscBTLookup(btbd, i)) || (ecount[i] == 2 && PetscBTLookup(btb, i))) PetscCall(PetscBTSet(btee, i)); 44562b0c6f7SStefano Zampini } 4469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ne, &marks)); 44762b0c6f7SStefano Zampini if (!conforming) { 4489566063dSJacob Faibussowitsch PetscCall(MatTranspose(lGe, MAT_INITIAL_MATRIX, &lGt)); 4499566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 45062b0c6f7SStefano Zampini } 4519566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGe, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 4529566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(lGe, &vals)); 45362b0c6f7SStefano Zampini cum = 0; 454a13144ffSStefano Zampini for (i = 0; i < ne; i++) { 455dec27d64SStefano Zampini /* eliminate rows corresponding to edge dofs belonging to coarse faces */ 45662b0c6f7SStefano Zampini if (!PetscBTLookup(btee, i)) { 457a13144ffSStefano Zampini marks[cum++] = i; 458dec27d64SStefano Zampini continue; 459dec27d64SStefano Zampini } 460dec27d64SStefano Zampini /* set badly connected edge dofs as primal */ 46162b0c6f7SStefano Zampini if (!conforming) { 46262b0c6f7SStefano Zampini if (ii[i + 1] - ii[i] != order + 1) { /* every row of G on the coarse edge should list order+1 nodal dofs */ 463a13144ffSStefano Zampini marks[cum++] = i; 4649566063dSJacob Faibussowitsch PetscCall(PetscBTSet(bte, i)); 46548a46eb9SPierre Jolivet for (j = ii[i]; j < ii[i + 1]; j++) PetscCall(PetscBTSet(btv, jj[j])); 46662b0c6f7SStefano Zampini } else { 467*aaa8cc7dSPierre Jolivet /* every edge dofs should be connected through a certain number of nodal dofs 46862b0c6f7SStefano Zampini to other edge dofs belonging to coarse edges 46962b0c6f7SStefano Zampini - at most 2 endpoints 47062b0c6f7SStefano Zampini - order-1 interior nodal dofs 47162b0c6f7SStefano Zampini - no undefined nodal dofs (nconn < order) 47262b0c6f7SStefano Zampini */ 47362b0c6f7SStefano Zampini PetscInt ends = 0, ints = 0, undef = 0; 47462b0c6f7SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 47562b0c6f7SStefano Zampini PetscInt v = jj[j], k; 47662b0c6f7SStefano Zampini PetscInt nconn = iit[v + 1] - iit[v]; 4779371c9d4SSatish Balay for (k = iit[v]; k < iit[v + 1]; k++) 4789371c9d4SSatish Balay if (!PetscBTLookup(btee, jjt[k])) nconn--; 47962b0c6f7SStefano Zampini if (nconn > order) ends++; 48062b0c6f7SStefano Zampini else if (nconn == order) ints++; 48162b0c6f7SStefano Zampini else undef++; 48262b0c6f7SStefano Zampini } 48362b0c6f7SStefano Zampini if (undef || ends > 2 || ints != order - 1) { 48462b0c6f7SStefano Zampini marks[cum++] = i; 4859566063dSJacob Faibussowitsch PetscCall(PetscBTSet(bte, i)); 48648a46eb9SPierre Jolivet for (j = ii[i]; j < ii[i + 1]; j++) PetscCall(PetscBTSet(btv, jj[j])); 48762b0c6f7SStefano Zampini } 48862b0c6f7SStefano Zampini } 489a13144ffSStefano Zampini } 490dec27d64SStefano Zampini /* We assume the order on the element edge is ii[i+1]-ii[i]-1 */ 491dec27d64SStefano Zampini if (!order && ii[i + 1] != ii[i]) { 492dec27d64SStefano Zampini PetscScalar val = 1. / (ii[i + 1] - ii[i] - 1); 493dec27d64SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) vals[j] = val; 494a13144ffSStefano Zampini } 495dec27d64SStefano Zampini } 4969566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btee)); 4979566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(lGe, &vals)); 4989566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGe, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 49962b0c6f7SStefano Zampini if (!conforming) { 5009566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 5019566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGt)); 50262b0c6f7SStefano Zampini } 5039566063dSJacob Faibussowitsch PetscCall(MatZeroRows(lGe, cum, marks, 0., NULL, NULL)); 504637e8532SStefano Zampini 505b03ebc13SStefano Zampini /* identify splitpoints and corner candidates */ 5069566063dSJacob Faibussowitsch PetscCall(MatTranspose(lGe, MAT_INITIAL_MATRIX, &lGt)); 507a13144ffSStefano Zampini if (print) { 5089566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)lGe, "edgerestr_lG")); 5099566063dSJacob Faibussowitsch PetscCall(MatView(lGe, NULL)); 5109566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)lGt, "edgerestr_lGt")); 5119566063dSJacob Faibussowitsch PetscCall(MatView(lGt, NULL)); 512a13144ffSStefano Zampini } 5139566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 5149566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(lGt, &vals)); 515a13144ffSStefano Zampini for (i = 0; i < nv; i++) { 516637e8532SStefano Zampini PetscInt ord = order, test = ii[i + 1] - ii[i], vc = vcount[i]; 5177d871cd7SStefano Zampini PetscBool sneighs = PETSC_TRUE, bdir = PETSC_FALSE; 518b03ebc13SStefano Zampini if (!order) { /* variable order */ 519dec27d64SStefano Zampini PetscReal vorder = 0.; 520dec27d64SStefano Zampini 521dec27d64SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) vorder += PetscRealPart(vals[j]); 522dec27d64SStefano Zampini test = PetscFloorReal(vorder + 10. * PETSC_SQRT_MACHINE_EPSILON); 52363a3b9bcSJacob Faibussowitsch PetscCheck(vorder - test <= PETSC_SQRT_MACHINE_EPSILON, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected value for vorder: %g (%" PetscInt_FMT ")", (double)vorder, test); 524dec27d64SStefano Zampini ord = 1; 525dec27d64SStefano Zampini } 5266bdcaf15SBarry Smith PetscAssert(test % ord == 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected number of edge dofs %" PetscInt_FMT " connected with nodal dof %" PetscInt_FMT " with order %" PetscInt_FMT, test, i, ord); 527637e8532SStefano Zampini for (j = ii[i]; j < ii[i + 1] && sneighs; j++) { 5287d871cd7SStefano Zampini if (PetscBTLookup(btbd, jj[j])) { 5297d871cd7SStefano Zampini bdir = PETSC_TRUE; 5307d871cd7SStefano Zampini break; 5317d871cd7SStefano Zampini } 532637e8532SStefano Zampini if (vc != ecount[jj[j]]) { 533637e8532SStefano Zampini sneighs = PETSC_FALSE; 534637e8532SStefano Zampini } else { 535637e8532SStefano Zampini PetscInt k, *vn = vneighs[i], *en = eneighs[jj[j]]; 536637e8532SStefano Zampini for (k = 0; k < vc; k++) { 537637e8532SStefano Zampini if (vn[k] != en[k]) { 538637e8532SStefano Zampini sneighs = PETSC_FALSE; 539637e8532SStefano Zampini break; 540637e8532SStefano Zampini } 541637e8532SStefano Zampini } 542637e8532SStefano Zampini } 543637e8532SStefano Zampini } 5447d871cd7SStefano Zampini if (!sneighs || test >= 3 * ord || bdir) { /* splitpoints */ 5453ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, "SPLITPOINT %" PetscInt_FMT " (%s %s %s)\n", i, PetscBools[!sneighs], PetscBools[test >= 3 * ord], PetscBools[bdir])); 5469566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, i)); 547dec27d64SStefano Zampini } else if (test == ord) { 548b03ebc13SStefano Zampini if (order == 1 || (!order && ii[i + 1] - ii[i] == 1)) { 5493ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, "ENDPOINT %" PetscInt_FMT "\n", i)); 5509566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, i)); 551a13144ffSStefano Zampini } else { 5523ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, "CORNER CANDIDATE %" PetscInt_FMT "\n", i)); 5539566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btvcand, i)); 554a13144ffSStefano Zampini } 555a13144ffSStefano Zampini } 556a13144ffSStefano Zampini } 5579566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(el2g, NULL, &ecount, &eneighs)); 5589566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(vl2g, NULL, &vcount, &vneighs)); 5599566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btbd)); 560b03ebc13SStefano Zampini 561b03ebc13SStefano Zampini /* a candidate is valid if it is connected to another candidate via a non-primal edge dof */ 562b03ebc13SStefano Zampini if (order != 1) { 5633ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, "INSPECTING CANDIDATES\n")); 5649566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGe, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 565b03ebc13SStefano Zampini for (i = 0; i < nv; i++) { 566b03ebc13SStefano Zampini if (PetscBTLookup(btvcand, i)) { 567b03ebc13SStefano Zampini PetscBool found = PETSC_FALSE; 568b03ebc13SStefano Zampini for (j = ii[i]; j < ii[i + 1] && !found; j++) { 569b03ebc13SStefano Zampini PetscInt k, e = jj[j]; 570b03ebc13SStefano Zampini if (PetscBTLookup(bte, e)) continue; 571b03ebc13SStefano Zampini for (k = iit[e]; k < iit[e + 1]; k++) { 572b03ebc13SStefano Zampini PetscInt v = jjt[k]; 573b03ebc13SStefano Zampini if (v != i && PetscBTLookup(btvcand, v)) { 574b03ebc13SStefano Zampini found = PETSC_TRUE; 575b03ebc13SStefano Zampini break; 576b03ebc13SStefano Zampini } 577b03ebc13SStefano Zampini } 578b03ebc13SStefano Zampini } 579b03ebc13SStefano Zampini if (!found) { 5803ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " CANDIDATE %" PetscInt_FMT " CLEARED\n", i)); 5819566063dSJacob Faibussowitsch PetscCall(PetscBTClear(btvcand, i)); 582b03ebc13SStefano Zampini } else { 5833ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " CANDIDATE %" PetscInt_FMT " ACCEPTED\n", i)); 584b03ebc13SStefano Zampini } 585b03ebc13SStefano Zampini } 586b03ebc13SStefano Zampini } 5879566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGe, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 588b03ebc13SStefano Zampini } 5899566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(lGt, &vals)); 5909566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 5919566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGe)); 592a13144ffSStefano Zampini 593a13144ffSStefano Zampini /* Get the local G^T explicitly */ 5949566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGt)); 5959566063dSJacob Faibussowitsch PetscCall(MatTranspose(lG, MAT_INITIAL_MATRIX, &lGt)); 5969566063dSJacob Faibussowitsch PetscCall(MatSetOption(lGt, MAT_KEEP_NONZERO_PATTERN, PETSC_FALSE)); 597a13144ffSStefano Zampini 5984e64d54eSstefano_zampini /* Mark interior nodal dofs */ 5999566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetInfo(vl2g, &n_neigh, &neigh, &n_shared, &shared)); 6009566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(nv, &btvi)); 601a13144ffSStefano Zampini for (i = 1; i < n_neigh; i++) { 60248a46eb9SPierre Jolivet for (j = 0; j < n_shared[i]; j++) PetscCall(PetscBTSet(btvi, shared[i][j])); 603a13144ffSStefano Zampini } 6049566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreInfo(vl2g, &n_neigh, &neigh, &n_shared, &shared)); 605a13144ffSStefano Zampini 606a13144ffSStefano Zampini /* communicate corners and splitpoints */ 6079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nv, &vmarks)); 6089566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(sfvleaves, nv)); 6099566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(sfvroots, Lv)); 6109371c9d4SSatish Balay for (i = 0; i < nv; i++) 6119371c9d4SSatish Balay if (PetscUnlikely(PetscBTLookup(btv, i))) sfvleaves[i] = 1; 612a13144ffSStefano Zampini 613a13144ffSStefano Zampini if (print) { 614a13144ffSStefano Zampini IS tbz; 615a13144ffSStefano Zampini 616a13144ffSStefano Zampini cum = 0; 617a13144ffSStefano Zampini for (i = 0; i < nv; i++) 6189371c9d4SSatish Balay if (sfvleaves[i]) vmarks[cum++] = i; 619a13144ffSStefano Zampini 6209566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cum, vmarks, PETSC_COPY_VALUES, &tbz)); 6219566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)tbz, "corners_to_be_zeroed_local")); 6229566063dSJacob Faibussowitsch PetscCall(ISView(tbz, NULL)); 6239566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tbz)); 624a13144ffSStefano Zampini } 625a13144ffSStefano Zampini 6269566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(sfv, MPIU_INT, sfvleaves, sfvroots, MPI_SUM)); 6279566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(sfv, MPIU_INT, sfvleaves, sfvroots, MPI_SUM)); 6289566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfv, MPIU_INT, sfvroots, sfvleaves, MPI_REPLACE)); 6299566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfv, MPIU_INT, sfvroots, sfvleaves, MPI_REPLACE)); 630a13144ffSStefano Zampini 6314e64d54eSstefano_zampini /* Zero rows of lGt corresponding to identified corners 6324e64d54eSstefano_zampini and interior nodal dofs */ 633a13144ffSStefano Zampini cum = 0; 634a13144ffSStefano Zampini for (i = 0; i < nv; i++) { 635a13144ffSStefano Zampini if (sfvleaves[i]) { 636a13144ffSStefano Zampini vmarks[cum++] = i; 6379566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, i)); 638a13144ffSStefano Zampini } 6394e64d54eSstefano_zampini if (!PetscBTLookup(btvi, i)) vmarks[cum++] = i; 640a13144ffSStefano Zampini } 6419566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btvi)); 642a13144ffSStefano Zampini if (print) { 643a13144ffSStefano Zampini IS tbz; 644a13144ffSStefano Zampini 6459566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cum, vmarks, PETSC_COPY_VALUES, &tbz)); 6469566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)tbz, "corners_to_be_zeroed_with_interior")); 6479566063dSJacob Faibussowitsch PetscCall(ISView(tbz, NULL)); 6489566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tbz)); 649a13144ffSStefano Zampini } 6509566063dSJacob Faibussowitsch PetscCall(MatZeroRows(lGt, cum, vmarks, 0., NULL, NULL)); 6519566063dSJacob Faibussowitsch PetscCall(PetscFree(vmarks)); 6529566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfv)); 6539566063dSJacob Faibussowitsch PetscCall(PetscFree2(sfvleaves, sfvroots)); 654a13144ffSStefano Zampini 655a13144ffSStefano Zampini /* Recompute G */ 6569566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lG)); 6579566063dSJacob Faibussowitsch PetscCall(MatTranspose(lGt, MAT_INITIAL_MATRIX, &lG)); 658a13144ffSStefano Zampini if (print) { 6599566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)lG, "used_lG")); 6609566063dSJacob Faibussowitsch PetscCall(MatView(lG, NULL)); 6619566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)lGt, "used_lGt")); 6629566063dSJacob Faibussowitsch PetscCall(MatView(lGt, NULL)); 663a13144ffSStefano Zampini } 664a13144ffSStefano Zampini 665a13144ffSStefano Zampini /* Get primal dofs (if any) */ 666a13144ffSStefano Zampini cum = 0; 667a13144ffSStefano Zampini for (i = 0; i < ne; i++) { 668a13144ffSStefano Zampini if (PetscUnlikely(PetscBTLookup(bte, i))) marks[cum++] = i; 669a13144ffSStefano Zampini } 6701baa6e33SBarry Smith if (fl2g) PetscCall(ISLocalToGlobalMappingApply(fl2g, cum, marks, marks)); 6719566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, cum, marks, PETSC_COPY_VALUES, &primals)); 672a13144ffSStefano Zampini if (print) { 6739566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)primals, "prescribed_primal_dofs")); 6749566063dSJacob Faibussowitsch PetscCall(ISView(primals, NULL)); 675a13144ffSStefano Zampini } 6769566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&bte)); 677c2151214SStefano Zampini /* TODO: what if the user passed in some of them ? */ 6789566063dSJacob Faibussowitsch PetscCall(PCBDDCSetPrimalVerticesLocalIS(pc, primals)); 6799566063dSJacob Faibussowitsch PetscCall(ISDestroy(&primals)); 680a13144ffSStefano Zampini 681a13144ffSStefano Zampini /* Compute edge connectivity */ 6829566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)lG, "econn_")); 6834222ddf1SHong Zhang 6844222ddf1SHong Zhang /* Symbolic conn = lG*lGt */ 6859566063dSJacob Faibussowitsch PetscCall(MatProductCreate(lG, lGt, NULL, &conn)); 6869566063dSJacob Faibussowitsch PetscCall(MatProductSetType(conn, MATPRODUCT_AB)); 6879566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(conn, "default")); 6889566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(conn, PETSC_DEFAULT)); 6899566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)conn, "econn_")); 6909566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(conn)); 6919566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(conn)); 6924222ddf1SHong Zhang 6939566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 694c2151214SStefano Zampini if (fl2g) { 695c2151214SStefano Zampini PetscBT btf; 696c2151214SStefano Zampini PetscInt *iia, *jja, *iiu, *jju; 697c2151214SStefano Zampini PetscBool rest = PETSC_FALSE, free = PETSC_FALSE; 698c2151214SStefano Zampini 699c2151214SStefano Zampini /* create CSR for all local dofs */ 7009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n + 1, &iia)); 701c2151214SStefano Zampini if (pcbddc->mat_graph->nvtxs_csr) { /* the user has passed in a CSR graph */ 70263a3b9bcSJacob Faibussowitsch PetscCheck(pcbddc->mat_graph->nvtxs_csr == n, PETSC_COMM_SELF, PETSC_ERR_USER, "Invalid size of CSR graph %" PetscInt_FMT ". Should be %" PetscInt_FMT, pcbddc->mat_graph->nvtxs_csr, n); 703c2151214SStefano Zampini iiu = pcbddc->mat_graph->xadj; 704c2151214SStefano Zampini jju = pcbddc->mat_graph->adjncy; 705c2151214SStefano Zampini } else if (pcbddc->use_local_adj) { 706c2151214SStefano Zampini rest = PETSC_TRUE; 7079566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(matis->A, 0, PETSC_TRUE, PETSC_FALSE, &i, (const PetscInt **)&iiu, (const PetscInt **)&jju, &done)); 708c2151214SStefano Zampini } else { 709c2151214SStefano Zampini free = PETSC_TRUE; 7109566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n + 1, &iiu, n, &jju)); 711c2151214SStefano Zampini iiu[0] = 0; 712c2151214SStefano Zampini for (i = 0; i < n; i++) { 713c2151214SStefano Zampini iiu[i + 1] = i + 1; 714c2151214SStefano Zampini jju[i] = -1; 715d904f53bSStefano Zampini } 716c2151214SStefano Zampini } 717c2151214SStefano Zampini 718c2151214SStefano Zampini /* import sizes of CSR */ 719c2151214SStefano Zampini iia[0] = 0; 720c2151214SStefano Zampini for (i = 0; i < n; i++) iia[i + 1] = iiu[i + 1] - iiu[i]; 721c2151214SStefano Zampini 722c2151214SStefano Zampini /* overwrite entries corresponding to the Nedelec field */ 7239566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(n, &btf)); 7249566063dSJacob Faibussowitsch PetscCall(ISGetIndices(nedfieldlocal, &idxs)); 725c2151214SStefano Zampini for (i = 0; i < ne; i++) { 7269566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btf, idxs[i])); 727c2151214SStefano Zampini iia[idxs[i] + 1] = ii[i + 1] - ii[i]; 728c2151214SStefano Zampini } 729c2151214SStefano Zampini 730c2151214SStefano Zampini /* iia in CSR */ 731c2151214SStefano Zampini for (i = 0; i < n; i++) iia[i + 1] += iia[i]; 732c2151214SStefano Zampini 733c2151214SStefano Zampini /* jja in CSR */ 7349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(iia[n], &jja)); 735c2151214SStefano Zampini for (i = 0; i < n; i++) 736c2151214SStefano Zampini if (!PetscBTLookup(btf, i)) 7379371c9d4SSatish Balay for (j = 0; j < iiu[i + 1] - iiu[i]; j++) jja[iia[i] + j] = jju[iiu[i] + j]; 738c2151214SStefano Zampini 739c2151214SStefano Zampini /* map edge dofs connectivity */ 7401e0482f5SStefano Zampini if (jj) { 7419566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(fl2g, ii[ne], jj, (PetscInt *)jj)); 742c2151214SStefano Zampini for (i = 0; i < ne; i++) { 743c2151214SStefano Zampini PetscInt e = idxs[i]; 744c2151214SStefano Zampini for (j = 0; j < ii[i + 1] - ii[i]; j++) jja[iia[e] + j] = jj[ii[i] + j]; 745c2151214SStefano Zampini } 7461e0482f5SStefano Zampini } 7479566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(nedfieldlocal, &idxs)); 7489566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLocalAdjacencyGraph(pc, n, iia, jja, PETSC_OWN_POINTER)); 74948a46eb9SPierre Jolivet if (rest) PetscCall(MatRestoreRowIJ(matis->A, 0, PETSC_TRUE, PETSC_FALSE, &i, (const PetscInt **)&iiu, (const PetscInt **)&jju, &done)); 7501baa6e33SBarry Smith if (free) PetscCall(PetscFree2(iiu, jju)); 7519566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btf)); 752c2151214SStefano Zampini } else { 7539566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLocalAdjacencyGraph(pc, n, ii, jj, PETSC_USE_POINTER)); 754c2151214SStefano Zampini } 755c2151214SStefano Zampini 756a13144ffSStefano Zampini /* Analyze interface for edge dofs */ 7579566063dSJacob Faibussowitsch PetscCall(PCBDDCAnalyzeInterface(pc)); 758213b8bfaSStefano Zampini pcbddc->mat_graph->twodim = PETSC_FALSE; 759a13144ffSStefano Zampini 760a13144ffSStefano Zampini /* Get coarse edges in the edge space */ 7619566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, NULL, NULL, &nee, &alleedges, &allprimals)); 7629566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 763a13144ffSStefano Zampini 764c2151214SStefano Zampini if (fl2g) { 7659566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(fl2g, IS_GTOLM_DROP, allprimals, &primals)); 7669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nee, &eedges)); 76748a46eb9SPierre Jolivet for (i = 0; i < nee; i++) PetscCall(ISGlobalToLocalMappingApplyIS(fl2g, IS_GTOLM_DROP, alleedges[i], &eedges[i])); 768c2151214SStefano Zampini } else { 769c2151214SStefano Zampini eedges = alleedges; 770c2151214SStefano Zampini primals = allprimals; 771c2151214SStefano Zampini } 772c2151214SStefano Zampini 773a13144ffSStefano Zampini /* Mark fine edge dofs with their coarse edge id */ 7749566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(marks, ne)); 7759566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(primals, &cum)); 7769566063dSJacob Faibussowitsch PetscCall(ISGetIndices(primals, &idxs)); 777c2151214SStefano Zampini for (i = 0; i < cum; i++) marks[idxs[i]] = nee + 1; 7789566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(primals, &idxs)); 779c2151214SStefano Zampini if (print) { 7809566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)primals, "obtained_primal_dofs")); 7819566063dSJacob Faibussowitsch PetscCall(ISView(primals, NULL)); 782c2151214SStefano Zampini } 783c2151214SStefano Zampini 784c2151214SStefano Zampini maxsize = 0; 785a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 786a13144ffSStefano Zampini PetscInt size, mark = i + 1; 787a13144ffSStefano Zampini 7889566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 7899566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 790a13144ffSStefano Zampini for (j = 0; j < size; j++) marks[idxs[j]] = mark; 7919566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 792a13144ffSStefano Zampini maxsize = PetscMax(maxsize, size); 793a13144ffSStefano Zampini } 794a13144ffSStefano Zampini 795a13144ffSStefano Zampini /* Find coarse edge endpoints */ 7969566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lG, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 7979566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 798a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 799a13144ffSStefano Zampini PetscInt mark = i + 1, size; 800a13144ffSStefano Zampini 8019566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 8021e0482f5SStefano Zampini if (!size && nedfieldlocal) continue; 80363a3b9bcSJacob Faibussowitsch PetscCheck(size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected zero sized edge %" PetscInt_FMT, i); 8049566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 805a13144ffSStefano Zampini if (print) { 80663a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "ENDPOINTS ANALYSIS EDGE %" PetscInt_FMT "\n", i)); 8079566063dSJacob Faibussowitsch PetscCall(ISView(eedges[i], NULL)); 808a13144ffSStefano Zampini } 809a13144ffSStefano Zampini for (j = 0; j < size; j++) { 810a13144ffSStefano Zampini PetscInt k, ee = idxs[j]; 8113ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " idx %" PetscInt_FMT "\n", ee)); 812a13144ffSStefano Zampini for (k = ii[ee]; k < ii[ee + 1]; k++) { 8133ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " inspect %" PetscInt_FMT "\n", jj[k])); 814a13144ffSStefano Zampini if (PetscBTLookup(btv, jj[k])) { 8153ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " corner found (already set) %" PetscInt_FMT "\n", jj[k])); 816a13144ffSStefano Zampini } else if (PetscBTLookup(btvcand, jj[k])) { /* is it ok? */ 817a13144ffSStefano Zampini PetscInt k2; 818a13144ffSStefano Zampini PetscBool corner = PETSC_FALSE; 819a13144ffSStefano Zampini for (k2 = iit[jj[k]]; k2 < iit[jj[k] + 1]; k2++) { 8203ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " INSPECTING %" PetscInt_FMT ": mark %" PetscInt_FMT " (ref mark %" PetscInt_FMT "), boundary %d\n", jjt[k2], marks[jjt[k2]], mark, (int)!!PetscBTLookup(btb, jjt[k2]))); 821c2151214SStefano Zampini /* it's a corner if either is connected with an edge dof belonging to a different cc or 822c2151214SStefano Zampini if the edge dof lie on the natural part of the boundary */ 823c2151214SStefano Zampini if ((marks[jjt[k2]] && marks[jjt[k2]] != mark) || (!marks[jjt[k2]] && PetscBTLookup(btb, jjt[k2]))) { 824a13144ffSStefano Zampini corner = PETSC_TRUE; 825a13144ffSStefano Zampini break; 826a13144ffSStefano Zampini } 827a13144ffSStefano Zampini } 828a13144ffSStefano Zampini if (corner) { /* found the nodal dof corresponding to the endpoint of the edge */ 8293ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " corner found %" PetscInt_FMT "\n", jj[k])); 8309566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, jj[k])); 831a13144ffSStefano Zampini } else { 8323ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " no corners found\n")); 833a13144ffSStefano Zampini } 834a13144ffSStefano Zampini } 835a13144ffSStefano Zampini } 836a13144ffSStefano Zampini } 8379566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 838a13144ffSStefano Zampini } 8399566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 8409566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lG, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 8419566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btb)); 842a13144ffSStefano Zampini 843a13144ffSStefano Zampini /* Reset marked primal dofs */ 8449566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(primals, &cum)); 8459566063dSJacob Faibussowitsch PetscCall(ISGetIndices(primals, &idxs)); 846a13144ffSStefano Zampini for (i = 0; i < cum; i++) marks[idxs[i]] = 0; 8479566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(primals, &idxs)); 848a13144ffSStefano Zampini 8490569b399SStefano Zampini /* Now use the initial lG */ 8509566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lG)); 8519566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGt)); 8520569b399SStefano Zampini lG = lGinit; 8539566063dSJacob Faibussowitsch PetscCall(MatTranspose(lG, MAT_INITIAL_MATRIX, &lGt)); 8540569b399SStefano Zampini 855a13144ffSStefano Zampini /* Compute extended cols indices */ 8569566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(nv, &btvc)); 8579566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(nee, &bter)); 8589566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lG, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 8599566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetMaxRowNonzeros(lG, &i)); 860a13144ffSStefano Zampini i *= maxsize; 8619566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nee, &extcols)); 8629566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(i, &extrow, i, &gidxs)); 863a13144ffSStefano Zampini eerr = PETSC_FALSE; 864a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 865b03ebc13SStefano Zampini PetscInt size, found = 0; 866a13144ffSStefano Zampini 867a13144ffSStefano Zampini cum = 0; 8689566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 8691e0482f5SStefano Zampini if (!size && nedfieldlocal) continue; 87063a3b9bcSJacob Faibussowitsch PetscCheck(size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected zero sized edge %" PetscInt_FMT, i); 8719566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 8729566063dSJacob Faibussowitsch PetscCall(PetscBTMemzero(nv, btvc)); 873a13144ffSStefano Zampini for (j = 0; j < size; j++) { 874a13144ffSStefano Zampini PetscInt k, ee = idxs[j]; 875b03ebc13SStefano Zampini for (k = ii[ee]; k < ii[ee + 1]; k++) { 876b03ebc13SStefano Zampini PetscInt vv = jj[k]; 877b03ebc13SStefano Zampini if (!PetscBTLookup(btv, vv)) extrow[cum++] = vv; 878b03ebc13SStefano Zampini else if (!PetscBTLookupSet(btvc, vv)) found++; 879b03ebc13SStefano Zampini } 880a13144ffSStefano Zampini } 8819566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 8829566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&cum, extrow)); 8839566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(vl2g, cum, extrow, gidxs)); 8849566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(cum, gidxs, extrow)); 8859566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cum, extrow, PETSC_COPY_VALUES, &extcols[i])); 886a13144ffSStefano Zampini /* it may happen that endpoints are not defined at this point 887a13144ffSStefano Zampini if it is the case, mark this edge for a second pass */ 888b03ebc13SStefano Zampini if (cum != size - 1 || found != 2) { 8899566063dSJacob Faibussowitsch PetscCall(PetscBTSet(bter, i)); 890a13144ffSStefano Zampini if (print) { 8919566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)eedges[i], "error_edge")); 8929566063dSJacob Faibussowitsch PetscCall(ISView(eedges[i], NULL)); 8939566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)extcols[i], "error_extcol")); 8949566063dSJacob Faibussowitsch PetscCall(ISView(extcols[i], NULL)); 895a13144ffSStefano Zampini } 896a13144ffSStefano Zampini eerr = PETSC_TRUE; 897a13144ffSStefano Zampini } 898a13144ffSStefano Zampini } 89928b400f6SJacob Faibussowitsch /* PetscCheck(!eerr,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL FIRST PASS"); */ 9001c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&eerr, &done, 1, MPIU_BOOL, MPI_LOR, comm)); 901a13144ffSStefano Zampini if (done) { 902a13144ffSStefano Zampini PetscInt *newprimals; 903a13144ffSStefano Zampini 9049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ne, &newprimals)); 9059566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(primals, &cum)); 9069566063dSJacob Faibussowitsch PetscCall(ISGetIndices(primals, &idxs)); 9079566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(newprimals, idxs, cum)); 9089566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(primals, &idxs)); 9099566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 9103ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, "DOING SECOND PASS (eerr %s)\n", PetscBools[eerr])); 911a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 912b03ebc13SStefano Zampini PetscBool has_candidates = PETSC_FALSE; 913b03ebc13SStefano Zampini if (PetscBTLookup(bter, i)) { 914a13144ffSStefano Zampini PetscInt size, mark = i + 1; 915a13144ffSStefano Zampini 9169566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 9179566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 918c2151214SStefano Zampini /* for (j=0;j<size;j++) newprimals[cum++] = idxs[j]; */ 919a13144ffSStefano Zampini for (j = 0; j < size; j++) { 920a13144ffSStefano Zampini PetscInt k, ee = idxs[j]; 9213ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, "Inspecting edge dof %" PetscInt_FMT " [%" PetscInt_FMT " %" PetscInt_FMT ")\n", ee, ii[ee], ii[ee + 1])); 922a13144ffSStefano Zampini for (k = ii[ee]; k < ii[ee + 1]; k++) { 923a13144ffSStefano Zampini /* set all candidates located on the edge as corners */ 924a13144ffSStefano Zampini if (PetscBTLookup(btvcand, jj[k])) { 925a13144ffSStefano Zampini PetscInt k2, vv = jj[k]; 926b03ebc13SStefano Zampini has_candidates = PETSC_TRUE; 9273ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Candidate set to vertex %" PetscInt_FMT "\n", vv)); 9289566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, vv)); 929a13144ffSStefano Zampini /* set all edge dofs connected to candidate as primals */ 930a13144ffSStefano Zampini for (k2 = iit[vv]; k2 < iit[vv + 1]; k2++) { 931a13144ffSStefano Zampini if (marks[jjt[k2]] == mark) { 932a13144ffSStefano Zampini PetscInt k3, ee2 = jjt[k2]; 9333ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Connected edge dof set to primal %" PetscInt_FMT "\n", ee2)); 934a13144ffSStefano Zampini newprimals[cum++] = ee2; 935a13144ffSStefano Zampini /* finally set the new corners */ 936a13144ffSStefano Zampini for (k3 = ii[ee2]; k3 < ii[ee2 + 1]; k3++) { 9373ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Connected nodal dof set to vertex %" PetscInt_FMT "\n", jj[k3])); 9389566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, jj[k3])); 939a13144ffSStefano Zampini } 940a13144ffSStefano Zampini } 941a13144ffSStefano Zampini } 942b03ebc13SStefano Zampini } else { 9433ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Not a candidate vertex %" PetscInt_FMT "\n", jj[k])); 944a13144ffSStefano Zampini } 945a13144ffSStefano Zampini } 946a13144ffSStefano Zampini } 947b03ebc13SStefano Zampini if (!has_candidates) { /* circular edge */ 948b03ebc13SStefano Zampini PetscInt k, ee = idxs[0], *tmarks; 949b03ebc13SStefano Zampini 9509566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(ne, &tmarks)); 9513ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Circular edge %" PetscInt_FMT "\n", i)); 952b03ebc13SStefano Zampini for (k = ii[ee]; k < ii[ee + 1]; k++) { 953b03ebc13SStefano Zampini PetscInt k2; 9543ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Set to corner %" PetscInt_FMT "\n", jj[k])); 9559566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, jj[k])); 956b03ebc13SStefano Zampini for (k2 = iit[jj[k]]; k2 < iit[jj[k] + 1]; k2++) tmarks[jjt[k2]]++; 957b03ebc13SStefano Zampini } 958b03ebc13SStefano Zampini for (j = 0; j < size; j++) { 959b03ebc13SStefano Zampini if (tmarks[idxs[j]] > 1) { 9603ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Edge dof set to primal %" PetscInt_FMT "\n", idxs[j])); 961b03ebc13SStefano Zampini newprimals[cum++] = idxs[j]; 962b03ebc13SStefano Zampini } 963b03ebc13SStefano Zampini } 9649566063dSJacob Faibussowitsch PetscCall(PetscFree(tmarks)); 965b03ebc13SStefano Zampini } 9669566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 967a13144ffSStefano Zampini } 9689566063dSJacob Faibussowitsch PetscCall(ISDestroy(&extcols[i])); 969a13144ffSStefano Zampini } 9709566063dSJacob Faibussowitsch PetscCall(PetscFree(extcols)); 9719566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 9729566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&cum, newprimals)); 973c2151214SStefano Zampini if (fl2g) { 9749566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(fl2g, cum, newprimals, newprimals)); 9759566063dSJacob Faibussowitsch PetscCall(ISDestroy(&primals)); 97648a46eb9SPierre Jolivet for (i = 0; i < nee; i++) PetscCall(ISDestroy(&eedges[i])); 9779566063dSJacob Faibussowitsch PetscCall(PetscFree(eedges)); 978c2151214SStefano Zampini } 9799566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, NULL, NULL, &nee, &alleedges, &allprimals)); 9809566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, cum, newprimals, PETSC_COPY_VALUES, &primals)); 9819566063dSJacob Faibussowitsch PetscCall(PetscFree(newprimals)); 9829566063dSJacob Faibussowitsch PetscCall(PCBDDCSetPrimalVerticesLocalIS(pc, primals)); 9839566063dSJacob Faibussowitsch PetscCall(ISDestroy(&primals)); 9849566063dSJacob Faibussowitsch PetscCall(PCBDDCAnalyzeInterface(pc)); 985213b8bfaSStefano Zampini pcbddc->mat_graph->twodim = PETSC_FALSE; 9869566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, NULL, NULL, &nee, &alleedges, &allprimals)); 987c2151214SStefano Zampini if (fl2g) { 9889566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(fl2g, IS_GTOLM_DROP, allprimals, &primals)); 9899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nee, &eedges)); 99048a46eb9SPierre Jolivet for (i = 0; i < nee; i++) PetscCall(ISGlobalToLocalMappingApplyIS(fl2g, IS_GTOLM_DROP, alleedges[i], &eedges[i])); 991c2151214SStefano Zampini } else { 992c2151214SStefano Zampini eedges = alleedges; 993c2151214SStefano Zampini primals = allprimals; 994c2151214SStefano Zampini } 9959566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nee, &extcols)); 996a13144ffSStefano Zampini 997a13144ffSStefano Zampini /* Mark again */ 9989566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(marks, ne)); 999a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 1000a13144ffSStefano Zampini PetscInt size, mark = i + 1; 1001a13144ffSStefano Zampini 10029566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 10039566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 1004a13144ffSStefano Zampini for (j = 0; j < size; j++) marks[idxs[j]] = mark; 10059566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 1006a13144ffSStefano Zampini } 1007a13144ffSStefano Zampini if (print) { 10089566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)primals, "obtained_primal_dofs_secondpass")); 10099566063dSJacob Faibussowitsch PetscCall(ISView(primals, NULL)); 1010a13144ffSStefano Zampini } 1011a13144ffSStefano Zampini 1012a13144ffSStefano Zampini /* Recompute extended cols */ 1013a13144ffSStefano Zampini eerr = PETSC_FALSE; 1014a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 1015a13144ffSStefano Zampini PetscInt size; 1016a13144ffSStefano Zampini 1017a13144ffSStefano Zampini cum = 0; 10189566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 10191e0482f5SStefano Zampini if (!size && nedfieldlocal) continue; 102063a3b9bcSJacob Faibussowitsch PetscCheck(size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected zero sized edge %" PetscInt_FMT, i); 10219566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 1022a13144ffSStefano Zampini for (j = 0; j < size; j++) { 1023a13144ffSStefano Zampini PetscInt k, ee = idxs[j]; 10249371c9d4SSatish Balay for (k = ii[ee]; k < ii[ee + 1]; k++) 10259371c9d4SSatish Balay if (!PetscBTLookup(btv, jj[k])) extrow[cum++] = jj[k]; 1026a13144ffSStefano Zampini } 10279566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 10289566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&cum, extrow)); 10299566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(vl2g, cum, extrow, gidxs)); 10309566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(cum, gidxs, extrow)); 10319566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cum, extrow, PETSC_COPY_VALUES, &extcols[i])); 1032a13144ffSStefano Zampini if (cum != size - 1) { 1033a13144ffSStefano Zampini if (print) { 10349566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)eedges[i], "error_edge_secondpass")); 10359566063dSJacob Faibussowitsch PetscCall(ISView(eedges[i], NULL)); 10369566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)extcols[i], "error_extcol_secondpass")); 10379566063dSJacob Faibussowitsch PetscCall(ISView(extcols[i], NULL)); 1038a13144ffSStefano Zampini } 1039a13144ffSStefano Zampini eerr = PETSC_TRUE; 1040a13144ffSStefano Zampini } 1041a13144ffSStefano Zampini } 1042a13144ffSStefano Zampini } 10439566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lG, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 10449566063dSJacob Faibussowitsch PetscCall(PetscFree2(extrow, gidxs)); 10459566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&bter)); 10469566063dSJacob Faibussowitsch if (print) PetscCall(PCBDDCGraphASCIIView(pcbddc->mat_graph, 5, PETSC_VIEWER_STDOUT_SELF)); 1047a13144ffSStefano Zampini /* an error should not occur at this point */ 104828b400f6SJacob Faibussowitsch PetscCheck(!eerr, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected SIZE OF EDGE > EXTCOL SECOND PASS"); 1049a13144ffSStefano Zampini 10504e64d54eSstefano_zampini /* Check the number of endpoints */ 10519566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lG, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 10529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2 * nee, &corners)); 10539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nee, &cedges)); 10544e64d54eSstefano_zampini for (i = 0; i < nee; i++) { 1055b03ebc13SStefano Zampini PetscInt size, found = 0, gc[2]; 10564e64d54eSstefano_zampini 1057b03ebc13SStefano Zampini /* init with defaults */ 1058b03ebc13SStefano Zampini cedges[i] = corners[i * 2] = corners[i * 2 + 1] = -1; 10599566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 10601e0482f5SStefano Zampini if (!size && nedfieldlocal) continue; 106163a3b9bcSJacob Faibussowitsch PetscCheck(size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected zero sized edge %" PetscInt_FMT, i); 10629566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 10639566063dSJacob Faibussowitsch PetscCall(PetscBTMemzero(nv, btvc)); 10644e64d54eSstefano_zampini for (j = 0; j < size; j++) { 10654e64d54eSstefano_zampini PetscInt k, ee = idxs[j]; 10664e64d54eSstefano_zampini for (k = ii[ee]; k < ii[ee + 1]; k++) { 10674e64d54eSstefano_zampini PetscInt vv = jj[k]; 10684e64d54eSstefano_zampini if (PetscBTLookup(btv, vv) && !PetscBTLookupSet(btvc, vv)) { 106963a3b9bcSJacob Faibussowitsch PetscCheck(found != 2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Found more then two corners for edge %" PetscInt_FMT, i); 1070b03ebc13SStefano Zampini corners[i * 2 + found++] = vv; 10714e64d54eSstefano_zampini } 10724e64d54eSstefano_zampini } 10734e64d54eSstefano_zampini } 1074b03ebc13SStefano Zampini if (found != 2) { 1075b03ebc13SStefano Zampini PetscInt e; 1076b03ebc13SStefano Zampini if (fl2g) { 10779566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(fl2g, 1, idxs, &e)); 1078b03ebc13SStefano Zampini } else { 1079b03ebc13SStefano Zampini e = idxs[0]; 1080b03ebc13SStefano Zampini } 108163a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Found %" PetscInt_FMT " corners for edge %" PetscInt_FMT " (astart %" PetscInt_FMT ", estart %" PetscInt_FMT ")", found, i, e, idxs[0]); 1082b03ebc13SStefano Zampini } 1083eee23b56SStefano Zampini 1084eee23b56SStefano Zampini /* get primal dof index on this coarse edge */ 10859566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(vl2g, 2, corners + 2 * i, gc)); 1086b03ebc13SStefano Zampini if (gc[0] > gc[1]) { 1087b03ebc13SStefano Zampini PetscInt swap = corners[2 * i]; 1088b03ebc13SStefano Zampini corners[2 * i] = corners[2 * i + 1]; 1089b03ebc13SStefano Zampini corners[2 * i + 1] = swap; 1090b03ebc13SStefano Zampini } 1091eee23b56SStefano Zampini cedges[i] = idxs[size - 1]; 10929566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 10933ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, "EDGE %" PetscInt_FMT ": ce %" PetscInt_FMT ", corners (%" PetscInt_FMT ",%" PetscInt_FMT ")\n", i, cedges[i], corners[2 * i], corners[2 * i + 1])); 10944e64d54eSstefano_zampini } 10959566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lG, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 10969566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btvc)); 10974e64d54eSstefano_zampini 109876bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 1099a13144ffSStefano Zampini /* Inspects columns of lG (rows of lGt) and make sure the change of basis will 1100a13144ffSStefano Zampini not interfere with neighbouring coarse edges */ 11019566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nee + 1, &emarks)); 11029566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 1103a13144ffSStefano Zampini for (i = 0; i < nv; i++) { 1104a13144ffSStefano Zampini PetscInt emax = 0, eemax = 0; 1105a13144ffSStefano Zampini 1106a13144ffSStefano Zampini if (ii[i + 1] == ii[i] || PetscBTLookup(btv, i)) continue; 11079566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(emarks, nee + 1)); 1108a13144ffSStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) emarks[marks[jj[j]]]++; 1109a13144ffSStefano Zampini for (j = 1; j < nee + 1; j++) { 1110a13144ffSStefano Zampini if (emax < emarks[j]) { 1111a13144ffSStefano Zampini emax = emarks[j]; 1112a13144ffSStefano Zampini eemax = j; 1113a13144ffSStefano Zampini } 1114a13144ffSStefano Zampini } 1115a13144ffSStefano Zampini /* not relevant for edges */ 1116a13144ffSStefano Zampini if (!eemax) continue; 1117a13144ffSStefano Zampini 1118a13144ffSStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 11197a46b595SBarry Smith PetscCheck(!marks[jj[j]] || marks[jj[j]] == eemax, PETSC_COMM_SELF, PETSC_ERR_SUP, "Found 2 coarse edges (id %" PetscInt_FMT " and %" PetscInt_FMT ") connected through the %" PetscInt_FMT " nodal dof at edge dof %" PetscInt_FMT, marks[jj[j]] - 1, eemax, i, jj[j]); 1120a13144ffSStefano Zampini } 1121a13144ffSStefano Zampini } 11229566063dSJacob Faibussowitsch PetscCall(PetscFree(emarks)); 11239566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 112476bd3646SJed Brown } 1125a13144ffSStefano Zampini 1126a13144ffSStefano Zampini /* Compute extended rows indices for edge blocks of the change of basis */ 11279566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 11289566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetMaxRowNonzeros(lGt, &extmem)); 1129a13144ffSStefano Zampini extmem *= maxsize; 11309566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(extmem * nee, &extrow)); 11319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nee, &extrows)); 11329566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nee, &extrowcum)); 1133a13144ffSStefano Zampini for (i = 0; i < nv; i++) { 1134a13144ffSStefano Zampini PetscInt mark = 0, size, start; 1135213b8bfaSStefano Zampini 1136a13144ffSStefano Zampini if (ii[i + 1] == ii[i] || PetscBTLookup(btv, i)) continue; 1137a13144ffSStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) 11389371c9d4SSatish Balay if (marks[jj[j]] && !mark) mark = marks[jj[j]]; 1139a13144ffSStefano Zampini 1140a13144ffSStefano Zampini /* not relevant */ 1141a13144ffSStefano Zampini if (!mark) continue; 1142a13144ffSStefano Zampini 1143a13144ffSStefano Zampini /* import extended row */ 1144a13144ffSStefano Zampini mark--; 1145a13144ffSStefano Zampini start = mark * extmem + extrowcum[mark]; 1146a13144ffSStefano Zampini size = ii[i + 1] - ii[i]; 114763a3b9bcSJacob Faibussowitsch PetscCheck(extrowcum[mark] + size <= extmem, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Not enough memory allocated %" PetscInt_FMT " > %" PetscInt_FMT, extrowcum[mark] + size, extmem); 11489566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(extrow + start, jj + ii[i], size)); 1149a13144ffSStefano Zampini extrowcum[mark] += size; 1150a13144ffSStefano Zampini } 11519566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 11529566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGt)); 11539566063dSJacob Faibussowitsch PetscCall(PetscFree(marks)); 1154213b8bfaSStefano Zampini 1155213b8bfaSStefano Zampini /* Compress extrows */ 1156a13144ffSStefano Zampini cum = 0; 1157a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 1158a13144ffSStefano Zampini PetscInt size = extrowcum[i], *start = extrow + i * extmem; 11599566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&size, start)); 11609566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, size, start, PETSC_USE_POINTER, &extrows[i])); 1161a13144ffSStefano Zampini cum = PetscMax(cum, size); 1162a13144ffSStefano Zampini } 11639566063dSJacob Faibussowitsch PetscCall(PetscFree(extrowcum)); 11649566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btv)); 11659566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btvcand)); 1166a13144ffSStefano Zampini 1167a13144ffSStefano Zampini /* Workspace for lapack inner calls and VecSetValues */ 11689566063dSJacob Faibussowitsch PetscCall(PetscMalloc2((5 + cum + maxsize) * maxsize, &work, maxsize, &rwork)); 1169a13144ffSStefano Zampini 1170a13144ffSStefano Zampini /* Create change of basis matrix (preallocation can be improved) */ 11719566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &T)); 1172d0609cedSBarry Smith PetscCall(MatSetSizes(T, pc->pmat->rmap->n, pc->pmat->rmap->n, pc->pmat->rmap->N, pc->pmat->rmap->N)); 11739566063dSJacob Faibussowitsch PetscCall(MatSetType(T, MATAIJ)); 11749566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(T, 10, NULL)); 11759566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(T, 10, NULL, 10, NULL)); 11769566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(T, al2g, al2g)); 11779566063dSJacob Faibussowitsch PetscCall(MatSetOption(T, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 11789566063dSJacob Faibussowitsch PetscCall(MatSetOption(T, MAT_ROW_ORIENTED, PETSC_FALSE)); 11799566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&al2g)); 1180a13144ffSStefano Zampini 1181a13144ffSStefano Zampini /* Defaults to identity */ 11829566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(pc->pmat, &tvec, NULL)); 11839566063dSJacob Faibussowitsch PetscCall(VecSet(tvec, 1.0)); 11849566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(T, tvec, INSERT_VALUES)); 11859566063dSJacob Faibussowitsch PetscCall(VecDestroy(&tvec)); 1186a13144ffSStefano Zampini 11871e0482f5SStefano Zampini /* Create discrete gradient for the coarser level if needed */ 11889566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->nedcG)); 11899566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->nedclocal)); 11901e0482f5SStefano Zampini if (pcbddc->current_level < pcbddc->max_levels) { 11911e0482f5SStefano Zampini ISLocalToGlobalMapping cel2g, cvl2g; 11921e0482f5SStefano Zampini IS wis, gwis; 11931e0482f5SStefano Zampini PetscInt cnv, cne; 11941e0482f5SStefano Zampini 11959566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, nee, cedges, PETSC_COPY_VALUES, &wis)); 11961e0482f5SStefano Zampini if (fl2g) { 11979566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(fl2g, wis, &pcbddc->nedclocal)); 11981e0482f5SStefano Zampini } else { 11999566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)wis)); 12001e0482f5SStefano Zampini pcbddc->nedclocal = wis; 12011e0482f5SStefano Zampini } 12029566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(el2g, wis, &gwis)); 12039566063dSJacob Faibussowitsch PetscCall(ISDestroy(&wis)); 12049566063dSJacob Faibussowitsch PetscCall(ISRenumber(gwis, NULL, &cne, &wis)); 12059566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(wis, &cel2g)); 12069566063dSJacob Faibussowitsch PetscCall(ISDestroy(&wis)); 12079566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gwis)); 12081e0482f5SStefano Zampini 12099566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, 2 * nee, corners, PETSC_USE_POINTER, &wis)); 12109566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(vl2g, wis, &gwis)); 12119566063dSJacob Faibussowitsch PetscCall(ISDestroy(&wis)); 12129566063dSJacob Faibussowitsch PetscCall(ISRenumber(gwis, NULL, &cnv, &wis)); 12139566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(wis, &cvl2g)); 12149566063dSJacob Faibussowitsch PetscCall(ISDestroy(&wis)); 12159566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gwis)); 12161e0482f5SStefano Zampini 12179566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &pcbddc->nedcG)); 12189566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->nedcG, PETSC_DECIDE, PETSC_DECIDE, cne, cnv)); 12199566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->nedcG, MATAIJ)); 12209566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(pcbddc->nedcG, 2, NULL)); 12219566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(pcbddc->nedcG, 2, NULL, 2, NULL)); 12229566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(pcbddc->nedcG, cel2g, cvl2g)); 12239566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cel2g)); 12249566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cvl2g)); 12251e0482f5SStefano Zampini } 12269566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&vl2g)); 12271e0482f5SStefano Zampini 12281e0482f5SStefano Zampini #if defined(PRINT_GDET) 12291e0482f5SStefano Zampini inc = 0; 12301e0482f5SStefano Zampini lev = pcbddc->current_level; 12311e0482f5SStefano Zampini #endif 1232213b8bfaSStefano Zampini 1233213b8bfaSStefano Zampini /* Insert values in the change of basis matrix */ 1234a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 1235a13144ffSStefano Zampini Mat Gins = NULL, GKins = NULL; 12361e0482f5SStefano Zampini IS cornersis = NULL; 12371e0482f5SStefano Zampini PetscScalar cvals[2]; 1238a13144ffSStefano Zampini 123948a46eb9SPierre Jolivet if (pcbddc->nedcG) PetscCall(ISCreateGeneral(PETSC_COMM_SELF, 2, corners + 2 * i, PETSC_USE_POINTER, &cornersis)); 12409566063dSJacob Faibussowitsch PetscCall(PCBDDCComputeNedelecChangeEdge(lG, eedges[i], extrows[i], extcols[i], cornersis, &Gins, &GKins, cvals, work, rwork)); 1241a13144ffSStefano Zampini if (Gins && GKins) { 12421683a169SBarry Smith const PetscScalar *data; 1243a13144ffSStefano Zampini const PetscInt *rows, *cols; 1244a13144ffSStefano Zampini PetscInt nrh, nch, nrc, ncc; 1245a13144ffSStefano Zampini 12469566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &cols)); 1247a13144ffSStefano Zampini /* H1 */ 12489566063dSJacob Faibussowitsch PetscCall(ISGetIndices(extrows[i], &rows)); 12499566063dSJacob Faibussowitsch PetscCall(MatGetSize(Gins, &nrh, &nch)); 12509566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(Gins, &data)); 12519566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(T, nrh, rows, nch, cols, data, INSERT_VALUES)); 12529566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(Gins, &data)); 12539566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(extrows[i], &rows)); 1254a13144ffSStefano Zampini /* complement */ 12559566063dSJacob Faibussowitsch PetscCall(MatGetSize(GKins, &nrc, &ncc)); 125663a3b9bcSJacob Faibussowitsch PetscCheck(ncc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Constant function has not been generated for coarse edge %" PetscInt_FMT, i); 125763a3b9bcSJacob Faibussowitsch PetscCheck(ncc + nch == nrc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "The sum of the number of columns of GKins %" PetscInt_FMT " and Gins %" PetscInt_FMT " does not match %" PetscInt_FMT " for coarse edge %" PetscInt_FMT, ncc, nch, nrc, i); 125863a3b9bcSJacob Faibussowitsch PetscCheck(ncc == 1 || !pcbddc->nedcG, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot generate the coarse discrete gradient for coarse edge %" PetscInt_FMT " with ncc %" PetscInt_FMT, i, ncc); 12599566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(GKins, &data)); 12609566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(T, nrc, cols, ncc, cols + nch, data, INSERT_VALUES)); 12619566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(GKins, &data)); 12621e0482f5SStefano Zampini 12631e0482f5SStefano Zampini /* coarse discrete gradient */ 12641e0482f5SStefano Zampini if (pcbddc->nedcG) { 12651e0482f5SStefano Zampini PetscInt cols[2]; 12661e0482f5SStefano Zampini 12671e0482f5SStefano Zampini cols[0] = 2 * i; 12681e0482f5SStefano Zampini cols[1] = 2 * i + 1; 12699566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(pcbddc->nedcG, 1, &i, 2, cols, cvals, INSERT_VALUES)); 12701e0482f5SStefano Zampini } 12719566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &cols)); 1272a13144ffSStefano Zampini } 12739566063dSJacob Faibussowitsch PetscCall(ISDestroy(&extrows[i])); 12749566063dSJacob Faibussowitsch PetscCall(ISDestroy(&extcols[i])); 12759566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cornersis)); 12769566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Gins)); 12779566063dSJacob Faibussowitsch PetscCall(MatDestroy(&GKins)); 1278a13144ffSStefano Zampini } 12799566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&el2g)); 1280a13144ffSStefano Zampini 1281a13144ffSStefano Zampini /* Start assembling */ 12829566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(T, MAT_FINAL_ASSEMBLY)); 12831baa6e33SBarry Smith if (pcbddc->nedcG) PetscCall(MatAssemblyBegin(pcbddc->nedcG, MAT_FINAL_ASSEMBLY)); 1284a13144ffSStefano Zampini 1285a13144ffSStefano Zampini /* Free */ 1286c2151214SStefano Zampini if (fl2g) { 12879566063dSJacob Faibussowitsch PetscCall(ISDestroy(&primals)); 128848a46eb9SPierre Jolivet for (i = 0; i < nee; i++) PetscCall(ISDestroy(&eedges[i])); 12899566063dSJacob Faibussowitsch PetscCall(PetscFree(eedges)); 1290c2151214SStefano Zampini } 1291eee23b56SStefano Zampini 1292eee23b56SStefano Zampini /* hack mat_graph with primal dofs on the coarse edges */ 1293eee23b56SStefano Zampini { 1294eee23b56SStefano Zampini PCBDDCGraph graph = pcbddc->mat_graph; 1295eee23b56SStefano Zampini PetscInt *oqueue = graph->queue; 1296eee23b56SStefano Zampini PetscInt *ocptr = graph->cptr; 1297eee23b56SStefano Zampini PetscInt ncc, *idxs; 1298eee23b56SStefano Zampini 1299eee23b56SStefano Zampini /* find first primal edge */ 1300eee23b56SStefano Zampini if (pcbddc->nedclocal) { 13019566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->nedclocal, (const PetscInt **)&idxs)); 1302eee23b56SStefano Zampini } else { 13031baa6e33SBarry Smith if (fl2g) PetscCall(ISLocalToGlobalMappingApply(fl2g, nee, cedges, cedges)); 1304eee23b56SStefano Zampini idxs = cedges; 1305eee23b56SStefano Zampini } 1306eee23b56SStefano Zampini cum = 0; 1307eee23b56SStefano Zampini while (cum < nee && cedges[cum] < 0) cum++; 1308eee23b56SStefano Zampini 1309eee23b56SStefano Zampini /* adapt connected components */ 13109566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(graph->nvtxs + 1, &graph->cptr, ocptr[graph->ncc], &graph->queue)); 1311eee23b56SStefano Zampini graph->cptr[0] = 0; 1312eee23b56SStefano Zampini for (i = 0, ncc = 0; i < graph->ncc; i++) { 1313eee23b56SStefano Zampini PetscInt lc = ocptr[i + 1] - ocptr[i]; 1314eee23b56SStefano Zampini if (cum != nee && oqueue[ocptr[i + 1] - 1] == cedges[cum]) { /* this cc has a primal dof */ 1315eee23b56SStefano Zampini graph->cptr[ncc + 1] = graph->cptr[ncc] + 1; 1316eee23b56SStefano Zampini graph->queue[graph->cptr[ncc]] = cedges[cum]; 1317eee23b56SStefano Zampini ncc++; 1318eee23b56SStefano Zampini lc--; 1319eee23b56SStefano Zampini cum++; 1320eee23b56SStefano Zampini while (cum < nee && cedges[cum] < 0) cum++; 1321eee23b56SStefano Zampini } 1322eee23b56SStefano Zampini graph->cptr[ncc + 1] = graph->cptr[ncc] + lc; 1323eee23b56SStefano Zampini for (j = 0; j < lc; j++) graph->queue[graph->cptr[ncc] + j] = oqueue[ocptr[i] + j]; 1324eee23b56SStefano Zampini ncc++; 1325eee23b56SStefano Zampini } 1326eee23b56SStefano Zampini graph->ncc = ncc; 132748a46eb9SPierre Jolivet if (pcbddc->nedclocal) PetscCall(ISRestoreIndices(pcbddc->nedclocal, (const PetscInt **)&idxs)); 13289566063dSJacob Faibussowitsch PetscCall(PetscFree2(ocptr, oqueue)); 1329eee23b56SStefano Zampini } 13309566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&fl2g)); 13319566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, NULL, NULL, &nee, &alleedges, &allprimals)); 13329566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphResetCSR(pcbddc->mat_graph)); 13339566063dSJacob Faibussowitsch PetscCall(MatDestroy(&conn)); 1334eee23b56SStefano Zampini 13359566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nedfieldlocal)); 13369566063dSJacob Faibussowitsch PetscCall(PetscFree(extrow)); 13379566063dSJacob Faibussowitsch PetscCall(PetscFree2(work, rwork)); 13389566063dSJacob Faibussowitsch PetscCall(PetscFree(corners)); 13399566063dSJacob Faibussowitsch PetscCall(PetscFree(cedges)); 13409566063dSJacob Faibussowitsch PetscCall(PetscFree(extrows)); 13419566063dSJacob Faibussowitsch PetscCall(PetscFree(extcols)); 13429566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lG)); 1343a13144ffSStefano Zampini 1344a13144ffSStefano Zampini /* Complete assembling */ 13459566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(T, MAT_FINAL_ASSEMBLY)); 13461e0482f5SStefano Zampini if (pcbddc->nedcG) { 13479566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->nedcG, MAT_FINAL_ASSEMBLY)); 13481e0482f5SStefano Zampini #if 0 13499566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)pcbddc->nedcG,"coarse_G")); 13509566063dSJacob Faibussowitsch PetscCall(MatView(pcbddc->nedcG,NULL)); 13511e0482f5SStefano Zampini #endif 13521e0482f5SStefano Zampini } 1353a13144ffSStefano Zampini 1354a13144ffSStefano Zampini /* set change of basis */ 13559566063dSJacob Faibussowitsch PetscCall(PCBDDCSetChangeOfBasisMat(pc, T, singular)); 13569566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 1357a13144ffSStefano Zampini 13583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1359a13144ffSStefano Zampini } 1360a13144ffSStefano Zampini 1361d8203eabSStefano Zampini /* the near-null space of BDDC carries information on quadrature weights, 1362d8203eabSStefano Zampini and these can be collinear -> so cheat with MatNullSpaceCreate 1363d8203eabSStefano Zampini and create a suitable set of basis vectors first */ 1364d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCNullSpaceCreate(MPI_Comm comm, PetscBool has_const, PetscInt nvecs, Vec quad_vecs[], MatNullSpace *nnsp) 1365d71ae5a4SJacob Faibussowitsch { 1366d8203eabSStefano Zampini PetscInt i; 1367d8203eabSStefano Zampini 1368d8203eabSStefano Zampini PetscFunctionBegin; 1369d8203eabSStefano Zampini for (i = 0; i < nvecs; i++) { 1370d8203eabSStefano Zampini PetscInt first, last; 1371d8203eabSStefano Zampini 13729566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(quad_vecs[i], &first, &last)); 13737827d75bSBarry Smith PetscCheck(last - first >= 2 * nvecs || !has_const, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented"); 1374d8203eabSStefano Zampini if (i >= first && i < last) { 1375d8203eabSStefano Zampini PetscScalar *data; 13769566063dSJacob Faibussowitsch PetscCall(VecGetArray(quad_vecs[i], &data)); 1377d8203eabSStefano Zampini if (!has_const) { 1378d8203eabSStefano Zampini data[i - first] = 1.; 1379d8203eabSStefano Zampini } else { 138086fa73c5SStefano Zampini data[2 * i - first] = 1. / PetscSqrtReal(2.); 138186fa73c5SStefano Zampini data[2 * i - first + 1] = -1. / PetscSqrtReal(2.); 1382d8203eabSStefano Zampini } 13839566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(quad_vecs[i], &data)); 1384d8203eabSStefano Zampini } 13859566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)quad_vecs[i])); 1386d8203eabSStefano Zampini } 13879566063dSJacob Faibussowitsch PetscCall(MatNullSpaceCreate(comm, has_const, nvecs, quad_vecs, nnsp)); 1388d8203eabSStefano Zampini for (i = 0; i < nvecs; i++) { /* reset vectors */ 1389d8203eabSStefano Zampini PetscInt first, last; 13909566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(quad_vecs[i])); 13919566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(quad_vecs[i], &first, &last)); 1392d8203eabSStefano Zampini if (i >= first && i < last) { 1393d8203eabSStefano Zampini PetscScalar *data; 13949566063dSJacob Faibussowitsch PetscCall(VecGetArray(quad_vecs[i], &data)); 1395d8203eabSStefano Zampini if (!has_const) { 1396d8203eabSStefano Zampini data[i - first] = 0.; 1397d8203eabSStefano Zampini } else { 139886fa73c5SStefano Zampini data[2 * i - first] = 0.; 139986fa73c5SStefano Zampini data[2 * i - first + 1] = 0.; 1400d8203eabSStefano Zampini } 14019566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(quad_vecs[i], &data)); 1402d8203eabSStefano Zampini } 14039566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)quad_vecs[i])); 14049566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(quad_vecs[i])); 1405d8203eabSStefano Zampini } 14063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1407d8203eabSStefano Zampini } 1408d8203eabSStefano Zampini 1409d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, PetscBool transpose, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp) 1410d71ae5a4SJacob Faibussowitsch { 1411a198735bSStefano Zampini Mat loc_divudotp; 1412fa23a32eSStefano Zampini Vec p, v, vins, quad_vec, *quad_vecs; 14138ae0ca82SStefano Zampini ISLocalToGlobalMapping map; 1414669cc0f4SStefano Zampini PetscScalar *vals; 1415669cc0f4SStefano Zampini const PetscScalar *array; 14160f04eeffSStefano Zampini PetscInt i, maxneighs = 0, maxsize, *gidxs; 1417a040e873SStefano Zampini PetscInt n_neigh, *neigh, *n_shared, **shared; 14181ae86dd6SStefano Zampini PetscMPIInt rank; 1419669cc0f4SStefano Zampini 1420669cc0f4SStefano Zampini PetscFunctionBegin; 14219566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetInfo(graph->l2gmap, &n_neigh, &neigh, &n_shared, &shared)); 14220f04eeffSStefano Zampini for (i = 0; i < n_neigh; i++) maxneighs = PetscMax(graph->count[shared[i][0]] + 1, maxneighs); 14231c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(MPI_IN_PLACE, &maxneighs, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)A))); 14248037d520SStefano Zampini if (!maxneighs) { 14259566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreInfo(graph->l2gmap, &n_neigh, &neigh, &n_shared, &shared)); 14268037d520SStefano Zampini *nnsp = NULL; 14273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1428669cc0f4SStefano Zampini } 1429669cc0f4SStefano Zampini maxsize = 0; 1430a040e873SStefano Zampini for (i = 0; i < n_neigh; i++) maxsize = PetscMax(n_shared[i], maxsize); 14319566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(maxsize, &gidxs, maxsize, &vals)); 1432669cc0f4SStefano Zampini /* create vectors to hold quadrature weights */ 14339566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, &quad_vec, NULL)); 14348ae0ca82SStefano Zampini if (!transpose) { 14359566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(A, &map, NULL)); 14368ae0ca82SStefano Zampini } else { 14379566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(A, NULL, &map)); 14388ae0ca82SStefano Zampini } 14399566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(quad_vec, maxneighs, &quad_vecs)); 14409566063dSJacob Faibussowitsch PetscCall(VecDestroy(&quad_vec)); 14419566063dSJacob Faibussowitsch PetscCall(PCBDDCNullSpaceCreate(PetscObjectComm((PetscObject)A), PETSC_FALSE, maxneighs, quad_vecs, nnsp)); 144248a46eb9SPierre Jolivet for (i = 0; i < maxneighs; i++) PetscCall(VecLockReadPop(quad_vecs[i])); 1443d8203eabSStefano Zampini 1444669cc0f4SStefano Zampini /* compute local quad vec */ 14459566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(divudotp, &loc_divudotp)); 14468ae0ca82SStefano Zampini if (!transpose) { 14479566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(loc_divudotp, &v, &p)); 14488ae0ca82SStefano Zampini } else { 14499566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(loc_divudotp, &p, &v)); 14508ae0ca82SStefano Zampini } 14519566063dSJacob Faibussowitsch PetscCall(VecSet(p, 1.)); 14528ae0ca82SStefano Zampini if (!transpose) { 14539566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(loc_divudotp, p, v)); 14548ae0ca82SStefano Zampini } else { 14559566063dSJacob Faibussowitsch PetscCall(MatMult(loc_divudotp, p, v)); 14568ae0ca82SStefano Zampini } 1457fa23a32eSStefano Zampini if (vl2l) { 1458187c917aSStefano Zampini Mat lA; 1459187c917aSStefano Zampini VecScatter sc; 1460187c917aSStefano Zampini 14619566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A, &lA)); 14629566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(lA, &vins, NULL)); 14639566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(v, NULL, vins, vl2l, &sc)); 14649566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sc, v, vins, INSERT_VALUES, SCATTER_FORWARD)); 14659566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sc, v, vins, INSERT_VALUES, SCATTER_FORWARD)); 14669566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sc)); 1467fa23a32eSStefano Zampini } else { 1468fa23a32eSStefano Zampini vins = v; 1469fa23a32eSStefano Zampini } 14709566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vins, &array)); 14719566063dSJacob Faibussowitsch PetscCall(VecDestroy(&p)); 14729a962809SStefano Zampini 14731ae86dd6SStefano Zampini /* insert in global quadrature vecs */ 14749566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 14750f04eeffSStefano Zampini for (i = 1; i < n_neigh; i++) { 1476669cc0f4SStefano Zampini const PetscInt *idxs; 1477669cc0f4SStefano Zampini PetscInt idx, nn, j; 1478669cc0f4SStefano Zampini 1479a040e873SStefano Zampini idxs = shared[i]; 1480a040e873SStefano Zampini nn = n_shared[i]; 1481669cc0f4SStefano Zampini for (j = 0; j < nn; j++) vals[j] = array[idxs[j]]; 14829566063dSJacob Faibussowitsch PetscCall(PetscFindInt(rank, graph->count[idxs[0]], graph->neighbours_set[idxs[0]], &idx)); 1483669cc0f4SStefano Zampini idx = -(idx + 1); 148463a3b9bcSJacob Faibussowitsch PetscCheck(idx >= 0 && idx < maxneighs, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid index %" PetscInt_FMT " not in [0,%" PetscInt_FMT ")", idx, maxneighs); 14859566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(map, nn, idxs, gidxs)); 14869566063dSJacob Faibussowitsch PetscCall(VecSetValues(quad_vecs[idx], nn, gidxs, vals, INSERT_VALUES)); 1487669cc0f4SStefano Zampini } 14889566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreInfo(graph->l2gmap, &n_neigh, &neigh, &n_shared, &shared)); 14899566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vins, &array)); 149048a46eb9SPierre Jolivet if (vl2l) PetscCall(VecDestroy(&vins)); 14919566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 14929566063dSJacob Faibussowitsch PetscCall(PetscFree2(gidxs, vals)); 1493669cc0f4SStefano Zampini 1494669cc0f4SStefano Zampini /* assemble near null space */ 149548a46eb9SPierre Jolivet for (i = 0; i < maxneighs; i++) PetscCall(VecAssemblyBegin(quad_vecs[i])); 1496669cc0f4SStefano Zampini for (i = 0; i < maxneighs; i++) { 14979566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(quad_vecs[i])); 14989566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(quad_vecs[i], NULL, "-pc_bddc_quad_vecs_view")); 14999566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(quad_vecs[i])); 1500669cc0f4SStefano Zampini } 15019566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(maxneighs, &quad_vecs)); 15023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1503669cc0f4SStefano Zampini } 1504669cc0f4SStefano Zampini 1505d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCAddPrimalVerticesLocalIS(PC pc, IS primalv) 1506d71ae5a4SJacob Faibussowitsch { 15077620a527SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 15087620a527SStefano Zampini 15097620a527SStefano Zampini PetscFunctionBegin; 15107620a527SStefano Zampini if (primalv) { 15117620a527SStefano Zampini if (pcbddc->user_primal_vertices_local) { 15127620a527SStefano Zampini IS list[2], newp; 15137620a527SStefano Zampini 15147620a527SStefano Zampini list[0] = primalv; 15157620a527SStefano Zampini list[1] = pcbddc->user_primal_vertices_local; 15169566063dSJacob Faibussowitsch PetscCall(ISConcatenate(PetscObjectComm((PetscObject)pc), 2, list, &newp)); 15179566063dSJacob Faibussowitsch PetscCall(ISSortRemoveDups(newp)); 15189566063dSJacob Faibussowitsch PetscCall(ISDestroy(&list[1])); 15197620a527SStefano Zampini pcbddc->user_primal_vertices_local = newp; 15207620a527SStefano Zampini } else { 15219566063dSJacob Faibussowitsch PetscCall(PCBDDCSetPrimalVerticesLocalIS(pc, primalv)); 15227620a527SStefano Zampini } 15237620a527SStefano Zampini } 15243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15257620a527SStefano Zampini } 1526669cc0f4SStefano Zampini 1527d71ae5a4SJacob Faibussowitsch static PetscErrorCode func_coords_private(PetscInt dim, PetscReal t, const PetscReal X[], PetscInt Nf, PetscScalar *out, void *ctx) 1528d71ae5a4SJacob Faibussowitsch { 15291c7a958bSStefano Zampini PetscInt f, *comp = (PetscInt *)ctx; 15301c7a958bSStefano Zampini 15311c7a958bSStefano Zampini PetscFunctionBegin; 15321c7a958bSStefano Zampini for (f = 0; f < Nf; f++) out[f] = X[*comp]; 15333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15341c7a958bSStefano Zampini } 1535674ae819SStefano Zampini 1536d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc) 1537d71ae5a4SJacob Faibussowitsch { 15381f4df5f7SStefano Zampini Vec local, global; 15391f4df5f7SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 15401f4df5f7SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 15415c5e10d6SStefano Zampini PetscBool monolithic = PETSC_FALSE; 15421f4df5f7SStefano Zampini 15431f4df5f7SStefano Zampini PetscFunctionBegin; 1544d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)pc), ((PetscObject)pc)->prefix, "BDDC topology options", "PC"); 15459566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_monolithic", "Discard any information on dofs splitting", NULL, monolithic, &monolithic, NULL)); 1546d0609cedSBarry Smith PetscOptionsEnd(); 15471f4df5f7SStefano Zampini /* need to convert from global to local topology information and remove references to information in global ordering */ 15489566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(pc->pmat, &global, NULL)); 15499566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(matis->A, &local, NULL)); 15509566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(global, PETSC_TRUE)); 15519566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(local, PETSC_TRUE)); 15526a8fc67bSStefano Zampini if (monolithic) { /* just get block size to properly compute vertices */ 155348a46eb9SPierre Jolivet if (pcbddc->vertex_size == 1) PetscCall(MatGetBlockSize(pc->pmat, &pcbddc->vertex_size)); 15546a8fc67bSStefano Zampini goto boundary; 15556a8fc67bSStefano Zampini } 15565c5e10d6SStefano Zampini 15571f4df5f7SStefano Zampini if (pcbddc->user_provided_isfordofs) { 15581f4df5f7SStefano Zampini if (pcbddc->n_ISForDofs) { 15591f4df5f7SStefano Zampini PetscInt i; 15600c85b387SStefano Zampini 15619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->n_ISForDofs, &pcbddc->ISForDofsLocal)); 15621f4df5f7SStefano Zampini for (i = 0; i < pcbddc->n_ISForDofs; i++) { 15630c85b387SStefano Zampini PetscInt bs; 15640c85b387SStefano Zampini 15659566063dSJacob Faibussowitsch PetscCall(PCBDDCGlobalToLocal(matis->rctx, global, local, pcbddc->ISForDofs[i], &pcbddc->ISForDofsLocal[i])); 15669566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(pcbddc->ISForDofs[i], &bs)); 15679566063dSJacob Faibussowitsch PetscCall(ISSetBlockSize(pcbddc->ISForDofsLocal[i], bs)); 15689566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->ISForDofs[i])); 15691f4df5f7SStefano Zampini } 15701f4df5f7SStefano Zampini pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs; 15711f4df5f7SStefano Zampini pcbddc->n_ISForDofs = 0; 15729566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->ISForDofs)); 15731f4df5f7SStefano Zampini } 15741f4df5f7SStefano Zampini } else { 157521ef3d20SStefano Zampini if (!pcbddc->n_ISForDofsLocal) { /* field split not present */ 157621ef3d20SStefano Zampini DM dm; 157721ef3d20SStefano Zampini 15789566063dSJacob Faibussowitsch PetscCall(MatGetDM(pc->pmat, &dm)); 157948a46eb9SPierre Jolivet if (!dm) PetscCall(PCGetDM(pc, &dm)); 158021ef3d20SStefano Zampini if (dm) { 158121ef3d20SStefano Zampini IS *fields; 158221ef3d20SStefano Zampini PetscInt nf, i; 15830c85b387SStefano Zampini 15849566063dSJacob Faibussowitsch PetscCall(DMCreateFieldDecomposition(dm, &nf, NULL, &fields, NULL)); 15859566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nf, &pcbddc->ISForDofsLocal)); 158621ef3d20SStefano Zampini for (i = 0; i < nf; i++) { 15870c85b387SStefano Zampini PetscInt bs; 15880c85b387SStefano Zampini 15899566063dSJacob Faibussowitsch PetscCall(PCBDDCGlobalToLocal(matis->rctx, global, local, fields[i], &pcbddc->ISForDofsLocal[i])); 15909566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(fields[i], &bs)); 15919566063dSJacob Faibussowitsch PetscCall(ISSetBlockSize(pcbddc->ISForDofsLocal[i], bs)); 15929566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fields[i])); 159321ef3d20SStefano Zampini } 15949566063dSJacob Faibussowitsch PetscCall(PetscFree(fields)); 159521ef3d20SStefano Zampini pcbddc->n_ISForDofsLocal = nf; 159621ef3d20SStefano Zampini } else { /* See if MATIS has fields attached by the conversion from MatNest */ 159721ef3d20SStefano Zampini PetscContainer c; 159821ef3d20SStefano Zampini 15999566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc->pmat, "_convert_nest_lfields", (PetscObject *)&c)); 160021ef3d20SStefano Zampini if (c) { 160121ef3d20SStefano Zampini MatISLocalFields lf; 16029566063dSJacob Faibussowitsch PetscCall(PetscContainerGetPointer(c, (void **)&lf)); 16039566063dSJacob Faibussowitsch PetscCall(PCBDDCSetDofsSplittingLocal(pc, lf->nr, lf->rf)); 160421ef3d20SStefano Zampini } else { /* fallback, create the default fields if bs > 1 */ 16051f4df5f7SStefano Zampini PetscInt i, n = matis->A->rmap->n; 16069566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(pc->pmat, &i)); 160721ef3d20SStefano Zampini if (i > 1) { 1608986cdee1SStefano Zampini pcbddc->n_ISForDofsLocal = i; 16099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->n_ISForDofsLocal, &pcbddc->ISForDofsLocal)); 161048a46eb9SPierre Jolivet for (i = 0; i < pcbddc->n_ISForDofsLocal; i++) PetscCall(ISCreateStride(PetscObjectComm((PetscObject)pc), n / pcbddc->n_ISForDofsLocal, i, pcbddc->n_ISForDofsLocal, &pcbddc->ISForDofsLocal[i])); 16111f4df5f7SStefano Zampini } 161221ef3d20SStefano Zampini } 161321ef3d20SStefano Zampini } 16147a0e7b2cSstefano_zampini } else { 16157a0e7b2cSstefano_zampini PetscInt i; 161648a46eb9SPierre Jolivet for (i = 0; i < pcbddc->n_ISForDofsLocal; i++) PetscCall(PCBDDCConsistencyCheckIS(pc, MPI_LAND, &pcbddc->ISForDofsLocal[i])); 16171f4df5f7SStefano Zampini } 1618986cdee1SStefano Zampini } 16191f4df5f7SStefano Zampini 16205c5e10d6SStefano Zampini boundary: 16211f4df5f7SStefano Zampini if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) { 16229566063dSJacob Faibussowitsch PetscCall(PCBDDCGlobalToLocal(matis->rctx, global, local, pcbddc->DirichletBoundaries, &pcbddc->DirichletBoundariesLocal)); 16237a0e7b2cSstefano_zampini } else if (pcbddc->DirichletBoundariesLocal) { 16249566063dSJacob Faibussowitsch PetscCall(PCBDDCConsistencyCheckIS(pc, MPI_LAND, &pcbddc->DirichletBoundariesLocal)); 16251f4df5f7SStefano Zampini } 16261f4df5f7SStefano Zampini if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) { 16279566063dSJacob Faibussowitsch PetscCall(PCBDDCGlobalToLocal(matis->rctx, global, local, pcbddc->NeumannBoundaries, &pcbddc->NeumannBoundariesLocal)); 16287a0e7b2cSstefano_zampini } else if (pcbddc->NeumannBoundariesLocal) { 16299566063dSJacob Faibussowitsch PetscCall(PCBDDCConsistencyCheckIS(pc, MPI_LOR, &pcbddc->NeumannBoundariesLocal)); 16301f4df5f7SStefano Zampini } 163148a46eb9SPierre Jolivet if (!pcbddc->user_primal_vertices_local && pcbddc->user_primal_vertices) PetscCall(PCBDDCGlobalToLocal(matis->rctx, global, local, pcbddc->user_primal_vertices, &pcbddc->user_primal_vertices_local)); 16329566063dSJacob Faibussowitsch PetscCall(VecDestroy(&global)); 16339566063dSJacob Faibussowitsch PetscCall(VecDestroy(&local)); 16347620a527SStefano Zampini /* detect local disconnected subdomains if requested (use matis->A) */ 16357620a527SStefano Zampini if (pcbddc->detect_disconnected) { 16367620a527SStefano Zampini IS primalv = NULL; 16377620a527SStefano Zampini PetscInt i; 16388361f951SStefano Zampini PetscBool filter = pcbddc->detect_disconnected_filter; 16397a0e7b2cSstefano_zampini 164048a46eb9SPierre Jolivet for (i = 0; i < pcbddc->n_local_subs; i++) PetscCall(ISDestroy(&pcbddc->local_subs[i])); 16419566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->local_subs)); 16429566063dSJacob Faibussowitsch PetscCall(PCBDDCDetectDisconnectedComponents(pc, filter, &pcbddc->n_local_subs, &pcbddc->local_subs, &primalv)); 16439566063dSJacob Faibussowitsch PetscCall(PCBDDCAddPrimalVerticesLocalIS(pc, primalv)); 16449566063dSJacob Faibussowitsch PetscCall(ISDestroy(&primalv)); 16457620a527SStefano Zampini } 16467620a527SStefano Zampini /* early stage corner detection */ 16477620a527SStefano Zampini { 16487620a527SStefano Zampini DM dm; 16497620a527SStefano Zampini 16509566063dSJacob Faibussowitsch PetscCall(MatGetDM(pc->pmat, &dm)); 165148a46eb9SPierre Jolivet if (!dm) PetscCall(PCGetDM(pc, &dm)); 16527620a527SStefano Zampini if (dm) { 16537620a527SStefano Zampini PetscBool isda; 16547620a527SStefano Zampini 16559566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMDA, &isda)); 16567620a527SStefano Zampini if (isda) { 16577620a527SStefano Zampini ISLocalToGlobalMapping l2l; 16587620a527SStefano Zampini IS corners; 16597620a527SStefano Zampini Mat lA; 16604f819b78SStefano Zampini PetscBool gl, lo; 16617620a527SStefano Zampini 16624f819b78SStefano Zampini { 16634f819b78SStefano Zampini Vec cvec; 16644f819b78SStefano Zampini const PetscScalar *coords; 16654f819b78SStefano Zampini PetscInt dof, n, cdim; 16664f819b78SStefano Zampini PetscBool memc = PETSC_TRUE; 16674f819b78SStefano Zampini 16689566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL)); 16699566063dSJacob Faibussowitsch PetscCall(DMGetCoordinates(dm, &cvec)); 16709566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(cvec, &n)); 16719566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(cvec, &cdim)); 16724f819b78SStefano Zampini n /= cdim; 16739566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->mat_graph->coords)); 16749566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dof * n * cdim, &pcbddc->mat_graph->coords)); 16759566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cvec, &coords)); 16764f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX) 16774f819b78SStefano Zampini memc = PETSC_FALSE; 16784f819b78SStefano Zampini #endif 16794f819b78SStefano Zampini if (dof != 1) memc = PETSC_FALSE; 16804f819b78SStefano Zampini if (memc) { 16819566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pcbddc->mat_graph->coords, coords, cdim * n * dof)); 16824f819b78SStefano Zampini } else { /* BDDC graph does not use any blocked information, we need to replicate the data */ 16834f819b78SStefano Zampini PetscReal *bcoords = pcbddc->mat_graph->coords; 16844f819b78SStefano Zampini PetscInt i, b, d; 16854f819b78SStefano Zampini 16864f819b78SStefano Zampini for (i = 0; i < n; i++) { 16874f819b78SStefano Zampini for (b = 0; b < dof; b++) { 1688ad540459SPierre Jolivet for (d = 0; d < cdim; d++) bcoords[i * dof * cdim + b * cdim + d] = PetscRealPart(coords[i * cdim + d]); 16894f819b78SStefano Zampini } 16904f819b78SStefano Zampini } 16914f819b78SStefano Zampini } 16929566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(cvec, &coords)); 16934f819b78SStefano Zampini pcbddc->mat_graph->cdim = cdim; 16944f819b78SStefano Zampini pcbddc->mat_graph->cnloc = dof * n; 16954f819b78SStefano Zampini pcbddc->mat_graph->cloc = PETSC_FALSE; 16964f819b78SStefano Zampini } 16979566063dSJacob Faibussowitsch PetscCall(DMDAGetSubdomainCornersIS(dm, &corners)); 16989566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->pmat, &lA)); 16999566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(lA, &l2l, NULL)); 17009566063dSJacob Faibussowitsch PetscCall(MatISRestoreLocalMat(pc->pmat, &lA)); 17014f819b78SStefano Zampini lo = (PetscBool)(l2l && corners); 17021c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&lo, &gl, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)pc))); 17034f819b78SStefano Zampini if (gl) { /* From PETSc's DMDA */ 17047620a527SStefano Zampini const PetscInt *idx; 170572ed36d8SStefano Zampini PetscInt dof, bs, *idxout, n; 17067620a527SStefano Zampini 17079566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL)); 17089566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(l2l, &bs)); 17099566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(corners, &n)); 17109566063dSJacob Faibussowitsch PetscCall(ISGetIndices(corners, &idx)); 171172ed36d8SStefano Zampini if (bs == dof) { 17129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &idxout)); 17139566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(l2l, n, idx, idxout)); 171472ed36d8SStefano Zampini } else { /* the original DMDA local-to-local map have been modified */ 171572ed36d8SStefano Zampini PetscInt i, d; 171672ed36d8SStefano Zampini 17179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dof * n, &idxout)); 17189371c9d4SSatish Balay for (i = 0; i < n; i++) 17199371c9d4SSatish Balay for (d = 0; d < dof; d++) idxout[dof * i + d] = dof * idx[i] + d; 17209566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(l2l, dof * n, idxout, idxout)); 172172ed36d8SStefano Zampini 172272ed36d8SStefano Zampini bs = 1; 172372ed36d8SStefano Zampini n *= dof; 172472ed36d8SStefano Zampini } 17259566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(corners, &idx)); 17269566063dSJacob Faibussowitsch PetscCall(DMDARestoreSubdomainCornersIS(dm, &corners)); 17279566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)pc), bs, n, idxout, PETSC_OWN_POINTER, &corners)); 17289566063dSJacob Faibussowitsch PetscCall(PCBDDCAddPrimalVerticesLocalIS(pc, corners)); 17299566063dSJacob Faibussowitsch PetscCall(ISDestroy(&corners)); 17301c7a958bSStefano Zampini pcbddc->corner_selected = PETSC_TRUE; 17314f819b78SStefano Zampini pcbddc->corner_selection = PETSC_TRUE; 17324f819b78SStefano Zampini } 173348a46eb9SPierre Jolivet if (corners) PetscCall(DMDARestoreSubdomainCornersIS(dm, &corners)); 17347620a527SStefano Zampini } 17357620a527SStefano Zampini } 17367620a527SStefano Zampini } 17371c7a958bSStefano Zampini if (pcbddc->corner_selection && !pcbddc->mat_graph->cdim) { 17381c7a958bSStefano Zampini DM dm; 17391c7a958bSStefano Zampini 17409566063dSJacob Faibussowitsch PetscCall(MatGetDM(pc->pmat, &dm)); 174148a46eb9SPierre Jolivet if (!dm) PetscCall(PCGetDM(pc, &dm)); 17424f819b78SStefano Zampini if (dm) { /* this can get very expensive, I need to find a faster alternative */ 17431c7a958bSStefano Zampini Vec vcoords; 17441c7a958bSStefano Zampini PetscSection section; 17451c7a958bSStefano Zampini PetscReal *coords; 17461c7a958bSStefano Zampini PetscInt d, cdim, nl, nf, **ctxs; 17471c7a958bSStefano Zampini PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal *, PetscInt, PetscScalar *, void *); 174851ab8ad6SStefano Zampini /* debug coordinates */ 174951ab8ad6SStefano Zampini PetscViewer viewer; 175051ab8ad6SStefano Zampini PetscBool flg; 175151ab8ad6SStefano Zampini PetscViewerFormat format; 175251ab8ad6SStefano Zampini const char *prefix; 17531c7a958bSStefano Zampini 17549566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 17559566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 17569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &nf)); 17579566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dm, &vcoords)); 17589566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vcoords, &nl)); 17599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl * cdim, &coords)); 17609566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nf, &funcs, nf, &ctxs)); 17619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nf, &ctxs[0])); 17621c7a958bSStefano Zampini for (d = 0; d < nf; d++) funcs[d] = func_coords_private; 17631c7a958bSStefano Zampini for (d = 1; d < nf; d++) ctxs[d] = ctxs[d - 1] + 1; 176451ab8ad6SStefano Zampini 176551ab8ad6SStefano Zampini /* debug coordinates */ 176651ab8ad6SStefano Zampini PetscCall(PCGetOptionsPrefix(pc, &prefix)); 176751ab8ad6SStefano Zampini PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)vcoords), ((PetscObject)vcoords)->options, prefix, "-pc_bddc_coords_vec_view", &viewer, &format, &flg)); 176851ab8ad6SStefano Zampini if (flg) PetscCall(PetscViewerPushFormat(viewer, format)); 17691c7a958bSStefano Zampini for (d = 0; d < cdim; d++) { 17701c7a958bSStefano Zampini PetscInt i; 17711c7a958bSStefano Zampini const PetscScalar *v; 177251ab8ad6SStefano Zampini char name[16]; 17731c7a958bSStefano Zampini 17741c7a958bSStefano Zampini for (i = 0; i < nf; i++) ctxs[i][0] = d; 177551ab8ad6SStefano Zampini PetscCall(PetscSNPrintf(name, sizeof(name), "bddc_coords_%d", (int)d)); 177651ab8ad6SStefano Zampini PetscCall(PetscObjectSetName((PetscObject)vcoords, name)); 17779566063dSJacob Faibussowitsch PetscCall(DMProjectFunction(dm, 0.0, funcs, (void **)ctxs, INSERT_VALUES, vcoords)); 177851ab8ad6SStefano Zampini if (flg) PetscCall(VecView(vcoords, viewer)); 17799566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vcoords, &v)); 17801c7a958bSStefano Zampini for (i = 0; i < nl; i++) coords[i * cdim + d] = PetscRealPart(v[i]); 17819566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vcoords, &v)); 17821c7a958bSStefano Zampini } 17839566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vcoords)); 17849566063dSJacob Faibussowitsch PetscCall(PCSetCoordinates(pc, cdim, nl, coords)); 17859566063dSJacob Faibussowitsch PetscCall(PetscFree(coords)); 17869566063dSJacob Faibussowitsch PetscCall(PetscFree(ctxs[0])); 17879566063dSJacob Faibussowitsch PetscCall(PetscFree2(funcs, ctxs)); 178851ab8ad6SStefano Zampini if (flg) { 178951ab8ad6SStefano Zampini PetscCall(PetscViewerPopFormat(viewer)); 179051ab8ad6SStefano Zampini PetscCall(PetscViewerDestroy(&viewer)); 179151ab8ad6SStefano Zampini } 17921c7a958bSStefano Zampini } 17931c7a958bSStefano Zampini } 17943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17957a0e7b2cSstefano_zampini } 17967a0e7b2cSstefano_zampini 1797d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCConsistencyCheckIS(PC pc, MPI_Op mop, IS *is) 1798d71ae5a4SJacob Faibussowitsch { 17997a0e7b2cSstefano_zampini Mat_IS *matis = (Mat_IS *)(pc->pmat->data); 18007a0e7b2cSstefano_zampini IS nis; 18017a0e7b2cSstefano_zampini const PetscInt *idxs; 18027a0e7b2cSstefano_zampini PetscInt i, nd, n = matis->A->rmap->n, *nidxs, nnd; 18037a0e7b2cSstefano_zampini 18047a0e7b2cSstefano_zampini PetscFunctionBegin; 18057827d75bSBarry Smith PetscCheck(mop == MPI_LAND || mop == MPI_LOR, PetscObjectComm((PetscObject)(pc)), PETSC_ERR_SUP, "Supported are MPI_LAND and MPI_LOR"); 18067a0e7b2cSstefano_zampini if (mop == MPI_LAND) { 18077a0e7b2cSstefano_zampini /* init rootdata with true */ 18081bd50df1SStefano Zampini for (i = 0; i < pc->pmat->rmap->n; i++) matis->sf_rootdata[i] = 1; 18097a0e7b2cSstefano_zampini } else { 18109566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_rootdata, pc->pmat->rmap->n)); 18117a0e7b2cSstefano_zampini } 18129566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_leafdata, n)); 18139566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(*is, &nd)); 18149566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*is, &idxs)); 18157a0e7b2cSstefano_zampini for (i = 0; i < nd; i++) 18169371c9d4SSatish Balay if (-1 < idxs[i] && idxs[i] < n) matis->sf_leafdata[idxs[i]] = 1; 18179566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*is, &idxs)); 18189566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, matis->sf_leafdata, matis->sf_rootdata, mop)); 18199566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, matis->sf_leafdata, matis->sf_rootdata, mop)); 18209566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 18219566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 18227a0e7b2cSstefano_zampini if (mop == MPI_LAND) { 18239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nd, &nidxs)); 18247a0e7b2cSstefano_zampini } else { 18259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &nidxs)); 18267a0e7b2cSstefano_zampini } 18277a0e7b2cSstefano_zampini for (i = 0, nnd = 0; i < n; i++) 18289371c9d4SSatish Balay if (matis->sf_leafdata[i]) nidxs[nnd++] = i; 18299566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)(*is)), nnd, nidxs, PETSC_OWN_POINTER, &nis)); 18309566063dSJacob Faibussowitsch PetscCall(ISDestroy(is)); 18317a0e7b2cSstefano_zampini *is = nis; 18323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18331f4df5f7SStefano Zampini } 18341f4df5f7SStefano Zampini 1835d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignRemoveInterior(PC pc, Vec r, Vec z) 1836d71ae5a4SJacob Faibussowitsch { 18373e589ea0SStefano Zampini PC_IS *pcis = (PC_IS *)(pc->data); 18383e589ea0SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)(pc->data); 18393e589ea0SStefano Zampini 18403e589ea0SStefano Zampini PetscFunctionBegin; 18413ba16761SJacob Faibussowitsch if (!pcbddc->benign_have_null) PetscFunctionReturn(PETSC_SUCCESS); 18423e589ea0SStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 18433e589ea0SStefano Zampini Vec swap; 18443e589ea0SStefano Zampini 18459566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, r, pcbddc->work_change)); 18463e589ea0SStefano Zampini swap = pcbddc->work_change; 18473e589ea0SStefano Zampini pcbddc->work_change = r; 18483e589ea0SStefano Zampini r = swap; 18493e589ea0SStefano Zampini } 18509566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 18519566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 18529566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 18539566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D)); 18549566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 18559566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D)); 18569566063dSJacob Faibussowitsch PetscCall(VecSet(z, 0.)); 18579566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE)); 18589566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE)); 18593e589ea0SStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 1860f913dca9SStefano Zampini pcbddc->work_change = r; 18619566063dSJacob Faibussowitsch PetscCall(VecCopy(z, pcbddc->work_change)); 18629566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcbddc->work_change, z)); 18633e589ea0SStefano Zampini } 18643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18653e589ea0SStefano Zampini } 18663e589ea0SStefano Zampini 1867d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose) 1868d71ae5a4SJacob Faibussowitsch { 1869a3df083aSStefano Zampini PCBDDCBenignMatMult_ctx ctx; 1870a3df083aSStefano Zampini PetscBool apply_right, apply_left, reset_x; 1871a3df083aSStefano Zampini 1872a3df083aSStefano Zampini PetscFunctionBegin; 18739566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(A, &ctx)); 1874a3df083aSStefano Zampini if (transpose) { 1875a3df083aSStefano Zampini apply_right = ctx->apply_left; 1876a3df083aSStefano Zampini apply_left = ctx->apply_right; 1877a3df083aSStefano Zampini } else { 1878a3df083aSStefano Zampini apply_right = ctx->apply_right; 1879a3df083aSStefano Zampini apply_left = ctx->apply_left; 1880a3df083aSStefano Zampini } 1881a3df083aSStefano Zampini reset_x = PETSC_FALSE; 1882a3df083aSStefano Zampini if (apply_right) { 1883a3df083aSStefano Zampini const PetscScalar *ax; 1884a3df083aSStefano Zampini PetscInt nl, i; 1885a3df083aSStefano Zampini 18869566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(x, &nl)); 18879566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &ax)); 18889566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(ctx->work, ax, nl)); 18899566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &ax)); 1890a3df083aSStefano Zampini for (i = 0; i < ctx->benign_n; i++) { 1891a3df083aSStefano Zampini PetscScalar sum, val; 1892a3df083aSStefano Zampini const PetscInt *idxs; 1893a3df083aSStefano Zampini PetscInt nz, j; 18949566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(ctx->benign_zerodiag_subs[i], &nz)); 18959566063dSJacob Faibussowitsch PetscCall(ISGetIndices(ctx->benign_zerodiag_subs[i], &idxs)); 1896a3df083aSStefano Zampini sum = 0.; 1897a3df083aSStefano Zampini if (ctx->apply_p0) { 1898a3df083aSStefano Zampini val = ctx->work[idxs[nz - 1]]; 1899a3df083aSStefano Zampini for (j = 0; j < nz - 1; j++) { 1900a3df083aSStefano Zampini sum += ctx->work[idxs[j]]; 1901a3df083aSStefano Zampini ctx->work[idxs[j]] += val; 1902a3df083aSStefano Zampini } 1903a3df083aSStefano Zampini } else { 1904ad540459SPierre Jolivet for (j = 0; j < nz - 1; j++) sum += ctx->work[idxs[j]]; 1905a3df083aSStefano Zampini } 1906a3df083aSStefano Zampini ctx->work[idxs[nz - 1]] -= sum; 19079566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(ctx->benign_zerodiag_subs[i], &idxs)); 1908a3df083aSStefano Zampini } 19099566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(x, ctx->work)); 1910a3df083aSStefano Zampini reset_x = PETSC_TRUE; 1911a3df083aSStefano Zampini } 1912a3df083aSStefano Zampini if (transpose) { 19139566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(ctx->A, x, y)); 1914a3df083aSStefano Zampini } else { 19159566063dSJacob Faibussowitsch PetscCall(MatMult(ctx->A, x, y)); 1916a3df083aSStefano Zampini } 19171baa6e33SBarry Smith if (reset_x) PetscCall(VecResetArray(x)); 1918a3df083aSStefano Zampini if (apply_left) { 1919a3df083aSStefano Zampini PetscScalar *ay; 1920a3df083aSStefano Zampini PetscInt i; 1921a3df083aSStefano Zampini 19229566063dSJacob Faibussowitsch PetscCall(VecGetArray(y, &ay)); 1923a3df083aSStefano Zampini for (i = 0; i < ctx->benign_n; i++) { 1924a3df083aSStefano Zampini PetscScalar sum, val; 1925a3df083aSStefano Zampini const PetscInt *idxs; 1926a3df083aSStefano Zampini PetscInt nz, j; 19279566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(ctx->benign_zerodiag_subs[i], &nz)); 19289566063dSJacob Faibussowitsch PetscCall(ISGetIndices(ctx->benign_zerodiag_subs[i], &idxs)); 1929a3df083aSStefano Zampini val = -ay[idxs[nz - 1]]; 1930a3df083aSStefano Zampini if (ctx->apply_p0) { 1931a3df083aSStefano Zampini sum = 0.; 1932a3df083aSStefano Zampini for (j = 0; j < nz - 1; j++) { 1933a3df083aSStefano Zampini sum += ay[idxs[j]]; 1934a3df083aSStefano Zampini ay[idxs[j]] += val; 1935a3df083aSStefano Zampini } 1936a3df083aSStefano Zampini ay[idxs[nz - 1]] += sum; 1937a3df083aSStefano Zampini } else { 1938ad540459SPierre Jolivet for (j = 0; j < nz - 1; j++) ay[idxs[j]] += val; 1939a3df083aSStefano Zampini ay[idxs[nz - 1]] = 0.; 1940a3df083aSStefano Zampini } 19419566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(ctx->benign_zerodiag_subs[i], &idxs)); 1942a3df083aSStefano Zampini } 19439566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(y, &ay)); 1944a3df083aSStefano Zampini } 19453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1946a3df083aSStefano Zampini } 1947a3df083aSStefano Zampini 1948d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y) 1949d71ae5a4SJacob Faibussowitsch { 1950a3df083aSStefano Zampini PetscFunctionBegin; 19519566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignMatMult_Private_Private(A, x, y, PETSC_TRUE)); 19523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1953a3df083aSStefano Zampini } 1954a3df083aSStefano Zampini 1955d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y) 1956d71ae5a4SJacob Faibussowitsch { 1957a3df083aSStefano Zampini PetscFunctionBegin; 19589566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignMatMult_Private_Private(A, x, y, PETSC_FALSE)); 19593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1960a3df083aSStefano Zampini } 1961a3df083aSStefano Zampini 1962d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore) 1963d71ae5a4SJacob Faibussowitsch { 1964a3df083aSStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 1965a3df083aSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 1966a3df083aSStefano Zampini PCBDDCBenignMatMult_ctx ctx; 1967a3df083aSStefano Zampini 1968a3df083aSStefano Zampini PetscFunctionBegin; 1969a3df083aSStefano Zampini if (!restore) { 19701dd7afcfSStefano Zampini Mat A_IB, A_BI; 1971a3df083aSStefano Zampini PetscScalar *work; 1972b334f244SStefano Zampini PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL; 1973a3df083aSStefano Zampini 197428b400f6SJacob Faibussowitsch PetscCheck(!pcbddc->benign_original_mat, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Benign original mat has not been restored"); 19753ba16761SJacob Faibussowitsch if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(PETSC_SUCCESS); 19769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n, &work)); 19779566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &A_IB)); 19789566063dSJacob Faibussowitsch PetscCall(MatSetSizes(A_IB, pcis->n - pcis->n_B, pcis->n_B, PETSC_DECIDE, PETSC_DECIDE)); 19799566063dSJacob Faibussowitsch PetscCall(MatSetType(A_IB, MATSHELL)); 19809566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(A_IB, MATOP_MULT, (void (*)(void))PCBDDCBenignMatMult_Private)); 19819566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(A_IB, MATOP_MULT_TRANSPOSE, (void (*)(void))PCBDDCBenignMatMultTranspose_Private)); 19829566063dSJacob Faibussowitsch PetscCall(PetscNew(&ctx)); 19839566063dSJacob Faibussowitsch PetscCall(MatShellSetContext(A_IB, ctx)); 1984a3df083aSStefano Zampini ctx->apply_left = PETSC_TRUE; 1985a3df083aSStefano Zampini ctx->apply_right = PETSC_FALSE; 1986a3df083aSStefano Zampini ctx->apply_p0 = PETSC_FALSE; 1987a3df083aSStefano Zampini ctx->benign_n = pcbddc->benign_n; 1988059032f7SStefano Zampini if (reuse) { 1989a3df083aSStefano Zampini ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs; 19901dd7afcfSStefano Zampini ctx->free = PETSC_FALSE; 1991059032f7SStefano Zampini } else { /* TODO: could be optimized for successive solves */ 1992059032f7SStefano Zampini ISLocalToGlobalMapping N_to_D; 1993059032f7SStefano Zampini PetscInt i; 1994059032f7SStefano Zampini 19959566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(pcis->is_I_local, &N_to_D)); 19969566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->benign_n, &ctx->benign_zerodiag_subs)); 199748a46eb9SPierre Jolivet for (i = 0; i < pcbddc->benign_n; i++) PetscCall(ISGlobalToLocalMappingApplyIS(N_to_D, IS_GTOLM_DROP, pcbddc->benign_zerodiag_subs[i], &ctx->benign_zerodiag_subs[i])); 19989566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&N_to_D)); 19991dd7afcfSStefano Zampini ctx->free = PETSC_TRUE; 2000059032f7SStefano Zampini } 2001a3df083aSStefano Zampini ctx->A = pcis->A_IB; 2002a3df083aSStefano Zampini ctx->work = work; 20039566063dSJacob Faibussowitsch PetscCall(MatSetUp(A_IB)); 20049566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A_IB, MAT_FINAL_ASSEMBLY)); 20059566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A_IB, MAT_FINAL_ASSEMBLY)); 2006a3df083aSStefano Zampini pcis->A_IB = A_IB; 2007a3df083aSStefano Zampini 2008a3df083aSStefano Zampini /* A_BI as A_IB^T */ 20099566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(A_IB, &A_BI)); 2010a3df083aSStefano Zampini pcbddc->benign_original_mat = pcis->A_BI; 2011a3df083aSStefano Zampini pcis->A_BI = A_BI; 2012a3df083aSStefano Zampini } else { 20133ba16761SJacob Faibussowitsch if (!pcbddc->benign_original_mat) PetscFunctionReturn(PETSC_SUCCESS); 20149566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(pcis->A_IB, &ctx)); 20159566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_IB)); 2016a3df083aSStefano Zampini pcis->A_IB = ctx->A; 20171dd7afcfSStefano Zampini ctx->A = NULL; 20189566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_BI)); 20191dd7afcfSStefano Zampini pcis->A_BI = pcbddc->benign_original_mat; 20201dd7afcfSStefano Zampini pcbddc->benign_original_mat = NULL; 20211dd7afcfSStefano Zampini if (ctx->free) { 2022059032f7SStefano Zampini PetscInt i; 202348a46eb9SPierre Jolivet for (i = 0; i < ctx->benign_n; i++) PetscCall(ISDestroy(&ctx->benign_zerodiag_subs[i])); 20249566063dSJacob Faibussowitsch PetscCall(PetscFree(ctx->benign_zerodiag_subs)); 2025059032f7SStefano Zampini } 20269566063dSJacob Faibussowitsch PetscCall(PetscFree(ctx->work)); 20279566063dSJacob Faibussowitsch PetscCall(PetscFree(ctx)); 2028a3df083aSStefano Zampini } 20293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2030a3df083aSStefano Zampini } 2031a3df083aSStefano Zampini 2032a3df083aSStefano Zampini /* used just in bddc debug mode */ 2033d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B) 2034d71ae5a4SJacob Faibussowitsch { 2035a3df083aSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 2036a3df083aSStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 2037a3df083aSStefano Zampini Mat An; 2038a3df083aSStefano Zampini 2039a3df083aSStefano Zampini PetscFunctionBegin; 20409566063dSJacob Faibussowitsch PetscCall(MatPtAP(matis->A, pcbddc->benign_change, MAT_INITIAL_MATRIX, 2.0, &An)); 20419566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns(An, pcbddc->benign_n, pcbddc->benign_p0_lidx, 1.0, NULL, NULL)); 2042a3df083aSStefano Zampini if (is1) { 20439566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(An, is1, is2, MAT_INITIAL_MATRIX, B)); 20449566063dSJacob Faibussowitsch PetscCall(MatDestroy(&An)); 2045a3df083aSStefano Zampini } else { 2046a3df083aSStefano Zampini *B = An; 2047a3df083aSStefano Zampini } 20483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2049a3df083aSStefano Zampini } 2050a3df083aSStefano Zampini 20511cf9b237SStefano Zampini /* TODO: add reuse flag */ 2052d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B) 2053d71ae5a4SJacob Faibussowitsch { 20541cf9b237SStefano Zampini Mat Bt; 20551cf9b237SStefano Zampini PetscScalar *a, *bdata; 20561cf9b237SStefano Zampini const PetscInt *ii, *ij; 20571cf9b237SStefano Zampini PetscInt m, n, i, nnz, *bii, *bij; 20581cf9b237SStefano Zampini PetscBool flg_row; 20591cf9b237SStefano Zampini 20601cf9b237SStefano Zampini PetscFunctionBegin; 20619566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &n, &m)); 20629566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &ij, &flg_row)); 20639566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &a)); 20641cf9b237SStefano Zampini nnz = n; 20651cf9b237SStefano Zampini for (i = 0; i < ii[n]; i++) { 20661cf9b237SStefano Zampini if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++; 20671cf9b237SStefano Zampini } 20689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n + 1, &bii)); 20699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &bij)); 20709566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &bdata)); 20711cf9b237SStefano Zampini nnz = 0; 20721cf9b237SStefano Zampini bii[0] = 0; 20731cf9b237SStefano Zampini for (i = 0; i < n; i++) { 20741cf9b237SStefano Zampini PetscInt j; 20751cf9b237SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 20761cf9b237SStefano Zampini PetscScalar entry = a[j]; 20773272d46bSStefano Zampini if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || (n == m && ij[j] == i)) { 20781cf9b237SStefano Zampini bij[nnz] = ij[j]; 20791cf9b237SStefano Zampini bdata[nnz] = entry; 20801cf9b237SStefano Zampini nnz++; 20811cf9b237SStefano Zampini } 20821cf9b237SStefano Zampini } 20831cf9b237SStefano Zampini bii[i + 1] = nnz; 20841cf9b237SStefano Zampini } 20859566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &a)); 20869566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A), n, m, bii, bij, bdata, &Bt)); 20879566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &ij, &flg_row)); 20881cf9b237SStefano Zampini { 20891cf9b237SStefano Zampini Mat_SeqAIJ *b = (Mat_SeqAIJ *)(Bt->data); 20901cf9b237SStefano Zampini b->free_a = PETSC_TRUE; 20911cf9b237SStefano Zampini b->free_ij = PETSC_TRUE; 20921cf9b237SStefano Zampini } 209348a46eb9SPierre Jolivet if (*B == A) PetscCall(MatDestroy(&A)); 20941cf9b237SStefano Zampini *B = Bt; 20953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20961cf9b237SStefano Zampini } 20971cf9b237SStefano Zampini 2098d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCDetectDisconnectedComponents(PC pc, PetscBool filter, PetscInt *ncc, IS *cc[], IS *primalv) 2099d71ae5a4SJacob Faibussowitsch { 2100c80a6c00SStefano Zampini Mat B = NULL; 2101c80a6c00SStefano Zampini DM dm; 21024f1b2e48SStefano Zampini IS is_dummy, *cc_n; 21034f1b2e48SStefano Zampini ISLocalToGlobalMapping l2gmap_dummy; 21044f1b2e48SStefano Zampini PCBDDCGraph graph; 2105c80a6c00SStefano Zampini PetscInt *xadj_filtered = NULL, *adjncy_filtered = NULL; 21064f1b2e48SStefano Zampini PetscInt i, n; 21074f1b2e48SStefano Zampini PetscInt *xadj, *adjncy; 2108c80a6c00SStefano Zampini PetscBool isplex = PETSC_FALSE; 21094f1b2e48SStefano Zampini 21104f1b2e48SStefano Zampini PetscFunctionBegin; 2111a2eca866SStefano Zampini if (ncc) *ncc = 0; 2112a2eca866SStefano Zampini if (cc) *cc = NULL; 2113a2eca866SStefano Zampini if (primalv) *primalv = NULL; 21149566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphCreate(&graph)); 21159566063dSJacob Faibussowitsch PetscCall(MatGetDM(pc->pmat, &dm)); 211648a46eb9SPierre Jolivet if (!dm) PetscCall(PCGetDM(pc, &dm)); 211748a46eb9SPierre Jolivet if (dm) PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMPLEX, &isplex)); 21188361f951SStefano Zampini if (filter) isplex = PETSC_FALSE; 21198361f951SStefano Zampini 2120c80a6c00SStefano Zampini if (isplex) { /* this code has been modified from plexpartition.c */ 2121c80a6c00SStefano Zampini PetscInt p, pStart, pEnd, a, adjSize, idx, size, nroots; 2122c80a6c00SStefano Zampini PetscInt *adj = NULL; 2123c80a6c00SStefano Zampini IS cellNumbering; 2124c80a6c00SStefano Zampini const PetscInt *cellNum; 2125c80a6c00SStefano Zampini PetscBool useCone, useClosure; 2126c80a6c00SStefano Zampini PetscSection section; 2127c80a6c00SStefano Zampini PetscSegBuffer adjBuffer; 2128c80a6c00SStefano Zampini PetscSF sfPoint; 2129c80a6c00SStefano Zampini 21309566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd)); 21319566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 21329566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL)); 2133c80a6c00SStefano Zampini /* Build adjacency graph via a section/segbuffer */ 21349566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 21359566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 21369566063dSJacob Faibussowitsch PetscCall(PetscSegBufferCreate(sizeof(PetscInt), 1000, &adjBuffer)); 2137c80a6c00SStefano Zampini /* Always use FVM adjacency to create partitioner graph */ 21389566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 21399566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE)); 21409566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellNumbering(dm, &cellNumbering)); 21419566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cellNumbering, &cellNum)); 2142c80a6c00SStefano Zampini for (n = 0, p = pStart; p < pEnd; p++) { 2143c80a6c00SStefano Zampini /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 21449371c9d4SSatish Balay if (nroots > 0) { 21459371c9d4SSatish Balay if (cellNum[p] < 0) continue; 21469371c9d4SSatish Balay } 2147c80a6c00SStefano Zampini adjSize = PETSC_DETERMINE; 21489566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj)); 2149c80a6c00SStefano Zampini for (a = 0; a < adjSize; ++a) { 2150c80a6c00SStefano Zampini const PetscInt point = adj[a]; 21515cef3d0dSStefano Zampini if (pStart <= point && point < pEnd) { 2152c80a6c00SStefano Zampini PetscInt *PETSC_RESTRICT pBuf; 21539566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(section, p, 1)); 21549566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGetInts(adjBuffer, 1, &pBuf)); 2155c80a6c00SStefano Zampini *pBuf = point; 2156c80a6c00SStefano Zampini } 2157c80a6c00SStefano Zampini } 2158c80a6c00SStefano Zampini n++; 2159c80a6c00SStefano Zampini } 21609566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dm, useCone, useClosure)); 2161c80a6c00SStefano Zampini /* Derive CSR graph from section/segbuffer */ 21629566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 21639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &size)); 21649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n + 1, &xadj)); 2165c80a6c00SStefano Zampini for (idx = 0, p = pStart; p < pEnd; p++) { 21669371c9d4SSatish Balay if (nroots > 0) { 21679371c9d4SSatish Balay if (cellNum[p] < 0) continue; 21689371c9d4SSatish Balay } 21699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(section, p, &(xadj[idx++]))); 2170c80a6c00SStefano Zampini } 2171c80a6c00SStefano Zampini xadj[n] = size; 21729566063dSJacob Faibussowitsch PetscCall(PetscSegBufferExtractAlloc(adjBuffer, &adjncy)); 2173c80a6c00SStefano Zampini /* Clean up */ 21749566063dSJacob Faibussowitsch PetscCall(PetscSegBufferDestroy(&adjBuffer)); 21759566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 21769566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 2177c80a6c00SStefano Zampini graph->xadj = xadj; 2178c80a6c00SStefano Zampini graph->adjncy = adjncy; 2179c80a6c00SStefano Zampini } else { 2180c80a6c00SStefano Zampini Mat A; 21818361f951SStefano Zampini PetscBool isseqaij, flg_row; 2182c80a6c00SStefano Zampini 21839566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->pmat, &A)); 218463c961adSStefano Zampini if (!A->rmap->N || !A->cmap->N) { 21859566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphDestroy(&graph)); 21863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 218763c961adSStefano Zampini } 21889566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isseqaij)); 21894f1b2e48SStefano Zampini if (!isseqaij && filter) { 21901cf9b237SStefano Zampini PetscBool isseqdense; 21911cf9b237SStefano Zampini 21929566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATSEQDENSE, &isseqdense)); 21931cf9b237SStefano Zampini if (!isseqdense) { 21949566063dSJacob Faibussowitsch PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &B)); 21951cf9b237SStefano Zampini } else { /* TODO: rectangular case and LDA */ 21961cf9b237SStefano Zampini PetscScalar *array; 21971cf9b237SStefano Zampini PetscReal chop = 1.e-6; 21981cf9b237SStefano Zampini 21999566063dSJacob Faibussowitsch PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &B)); 22009566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(B, &array)); 22019566063dSJacob Faibussowitsch PetscCall(MatGetSize(B, &n, NULL)); 22021cf9b237SStefano Zampini for (i = 0; i < n; i++) { 22031cf9b237SStefano Zampini PetscInt j; 22041cf9b237SStefano Zampini for (j = i + 1; j < n; j++) { 22051cf9b237SStefano Zampini PetscReal thresh = chop * (PetscAbsScalar(array[i * (n + 1)]) + PetscAbsScalar(array[j * (n + 1)])); 22061cf9b237SStefano Zampini if (PetscAbsScalar(array[i * n + j]) < thresh) array[i * n + j] = 0.; 22071cf9b237SStefano Zampini if (PetscAbsScalar(array[j * n + i]) < thresh) array[j * n + i] = 0.; 22081cf9b237SStefano Zampini } 22091cf9b237SStefano Zampini } 22109566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(B, &array)); 22119566063dSJacob Faibussowitsch PetscCall(MatConvert(B, MATSEQAIJ, MAT_INPLACE_MATRIX, &B)); 22121cf9b237SStefano Zampini } 22134f1b2e48SStefano Zampini } else { 22149566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 22154f1b2e48SStefano Zampini B = A; 22164f1b2e48SStefano Zampini } 22179566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(B, 0, PETSC_TRUE, PETSC_FALSE, &n, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &flg_row)); 22184f1b2e48SStefano Zampini 22194f1b2e48SStefano Zampini /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */ 22204f1b2e48SStefano Zampini if (filter) { 22214f1b2e48SStefano Zampini PetscScalar *data; 22224f1b2e48SStefano Zampini PetscInt j, cum; 22234f1b2e48SStefano Zampini 22249566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(n + 1, &xadj_filtered, xadj[n], &adjncy_filtered)); 22259566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(B, &data)); 22264f1b2e48SStefano Zampini cum = 0; 22274f1b2e48SStefano Zampini for (i = 0; i < n; i++) { 22284f1b2e48SStefano Zampini PetscInt t; 22294f1b2e48SStefano Zampini 22304f1b2e48SStefano Zampini for (j = xadj[i]; j < xadj[i + 1]; j++) { 2231ad540459SPierre Jolivet if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) continue; 22324f1b2e48SStefano Zampini adjncy_filtered[cum + xadj_filtered[i]++] = adjncy[j]; 22334f1b2e48SStefano Zampini } 22344f1b2e48SStefano Zampini t = xadj_filtered[i]; 22354f1b2e48SStefano Zampini xadj_filtered[i] = cum; 22364f1b2e48SStefano Zampini cum += t; 22374f1b2e48SStefano Zampini } 22389566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(B, &data)); 22394f1b2e48SStefano Zampini graph->xadj = xadj_filtered; 22404f1b2e48SStefano Zampini graph->adjncy = adjncy_filtered; 22414f1b2e48SStefano Zampini } else { 22424f1b2e48SStefano Zampini graph->xadj = xadj; 22434f1b2e48SStefano Zampini graph->adjncy = adjncy; 22444f1b2e48SStefano Zampini } 2245c80a6c00SStefano Zampini } 2246c80a6c00SStefano Zampini /* compute local connected components using PCBDDCGraph */ 22479566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, n, 0, 1, &is_dummy)); 22489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is_dummy, &l2gmap_dummy)); 22499566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_dummy)); 22509566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphInit(graph, l2gmap_dummy, n, PETSC_MAX_INT)); 22519566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&l2gmap_dummy)); 22529566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphSetUp(graph, 1, NULL, NULL, 0, NULL, NULL)); 22539566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphComputeConnectedComponents(graph)); 2254c80a6c00SStefano Zampini 22554f1b2e48SStefano Zampini /* partial clean up */ 22569566063dSJacob Faibussowitsch PetscCall(PetscFree2(xadj_filtered, adjncy_filtered)); 2257c80a6c00SStefano Zampini if (B) { 2258c80a6c00SStefano Zampini PetscBool flg_row; 22599566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(B, 0, PETSC_TRUE, PETSC_FALSE, &n, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &flg_row)); 22609566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 22614f1b2e48SStefano Zampini } 2262c80a6c00SStefano Zampini if (isplex) { 22639566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 22649566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 2265c80a6c00SStefano Zampini } 22664f1b2e48SStefano Zampini 22674f1b2e48SStefano Zampini /* get back data */ 2268c80a6c00SStefano Zampini if (isplex) { 2269c80a6c00SStefano Zampini if (ncc) *ncc = graph->ncc; 2270c80a6c00SStefano Zampini if (cc || primalv) { 2271c80a6c00SStefano Zampini Mat A; 2272c80a6c00SStefano Zampini PetscBT btv, btvt; 2273c80a6c00SStefano Zampini PetscSection subSection; 2274c80a6c00SStefano Zampini PetscInt *ids, cum, cump, *cids, *pids; 2275c80a6c00SStefano Zampini 22769566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubdomainSection(dm, &subSection)); 22779566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->pmat, &A)); 22789566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(A->rmap->n, &ids, graph->ncc + 1, &cids, A->rmap->n, &pids)); 22799566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(A->rmap->n, &btv)); 22809566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(A->rmap->n, &btvt)); 2281c80a6c00SStefano Zampini 2282c80a6c00SStefano Zampini cids[0] = 0; 2283c80a6c00SStefano Zampini for (i = 0, cump = 0, cum = 0; i < graph->ncc; i++) { 2284c80a6c00SStefano Zampini PetscInt j; 2285c80a6c00SStefano Zampini 22869566063dSJacob Faibussowitsch PetscCall(PetscBTMemzero(A->rmap->n, btvt)); 2287c80a6c00SStefano Zampini for (j = graph->cptr[i]; j < graph->cptr[i + 1]; j++) { 2288c80a6c00SStefano Zampini PetscInt k, size, *closure = NULL, cell = graph->queue[j]; 2289c80a6c00SStefano Zampini 22909566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &size, &closure)); 2291c80a6c00SStefano Zampini for (k = 0; k < 2 * size; k += 2) { 229220c3699dSStefano Zampini PetscInt s, pp, p = closure[k], off, dof, cdof; 2293c80a6c00SStefano Zampini 22949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(subSection, p, &cdof)); 22959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(subSection, p, &off)); 22969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subSection, p, &dof)); 2297c80a6c00SStefano Zampini for (s = 0; s < dof - cdof; s++) { 2298c80a6c00SStefano Zampini if (PetscBTLookupSet(btvt, off + s)) continue; 2299e432b41dSStefano Zampini if (!PetscBTLookup(btv, off + s)) ids[cum++] = off + s; 2300e432b41dSStefano Zampini else pids[cump++] = off + s; /* cross-vertex */ 2301c80a6c00SStefano Zampini } 23029566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL)); 230320c3699dSStefano Zampini if (pp != p) { 23049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(subSection, pp, &cdof)); 23059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(subSection, pp, &off)); 23069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subSection, pp, &dof)); 230720c3699dSStefano Zampini for (s = 0; s < dof - cdof; s++) { 230820c3699dSStefano Zampini if (PetscBTLookupSet(btvt, off + s)) continue; 2309e432b41dSStefano Zampini if (!PetscBTLookup(btv, off + s)) ids[cum++] = off + s; 2310e432b41dSStefano Zampini else pids[cump++] = off + s; /* cross-vertex */ 231120c3699dSStefano Zampini } 231220c3699dSStefano Zampini } 2313c80a6c00SStefano Zampini } 23149566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &size, &closure)); 2315c80a6c00SStefano Zampini } 2316c80a6c00SStefano Zampini cids[i + 1] = cum; 2317c80a6c00SStefano Zampini /* mark dofs as already assigned */ 231848a46eb9SPierre Jolivet for (j = cids[i]; j < cids[i + 1]; j++) PetscCall(PetscBTSet(btv, ids[j])); 2319c80a6c00SStefano Zampini } 2320c80a6c00SStefano Zampini if (cc) { 23219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(graph->ncc, &cc_n)); 232248a46eb9SPierre Jolivet for (i = 0; i < graph->ncc; i++) PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cids[i + 1] - cids[i], ids + cids[i], PETSC_COPY_VALUES, &cc_n[i])); 2323c80a6c00SStefano Zampini *cc = cc_n; 2324c80a6c00SStefano Zampini } 23251baa6e33SBarry Smith if (primalv) PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), cump, pids, PETSC_COPY_VALUES, primalv)); 23269566063dSJacob Faibussowitsch PetscCall(PetscFree3(ids, cids, pids)); 23279566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btv)); 23289566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btvt)); 2329c80a6c00SStefano Zampini } 2330c80a6c00SStefano Zampini } else { 23311cf9b237SStefano Zampini if (ncc) *ncc = graph->ncc; 23321cf9b237SStefano Zampini if (cc) { 23339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(graph->ncc, &cc_n)); 233448a46eb9SPierre Jolivet for (i = 0; i < graph->ncc; i++) PetscCall(ISCreateGeneral(PETSC_COMM_SELF, graph->cptr[i + 1] - graph->cptr[i], graph->queue + graph->cptr[i], PETSC_COPY_VALUES, &cc_n[i])); 23354f1b2e48SStefano Zampini *cc = cc_n; 23361cf9b237SStefano Zampini } 2337c80a6c00SStefano Zampini } 23384f1b2e48SStefano Zampini /* clean up graph */ 23390a545947SLisandro Dalcin graph->xadj = NULL; 23400a545947SLisandro Dalcin graph->adjncy = NULL; 23419566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphDestroy(&graph)); 23423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23434f1b2e48SStefano Zampini } 23444f1b2e48SStefano Zampini 2345d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag) 2346d71ae5a4SJacob Faibussowitsch { 23475408967cSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 23485408967cSStefano Zampini PC_IS *pcis = (PC_IS *)(pc->data); 2349dee84bffSStefano Zampini IS dirIS = NULL; 23504f1b2e48SStefano Zampini PetscInt i; 23515408967cSStefano Zampini 23525408967cSStefano Zampini PetscFunctionBegin; 23539566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph, &dirIS)); 23545408967cSStefano Zampini if (zerodiag) { 23555408967cSStefano Zampini Mat A; 23565408967cSStefano Zampini Vec vec3_N; 23575408967cSStefano Zampini PetscScalar *vals; 23585408967cSStefano Zampini const PetscInt *idxs; 2359d12d3064SStefano Zampini PetscInt nz, *count; 23605408967cSStefano Zampini 23615408967cSStefano Zampini /* p0 */ 23629566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_N, 0.)); 23639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n, &vals)); 23649566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zerodiag, &nz)); 23659566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zerodiag, &idxs)); 23664f1b2e48SStefano Zampini for (i = 0; i < nz; i++) vals[i] = 1.; 23679566063dSJacob Faibussowitsch PetscCall(VecSetValues(pcis->vec1_N, nz, idxs, vals, INSERT_VALUES)); 23689566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(pcis->vec1_N)); 23699566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(pcis->vec1_N)); 23705408967cSStefano Zampini /* v_I */ 23719566063dSJacob Faibussowitsch PetscCall(VecSetRandom(pcis->vec2_N, NULL)); 23725408967cSStefano Zampini for (i = 0; i < nz; i++) vals[i] = 0.; 23739566063dSJacob Faibussowitsch PetscCall(VecSetValues(pcis->vec2_N, nz, idxs, vals, INSERT_VALUES)); 23749566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zerodiag, &idxs)); 23759566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_B_local, &idxs)); 23765408967cSStefano Zampini for (i = 0; i < pcis->n_B; i++) vals[i] = 0.; 23779566063dSJacob Faibussowitsch PetscCall(VecSetValues(pcis->vec2_N, pcis->n_B, idxs, vals, INSERT_VALUES)); 23789566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_B_local, &idxs)); 23795408967cSStefano Zampini if (dirIS) { 23805408967cSStefano Zampini PetscInt n; 23815408967cSStefano Zampini 23829566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(dirIS, &n)); 23839566063dSJacob Faibussowitsch PetscCall(ISGetIndices(dirIS, &idxs)); 23845408967cSStefano Zampini for (i = 0; i < n; i++) vals[i] = 0.; 23859566063dSJacob Faibussowitsch PetscCall(VecSetValues(pcis->vec2_N, n, idxs, vals, INSERT_VALUES)); 23869566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(dirIS, &idxs)); 23875408967cSStefano Zampini } 23889566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(pcis->vec2_N)); 23899566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(pcis->vec2_N)); 23909566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_N, &vec3_N)); 23919566063dSJacob Faibussowitsch PetscCall(VecSet(vec3_N, 0.)); 23929566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->pmat, &A)); 23939566063dSJacob Faibussowitsch PetscCall(MatMult(A, pcis->vec1_N, vec3_N)); 23949566063dSJacob Faibussowitsch PetscCall(VecDot(vec3_N, pcis->vec2_N, &vals[0])); 23957827d75bSBarry Smith PetscCheck(PetscAbsScalar(vals[0]) <= 1.e-1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Benign trick can not be applied! b(v_I,p_0) = %1.6e (should be numerically 0.)", (double)PetscAbsScalar(vals[0])); 23969566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 23979566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vec3_N)); 2398d12d3064SStefano Zampini 2399d12d3064SStefano Zampini /* there should not be any pressure dofs lying on the interface */ 24009566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pcis->n, &count)); 24019566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_B_local, &idxs)); 2402d12d3064SStefano Zampini for (i = 0; i < pcis->n_B; i++) count[idxs[i]]++; 24039566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_B_local, &idxs)); 24049566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zerodiag, &idxs)); 240563a3b9bcSJacob Faibussowitsch for (i = 0; i < nz; i++) PetscCheck(!count[idxs[i]], PETSC_COMM_SELF, PETSC_ERR_SUP, "Benign trick can not be applied! pressure dof %" PetscInt_FMT " is an interface dof", idxs[i]); 24069566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zerodiag, &idxs)); 24079566063dSJacob Faibussowitsch PetscCall(PetscFree(count)); 24085408967cSStefano Zampini } 24099566063dSJacob Faibussowitsch PetscCall(ISDestroy(&dirIS)); 24105408967cSStefano Zampini 24115408967cSStefano Zampini /* check PCBDDCBenignGetOrSetP0 */ 24129566063dSJacob Faibussowitsch PetscCall(VecSetRandom(pcis->vec1_global, NULL)); 24134f1b2e48SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) pcbddc->benign_p0[i] = -PetscGlobalRank - i; 24149566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc, pcis->vec1_global, PETSC_FALSE)); 24154f1b2e48SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) pcbddc->benign_p0[i] = 1; 24169566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc, pcis->vec1_global, PETSC_TRUE)); 2417f2a566d8SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) { 2418f2a566d8SStefano Zampini PetscInt val = PetscRealPart(pcbddc->benign_p0[i]); 241963a3b9bcSJacob Faibussowitsch PetscCheck(val == -PetscGlobalRank - i, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Error testing PCBDDCBenignGetOrSetP0! Found %g at %" PetscInt_FMT " instead of %g", (double)PetscRealPart(pcbddc->benign_p0[i]), i, (double)(-PetscGlobalRank - i)); 2420f2a566d8SStefano Zampini } 24213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24225408967cSStefano Zampini } 24235408967cSStefano Zampini 2424d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, PetscBool reuse, IS *zerodiaglocal) 2425d71ae5a4SJacob Faibussowitsch { 2426339f8db1SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 2427e432b41dSStefano Zampini Mat_IS *matis = (Mat_IS *)(pc->pmat->data); 24283b03f7bbSStefano Zampini IS pressures = NULL, zerodiag = NULL, *bzerodiag = NULL, zerodiag_save, *zerodiag_subs; 24293b03f7bbSStefano Zampini PetscInt nz, n, benign_n, bsp = 1; 24304edc6404Sstefano_zampini PetscInt *interior_dofs, n_interior_dofs, nneu; 24314edc6404Sstefano_zampini PetscBool sorted, have_null, has_null_pressures, recompute_zerodiag, checkb; 2432339f8db1SStefano Zampini 2433339f8db1SStefano Zampini PetscFunctionBegin; 24343b03f7bbSStefano Zampini if (reuse) goto project_b0; 24359566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pcbddc->benign_sf)); 24369566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->benign_B0)); 243748a46eb9SPierre Jolivet for (n = 0; n < pcbddc->benign_n; n++) PetscCall(ISDestroy(&pcbddc->benign_zerodiag_subs[n])); 24389566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->benign_zerodiag_subs)); 24393b03f7bbSStefano Zampini has_null_pressures = PETSC_TRUE; 24403b03f7bbSStefano Zampini have_null = PETSC_TRUE; 24413b03f7bbSStefano Zampini /* if a local information on dofs is present, gets pressure dofs from command line (uses the last field is not provided) 24423b03f7bbSStefano Zampini Without local information, it uses only the zerodiagonal dofs (ok if the pressure block is all zero and it is a scalar field) 24434f1b2e48SStefano Zampini Checks if all the pressure dofs in each subdomain have a zero diagonal 24444f1b2e48SStefano Zampini If not, a change of basis on pressures is not needed 24451ae86dd6SStefano Zampini since the local Schur complements are already SPD 24464f1b2e48SStefano Zampini */ 244740fa8d13SStefano Zampini if (pcbddc->n_ISForDofsLocal) { 24487fbe2174Sstefano_zampini IS iP = NULL; 24493b03f7bbSStefano Zampini PetscInt p, *pp; 24503b03f7bbSStefano Zampini PetscBool flg; 24514f1b2e48SStefano Zampini 24529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->n_ISForDofsLocal, &pp)); 24533b03f7bbSStefano Zampini n = pcbddc->n_ISForDofsLocal; 2454d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)pc), ((PetscObject)pc)->prefix, "BDDC benign options", "PC"); 24559566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-pc_bddc_pressure_field", "Field id for pressures", NULL, pp, &n, &flg)); 2456d0609cedSBarry Smith PetscOptionsEnd(); 24573b03f7bbSStefano Zampini if (!flg) { 24583b03f7bbSStefano Zampini n = 1; 24593b03f7bbSStefano Zampini pp[0] = pcbddc->n_ISForDofsLocal - 1; 24603b03f7bbSStefano Zampini } 24613b03f7bbSStefano Zampini 24623b03f7bbSStefano Zampini bsp = 0; 24633b03f7bbSStefano Zampini for (p = 0; p < n; p++) { 24643b03f7bbSStefano Zampini PetscInt bs; 24653b03f7bbSStefano Zampini 246663a3b9bcSJacob Faibussowitsch PetscCheck(pp[p] >= 0 && pp[p] < pcbddc->n_ISForDofsLocal, PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "Invalid field id for pressures %" PetscInt_FMT, pp[p]); 24679566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(pcbddc->ISForDofsLocal[pp[p]], &bs)); 24683b03f7bbSStefano Zampini bsp += bs; 24693b03f7bbSStefano Zampini } 24709566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bsp, &bzerodiag)); 24713b03f7bbSStefano Zampini bsp = 0; 24723b03f7bbSStefano Zampini for (p = 0; p < n; p++) { 24733b03f7bbSStefano Zampini const PetscInt *idxs; 24743b03f7bbSStefano Zampini PetscInt b, bs, npl, *bidxs; 24753b03f7bbSStefano Zampini 24769566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(pcbddc->ISForDofsLocal[pp[p]], &bs)); 24779566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->ISForDofsLocal[pp[p]], &npl)); 24789566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->ISForDofsLocal[pp[p]], &idxs)); 24799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(npl / bs, &bidxs)); 24803b03f7bbSStefano Zampini for (b = 0; b < bs; b++) { 24813b03f7bbSStefano Zampini PetscInt i; 24823b03f7bbSStefano Zampini 24833b03f7bbSStefano Zampini for (i = 0; i < npl / bs; i++) bidxs[i] = idxs[bs * i + b]; 24849566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, npl / bs, bidxs, PETSC_COPY_VALUES, &bzerodiag[bsp])); 24853b03f7bbSStefano Zampini bsp++; 24863b03f7bbSStefano Zampini } 24879566063dSJacob Faibussowitsch PetscCall(PetscFree(bidxs)); 24889566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->ISForDofsLocal[pp[p]], &idxs)); 24893b03f7bbSStefano Zampini } 24909566063dSJacob Faibussowitsch PetscCall(ISConcatenate(PETSC_COMM_SELF, bsp, bzerodiag, &pressures)); 24913b03f7bbSStefano Zampini 24927fbe2174Sstefano_zampini /* remove zeroed out pressures if we are setting up a BDDC solver for a saddle-point FETI-DP */ 24939566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lP", (PetscObject *)&iP)); 24947fbe2174Sstefano_zampini if (iP) { 24957fbe2174Sstefano_zampini IS newpressures; 24967fbe2174Sstefano_zampini 24979566063dSJacob Faibussowitsch PetscCall(ISDifference(pressures, iP, &newpressures)); 24989566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pressures)); 24997fbe2174Sstefano_zampini pressures = newpressures; 25007fbe2174Sstefano_zampini } 25019566063dSJacob Faibussowitsch PetscCall(ISSorted(pressures, &sorted)); 250248a46eb9SPierre Jolivet if (!sorted) PetscCall(ISSort(pressures)); 25039566063dSJacob Faibussowitsch PetscCall(PetscFree(pp)); 250440fa8d13SStefano Zampini } 25053b03f7bbSStefano Zampini 250697d764eeSStefano Zampini /* pcis has not been setup yet, so get the local size from the subdomain matrix */ 25079566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pcbddc->local_mat, &n, NULL)); 250827b6a85dSStefano Zampini if (!n) pcbddc->benign_change_explicit = PETSC_TRUE; 25099566063dSJacob Faibussowitsch PetscCall(MatFindZeroDiagonals(pcbddc->local_mat, &zerodiag)); 25109566063dSJacob Faibussowitsch PetscCall(ISSorted(zerodiag, &sorted)); 251148a46eb9SPierre Jolivet if (!sorted) PetscCall(ISSort(zerodiag)); 25129566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)zerodiag)); 25134edc6404Sstefano_zampini zerodiag_save = zerodiag; 25149566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zerodiag, &nz)); 25154f1b2e48SStefano Zampini if (!nz) { 25164f1b2e48SStefano Zampini if (n) have_null = PETSC_FALSE; 25174f1b2e48SStefano Zampini has_null_pressures = PETSC_FALSE; 25189566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zerodiag)); 251940fa8d13SStefano Zampini } 25204f1b2e48SStefano Zampini recompute_zerodiag = PETSC_FALSE; 25213b03f7bbSStefano Zampini 25224f1b2e48SStefano Zampini /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */ 25234f1b2e48SStefano Zampini zerodiag_subs = NULL; 25243b03f7bbSStefano Zampini benign_n = 0; 25251f4df5f7SStefano Zampini n_interior_dofs = 0; 25261f4df5f7SStefano Zampini interior_dofs = NULL; 25274edc6404Sstefano_zampini nneu = 0; 252848a46eb9SPierre Jolivet if (pcbddc->NeumannBoundariesLocal) PetscCall(ISGetLocalSize(pcbddc->NeumannBoundariesLocal, &nneu)); 25293369cb78Sstefano_zampini checkb = (PetscBool)(!pcbddc->NeumannBoundariesLocal || pcbddc->current_level); 25304edc6404Sstefano_zampini if (checkb) { /* need to compute interior nodes */ 25311f4df5f7SStefano Zampini PetscInt n, i, j; 25321f4df5f7SStefano Zampini PetscInt n_neigh, *neigh, *n_shared, **shared; 25331f4df5f7SStefano Zampini PetscInt *iwork; 25341f4df5f7SStefano Zampini 25359566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->rmapping, &n)); 25369566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetInfo(matis->rmapping, &n_neigh, &neigh, &n_shared, &shared)); 25379566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(n, &iwork)); 25389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &interior_dofs)); 253990648384SStefano Zampini for (i = 1; i < n_neigh; i++) 25409371c9d4SSatish Balay for (j = 0; j < n_shared[i]; j++) iwork[shared[i][j]] += 1; 25411f4df5f7SStefano Zampini for (i = 0; i < n; i++) 25429371c9d4SSatish Balay if (!iwork[i]) interior_dofs[n_interior_dofs++] = i; 25439566063dSJacob Faibussowitsch PetscCall(PetscFree(iwork)); 25449566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreInfo(matis->rmapping, &n_neigh, &neigh, &n_shared, &shared)); 25451f4df5f7SStefano Zampini } 25464f1b2e48SStefano Zampini if (has_null_pressures) { 25474f1b2e48SStefano Zampini IS *subs; 25484edc6404Sstefano_zampini PetscInt nsubs, i, j, nl; 25491f4df5f7SStefano Zampini const PetscInt *idxs; 25501f4df5f7SStefano Zampini PetscScalar *array; 25511f4df5f7SStefano Zampini Vec *work; 25524f1b2e48SStefano Zampini 25534f1b2e48SStefano Zampini subs = pcbddc->local_subs; 25544f1b2e48SStefano Zampini nsubs = pcbddc->n_local_subs; 25551f4df5f7SStefano 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) */ 25564edc6404Sstefano_zampini if (checkb) { 25579566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(matis->y, 2, &work)); 25589566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zerodiag, &nl)); 25599566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zerodiag, &idxs)); 25601f4df5f7SStefano Zampini /* work[0] = 1_p */ 25619566063dSJacob Faibussowitsch PetscCall(VecSet(work[0], 0.)); 25629566063dSJacob Faibussowitsch PetscCall(VecGetArray(work[0], &array)); 25631f4df5f7SStefano Zampini for (j = 0; j < nl; j++) array[idxs[j]] = 1.; 25649566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(work[0], &array)); 25651f4df5f7SStefano Zampini /* work[0] = 1_v */ 25669566063dSJacob Faibussowitsch PetscCall(VecSet(work[1], 1.)); 25679566063dSJacob Faibussowitsch PetscCall(VecGetArray(work[1], &array)); 25681f4df5f7SStefano Zampini for (j = 0; j < nl; j++) array[idxs[j]] = 0.; 25699566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(work[1], &array)); 25709566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zerodiag, &idxs)); 25711f4df5f7SStefano Zampini } 25723b03f7bbSStefano Zampini 25733b03f7bbSStefano Zampini if (nsubs > 1 || bsp > 1) { 25743b03f7bbSStefano Zampini IS *is; 25753b03f7bbSStefano Zampini PetscInt b, totb; 25763b03f7bbSStefano Zampini 25773b03f7bbSStefano Zampini totb = bsp; 25783b03f7bbSStefano Zampini is = bsp > 1 ? bzerodiag : &zerodiag; 25793b03f7bbSStefano Zampini nsubs = PetscMax(nsubs, 1); 25809566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nsubs * totb, &zerodiag_subs)); 25813b03f7bbSStefano Zampini for (b = 0; b < totb; b++) { 25824f1b2e48SStefano Zampini for (i = 0; i < nsubs; i++) { 25834f1b2e48SStefano Zampini ISLocalToGlobalMapping l2g; 25844f1b2e48SStefano Zampini IS t_zerodiag_subs; 25854f1b2e48SStefano Zampini PetscInt nl; 25864f1b2e48SStefano Zampini 25873b03f7bbSStefano Zampini if (subs) { 25889566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(subs[i], &l2g)); 25893b03f7bbSStefano Zampini } else { 25903b03f7bbSStefano Zampini IS tis; 25913b03f7bbSStefano Zampini 25929566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pcbddc->local_mat, &nl, NULL)); 25939566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, nl, 0, 1, &tis)); 25949566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(tis, &l2g)); 25959566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tis)); 25963b03f7bbSStefano Zampini } 25979566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(l2g, IS_GTOLM_DROP, is[b], &t_zerodiag_subs)); 25989566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(t_zerodiag_subs, &nl)); 25994f1b2e48SStefano Zampini if (nl) { 26004f1b2e48SStefano Zampini PetscBool valid = PETSC_TRUE; 26014f1b2e48SStefano Zampini 26024edc6404Sstefano_zampini if (checkb) { 26039566063dSJacob Faibussowitsch PetscCall(VecSet(matis->x, 0)); 26049566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(subs[i], &nl)); 26059566063dSJacob Faibussowitsch PetscCall(ISGetIndices(subs[i], &idxs)); 26069566063dSJacob Faibussowitsch PetscCall(VecGetArray(matis->x, &array)); 26071f4df5f7SStefano Zampini for (j = 0; j < nl; j++) array[idxs[j]] = 1.; 26089566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(matis->x, &array)); 26099566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(subs[i], &idxs)); 26109566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(matis->x, work[0], matis->x)); 26119566063dSJacob Faibussowitsch PetscCall(MatMult(matis->A, matis->x, matis->y)); 26129566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(matis->y, work[1], matis->y)); 26139566063dSJacob Faibussowitsch PetscCall(VecGetArray(matis->y, &array)); 26141f4df5f7SStefano Zampini for (j = 0; j < n_interior_dofs; j++) { 26151f4df5f7SStefano Zampini if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) { 26161f4df5f7SStefano Zampini valid = PETSC_FALSE; 26171f4df5f7SStefano Zampini break; 26181f4df5f7SStefano Zampini } 26191f4df5f7SStefano Zampini } 26209566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(matis->y, &array)); 26211f4df5f7SStefano Zampini } 26226632bad2Sstefano_zampini if (valid && nneu) { 26236632bad2Sstefano_zampini const PetscInt *idxs; 26241f4df5f7SStefano Zampini PetscInt nzb; 26251f4df5f7SStefano Zampini 26269566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->NeumannBoundariesLocal, &idxs)); 26279566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(l2g, IS_GTOLM_DROP, nneu, idxs, &nzb, NULL)); 26289566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->NeumannBoundariesLocal, &idxs)); 26291f4df5f7SStefano Zampini if (nzb) valid = PETSC_FALSE; 26301f4df5f7SStefano Zampini } 26311f4df5f7SStefano Zampini if (valid && pressures) { 26323b03f7bbSStefano Zampini IS t_pressure_subs, tmp; 26333b03f7bbSStefano Zampini PetscInt i1, i2; 26343b03f7bbSStefano Zampini 26359566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(l2g, IS_GTOLM_DROP, pressures, &t_pressure_subs)); 26369566063dSJacob Faibussowitsch PetscCall(ISEmbed(t_zerodiag_subs, t_pressure_subs, PETSC_TRUE, &tmp)); 26379566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(tmp, &i1)); 26389566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(t_zerodiag_subs, &i2)); 26393b03f7bbSStefano Zampini if (i2 != i1) valid = PETSC_FALSE; 26409566063dSJacob Faibussowitsch PetscCall(ISDestroy(&t_pressure_subs)); 26419566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tmp)); 26424f1b2e48SStefano Zampini } 26434f1b2e48SStefano Zampini if (valid) { 26449566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(l2g, t_zerodiag_subs, &zerodiag_subs[benign_n])); 26453b03f7bbSStefano Zampini benign_n++; 26463b03f7bbSStefano Zampini } else recompute_zerodiag = PETSC_TRUE; 26474f1b2e48SStefano Zampini } 26489566063dSJacob Faibussowitsch PetscCall(ISDestroy(&t_zerodiag_subs)); 26499566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&l2g)); 26504f1b2e48SStefano Zampini } 26513b03f7bbSStefano Zampini } 26524f1b2e48SStefano Zampini } else { /* there's just one subdomain (or zero if they have not been detected */ 26534f1b2e48SStefano Zampini PetscBool valid = PETSC_TRUE; 26541f4df5f7SStefano Zampini 26556632bad2Sstefano_zampini if (nneu) valid = PETSC_FALSE; 265648a46eb9SPierre Jolivet if (valid && pressures) PetscCall(ISEqual(pressures, zerodiag, &valid)); 26574edc6404Sstefano_zampini if (valid && checkb) { 26589566063dSJacob Faibussowitsch PetscCall(MatMult(matis->A, work[0], matis->x)); 26599566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(matis->x, work[1], matis->x)); 26609566063dSJacob Faibussowitsch PetscCall(VecGetArray(matis->x, &array)); 26611f4df5f7SStefano Zampini for (j = 0; j < n_interior_dofs; j++) { 26621f4df5f7SStefano Zampini if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) { 26631f4df5f7SStefano Zampini valid = PETSC_FALSE; 26641f4df5f7SStefano Zampini break; 26651f4df5f7SStefano Zampini } 26661f4df5f7SStefano Zampini } 26679566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(matis->x, &array)); 26681f4df5f7SStefano Zampini } 26694f1b2e48SStefano Zampini if (valid) { 26703b03f7bbSStefano Zampini benign_n = 1; 26719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(benign_n, &zerodiag_subs)); 26729566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)zerodiag)); 26734f1b2e48SStefano Zampini zerodiag_subs[0] = zerodiag; 26744f1b2e48SStefano Zampini } 26754f1b2e48SStefano Zampini } 267648a46eb9SPierre Jolivet if (checkb) PetscCall(VecDestroyVecs(2, &work)); 26771f4df5f7SStefano Zampini } 26789566063dSJacob Faibussowitsch PetscCall(PetscFree(interior_dofs)); 26794f1b2e48SStefano Zampini 26803b03f7bbSStefano Zampini if (!benign_n) { 2681b9b0e38cSStefano Zampini PetscInt n; 2682b9b0e38cSStefano Zampini 26839566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zerodiag)); 26844f1b2e48SStefano Zampini recompute_zerodiag = PETSC_FALSE; 26859566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pcbddc->local_mat, &n, NULL)); 268676a58201SStefano Zampini if (n) have_null = PETSC_FALSE; 2687b9b0e38cSStefano Zampini } 26884f1b2e48SStefano Zampini 26894f1b2e48SStefano Zampini /* final check for null pressures */ 269048a46eb9SPierre Jolivet if (zerodiag && pressures) PetscCall(ISEqual(pressures, zerodiag, &have_null)); 26914f1b2e48SStefano Zampini 26924f1b2e48SStefano Zampini if (recompute_zerodiag) { 26939566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zerodiag)); 26943b03f7bbSStefano Zampini if (benign_n == 1) { 26959566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)zerodiag_subs[0])); 26964f1b2e48SStefano Zampini zerodiag = zerodiag_subs[0]; 26974f1b2e48SStefano Zampini } else { 26984f1b2e48SStefano Zampini PetscInt i, nzn, *new_idxs; 26994f1b2e48SStefano Zampini 27004f1b2e48SStefano Zampini nzn = 0; 27013b03f7bbSStefano Zampini for (i = 0; i < benign_n; i++) { 27024f1b2e48SStefano Zampini PetscInt ns; 27039566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zerodiag_subs[i], &ns)); 27044f1b2e48SStefano Zampini nzn += ns; 27054f1b2e48SStefano Zampini } 27069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nzn, &new_idxs)); 27074f1b2e48SStefano Zampini nzn = 0; 27083b03f7bbSStefano Zampini for (i = 0; i < benign_n; i++) { 27094f1b2e48SStefano Zampini PetscInt ns, *idxs; 27109566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zerodiag_subs[i], &ns)); 27119566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zerodiag_subs[i], (const PetscInt **)&idxs)); 27129566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(new_idxs + nzn, idxs, ns)); 27139566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zerodiag_subs[i], (const PetscInt **)&idxs)); 27144f1b2e48SStefano Zampini nzn += ns; 27154f1b2e48SStefano Zampini } 27169566063dSJacob Faibussowitsch PetscCall(PetscSortInt(nzn, new_idxs)); 27179566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nzn, new_idxs, PETSC_OWN_POINTER, &zerodiag)); 27184f1b2e48SStefano Zampini } 27194f1b2e48SStefano Zampini have_null = PETSC_FALSE; 27204f1b2e48SStefano Zampini } 27214f1b2e48SStefano Zampini 27223b03f7bbSStefano Zampini /* determines if the coarse solver will be singular or not */ 27231c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&have_null, &pcbddc->benign_null, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)pc))); 27243b03f7bbSStefano Zampini 2725669cc0f4SStefano Zampini /* Prepare matrix to compute no-net-flux */ 2726a198735bSStefano Zampini if (pcbddc->compute_nonetflux && !pcbddc->divudotp) { 2727a198735bSStefano Zampini Mat A, loc_divudotp; 2728a198735bSStefano Zampini ISLocalToGlobalMapping rl2g, cl2g, l2gmap; 2729a198735bSStefano Zampini IS row, col, isused = NULL; 2730a198735bSStefano Zampini PetscInt M, N, n, st, n_isused; 2731a198735bSStefano Zampini 27321f4df5f7SStefano Zampini if (pressures) { 27331f4df5f7SStefano Zampini isused = pressures; 27341f4df5f7SStefano Zampini } else { 27354edc6404Sstefano_zampini isused = zerodiag_save; 27361f4df5f7SStefano Zampini } 27379566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(pc->pmat, &l2gmap, NULL)); 27389566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->pmat, &A)); 27399566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &n, NULL)); 27407827d75bSBarry Smith PetscCheck(isused || (n == 0), PETSC_COMM_SELF, PETSC_ERR_USER, "Don't know how to extract div u dot p! Please provide the pressure field"); 2741a198735bSStefano Zampini n_isused = 0; 274248a46eb9SPierre Jolivet if (isused) PetscCall(ISGetLocalSize(isused, &n_isused)); 27439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Scan(&n_isused, &st, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)pc))); 2744a198735bSStefano Zampini st = st - n_isused; 27451ae86dd6SStefano Zampini if (n) { 2746a198735bSStefano Zampini const PetscInt *gidxs; 2747a198735bSStefano Zampini 27489566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, isused, NULL, MAT_INITIAL_MATRIX, &loc_divudotp)); 27499566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(l2gmap, &gidxs)); 2750a198735bSStefano Zampini /* TODO: extend ISCreateStride with st = PETSC_DECIDE */ 27519566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)pc), n_isused, st, 1, &row)); 27529566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), n, gidxs, PETSC_COPY_VALUES, &col)); 27539566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(l2gmap, &gidxs)); 27541ae86dd6SStefano Zampini } else { 27559566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, 0, 0, 1, NULL, &loc_divudotp)); 27569566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)pc), n_isused, st, 1, &row)); 27579566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), 0, NULL, PETSC_COPY_VALUES, &col)); 2758a198735bSStefano Zampini } 27599566063dSJacob Faibussowitsch PetscCall(MatGetSize(pc->pmat, NULL, &N)); 27609566063dSJacob Faibussowitsch PetscCall(ISGetSize(row, &M)); 27619566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(row, &rl2g)); 27629566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(col, &cl2g)); 27639566063dSJacob Faibussowitsch PetscCall(ISDestroy(&row)); 27649566063dSJacob Faibussowitsch PetscCall(ISDestroy(&col)); 27659566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)pc), &pcbddc->divudotp)); 27669566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->divudotp, MATIS)); 27679566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->divudotp, PETSC_DECIDE, PETSC_DECIDE, M, N)); 27689566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(pcbddc->divudotp, rl2g, cl2g)); 27699566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 27709566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 27719566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(pcbddc->divudotp, loc_divudotp)); 27729566063dSJacob Faibussowitsch PetscCall(MatDestroy(&loc_divudotp)); 27739566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pcbddc->divudotp, MAT_FINAL_ASSEMBLY)); 27749566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->divudotp, MAT_FINAL_ASSEMBLY)); 27751ae86dd6SStefano Zampini } 27769566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zerodiag_save)); 27779566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pressures)); 27783b03f7bbSStefano Zampini if (bzerodiag) { 27793b03f7bbSStefano Zampini PetscInt i; 2780b3afcdbeSStefano Zampini 278148a46eb9SPierre Jolivet for (i = 0; i < bsp; i++) PetscCall(ISDestroy(&bzerodiag[i])); 27829566063dSJacob Faibussowitsch PetscCall(PetscFree(bzerodiag)); 27833b03f7bbSStefano Zampini } 27843b03f7bbSStefano Zampini pcbddc->benign_n = benign_n; 27853b03f7bbSStefano Zampini pcbddc->benign_zerodiag_subs = zerodiag_subs; 27863b03f7bbSStefano Zampini 27873b03f7bbSStefano Zampini /* determines if the problem has subdomains with 0 pressure block */ 27883b03f7bbSStefano Zampini have_null = (PetscBool)(!!pcbddc->benign_n); 27891c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&have_null, &pcbddc->benign_have_null, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 27903b03f7bbSStefano Zampini 27913b03f7bbSStefano Zampini project_b0: 27929566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pcbddc->local_mat, &n, NULL)); 2793b3afcdbeSStefano Zampini /* change of basis and p0 dofs */ 27943b03f7bbSStefano Zampini if (pcbddc->benign_n) { 27954f1b2e48SStefano Zampini PetscInt i, s, *nnz; 27964f1b2e48SStefano Zampini 2797339f8db1SStefano Zampini /* local change of basis for pressures */ 27989566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->benign_change)); 27999566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat), &pcbddc->benign_change)); 28009566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->benign_change, MATAIJ)); 28019566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->benign_change, n, n, PETSC_DECIDE, PETSC_DECIDE)); 28029566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &nnz)); 2803aa0d93e9SStefano Zampini for (i = 0; i < n; i++) nnz[i] = 1; /* defaults to identity */ 28044f1b2e48SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) { 2805aa0d93e9SStefano Zampini const PetscInt *idxs; 28064f1b2e48SStefano Zampini PetscInt nzs, j; 28074f1b2e48SStefano Zampini 28089566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[i], &nzs)); 28099566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->benign_zerodiag_subs[i], &idxs)); 28104f1b2e48SStefano Zampini for (j = 0; j < nzs - 1; j++) nnz[idxs[j]] = 2; /* change on pressures */ 28114f1b2e48SStefano Zampini nnz[idxs[nzs - 1]] = nzs; /* last local pressure dof in subdomain */ 28129566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->benign_zerodiag_subs[i], &idxs)); 28134f1b2e48SStefano Zampini } 28149566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(pcbddc->benign_change, 0, nnz)); 28159566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->benign_change, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 28169566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 2817aa0d93e9SStefano Zampini /* set identity by default */ 281848a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall(MatSetValue(pcbddc->benign_change, i, i, 1., INSERT_VALUES)); 28199566063dSJacob Faibussowitsch PetscCall(PetscFree3(pcbddc->benign_p0_lidx, pcbddc->benign_p0_gidx, pcbddc->benign_p0)); 28209566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(pcbddc->benign_n, &pcbddc->benign_p0_lidx, pcbddc->benign_n, &pcbddc->benign_p0_gidx, pcbddc->benign_n, &pcbddc->benign_p0)); 2821339f8db1SStefano Zampini /* set change on pressures */ 28224f1b2e48SStefano Zampini for (s = 0; s < pcbddc->benign_n; s++) { 28234f1b2e48SStefano Zampini PetscScalar *array; 2824aa0d93e9SStefano Zampini const PetscInt *idxs; 28254f1b2e48SStefano Zampini PetscInt nzs; 28264f1b2e48SStefano Zampini 28279566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[s], &nzs)); 28289566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->benign_zerodiag_subs[s], &idxs)); 28294f1b2e48SStefano Zampini for (i = 0; i < nzs - 1; i++) { 2830339f8db1SStefano Zampini PetscScalar vals[2]; 2831339f8db1SStefano Zampini PetscInt cols[2]; 2832339f8db1SStefano Zampini 2833339f8db1SStefano Zampini cols[0] = idxs[i]; 28344f1b2e48SStefano Zampini cols[1] = idxs[nzs - 1]; 2835339f8db1SStefano Zampini vals[0] = 1.; 2836b0f5fe93SStefano Zampini vals[1] = 1.; 28379566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->benign_change, 1, cols, 2, cols, vals, INSERT_VALUES)); 2838339f8db1SStefano Zampini } 28399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nzs, &array)); 28404f1b2e48SStefano Zampini for (i = 0; i < nzs - 1; i++) array[i] = -1.; 28414f1b2e48SStefano Zampini array[nzs - 1] = 1.; 28429566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->benign_change, 1, idxs + nzs - 1, nzs, idxs, array, INSERT_VALUES)); 28434f1b2e48SStefano Zampini /* store local idxs for p0 */ 28444f1b2e48SStefano Zampini pcbddc->benign_p0_lidx[s] = idxs[nzs - 1]; 28459566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->benign_zerodiag_subs[s], &idxs)); 28469566063dSJacob Faibussowitsch PetscCall(PetscFree(array)); 28474f1b2e48SStefano Zampini } 28489566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pcbddc->benign_change, MAT_FINAL_ASSEMBLY)); 28499566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->benign_change, MAT_FINAL_ASSEMBLY)); 28503b03f7bbSStefano Zampini 2851a3df083aSStefano Zampini /* project if needed */ 2852a3df083aSStefano Zampini if (pcbddc->benign_change_explicit) { 28531dd7afcfSStefano Zampini Mat M; 28541dd7afcfSStefano Zampini 28559566063dSJacob Faibussowitsch PetscCall(MatPtAP(pcbddc->local_mat, pcbddc->benign_change, MAT_INITIAL_MATRIX, 2.0, &M)); 28569566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 28579566063dSJacob Faibussowitsch PetscCall(MatSeqAIJCompress(M, &pcbddc->local_mat)); 28589566063dSJacob Faibussowitsch PetscCall(MatDestroy(&M)); 2859a3df083aSStefano Zampini } 28604f1b2e48SStefano Zampini /* store global idxs for p0 */ 28619566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(matis->rmapping, pcbddc->benign_n, pcbddc->benign_p0_lidx, pcbddc->benign_p0_gidx)); 2862339f8db1SStefano Zampini } 2863339f8db1SStefano Zampini *zerodiaglocal = zerodiag; 28643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2865339f8db1SStefano Zampini } 2866339f8db1SStefano Zampini 2867d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get) 2868d71ae5a4SJacob Faibussowitsch { 2869efc2fbd9SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 2870de9d7bd0SStefano Zampini PetscScalar *array; 2871efc2fbd9SStefano Zampini 2872efc2fbd9SStefano Zampini PetscFunctionBegin; 2873efc2fbd9SStefano Zampini if (!pcbddc->benign_sf) { 28749566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)pc), &pcbddc->benign_sf)); 28759566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(pcbddc->benign_sf, pc->pmat->rmap, pcbddc->benign_n, NULL, PETSC_OWN_POINTER, pcbddc->benign_p0_gidx)); 2876efc2fbd9SStefano Zampini } 2877de9d7bd0SStefano Zampini if (get) { 28789566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, (const PetscScalar **)&array)); 28799566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pcbddc->benign_sf, MPIU_SCALAR, array, pcbddc->benign_p0, MPI_REPLACE)); 28809566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pcbddc->benign_sf, MPIU_SCALAR, array, pcbddc->benign_p0, MPI_REPLACE)); 28819566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, (const PetscScalar **)&array)); 2882de9d7bd0SStefano Zampini } else { 28839566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 28849566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(pcbddc->benign_sf, MPIU_SCALAR, pcbddc->benign_p0, array, MPI_REPLACE)); 28859566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(pcbddc->benign_sf, MPIU_SCALAR, pcbddc->benign_p0, array, MPI_REPLACE)); 28869566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 2887efc2fbd9SStefano Zampini } 28883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2889efc2fbd9SStefano Zampini } 2890efc2fbd9SStefano Zampini 2891d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop) 2892d71ae5a4SJacob Faibussowitsch { 2893c263805aSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 2894c263805aSStefano Zampini 2895c263805aSStefano Zampini PetscFunctionBegin; 2896c263805aSStefano Zampini /* TODO: add error checking 2897c263805aSStefano Zampini - avoid nested pop (or push) calls. 2898c263805aSStefano Zampini - cannot push before pop. 28991c604dc7SStefano Zampini - cannot call this if pcbddc->local_mat is NULL 2900c263805aSStefano Zampini */ 29013ba16761SJacob Faibussowitsch if (!pcbddc->benign_n) PetscFunctionReturn(PETSC_SUCCESS); 2902c263805aSStefano Zampini if (pop) { 2903a3df083aSStefano Zampini if (pcbddc->benign_change_explicit) { 29044f1b2e48SStefano Zampini IS is_p0; 29054f1b2e48SStefano Zampini MatReuse reuse; 2906c263805aSStefano Zampini 2907c263805aSStefano Zampini /* extract B_0 */ 29084f1b2e48SStefano Zampini reuse = MAT_INITIAL_MATRIX; 2909ad540459SPierre Jolivet if (pcbddc->benign_B0) reuse = MAT_REUSE_MATRIX; 29109566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, pcbddc->benign_n, pcbddc->benign_p0_lidx, PETSC_COPY_VALUES, &is_p0)); 29119566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, is_p0, NULL, reuse, &pcbddc->benign_B0)); 2912c263805aSStefano Zampini /* remove rows and cols from local problem */ 29139566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->local_mat, MAT_KEEP_NONZERO_PATTERN, PETSC_TRUE)); 29149566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->local_mat, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_FALSE)); 29159566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumnsIS(pcbddc->local_mat, is_p0, 1.0, NULL, NULL)); 29169566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_p0)); 2917a3df083aSStefano Zampini } else { 2918a3df083aSStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 2919a3df083aSStefano Zampini PetscScalar *vals; 2920a3df083aSStefano Zampini PetscInt i, n, *idxs_ins; 2921a3df083aSStefano Zampini 29229566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(matis->y, &n)); 29239566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n, &idxs_ins, n, &vals)); 2924a3df083aSStefano Zampini if (!pcbddc->benign_B0) { 29250b5adadeSStefano Zampini PetscInt *nnz; 29269566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat), &pcbddc->benign_B0)); 29279566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->benign_B0, MATAIJ)); 29289566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->benign_B0, pcbddc->benign_n, n, PETSC_DECIDE, PETSC_DECIDE)); 29299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->benign_n, &nnz)); 2930331e053bSStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) { 29319566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[i], &nnz[i])); 2932331e053bSStefano Zampini nnz[i] = n - nnz[i]; 2933331e053bSStefano Zampini } 29349566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(pcbddc->benign_B0, 0, nnz)); 29359566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->benign_B0, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 29369566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 2937331e053bSStefano Zampini } 2938a3df083aSStefano Zampini 2939a3df083aSStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) { 2940a3df083aSStefano Zampini PetscScalar *array; 2941a3df083aSStefano Zampini PetscInt *idxs, j, nz, cum; 2942a3df083aSStefano Zampini 29439566063dSJacob Faibussowitsch PetscCall(VecSet(matis->x, 0.)); 29449566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[i], &nz)); 29459566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->benign_zerodiag_subs[i], (const PetscInt **)&idxs)); 2946a3df083aSStefano Zampini for (j = 0; j < nz; j++) vals[j] = 1.; 29479566063dSJacob Faibussowitsch PetscCall(VecSetValues(matis->x, nz, idxs, vals, INSERT_VALUES)); 29489566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(matis->x)); 29499566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(matis->x)); 29509566063dSJacob Faibussowitsch PetscCall(VecSet(matis->y, 0.)); 29519566063dSJacob Faibussowitsch PetscCall(MatMult(matis->A, matis->x, matis->y)); 29529566063dSJacob Faibussowitsch PetscCall(VecGetArray(matis->y, &array)); 2953a3df083aSStefano Zampini cum = 0; 2954a3df083aSStefano Zampini for (j = 0; j < n; j++) { 295522db5ddcSStefano Zampini if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) { 2956a3df083aSStefano Zampini vals[cum] = array[j]; 2957a3df083aSStefano Zampini idxs_ins[cum] = j; 2958a3df083aSStefano Zampini cum++; 2959a3df083aSStefano Zampini } 2960a3df083aSStefano Zampini } 29619566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->benign_B0, 1, &i, cum, idxs_ins, vals, INSERT_VALUES)); 29629566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(matis->y, &array)); 29639566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->benign_zerodiag_subs[i], (const PetscInt **)&idxs)); 2964a3df083aSStefano Zampini } 29659566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pcbddc->benign_B0, MAT_FINAL_ASSEMBLY)); 29669566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->benign_B0, MAT_FINAL_ASSEMBLY)); 29679566063dSJacob Faibussowitsch PetscCall(PetscFree2(idxs_ins, vals)); 2968a3df083aSStefano Zampini } 2969c263805aSStefano Zampini } else { /* push */ 29704f1b2e48SStefano Zampini 29710fdf79fbSJacob Faibussowitsch PetscCheck(pcbddc->benign_change_explicit, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Cannot push B0!"); 29720fdf79fbSJacob Faibussowitsch for (PetscInt i = 0; i < pcbddc->benign_n; i++) { 29734f1b2e48SStefano Zampini PetscScalar *B0_vals; 29744f1b2e48SStefano Zampini PetscInt *B0_cols, B0_ncol; 29754f1b2e48SStefano Zampini 29769566063dSJacob Faibussowitsch PetscCall(MatGetRow(pcbddc->benign_B0, i, &B0_ncol, (const PetscInt **)&B0_cols, (const PetscScalar **)&B0_vals)); 29779566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->local_mat, 1, pcbddc->benign_p0_lidx + i, B0_ncol, B0_cols, B0_vals, INSERT_VALUES)); 29789566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->local_mat, B0_ncol, B0_cols, 1, pcbddc->benign_p0_lidx + i, B0_vals, INSERT_VALUES)); 29799566063dSJacob Faibussowitsch PetscCall(MatSetValue(pcbddc->local_mat, pcbddc->benign_p0_lidx[i], pcbddc->benign_p0_lidx[i], 0.0, INSERT_VALUES)); 29809566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(pcbddc->benign_B0, i, &B0_ncol, (const PetscInt **)&B0_cols, (const PetscScalar **)&B0_vals)); 29814f1b2e48SStefano Zampini } 29829566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pcbddc->local_mat, MAT_FINAL_ASSEMBLY)); 29839566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->local_mat, MAT_FINAL_ASSEMBLY)); 2984c263805aSStefano Zampini } 29853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2986c263805aSStefano Zampini } 2987c263805aSStefano Zampini 2988d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCAdaptiveSelection(PC pc) 2989d71ae5a4SJacob Faibussowitsch { 2990b1b3d7a2SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 299108122e43SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 299208122e43SStefano Zampini PetscBLASInt B_dummyint, B_neigs, B_ierr, B_lwork; 299308122e43SStefano Zampini PetscBLASInt *B_iwork, *B_ifail; 299408122e43SStefano Zampini PetscScalar *work, lwork; 299508122e43SStefano Zampini PetscScalar *St, *S, *eigv; 299608122e43SStefano Zampini PetscScalar *Sarray, *Starray; 2997bd2a564bSStefano Zampini PetscReal *eigs, thresh, lthresh, uthresh; 29981b968477SStefano Zampini PetscInt i, nmax, nmin, nv, cum, mss, cum2, cumarray, maxneigs; 299932fe681dSStefano Zampini PetscBool allocated_S_St, upart; 300008122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 300108122e43SStefano Zampini PetscReal *rwork; 300208122e43SStefano Zampini #endif 3003b1b3d7a2SStefano Zampini 3004b1b3d7a2SStefano Zampini PetscFunctionBegin; 30053ba16761SJacob Faibussowitsch if (!pcbddc->adaptive_selection) PetscFunctionReturn(PETSC_SUCCESS); 300628b400f6SJacob Faibussowitsch PetscCheck(sub_schurs, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Adaptive selection of constraints requires SubSchurs data"); 300732fe681dSStefano Zampini PetscCheck(sub_schurs->schur_explicit || !sub_schurs->n_subs, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Adaptive selection of constraints requires MUMPS and/or MKL_CPARDISO"); 30089371c9d4SSatish Balay PetscCheck(!sub_schurs->n_subs || sub_schurs->is_symmetric, PETSC_COMM_SELF, PETSC_ERR_SUP, "Adaptive selection not yet implemented for this matrix pencil (herm %d, symm %d, posdef %d)", sub_schurs->is_hermitian, sub_schurs->is_symmetric, 30099371c9d4SSatish Balay sub_schurs->is_posdef); 30109566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_AdaptiveSetUp[pcbddc->current_level], pc, 0, 0, 0)); 301106a4e24aSStefano Zampini 3012fd14bc51SStefano Zampini if (pcbddc->dbg_flag) { 301332fe681dSStefano Zampini if (!pcbddc->dbg_viewer) pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc)); 30149566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 30159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 30169566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Check adaptive selection of constraints\n")); 30179566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 3018fd14bc51SStefano Zampini } 3019fd14bc51SStefano Zampini 302048a46eb9SPierre Jolivet if (pcbddc->dbg_flag) PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d cc %" PetscInt_FMT " (%d,%d).\n", PetscGlobalRank, sub_schurs->n_subs, sub_schurs->is_hermitian, sub_schurs->is_posdef)); 3021e496cd5dSStefano Zampini 302208122e43SStefano Zampini /* max size of subsets */ 302308122e43SStefano Zampini mss = 0; 302408122e43SStefano Zampini for (i = 0; i < sub_schurs->n_subs; i++) { 302508122e43SStefano Zampini PetscInt subset_size; 3026862806e4SStefano Zampini 30279566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->is_subs[i], &subset_size)); 302808122e43SStefano Zampini mss = PetscMax(mss, subset_size); 302908122e43SStefano Zampini } 303008122e43SStefano Zampini 303108122e43SStefano Zampini /* min/max and threshold */ 303208122e43SStefano Zampini nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss; 3033f6f667cfSStefano Zampini nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0; 303408122e43SStefano Zampini nmax = PetscMax(nmin, nmax); 3035f6f667cfSStefano Zampini allocated_S_St = PETSC_FALSE; 3036bd2a564bSStefano Zampini if (nmin || !sub_schurs->is_posdef) { /* XXX */ 3037f6f667cfSStefano Zampini allocated_S_St = PETSC_TRUE; 3038f6f667cfSStefano Zampini } 303908122e43SStefano Zampini 304008122e43SStefano Zampini /* allocate lapack workspace */ 304108122e43SStefano Zampini cum = cum2 = 0; 304208122e43SStefano Zampini maxneigs = 0; 304308122e43SStefano Zampini for (i = 0; i < sub_schurs->n_subs; i++) { 304408122e43SStefano Zampini PetscInt n, subset_size; 3045f6f667cfSStefano Zampini 30469566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->is_subs[i], &subset_size)); 304708122e43SStefano Zampini n = PetscMin(subset_size, nmax); 30489162d606SStefano Zampini cum += subset_size; 30499162d606SStefano Zampini cum2 += subset_size * n; 305008122e43SStefano Zampini maxneigs = PetscMax(maxneigs, n); 305108122e43SStefano Zampini } 30527ebab0bbSStefano Zampini lwork = 0; 305308122e43SStefano Zampini if (mss) { 30547ebab0bbSStefano Zampini PetscScalar sdummy = 0.; 305508122e43SStefano Zampini PetscBLASInt B_itype = 1; 30567ebab0bbSStefano Zampini PetscBLASInt B_N = mss, idummy = 0; 30577ebab0bbSStefano Zampini PetscReal rdummy = 0., zero = 0.0; 30584c6709b3SStefano Zampini PetscReal eps = 0.0; /* dlamch? */ 305908122e43SStefano Zampini 30600fdf79fbSJacob Faibussowitsch PetscCheck(sub_schurs->is_symmetric, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not yet implemented"); 306108122e43SStefano Zampini B_lwork = -1; 30627ebab0bbSStefano Zampini /* some implementations may complain about NULL pointers, even if we are querying */ 30637ebab0bbSStefano Zampini S = &sdummy; 30647ebab0bbSStefano Zampini St = &sdummy; 30657ebab0bbSStefano Zampini eigs = &rdummy; 30667ebab0bbSStefano Zampini eigv = &sdummy; 30677ebab0bbSStefano Zampini B_iwork = &idummy; 30687ebab0bbSStefano Zampini B_ifail = &idummy; 3069d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX) 30707ebab0bbSStefano Zampini rwork = &rdummy; 3071d1710679SStefano Zampini #endif 30728bec7fa6SStefano Zampini thresh = 1.0; 30739566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 307408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 3075792fecdfSBarry Smith PetscCallBLAS("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)); 307608122e43SStefano Zampini #else 3077792fecdfSBarry Smith PetscCallBLAS("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)); 307808122e43SStefano Zampini #endif 307908401ef6SPierre Jolivet PetscCheck(B_ierr == 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in query to SYGVX Lapack routine %d", (int)B_ierr); 30809566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 308108122e43SStefano Zampini } 308208122e43SStefano Zampini 308308122e43SStefano Zampini nv = 0; 3084d62866d3SStefano 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) */ 30859566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->is_vertices, &nv)); 308608122e43SStefano Zampini } 30879566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(lwork), &B_lwork)); 308848a46eb9SPierre Jolivet if (allocated_S_St) PetscCall(PetscMalloc2(mss * mss, &S, mss * mss, &St)); 30899566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(mss * mss, &eigv, mss, &eigs, B_lwork, &work, 5 * mss, &B_iwork, mss, &B_ifail)); 309008122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 30919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(7 * mss, &rwork)); 309208122e43SStefano Zampini #endif 30939371c9d4SSatish Balay PetscCall(PetscMalloc5(nv + sub_schurs->n_subs, &pcbddc->adaptive_constraints_n, nv + sub_schurs->n_subs + 1, &pcbddc->adaptive_constraints_idxs_ptr, nv + sub_schurs->n_subs + 1, &pcbddc->adaptive_constraints_data_ptr, nv + cum, &pcbddc->adaptive_constraints_idxs, nv + cum2, 30949371c9d4SSatish Balay &pcbddc->adaptive_constraints_data)); 30959566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(pcbddc->adaptive_constraints_n, nv + sub_schurs->n_subs)); 309608122e43SStefano Zampini 309708122e43SStefano Zampini maxneigs = 0; 309872b8c272SStefano Zampini cum = cumarray = 0; 30999162d606SStefano Zampini pcbddc->adaptive_constraints_idxs_ptr[0] = 0; 31009162d606SStefano Zampini pcbddc->adaptive_constraints_data_ptr[0] = 0; 3101d62866d3SStefano Zampini if (sub_schurs->is_vertices && pcbddc->use_vertices) { 310208122e43SStefano Zampini const PetscInt *idxs; 310308122e43SStefano Zampini 31049566063dSJacob Faibussowitsch PetscCall(ISGetIndices(sub_schurs->is_vertices, &idxs)); 310508122e43SStefano Zampini for (cum = 0; cum < nv; cum++) { 310608122e43SStefano Zampini pcbddc->adaptive_constraints_n[cum] = 1; 310708122e43SStefano Zampini pcbddc->adaptive_constraints_idxs[cum] = idxs[cum]; 310808122e43SStefano Zampini pcbddc->adaptive_constraints_data[cum] = 1.0; 31099162d606SStefano Zampini pcbddc->adaptive_constraints_idxs_ptr[cum + 1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + 1; 31109162d606SStefano Zampini pcbddc->adaptive_constraints_data_ptr[cum + 1] = pcbddc->adaptive_constraints_data_ptr[cum] + 1; 311108122e43SStefano Zampini } 31129566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(sub_schurs->is_vertices, &idxs)); 311308122e43SStefano Zampini } 311408122e43SStefano Zampini 311508122e43SStefano Zampini if (mss) { /* multilevel */ 311632fe681dSStefano Zampini if (sub_schurs->gdsw) { 311732fe681dSStefano Zampini PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_all, &Sarray)); 311832fe681dSStefano Zampini PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all, &Starray)); 311932fe681dSStefano Zampini } else { 31209566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all, &Sarray)); 31219566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all, &Starray)); 312208122e43SStefano Zampini } 312332fe681dSStefano Zampini } 312408122e43SStefano Zampini 3125bd2a564bSStefano Zampini lthresh = pcbddc->adaptive_threshold[0]; 3126bd2a564bSStefano Zampini uthresh = pcbddc->adaptive_threshold[1]; 312732fe681dSStefano Zampini upart = pcbddc->use_deluxe_scaling; 312808122e43SStefano Zampini for (i = 0; i < sub_schurs->n_subs; i++) { 312908122e43SStefano Zampini const PetscInt *idxs; 31309d54b7f4SStefano Zampini PetscReal upper, lower; 3131862806e4SStefano Zampini PetscInt j, subset_size, eigs_start = 0; 313208122e43SStefano Zampini PetscBLASInt B_N; 3133aff50787SStefano Zampini PetscBool same_data = PETSC_FALSE; 3134bd2a564bSStefano Zampini PetscBool scal = PETSC_FALSE; 313508122e43SStefano Zampini 313632fe681dSStefano Zampini if (upart) { 31379d54b7f4SStefano Zampini upper = PETSC_MAX_REAL; 3138bd2a564bSStefano Zampini lower = uthresh; 31399d54b7f4SStefano Zampini } else { 314032fe681dSStefano Zampini if (sub_schurs->gdsw) { 314132fe681dSStefano Zampini upper = uthresh; 314232fe681dSStefano Zampini lower = PETSC_MIN_REAL; 314332fe681dSStefano Zampini } else { 314428b400f6SJacob Faibussowitsch PetscCheck(sub_schurs->is_posdef, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not yet implemented without deluxe scaling"); 3145bd2a564bSStefano Zampini upper = 1. / uthresh; 31469d54b7f4SStefano Zampini lower = 0.; 31479d54b7f4SStefano Zampini } 314832fe681dSStefano Zampini } 31499566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->is_subs[i], &subset_size)); 31509566063dSJacob Faibussowitsch PetscCall(ISGetIndices(sub_schurs->is_subs[i], &idxs)); 31519566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(subset_size, &B_N)); 3152bd2a564bSStefano Zampini /* this is experimental: we assume the dofs have been properly grouped to have 3153bd2a564bSStefano Zampini the diagonal blocks Schur complements either positive or negative definite (true for Stokes) */ 3154bd2a564bSStefano Zampini if (!sub_schurs->is_posdef) { 3155bd2a564bSStefano Zampini Mat T; 3156bd2a564bSStefano Zampini 3157bd2a564bSStefano Zampini for (j = 0; j < subset_size; j++) { 3158bd2a564bSStefano Zampini if (PetscRealPart(*(Sarray + cumarray + j * (subset_size + 1))) < 0.0) { 31599566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, subset_size, subset_size, Sarray + cumarray, &T)); 31609566063dSJacob Faibussowitsch PetscCall(MatScale(T, -1.0)); 31619566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 31629566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, subset_size, subset_size, Starray + cumarray, &T)); 31639566063dSJacob Faibussowitsch PetscCall(MatScale(T, -1.0)); 31649566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 3165bd2a564bSStefano Zampini if (sub_schurs->change_primal_sub) { 3166bd2a564bSStefano Zampini PetscInt nz, k; 3167bd2a564bSStefano Zampini const PetscInt *idxs; 3168bd2a564bSStefano Zampini 31699566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->change_primal_sub[i], &nz)); 31709566063dSJacob Faibussowitsch PetscCall(ISGetIndices(sub_schurs->change_primal_sub[i], &idxs)); 3171bd2a564bSStefano Zampini for (k = 0; k < nz; k++) { 3172bd2a564bSStefano Zampini *(Sarray + cumarray + idxs[k] * (subset_size + 1)) *= -1.0; 3173bd2a564bSStefano Zampini *(Starray + cumarray + idxs[k] * (subset_size + 1)) = 0.0; 3174bd2a564bSStefano Zampini } 31759566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(sub_schurs->change_primal_sub[i], &idxs)); 3176bd2a564bSStefano Zampini } 3177bd2a564bSStefano Zampini scal = PETSC_TRUE; 3178bd2a564bSStefano Zampini break; 3179bd2a564bSStefano Zampini } 3180bd2a564bSStefano Zampini } 3181bd2a564bSStefano Zampini } 3182bd2a564bSStefano Zampini 3183f6f667cfSStefano Zampini if (allocated_S_St) { /* S and S_t should be copied since we could need them later */ 3184bd2a564bSStefano Zampini if (sub_schurs->is_symmetric) { 3185aff50787SStefano Zampini PetscInt j, k; 3186580bdb30SBarry Smith if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscArraycmp() later */ 31879566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(S, subset_size * subset_size)); 31889566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(St, subset_size * subset_size)); 318908122e43SStefano Zampini } 319008122e43SStefano Zampini for (j = 0; j < subset_size; j++) { 3191aff50787SStefano Zampini for (k = j; k < subset_size; k++) { 3192aff50787SStefano Zampini S[j * subset_size + k] = Sarray[cumarray + j * subset_size + k]; 3193aff50787SStefano Zampini St[j * subset_size + k] = Starray[cumarray + j * subset_size + k]; 3194aff50787SStefano Zampini } 319508122e43SStefano Zampini } 319608122e43SStefano Zampini } else { 31979566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 31989566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 319908122e43SStefano Zampini } 32008bec7fa6SStefano Zampini } else { 3201f6f667cfSStefano Zampini S = Sarray + cumarray; 3202f6f667cfSStefano Zampini St = Starray + cumarray; 32038bec7fa6SStefano Zampini } 3204aff50787SStefano Zampini /* see if we can save some work */ 320548a46eb9SPierre Jolivet if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) PetscCall(PetscArraycmp(S, St, subset_size * subset_size, &same_data)); 3206aff50787SStefano Zampini 3207b7ab4a40SStefano Zampini if (same_data && !sub_schurs->change) { /* there's no need of constraints here */ 3208aff50787SStefano Zampini B_neigs = 0; 3209aff50787SStefano Zampini } else { 321008122e43SStefano Zampini PetscBLASInt B_itype = 1; 3211f6f667cfSStefano Zampini PetscBLASInt B_IL, B_IU; 32124c6709b3SStefano Zampini PetscReal eps = -1.0; /* dlamch? */ 32139552c7c7SStefano Zampini PetscInt nmin_s; 3214bd2a564bSStefano Zampini PetscBool compute_range; 3215bd2a564bSStefano Zampini 32160fdf79fbSJacob Faibussowitsch PetscCheck(sub_schurs->is_symmetric, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not yet implemented"); 32179036ceccSStefano Zampini B_neigs = 0; 3218bd2a564bSStefano Zampini compute_range = (PetscBool)!same_data; 3219bd2a564bSStefano Zampini if (nmin >= subset_size) compute_range = PETSC_FALSE; 322008122e43SStefano Zampini 3221fd14bc51SStefano Zampini if (pcbddc->dbg_flag) { 32229036ceccSStefano Zampini PetscInt nc = 0; 3223d16cbb6bSStefano Zampini 322448a46eb9SPierre Jolivet if (sub_schurs->change_primal_sub) PetscCall(ISGetLocalSize(sub_schurs->change_primal_sub[i], &nc)); 32259371c9d4SSatish Balay PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Computing for sub %" PetscInt_FMT "/%" PetscInt_FMT " size %" PetscInt_FMT " count %" PetscInt_FMT " fid %" PetscInt_FMT " (range %d) (change %" PetscInt_FMT ").\n", i, 32269371c9d4SSatish Balay sub_schurs->n_subs, subset_size, pcbddc->mat_graph->count[idxs[0]] + 1, pcbddc->mat_graph->which_dof[idxs[0]], compute_range, nc)); 3227b7ab4a40SStefano Zampini } 3228b7ab4a40SStefano Zampini 32299566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 3230b7ab4a40SStefano Zampini if (compute_range) { 3231d16cbb6bSStefano Zampini /* ask for eigenvalues larger than thresh */ 3232bd2a564bSStefano Zampini if (sub_schurs->is_posdef) { 323308122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 3234792fecdfSBarry Smith PetscCallBLAS("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)); 323508122e43SStefano Zampini #else 3236792fecdfSBarry Smith PetscCallBLAS("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)); 323708122e43SStefano Zampini #endif 32389566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 3239bd2a564bSStefano Zampini } else { /* no theory so far, but it works nicely */ 32409036ceccSStefano Zampini PetscInt recipe = 0, recipe_m = 1; 3241bd2a564bSStefano Zampini PetscReal bb[2]; 3242bd2a564bSStefano Zampini 32439566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)pc)->prefix, "-pc_bddc_adaptive_recipe", &recipe, NULL)); 3244bd2a564bSStefano Zampini switch (recipe) { 3245bd2a564bSStefano Zampini case 0: 32469371c9d4SSatish Balay if (scal) { 32479371c9d4SSatish Balay bb[0] = PETSC_MIN_REAL; 32489371c9d4SSatish Balay bb[1] = lthresh; 32499371c9d4SSatish Balay } else { 32509371c9d4SSatish Balay bb[0] = uthresh; 32519371c9d4SSatish Balay bb[1] = PETSC_MAX_REAL; 32529371c9d4SSatish Balay } 3253bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3254792fecdfSBarry Smith PetscCallBLAS("LAPACKsygvx", LAPACKsygvx_(&B_itype, "V", "V", "L", &B_N, St, &B_N, S, &B_N, &bb[0], &bb[1], &B_IL, &B_IU, &eps, &B_neigs, eigs, eigv, &B_N, work, &B_lwork, rwork, B_iwork, B_ifail, &B_ierr)); 3255bd2a564bSStefano Zampini #else 3256792fecdfSBarry Smith PetscCallBLAS("LAPACKsygvx", LAPACKsygvx_(&B_itype, "V", "V", "L", &B_N, St, &B_N, S, &B_N, &bb[0], &bb[1], &B_IL, &B_IU, &eps, &B_neigs, eigs, eigv, &B_N, work, &B_lwork, B_iwork, B_ifail, &B_ierr)); 3257bd2a564bSStefano Zampini #endif 32589566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 3259bd2a564bSStefano Zampini break; 3260d71ae5a4SJacob Faibussowitsch case 1: 3261d71ae5a4SJacob Faibussowitsch bb[0] = PETSC_MIN_REAL; 3262d71ae5a4SJacob Faibussowitsch bb[1] = lthresh * lthresh; 3263bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3264792fecdfSBarry Smith PetscCallBLAS("LAPACKsygvx", LAPACKsygvx_(&B_itype, "V", "V", "L", &B_N, St, &B_N, S, &B_N, &bb[0], &bb[1], &B_IL, &B_IU, &eps, &B_neigs, eigs, eigv, &B_N, work, &B_lwork, rwork, B_iwork, B_ifail, &B_ierr)); 3265bd2a564bSStefano Zampini #else 3266792fecdfSBarry Smith PetscCallBLAS("LAPACKsygvx", LAPACKsygvx_(&B_itype, "V", "V", "L", &B_N, St, &B_N, S, &B_N, &bb[0], &bb[1], &B_IL, &B_IU, &eps, &B_neigs, eigs, eigv, &B_N, work, &B_lwork, B_iwork, B_ifail, &B_ierr)); 3267bd2a564bSStefano Zampini #endif 32689566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 3269bd2a564bSStefano Zampini if (!scal) { 32709036ceccSStefano Zampini PetscBLASInt B_neigs2 = 0; 3271bd2a564bSStefano Zampini 32729371c9d4SSatish Balay bb[0] = PetscMax(lthresh * lthresh, uthresh); 32739371c9d4SSatish Balay bb[1] = PETSC_MAX_REAL; 32749566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 32759566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 3276bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3277792fecdfSBarry Smith PetscCallBLAS("LAPACKsygvx", LAPACKsygvx_(&B_itype, "V", "V", "L", &B_N, St, &B_N, S, &B_N, &bb[0], &bb[1], &B_IL, &B_IU, &eps, &B_neigs2, eigs + B_neigs, eigv + B_neigs * B_N, &B_N, work, &B_lwork, rwork, B_iwork, B_ifail, &B_ierr)); 3278bd2a564bSStefano Zampini #else 3279792fecdfSBarry Smith PetscCallBLAS("LAPACKsygvx", LAPACKsygvx_(&B_itype, "V", "V", "L", &B_N, St, &B_N, S, &B_N, &bb[0], &bb[1], &B_IL, &B_IU, &eps, &B_neigs2, eigs + B_neigs, eigv + B_neigs * B_N, &B_N, work, &B_lwork, B_iwork, B_ifail, &B_ierr)); 3280bd2a564bSStefano Zampini #endif 32819566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 3282bd2a564bSStefano Zampini B_neigs += B_neigs2; 3283bd2a564bSStefano Zampini } 3284bd2a564bSStefano Zampini break; 32859036ceccSStefano Zampini case 2: 32869036ceccSStefano Zampini if (scal) { 32879036ceccSStefano Zampini bb[0] = PETSC_MIN_REAL; 32889036ceccSStefano Zampini bb[1] = 0; 32899036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3290792fecdfSBarry Smith PetscCallBLAS("LAPACKsygvx", LAPACKsygvx_(&B_itype, "V", "V", "L", &B_N, St, &B_N, S, &B_N, &bb[0], &bb[1], &B_IL, &B_IU, &eps, &B_neigs, eigs, eigv, &B_N, work, &B_lwork, rwork, B_iwork, B_ifail, &B_ierr)); 32919036ceccSStefano Zampini #else 3292792fecdfSBarry Smith PetscCallBLAS("LAPACKsygvx", LAPACKsygvx_(&B_itype, "V", "V", "L", &B_N, St, &B_N, S, &B_N, &bb[0], &bb[1], &B_IL, &B_IU, &eps, &B_neigs, eigs, eigv, &B_N, work, &B_lwork, B_iwork, B_ifail, &B_ierr)); 32939036ceccSStefano Zampini #endif 32949566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 32959036ceccSStefano Zampini } else { 32969036ceccSStefano Zampini PetscBLASInt B_neigs2 = 0; 329713bcc0bdSJacob Faibussowitsch PetscBool do_copy = PETSC_FALSE; 32989036ceccSStefano Zampini 32999036ceccSStefano Zampini lthresh = PetscMax(lthresh, 0.0); 33009036ceccSStefano Zampini if (lthresh > 0.0) { 33019036ceccSStefano Zampini bb[0] = PETSC_MIN_REAL; 33029036ceccSStefano Zampini bb[1] = lthresh * lthresh; 33039036ceccSStefano Zampini 330413bcc0bdSJacob Faibussowitsch do_copy = PETSC_TRUE; 33059036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3306792fecdfSBarry Smith PetscCallBLAS("LAPACKsygvx", LAPACKsygvx_(&B_itype, "V", "V", "L", &B_N, St, &B_N, S, &B_N, &bb[0], &bb[1], &B_IL, &B_IU, &eps, &B_neigs, eigs, eigv, &B_N, work, &B_lwork, rwork, B_iwork, B_ifail, &B_ierr)); 33079036ceccSStefano Zampini #else 3308792fecdfSBarry Smith PetscCallBLAS("LAPACKsygvx", LAPACKsygvx_(&B_itype, "V", "V", "L", &B_N, St, &B_N, S, &B_N, &bb[0], &bb[1], &B_IL, &B_IU, &eps, &B_neigs, eigs, eigv, &B_N, work, &B_lwork, B_iwork, B_ifail, &B_ierr)); 33099036ceccSStefano Zampini #endif 33109566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 33119036ceccSStefano Zampini } 33129036ceccSStefano Zampini bb[0] = PetscMax(lthresh * lthresh, uthresh); 33139036ceccSStefano Zampini bb[1] = PETSC_MAX_REAL; 331413bcc0bdSJacob Faibussowitsch if (do_copy) { 33159566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 33169566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 33179036ceccSStefano Zampini } 33189036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3319792fecdfSBarry Smith PetscCallBLAS("LAPACKsygvx", LAPACKsygvx_(&B_itype, "V", "V", "L", &B_N, St, &B_N, S, &B_N, &bb[0], &bb[1], &B_IL, &B_IU, &eps, &B_neigs2, eigs + B_neigs, eigv + B_neigs * B_N, &B_N, work, &B_lwork, rwork, B_iwork, B_ifail, &B_ierr)); 33209036ceccSStefano Zampini #else 3321792fecdfSBarry Smith PetscCallBLAS("LAPACKsygvx", LAPACKsygvx_(&B_itype, "V", "V", "L", &B_N, St, &B_N, S, &B_N, &bb[0], &bb[1], &B_IL, &B_IU, &eps, &B_neigs2, eigs + B_neigs, eigv + B_neigs * B_N, &B_N, work, &B_lwork, B_iwork, B_ifail, &B_ierr)); 33229036ceccSStefano Zampini #endif 33239566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 33249036ceccSStefano Zampini B_neigs += B_neigs2; 33259036ceccSStefano Zampini } 33269036ceccSStefano Zampini break; 33279036ceccSStefano Zampini case 3: 33289036ceccSStefano Zampini if (scal) { 33299566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)pc)->prefix, "-pc_bddc_adaptive_recipe3_min_scal", &recipe_m, NULL)); 33309036ceccSStefano Zampini } else { 33319566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)pc)->prefix, "-pc_bddc_adaptive_recipe3_min", &recipe_m, NULL)); 33329036ceccSStefano Zampini } 33339036ceccSStefano Zampini if (!scal) { 33349036ceccSStefano Zampini bb[0] = uthresh; 33359036ceccSStefano Zampini bb[1] = PETSC_MAX_REAL; 33369036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3337792fecdfSBarry Smith PetscCallBLAS("LAPACKsygvx", LAPACKsygvx_(&B_itype, "V", "V", "L", &B_N, St, &B_N, S, &B_N, &bb[0], &bb[1], &B_IL, &B_IU, &eps, &B_neigs, eigs, eigv, &B_N, work, &B_lwork, rwork, B_iwork, B_ifail, &B_ierr)); 33389036ceccSStefano Zampini #else 3339792fecdfSBarry Smith PetscCallBLAS("LAPACKsygvx", LAPACKsygvx_(&B_itype, "V", "V", "L", &B_N, St, &B_N, S, &B_N, &bb[0], &bb[1], &B_IL, &B_IU, &eps, &B_neigs, eigs, eigv, &B_N, work, &B_lwork, B_iwork, B_ifail, &B_ierr)); 33409036ceccSStefano Zampini #endif 33419566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 33429036ceccSStefano Zampini } 33439036ceccSStefano Zampini if (recipe_m > 0 && B_N - B_neigs > 0) { 33449036ceccSStefano Zampini PetscBLASInt B_neigs2 = 0; 33459036ceccSStefano Zampini 33469036ceccSStefano Zampini B_IL = 1; 33479566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(PetscMin(recipe_m, B_N - B_neigs), &B_IU)); 33489566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 33499566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 33509036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3351792fecdfSBarry Smith PetscCallBLAS("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 * B_N, &B_N, work, &B_lwork, rwork, B_iwork, B_ifail, &B_ierr)); 33529036ceccSStefano Zampini #else 3353792fecdfSBarry Smith PetscCallBLAS("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 * B_N, &B_N, work, &B_lwork, B_iwork, B_ifail, &B_ierr)); 33549036ceccSStefano Zampini #endif 33559566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 33569036ceccSStefano Zampini B_neigs += B_neigs2; 33579036ceccSStefano Zampini } 33589036ceccSStefano Zampini break; 3359d71ae5a4SJacob Faibussowitsch case 4: 3360d71ae5a4SJacob Faibussowitsch bb[0] = PETSC_MIN_REAL; 3361d71ae5a4SJacob Faibussowitsch bb[1] = lthresh; 336248cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX) 3363792fecdfSBarry Smith PetscCallBLAS("LAPACKsygvx", LAPACKsygvx_(&B_itype, "V", "V", "L", &B_N, St, &B_N, S, &B_N, &bb[0], &bb[1], &B_IL, &B_IU, &eps, &B_neigs, eigs, eigv, &B_N, work, &B_lwork, rwork, B_iwork, B_ifail, &B_ierr)); 336448cebe81SStefano Zampini #else 3365792fecdfSBarry Smith PetscCallBLAS("LAPACKsygvx", LAPACKsygvx_(&B_itype, "V", "V", "L", &B_N, St, &B_N, S, &B_N, &bb[0], &bb[1], &B_IL, &B_IU, &eps, &B_neigs, eigs, eigv, &B_N, work, &B_lwork, B_iwork, B_ifail, &B_ierr)); 336648cebe81SStefano Zampini #endif 33679566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 336848cebe81SStefano Zampini { 336948cebe81SStefano Zampini PetscBLASInt B_neigs2 = 0; 337048cebe81SStefano Zampini 33719371c9d4SSatish Balay bb[0] = PetscMax(lthresh + PETSC_SMALL, uthresh); 33729371c9d4SSatish Balay bb[1] = PETSC_MAX_REAL; 33739566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 33749566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 337548cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX) 3376792fecdfSBarry Smith PetscCallBLAS("LAPACKsygvx", LAPACKsygvx_(&B_itype, "V", "V", "L", &B_N, St, &B_N, S, &B_N, &bb[0], &bb[1], &B_IL, &B_IU, &eps, &B_neigs2, eigs + B_neigs, eigv + B_neigs * B_N, &B_N, work, &B_lwork, rwork, B_iwork, B_ifail, &B_ierr)); 337748cebe81SStefano Zampini #else 3378792fecdfSBarry Smith PetscCallBLAS("LAPACKsygvx", LAPACKsygvx_(&B_itype, "V", "V", "L", &B_N, St, &B_N, S, &B_N, &bb[0], &bb[1], &B_IL, &B_IU, &eps, &B_neigs2, eigs + B_neigs, eigv + B_neigs * B_N, &B_N, work, &B_lwork, B_iwork, B_ifail, &B_ierr)); 337948cebe81SStefano Zampini #endif 33809566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 338148cebe81SStefano Zampini B_neigs += B_neigs2; 338248cebe81SStefano Zampini } 338348cebe81SStefano Zampini break; 338480db8efeSStefano Zampini case 5: /* same as before: first compute all eigenvalues, then filter */ 338580db8efeSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3386792fecdfSBarry Smith PetscCallBLAS("LAPACKsygvx", LAPACKsygvx_(&B_itype, "V", "A", "L", &B_N, St, &B_N, S, &B_N, &bb[0], &bb[1], &B_IL, &B_IU, &eps, &B_neigs, eigs, eigv, &B_N, work, &B_lwork, rwork, B_iwork, B_ifail, &B_ierr)); 338780db8efeSStefano Zampini #else 3388792fecdfSBarry Smith PetscCallBLAS("LAPACKsygvx", LAPACKsygvx_(&B_itype, "V", "A", "L", &B_N, St, &B_N, S, &B_N, &bb[0], &bb[1], &B_IL, &B_IU, &eps, &B_neigs, eigs, eigv, &B_N, work, &B_lwork, B_iwork, B_ifail, &B_ierr)); 338980db8efeSStefano Zampini #endif 33909566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 339180db8efeSStefano Zampini { 339280db8efeSStefano Zampini PetscInt e, k, ne; 339380db8efeSStefano Zampini for (e = 0, ne = 0; e < B_neigs; e++) { 339480db8efeSStefano Zampini if (eigs[e] < lthresh || eigs[e] > uthresh) { 339580db8efeSStefano Zampini for (k = 0; k < B_N; k++) S[ne * B_N + k] = eigv[e * B_N + k]; 339680db8efeSStefano Zampini eigs[ne] = eigs[e]; 339780db8efeSStefano Zampini ne++; 339880db8efeSStefano Zampini } 339980db8efeSStefano Zampini } 34009566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(eigv, S, B_N * ne)); 340180db8efeSStefano Zampini B_neigs = ne; 340280db8efeSStefano Zampini } 340380db8efeSStefano Zampini break; 3404d71ae5a4SJacob Faibussowitsch default: 3405d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Unknown recipe %" PetscInt_FMT, recipe); 3406bd2a564bSStefano Zampini } 3407bd2a564bSStefano Zampini } 3408bd2a564bSStefano Zampini } else if (!same_data) { /* this is just to see all the eigenvalues */ 3409d16cbb6bSStefano Zampini B_IU = PetscMax(1, PetscMin(B_N, nmax)); 3410d16cbb6bSStefano Zampini B_IL = 1; 3411d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3412792fecdfSBarry Smith PetscCallBLAS("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)); 3413d16cbb6bSStefano Zampini #else 3414792fecdfSBarry Smith PetscCallBLAS("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)); 3415d16cbb6bSStefano Zampini #endif 34169566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 3417b03ebc13SStefano Zampini } else { /* same_data is true, so just get the adaptive functional requested by the user */ 3418b7ab4a40SStefano Zampini PetscInt k; 341928b400f6SJacob Faibussowitsch PetscCheck(sub_schurs->change_primal_sub, PETSC_COMM_SELF, PETSC_ERR_PLIB, "This should not happen"); 34209566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->change_primal_sub[i], &nmax)); 34219566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(nmax, &B_neigs)); 3422b7ab4a40SStefano Zampini nmin = nmax; 34239566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(eigv, subset_size * nmax)); 3424b7ab4a40SStefano Zampini for (k = 0; k < nmax; k++) { 3425b7ab4a40SStefano Zampini eigs[k] = 1. / PETSC_SMALL; 3426b7ab4a40SStefano Zampini eigv[k * (subset_size + 1)] = 1.0; 3427b7ab4a40SStefano Zampini } 3428d16cbb6bSStefano Zampini } 34299566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 343008122e43SStefano Zampini if (B_ierr) { 343163a3b9bcSJacob Faibussowitsch PetscCheck(B_ierr >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in SYGVX Lapack routine: illegal value for argument %" PetscBLASInt_FMT, -B_ierr); 343263a3b9bcSJacob Faibussowitsch PetscCheck(B_ierr > B_N, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in SYGVX Lapack routine: %" PetscBLASInt_FMT " eigenvalues failed to converge", B_ierr); 343363a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in SYGVX Lapack routine: leading minor of order %" PetscBLASInt_FMT " is not positive definite", B_ierr - B_N - 1); 343408122e43SStefano Zampini } 343508122e43SStefano Zampini 343608122e43SStefano Zampini if (B_neigs > nmax) { 343748a46eb9SPierre Jolivet if (pcbddc->dbg_flag) PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " found %" PetscBLASInt_FMT " eigs, more than maximum required %" PetscInt_FMT ".\n", B_neigs, nmax)); 343832fe681dSStefano Zampini if (upart) eigs_start = scal ? 0 : B_neigs - nmax; 343908122e43SStefano Zampini B_neigs = nmax; 344008122e43SStefano Zampini } 344108122e43SStefano Zampini 34429552c7c7SStefano Zampini nmin_s = PetscMin(nmin, B_N); 34439552c7c7SStefano Zampini if (B_neigs < nmin_s) { 34449036ceccSStefano Zampini PetscBLASInt B_neigs2 = 0; 344508122e43SStefano Zampini 344632fe681dSStefano Zampini if (upart) { 3447bd2a564bSStefano Zampini if (scal) { 3448bd2a564bSStefano Zampini B_IU = nmin_s; 3449bd2a564bSStefano Zampini B_IL = B_neigs + 1; 3450bd2a564bSStefano Zampini } else { 3451f6f667cfSStefano Zampini B_IL = B_N - nmin_s + 1; 34529d54b7f4SStefano Zampini B_IU = B_N - B_neigs; 3453bd2a564bSStefano Zampini } 34549d54b7f4SStefano Zampini } else { 34559d54b7f4SStefano Zampini B_IL = B_neigs + 1; 34569d54b7f4SStefano Zampini B_IU = nmin_s; 34579d54b7f4SStefano Zampini } 3458fd14bc51SStefano Zampini if (pcbddc->dbg_flag) { 345963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " found %" PetscBLASInt_FMT " eigs, less than minimum required %" PetscInt_FMT ". Asking for %" PetscBLASInt_FMT " to %" PetscBLASInt_FMT " incl (fortran like)\n", B_neigs, nmin, B_IL, B_IU)); 3460fd14bc51SStefano Zampini } 3461bd2a564bSStefano Zampini if (sub_schurs->is_symmetric) { 34621ae86dd6SStefano Zampini PetscInt j, k; 346308122e43SStefano Zampini for (j = 0; j < subset_size; j++) { 34641ae86dd6SStefano Zampini for (k = j; k < subset_size; k++) { 34651ae86dd6SStefano Zampini S[j * subset_size + k] = Sarray[cumarray + j * subset_size + k]; 34661ae86dd6SStefano Zampini St[j * subset_size + k] = Starray[cumarray + j * subset_size + k]; 346708122e43SStefano Zampini } 346808122e43SStefano Zampini } 346908122e43SStefano Zampini } else { 34709566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 34719566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 347208122e43SStefano Zampini } 34739566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 347408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 3475792fecdfSBarry Smith PetscCallBLAS("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)); 347608122e43SStefano Zampini #else 3477792fecdfSBarry Smith PetscCallBLAS("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)); 347808122e43SStefano Zampini #endif 34799566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 34809566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 348108122e43SStefano Zampini B_neigs += B_neigs2; 348208122e43SStefano Zampini } 348308122e43SStefano Zampini if (B_ierr) { 348463a3b9bcSJacob Faibussowitsch PetscCheck(B_ierr >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in SYGVX Lapack routine: illegal value for argument %" PetscBLASInt_FMT, -B_ierr); 348563a3b9bcSJacob Faibussowitsch PetscCheck(B_ierr > B_N, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in SYGVX Lapack routine: %" PetscBLASInt_FMT " eigenvalues failed to converge", B_ierr); 348663a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in SYGVX Lapack routine: leading minor of order %" PetscBLASInt_FMT " is not positive definite", B_ierr - B_N - 1); 348708122e43SStefano Zampini } 3488fd14bc51SStefano Zampini if (pcbddc->dbg_flag) { 348963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " -> Got %" PetscBLASInt_FMT " eigs\n", B_neigs)); 349008122e43SStefano Zampini for (j = 0; j < B_neigs; j++) { 349132fe681dSStefano Zampini if (!sub_schurs->gdsw) { 349208122e43SStefano Zampini if (eigs[j] == 0.0) { 34939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " Inf\n")); 349408122e43SStefano Zampini } else { 349532fe681dSStefano Zampini if (upart) { 349663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.6e\n", (double)eigs[j + eigs_start])); 34979d54b7f4SStefano Zampini } else { 349863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.6e\n", (double)(1. / eigs[j + eigs_start]))); 34999d54b7f4SStefano Zampini } 3500fd14bc51SStefano Zampini } 350132fe681dSStefano Zampini } else { 350232fe681dSStefano Zampini double pg = (double)eigs[j + eigs_start]; 350332fe681dSStefano Zampini if (pg < 2 * PETSC_SMALL) pg = 0.0; 350432fe681dSStefano Zampini PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.6e\n", pg)); 350532fe681dSStefano Zampini } 350608122e43SStefano Zampini } 350708122e43SStefano Zampini } 3508aff50787SStefano Zampini } 35096c3e6151SStefano Zampini /* change the basis back to the original one */ 35106c3e6151SStefano Zampini if (sub_schurs->change) { 351172b8c272SStefano Zampini Mat change, phi, phit; 35126c3e6151SStefano Zampini 351303dfb2d7SStefano Zampini if (pcbddc->dbg_flag > 2) { 35146c3e6151SStefano Zampini PetscInt ii; 35156c3e6151SStefano Zampini for (ii = 0; ii < B_neigs; ii++) { 351663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " -> Eigenvector (old basis) %" PetscInt_FMT "/%" PetscBLASInt_FMT " (%" PetscBLASInt_FMT ")\n", ii, B_neigs, B_N)); 35176c3e6151SStefano Zampini for (j = 0; j < B_N; j++) { 3518684229deSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3519684229deSStefano Zampini PetscReal r = PetscRealPart(eigv[(ii + eigs_start) * subset_size + j]); 3520684229deSStefano Zampini PetscReal c = PetscImaginaryPart(eigv[(ii + eigs_start) * subset_size + j]); 352163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.4e + %1.4e i\n", (double)r, (double)c)); 3522684229deSStefano Zampini #else 352363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.4e\n", (double)(eigv[(ii + eigs_start) * subset_size + j]))); 3524684229deSStefano Zampini #endif 35256c3e6151SStefano Zampini } 35266c3e6151SStefano Zampini } 35276c3e6151SStefano Zampini } 35289566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(sub_schurs->change[i], &change, NULL)); 35299566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, subset_size, B_neigs, eigv + eigs_start * subset_size, &phit)); 35309566063dSJacob Faibussowitsch PetscCall(MatMatMult(change, phit, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &phi)); 35319566063dSJacob Faibussowitsch PetscCall(MatCopy(phi, phit, SAME_NONZERO_PATTERN)); 35329566063dSJacob Faibussowitsch PetscCall(MatDestroy(&phit)); 35339566063dSJacob Faibussowitsch PetscCall(MatDestroy(&phi)); 35346c3e6151SStefano Zampini } 35358bec7fa6SStefano Zampini maxneigs = PetscMax(B_neigs, maxneigs); 35368bec7fa6SStefano Zampini pcbddc->adaptive_constraints_n[i + nv] = B_neigs; 35379162d606SStefano Zampini if (B_neigs) { 35389566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pcbddc->adaptive_constraints_data + pcbddc->adaptive_constraints_data_ptr[cum], eigv + eigs_start * subset_size, B_neigs * subset_size)); 3539fd14bc51SStefano Zampini 3540fd14bc51SStefano Zampini if (pcbddc->dbg_flag > 1) { 35419552c7c7SStefano Zampini PetscInt ii; 35429552c7c7SStefano Zampini for (ii = 0; ii < B_neigs; ii++) { 354363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " -> Eigenvector %" PetscInt_FMT "/%" PetscBLASInt_FMT " (%" PetscBLASInt_FMT ")\n", ii, B_neigs, B_N)); 35449552c7c7SStefano Zampini for (j = 0; j < B_N; j++) { 3545ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3546ac47001eSStefano Zampini PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii * subset_size + j + pcbddc->adaptive_constraints_data_ptr[cum]]); 3547ac47001eSStefano Zampini PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii * subset_size + j + pcbddc->adaptive_constraints_data_ptr[cum]]); 354863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.4e + %1.4e i\n", (double)r, (double)c)); 3549ac47001eSStefano Zampini #else 355063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.4e\n", (double)PetscRealPart(pcbddc->adaptive_constraints_data[ii * subset_size + j + pcbddc->adaptive_constraints_data_ptr[cum]]))); 3551ac47001eSStefano Zampini #endif 35529552c7c7SStefano Zampini } 35539552c7c7SStefano Zampini } 3554fd14bc51SStefano Zampini } 35559566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pcbddc->adaptive_constraints_idxs + pcbddc->adaptive_constraints_idxs_ptr[cum], idxs, subset_size)); 35569162d606SStefano Zampini pcbddc->adaptive_constraints_idxs_ptr[cum + 1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size; 35579162d606SStefano Zampini pcbddc->adaptive_constraints_data_ptr[cum + 1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size * B_neigs; 35589162d606SStefano Zampini cum++; 355908122e43SStefano Zampini } 35609566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(sub_schurs->is_subs[i], &idxs)); 356108122e43SStefano Zampini /* shift for next computation */ 356208122e43SStefano Zampini cumarray += subset_size * subset_size; 356308122e43SStefano Zampini } 35641baa6e33SBarry Smith if (pcbddc->dbg_flag) PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 356508122e43SStefano Zampini 356608122e43SStefano Zampini if (mss) { 356732fe681dSStefano Zampini if (sub_schurs->gdsw) { 356832fe681dSStefano Zampini PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_all, &Sarray)); 356932fe681dSStefano Zampini PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all, &Starray)); 357032fe681dSStefano Zampini } else { 35719566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all, &Sarray)); 35729566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all, &Starray)); 3573f6f667cfSStefano Zampini /* destroy matrices (junk) */ 35749566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sub_schurs->sum_S_Ej_inv_all)); 35759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sub_schurs->sum_S_Ej_tilda_all)); 357608122e43SStefano Zampini } 357732fe681dSStefano Zampini } 35781baa6e33SBarry Smith if (allocated_S_St) PetscCall(PetscFree2(S, St)); 35799566063dSJacob Faibussowitsch PetscCall(PetscFree5(eigv, eigs, work, B_iwork, B_ifail)); 358008122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 35819566063dSJacob Faibussowitsch PetscCall(PetscFree(rwork)); 358208122e43SStefano Zampini #endif 358308122e43SStefano Zampini if (pcbddc->dbg_flag) { 35841b968477SStefano Zampini PetscInt maxneigs_r; 35851c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&maxneigs, &maxneigs_r, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)pc))); 358663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Maximum number of constraints per cc %" PetscInt_FMT "\n", maxneigs_r)); 358708122e43SStefano Zampini } 35889566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_AdaptiveSetUp[pcbddc->current_level], pc, 0, 0, 0)); 35893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 359008122e43SStefano Zampini } 3591b1b3d7a2SStefano Zampini 3592d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpSolvers(PC pc) 3593d71ae5a4SJacob Faibussowitsch { 35948629588bSStefano Zampini PetscScalar *coarse_submat_vals; 3595c8587f34SStefano Zampini 3596c8587f34SStefano Zampini PetscFunctionBegin; 3597f4ddd8eeSStefano Zampini /* Setup local scatters R_to_B and (optionally) R_to_D */ 35985e8657edSStefano Zampini /* PCBDDCSetUpLocalWorkVectors should be called first! */ 35999566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpLocalScatters(pc)); 3600c8587f34SStefano Zampini 3601684f6988SStefano Zampini /* Setup local neumann solver ksp_R */ 36020fccc4e9SStefano Zampini /* PCBDDCSetUpLocalScatters should be called first! */ 36039566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpLocalSolvers(pc, PETSC_FALSE, PETSC_TRUE)); 3604c8587f34SStefano Zampini 36058629588bSStefano Zampini /* 36068629588bSStefano Zampini Setup local correction and local part of coarse basis. 36078629588bSStefano Zampini Gives back the dense local part of the coarse matrix in column major ordering 36088629588bSStefano Zampini */ 36099566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpCorrection(pc, &coarse_submat_vals)); 36108629588bSStefano Zampini 36118629588bSStefano Zampini /* Compute total number of coarse nodes and setup coarse solver */ 36129566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpCoarseSolver(pc, coarse_submat_vals)); 36138629588bSStefano Zampini 36148629588bSStefano Zampini /* free */ 36159566063dSJacob Faibussowitsch PetscCall(PetscFree(coarse_submat_vals)); 36163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3617c8587f34SStefano Zampini } 3618c8587f34SStefano Zampini 3619d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCResetCustomization(PC pc) 3620d71ae5a4SJacob Faibussowitsch { 3621674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 3622674ae819SStefano Zampini 3623674ae819SStefano Zampini PetscFunctionBegin; 36249566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices)); 36259566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local)); 36269566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundaries)); 36279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal)); 36289566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundaries)); 36299566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&pcbddc->onearnullspace)); 36309566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->onearnullvecs_state)); 36319566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal)); 36329566063dSJacob Faibussowitsch PetscCall(PCBDDCSetDofsSplitting(pc, 0, NULL)); 36339566063dSJacob Faibussowitsch PetscCall(PCBDDCSetDofsSplittingLocal(pc, 0, NULL)); 36343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3635674ae819SStefano Zampini } 3636674ae819SStefano Zampini 3637d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCResetTopography(PC pc) 3638d71ae5a4SJacob Faibussowitsch { 3639674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 36404f1b2e48SStefano Zampini PetscInt i; 3641674ae819SStefano Zampini 3642674ae819SStefano Zampini PetscFunctionBegin; 36439566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->nedcG)); 36449566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->nedclocal)); 36459566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->discretegradient)); 36469566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->user_ChangeOfBasisMatrix)); 36479566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->ChangeOfBasisMatrix)); 36489566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->switch_static_change)); 36499566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->work_change)); 36509566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->ConstraintMatrix)); 36519566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->divudotp)); 36529566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->divudotp_vl2l)); 36539566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphDestroy(&pcbddc->mat_graph)); 365448a46eb9SPierre Jolivet for (i = 0; i < pcbddc->n_local_subs; i++) PetscCall(ISDestroy(&pcbddc->local_subs[i])); 3655e68a0315Sstefano_zampini pcbddc->n_local_subs = 0; 36569566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->local_subs)); 36579566063dSJacob Faibussowitsch PetscCall(PCBDDCSubSchursDestroy(&pcbddc->sub_schurs)); 3658c703fcc7SStefano Zampini pcbddc->graphanalyzed = PETSC_FALSE; 36598af8fcf9SStefano Zampini pcbddc->recompute_topography = PETSC_TRUE; 36601c7a958bSStefano Zampini pcbddc->corner_selected = PETSC_FALSE; 36613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3662674ae819SStefano Zampini } 3663674ae819SStefano Zampini 3664d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCResetSolvers(PC pc) 3665d71ae5a4SJacob Faibussowitsch { 3666674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 3667674ae819SStefano Zampini 3668674ae819SStefano Zampini PetscFunctionBegin; 36699566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->coarse_vec)); 367058da7f69SStefano Zampini if (pcbddc->coarse_phi_B) { 3671ca92afb2SStefano Zampini PetscScalar *array; 36729566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(pcbddc->coarse_phi_B, &array)); 36739566063dSJacob Faibussowitsch PetscCall(PetscFree(array)); 367458da7f69SStefano Zampini } 36759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_phi_B)); 36769566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_phi_D)); 36779566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_psi_B)); 36789566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_psi_D)); 36799566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_P)); 36809566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_C)); 36819566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_auxmat2)); 36829566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_auxmat1)); 36839566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_R)); 36849566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec2_R)); 36859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->is_R_local)); 36869566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->R_to_B)); 36879566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->R_to_D)); 36889566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->coarse_loc_to_glob)); 36899566063dSJacob Faibussowitsch PetscCall(KSPReset(pcbddc->ksp_D)); 36909566063dSJacob Faibussowitsch PetscCall(KSPReset(pcbddc->ksp_R)); 36919566063dSJacob Faibussowitsch PetscCall(KSPReset(pcbddc->coarse_ksp)); 36929566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 36939566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->primal_indices_local_idxs)); 36949566063dSJacob Faibussowitsch PetscCall(PetscFree2(pcbddc->local_primal_ref_node, pcbddc->local_primal_ref_mult)); 36959566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->global_primal_indices)); 36969566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->coarse_subassembling)); 36979566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->benign_change)); 36989566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->benign_vec)); 36999566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignShellMat(pc, PETSC_TRUE)); 37009566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->benign_B0)); 37019566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pcbddc->benign_sf)); 3702ca92afb2SStefano Zampini if (pcbddc->benign_zerodiag_subs) { 3703ca92afb2SStefano Zampini PetscInt i; 370448a46eb9SPierre Jolivet for (i = 0; i < pcbddc->benign_n; i++) PetscCall(ISDestroy(&pcbddc->benign_zerodiag_subs[i])); 37059566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->benign_zerodiag_subs)); 3706ca92afb2SStefano Zampini } 37079566063dSJacob Faibussowitsch PetscCall(PetscFree3(pcbddc->benign_p0_lidx, pcbddc->benign_p0_gidx, pcbddc->benign_p0)); 37083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3709674ae819SStefano Zampini } 3710674ae819SStefano Zampini 3711d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc) 3712d71ae5a4SJacob Faibussowitsch { 37136bfb1811SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 37146bfb1811SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 37156bfb1811SStefano Zampini VecType impVecType; 37164f1b2e48SStefano Zampini PetscInt n_constraints, n_R, old_size; 37176bfb1811SStefano Zampini 37186bfb1811SStefano Zampini PetscFunctionBegin; 37194f1b2e48SStefano Zampini n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices; 3720b371cd4fSStefano Zampini n_R = pcis->n - pcbddc->n_vertices; 37219566063dSJacob Faibussowitsch PetscCall(VecGetType(pcis->vec1_N, &impVecType)); 3722e7b262bdSStefano Zampini /* local work vectors (try to avoid unneeded work)*/ 3723e7b262bdSStefano Zampini /* R nodes */ 3724e7b262bdSStefano Zampini old_size = -1; 372548a46eb9SPierre Jolivet if (pcbddc->vec1_R) PetscCall(VecGetSize(pcbddc->vec1_R, &old_size)); 3726e7b262bdSStefano Zampini if (n_R != old_size) { 37279566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_R)); 37289566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec2_R)); 37299566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N), &pcbddc->vec1_R)); 37309566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pcbddc->vec1_R, PETSC_DECIDE, n_R)); 37319566063dSJacob Faibussowitsch PetscCall(VecSetType(pcbddc->vec1_R, impVecType)); 37329566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcbddc->vec1_R, &pcbddc->vec2_R)); 3733e7b262bdSStefano Zampini } 3734e7b262bdSStefano Zampini /* local primal dofs */ 3735e7b262bdSStefano Zampini old_size = -1; 373648a46eb9SPierre Jolivet if (pcbddc->vec1_P) PetscCall(VecGetSize(pcbddc->vec1_P, &old_size)); 3737e9189074SStefano Zampini if (pcbddc->local_primal_size != old_size) { 37389566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_P)); 37399566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N), &pcbddc->vec1_P)); 37409566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pcbddc->vec1_P, PETSC_DECIDE, pcbddc->local_primal_size)); 37419566063dSJacob Faibussowitsch PetscCall(VecSetType(pcbddc->vec1_P, impVecType)); 3742e7b262bdSStefano Zampini } 3743e7b262bdSStefano Zampini /* local explicit constraints */ 3744e7b262bdSStefano Zampini old_size = -1; 374548a46eb9SPierre Jolivet if (pcbddc->vec1_C) PetscCall(VecGetSize(pcbddc->vec1_C, &old_size)); 3746e7b262bdSStefano Zampini if (n_constraints && n_constraints != old_size) { 37479566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_C)); 37489566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N), &pcbddc->vec1_C)); 37499566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pcbddc->vec1_C, PETSC_DECIDE, n_constraints)); 37509566063dSJacob Faibussowitsch PetscCall(VecSetType(pcbddc->vec1_C, impVecType)); 375183b7ccabSStefano Zampini } 37523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 37536bfb1811SStefano Zampini } 37546bfb1811SStefano Zampini 3755d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n) 3756d71ae5a4SJacob Faibussowitsch { 375725084f0cSStefano Zampini /* pointers to pcis and pcbddc */ 375888ebb749SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 375988ebb749SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 3760d62866d3SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 376125084f0cSStefano Zampini /* submatrices of local problem */ 376280677318SStefano Zampini Mat A_RV, A_VR, A_VV, local_auxmat2_R; 376306656605SStefano Zampini /* submatrices of local coarse problem */ 376406656605SStefano Zampini Mat S_VV, S_CV, S_VC, S_CC; 376525084f0cSStefano Zampini /* working matrices */ 376606656605SStefano Zampini Mat C_CR; 376725084f0cSStefano Zampini /* additional working stuff */ 376806656605SStefano Zampini PC pc_R; 3769c58f9fdbSStefano Zampini Mat F, Brhs = NULL; 37705cbda25cSStefano Zampini Vec dummy_vec; 37717ebab0bbSStefano Zampini PetscBool isLU, isCHOL, need_benign_correction, sparserhs; 377225084f0cSStefano Zampini PetscScalar *coarse_submat_vals; /* TODO: use a PETSc matrix */ 377306656605SStefano Zampini PetscScalar *work; 377406656605SStefano Zampini PetscInt *idx_V_B; 3775ffd830a3SStefano Zampini PetscInt lda_rhs, n, n_vertices, n_constraints, *p0_lidx_I; 377606656605SStefano Zampini PetscInt i, n_R, n_D, n_B; 377706656605SStefano Zampini PetscScalar one = 1.0, m_one = -1.0; 377888ebb749SStefano Zampini 377988ebb749SStefano Zampini PetscFunctionBegin; 37807827d75bSBarry Smith PetscCheck(pcbddc->symmetric_primal || !pcbddc->benign_n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Non-symmetric primal basis computation with benign trick not yet implemented"); 37819566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_CorrectionSetUp[pcbddc->current_level], pc, 0, 0, 0)); 3782ffd830a3SStefano Zampini 3783ffd830a3SStefano Zampini /* Set Non-overlapping dimensions */ 3784b371cd4fSStefano Zampini n_vertices = pcbddc->n_vertices; 37854f1b2e48SStefano Zampini n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices; 3786b371cd4fSStefano Zampini n_B = pcis->n_B; 3787b371cd4fSStefano Zampini n_D = pcis->n - n_B; 378888ebb749SStefano Zampini n_R = pcis->n - n_vertices; 378988ebb749SStefano Zampini 379088ebb749SStefano Zampini /* vertices in boundary numbering */ 37919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_vertices, &idx_V_B)); 37929566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(pcis->BtoNmap, IS_GTOLM_DROP, n_vertices, pcbddc->local_primal_ref_node, &i, idx_V_B)); 379363a3b9bcSJacob Faibussowitsch PetscCheck(i == n_vertices, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Error in boundary numbering for BDDC vertices! %" PetscInt_FMT " != %" PetscInt_FMT, n_vertices, i); 379488ebb749SStefano Zampini 379506656605SStefano Zampini /* Subdomain contribution (Non-overlapping) to coarse matrix */ 37969566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pcbddc->local_primal_size * pcbddc->local_primal_size, &coarse_submat_vals)); 37979566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_vertices, n_vertices, coarse_submat_vals, &S_VV)); 37989566063dSJacob Faibussowitsch PetscCall(MatDenseSetLDA(S_VV, pcbddc->local_primal_size)); 37999566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_constraints, n_vertices, coarse_submat_vals + n_vertices, &S_CV)); 38009566063dSJacob Faibussowitsch PetscCall(MatDenseSetLDA(S_CV, pcbddc->local_primal_size)); 38019566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_vertices, n_constraints, coarse_submat_vals + pcbddc->local_primal_size * n_vertices, &S_VC)); 38029566063dSJacob Faibussowitsch PetscCall(MatDenseSetLDA(S_VC, pcbddc->local_primal_size)); 38039566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_constraints, n_constraints, coarse_submat_vals + (pcbddc->local_primal_size + 1) * n_vertices, &S_CC)); 38049566063dSJacob Faibussowitsch PetscCall(MatDenseSetLDA(S_CC, pcbddc->local_primal_size)); 380506656605SStefano Zampini 380606656605SStefano Zampini /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */ 38079566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_R, &pc_R)); 38089566063dSJacob Faibussowitsch PetscCall(PCSetUp(pc_R)); 38099566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_R, PCLU, &isLU)); 38109566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_R, PCCHOLESKY, &isCHOL)); 3811ffd830a3SStefano Zampini lda_rhs = n_R; 3812a3df083aSStefano Zampini need_benign_correction = PETSC_FALSE; 38137ebab0bbSStefano Zampini if (isLU || isCHOL) { 38149566063dSJacob Faibussowitsch PetscCall(PCFactorGetMatrix(pc_R, &F)); 3815b334f244SStefano Zampini } else if (sub_schurs && sub_schurs->reuse_solver) { 3816df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 3817d62866d3SStefano Zampini MatFactorType type; 3818d62866d3SStefano Zampini 3819df4d28bfSStefano Zampini F = reuse_solver->F; 38209566063dSJacob Faibussowitsch PetscCall(MatGetFactorType(F, &type)); 3821d62866d3SStefano Zampini if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE; 38227ebab0bbSStefano Zampini if (type == MAT_FACTOR_LU) isLU = PETSC_TRUE; 38239566063dSJacob Faibussowitsch PetscCall(MatGetSize(F, &lda_rhs, NULL)); 382422db5ddcSStefano Zampini need_benign_correction = (PetscBool)(!!reuse_solver->benign_n); 38257ebab0bbSStefano Zampini } else F = NULL; 382606656605SStefano Zampini 3827c58f9fdbSStefano Zampini /* determine if we can use a sparse right-hand side */ 3828c58f9fdbSStefano Zampini sparserhs = PETSC_FALSE; 3829c58f9fdbSStefano Zampini if (F) { 3830ea799195SBarry Smith MatSolverType solver; 3831c58f9fdbSStefano Zampini 38329566063dSJacob Faibussowitsch PetscCall(MatFactorGetSolverType(F, &solver)); 38339566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(solver, MATSOLVERMUMPS, &sparserhs)); 3834c58f9fdbSStefano Zampini } 3835c58f9fdbSStefano Zampini 3836ffd830a3SStefano Zampini /* allocate workspace */ 3837ffd830a3SStefano Zampini n = 0; 3838ad540459SPierre Jolivet if (n_constraints) n += lda_rhs * n_constraints; 3839ffd830a3SStefano Zampini if (n_vertices) { 3840ffd830a3SStefano Zampini n = PetscMax(2 * lda_rhs * n_vertices, n); 3841ffd830a3SStefano Zampini n = PetscMax((lda_rhs + n_B) * n_vertices, n); 3842ffd830a3SStefano Zampini } 3843ad540459SPierre Jolivet if (!pcbddc->symmetric_primal) n = PetscMax(2 * lda_rhs * pcbddc->local_primal_size, n); 38449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &work)); 3845ffd830a3SStefano Zampini 38465cbda25cSStefano Zampini /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */ 38475cbda25cSStefano Zampini dummy_vec = NULL; 38485cbda25cSStefano Zampini if (need_benign_correction && lda_rhs != n_R && F) { 38499566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N), &dummy_vec)); 38509566063dSJacob Faibussowitsch PetscCall(VecSetSizes(dummy_vec, lda_rhs, PETSC_DECIDE)); 38519566063dSJacob Faibussowitsch PetscCall(VecSetType(dummy_vec, ((PetscObject)pcis->vec1_N)->type_name)); 38525cbda25cSStefano Zampini } 38535cbda25cSStefano Zampini 38549566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_auxmat1)); 38559566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_auxmat2)); 38567ebab0bbSStefano Zampini 385788ebb749SStefano Zampini /* Precompute stuffs needed for preprocessing and application of BDDC*/ 385888ebb749SStefano Zampini if (n_constraints) { 3859837cedc9SStefano Zampini Mat M3, C_B; 386006656605SStefano Zampini IS is_aux; 386106656605SStefano Zampini 386225084f0cSStefano Zampini /* Extract constraints on R nodes: C_{CR} */ 38639566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, n_constraints, n_vertices, 1, &is_aux)); 38649566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->ConstraintMatrix, is_aux, pcbddc->is_R_local, MAT_INITIAL_MATRIX, &C_CR)); 38659566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->ConstraintMatrix, is_aux, pcis->is_B_local, MAT_INITIAL_MATRIX, &C_B)); 386688ebb749SStefano Zampini 386780677318SStefano Zampini /* Assemble local_auxmat2_R = (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */ 386880677318SStefano Zampini /* Assemble pcbddc->local_auxmat2 = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */ 3869c58f9fdbSStefano Zampini if (!sparserhs) { 38709566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(work, lda_rhs * n_constraints)); 387188ebb749SStefano Zampini for (i = 0; i < n_constraints; i++) { 387206656605SStefano Zampini const PetscScalar *row_cmat_values; 387306656605SStefano Zampini const PetscInt *row_cmat_indices; 387406656605SStefano Zampini PetscInt size_of_constraint, j; 387588ebb749SStefano Zampini 38769566063dSJacob Faibussowitsch PetscCall(MatGetRow(C_CR, i, &size_of_constraint, &row_cmat_indices, &row_cmat_values)); 3877ad540459SPierre Jolivet for (j = 0; j < size_of_constraint; j++) work[row_cmat_indices[j] + i * lda_rhs] = -row_cmat_values[j]; 38789566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(C_CR, i, &size_of_constraint, &row_cmat_indices, &row_cmat_values)); 387906656605SStefano Zampini } 38809566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, lda_rhs, n_constraints, work, &Brhs)); 3881c58f9fdbSStefano Zampini } else { 3882c58f9fdbSStefano Zampini Mat tC_CR; 3883c58f9fdbSStefano Zampini 38849566063dSJacob Faibussowitsch PetscCall(MatScale(C_CR, -1.0)); 3885c58f9fdbSStefano Zampini if (lda_rhs != n_R) { 3886c58f9fdbSStefano Zampini PetscScalar *aa; 3887c58f9fdbSStefano Zampini PetscInt r, *ii, *jj; 3888c58f9fdbSStefano Zampini PetscBool done; 3889c58f9fdbSStefano Zampini 38909566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(C_CR, 0, PETSC_FALSE, PETSC_FALSE, &r, (const PetscInt **)&ii, (const PetscInt **)&jj, &done)); 389128b400f6SJacob Faibussowitsch PetscCheck(done, PETSC_COMM_SELF, PETSC_ERR_PLIB, "GetRowIJ failed"); 38929566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(C_CR, &aa)); 38939566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, n_constraints, lda_rhs, ii, jj, aa, &tC_CR)); 38949566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(C_CR, 0, PETSC_FALSE, PETSC_FALSE, &r, (const PetscInt **)&ii, (const PetscInt **)&jj, &done)); 389528b400f6SJacob Faibussowitsch PetscCheck(done, PETSC_COMM_SELF, PETSC_ERR_PLIB, "RestoreRowIJ failed"); 3896c58f9fdbSStefano Zampini } else { 38979566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)C_CR)); 3898c58f9fdbSStefano Zampini tC_CR = C_CR; 3899c58f9fdbSStefano Zampini } 39009566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(tC_CR, &Brhs)); 39019566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tC_CR)); 3902c58f9fdbSStefano Zampini } 39039566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, lda_rhs, n_constraints, NULL, &local_auxmat2_R)); 390406656605SStefano Zampini if (F) { 3905a3df083aSStefano Zampini if (need_benign_correction) { 3906df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 3907a3df083aSStefano Zampini 390872b8c272SStefano Zampini /* rhs is already zero on interior dofs, no need to change the rhs */ 39099566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(reuse_solver->benign_save_vals, pcbddc->benign_n)); 3910a3df083aSStefano Zampini } 39119566063dSJacob Faibussowitsch PetscCall(MatMatSolve(F, Brhs, local_auxmat2_R)); 3912a3df083aSStefano Zampini if (need_benign_correction) { 3913a3df083aSStefano Zampini PetscScalar *marr; 3914df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 3915a3df083aSStefano Zampini 39169566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(local_auxmat2_R, &marr)); 39175cbda25cSStefano Zampini if (lda_rhs != n_R) { 39185cbda25cSStefano Zampini for (i = 0; i < n_constraints; i++) { 39199566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dummy_vec, marr + i * lda_rhs)); 39209566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, dummy_vec, NULL, PETSC_TRUE, PETSC_TRUE)); 39219566063dSJacob Faibussowitsch PetscCall(VecResetArray(dummy_vec)); 39225cbda25cSStefano Zampini } 39235cbda25cSStefano Zampini } else { 3924a3df083aSStefano Zampini for (i = 0; i < n_constraints; i++) { 39259566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, marr + i * lda_rhs)); 39269566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, pcbddc->vec1_R, NULL, PETSC_TRUE, PETSC_TRUE)); 39279566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 3928a3df083aSStefano Zampini } 39295cbda25cSStefano Zampini } 39309566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(local_auxmat2_R, &marr)); 3931a3df083aSStefano Zampini } 393206656605SStefano Zampini } else { 393380677318SStefano Zampini PetscScalar *marr; 393480677318SStefano Zampini 39359566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(local_auxmat2_R, &marr)); 393606656605SStefano Zampini for (i = 0; i < n_constraints; i++) { 39379566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, work + i * lda_rhs)); 39389566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec2_R, marr + i * lda_rhs)); 39399566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec2_R)); 39409566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec2_R)); 39419566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 39429566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec2_R)); 394306656605SStefano Zampini } 39449566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(local_auxmat2_R, &marr)); 394506656605SStefano Zampini } 39461baa6e33SBarry Smith if (sparserhs) PetscCall(MatScale(C_CR, -1.0)); 39479566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Brhs)); 394880677318SStefano Zampini if (!pcbddc->switch_static) { 39499566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_B, n_constraints, NULL, &pcbddc->local_auxmat2)); 395080677318SStefano Zampini for (i = 0; i < n_constraints; i++) { 3951ab2d12f3SJunchao Zhang Vec r, b; 39529566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVecRead(local_auxmat2_R, i, &r)); 39539566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVec(pcbddc->local_auxmat2, i, &b)); 39549566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, r, b, INSERT_VALUES, SCATTER_FORWARD)); 39559566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, r, b, INSERT_VALUES, SCATTER_FORWARD)); 39569566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVec(pcbddc->local_auxmat2, i, &b)); 39579566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVecRead(local_auxmat2_R, i, &r)); 395880677318SStefano Zampini } 39599566063dSJacob Faibussowitsch PetscCall(MatMatMult(C_B, pcbddc->local_auxmat2, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &M3)); 396080677318SStefano Zampini } else { 3961ffd830a3SStefano Zampini if (lda_rhs != n_R) { 3962ffd830a3SStefano Zampini IS dummy; 3963ffd830a3SStefano Zampini 39649566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, n_R, 0, 1, &dummy)); 39659566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(local_auxmat2_R, dummy, NULL, MAT_INITIAL_MATRIX, &pcbddc->local_auxmat2)); 39669566063dSJacob Faibussowitsch PetscCall(ISDestroy(&dummy)); 3967ffd830a3SStefano Zampini } else { 39689566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)local_auxmat2_R)); 396980677318SStefano Zampini pcbddc->local_auxmat2 = local_auxmat2_R; 3970ffd830a3SStefano Zampini } 39719566063dSJacob Faibussowitsch PetscCall(MatMatMult(C_CR, pcbddc->local_auxmat2, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &M3)); 397280677318SStefano Zampini } 39739566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_aux)); 397480677318SStefano Zampini /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR})^{-1} */ 39759566063dSJacob Faibussowitsch PetscCall(MatScale(M3, m_one)); 397680677318SStefano Zampini if (isCHOL) { 39779566063dSJacob Faibussowitsch PetscCall(MatCholeskyFactor(M3, NULL, NULL)); 397880677318SStefano Zampini } else { 39799566063dSJacob Faibussowitsch PetscCall(MatLUFactor(M3, NULL, NULL, NULL)); 398080677318SStefano Zampini } 39819566063dSJacob Faibussowitsch PetscCall(MatSeqDenseInvertFactors_Private(M3)); 398280677318SStefano Zampini /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */ 39839566063dSJacob Faibussowitsch PetscCall(MatMatMult(M3, C_B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &pcbddc->local_auxmat1)); 39849566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C_B)); 39859566063dSJacob Faibussowitsch PetscCall(MatCopy(M3, S_CC, SAME_NONZERO_PATTERN)); /* S_CC can have a different LDA, MatMatSolve doesn't support it */ 39869566063dSJacob Faibussowitsch PetscCall(MatDestroy(&M3)); 3987f4ddd8eeSStefano Zampini } 3988fc227af8SStefano Zampini 3989fc227af8SStefano Zampini /* Get submatrices from subdomain matrix */ 399088ebb749SStefano Zampini if (n_vertices) { 39917ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 39927ebab0bbSStefano Zampini PetscBool oldpin; 39937ebab0bbSStefano Zampini #endif 39947ebab0bbSStefano Zampini PetscBool isaij; 399506656605SStefano Zampini IS is_aux; 39963a50541eSStefano Zampini 3997b334f244SStefano Zampini if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */ 39986816873aSStefano Zampini IS tis; 39996816873aSStefano Zampini 40009566063dSJacob Faibussowitsch PetscCall(ISDuplicate(pcbddc->is_R_local, &tis)); 40019566063dSJacob Faibussowitsch PetscCall(ISSort(tis)); 40029566063dSJacob Faibussowitsch PetscCall(ISComplement(tis, 0, pcis->n, &is_aux)); 40039566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tis)); 40046816873aSStefano Zampini } else { 40059566063dSJacob Faibussowitsch PetscCall(ISComplement(pcbddc->is_R_local, 0, pcis->n, &is_aux)); 40066816873aSStefano Zampini } 40077ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 4008b470e4b4SRichard Tran Mills oldpin = pcbddc->local_mat->boundtocpu; 40097ebab0bbSStefano Zampini #endif 40109566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(pcbddc->local_mat, PETSC_TRUE)); 40119566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcbddc->is_R_local, is_aux, MAT_INITIAL_MATRIX, &A_RV)); 40129566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, is_aux, pcbddc->is_R_local, MAT_INITIAL_MATRIX, &A_VR)); 40139566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A_VR, MATSEQAIJ, &isaij)); 40147ebab0bbSStefano Zampini if (!isaij) { /* TODO REMOVE: MatMatMult(A_VR,A_RRmA_RV) below may raise an error */ 40159566063dSJacob Faibussowitsch PetscCall(MatConvert(A_VR, MATSEQAIJ, MAT_INPLACE_MATRIX, &A_VR)); 40167ebab0bbSStefano Zampini } 40179566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, is_aux, is_aux, MAT_INITIAL_MATRIX, &A_VV)); 40187ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 40199566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(pcbddc->local_mat, oldpin)); 40207ebab0bbSStefano Zampini #endif 40219566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_aux)); 402288ebb749SStefano Zampini } 402388ebb749SStefano Zampini 402488ebb749SStefano Zampini /* Matrix of coarse basis functions (local) */ 4025f4ddd8eeSStefano Zampini if (pcbddc->coarse_phi_B) { 402606656605SStefano Zampini PetscInt on_B, on_primal, on_D = n_D; 402748a46eb9SPierre Jolivet if (pcbddc->coarse_phi_D) PetscCall(MatGetSize(pcbddc->coarse_phi_D, &on_D, NULL)); 40289566063dSJacob Faibussowitsch PetscCall(MatGetSize(pcbddc->coarse_phi_B, &on_B, &on_primal)); 402906656605SStefano Zampini if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) { 403006656605SStefano Zampini PetscScalar *marray; 403106656605SStefano Zampini 40329566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(pcbddc->coarse_phi_B, &marray)); 40339566063dSJacob Faibussowitsch PetscCall(PetscFree(marray)); 40349566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_phi_B)); 40359566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_psi_B)); 40369566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_phi_D)); 40379566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_psi_D)); 4038f4ddd8eeSStefano Zampini } 4039f4ddd8eeSStefano Zampini } 404006656605SStefano Zampini 4041f4ddd8eeSStefano Zampini if (!pcbddc->coarse_phi_B) { 4042a6e023c1Sstefano_zampini PetscScalar *marr; 404388ebb749SStefano Zampini 4044a6e023c1Sstefano_zampini /* memory size */ 404506656605SStefano Zampini n = n_B * pcbddc->local_primal_size; 4046a6e023c1Sstefano_zampini if (pcbddc->switch_static || pcbddc->dbg_flag) n += n_D * pcbddc->local_primal_size; 4047a6e023c1Sstefano_zampini if (!pcbddc->symmetric_primal) n *= 2; 40489566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(n, &marr)); 40499566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_B, pcbddc->local_primal_size, marr, &pcbddc->coarse_phi_B)); 4050a6e023c1Sstefano_zampini marr += n_B * pcbddc->local_primal_size; 40518eeda7d8SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 40529566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_D, pcbddc->local_primal_size, marr, &pcbddc->coarse_phi_D)); 4053a6e023c1Sstefano_zampini marr += n_D * pcbddc->local_primal_size; 405488ebb749SStefano Zampini } 40553301b35fSStefano Zampini if (!pcbddc->symmetric_primal) { 40569566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_B, pcbddc->local_primal_size, marr, &pcbddc->coarse_psi_B)); 4057a6e023c1Sstefano_zampini marr += n_B * pcbddc->local_primal_size; 405848a46eb9SPierre Jolivet if (pcbddc->switch_static || pcbddc->dbg_flag) PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_D, pcbddc->local_primal_size, marr, &pcbddc->coarse_psi_D)); 405988ebb749SStefano Zampini } else { 40609566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->coarse_phi_B)); 4061c0553b1fSStefano Zampini pcbddc->coarse_psi_B = pcbddc->coarse_phi_B; 40621b968477SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 40639566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->coarse_phi_D)); 4064c0553b1fSStefano Zampini pcbddc->coarse_psi_D = pcbddc->coarse_phi_D; 4065c0553b1fSStefano Zampini } 406688ebb749SStefano Zampini } 406706656605SStefano Zampini } 4068019a44ceSStefano Zampini 406906656605SStefano Zampini /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */ 40704f1b2e48SStefano Zampini p0_lidx_I = NULL; 40714f1b2e48SStefano Zampini if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) { 4072d12edf2fSStefano Zampini const PetscInt *idxs; 4073d12edf2fSStefano Zampini 40749566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_I_local, &idxs)); 40759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->benign_n, &p0_lidx_I)); 407648a46eb9SPierre Jolivet for (i = 0; i < pcbddc->benign_n; i++) PetscCall(PetscFindInt(pcbddc->benign_p0_lidx[i], pcis->n - pcis->n_B, idxs, &p0_lidx_I[i])); 40779566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_I_local, &idxs)); 4078d12edf2fSStefano Zampini } 4079d16cbb6bSStefano Zampini 408006656605SStefano Zampini /* vertices */ 408106656605SStefano Zampini if (n_vertices) { 4082c58f9fdbSStefano Zampini PetscBool restoreavr = PETSC_FALSE; 408316f15bc4SStefano Zampini 40849566063dSJacob Faibussowitsch PetscCall(MatConvert(A_VV, MATDENSE, MAT_INPLACE_MATRIX, &A_VV)); 408504708bb6SStefano Zampini 408616f15bc4SStefano Zampini if (n_R) { 408714393ed6SStefano Zampini Mat A_RRmA_RV, A_RV_bcorr = NULL, S_VVt; /* S_VVt with LDA=N */ 408806656605SStefano Zampini PetscBLASInt B_N, B_one = 1; 40891683a169SBarry Smith const PetscScalar *x; 40901683a169SBarry Smith PetscScalar *y; 409106656605SStefano Zampini 40929566063dSJacob Faibussowitsch PetscCall(MatScale(A_RV, m_one)); 409314393ed6SStefano Zampini if (need_benign_correction) { 409414393ed6SStefano Zampini ISLocalToGlobalMapping RtoN; 409514393ed6SStefano Zampini IS is_p0; 409614393ed6SStefano Zampini PetscInt *idxs_p0, n; 409714393ed6SStefano Zampini 40989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->benign_n, &idxs_p0)); 40999566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local, &RtoN)); 41009566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(RtoN, IS_GTOLM_DROP, pcbddc->benign_n, pcbddc->benign_p0_lidx, &n, idxs_p0)); 410163a3b9bcSJacob Faibussowitsch PetscCheck(n == pcbddc->benign_n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Error in R numbering for benign p0! %" PetscInt_FMT " != %" PetscInt_FMT, n, pcbddc->benign_n); 41029566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&RtoN)); 41039566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, n, idxs_p0, PETSC_OWN_POINTER, &is_p0)); 41049566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A_RV, is_p0, NULL, MAT_INITIAL_MATRIX, &A_RV_bcorr)); 41059566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_p0)); 410614393ed6SStefano Zampini } 410714393ed6SStefano Zampini 41089566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, lda_rhs, n_vertices, work, &A_RRmA_RV)); 4109c58f9fdbSStefano Zampini if (!sparserhs || need_benign_correction) { 4110ffd830a3SStefano Zampini if (lda_rhs == n_R) { 41119566063dSJacob Faibussowitsch PetscCall(MatConvert(A_RV, MATDENSE, MAT_INPLACE_MATRIX, &A_RV)); 4112ffd830a3SStefano Zampini } else { 4113ca92afb2SStefano Zampini PetscScalar *av, *array; 4114ca92afb2SStefano Zampini const PetscInt *xadj, *adjncy; 4115ca92afb2SStefano Zampini PetscInt n; 4116ca92afb2SStefano Zampini PetscBool flg_row; 4117ffd830a3SStefano Zampini 4118ca92afb2SStefano Zampini array = work + lda_rhs * n_vertices; 41199566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(array, lda_rhs * n_vertices)); 41209566063dSJacob Faibussowitsch PetscCall(MatConvert(A_RV, MATSEQAIJ, MAT_INPLACE_MATRIX, &A_RV)); 41219566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A_RV, 0, PETSC_FALSE, PETSC_FALSE, &n, &xadj, &adjncy, &flg_row)); 41229566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A_RV, &av)); 4123ca92afb2SStefano Zampini for (i = 0; i < n; i++) { 4124ca92afb2SStefano Zampini PetscInt j; 4125ca92afb2SStefano Zampini for (j = xadj[i]; j < xadj[i + 1]; j++) array[lda_rhs * adjncy[j] + i] = av[j]; 4126ffd830a3SStefano Zampini } 41279566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A_RV, 0, PETSC_FALSE, PETSC_FALSE, &n, &xadj, &adjncy, &flg_row)); 41289566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RV)); 41299566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, lda_rhs, n_vertices, array, &A_RV)); 4130ffd830a3SStefano Zampini } 4131a3df083aSStefano Zampini if (need_benign_correction) { 4132df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 4133a3df083aSStefano Zampini PetscScalar *marr; 4134a3df083aSStefano Zampini 41359566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(A_RV, &marr)); 413614393ed6SStefano Zampini /* need \Phi^T A_RV = (I+L)A_RV, L given by 413714393ed6SStefano Zampini 413814393ed6SStefano Zampini | 0 0 0 | (V) 413914393ed6SStefano Zampini L = | 0 0 -1 | (P-p0) 414014393ed6SStefano Zampini | 0 0 -1 | (p0) 414114393ed6SStefano Zampini 414214393ed6SStefano Zampini */ 4143df4d28bfSStefano Zampini for (i = 0; i < reuse_solver->benign_n; i++) { 414414393ed6SStefano Zampini const PetscScalar *vals; 414514393ed6SStefano Zampini const PetscInt *idxs, *idxs_zero; 414614393ed6SStefano Zampini PetscInt n, j, nz; 414714393ed6SStefano Zampini 41489566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i], &nz)); 41499566063dSJacob Faibussowitsch PetscCall(ISGetIndices(reuse_solver->benign_zerodiag_subs[i], &idxs_zero)); 41509566063dSJacob Faibussowitsch PetscCall(MatGetRow(A_RV_bcorr, i, &n, &idxs, &vals)); 415114393ed6SStefano Zampini for (j = 0; j < n; j++) { 415214393ed6SStefano Zampini PetscScalar val = vals[j]; 415314393ed6SStefano Zampini PetscInt k, col = idxs[j]; 415414393ed6SStefano Zampini for (k = 0; k < nz; k++) marr[idxs_zero[k] + lda_rhs * col] -= val; 415514393ed6SStefano Zampini } 41569566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(A_RV_bcorr, i, &n, &idxs, &vals)); 41579566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i], &idxs_zero)); 415814393ed6SStefano Zampini } 41599566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(A_RV, &marr)); 416072b8c272SStefano Zampini } 41619566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A_RV)); 4162c58f9fdbSStefano Zampini Brhs = A_RV; 4163c58f9fdbSStefano Zampini } else { 4164c58f9fdbSStefano Zampini Mat tA_RVT, A_RVT; 4165c58f9fdbSStefano Zampini 4166c58f9fdbSStefano Zampini if (!pcbddc->symmetric_primal) { 4167fb6280fbSStefano Zampini /* A_RV already scaled by -1 */ 41689566063dSJacob Faibussowitsch PetscCall(MatTranspose(A_RV, MAT_INITIAL_MATRIX, &A_RVT)); 4169c58f9fdbSStefano Zampini } else { 4170c58f9fdbSStefano Zampini restoreavr = PETSC_TRUE; 41719566063dSJacob Faibussowitsch PetscCall(MatScale(A_VR, -1.0)); 41729566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A_VR)); 4173c58f9fdbSStefano Zampini A_RVT = A_VR; 4174c58f9fdbSStefano Zampini } 4175c58f9fdbSStefano Zampini if (lda_rhs != n_R) { 4176c58f9fdbSStefano Zampini PetscScalar *aa; 4177c58f9fdbSStefano Zampini PetscInt r, *ii, *jj; 4178c58f9fdbSStefano Zampini PetscBool done; 4179c58f9fdbSStefano Zampini 41809566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A_RVT, 0, PETSC_FALSE, PETSC_FALSE, &r, (const PetscInt **)&ii, (const PetscInt **)&jj, &done)); 418128b400f6SJacob Faibussowitsch PetscCheck(done, PETSC_COMM_SELF, PETSC_ERR_PLIB, "GetRowIJ failed"); 41829566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A_RVT, &aa)); 41839566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, n_vertices, lda_rhs, ii, jj, aa, &tA_RVT)); 41849566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A_RVT, 0, PETSC_FALSE, PETSC_FALSE, &r, (const PetscInt **)&ii, (const PetscInt **)&jj, &done)); 418528b400f6SJacob Faibussowitsch PetscCheck(done, PETSC_COMM_SELF, PETSC_ERR_PLIB, "RestoreRowIJ failed"); 4186c58f9fdbSStefano Zampini } else { 41879566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A_RVT)); 4188c58f9fdbSStefano Zampini tA_RVT = A_RVT; 4189c58f9fdbSStefano Zampini } 41909566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(tA_RVT, &Brhs)); 41919566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tA_RVT)); 41929566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RVT)); 4193c58f9fdbSStefano Zampini } 419472b8c272SStefano Zampini if (F) { 419514393ed6SStefano Zampini /* need to correct the rhs */ 419672b8c272SStefano Zampini if (need_benign_correction) { 419772b8c272SStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 419872b8c272SStefano Zampini PetscScalar *marr; 419972b8c272SStefano Zampini 42009566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(Brhs, &marr)); 42015cbda25cSStefano Zampini if (lda_rhs != n_R) { 42025cbda25cSStefano Zampini for (i = 0; i < n_vertices; i++) { 42039566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dummy_vec, marr + i * lda_rhs)); 42049566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, dummy_vec, NULL, PETSC_FALSE, PETSC_TRUE)); 42059566063dSJacob Faibussowitsch PetscCall(VecResetArray(dummy_vec)); 42065cbda25cSStefano Zampini } 42075cbda25cSStefano Zampini } else { 4208a3df083aSStefano Zampini for (i = 0; i < n_vertices; i++) { 42099566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, marr + i * lda_rhs)); 42109566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, pcbddc->vec1_R, NULL, PETSC_FALSE, PETSC_TRUE)); 42119566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 4212a3df083aSStefano Zampini } 42135cbda25cSStefano Zampini } 42149566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(Brhs, &marr)); 4215a3df083aSStefano Zampini } 42169566063dSJacob Faibussowitsch PetscCall(MatMatSolve(F, Brhs, A_RRmA_RV)); 42171baa6e33SBarry Smith if (restoreavr) PetscCall(MatScale(A_VR, -1.0)); 421814393ed6SStefano Zampini /* need to correct the solution */ 4219a3df083aSStefano Zampini if (need_benign_correction) { 4220df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 4221a3df083aSStefano Zampini PetscScalar *marr; 4222a3df083aSStefano Zampini 42239566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(A_RRmA_RV, &marr)); 42245cbda25cSStefano Zampini if (lda_rhs != n_R) { 42255cbda25cSStefano Zampini for (i = 0; i < n_vertices; i++) { 42269566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dummy_vec, marr + i * lda_rhs)); 42279566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, dummy_vec, NULL, PETSC_TRUE, PETSC_TRUE)); 42289566063dSJacob Faibussowitsch PetscCall(VecResetArray(dummy_vec)); 42295cbda25cSStefano Zampini } 42305cbda25cSStefano Zampini } else { 4231a3df083aSStefano Zampini for (i = 0; i < n_vertices; i++) { 42329566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, marr + i * lda_rhs)); 42339566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, pcbddc->vec1_R, NULL, PETSC_TRUE, PETSC_TRUE)); 42349566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 4235a3df083aSStefano Zampini } 42365cbda25cSStefano Zampini } 42379566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(A_RRmA_RV, &marr)); 4238a3df083aSStefano Zampini } 423906656605SStefano Zampini } else { 42409566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(Brhs, &y)); 424106656605SStefano Zampini for (i = 0; i < n_vertices; i++) { 42429566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, y + i * lda_rhs)); 42439566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec2_R, work + i * lda_rhs)); 42449566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec2_R)); 42459566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec2_R)); 42469566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 42479566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec2_R)); 424806656605SStefano Zampini } 42499566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(Brhs, &y)); 425006656605SStefano Zampini } 42519566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RV)); 42529566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Brhs)); 4253ffd830a3SStefano Zampini /* S_VV and S_CV */ 425406656605SStefano Zampini if (n_constraints) { 425506656605SStefano Zampini Mat B; 425680677318SStefano Zampini 42579566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(work + lda_rhs * n_vertices, n_B * n_vertices)); 425880677318SStefano Zampini for (i = 0; i < n_vertices; i++) { 42599566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, work + i * lda_rhs)); 42609566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcis->vec1_B, work + lda_rhs * n_vertices + i * n_B)); 42619566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, pcbddc->vec1_R, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 42629566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, pcbddc->vec1_R, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 42639566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcis->vec1_B)); 42649566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 426580677318SStefano Zampini } 42669566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_B, n_vertices, work + lda_rhs * n_vertices, &B)); 42674222ddf1SHong Zhang /* Reuse dense S_C = pcbddc->local_auxmat1 * B */ 42689566063dSJacob Faibussowitsch PetscCall(MatProductCreateWithMat(pcbddc->local_auxmat1, B, NULL, S_CV)); 42699566063dSJacob Faibussowitsch PetscCall(MatProductSetType(S_CV, MATPRODUCT_AB)); 42709566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(S_CV)); 42719566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(S_CV)); 42729566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(S_CV)); 42739566063dSJacob Faibussowitsch PetscCall(MatProductClear(S_CV)); 42744222ddf1SHong Zhang 42759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 42769566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, lda_rhs, n_vertices, work + lda_rhs * n_vertices, &B)); 42774222ddf1SHong Zhang /* Reuse B = local_auxmat2_R * S_CV */ 42789566063dSJacob Faibussowitsch PetscCall(MatProductCreateWithMat(local_auxmat2_R, S_CV, NULL, B)); 42799566063dSJacob Faibussowitsch PetscCall(MatProductSetType(B, MATPRODUCT_AB)); 42809566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(B)); 42819566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(B)); 42829566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(B)); 42834222ddf1SHong Zhang 42849566063dSJacob Faibussowitsch PetscCall(MatScale(S_CV, m_one)); 42859566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(lda_rhs * n_vertices, &B_N)); 4286792fecdfSBarry Smith PetscCallBLAS("BLASaxpy", BLASaxpy_(&B_N, &one, work + lda_rhs * n_vertices, &B_one, work, &B_one)); 42879566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 428806656605SStefano Zampini } 4289ffd830a3SStefano Zampini if (lda_rhs != n_R) { 42909566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RRmA_RV)); 42919566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_R, n_vertices, work, &A_RRmA_RV)); 42929566063dSJacob Faibussowitsch PetscCall(MatDenseSetLDA(A_RRmA_RV, lda_rhs)); 4293ffd830a3SStefano Zampini } 42949566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_VR, A_RRmA_RV, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &S_VVt)); 429514393ed6SStefano Zampini /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */ 429614393ed6SStefano Zampini if (need_benign_correction) { 4297df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 429814393ed6SStefano Zampini PetscScalar *marr, *sums; 429914393ed6SStefano Zampini 43009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_vertices, &sums)); 43019566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(S_VVt, &marr)); 4302df4d28bfSStefano Zampini for (i = 0; i < reuse_solver->benign_n; i++) { 430314393ed6SStefano Zampini const PetscScalar *vals; 430414393ed6SStefano Zampini const PetscInt *idxs, *idxs_zero; 430514393ed6SStefano Zampini PetscInt n, j, nz; 430614393ed6SStefano Zampini 43079566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i], &nz)); 43089566063dSJacob Faibussowitsch PetscCall(ISGetIndices(reuse_solver->benign_zerodiag_subs[i], &idxs_zero)); 430914393ed6SStefano Zampini for (j = 0; j < n_vertices; j++) { 431014393ed6SStefano Zampini PetscInt k; 431114393ed6SStefano Zampini sums[j] = 0.; 431214393ed6SStefano Zampini for (k = 0; k < nz; k++) sums[j] += work[idxs_zero[k] + j * lda_rhs]; 431314393ed6SStefano Zampini } 43149566063dSJacob Faibussowitsch PetscCall(MatGetRow(A_RV_bcorr, i, &n, &idxs, &vals)); 431514393ed6SStefano Zampini for (j = 0; j < n; j++) { 431614393ed6SStefano Zampini PetscScalar val = vals[j]; 431714393ed6SStefano Zampini PetscInt k; 4318ad540459SPierre Jolivet for (k = 0; k < n_vertices; k++) marr[idxs[j] + k * n_vertices] += val * sums[k]; 431914393ed6SStefano Zampini } 43209566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(A_RV_bcorr, i, &n, &idxs, &vals)); 43219566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i], &idxs_zero)); 432214393ed6SStefano Zampini } 43239566063dSJacob Faibussowitsch PetscCall(PetscFree(sums)); 43249566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(S_VVt, &marr)); 43259566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RV_bcorr)); 432614393ed6SStefano Zampini } 43279566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RRmA_RV)); 43289566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(n_vertices * n_vertices, &B_N)); 43299566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(A_VV, &x)); 43309566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(S_VVt, &y)); 4331792fecdfSBarry Smith PetscCallBLAS("BLASaxpy", BLASaxpy_(&B_N, &one, x, &B_one, y, &B_one)); 43329566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(A_VV, &x)); 43339566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(S_VVt, &y)); 43349566063dSJacob Faibussowitsch PetscCall(MatCopy(S_VVt, S_VV, SAME_NONZERO_PATTERN)); 43359566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_VVt)); 4336019a44ceSStefano Zampini } else { 43379566063dSJacob Faibussowitsch PetscCall(MatCopy(A_VV, S_VV, SAME_NONZERO_PATTERN)); 4338d16cbb6bSStefano Zampini } 43399566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_VV)); 4340d16cbb6bSStefano Zampini 434106656605SStefano Zampini /* coarse basis functions */ 434206656605SStefano Zampini for (i = 0; i < n_vertices; i++) { 4343ab2d12f3SJunchao Zhang Vec v; 4344ab2d12f3SJunchao Zhang PetscScalar one = 1.0, zero = 0.0; 434516f15bc4SStefano Zampini 43469566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, work + lda_rhs * i)); 43479566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVec(pcbddc->coarse_phi_B, i, &v)); 43489566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 43499566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 4350ab2d12f3SJunchao Zhang if (PetscDefined(USE_DEBUG)) { /* The following VecSetValues() expects a sequential matrix */ 4351ab2d12f3SJunchao Zhang PetscMPIInt rank; 43529566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pcbddc->coarse_phi_B), &rank)); 435308401ef6SPierre Jolivet PetscCheck(rank <= 1, PetscObjectComm((PetscObject)pcbddc->coarse_phi_B), PETSC_ERR_PLIB, "Expected a sequential dense matrix"); 4354ab2d12f3SJunchao Zhang } 43559566063dSJacob Faibussowitsch PetscCall(VecSetValues(v, 1, &idx_V_B[i], &one, INSERT_VALUES)); 43569566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(v)); /* If v is on device, hope VecSetValues() eventually implemented by a host to device memcopy */ 43579566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(v)); 43589566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_phi_B, i, &v)); 435906656605SStefano Zampini 436006656605SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 43614f1b2e48SStefano Zampini PetscInt j; 43624f1b2e48SStefano Zampini 43639566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVec(pcbddc->coarse_phi_D, i, &v)); 43649566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_D, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 43659566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_D, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 4366ab2d12f3SJunchao Zhang if (PetscDefined(USE_DEBUG)) { /* The following VecSetValues() expects a sequential matrix */ 4367ab2d12f3SJunchao Zhang PetscMPIInt rank; 43689566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pcbddc->coarse_phi_D), &rank)); 436908401ef6SPierre Jolivet PetscCheck(rank <= 1, PetscObjectComm((PetscObject)pcbddc->coarse_phi_D), PETSC_ERR_PLIB, "Expected a sequential dense matrix"); 4370ab2d12f3SJunchao Zhang } 43719566063dSJacob Faibussowitsch for (j = 0; j < pcbddc->benign_n; j++) PetscCall(VecSetValues(v, 1, &p0_lidx_I[j], &zero, INSERT_VALUES)); 43729566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(v)); 43739566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(v)); 43749566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_phi_D, i, &v)); 437506656605SStefano Zampini } 43769566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 437706656605SStefano Zampini } 437804708bb6SStefano Zampini /* if n_R == 0 the object is not destroyed */ 43799566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RV)); 438006656605SStefano Zampini } 43819566063dSJacob Faibussowitsch PetscCall(VecDestroy(&dummy_vec)); 438206656605SStefano Zampini 438306656605SStefano Zampini if (n_constraints) { 438406656605SStefano Zampini Mat B; 438506656605SStefano Zampini 43869566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, lda_rhs, n_constraints, work, &B)); 43879566063dSJacob Faibussowitsch PetscCall(MatScale(S_CC, m_one)); 43889566063dSJacob Faibussowitsch PetscCall(MatProductCreateWithMat(local_auxmat2_R, S_CC, NULL, B)); 43899566063dSJacob Faibussowitsch PetscCall(MatProductSetType(B, MATPRODUCT_AB)); 43909566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(B)); 43919566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(B)); 43929566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(B)); 4393a961b312SStefano Zampini 43949566063dSJacob Faibussowitsch PetscCall(MatScale(S_CC, m_one)); 439506656605SStefano Zampini if (n_vertices) { 439603dfb2d7SStefano Zampini if (isCHOL || need_benign_correction) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */ 43977fb60732SBarry Smith PetscCall(MatTransposeSetPrecursor(S_CV, S_VC)); 43989566063dSJacob Faibussowitsch PetscCall(MatTranspose(S_CV, MAT_REUSE_MATRIX, &S_VC)); 439980677318SStefano Zampini } else { 440080677318SStefano Zampini Mat S_VCt; 440180677318SStefano Zampini 4402ffd830a3SStefano Zampini if (lda_rhs != n_R) { 44039566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 44049566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_R, n_constraints, work, &B)); 44059566063dSJacob Faibussowitsch PetscCall(MatDenseSetLDA(B, lda_rhs)); 4406ffd830a3SStefano Zampini } 44079566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_VR, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &S_VCt)); 44089566063dSJacob Faibussowitsch PetscCall(MatCopy(S_VCt, S_VC, SAME_NONZERO_PATTERN)); 44099566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_VCt)); 441080677318SStefano Zampini } 441106656605SStefano Zampini } 44129566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 441306656605SStefano Zampini /* coarse basis functions */ 441406656605SStefano Zampini for (i = 0; i < n_constraints; i++) { 4415ab2d12f3SJunchao Zhang Vec v; 441606656605SStefano Zampini 44179566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, work + lda_rhs * i)); 44189566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVec(pcbddc->coarse_phi_B, i + n_vertices, &v)); 44199566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 44209566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 44219566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_phi_B, i + n_vertices, &v)); 442206656605SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 44234f1b2e48SStefano Zampini PetscInt j; 4424ab2d12f3SJunchao Zhang PetscScalar zero = 0.0; 44259566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVec(pcbddc->coarse_phi_D, i + n_vertices, &v)); 44269566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_D, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 44279566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_D, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 44289566063dSJacob Faibussowitsch for (j = 0; j < pcbddc->benign_n; j++) PetscCall(VecSetValues(v, 1, &p0_lidx_I[j], &zero, INSERT_VALUES)); 44299566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(v)); 44309566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(v)); 44319566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_phi_D, i + n_vertices, &v)); 443206656605SStefano Zampini } 44339566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 443406656605SStefano Zampini } 443506656605SStefano Zampini } 443648a46eb9SPierre Jolivet if (n_constraints) PetscCall(MatDestroy(&local_auxmat2_R)); 44379566063dSJacob Faibussowitsch PetscCall(PetscFree(p0_lidx_I)); 443872b8c272SStefano Zampini 443972b8c272SStefano Zampini /* coarse matrix entries relative to B_0 */ 444072b8c272SStefano Zampini if (pcbddc->benign_n) { 444172b8c272SStefano Zampini Mat B0_B, B0_BPHI; 444272b8c272SStefano Zampini IS is_dummy; 44431683a169SBarry Smith const PetscScalar *data; 444472b8c272SStefano Zampini PetscInt j; 444572b8c272SStefano Zampini 44469566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pcbddc->benign_n, 0, 1, &is_dummy)); 44479566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->benign_B0, is_dummy, pcis->is_B_local, MAT_INITIAL_MATRIX, &B0_B)); 44489566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_dummy)); 44499566063dSJacob Faibussowitsch PetscCall(MatMatMult(B0_B, pcbddc->coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &B0_BPHI)); 44509566063dSJacob Faibussowitsch PetscCall(MatConvert(B0_BPHI, MATSEQDENSE, MAT_INPLACE_MATRIX, &B0_BPHI)); 44519566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(B0_BPHI, &data)); 445272b8c272SStefano Zampini for (j = 0; j < pcbddc->benign_n; j++) { 445372b8c272SStefano Zampini PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j; 445472b8c272SStefano Zampini for (i = 0; i < pcbddc->local_primal_size; i++) { 445572b8c272SStefano Zampini coarse_submat_vals[primal_idx * pcbddc->local_primal_size + i] = data[i * pcbddc->benign_n + j]; 445672b8c272SStefano Zampini coarse_submat_vals[i * pcbddc->local_primal_size + primal_idx] = data[i * pcbddc->benign_n + j]; 445772b8c272SStefano Zampini } 445872b8c272SStefano Zampini } 44599566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(B0_BPHI, &data)); 44609566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B0_B)); 44619566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B0_BPHI)); 446272b8c272SStefano Zampini } 4463019a44ceSStefano Zampini 446406656605SStefano Zampini /* compute other basis functions for non-symmetric problems */ 44653301b35fSStefano Zampini if (!pcbddc->symmetric_primal) { 4466ffd830a3SStefano Zampini Mat B_V = NULL, B_C = NULL; 4467ffd830a3SStefano Zampini PetscScalar *marray; 446806656605SStefano Zampini 446906656605SStefano Zampini if (n_constraints) { 4470ffd830a3SStefano Zampini Mat S_CCT, C_CRT; 447106656605SStefano Zampini 44729566063dSJacob Faibussowitsch PetscCall(MatTranspose(C_CR, MAT_INITIAL_MATRIX, &C_CRT)); 44739566063dSJacob Faibussowitsch PetscCall(MatTranspose(S_CC, MAT_INITIAL_MATRIX, &S_CCT)); 44749566063dSJacob Faibussowitsch PetscCall(MatMatMult(C_CRT, S_CCT, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &B_C)); 44759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_CCT)); 447606656605SStefano Zampini if (n_vertices) { 4477ffd830a3SStefano Zampini Mat S_VCT; 447806656605SStefano Zampini 44799566063dSJacob Faibussowitsch PetscCall(MatTranspose(S_VC, MAT_INITIAL_MATRIX, &S_VCT)); 44809566063dSJacob Faibussowitsch PetscCall(MatMatMult(C_CRT, S_VCT, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &B_V)); 44819566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_VCT)); 448206656605SStefano Zampini } 44839566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C_CRT)); 44845b782168SStefano Zampini } else { 44859566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_R, n_vertices, NULL, &B_V)); 448606656605SStefano Zampini } 448716f15bc4SStefano Zampini if (n_vertices && n_R) { 4488ffd830a3SStefano Zampini PetscScalar *av, *marray; 4489ffd830a3SStefano Zampini const PetscInt *xadj, *adjncy; 4490ffd830a3SStefano Zampini PetscInt n; 4491ffd830a3SStefano Zampini PetscBool flg_row; 449206656605SStefano Zampini 4493ffd830a3SStefano Zampini /* B_V = B_V - A_VR^T */ 44949566063dSJacob Faibussowitsch PetscCall(MatConvert(A_VR, MATSEQAIJ, MAT_INPLACE_MATRIX, &A_VR)); 44959566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A_VR, 0, PETSC_FALSE, PETSC_FALSE, &n, &xadj, &adjncy, &flg_row)); 44969566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A_VR, &av)); 44979566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(B_V, &marray)); 4498ffd830a3SStefano Zampini for (i = 0; i < n; i++) { 4499ffd830a3SStefano Zampini PetscInt j; 4500ffd830a3SStefano Zampini for (j = xadj[i]; j < xadj[i + 1]; j++) marray[i * n_R + adjncy[j]] -= av[j]; 4501ffd830a3SStefano Zampini } 45029566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(B_V, &marray)); 45039566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A_VR, 0, PETSC_FALSE, PETSC_FALSE, &n, &xadj, &adjncy, &flg_row)); 45049566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_VR)); 450506656605SStefano Zampini } 450606656605SStefano Zampini 4507ffd830a3SStefano Zampini /* currently there's no support for MatTransposeMatSolve(F,B,X) */ 4508abc8f43dSstefano_zampini if (n_vertices) { 45099566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(B_V, &marray)); 4510ffd830a3SStefano Zampini for (i = 0; i < n_vertices; i++) { 45119566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, marray + i * n_R)); 45129566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec2_R, work + i * n_R)); 45139566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec2_R)); 45149566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec2_R)); 45159566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 45169566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec2_R)); 451706656605SStefano Zampini } 45189566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(B_V, &marray)); 4519abc8f43dSstefano_zampini } 45205b782168SStefano Zampini if (B_C) { 45219566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(B_C, &marray)); 4522ffd830a3SStefano Zampini for (i = n_vertices; i < n_constraints + n_vertices; i++) { 45239566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, marray + (i - n_vertices) * n_R)); 45249566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec2_R, work + i * n_R)); 45259566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec2_R)); 45269566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec2_R)); 45279566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 45289566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec2_R)); 452906656605SStefano Zampini } 45309566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(B_C, &marray)); 45315b782168SStefano Zampini } 453206656605SStefano Zampini /* coarse basis functions */ 453306656605SStefano Zampini for (i = 0; i < pcbddc->local_primal_size; i++) { 4534ab2d12f3SJunchao Zhang Vec v; 453506656605SStefano Zampini 45369566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, work + i * n_R)); 45379566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVec(pcbddc->coarse_psi_B, i, &v)); 45389566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 45399566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 454006656605SStefano Zampini if (i < n_vertices) { 4541ab2d12f3SJunchao Zhang PetscScalar one = 1.0; 45429566063dSJacob Faibussowitsch PetscCall(VecSetValues(v, 1, &idx_V_B[i], &one, INSERT_VALUES)); 45439566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(v)); 45449566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(v)); 454506656605SStefano Zampini } 45469566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_psi_B, i, &v)); 454706656605SStefano Zampini 454806656605SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 45499566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVec(pcbddc->coarse_psi_D, i, &v)); 45509566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_D, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 45519566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_D, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 45529566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_psi_D, i, &v)); 455306656605SStefano Zampini } 45549566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 455506656605SStefano Zampini } 45569566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B_V)); 45579566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B_C)); 455806656605SStefano Zampini } 4559a6e023c1Sstefano_zampini 4560d62866d3SStefano Zampini /* free memory */ 45619566063dSJacob Faibussowitsch PetscCall(PetscFree(idx_V_B)); 45629566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_VV)); 45639566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_CV)); 45649566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_VC)); 45659566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_CC)); 45669566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 456748a46eb9SPierre Jolivet if (n_vertices) PetscCall(MatDestroy(&A_VR)); 456848a46eb9SPierre Jolivet if (n_constraints) PetscCall(MatDestroy(&C_CR)); 45699566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_CorrectionSetUp[pcbddc->current_level], pc, 0, 0, 0)); 45708ead10e4SStefano Zampini 4571da81f932SPierre Jolivet /* Checking coarse_sub_mat and coarse basis functions */ 457288ebb749SStefano Zampini /* Symmetric case : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */ 457388ebb749SStefano Zampini /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */ 4574d12edf2fSStefano Zampini if (pcbddc->dbg_flag) { 457588ebb749SStefano Zampini Mat coarse_sub_mat; 457625084f0cSStefano Zampini Mat AUXMAT, TM1, TM2, TM3, TM4; 457788ebb749SStefano Zampini Mat coarse_phi_D, coarse_phi_B; 457888ebb749SStefano Zampini Mat coarse_psi_D, coarse_psi_B; 457988ebb749SStefano Zampini Mat A_II, A_BB, A_IB, A_BI; 45808bec7fa6SStefano Zampini Mat C_B, CPHI; 45818bec7fa6SStefano Zampini IS is_dummy; 45828bec7fa6SStefano Zampini Vec mones; 458388ebb749SStefano Zampini MatType checkmattype = MATSEQAIJ; 458488ebb749SStefano Zampini PetscReal real_value; 458588ebb749SStefano Zampini 4586a3df083aSStefano Zampini if (pcbddc->benign_n && !pcbddc->benign_change_explicit) { 4587a3df083aSStefano Zampini Mat A; 45889566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignProject(pc, NULL, NULL, &A)); 45899566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, pcis->is_I_local, pcis->is_I_local, MAT_INITIAL_MATRIX, &A_II)); 45909566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, pcis->is_I_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &A_IB)); 45919566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, pcis->is_B_local, pcis->is_I_local, MAT_INITIAL_MATRIX, &A_BI)); 45929566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, pcis->is_B_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &A_BB)); 45939566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 4594a3df083aSStefano Zampini } else { 45959566063dSJacob Faibussowitsch PetscCall(MatConvert(pcis->A_II, checkmattype, MAT_INITIAL_MATRIX, &A_II)); 45969566063dSJacob Faibussowitsch PetscCall(MatConvert(pcis->A_IB, checkmattype, MAT_INITIAL_MATRIX, &A_IB)); 45979566063dSJacob Faibussowitsch PetscCall(MatConvert(pcis->A_BI, checkmattype, MAT_INITIAL_MATRIX, &A_BI)); 45989566063dSJacob Faibussowitsch PetscCall(MatConvert(pcis->A_BB, checkmattype, MAT_INITIAL_MATRIX, &A_BB)); 4599a3df083aSStefano Zampini } 46009566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->coarse_phi_D, checkmattype, MAT_INITIAL_MATRIX, &coarse_phi_D)); 46019566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->coarse_phi_B, checkmattype, MAT_INITIAL_MATRIX, &coarse_phi_B)); 4602ffd830a3SStefano Zampini if (!pcbddc->symmetric_primal) { 46039566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->coarse_psi_D, checkmattype, MAT_INITIAL_MATRIX, &coarse_psi_D)); 46049566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->coarse_psi_B, checkmattype, MAT_INITIAL_MATRIX, &coarse_psi_B)); 460588ebb749SStefano Zampini } 46069566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, pcbddc->local_primal_size, pcbddc->local_primal_size, coarse_submat_vals, &coarse_sub_mat)); 460788ebb749SStefano Zampini 46089566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 46099566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Check coarse sub mat computation (symmetric %d)\n", pcbddc->symmetric_primal)); 46109566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 4611ffd830a3SStefano Zampini if (!pcbddc->symmetric_primal) { 46129566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_II, coarse_phi_D, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 46139566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_psi_D, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM1)); 46149566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 46159566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_BB, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 46169566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_psi_B, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM2)); 46179566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 46189566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_IB, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 46199566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_psi_D, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM3)); 46209566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 46219566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_BI, coarse_phi_D, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 46229566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_psi_B, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM4)); 46239566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 462488ebb749SStefano Zampini } else { 46259566063dSJacob Faibussowitsch PetscCall(MatPtAP(A_II, coarse_phi_D, MAT_INITIAL_MATRIX, 1.0, &TM1)); 46269566063dSJacob Faibussowitsch PetscCall(MatPtAP(A_BB, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &TM2)); 46279566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_IB, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 46289566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_phi_D, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM3)); 46299566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 46309566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_BI, coarse_phi_D, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 46319566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_phi_B, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM4)); 46329566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 463388ebb749SStefano Zampini } 46349566063dSJacob Faibussowitsch PetscCall(MatAXPY(TM1, one, TM2, DIFFERENT_NONZERO_PATTERN)); 46359566063dSJacob Faibussowitsch PetscCall(MatAXPY(TM1, one, TM3, DIFFERENT_NONZERO_PATTERN)); 46369566063dSJacob Faibussowitsch PetscCall(MatAXPY(TM1, one, TM4, DIFFERENT_NONZERO_PATTERN)); 46379566063dSJacob Faibussowitsch PetscCall(MatConvert(TM1, MATSEQDENSE, MAT_INPLACE_MATRIX, &TM1)); 46384f1b2e48SStefano Zampini if (pcbddc->benign_n) { 4639fc227af8SStefano Zampini Mat B0_B, B0_BPHI; 46401683a169SBarry Smith const PetscScalar *data2; 46411683a169SBarry Smith PetscScalar *data; 46424f1b2e48SStefano Zampini PetscInt j; 4643d12edf2fSStefano Zampini 46449566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pcbddc->benign_n, 0, 1, &is_dummy)); 46459566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->benign_B0, is_dummy, pcis->is_B_local, MAT_INITIAL_MATRIX, &B0_B)); 46469566063dSJacob Faibussowitsch PetscCall(MatMatMult(B0_B, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &B0_BPHI)); 46479566063dSJacob Faibussowitsch PetscCall(MatConvert(B0_BPHI, MATSEQDENSE, MAT_INPLACE_MATRIX, &B0_BPHI)); 46489566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(TM1, &data)); 46499566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(B0_BPHI, &data2)); 46504f1b2e48SStefano Zampini for (j = 0; j < pcbddc->benign_n; j++) { 46514f1b2e48SStefano Zampini PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j; 4652d12edf2fSStefano Zampini for (i = 0; i < pcbddc->local_primal_size; i++) { 46534f1b2e48SStefano Zampini data[primal_idx * pcbddc->local_primal_size + i] += data2[i * pcbddc->benign_n + j]; 46544f1b2e48SStefano Zampini data[i * pcbddc->local_primal_size + primal_idx] += data2[i * pcbddc->benign_n + j]; 46554f1b2e48SStefano Zampini } 4656d12edf2fSStefano Zampini } 46579566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(TM1, &data)); 46589566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(B0_BPHI, &data2)); 46599566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B0_B)); 46609566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_dummy)); 46619566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B0_BPHI)); 4662d12edf2fSStefano Zampini } 4663d12edf2fSStefano Zampini #if 0 4664d12edf2fSStefano Zampini { 4665d12edf2fSStefano Zampini PetscViewer viewer; 4666d12edf2fSStefano Zampini char filename[256]; 4667a364092eSJacob Faibussowitsch PetscCall(PetscSNPrintf(filename, PETSC_STATIC_ARRAY_LENGTH(filename), "details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level)); 46689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer)); 46699566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB)); 46709566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coarse_sub_mat,"computed")); 46719566063dSJacob Faibussowitsch PetscCall(MatView(coarse_sub_mat,viewer)); 46729566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)TM1,"projected")); 46739566063dSJacob Faibussowitsch PetscCall(MatView(TM1,viewer)); 4674a7414863SStefano Zampini if (pcbddc->coarse_phi_B) { 46759566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B")); 46769566063dSJacob Faibussowitsch PetscCall(MatView(pcbddc->coarse_phi_B,viewer)); 467772b8c272SStefano Zampini } 4678ffd830a3SStefano Zampini if (pcbddc->coarse_phi_D) { 46799566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D")); 46809566063dSJacob Faibussowitsch PetscCall(MatView(pcbddc->coarse_phi_D,viewer)); 4681ffd830a3SStefano Zampini } 4682ffd830a3SStefano Zampini if (pcbddc->coarse_psi_B) { 46839566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B")); 46849566063dSJacob Faibussowitsch PetscCall(MatView(pcbddc->coarse_psi_B,viewer)); 4685ffd830a3SStefano Zampini } 468672b8c272SStefano Zampini if (pcbddc->coarse_psi_D) { 46879566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D")); 46889566063dSJacob Faibussowitsch PetscCall(MatView(pcbddc->coarse_psi_D,viewer)); 4689ffd830a3SStefano Zampini } 46909566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)pcbddc->local_mat,"A")); 46919566063dSJacob Faibussowitsch PetscCall(MatView(pcbddc->local_mat,viewer)); 46929566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)pcbddc->ConstraintMatrix,"C")); 46939566063dSJacob Faibussowitsch PetscCall(MatView(pcbddc->ConstraintMatrix,viewer)); 46949566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)pcis->is_I_local,"I")); 46959566063dSJacob Faibussowitsch PetscCall(ISView(pcis->is_I_local,viewer)); 46969566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)pcis->is_B_local,"B")); 46979566063dSJacob Faibussowitsch PetscCall(ISView(pcis->is_B_local,viewer)); 46989566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)pcbddc->is_R_local,"R")); 46999566063dSJacob Faibussowitsch PetscCall(ISView(pcbddc->is_R_local,viewer)); 47009566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 4701d12edf2fSStefano Zampini } 4702d12edf2fSStefano Zampini #endif 47039566063dSJacob Faibussowitsch PetscCall(MatAXPY(TM1, m_one, coarse_sub_mat, DIFFERENT_NONZERO_PATTERN)); 47049566063dSJacob Faibussowitsch PetscCall(MatNorm(TM1, NORM_FROBENIUS, &real_value)); 47059566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 470663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d matrix error % 1.14e\n", PetscGlobalRank, (double)real_value)); 47078bec7fa6SStefano Zampini 47088bec7fa6SStefano Zampini /* check constraints */ 47099566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pcbddc->local_primal_size - pcbddc->benign_n, 0, 1, &is_dummy)); 47109566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->ConstraintMatrix, is_dummy, pcis->is_B_local, MAT_INITIAL_MATRIX, &C_B)); 47114f1b2e48SStefano Zampini if (!pcbddc->benign_n) { /* TODO: add benign case */ 47129566063dSJacob Faibussowitsch PetscCall(MatMatMult(C_B, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &CPHI)); 4713a00504b5SStefano Zampini } else { 4714a00504b5SStefano Zampini PetscScalar *data; 4715a00504b5SStefano Zampini Mat tmat; 47169566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(pcbddc->coarse_phi_B, &data)); 47179566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, pcis->n_B, pcbddc->local_primal_size - pcbddc->benign_n, data, &tmat)); 47189566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(pcbddc->coarse_phi_B, &data)); 47199566063dSJacob Faibussowitsch PetscCall(MatMatMult(C_B, tmat, MAT_INITIAL_MATRIX, 1.0, &CPHI)); 47209566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tmat)); 4721a00504b5SStefano Zampini } 47229566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(CPHI, &mones, NULL)); 47239566063dSJacob Faibussowitsch PetscCall(VecSet(mones, -1.0)); 47249566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(CPHI, mones, ADD_VALUES)); 47259566063dSJacob Faibussowitsch PetscCall(MatNorm(CPHI, NORM_FROBENIUS, &real_value)); 472663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d phi constraints error % 1.14e\n", PetscGlobalRank, (double)real_value)); 4727ffd830a3SStefano Zampini if (!pcbddc->symmetric_primal) { 47289566063dSJacob Faibussowitsch PetscCall(MatMatMult(C_B, coarse_psi_B, MAT_REUSE_MATRIX, 1.0, &CPHI)); 47299566063dSJacob Faibussowitsch PetscCall(VecSet(mones, -1.0)); 47309566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(CPHI, mones, ADD_VALUES)); 47319566063dSJacob Faibussowitsch PetscCall(MatNorm(CPHI, NORM_FROBENIUS, &real_value)); 473263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d psi constraints error % 1.14e\n", PetscGlobalRank, (double)real_value)); 473388ebb749SStefano Zampini } 47349566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C_B)); 47359566063dSJacob Faibussowitsch PetscCall(MatDestroy(&CPHI)); 47369566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_dummy)); 47379566063dSJacob Faibussowitsch PetscCall(VecDestroy(&mones)); 47389566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 47399566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_II)); 47409566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_BB)); 47419566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_IB)); 47429566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_BI)); 47439566063dSJacob Faibussowitsch PetscCall(MatDestroy(&TM1)); 47449566063dSJacob Faibussowitsch PetscCall(MatDestroy(&TM2)); 47459566063dSJacob Faibussowitsch PetscCall(MatDestroy(&TM3)); 47469566063dSJacob Faibussowitsch PetscCall(MatDestroy(&TM4)); 47479566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_phi_D)); 47489566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_phi_B)); 4749ffd830a3SStefano Zampini if (!pcbddc->symmetric_primal) { 47509566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_psi_D)); 47519566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_psi_B)); 475288ebb749SStefano Zampini } 47539566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_sub_mat)); 475488ebb749SStefano Zampini } 47557ebab0bbSStefano Zampini /* FINAL CUDA support (we cannot currently mix viennacl and cuda vectors */ 47567ebab0bbSStefano Zampini { 47577ebab0bbSStefano Zampini PetscBool gpu; 47587ebab0bbSStefano Zampini 47599566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pcis->vec1_N, VECSEQCUDA, &gpu)); 47607ebab0bbSStefano Zampini if (gpu) { 476148a46eb9SPierre Jolivet if (pcbddc->local_auxmat1) PetscCall(MatConvert(pcbddc->local_auxmat1, MATSEQDENSECUDA, MAT_INPLACE_MATRIX, &pcbddc->local_auxmat1)); 476248a46eb9SPierre Jolivet if (pcbddc->local_auxmat2) PetscCall(MatConvert(pcbddc->local_auxmat2, MATSEQDENSECUDA, MAT_INPLACE_MATRIX, &pcbddc->local_auxmat2)); 476348a46eb9SPierre Jolivet if (pcbddc->coarse_phi_B) PetscCall(MatConvert(pcbddc->coarse_phi_B, MATSEQDENSECUDA, MAT_INPLACE_MATRIX, &pcbddc->coarse_phi_B)); 476448a46eb9SPierre Jolivet if (pcbddc->coarse_phi_D) PetscCall(MatConvert(pcbddc->coarse_phi_D, MATSEQDENSECUDA, MAT_INPLACE_MATRIX, &pcbddc->coarse_phi_D)); 476548a46eb9SPierre Jolivet if (pcbddc->coarse_psi_B) PetscCall(MatConvert(pcbddc->coarse_psi_B, MATSEQDENSECUDA, MAT_INPLACE_MATRIX, &pcbddc->coarse_psi_B)); 476648a46eb9SPierre Jolivet if (pcbddc->coarse_psi_D) PetscCall(MatConvert(pcbddc->coarse_psi_D, MATSEQDENSECUDA, MAT_INPLACE_MATRIX, &pcbddc->coarse_psi_D)); 47677ebab0bbSStefano Zampini } 47687ebab0bbSStefano Zampini } 47698629588bSStefano Zampini /* get back data */ 47708629588bSStefano Zampini *coarse_submat_vals_n = coarse_submat_vals; 47713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 477288ebb749SStefano Zampini } 477388ebb749SStefano Zampini 4774d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat *B) 4775d71ae5a4SJacob Faibussowitsch { 4776d65f70fdSStefano Zampini Mat *work_mat; 4777d65f70fdSStefano Zampini IS isrow_s, iscol_s; 4778d65f70fdSStefano Zampini PetscBool rsorted, csorted; 4779c43ebad9SStefano Zampini PetscInt rsize, *idxs_perm_r = NULL, csize, *idxs_perm_c = NULL; 4780aa0d41d4SStefano Zampini 4781aa0d41d4SStefano Zampini PetscFunctionBegin; 47829566063dSJacob Faibussowitsch PetscCall(ISSorted(isrow, &rsorted)); 47839566063dSJacob Faibussowitsch PetscCall(ISSorted(iscol, &csorted)); 47849566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isrow, &rsize)); 47859566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(iscol, &csize)); 4786aa0d41d4SStefano Zampini 4787d65f70fdSStefano Zampini if (!rsorted) { 4788906d46d4SStefano Zampini const PetscInt *idxs; 4789906d46d4SStefano Zampini PetscInt *idxs_sorted, i; 4790aa0d41d4SStefano Zampini 47919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rsize, &idxs_perm_r)); 47929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rsize, &idxs_sorted)); 4793ad540459SPierre Jolivet for (i = 0; i < rsize; i++) idxs_perm_r[i] = i; 47949566063dSJacob Faibussowitsch PetscCall(ISGetIndices(isrow, &idxs)); 47959566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithPermutation(rsize, idxs, idxs_perm_r)); 4796ad540459SPierre Jolivet for (i = 0; i < rsize; i++) idxs_sorted[i] = idxs[idxs_perm_r[i]]; 47979566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(isrow, &idxs)); 47989566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, rsize, idxs_sorted, PETSC_OWN_POINTER, &isrow_s)); 4799d65f70fdSStefano Zampini } else { 48009566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)isrow)); 4801d65f70fdSStefano Zampini isrow_s = isrow; 4802aa0d41d4SStefano Zampini } 4803906d46d4SStefano Zampini 4804d65f70fdSStefano Zampini if (!csorted) { 4805d65f70fdSStefano Zampini if (isrow == iscol) { 48069566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)isrow_s)); 4807d65f70fdSStefano Zampini iscol_s = isrow_s; 4808d65f70fdSStefano Zampini } else { 4809d65f70fdSStefano Zampini const PetscInt *idxs; 4810d65f70fdSStefano Zampini PetscInt *idxs_sorted, i; 4811906d46d4SStefano Zampini 48129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(csize, &idxs_perm_c)); 48139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(csize, &idxs_sorted)); 4814ad540459SPierre Jolivet for (i = 0; i < csize; i++) idxs_perm_c[i] = i; 48159566063dSJacob Faibussowitsch PetscCall(ISGetIndices(iscol, &idxs)); 48169566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithPermutation(csize, idxs, idxs_perm_c)); 4817ad540459SPierre Jolivet for (i = 0; i < csize; i++) idxs_sorted[i] = idxs[idxs_perm_c[i]]; 48189566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(iscol, &idxs)); 48199566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, csize, idxs_sorted, PETSC_OWN_POINTER, &iscol_s)); 4820d65f70fdSStefano Zampini } 4821d65f70fdSStefano Zampini } else { 48229566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)iscol)); 4823d65f70fdSStefano Zampini iscol_s = iscol; 4824d65f70fdSStefano Zampini } 4825d65f70fdSStefano Zampini 48269566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(A, 1, &isrow_s, &iscol_s, MAT_INITIAL_MATRIX, &work_mat)); 4827d65f70fdSStefano Zampini 4828d65f70fdSStefano Zampini if (!rsorted || !csorted) { 4829906d46d4SStefano Zampini Mat new_mat; 4830d65f70fdSStefano Zampini IS is_perm_r, is_perm_c; 4831906d46d4SStefano Zampini 4832d65f70fdSStefano Zampini if (!rsorted) { 4833d65f70fdSStefano Zampini PetscInt *idxs_r, i; 48349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rsize, &idxs_r)); 4835ad540459SPierre Jolivet for (i = 0; i < rsize; i++) idxs_r[idxs_perm_r[i]] = i; 48369566063dSJacob Faibussowitsch PetscCall(PetscFree(idxs_perm_r)); 48379566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, rsize, idxs_r, PETSC_OWN_POINTER, &is_perm_r)); 4838d65f70fdSStefano Zampini } else { 48399566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, rsize, 0, 1, &is_perm_r)); 4840906d46d4SStefano Zampini } 48419566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(is_perm_r)); 4842d65f70fdSStefano Zampini 4843d65f70fdSStefano Zampini if (!csorted) { 4844d65f70fdSStefano Zampini if (isrow_s == iscol_s) { 48459566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is_perm_r)); 4846d65f70fdSStefano Zampini is_perm_c = is_perm_r; 4847d65f70fdSStefano Zampini } else { 4848d65f70fdSStefano Zampini PetscInt *idxs_c, i; 484928b400f6SJacob Faibussowitsch PetscCheck(idxs_perm_c, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Permutation array not present"); 48509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(csize, &idxs_c)); 4851ad540459SPierre Jolivet for (i = 0; i < csize; i++) idxs_c[idxs_perm_c[i]] = i; 48529566063dSJacob Faibussowitsch PetscCall(PetscFree(idxs_perm_c)); 48539566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, csize, idxs_c, PETSC_OWN_POINTER, &is_perm_c)); 4854d65f70fdSStefano Zampini } 4855d65f70fdSStefano Zampini } else { 48569566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, csize, 0, 1, &is_perm_c)); 4857d65f70fdSStefano Zampini } 48589566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(is_perm_c)); 4859d65f70fdSStefano Zampini 48609566063dSJacob Faibussowitsch PetscCall(MatPermute(work_mat[0], is_perm_r, is_perm_c, &new_mat)); 48619566063dSJacob Faibussowitsch PetscCall(MatDestroy(&work_mat[0])); 4862d65f70fdSStefano Zampini work_mat[0] = new_mat; 48639566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_perm_r)); 48649566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_perm_c)); 4865d65f70fdSStefano Zampini } 4866d65f70fdSStefano Zampini 48679566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)work_mat[0])); 4868d65f70fdSStefano Zampini *B = work_mat[0]; 48699566063dSJacob Faibussowitsch PetscCall(MatDestroyMatrices(1, &work_mat)); 48709566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isrow_s)); 48719566063dSJacob Faibussowitsch PetscCall(ISDestroy(&iscol_s)); 48723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4873d65f70fdSStefano Zampini } 4874d65f70fdSStefano Zampini 4875d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix) 4876d71ae5a4SJacob Faibussowitsch { 4877aa0d41d4SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 48785e8657edSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 4879022d8d2bSstefano_zampini Mat new_mat, lA; 48805e8657edSStefano Zampini IS is_local, is_global; 4881d65f70fdSStefano Zampini PetscInt local_size; 4882b94d7dedSBarry Smith PetscBool isseqaij, issym, isset; 4883aa0d41d4SStefano Zampini 4884aa0d41d4SStefano Zampini PetscFunctionBegin; 48859566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 48869566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A, &local_size, NULL)); 48879566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)matis->A), local_size, 0, 1, &is_local)); 48889566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(matis->rmapping, is_local, &is_global)); 48899566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_local)); 48909566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrixUnsorted(ChangeOfBasisMatrix, is_global, is_global, &new_mat)); 48919566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_global)); 4892906d46d4SStefano Zampini 4893906d46d4SStefano Zampini if (pcbddc->dbg_flag) { 4894906d46d4SStefano Zampini Vec x, x_change; 4895906d46d4SStefano Zampini PetscReal error; 4896906d46d4SStefano Zampini 48979566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(ChangeOfBasisMatrix, &x, &x_change)); 48989566063dSJacob Faibussowitsch PetscCall(VecSetRandom(x, NULL)); 48999566063dSJacob Faibussowitsch PetscCall(MatMult(ChangeOfBasisMatrix, x, x_change)); 49009566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->cctx, x, matis->x, INSERT_VALUES, SCATTER_FORWARD)); 49019566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->cctx, x, matis->x, INSERT_VALUES, SCATTER_FORWARD)); 49029566063dSJacob Faibussowitsch PetscCall(MatMult(new_mat, matis->x, matis->y)); 490388428137SStefano Zampini if (!pcbddc->change_interior) { 490488428137SStefano Zampini const PetscScalar *x, *y, *v; 490588428137SStefano Zampini PetscReal lerror = 0.; 490688428137SStefano Zampini PetscInt i; 490788428137SStefano Zampini 49089566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(matis->x, &x)); 49099566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(matis->y, &y)); 49109566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(matis->counter, &v)); 491188428137SStefano Zampini for (i = 0; i < local_size; i++) 49129371c9d4SSatish Balay if (PetscRealPart(v[i]) < 1.5 && PetscAbsScalar(x[i] - y[i]) > lerror) lerror = PetscAbsScalar(x[i] - y[i]); 49139566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(matis->x, &x)); 49149566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(matis->y, &y)); 49159566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(matis->counter, &v)); 49161c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&lerror, &error, 1, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)pc))); 4917637e8532SStefano Zampini if (error > PETSC_SMALL) { 4918637e8532SStefano Zampini if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) { 491963a3b9bcSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_PLIB, "Error global vs local change on I: %1.6e", (double)error); 4920637e8532SStefano Zampini } else { 492163a3b9bcSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "Error global vs local change on I: %1.6e", (double)error); 4922637e8532SStefano Zampini } 4923637e8532SStefano Zampini } 492488428137SStefano Zampini } 49259566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, matis->y, x, INSERT_VALUES, SCATTER_REVERSE)); 49269566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, matis->y, x, INSERT_VALUES, SCATTER_REVERSE)); 49279566063dSJacob Faibussowitsch PetscCall(VecAXPY(x, -1.0, x_change)); 49289566063dSJacob Faibussowitsch PetscCall(VecNorm(x, NORM_INFINITY, &error)); 4929637e8532SStefano Zampini if (error > PETSC_SMALL) { 4930637e8532SStefano Zampini if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) { 493163a3b9bcSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_PLIB, "Error global vs local change on N: %1.6e", (double)error); 4932637e8532SStefano Zampini } else { 493363a3b9bcSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "Error global vs local change on N: %1.6e", (double)error); 4934637e8532SStefano Zampini } 4935637e8532SStefano Zampini } 49369566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 49379566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x_change)); 4938906d46d4SStefano Zampini } 4939906d46d4SStefano Zampini 4940022d8d2bSstefano_zampini /* lA is present if we are setting up an inner BDDC for a saddle point FETI-DP */ 49419566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lA", (PetscObject *)&lA)); 4942022d8d2bSstefano_zampini 494322d5777bSStefano Zampini /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */ 49449566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQAIJ, &isseqaij)); 494522d5777bSStefano Zampini if (isseqaij) { 49469566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 49479566063dSJacob Faibussowitsch PetscCall(MatPtAP(matis->A, new_mat, MAT_INITIAL_MATRIX, 2.0, &pcbddc->local_mat)); 4948022d8d2bSstefano_zampini if (lA) { 4949022d8d2bSstefano_zampini Mat work; 49509566063dSJacob Faibussowitsch PetscCall(MatPtAP(lA, new_mat, MAT_INITIAL_MATRIX, 2.0, &work)); 49519566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_lA", (PetscObject)work)); 49529566063dSJacob Faibussowitsch PetscCall(MatDestroy(&work)); 4953022d8d2bSstefano_zampini } 4954aa0d41d4SStefano Zampini } else { 4955a00504b5SStefano Zampini Mat work_mat; 49561cf9b237SStefano Zampini 49579566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 49589566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &work_mat)); 49599566063dSJacob Faibussowitsch PetscCall(MatPtAP(work_mat, new_mat, MAT_INITIAL_MATRIX, 2.0, &pcbddc->local_mat)); 49609566063dSJacob Faibussowitsch PetscCall(MatDestroy(&work_mat)); 4961022d8d2bSstefano_zampini if (lA) { 4962022d8d2bSstefano_zampini Mat work; 49639566063dSJacob Faibussowitsch PetscCall(MatConvert(lA, MATSEQAIJ, MAT_INITIAL_MATRIX, &work_mat)); 49649566063dSJacob Faibussowitsch PetscCall(MatPtAP(work_mat, new_mat, MAT_INITIAL_MATRIX, 2.0, &work)); 49659566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_lA", (PetscObject)work)); 49669566063dSJacob Faibussowitsch PetscCall(MatDestroy(&work)); 4967022d8d2bSstefano_zampini } 4968aa0d41d4SStefano Zampini } 4969b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(matis->A, &isset, &issym)); 4970b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(pcbddc->local_mat, MAT_SYMMETRIC, issym)); 49719566063dSJacob Faibussowitsch PetscCall(MatDestroy(&new_mat)); 49723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4973aa0d41d4SStefano Zampini } 4974aa0d41d4SStefano Zampini 4975d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpLocalScatters(PC pc) 4976d71ae5a4SJacob Faibussowitsch { 4977a64d13efSStefano Zampini PC_IS *pcis = (PC_IS *)(pc->data); 4978a64d13efSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 4979d62866d3SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 498053892102SStefano Zampini PetscInt *idx_R_local = NULL; 49813a50541eSStefano Zampini PetscInt n_vertices, i, j, n_R, n_D, n_B; 49823a50541eSStefano Zampini PetscInt vbs, bs; 49836816873aSStefano Zampini PetscBT bitmask = NULL; 4984a64d13efSStefano Zampini 4985a64d13efSStefano Zampini PetscFunctionBegin; 4986b23d619eSStefano Zampini /* 4987b23d619eSStefano Zampini No need to setup local scatters if 4988b23d619eSStefano Zampini - primal space is unchanged 4989b23d619eSStefano Zampini AND 4990b23d619eSStefano Zampini - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains) 4991b23d619eSStefano Zampini AND 4992b23d619eSStefano Zampini - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine 4993b23d619eSStefano Zampini */ 49943ba16761SJacob Faibussowitsch if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) PetscFunctionReturn(PETSC_SUCCESS); 4995f4ddd8eeSStefano Zampini /* destroy old objects */ 49969566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->is_R_local)); 49979566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->R_to_B)); 49989566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->R_to_D)); 4999a64d13efSStefano Zampini /* Set Non-overlapping dimensions */ 5000b371cd4fSStefano Zampini n_B = pcis->n_B; 5001b371cd4fSStefano Zampini n_D = pcis->n - n_B; 5002b371cd4fSStefano Zampini n_vertices = pcbddc->n_vertices; 50033a50541eSStefano Zampini 5004a64d13efSStefano Zampini /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */ 50056816873aSStefano Zampini 500653892102SStefano Zampini /* create auxiliary bitmask and allocate workspace */ 5007b334f244SStefano Zampini if (!sub_schurs || !sub_schurs->reuse_solver) { 50089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n - n_vertices, &idx_R_local)); 50099566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(pcis->n, &bitmask)); 501048a46eb9SPierre Jolivet for (i = 0; i < n_vertices; i++) PetscCall(PetscBTSet(bitmask, pcbddc->local_primal_ref_node[i])); 5011a64d13efSStefano Zampini 5012a64d13efSStefano Zampini for (i = 0, n_R = 0; i < pcis->n; i++) { 5013ad540459SPierre Jolivet if (!PetscBTLookup(bitmask, i)) idx_R_local[n_R++] = i; 5014a64d13efSStefano Zampini } 5015df4d28bfSStefano Zampini } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */ 5016df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 50176816873aSStefano Zampini 50189566063dSJacob Faibussowitsch PetscCall(ISGetIndices(reuse_solver->is_R, (const PetscInt **)&idx_R_local)); 50199566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(reuse_solver->is_R, &n_R)); 50206816873aSStefano Zampini } 50213a50541eSStefano Zampini 50223a50541eSStefano Zampini /* Block code */ 50233a50541eSStefano Zampini vbs = 1; 50249566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(pcbddc->local_mat, &bs)); 50253a50541eSStefano Zampini if (bs > 1 && !(n_vertices % bs)) { 50263a50541eSStefano Zampini PetscBool is_blocked = PETSC_TRUE; 50273a50541eSStefano Zampini PetscInt *vary; 5028b334f244SStefano Zampini if (!sub_schurs || !sub_schurs->reuse_solver) { 50299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n / bs, &vary)); 50309566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(vary, pcis->n / bs)); 5031d3df7717SStefano Zampini /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */ 5032d3df7717SStefano 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 */ 50330e6343abSStefano Zampini for (i = 0; i < n_vertices; i++) vary[pcbddc->local_primal_ref_node[i] / bs]++; 5034d3df7717SStefano Zampini for (i = 0; i < pcis->n / bs; i++) { 50353a50541eSStefano Zampini if (vary[i] != 0 && vary[i] != bs) { 50363a50541eSStefano Zampini is_blocked = PETSC_FALSE; 50373a50541eSStefano Zampini break; 50383a50541eSStefano Zampini } 50393a50541eSStefano Zampini } 50409566063dSJacob Faibussowitsch PetscCall(PetscFree(vary)); 5041d3df7717SStefano Zampini } else { 5042d3df7717SStefano Zampini /* Verify directly the R set */ 5043d3df7717SStefano Zampini for (i = 0; i < n_R / bs; i++) { 5044d3df7717SStefano Zampini PetscInt j, node = idx_R_local[bs * i]; 5045d3df7717SStefano Zampini for (j = 1; j < bs; j++) { 5046d3df7717SStefano Zampini if (node != idx_R_local[bs * i + j] - j) { 5047d3df7717SStefano Zampini is_blocked = PETSC_FALSE; 5048d3df7717SStefano Zampini break; 5049d3df7717SStefano Zampini } 5050d3df7717SStefano Zampini } 5051d3df7717SStefano Zampini } 5052d3df7717SStefano Zampini } 50533a50541eSStefano Zampini if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */ 50543a50541eSStefano Zampini vbs = bs; 5055ad540459SPierre Jolivet for (i = 0; i < n_R / vbs; i++) idx_R_local[i] = idx_R_local[vbs * i] / vbs; 50563a50541eSStefano Zampini } 50573a50541eSStefano Zampini } 50589566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF, vbs, n_R / vbs, idx_R_local, PETSC_COPY_VALUES, &pcbddc->is_R_local)); 5059b334f244SStefano Zampini if (sub_schurs && sub_schurs->reuse_solver) { 5060df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 506153892102SStefano Zampini 50629566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(reuse_solver->is_R, (const PetscInt **)&idx_R_local)); 50639566063dSJacob Faibussowitsch PetscCall(ISDestroy(&reuse_solver->is_R)); 50649566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->is_R_local)); 5065df4d28bfSStefano Zampini reuse_solver->is_R = pcbddc->is_R_local; 506653892102SStefano Zampini } else { 50679566063dSJacob Faibussowitsch PetscCall(PetscFree(idx_R_local)); 506853892102SStefano Zampini } 5069a64d13efSStefano Zampini 5070a64d13efSStefano Zampini /* print some info if requested */ 5071a64d13efSStefano Zampini if (pcbddc->dbg_flag) { 50729566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 50739566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 50749566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 50759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d local dimensions\n", PetscGlobalRank)); 507663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "local_size = %" PetscInt_FMT ", dirichlet_size = %" PetscInt_FMT ", boundary_size = %" PetscInt_FMT "\n", pcis->n, n_D, n_B)); 50779371c9d4SSatish Balay PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "r_size = %" PetscInt_FMT ", v_size = %" PetscInt_FMT ", constraints = %" PetscInt_FMT ", local_primal_size = %" PetscInt_FMT "\n", n_R, n_vertices, 50789371c9d4SSatish Balay pcbddc->local_primal_size - n_vertices - pcbddc->benign_n, pcbddc->local_primal_size)); 50799566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 5080a64d13efSStefano Zampini } 5081a64d13efSStefano Zampini 5082a64d13efSStefano Zampini /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */ 5083b334f244SStefano Zampini if (!sub_schurs || !sub_schurs->reuse_solver) { 50846816873aSStefano Zampini IS is_aux1, is_aux2; 50856816873aSStefano Zampini PetscInt *aux_array1, *aux_array2, *is_indices, *idx_R_local; 50866816873aSStefano Zampini 50879566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->is_R_local, (const PetscInt **)&idx_R_local)); 50889566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n_B - n_vertices, &aux_array1)); 50899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n_B - n_vertices, &aux_array2)); 50909566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_I_local, (const PetscInt **)&is_indices)); 509148a46eb9SPierre Jolivet for (i = 0; i < n_D; i++) PetscCall(PetscBTSet(bitmask, is_indices[i])); 50929566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_I_local, (const PetscInt **)&is_indices)); 5093a64d13efSStefano Zampini for (i = 0, j = 0; i < n_R; i++) { 5094ad540459SPierre Jolivet if (!PetscBTLookup(bitmask, idx_R_local[i])) aux_array1[j++] = i; 5095a64d13efSStefano Zampini } 50969566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, aux_array1, PETSC_OWN_POINTER, &is_aux1)); 50979566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_B_local, (const PetscInt **)&is_indices)); 5098a64d13efSStefano Zampini for (i = 0, j = 0; i < n_B; i++) { 5099ad540459SPierre Jolivet if (!PetscBTLookup(bitmask, is_indices[i])) aux_array2[j++] = i; 5100a64d13efSStefano Zampini } 51019566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_B_local, (const PetscInt **)&is_indices)); 51029566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, aux_array2, PETSC_OWN_POINTER, &is_aux2)); 51039566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(pcbddc->vec1_R, is_aux1, pcis->vec1_B, is_aux2, &pcbddc->R_to_B)); 51049566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_aux1)); 51059566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_aux2)); 5106a64d13efSStefano Zampini 51078eeda7d8SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 51089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_D, &aux_array1)); 5109a64d13efSStefano Zampini for (i = 0, j = 0; i < n_R; i++) { 5110ad540459SPierre Jolivet if (PetscBTLookup(bitmask, idx_R_local[i])) aux_array1[j++] = i; 5111a64d13efSStefano Zampini } 51129566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, aux_array1, PETSC_OWN_POINTER, &is_aux1)); 51139566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(pcbddc->vec1_R, is_aux1, pcis->vec1_D, (IS)0, &pcbddc->R_to_D)); 51149566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_aux1)); 5115a64d13efSStefano Zampini } 51169566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&bitmask)); 51179566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->is_R_local, (const PetscInt **)&idx_R_local)); 5118d62866d3SStefano Zampini } else { 5119df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 51206816873aSStefano Zampini IS tis; 51216816873aSStefano Zampini PetscInt schur_size; 51226816873aSStefano Zampini 51239566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(reuse_solver->is_B, &schur_size)); 51249566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, schur_size, n_D, 1, &tis)); 51259566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(pcbddc->vec1_R, tis, pcis->vec1_B, reuse_solver->is_B, &pcbddc->R_to_B)); 51269566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tis)); 51276816873aSStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 51289566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, n_D, 0, 1, &tis)); 51299566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(pcbddc->vec1_R, tis, pcis->vec1_D, (IS)0, &pcbddc->R_to_D)); 51309566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tis)); 5131d62866d3SStefano Zampini } 5132d62866d3SStefano Zampini } 51333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5134a64d13efSStefano Zampini } 5135a64d13efSStefano Zampini 5136d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatNullSpacePropagateAny_Private(Mat A, IS is, Mat B) 5137d71ae5a4SJacob Faibussowitsch { 513892cccca0SStefano Zampini MatNullSpace NullSpace; 513992cccca0SStefano Zampini Mat dmat; 514092cccca0SStefano Zampini const Vec *nullvecs; 514192cccca0SStefano Zampini Vec v, v2, *nullvecs2; 51426d9e27e4SStefano Zampini VecScatter sct = NULL; 5143eb06acf8SStefano Zampini PetscContainer c; 5144eb06acf8SStefano Zampini PetscScalar *ddata; 5145295df10fSStefano Zampini PetscInt k, nnsp_size, bsiz, bsiz2, n, N, bs; 514692cccca0SStefano Zampini PetscBool nnsp_has_cnst; 514792cccca0SStefano Zampini 514892cccca0SStefano Zampini PetscFunctionBegin; 51496d9e27e4SStefano Zampini if (!is && !B) { /* MATIS */ 51506d9e27e4SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 51516d9e27e4SStefano Zampini 515248a46eb9SPierre Jolivet if (!B) PetscCall(MatISGetLocalMat(A, &B)); 51536d9e27e4SStefano Zampini sct = matis->cctx; 51549566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)sct)); 51556d9e27e4SStefano Zampini } else { 51569566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(B, &NullSpace)); 515748a46eb9SPierre Jolivet if (!NullSpace) PetscCall(MatGetNearNullSpace(B, &NullSpace)); 51583ba16761SJacob Faibussowitsch if (NullSpace) PetscFunctionReturn(PETSC_SUCCESS); 51596d9e27e4SStefano Zampini } 51609566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(A, &NullSpace)); 516148a46eb9SPierre Jolivet if (!NullSpace) PetscCall(MatGetNearNullSpace(A, &NullSpace)); 51623ba16761SJacob Faibussowitsch if (!NullSpace) PetscFunctionReturn(PETSC_SUCCESS); 51636d9e27e4SStefano Zampini 51649566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, &v, NULL)); 51659566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(B, &v2, NULL)); 516648a46eb9SPierre Jolivet if (!sct) PetscCall(VecScatterCreate(v, is, v2, NULL, &sct)); 51679566063dSJacob Faibussowitsch PetscCall(MatNullSpaceGetVecs(NullSpace, &nnsp_has_cnst, &nnsp_size, (const Vec **)&nullvecs)); 5168295df10fSStefano Zampini bsiz = bsiz2 = nnsp_size + !!nnsp_has_cnst; 51699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bsiz, &nullvecs2)); 51709566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(v2, &bs)); 51719566063dSJacob Faibussowitsch PetscCall(VecGetSize(v2, &N)); 51729566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v2, &n)); 51739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n * bsiz, &ddata)); 517492cccca0SStefano Zampini for (k = 0; k < nnsp_size; k++) { 51759566063dSJacob Faibussowitsch PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)B), bs, n, N, ddata + n * k, &nullvecs2[k])); 51769566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sct, nullvecs[k], nullvecs2[k], INSERT_VALUES, SCATTER_FORWARD)); 51779566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sct, nullvecs[k], nullvecs2[k], INSERT_VALUES, SCATTER_FORWARD)); 517892cccca0SStefano Zampini } 517992cccca0SStefano Zampini if (nnsp_has_cnst) { 51809566063dSJacob Faibussowitsch PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)B), bs, n, N, ddata + n * nnsp_size, &nullvecs2[nnsp_size])); 51819566063dSJacob Faibussowitsch PetscCall(VecSet(nullvecs2[nnsp_size], 1.0)); 518292cccca0SStefano Zampini } 51839566063dSJacob Faibussowitsch PetscCall(PCBDDCOrthonormalizeVecs(&bsiz2, nullvecs2)); 51849566063dSJacob Faibussowitsch PetscCall(MatNullSpaceCreate(PetscObjectComm((PetscObject)B), PETSC_FALSE, bsiz2, nullvecs2, &NullSpace)); 5185295df10fSStefano Zampini 51869566063dSJacob Faibussowitsch PetscCall(MatCreateDense(PetscObjectComm((PetscObject)B), n, PETSC_DECIDE, N, bsiz2, ddata, &dmat)); 51879566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &c)); 51889566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(c, ddata)); 51899566063dSJacob Faibussowitsch PetscCall(PetscContainerSetUserDestroy(c, PetscContainerUserDestroyDefault)); 51909566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dmat, "_PBDDC_Null_dmat_arr", (PetscObject)c)); 51919566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&c)); 51929566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)NullSpace, "_PBDDC_Null_dmat", (PetscObject)dmat)); 51939566063dSJacob Faibussowitsch PetscCall(MatDestroy(&dmat)); 5194eb06acf8SStefano Zampini 519548a46eb9SPierre Jolivet for (k = 0; k < bsiz; k++) PetscCall(VecDestroy(&nullvecs2[k])); 51969566063dSJacob Faibussowitsch PetscCall(PetscFree(nullvecs2)); 51979566063dSJacob Faibussowitsch PetscCall(MatSetNearNullSpace(B, NullSpace)); 51989566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&NullSpace)); 51999566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 52009566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v2)); 52019566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sct)); 52023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 520392cccca0SStefano Zampini } 5204304d26faSStefano Zampini 5205d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann) 5206d71ae5a4SJacob Faibussowitsch { 5207304d26faSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 5208304d26faSStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 5209304d26faSStefano Zampini PC pc_temp; 5210304d26faSStefano Zampini Mat A_RR; 521192cccca0SStefano Zampini MatNullSpace nnsp; 5212f4ddd8eeSStefano Zampini MatReuse reuse; 5213304d26faSStefano Zampini PetscScalar m_one = -1.0; 5214304d26faSStefano Zampini PetscReal value; 521504708bb6SStefano Zampini PetscInt n_D, n_R; 5216b94d7dedSBarry Smith PetscBool issbaij, opts, isset, issym; 52170a545947SLisandro Dalcin void (*f)(void) = NULL; 5218312be037SStefano Zampini char dir_prefix[256], neu_prefix[256], str_level[16]; 5219e604994aSStefano Zampini size_t len; 5220304d26faSStefano Zampini 5221304d26faSStefano Zampini PetscFunctionBegin; 52229566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_LocalSolvers[pcbddc->current_level], pc, 0, 0, 0)); 52236d9e27e4SStefano Zampini /* approximate solver, propagate NearNullSpace if needed */ 52246d9e27e4SStefano Zampini if (!pc->setupcalled && (pcbddc->NullSpace_corr[0] || pcbddc->NullSpace_corr[2])) { 52256d9e27e4SStefano Zampini MatNullSpace gnnsp1, gnnsp2; 52266d9e27e4SStefano Zampini PetscBool lhas, ghas; 52276d9e27e4SStefano Zampini 52289566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pcbddc->local_mat, &nnsp)); 52299566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pc->pmat, &gnnsp1)); 52309566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(pc->pmat, &gnnsp2)); 52316d9e27e4SStefano Zampini lhas = nnsp ? PETSC_TRUE : PETSC_FALSE; 52321c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&lhas, &ghas, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 523348a46eb9SPierre Jolivet if (!ghas && (gnnsp1 || gnnsp2)) PetscCall(MatNullSpacePropagateAny_Private(pc->pmat, NULL, NULL)); 52346d9e27e4SStefano Zampini } 52356d9e27e4SStefano Zampini 5236e604994aSStefano Zampini /* compute prefixes */ 5237c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(dir_prefix, "", sizeof(dir_prefix))); 5238c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(neu_prefix, "", sizeof(neu_prefix))); 5239e604994aSStefano Zampini if (!pcbddc->current_level) { 52409566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(dir_prefix, ((PetscObject)pc)->prefix, sizeof(dir_prefix))); 52419566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(neu_prefix, ((PetscObject)pc)->prefix, sizeof(neu_prefix))); 52429566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(dir_prefix, "pc_bddc_dirichlet_", sizeof(dir_prefix))); 52439566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(neu_prefix, "pc_bddc_neumann_", sizeof(neu_prefix))); 5244e604994aSStefano Zampini } else { 52459566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(str_level, sizeof(str_level), "l%d_", (int)(pcbddc->current_level))); 52469566063dSJacob Faibussowitsch PetscCall(PetscStrlen(((PetscObject)pc)->prefix, &len)); 5247e604994aSStefano Zampini len -= 15; /* remove "pc_bddc_coarse_" */ 5248312be037SStefano Zampini if (pcbddc->current_level > 1) len -= 3; /* remove "lX_" with X level number */ 5249312be037SStefano Zampini if (pcbddc->current_level > 10) len -= 1; /* remove another char from level number */ 5250a126751eSBarry Smith /* Nonstandard use of PetscStrncpy() to only copy a portion of the input string */ 52519566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(dir_prefix, ((PetscObject)pc)->prefix, len + 1)); 52529566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(neu_prefix, ((PetscObject)pc)->prefix, len + 1)); 52539566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(dir_prefix, "pc_bddc_dirichlet_", sizeof(dir_prefix))); 52549566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(neu_prefix, "pc_bddc_neumann_", sizeof(neu_prefix))); 52559566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(dir_prefix, str_level, sizeof(dir_prefix))); 52569566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(neu_prefix, str_level, sizeof(neu_prefix))); 5257e604994aSStefano Zampini } 5258e604994aSStefano Zampini 5259304d26faSStefano Zampini /* DIRICHLET PROBLEM */ 5260684f6988SStefano Zampini if (dirichlet) { 5261d5574798SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 5262450f8f5eSStefano Zampini if (pcbddc->benign_n && !pcbddc->benign_change_explicit) { 52637827d75bSBarry Smith PetscCheck(sub_schurs && sub_schurs->reuse_solver, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not yet implemented"); 5264450f8f5eSStefano Zampini if (pcbddc->dbg_flag) { 5265a3df083aSStefano Zampini Mat A_IIn; 5266a3df083aSStefano Zampini 52679566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignProject(pc, pcis->is_I_local, pcis->is_I_local, &A_IIn)); 52689566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_II)); 5269a3df083aSStefano Zampini pcis->A_II = A_IIn; 5270a3df083aSStefano Zampini } 5271450f8f5eSStefano Zampini } 5272b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(pcbddc->local_mat, &isset, &issym)); 5273b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(pcis->A_II, MAT_SYMMETRIC, issym)); 5274b94d7dedSBarry Smith 5275ac78edfcSStefano Zampini /* Matrix for Dirichlet problem is pcis->A_II */ 5276964fefecSStefano Zampini n_D = pcis->n - pcis->n_B; 527792cccca0SStefano Zampini opts = PETSC_FALSE; 5278304d26faSStefano Zampini if (!pcbddc->ksp_D) { /* create object if not yet build */ 527992cccca0SStefano Zampini opts = PETSC_TRUE; 52809566063dSJacob Faibussowitsch PetscCall(KSPCreate(PETSC_COMM_SELF, &pcbddc->ksp_D)); 52819566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D, (PetscObject)pc, 1)); 5282304d26faSStefano Zampini /* default */ 52839566063dSJacob Faibussowitsch PetscCall(KSPSetType(pcbddc->ksp_D, KSPPREONLY)); 52849566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(pcbddc->ksp_D, dir_prefix)); 52859566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pcis->pA_II, MATSEQSBAIJ, &issbaij)); 52869566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_D, &pc_temp)); 52879577ea80SStefano Zampini if (issbaij) { 52889566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCCHOLESKY)); 52899577ea80SStefano Zampini } else { 52909566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCLU)); 52919577ea80SStefano Zampini } 52929566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(pcbddc->ksp_D, pc->erroriffailure)); 529392cccca0SStefano Zampini } 52949566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(pcis->pA_II, ((PetscObject)pcbddc->ksp_D)->prefix)); 52959566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(pcbddc->ksp_D, pcis->A_II, pcis->pA_II)); 5296304d26faSStefano Zampini /* Allow user's customization */ 52971baa6e33SBarry Smith if (opts) PetscCall(KSPSetFromOptions(pcbddc->ksp_D)); 52989566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pcis->pA_II, &nnsp)); 52996d9e27e4SStefano Zampini if (pcbddc->NullSpace_corr[0] && !nnsp) { /* approximate solver, propagate NearNullSpace */ 53009566063dSJacob Faibussowitsch PetscCall(MatNullSpacePropagateAny_Private(pcbddc->local_mat, pcis->is_I_local, pcis->pA_II)); 530192cccca0SStefano Zampini } 53029566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pcis->pA_II, &nnsp)); 53039566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_D, &pc_temp)); 53049566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)pc_temp, "PCSetCoordinates_C", &f)); 530592cccca0SStefano Zampini if (f && pcbddc->mat_graph->cloc && !nnsp) { 5306cd18cfedSStefano Zampini PetscReal *coords = pcbddc->mat_graph->coords, *scoords; 5307cd18cfedSStefano Zampini const PetscInt *idxs; 5308cd18cfedSStefano Zampini PetscInt cdim = pcbddc->mat_graph->cdim, nl, i, d; 5309cd18cfedSStefano Zampini 53109566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcis->is_I_local, &nl)); 53119566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_I_local, &idxs)); 53129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl * cdim, &scoords)); 5313cd18cfedSStefano Zampini for (i = 0; i < nl; i++) { 5314ad540459SPierre Jolivet for (d = 0; d < cdim; d++) scoords[i * cdim + d] = coords[idxs[i] * cdim + d]; 5315cd18cfedSStefano Zampini } 53169566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_I_local, &idxs)); 53179566063dSJacob Faibussowitsch PetscCall(PCSetCoordinates(pc_temp, cdim, nl, scoords)); 53189566063dSJacob Faibussowitsch PetscCall(PetscFree(scoords)); 5319cd18cfedSStefano Zampini } 5320b334f244SStefano Zampini if (sub_schurs && sub_schurs->reuse_solver) { 5321df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 5322d62866d3SStefano Zampini 53239566063dSJacob Faibussowitsch PetscCall(KSPSetPC(pcbddc->ksp_D, reuse_solver->interior_solver)); 5324d5574798SStefano Zampini } 532592cccca0SStefano Zampini 5326304d26faSStefano Zampini /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */ 5327304d26faSStefano Zampini if (!n_D) { 53289566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_D, &pc_temp)); 53299566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCNONE)); 5330304d26faSStefano Zampini } 53319566063dSJacob Faibussowitsch PetscCall(KSPSetUp(pcbddc->ksp_D)); 5332304d26faSStefano Zampini /* set ksp_D into pcis data */ 53339566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->ksp_D)); 53349566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&pcis->ksp_D)); 5335304d26faSStefano Zampini pcis->ksp_D = pcbddc->ksp_D; 5336684f6988SStefano Zampini } 5337304d26faSStefano Zampini 5338304d26faSStefano Zampini /* NEUMANN PROBLEM */ 53390a545947SLisandro Dalcin A_RR = NULL; 5340684f6988SStefano Zampini if (neumann) { 5341d62866d3SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 534204708bb6SStefano Zampini PetscInt ibs, mbs; 5343b94d7dedSBarry Smith PetscBool issbaij, reuse_neumann_solver, isset, issym; 534404708bb6SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 53450aa714b2SStefano Zampini 53460aa714b2SStefano Zampini reuse_neumann_solver = PETSC_FALSE; 53470aa714b2SStefano Zampini if (sub_schurs && sub_schurs->reuse_solver) { 53480aa714b2SStefano Zampini IS iP; 53490aa714b2SStefano Zampini 53500aa714b2SStefano Zampini reuse_neumann_solver = PETSC_TRUE; 53519566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)sub_schurs->A, "__KSPFETIDP_iP", (PetscObject *)&iP)); 53520aa714b2SStefano Zampini if (iP) reuse_neumann_solver = PETSC_FALSE; 53530aa714b2SStefano Zampini } 5354f4ddd8eeSStefano Zampini /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */ 53559566063dSJacob Faibussowitsch PetscCall(ISGetSize(pcbddc->is_R_local, &n_R)); 5356f4ddd8eeSStefano Zampini if (pcbddc->ksp_R) { /* already created ksp */ 5357f4ddd8eeSStefano Zampini PetscInt nn_R; 53589566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(pcbddc->ksp_R, NULL, &A_RR)); 53599566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A_RR)); 53609566063dSJacob Faibussowitsch PetscCall(MatGetSize(A_RR, &nn_R, NULL)); 5361f4ddd8eeSStefano Zampini if (nn_R != n_R) { /* old ksp is not reusable, so reset it */ 53629566063dSJacob Faibussowitsch PetscCall(KSPReset(pcbddc->ksp_R)); 53639566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 5364f4ddd8eeSStefano Zampini reuse = MAT_INITIAL_MATRIX; 5365f4ddd8eeSStefano Zampini } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */ 5366727cdba6SStefano Zampini if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */ 53679566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 5368f4ddd8eeSStefano Zampini reuse = MAT_INITIAL_MATRIX; 5369f4ddd8eeSStefano Zampini } else { /* safe to reuse the matrix */ 5370f4ddd8eeSStefano Zampini reuse = MAT_REUSE_MATRIX; 5371f4ddd8eeSStefano Zampini } 5372f4ddd8eeSStefano Zampini } 5373f4ddd8eeSStefano Zampini /* last check */ 5374d1e9a80fSBarry Smith if (pc->flag == DIFFERENT_NONZERO_PATTERN) { 53759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 5376f4ddd8eeSStefano Zampini reuse = MAT_INITIAL_MATRIX; 5377f4ddd8eeSStefano Zampini } 5378f4ddd8eeSStefano Zampini } else { /* first time, so we need to create the matrix */ 5379f4ddd8eeSStefano Zampini reuse = MAT_INITIAL_MATRIX; 5380f4ddd8eeSStefano Zampini } 5381365a3a41SStefano Zampini /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection 5382365a3a41SStefano Zampini TODO: Get Rid of these conversions */ 53839566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(pcbddc->local_mat, &mbs)); 53849566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(pcbddc->is_R_local, &ibs)); 53859566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pcbddc->local_mat, MATSEQSBAIJ, &issbaij)); 538604708bb6SStefano Zampini if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */ 538704708bb6SStefano Zampini if (matis->A == pcbddc->local_mat) { 53889566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 53899566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &pcbddc->local_mat)); 5390af732b37SStefano Zampini } else { 53919566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->local_mat, MATSEQAIJ, MAT_INPLACE_MATRIX, &pcbddc->local_mat)); 53926816873aSStefano Zampini } 539304708bb6SStefano Zampini } else if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */ 539404708bb6SStefano Zampini if (matis->A == pcbddc->local_mat) { 53959566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 53969566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, mbs > 1 ? MATSEQBAIJ : MATSEQAIJ, MAT_INITIAL_MATRIX, &pcbddc->local_mat)); 539704708bb6SStefano Zampini } else { 53989566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->local_mat, mbs > 1 ? MATSEQBAIJ : MATSEQAIJ, MAT_INPLACE_MATRIX, &pcbddc->local_mat)); 539904708bb6SStefano Zampini } 540004708bb6SStefano Zampini } 5401a00504b5SStefano Zampini /* extract A_RR */ 54020aa714b2SStefano Zampini if (reuse_neumann_solver) { 5403a00504b5SStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 5404a00504b5SStefano Zampini 5405a00504b5SStefano Zampini if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */ 54069566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 5407a00504b5SStefano Zampini if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */ 54089566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignProject(pc, pcbddc->is_R_local, pcbddc->is_R_local, &A_RR)); 540916e386b8SStefano Zampini } else { 54109566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcbddc->is_R_local, pcbddc->is_R_local, MAT_INITIAL_MATRIX, &A_RR)); 5411a00504b5SStefano Zampini } 5412a00504b5SStefano Zampini } else { 54139566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 54149566063dSJacob Faibussowitsch PetscCall(PCGetOperators(reuse_solver->correction_solver, &A_RR, NULL)); 54159566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A_RR)); 5416a00504b5SStefano Zampini } 5417a00504b5SStefano Zampini } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */ 54189566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcbddc->is_R_local, pcbddc->is_R_local, reuse, &A_RR)); 541916e386b8SStefano Zampini } 5420b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(pcbddc->local_mat, &isset, &issym)); 5421b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(A_RR, MAT_SYMMETRIC, issym)); 542292cccca0SStefano Zampini opts = PETSC_FALSE; 5423f4ddd8eeSStefano Zampini if (!pcbddc->ksp_R) { /* create object if not present */ 542492cccca0SStefano Zampini opts = PETSC_TRUE; 54259566063dSJacob Faibussowitsch PetscCall(KSPCreate(PETSC_COMM_SELF, &pcbddc->ksp_R)); 54269566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R, (PetscObject)pc, 1)); 5427304d26faSStefano Zampini /* default */ 54289566063dSJacob Faibussowitsch PetscCall(KSPSetType(pcbddc->ksp_R, KSPPREONLY)); 54299566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(pcbddc->ksp_R, neu_prefix)); 54309566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_R, &pc_temp)); 54319566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A_RR, MATSEQSBAIJ, &issbaij)); 54329577ea80SStefano Zampini if (issbaij) { 54339566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCCHOLESKY)); 54349577ea80SStefano Zampini } else { 54359566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCLU)); 54369577ea80SStefano Zampini } 54379566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(pcbddc->ksp_R, pc->erroriffailure)); 543892cccca0SStefano Zampini } 54399566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(pcbddc->ksp_R, A_RR, A_RR)); 54409566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(A_RR, ((PetscObject)pcbddc->ksp_R)->prefix)); 544192cccca0SStefano Zampini if (opts) { /* Allow user's customization once */ 54429566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(pcbddc->ksp_R)); 544392cccca0SStefano Zampini } 54449566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(A_RR, &nnsp)); 54456d9e27e4SStefano Zampini if (pcbddc->NullSpace_corr[2] && !nnsp) { /* approximate solver, propagate NearNullSpace */ 54469566063dSJacob Faibussowitsch PetscCall(MatNullSpacePropagateAny_Private(pcbddc->local_mat, pcbddc->is_R_local, A_RR)); 544792cccca0SStefano Zampini } 54489566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(A_RR, &nnsp)); 54499566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_R, &pc_temp)); 54509566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)pc_temp, "PCSetCoordinates_C", &f)); 545192cccca0SStefano Zampini if (f && pcbddc->mat_graph->cloc && !nnsp) { 5452cd18cfedSStefano Zampini PetscReal *coords = pcbddc->mat_graph->coords, *scoords; 5453cd18cfedSStefano Zampini const PetscInt *idxs; 5454cd18cfedSStefano Zampini PetscInt cdim = pcbddc->mat_graph->cdim, nl, i, d; 5455cd18cfedSStefano Zampini 54569566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->is_R_local, &nl)); 54579566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->is_R_local, &idxs)); 54589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl * cdim, &scoords)); 5459cd18cfedSStefano Zampini for (i = 0; i < nl; i++) { 5460ad540459SPierre Jolivet for (d = 0; d < cdim; d++) scoords[i * cdim + d] = coords[idxs[i] * cdim + d]; 5461cd18cfedSStefano Zampini } 54629566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->is_R_local, &idxs)); 54639566063dSJacob Faibussowitsch PetscCall(PCSetCoordinates(pc_temp, cdim, nl, scoords)); 54649566063dSJacob Faibussowitsch PetscCall(PetscFree(scoords)); 5465cd18cfedSStefano Zampini } 546692cccca0SStefano Zampini 5467304d26faSStefano Zampini /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */ 5468304d26faSStefano Zampini if (!n_R) { 54699566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_R, &pc_temp)); 54709566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCNONE)); 5471304d26faSStefano Zampini } 5472df4d28bfSStefano Zampini /* Reuse solver if it is present */ 54730aa714b2SStefano Zampini if (reuse_neumann_solver) { 5474df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 5475d62866d3SStefano Zampini 54769566063dSJacob Faibussowitsch PetscCall(KSPSetPC(pcbddc->ksp_R, reuse_solver->correction_solver)); 5477d62866d3SStefano Zampini } 54789566063dSJacob Faibussowitsch PetscCall(KSPSetUp(pcbddc->ksp_R)); 5479684f6988SStefano Zampini } 5480304d26faSStefano Zampini 5481684f6988SStefano Zampini if (pcbddc->dbg_flag) { 54829566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 54839566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 54849566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 5485684f6988SStefano Zampini } 54869566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_LocalSolvers[pcbddc->current_level], pc, 0, 0, 0)); 5487c7017625SStefano Zampini 5488c7017625SStefano Zampini /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */ 548948a46eb9SPierre Jolivet if (pcbddc->NullSpace_corr[0]) PetscCall(PCBDDCSetUseExactDirichlet(pc, PETSC_FALSE)); 549048a46eb9SPierre Jolivet if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) PetscCall(PCBDDCNullSpaceAssembleCorrection(pc, PETSC_TRUE, pcbddc->NullSpace_corr[1])); 549148a46eb9SPierre Jolivet if (neumann && pcbddc->NullSpace_corr[2]) PetscCall(PCBDDCNullSpaceAssembleCorrection(pc, PETSC_FALSE, pcbddc->NullSpace_corr[3])); 5492c7017625SStefano Zampini /* check Dirichlet and Neumann solvers */ 5493c7017625SStefano Zampini if (pcbddc->dbg_flag) { 5494684f6988SStefano Zampini if (dirichlet) { /* Dirichlet */ 54959566063dSJacob Faibussowitsch PetscCall(VecSetRandom(pcis->vec1_D, NULL)); 54969566063dSJacob Faibussowitsch PetscCall(MatMult(pcis->A_II, pcis->vec1_D, pcis->vec2_D)); 54979566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec2_D, pcis->vec2_D)); 54989566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D)); 54999566063dSJacob Faibussowitsch PetscCall(VecAXPY(pcis->vec1_D, m_one, pcis->vec2_D)); 55009566063dSJacob Faibussowitsch PetscCall(VecNorm(pcis->vec1_D, NORM_INFINITY, &value)); 550163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d infinity error for Dirichlet solve (%s) = % 1.14e \n", PetscGlobalRank, ((PetscObject)(pcbddc->ksp_D))->prefix, (double)value)); 55029566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 5503304d26faSStefano Zampini } 5504684f6988SStefano Zampini if (neumann) { /* Neumann */ 55059566063dSJacob Faibussowitsch PetscCall(VecSetRandom(pcbddc->vec1_R, NULL)); 55069566063dSJacob Faibussowitsch PetscCall(MatMult(A_RR, pcbddc->vec1_R, pcbddc->vec2_R)); 55079566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_R, pcbddc->vec2_R, pcbddc->vec2_R)); 55089566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec2_R)); 55099566063dSJacob Faibussowitsch PetscCall(VecAXPY(pcbddc->vec1_R, m_one, pcbddc->vec2_R)); 55109566063dSJacob Faibussowitsch PetscCall(VecNorm(pcbddc->vec1_R, NORM_INFINITY, &value)); 551163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d infinity error for Neumann solve (%s) = % 1.14e\n", PetscGlobalRank, ((PetscObject)(pcbddc->ksp_R))->prefix, (double)value)); 55129566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 5513304d26faSStefano Zampini } 5514684f6988SStefano Zampini } 55155cbda25cSStefano Zampini /* free Neumann problem's matrix */ 55169566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 55173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5518304d26faSStefano Zampini } 5519304d26faSStefano Zampini 5520d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose) 5521d71ae5a4SJacob Faibussowitsch { 5522674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)(pc->data); 5523be83ff47SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 5524b334f244SStefano Zampini PetscBool reuse_solver = sub_schurs ? (sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE) : PETSC_FALSE; 5525674ae819SStefano Zampini 5526674ae819SStefano Zampini PetscFunctionBegin; 552748a46eb9SPierre Jolivet if (!reuse_solver) PetscCall(VecSet(pcbddc->vec1_R, 0.)); 552880677318SStefano Zampini if (!pcbddc->switch_static) { 552980677318SStefano Zampini if (applytranspose && pcbddc->local_auxmat1) { 55309566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->local_auxmat2, inout_B, pcbddc->vec1_C)); 55319566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(pcbddc->local_auxmat1, pcbddc->vec1_C, inout_B, inout_B)); 553220c7b377SStefano Zampini } 5533b334f244SStefano Zampini if (!reuse_solver) { 55349566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 55359566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 553620c7b377SStefano Zampini } else { 5537df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 5538be83ff47SStefano Zampini 55399566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(reuse_solver->correction_scatter_B, inout_B, reuse_solver->rhs_B, INSERT_VALUES, SCATTER_FORWARD)); 55409566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(reuse_solver->correction_scatter_B, inout_B, reuse_solver->rhs_B, INSERT_VALUES, SCATTER_FORWARD)); 554120c7b377SStefano Zampini } 5542be83ff47SStefano Zampini } else { 55439566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 55449566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 55459566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_D, inout_D, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 55469566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_D, inout_D, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 554780677318SStefano Zampini if (applytranspose && pcbddc->local_auxmat1) { 55489566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->local_auxmat2, pcbddc->vec1_R, pcbddc->vec1_C)); 55499566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(pcbddc->local_auxmat1, pcbddc->vec1_C, inout_B, inout_B)); 55509566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 55519566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 5552674ae819SStefano Zampini } 5553674ae819SStefano Zampini } 55549566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][1], pc, 0, 0, 0)); 5555b334f244SStefano Zampini if (!reuse_solver || pcbddc->switch_static) { 555680677318SStefano Zampini if (applytranspose) { 55579566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec1_R)); 555880677318SStefano Zampini } else { 55599566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec1_R)); 556080677318SStefano Zampini } 55619566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec1_R)); 5562be83ff47SStefano Zampini } else { 5563df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 5564be83ff47SStefano Zampini 5565be83ff47SStefano Zampini if (applytranspose) { 55669566063dSJacob Faibussowitsch PetscCall(MatFactorSolveSchurComplementTranspose(reuse_solver->F, reuse_solver->rhs_B, reuse_solver->sol_B)); 5567be83ff47SStefano Zampini } else { 55689566063dSJacob Faibussowitsch PetscCall(MatFactorSolveSchurComplement(reuse_solver->F, reuse_solver->rhs_B, reuse_solver->sol_B)); 5569be83ff47SStefano Zampini } 5570be83ff47SStefano Zampini } 55719566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][1], pc, 0, 0, 0)); 55729566063dSJacob Faibussowitsch PetscCall(VecSet(inout_B, 0.)); 557380677318SStefano Zampini if (!pcbddc->switch_static) { 5574b334f244SStefano Zampini if (!reuse_solver) { 55759566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 55769566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 5577be83ff47SStefano Zampini } else { 5578df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 5579be83ff47SStefano Zampini 55809566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(reuse_solver->correction_scatter_B, reuse_solver->sol_B, inout_B, INSERT_VALUES, SCATTER_REVERSE)); 55819566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(reuse_solver->correction_scatter_B, reuse_solver->sol_B, inout_B, INSERT_VALUES, SCATTER_REVERSE)); 5582be83ff47SStefano Zampini } 558380677318SStefano Zampini if (!applytranspose && pcbddc->local_auxmat1) { 55849566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->local_auxmat1, inout_B, pcbddc->vec1_C)); 55859566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pcbddc->local_auxmat2, pcbddc->vec1_C, inout_B, inout_B)); 558680677318SStefano Zampini } 558780677318SStefano Zampini } else { 55889566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 55899566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 55909566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_D, pcbddc->vec1_R, inout_D, INSERT_VALUES, SCATTER_FORWARD)); 55919566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_D, pcbddc->vec1_R, inout_D, INSERT_VALUES, SCATTER_FORWARD)); 559280677318SStefano Zampini if (!applytranspose && pcbddc->local_auxmat1) { 55939566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->local_auxmat1, inout_B, pcbddc->vec1_C)); 55949566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pcbddc->local_auxmat2, pcbddc->vec1_C, pcbddc->vec1_R, pcbddc->vec1_R)); 559580677318SStefano Zampini } 55969566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 55979566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 55989566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_D, pcbddc->vec1_R, inout_D, INSERT_VALUES, SCATTER_FORWARD)); 55999566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_D, pcbddc->vec1_R, inout_D, INSERT_VALUES, SCATTER_FORWARD)); 5600674ae819SStefano Zampini } 56013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5602674ae819SStefano Zampini } 5603674ae819SStefano Zampini 5604dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */ 5605d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose) 5606d71ae5a4SJacob Faibussowitsch { 5607674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)(pc->data); 5608674ae819SStefano Zampini PC_IS *pcis = (PC_IS *)(pc->data); 5609674ae819SStefano Zampini const PetscScalar zero = 0.0; 5610674ae819SStefano Zampini 5611674ae819SStefano Zampini PetscFunctionBegin; 5612dc359a40SStefano Zampini /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */ 56134fee134fSStefano Zampini if (!pcbddc->benign_apply_coarse_only) { 5614dc359a40SStefano Zampini if (applytranspose) { 56159566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->coarse_phi_B, pcis->vec1_B, pcbddc->vec1_P)); 56169566063dSJacob Faibussowitsch if (pcbddc->switch_static) PetscCall(MatMultTransposeAdd(pcbddc->coarse_phi_D, pcis->vec1_D, pcbddc->vec1_P, pcbddc->vec1_P)); 5617dc359a40SStefano Zampini } else { 56189566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->coarse_psi_B, pcis->vec1_B, pcbddc->vec1_P)); 56199566063dSJacob Faibussowitsch if (pcbddc->switch_static) PetscCall(MatMultTransposeAdd(pcbddc->coarse_psi_D, pcis->vec1_D, pcbddc->vec1_P, pcbddc->vec1_P)); 562015aaf578SStefano Zampini } 56214fee134fSStefano Zampini } else { 56229566063dSJacob Faibussowitsch PetscCall(VecSet(pcbddc->vec1_P, zero)); 56234fee134fSStefano Zampini } 5624efc2fbd9SStefano Zampini 5625efc2fbd9SStefano Zampini /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */ 56264f1b2e48SStefano Zampini if (pcbddc->benign_n) { 5627efc2fbd9SStefano Zampini PetscScalar *array; 56284f1b2e48SStefano Zampini PetscInt j; 5629efc2fbd9SStefano Zampini 56309566063dSJacob Faibussowitsch PetscCall(VecGetArray(pcbddc->vec1_P, &array)); 56314f1b2e48SStefano Zampini for (j = 0; j < pcbddc->benign_n; j++) array[pcbddc->local_primal_size - pcbddc->benign_n + j] += pcbddc->benign_p0[j]; 56329566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pcbddc->vec1_P, &array)); 5633efc2fbd9SStefano Zampini } 5634efc2fbd9SStefano Zampini 563512edc857SStefano Zampini /* start communications from local primal nodes to rhs of coarse solver */ 56369566063dSJacob Faibussowitsch PetscCall(VecSet(pcbddc->coarse_vec, zero)); 56379566063dSJacob Faibussowitsch PetscCall(PCBDDCScatterCoarseDataBegin(pc, ADD_VALUES, SCATTER_FORWARD)); 56389566063dSJacob Faibussowitsch PetscCall(PCBDDCScatterCoarseDataEnd(pc, ADD_VALUES, SCATTER_FORWARD)); 563912edc857SStefano Zampini 56409f00e9b4SStefano Zampini /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */ 564112edc857SStefano Zampini if (pcbddc->coarse_ksp) { 564251694757SStefano Zampini Mat coarse_mat; 5643964fefecSStefano Zampini Vec rhs, sol; 564451694757SStefano Zampini MatNullSpace nullsp; 564527b6a85dSStefano Zampini PetscBool isbddc = PETSC_FALSE; 5646964fefecSStefano Zampini 564727b6a85dSStefano Zampini if (pcbddc->benign_have_null) { 564827b6a85dSStefano Zampini PC coarse_pc; 564927b6a85dSStefano Zampini 56509566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &coarse_pc)); 56519566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)coarse_pc, PCBDDC, &isbddc)); 565227b6a85dSStefano Zampini /* we need to propagate to coarser levels the need for a possible benign correction */ 565327b6a85dSStefano Zampini if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) { 565427b6a85dSStefano Zampini PC_BDDC *coarsepcbddc = (PC_BDDC *)(coarse_pc->data); 565527b6a85dSStefano Zampini coarsepcbddc->benign_skip_correction = PETSC_FALSE; 56563bca92a6SStefano Zampini coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE; 565727b6a85dSStefano Zampini } 565827b6a85dSStefano Zampini } 56599566063dSJacob Faibussowitsch PetscCall(KSPGetRhs(pcbddc->coarse_ksp, &rhs)); 56609566063dSJacob Faibussowitsch PetscCall(KSPGetSolution(pcbddc->coarse_ksp, &sol)); 56619566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(pcbddc->coarse_ksp, &coarse_mat, NULL)); 566212edc857SStefano Zampini if (applytranspose) { 566328b400f6SJacob Faibussowitsch PetscCheck(!pcbddc->benign_apply_coarse_only, PetscObjectComm((PetscObject)pcbddc->coarse_ksp), PETSC_ERR_SUP, "Not yet implemented"); 56649566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][2], pc, 0, 0, 0)); 56659566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->coarse_ksp, rhs, sol)); 56669566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][2], pc, 0, 0, 0)); 56679566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->coarse_ksp, pc, sol)); 56689566063dSJacob Faibussowitsch PetscCall(MatGetTransposeNullSpace(coarse_mat, &nullsp)); 56691baa6e33SBarry Smith if (nullsp) PetscCall(MatNullSpaceRemove(nullsp, sol)); 56702701bc32SStefano Zampini } else { 56719566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(coarse_mat, &nullsp)); 56721f4df5f7SStefano Zampini if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */ 56732701bc32SStefano Zampini PC coarse_pc; 56742701bc32SStefano Zampini 56751baa6e33SBarry Smith if (nullsp) PetscCall(MatNullSpaceRemove(nullsp, rhs)); 56769566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &coarse_pc)); 56779566063dSJacob Faibussowitsch PetscCall(PCPreSolve(coarse_pc, pcbddc->coarse_ksp)); 56789566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignRemoveInterior(coarse_pc, rhs, sol)); 56799566063dSJacob Faibussowitsch PetscCall(PCPostSolve(coarse_pc, pcbddc->coarse_ksp)); 568012edc857SStefano Zampini } else { 56819566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][2], pc, 0, 0, 0)); 56829566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->coarse_ksp, rhs, sol)); 56839566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][2], pc, 0, 0, 0)); 56849566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->coarse_ksp, pc, sol)); 56851baa6e33SBarry Smith if (nullsp) PetscCall(MatNullSpaceRemove(nullsp, sol)); 568612edc857SStefano Zampini } 56872701bc32SStefano Zampini } 56881d82a3b6SStefano Zampini /* we don't need the benign correction at coarser levels anymore */ 568927b6a85dSStefano Zampini if (pcbddc->benign_have_null && isbddc) { 569027b6a85dSStefano Zampini PC coarse_pc; 569127b6a85dSStefano Zampini PC_BDDC *coarsepcbddc; 569227b6a85dSStefano Zampini 56939566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &coarse_pc)); 569427b6a85dSStefano Zampini coarsepcbddc = (PC_BDDC *)(coarse_pc->data); 569527b6a85dSStefano Zampini coarsepcbddc->benign_skip_correction = PETSC_TRUE; 56963bca92a6SStefano Zampini coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE; 569727b6a85dSStefano Zampini } 569812edc857SStefano Zampini } 5699674ae819SStefano Zampini 5700674ae819SStefano Zampini /* Local solution on R nodes */ 570148a46eb9SPierre Jolivet if (pcis->n && !pcbddc->benign_apply_coarse_only) PetscCall(PCBDDCSolveSubstructureCorrection(pc, pcis->vec1_B, pcis->vec1_D, applytranspose)); 57029f00e9b4SStefano Zampini /* communications from coarse sol to local primal nodes */ 57039566063dSJacob Faibussowitsch PetscCall(PCBDDCScatterCoarseDataBegin(pc, INSERT_VALUES, SCATTER_REVERSE)); 57049566063dSJacob Faibussowitsch PetscCall(PCBDDCScatterCoarseDataEnd(pc, INSERT_VALUES, SCATTER_REVERSE)); 5705674ae819SStefano Zampini 57064fee134fSStefano Zampini /* Sum contributions from the two levels */ 57074fee134fSStefano Zampini if (!pcbddc->benign_apply_coarse_only) { 5708dc359a40SStefano Zampini if (applytranspose) { 57099566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pcbddc->coarse_psi_B, pcbddc->vec1_P, pcis->vec1_B, pcis->vec1_B)); 57109566063dSJacob Faibussowitsch if (pcbddc->switch_static) PetscCall(MatMultAdd(pcbddc->coarse_psi_D, pcbddc->vec1_P, pcis->vec1_D, pcis->vec1_D)); 5711dc359a40SStefano Zampini } else { 57129566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pcbddc->coarse_phi_B, pcbddc->vec1_P, pcis->vec1_B, pcis->vec1_B)); 57139566063dSJacob Faibussowitsch if (pcbddc->switch_static) PetscCall(MatMultAdd(pcbddc->coarse_phi_D, pcbddc->vec1_P, pcis->vec1_D, pcis->vec1_D)); 5714dc359a40SStefano Zampini } 5715efc2fbd9SStefano Zampini /* store p0 */ 57164f1b2e48SStefano Zampini if (pcbddc->benign_n) { 5717efc2fbd9SStefano Zampini PetscScalar *array; 57184f1b2e48SStefano Zampini PetscInt j; 5719efc2fbd9SStefano Zampini 57209566063dSJacob Faibussowitsch PetscCall(VecGetArray(pcbddc->vec1_P, &array)); 57214f1b2e48SStefano Zampini for (j = 0; j < pcbddc->benign_n; j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size - pcbddc->benign_n + j]; 57229566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pcbddc->vec1_P, &array)); 5723efc2fbd9SStefano Zampini } 57244fee134fSStefano Zampini } else { /* expand the coarse solution */ 57254fee134fSStefano Zampini if (applytranspose) { 57269566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->coarse_psi_B, pcbddc->vec1_P, pcis->vec1_B)); 57274fee134fSStefano Zampini } else { 57289566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->coarse_phi_B, pcbddc->vec1_P, pcis->vec1_B)); 57294fee134fSStefano Zampini } 57304fee134fSStefano Zampini } 57313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5732674ae819SStefano Zampini } 5733674ae819SStefano Zampini 5734d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc, InsertMode imode, ScatterMode smode) 5735d71ae5a4SJacob Faibussowitsch { 5736674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)(pc->data); 573712edc857SStefano Zampini Vec from, to; 57387ebab0bbSStefano Zampini const PetscScalar *array; 5739674ae819SStefano Zampini 5740674ae819SStefano Zampini PetscFunctionBegin; 574112edc857SStefano Zampini if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */ 574212edc857SStefano Zampini from = pcbddc->coarse_vec; 574312edc857SStefano Zampini to = pcbddc->vec1_P; 574412edc857SStefano Zampini if (pcbddc->coarse_ksp) { /* get array from coarse processes */ 574512edc857SStefano Zampini Vec tvec; 574658da7f69SStefano Zampini 57479566063dSJacob Faibussowitsch PetscCall(KSPGetRhs(pcbddc->coarse_ksp, &tvec)); 57489566063dSJacob Faibussowitsch PetscCall(VecResetArray(tvec)); 57499566063dSJacob Faibussowitsch PetscCall(KSPGetSolution(pcbddc->coarse_ksp, &tvec)); 57509566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(tvec, &array)); 57519566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(from, array)); 57529566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(tvec, &array)); 575312edc857SStefano Zampini } 575412edc857SStefano Zampini } else { /* from local to global -> put data in coarse right hand side */ 575512edc857SStefano Zampini from = pcbddc->vec1_P; 575612edc857SStefano Zampini to = pcbddc->coarse_vec; 575712edc857SStefano Zampini } 57589566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob, from, to, imode, smode)); 57593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5760674ae819SStefano Zampini } 5761674ae819SStefano Zampini 5762d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode) 5763d71ae5a4SJacob Faibussowitsch { 5764674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)(pc->data); 576512edc857SStefano Zampini Vec from, to; 57667ebab0bbSStefano Zampini const PetscScalar *array; 5767674ae819SStefano Zampini 5768674ae819SStefano Zampini PetscFunctionBegin; 576912edc857SStefano Zampini if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */ 577012edc857SStefano Zampini from = pcbddc->coarse_vec; 577112edc857SStefano Zampini to = pcbddc->vec1_P; 577212edc857SStefano Zampini } else { /* from local to global -> put data in coarse right hand side */ 577312edc857SStefano Zampini from = pcbddc->vec1_P; 577412edc857SStefano Zampini to = pcbddc->coarse_vec; 577512edc857SStefano Zampini } 57769566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob, from, to, imode, smode)); 577712edc857SStefano Zampini if (smode == SCATTER_FORWARD) { 577812edc857SStefano Zampini if (pcbddc->coarse_ksp) { /* get array from coarse processes */ 577912edc857SStefano Zampini Vec tvec; 578058da7f69SStefano Zampini 57819566063dSJacob Faibussowitsch PetscCall(KSPGetRhs(pcbddc->coarse_ksp, &tvec)); 57829566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(to, &array)); 57839566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(tvec, array)); 57849566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(to, &array)); 578558da7f69SStefano Zampini } 578658da7f69SStefano Zampini } else { 578758da7f69SStefano Zampini if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */ 57889566063dSJacob Faibussowitsch PetscCall(VecResetArray(from)); 578912edc857SStefano Zampini } 579012edc857SStefano Zampini } 57913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5792674ae819SStefano Zampini } 5793674ae819SStefano Zampini 5794d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCConstraintsSetUp(PC pc) 5795d71ae5a4SJacob Faibussowitsch { 5796674ae819SStefano Zampini PC_IS *pcis = (PC_IS *)(pc->data); 5797674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 5798674ae819SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 5799984c4197SStefano Zampini /* one and zero */ 5800984c4197SStefano Zampini PetscScalar one = 1.0, zero = 0.0; 5801984c4197SStefano Zampini /* space to store constraints and their local indices */ 58029162d606SStefano Zampini PetscScalar *constraints_data; 58039162d606SStefano Zampini PetscInt *constraints_idxs, *constraints_idxs_B; 58049162d606SStefano Zampini PetscInt *constraints_idxs_ptr, *constraints_data_ptr; 58059162d606SStefano Zampini PetscInt *constraints_n; 5806984c4197SStefano Zampini /* iterators */ 5807b3d85658SStefano Zampini PetscInt i, j, k, total_counts, total_counts_cc, cum; 5808984c4197SStefano Zampini /* BLAS integers */ 5809e310c8b4SStefano Zampini PetscBLASInt lwork, lierr; 5810e310c8b4SStefano Zampini PetscBLASInt Blas_N, Blas_M, Blas_K, Blas_one = 1; 5811c4303822SStefano Zampini PetscBLASInt Blas_LDA, Blas_LDB, Blas_LDC; 5812727cdba6SStefano Zampini /* reuse */ 58130e6343abSStefano Zampini PetscInt olocal_primal_size, olocal_primal_size_cc; 58140e6343abSStefano Zampini PetscInt *olocal_primal_ref_node, *olocal_primal_ref_mult; 5815984c4197SStefano Zampini /* change of basis */ 5816b3d85658SStefano Zampini PetscBool qr_needed; 58179162d606SStefano Zampini PetscBT change_basis, qr_needed_idx; 5818984c4197SStefano Zampini /* auxiliary stuff */ 581964efe560SStefano Zampini PetscInt *nnz, *is_indices; 58208a0068c3SStefano Zampini PetscInt ncc; 5821984c4197SStefano Zampini /* some quantities */ 582245a1bb75SStefano Zampini PetscInt n_vertices, total_primal_vertices, valid_constraints; 5823a58a30b4SStefano Zampini PetscInt size_of_constraint, max_size_of_constraint = 0, max_constraints, temp_constraints; 582457715f18SStefano Zampini PetscReal tol; /* tolerance for retaining eigenmodes */ 5825984c4197SStefano Zampini 5826674ae819SStefano Zampini PetscFunctionBegin; 582757715f18SStefano Zampini tol = PetscSqrtReal(PETSC_SMALL); 58288e61c736SStefano Zampini /* Destroy Mat objects computed previously */ 58299566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->ChangeOfBasisMatrix)); 58309566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->ConstraintMatrix)); 58319566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->switch_static_change)); 5832088faed8SStefano Zampini /* save info on constraints from previous setup (if any) */ 5833088faed8SStefano Zampini olocal_primal_size = pcbddc->local_primal_size; 58340e6343abSStefano Zampini olocal_primal_size_cc = pcbddc->local_primal_size_cc; 58359566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(olocal_primal_size_cc, &olocal_primal_ref_node, olocal_primal_size_cc, &olocal_primal_ref_mult)); 58369566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(olocal_primal_ref_node, pcbddc->local_primal_ref_node, olocal_primal_size_cc)); 58379566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(olocal_primal_ref_mult, pcbddc->local_primal_ref_mult, olocal_primal_size_cc)); 58389566063dSJacob Faibussowitsch PetscCall(PetscFree2(pcbddc->local_primal_ref_node, pcbddc->local_primal_ref_mult)); 58399566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->primal_indices_local_idxs)); 5840cf5a6209SStefano Zampini 5841cf5a6209SStefano Zampini if (!pcbddc->adaptive_selection) { 58429162d606SStefano Zampini IS ISForVertices, *ISForFaces, *ISForEdges; 5843cf5a6209SStefano Zampini MatNullSpace nearnullsp; 5844cf5a6209SStefano Zampini const Vec *nearnullvecs; 5845cf5a6209SStefano Zampini Vec *localnearnullsp; 5846cf5a6209SStefano Zampini PetscScalar *array; 584732fe681dSStefano Zampini PetscInt n_ISForFaces, n_ISForEdges, nnsp_size, o_nf, o_ne; 5848cf5a6209SStefano Zampini PetscBool nnsp_has_cnst; 5849674ae819SStefano Zampini /* LAPACK working arrays for SVD or POD */ 5850b3d85658SStefano Zampini PetscBool skip_lapack, boolforchange; 5851674ae819SStefano Zampini PetscScalar *work; 5852674ae819SStefano Zampini PetscReal *singular_vals; 5853674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX) 5854674ae819SStefano Zampini PetscReal *rwork; 5855674ae819SStefano Zampini #endif 585655080a34SStefano Zampini PetscScalar *temp_basis = NULL, *correlation_mat = NULL; 5857964fefecSStefano Zampini PetscBLASInt dummy_int = 1; 5858964fefecSStefano Zampini PetscScalar dummy_scalar = 1.; 585955080a34SStefano Zampini PetscBool use_pod = PETSC_FALSE; 5860674ae819SStefano Zampini 586155080a34SStefano Zampini /* MKL SVD with same input gives different results on different processes! */ 5862b88df2e7SBarry Smith #if defined(PETSC_MISSING_LAPACK_GESVD) || defined(PETSC_HAVE_MKL_LIBS) 586355080a34SStefano Zampini use_pod = PETSC_TRUE; 586455080a34SStefano Zampini #endif 5865674ae819SStefano Zampini /* Get index sets for faces, edges and vertices from graph */ 58669566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, &n_ISForFaces, &ISForFaces, &n_ISForEdges, &ISForEdges, &ISForVertices)); 586732fe681dSStefano Zampini o_nf = n_ISForFaces; 586832fe681dSStefano Zampini o_ne = n_ISForEdges; 586932fe681dSStefano Zampini n_vertices = 0; 587032fe681dSStefano Zampini if (ISForVertices) PetscCall(ISGetSize(ISForVertices, &n_vertices)); 5871e4d548c7SStefano Zampini /* print some info */ 58725c643e28SStefano Zampini if (pcbddc->dbg_flag && (!pcbddc->sub_schurs || pcbddc->sub_schurs_rebuild)) { 587332fe681dSStefano Zampini if (!pcbddc->dbg_viewer) pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc)); 58749566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphASCIIView(pcbddc->mat_graph, pcbddc->dbg_flag, pcbddc->dbg_viewer)); 58759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 58769566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "--------------------------------------------------------------\n")); 587732fe681dSStefano Zampini PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate vertices (%d)\n", PetscGlobalRank, n_vertices, pcbddc->use_vertices)); 587863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate edges (%d)\n", PetscGlobalRank, n_ISForEdges, pcbddc->use_edges)); 587963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate faces (%d)\n", PetscGlobalRank, n_ISForFaces, pcbddc->use_faces)); 58809566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 58819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer)); 5882e4d548c7SStefano Zampini } 5883e4d548c7SStefano Zampini 588432fe681dSStefano Zampini if (!pcbddc->use_vertices) n_vertices = 0; 588532fe681dSStefano Zampini if (!pcbddc->use_edges) n_ISForEdges = 0; 588632fe681dSStefano Zampini if (!pcbddc->use_faces) n_ISForFaces = 0; 588770022509SStefano Zampini 5888674ae819SStefano Zampini /* check if near null space is attached to global mat */ 58896d9e27e4SStefano Zampini if (pcbddc->use_nnsp) { 58909566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pc->pmat, &nearnullsp)); 58916d9e27e4SStefano Zampini } else nearnullsp = NULL; 58926d9e27e4SStefano Zampini 5893674ae819SStefano Zampini if (nearnullsp) { 58949566063dSJacob Faibussowitsch PetscCall(MatNullSpaceGetVecs(nearnullsp, &nnsp_has_cnst, &nnsp_size, &nearnullvecs)); 5895f4ddd8eeSStefano Zampini /* remove any stored info */ 58969566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&pcbddc->onearnullspace)); 58979566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->onearnullvecs_state)); 5898f4ddd8eeSStefano Zampini /* store information for BDDC solver reuse */ 58999566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)nearnullsp)); 5900f4ddd8eeSStefano Zampini pcbddc->onearnullspace = nearnullsp; 59019566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnsp_size, &pcbddc->onearnullvecs_state)); 590248a46eb9SPierre Jolivet for (i = 0; i < nnsp_size; i++) PetscCall(PetscObjectStateGet((PetscObject)nearnullvecs[i], &pcbddc->onearnullvecs_state[i])); 5903984c4197SStefano Zampini } else { /* if near null space is not provided BDDC uses constants by default */ 5904984c4197SStefano Zampini nnsp_size = 0; 5905674ae819SStefano Zampini nnsp_has_cnst = PETSC_TRUE; 5906674ae819SStefano Zampini } 5907984c4197SStefano Zampini /* get max number of constraints on a single cc */ 5908984c4197SStefano Zampini max_constraints = nnsp_size; 5909984c4197SStefano Zampini if (nnsp_has_cnst) max_constraints++; 5910984c4197SStefano Zampini 5911674ae819SStefano Zampini /* 5912674ae819SStefano Zampini Evaluate maximum storage size needed by the procedure 59139162d606SStefano Zampini - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]" 59149162d606SStefano Zampini - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]" 59159162d606SStefano Zampini There can be multiple constraints per connected component 5916674ae819SStefano Zampini */ 59179162d606SStefano Zampini ncc = n_vertices + n_ISForFaces + n_ISForEdges; 59189566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(ncc + 1, &constraints_idxs_ptr, ncc + 1, &constraints_data_ptr, ncc, &constraints_n)); 59199162d606SStefano Zampini 59209162d606SStefano Zampini total_counts = n_ISForFaces + n_ISForEdges; 59219162d606SStefano Zampini total_counts *= max_constraints; 5922674ae819SStefano Zampini total_counts += n_vertices; 59239566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(total_counts, &change_basis)); 59249162d606SStefano Zampini 5925674ae819SStefano Zampini total_counts = 0; 5926674ae819SStefano Zampini max_size_of_constraint = 0; 5927674ae819SStefano Zampini for (i = 0; i < n_ISForEdges + n_ISForFaces; i++) { 59289162d606SStefano Zampini IS used_is; 5929674ae819SStefano Zampini if (i < n_ISForEdges) { 59309162d606SStefano Zampini used_is = ISForEdges[i]; 5931674ae819SStefano Zampini } else { 59329162d606SStefano Zampini used_is = ISForFaces[i - n_ISForEdges]; 5933674ae819SStefano Zampini } 59349566063dSJacob Faibussowitsch PetscCall(ISGetSize(used_is, &j)); 5935674ae819SStefano Zampini total_counts += j; 5936674ae819SStefano Zampini max_size_of_constraint = PetscMax(j, max_size_of_constraint); 5937674ae819SStefano Zampini } 59389566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(total_counts * max_constraints + n_vertices, &constraints_data, total_counts + n_vertices, &constraints_idxs, total_counts + n_vertices, &constraints_idxs_B)); 59399162d606SStefano Zampini 5940984c4197SStefano Zampini /* get local part of global near null space vectors */ 59419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnsp_size, &localnearnullsp)); 5942984c4197SStefano Zampini for (k = 0; k < nnsp_size; k++) { 59439566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_N, &localnearnullsp[k])); 59449566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, nearnullvecs[k], localnearnullsp[k], INSERT_VALUES, SCATTER_FORWARD)); 59459566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, nearnullvecs[k], localnearnullsp[k], INSERT_VALUES, SCATTER_FORWARD)); 5946984c4197SStefano Zampini } 5947674ae819SStefano Zampini 5948242a89d7SStefano Zampini /* whether or not to skip lapack calls */ 5949242a89d7SStefano Zampini skip_lapack = PETSC_TRUE; 5950a773dcb8SStefano Zampini if (n_ISForFaces + n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE; 5951242a89d7SStefano Zampini 5952984c4197SStefano Zampini /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */ 5953a773dcb8SStefano Zampini if (!skip_lapack) { 5954674ae819SStefano Zampini PetscScalar temp_work; 5955911cabfeSStefano Zampini 595655080a34SStefano Zampini if (use_pod) { 5957984c4197SStefano Zampini /* Proper Orthogonal Decomposition (POD) using the snapshot method */ 59589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_constraints * max_constraints, &correlation_mat)); 59599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_constraints, &singular_vals)); 59609566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_size_of_constraint * max_constraints, &temp_basis)); 5961674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX) 59629566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(3 * max_constraints, &rwork)); 5963674ae819SStefano Zampini #endif 5964674ae819SStefano Zampini /* now we evaluate the optimal workspace using query with lwork=-1 */ 59659566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_constraints, &Blas_N)); 59669566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_constraints, &Blas_LDA)); 5967674ae819SStefano Zampini lwork = -1; 59689566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 5969674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX) 5970792fecdfSBarry Smith PetscCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &Blas_N, correlation_mat, &Blas_LDA, singular_vals, &temp_work, &lwork, &lierr)); 5971674ae819SStefano Zampini #else 5972792fecdfSBarry Smith PetscCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &Blas_N, correlation_mat, &Blas_LDA, singular_vals, &temp_work, &lwork, rwork, &lierr)); 5973674ae819SStefano Zampini #endif 59749566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 597528b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in query to SYEV Lapack routine %d", (int)lierr); 597655080a34SStefano Zampini } else { 597755080a34SStefano Zampini #if !defined(PETSC_MISSING_LAPACK_GESVD) 5978674ae819SStefano Zampini /* SVD */ 5979674ae819SStefano Zampini PetscInt max_n, min_n; 5980674ae819SStefano Zampini max_n = max_size_of_constraint; 5981984c4197SStefano Zampini min_n = max_constraints; 5982984c4197SStefano Zampini if (max_size_of_constraint < max_constraints) { 5983674ae819SStefano Zampini min_n = max_size_of_constraint; 5984984c4197SStefano Zampini max_n = max_constraints; 5985674ae819SStefano Zampini } 59869566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(min_n, &singular_vals)); 5987674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX) 59889566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(5 * min_n, &rwork)); 5989674ae819SStefano Zampini #endif 5990674ae819SStefano Zampini /* now we evaluate the optimal workspace using query with lwork=-1 */ 5991674ae819SStefano Zampini lwork = -1; 59929566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_n, &Blas_M)); 59939566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(min_n, &Blas_N)); 59949566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_n, &Blas_LDA)); 59959566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 5996674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX) 5997792fecdfSBarry Smith PetscCallBLAS("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)); 5998674ae819SStefano Zampini #else 5999792fecdfSBarry Smith PetscCallBLAS("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)); 6000674ae819SStefano Zampini #endif 60019566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 600228b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in query to GESVD Lapack routine %d", (int)lierr); 600355080a34SStefano Zampini #else 600455080a34SStefano Zampini SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "This should not happen"); 6005984c4197SStefano Zampini #endif /* on missing GESVD */ 600655080a34SStefano Zampini } 6007674ae819SStefano Zampini /* Allocate optimal workspace */ 60089566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(temp_work), &lwork)); 60099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(lwork, &work)); 6010674ae819SStefano Zampini } 6011674ae819SStefano Zampini /* Now we can loop on constraining sets */ 6012674ae819SStefano Zampini total_counts = 0; 60139162d606SStefano Zampini constraints_idxs_ptr[0] = 0; 60149162d606SStefano Zampini constraints_data_ptr[0] = 0; 6015674ae819SStefano Zampini /* vertices */ 60169162d606SStefano Zampini if (n_vertices) { 60179566063dSJacob Faibussowitsch PetscCall(ISGetIndices(ISForVertices, (const PetscInt **)&is_indices)); 60189566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(constraints_idxs, is_indices, n_vertices)); 6019674ae819SStefano Zampini for (i = 0; i < n_vertices; i++) { 60209162d606SStefano Zampini constraints_n[total_counts] = 1; 60219162d606SStefano Zampini constraints_data[total_counts] = 1.0; 60229162d606SStefano Zampini constraints_idxs_ptr[total_counts + 1] = constraints_idxs_ptr[total_counts] + 1; 60239162d606SStefano Zampini constraints_data_ptr[total_counts + 1] = constraints_data_ptr[total_counts] + 1; 6024674ae819SStefano Zampini total_counts++; 6025674ae819SStefano Zampini } 60269566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(ISForVertices, (const PetscInt **)&is_indices)); 6027674ae819SStefano Zampini } 6028984c4197SStefano Zampini 6029674ae819SStefano Zampini /* edges and faces */ 60309162d606SStefano Zampini total_counts_cc = total_counts; 6031911cabfeSStefano Zampini for (ncc = 0; ncc < n_ISForEdges + n_ISForFaces; ncc++) { 60329162d606SStefano Zampini IS used_is; 60339162d606SStefano Zampini PetscBool idxs_copied = PETSC_FALSE; 60349162d606SStefano Zampini 6035911cabfeSStefano Zampini if (ncc < n_ISForEdges) { 60369162d606SStefano Zampini used_is = ISForEdges[ncc]; 6037984c4197SStefano Zampini boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */ 6038674ae819SStefano Zampini } else { 60399162d606SStefano Zampini used_is = ISForFaces[ncc - n_ISForEdges]; 6040984c4197SStefano Zampini boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */ 6041674ae819SStefano Zampini } 6042674ae819SStefano Zampini temp_constraints = 0; /* zero the number of constraints I have on this conn comp */ 60439162d606SStefano Zampini 60449566063dSJacob Faibussowitsch PetscCall(ISGetSize(used_is, &size_of_constraint)); 604532fe681dSStefano Zampini if (!size_of_constraint) continue; 60469566063dSJacob Faibussowitsch PetscCall(ISGetIndices(used_is, (const PetscInt **)&is_indices)); 6047984c4197SStefano Zampini /* change of basis should not be performed on local periodic nodes */ 6048984c4197SStefano Zampini if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE; 6049674ae819SStefano Zampini if (nnsp_has_cnst) { 60505b08dc53SStefano Zampini PetscScalar quad_value; 60519162d606SStefano Zampini 60529566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc], is_indices, size_of_constraint)); 60539162d606SStefano Zampini idxs_copied = PETSC_TRUE; 60549162d606SStefano Zampini 6055a773dcb8SStefano Zampini if (!pcbddc->use_nnsp_true) { 6056674ae819SStefano Zampini quad_value = (PetscScalar)(1.0 / PetscSqrtReal((PetscReal)size_of_constraint)); 6057a773dcb8SStefano Zampini } else { 6058a773dcb8SStefano Zampini quad_value = 1.0; 6059a773dcb8SStefano Zampini } 6060ad540459SPierre Jolivet for (j = 0; j < size_of_constraint; j++) constraints_data[constraints_data_ptr[total_counts_cc] + j] = quad_value; 60619162d606SStefano Zampini temp_constraints++; 6062674ae819SStefano Zampini total_counts++; 6063674ae819SStefano Zampini } 6064674ae819SStefano Zampini for (k = 0; k < nnsp_size; k++) { 6065984c4197SStefano Zampini PetscReal real_value; 60669162d606SStefano Zampini PetscScalar *ptr_to_data; 60679162d606SStefano Zampini 60689566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(localnearnullsp[k], (const PetscScalar **)&array)); 60699162d606SStefano Zampini ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc] + temp_constraints * size_of_constraint]; 6070ad540459SPierre Jolivet for (j = 0; j < size_of_constraint; j++) ptr_to_data[j] = array[is_indices[j]]; 60719566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(localnearnullsp[k], (const PetscScalar **)&array)); 6072984c4197SStefano Zampini /* check if array is null on the connected component */ 60739566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 6074792fecdfSBarry Smith PetscCallBLAS("BLASasum", real_value = BLASasum_(&Blas_N, ptr_to_data, &Blas_one)); 607557715f18SStefano Zampini if (real_value > tol * size_of_constraint) { /* keep indices and values */ 6076674ae819SStefano Zampini temp_constraints++; 6077674ae819SStefano Zampini total_counts++; 60789162d606SStefano Zampini if (!idxs_copied) { 60799566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc], is_indices, size_of_constraint)); 60809162d606SStefano Zampini idxs_copied = PETSC_TRUE; 6081674ae819SStefano Zampini } 6082674ae819SStefano Zampini } 60839162d606SStefano Zampini } 60849566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(used_is, (const PetscInt **)&is_indices)); 608545a1bb75SStefano Zampini valid_constraints = temp_constraints; 6086eb97c9d2SStefano Zampini if (!pcbddc->use_nnsp_true && temp_constraints) { 6087a773dcb8SStefano Zampini if (temp_constraints == 1) { /* just normalize the constraint */ 60889162d606SStefano Zampini PetscScalar norm, *ptr_to_data; 60899162d606SStefano Zampini 60909162d606SStefano Zampini ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]]; 60919566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 6092792fecdfSBarry Smith PetscCallBLAS("BLASdot", norm = BLASdot_(&Blas_N, ptr_to_data, &Blas_one, ptr_to_data, &Blas_one)); 6093a773dcb8SStefano Zampini norm = 1.0 / PetscSqrtReal(PetscRealPart(norm)); 6094792fecdfSBarry Smith PetscCallBLAS("BLASscal", BLASscal_(&Blas_N, &norm, ptr_to_data, &Blas_one)); 6095a773dcb8SStefano Zampini } else { /* perform SVD */ 60969162d606SStefano Zampini PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]]; 6097674ae819SStefano Zampini 609855080a34SStefano Zampini if (use_pod) { 6099984c4197SStefano Zampini /* SVD: Y = U*S*V^H -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag 6100984c4197SStefano Zampini POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2) 6101984c4197SStefano Zampini -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined 6102984c4197SStefano Zampini the constraints basis will differ (by a complex factor with absolute value equal to 1) 6103984c4197SStefano Zampini from that computed using LAPACKgesvd 6104984c4197SStefano Zampini -> This is due to a different computation of eigenvectors in LAPACKheev 6105984c4197SStefano Zampini -> The quality of the POD-computed basis will be the same */ 61069566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(correlation_mat, temp_constraints * temp_constraints)); 6107674ae819SStefano Zampini /* Store upper triangular part of correlation matrix */ 61089566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 61099566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6110674ae819SStefano Zampini for (j = 0; j < temp_constraints; j++) { 611148a46eb9SPierre Jolivet for (k = 0; k < j + 1; k++) PetscCallBLAS("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)); 6112674ae819SStefano Zampini } 6113e310c8b4SStefano Zampini /* compute eigenvalues and eigenvectors of correlation matrix */ 61149566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_N)); 61159566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_LDA)); 6116674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX) 6117792fecdfSBarry Smith PetscCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &Blas_N, correlation_mat, &Blas_LDA, singular_vals, work, &lwork, &lierr)); 6118674ae819SStefano Zampini #else 6119792fecdfSBarry Smith PetscCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &Blas_N, correlation_mat, &Blas_LDA, singular_vals, work, &lwork, rwork, &lierr)); 6120674ae819SStefano Zampini #endif 61219566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 612228b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in SYEV Lapack routine %d", (int)lierr); 6123984c4197SStefano Zampini /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */ 6124674ae819SStefano Zampini j = 0; 612587b3baaaSStefano Zampini while (j < temp_constraints && singular_vals[j] / singular_vals[temp_constraints - 1] < tol) j++; 6126674ae819SStefano Zampini total_counts = total_counts - j; 612745a1bb75SStefano Zampini valid_constraints = temp_constraints - j; 6128e310c8b4SStefano Zampini /* scale and copy POD basis into used quadrature memory */ 61299566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_M)); 61309566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_N)); 61319566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_K)); 61329566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 61339566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_LDB)); 61349566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDC)); 6135674ae819SStefano Zampini if (j < temp_constraints) { 6136984c4197SStefano Zampini PetscInt ii; 6137984c4197SStefano Zampini for (k = j; k < temp_constraints; k++) singular_vals[k] = 1.0 / PetscSqrtReal(singular_vals[k]); 61389566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6139792fecdfSBarry Smith PetscCallBLAS("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)); 61409566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 6141984c4197SStefano Zampini for (k = 0; k < temp_constraints - j; k++) { 6142ad540459SPierre Jolivet for (ii = 0; ii < size_of_constraint; ii++) ptr_to_data[k * size_of_constraint + ii] = singular_vals[temp_constraints - 1 - k] * temp_basis[(temp_constraints - 1 - k) * size_of_constraint + ii]; 6143674ae819SStefano Zampini } 6144674ae819SStefano Zampini } 614555080a34SStefano Zampini } else { 614655080a34SStefano Zampini #if !defined(PETSC_MISSING_LAPACK_GESVD) 61479566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_M)); 61489566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_N)); 61499566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 61509566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6151674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX) 6152792fecdfSBarry Smith PetscCallBLAS("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)); 6153674ae819SStefano Zampini #else 6154792fecdfSBarry Smith PetscCallBLAS("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)); 6155674ae819SStefano Zampini #endif 615628b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in GESVD Lapack routine %d", (int)lierr); 61579566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 6158984c4197SStefano Zampini /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */ 6159e310c8b4SStefano Zampini k = temp_constraints; 6160e310c8b4SStefano Zampini if (k > size_of_constraint) k = size_of_constraint; 6161674ae819SStefano Zampini j = 0; 616287b3baaaSStefano Zampini while (j < k && singular_vals[k - j - 1] / singular_vals[0] < tol) j++; 616345a1bb75SStefano Zampini valid_constraints = k - j; 6164911cabfeSStefano Zampini total_counts = total_counts - temp_constraints + valid_constraints; 616555080a34SStefano Zampini #else 616655080a34SStefano Zampini SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "This should not happen"); 6167984c4197SStefano Zampini #endif /* on missing GESVD */ 6168674ae819SStefano Zampini } 6169a773dcb8SStefano Zampini } 617055080a34SStefano Zampini } 61719162d606SStefano Zampini /* update pointers information */ 61729162d606SStefano Zampini if (valid_constraints) { 61739162d606SStefano Zampini constraints_n[total_counts_cc] = valid_constraints; 61749162d606SStefano Zampini constraints_idxs_ptr[total_counts_cc + 1] = constraints_idxs_ptr[total_counts_cc] + size_of_constraint; 61759162d606SStefano Zampini constraints_data_ptr[total_counts_cc + 1] = constraints_data_ptr[total_counts_cc] + size_of_constraint * valid_constraints; 61769162d606SStefano Zampini /* set change_of_basis flag */ 61773ba16761SJacob Faibussowitsch if (boolforchange) PetscCall(PetscBTSet(change_basis, total_counts_cc)); 6178b3d85658SStefano Zampini total_counts_cc++; 617945a1bb75SStefano Zampini } 618045a1bb75SStefano Zampini } 6181984c4197SStefano Zampini /* free workspace */ 61828f1c130eSStefano Zampini if (!skip_lapack) { 61839566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 6184984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX) 61859566063dSJacob Faibussowitsch PetscCall(PetscFree(rwork)); 6186984c4197SStefano Zampini #endif 61879566063dSJacob Faibussowitsch PetscCall(PetscFree(singular_vals)); 61889566063dSJacob Faibussowitsch PetscCall(PetscFree(correlation_mat)); 61899566063dSJacob Faibussowitsch PetscCall(PetscFree(temp_basis)); 6190984c4197SStefano Zampini } 619148a46eb9SPierre Jolivet for (k = 0; k < nnsp_size; k++) PetscCall(VecDestroy(&localnearnullsp[k])); 61929566063dSJacob Faibussowitsch PetscCall(PetscFree(localnearnullsp)); 6193cf5a6209SStefano Zampini /* free index sets of faces, edges and vertices */ 619432fe681dSStefano Zampini PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, &o_nf, &ISForFaces, &o_ne, &ISForEdges, &ISForVertices)); 619508122e43SStefano Zampini } else { 619608122e43SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 6197984c4197SStefano Zampini 619808122e43SStefano Zampini total_counts = 0; 619908122e43SStefano Zampini n_vertices = 0; 620048a46eb9SPierre Jolivet if (sub_schurs->is_vertices && pcbddc->use_vertices) PetscCall(ISGetLocalSize(sub_schurs->is_vertices, &n_vertices)); 620108122e43SStefano Zampini max_constraints = 0; 62029162d606SStefano Zampini total_counts_cc = 0; 620308122e43SStefano Zampini for (i = 0; i < sub_schurs->n_subs + n_vertices; i++) { 620408122e43SStefano Zampini total_counts += pcbddc->adaptive_constraints_n[i]; 62059162d606SStefano Zampini if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++; 620608122e43SStefano Zampini max_constraints = PetscMax(max_constraints, pcbddc->adaptive_constraints_n[i]); 620708122e43SStefano Zampini } 62089162d606SStefano Zampini constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr; 62099162d606SStefano Zampini constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr; 62109162d606SStefano Zampini constraints_idxs = pcbddc->adaptive_constraints_idxs; 62119162d606SStefano Zampini constraints_data = pcbddc->adaptive_constraints_data; 621274d5cdf7SStefano Zampini /* constraints_n differs from pcbddc->adaptive_constraints_n */ 62139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(total_counts_cc, &constraints_n)); 62149162d606SStefano Zampini total_counts_cc = 0; 62159162d606SStefano Zampini for (i = 0; i < sub_schurs->n_subs + n_vertices; i++) { 6216ad540459SPierre Jolivet if (pcbddc->adaptive_constraints_n[i]) constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i]; 621708122e43SStefano Zampini } 621808122e43SStefano Zampini 62198bec7fa6SStefano Zampini max_size_of_constraint = 0; 62209162d606SStefano 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]); 62219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(constraints_idxs_ptr[total_counts_cc], &constraints_idxs_B)); 622208122e43SStefano Zampini /* Change of basis */ 62239566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(total_counts_cc, &change_basis)); 622408122e43SStefano Zampini if (pcbddc->use_change_of_basis) { 622508122e43SStefano Zampini for (i = 0; i < sub_schurs->n_subs; i++) { 622648a46eb9SPierre Jolivet if (PetscBTLookup(sub_schurs->is_edge, i) || pcbddc->use_change_on_faces) PetscCall(PetscBTSet(change_basis, i + n_vertices)); 622708122e43SStefano Zampini } 622808122e43SStefano Zampini } 622908122e43SStefano Zampini } 6230984c4197SStefano Zampini pcbddc->local_primal_size = total_counts; 62319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->local_primal_size + pcbddc->benign_n, &pcbddc->primal_indices_local_idxs)); 623208122e43SStefano Zampini 62339162d606SStefano Zampini /* map constraints_idxs in boundary numbering */ 623432fe681dSStefano Zampini if (pcbddc->use_change_of_basis) { 62359566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(pcis->BtoNmap, IS_GTOLM_DROP, constraints_idxs_ptr[total_counts_cc], constraints_idxs, &i, constraints_idxs_B)); 623663a3b9bcSJacob Faibussowitsch PetscCheck(i == constraints_idxs_ptr[total_counts_cc], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Error in boundary numbering for constraints indices %" PetscInt_FMT " != %" PetscInt_FMT, constraints_idxs_ptr[total_counts_cc], i); 623732fe681dSStefano Zampini } 6238674ae819SStefano Zampini 6239674ae819SStefano Zampini /* Create constraint matrix */ 62409566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &pcbddc->ConstraintMatrix)); 62419566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->ConstraintMatrix, MATAIJ)); 62429566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->ConstraintMatrix, pcbddc->local_primal_size, pcis->n, pcbddc->local_primal_size, pcis->n)); 6243984c4197SStefano Zampini 6244984c4197SStefano Zampini /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */ 6245a717540cSStefano Zampini /* determine if a QR strategy is needed for change of basis */ 62465a52fde0SStefano Zampini qr_needed = pcbddc->use_qr_single; 62479566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(total_counts_cc, &qr_needed_idx)); 6248984c4197SStefano Zampini total_primal_vertices = 0; 6249b3d85658SStefano Zampini pcbddc->local_primal_size_cc = 0; 62509162d606SStefano Zampini for (i = 0; i < total_counts_cc; i++) { 62519162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[i + 1] - constraints_idxs_ptr[i]; 625272b8c272SStefano Zampini if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) { 62539162d606SStefano Zampini pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]]; 6254b3d85658SStefano Zampini pcbddc->local_primal_size_cc += 1; 625564efe560SStefano Zampini } else if (PetscBTLookup(change_basis, i)) { 6256ad540459SPierre Jolivet for (k = 0; k < constraints_n[i]; k++) pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i] + k]; 6257b3d85658SStefano Zampini pcbddc->local_primal_size_cc += constraints_n[i]; 625891af6908SStefano Zampini if (constraints_n[i] > 1 || pcbddc->use_qr_single) { 62593ba16761SJacob Faibussowitsch PetscCall(PetscBTSet(qr_needed_idx, i)); 6260a717540cSStefano Zampini qr_needed = PETSC_TRUE; 6261a717540cSStefano Zampini } 6262fa434743SStefano Zampini } else { 6263b3d85658SStefano Zampini pcbddc->local_primal_size_cc += 1; 6264fa434743SStefano Zampini } 6265a717540cSStefano Zampini } 6266b371cd4fSStefano Zampini /* note that the local variable n_vertices used below stores the number of pointwise constraints */ 6267b371cd4fSStefano Zampini pcbddc->n_vertices = total_primal_vertices; 6268674ae819SStefano Zampini /* permute indices in order to have a sorted set of vertices */ 62699566063dSJacob Faibussowitsch PetscCall(PetscSortInt(total_primal_vertices, pcbddc->primal_indices_local_idxs)); 62709566063dSJacob Faibussowitsch PetscCall(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)); 62719566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pcbddc->local_primal_ref_node, pcbddc->primal_indices_local_idxs, total_primal_vertices)); 62720e6343abSStefano Zampini for (i = 0; i < total_primal_vertices; i++) pcbddc->local_primal_ref_mult[i] = 1; 6273984c4197SStefano Zampini 6274984c4197SStefano Zampini /* nonzero structure of constraint matrix */ 627574d5cdf7SStefano Zampini /* and get reference dof for local constraints */ 62769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->local_primal_size, &nnz)); 6277984c4197SStefano Zampini for (i = 0; i < total_primal_vertices; i++) nnz[i] = 1; 627874d5cdf7SStefano Zampini 6279984c4197SStefano Zampini j = total_primal_vertices; 628074d5cdf7SStefano Zampini total_counts = total_primal_vertices; 6281b3d85658SStefano Zampini cum = total_primal_vertices; 62829162d606SStefano Zampini for (i = n_vertices; i < total_counts_cc; i++) { 62834641a718SStefano Zampini if (!PetscBTLookup(change_basis, i)) { 6284b3d85658SStefano Zampini pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]]; 6285b3d85658SStefano Zampini pcbddc->local_primal_ref_mult[cum] = constraints_n[i]; 6286b3d85658SStefano Zampini cum++; 62879162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[i + 1] - constraints_idxs_ptr[i]; 628874d5cdf7SStefano Zampini for (k = 0; k < constraints_n[i]; k++) { 628974d5cdf7SStefano Zampini pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i] + k]; 629074d5cdf7SStefano Zampini nnz[j + k] = size_of_constraint; 629174d5cdf7SStefano Zampini } 62929162d606SStefano Zampini j += constraints_n[i]; 6293674ae819SStefano Zampini } 6294674ae819SStefano Zampini } 62959566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix, 0, nnz)); 62969566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->ConstraintMatrix, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 62979566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 6298088faed8SStefano Zampini 6299674ae819SStefano Zampini /* set values in constraint matrix */ 630048a46eb9SPierre Jolivet for (i = 0; i < total_primal_vertices; i++) PetscCall(MatSetValue(pcbddc->ConstraintMatrix, i, pcbddc->local_primal_ref_node[i], 1.0, INSERT_VALUES)); 6301984c4197SStefano Zampini total_counts = total_primal_vertices; 63029162d606SStefano Zampini for (i = n_vertices; i < total_counts_cc; i++) { 63034641a718SStefano Zampini if (!PetscBTLookup(change_basis, i)) { 63049162d606SStefano Zampini PetscInt *cols; 63059162d606SStefano Zampini 63069162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[i + 1] - constraints_idxs_ptr[i]; 63079162d606SStefano Zampini cols = constraints_idxs + constraints_idxs_ptr[i]; 63089162d606SStefano Zampini for (k = 0; k < constraints_n[i]; k++) { 63099162d606SStefano Zampini PetscInt row = total_counts + k; 63109162d606SStefano Zampini PetscScalar *vals; 63119162d606SStefano Zampini 63129162d606SStefano Zampini vals = constraints_data + constraints_data_ptr[i] + k * size_of_constraint; 63139566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->ConstraintMatrix, 1, &row, size_of_constraint, cols, vals, INSERT_VALUES)); 63149162d606SStefano Zampini } 63159162d606SStefano Zampini total_counts += constraints_n[i]; 6316674ae819SStefano Zampini } 6317674ae819SStefano Zampini } 6318674ae819SStefano Zampini /* assembling */ 63199566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pcbddc->ConstraintMatrix, MAT_FINAL_ASSEMBLY)); 63209566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->ConstraintMatrix, MAT_FINAL_ASSEMBLY)); 63219566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(pcbddc->ConstraintMatrix, (PetscObject)pc, "-pc_bddc_constraint_mat_view")); 6322088faed8SStefano Zampini 6323674ae819SStefano Zampini /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */ 6324674ae819SStefano Zampini if (pcbddc->use_change_of_basis) { 6325026de310SStefano Zampini /* dual and primal dofs on a single cc */ 6326984c4197SStefano Zampini PetscInt dual_dofs, primal_dofs; 6327984c4197SStefano Zampini /* working stuff for GEQRF */ 63285a52fde0SStefano Zampini PetscScalar *qr_basis = NULL, *qr_tau = NULL, *qr_work = NULL, lqr_work_t; 6329984c4197SStefano Zampini PetscBLASInt lqr_work; 6330984c4197SStefano Zampini /* working stuff for UNGQR */ 63313c377650SSatish Balay PetscScalar *gqr_work = NULL, lgqr_work_t = 0.0; 6332984c4197SStefano Zampini PetscBLASInt lgqr_work; 6333984c4197SStefano Zampini /* working stuff for TRTRS */ 63345a52fde0SStefano Zampini PetscScalar *trs_rhs = NULL; 63353f08241aSStefano Zampini PetscBLASInt Blas_NRHS; 6336984c4197SStefano Zampini /* pointers for values insertion into change of basis matrix */ 6337984c4197SStefano Zampini PetscInt *start_rows, *start_cols; 6338984c4197SStefano Zampini PetscScalar *start_vals; 6339984c4197SStefano Zampini /* working stuff for values insertion */ 63404641a718SStefano Zampini PetscBT is_primal; 634164efe560SStefano Zampini PetscInt *aux_primal_numbering_B; 6342906d46d4SStefano Zampini /* matrix sizes */ 6343906d46d4SStefano Zampini PetscInt global_size, local_size; 6344906d46d4SStefano Zampini /* temporary change of basis */ 6345906d46d4SStefano Zampini Mat localChangeOfBasisMatrix; 6346cf5a6209SStefano Zampini /* extra space for debugging */ 63475a52fde0SStefano Zampini PetscScalar *dbg_work = NULL; 6348984c4197SStefano Zampini 63499566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &localChangeOfBasisMatrix)); 63509566063dSJacob Faibussowitsch PetscCall(MatSetType(localChangeOfBasisMatrix, MATAIJ)); 63519566063dSJacob Faibussowitsch PetscCall(MatSetSizes(localChangeOfBasisMatrix, pcis->n, pcis->n, pcis->n, pcis->n)); 6352906d46d4SStefano Zampini /* nonzeros for local mat */ 63539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n, &nnz)); 63541dd7afcfSStefano Zampini if (!pcbddc->benign_change || pcbddc->fake_change) { 6355bbb9e6c6SStefano Zampini for (i = 0; i < pcis->n; i++) nnz[i] = 1; 63561dd7afcfSStefano Zampini } else { 63571dd7afcfSStefano Zampini const PetscInt *ii; 63581dd7afcfSStefano Zampini PetscInt n; 63591dd7afcfSStefano Zampini PetscBool flg_row; 63609566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(pcbddc->benign_change, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, NULL, &flg_row)); 63611dd7afcfSStefano Zampini for (i = 0; i < n; i++) nnz[i] = ii[i + 1] - ii[i]; 63629566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(pcbddc->benign_change, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, NULL, &flg_row)); 63631dd7afcfSStefano Zampini } 63649162d606SStefano Zampini for (i = n_vertices; i < total_counts_cc; i++) { 6365a717540cSStefano Zampini if (PetscBTLookup(change_basis, i)) { 63669162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[i + 1] - constraints_idxs_ptr[i]; 6367a717540cSStefano Zampini if (PetscBTLookup(qr_needed_idx, i)) { 63689162d606SStefano Zampini for (j = 0; j < size_of_constraint; j++) nnz[constraints_idxs[constraints_idxs_ptr[i] + j]] = size_of_constraint; 6369a717540cSStefano Zampini } else { 63709162d606SStefano Zampini nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint; 63719162d606SStefano Zampini for (j = 1; j < size_of_constraint; j++) nnz[constraints_idxs[constraints_idxs_ptr[i] + j]] = 2; 6372a717540cSStefano Zampini } 6373a717540cSStefano Zampini } 6374a717540cSStefano Zampini } 63759566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(localChangeOfBasisMatrix, 0, nnz)); 63769566063dSJacob Faibussowitsch PetscCall(MatSetOption(localChangeOfBasisMatrix, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 63779566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 63781dd7afcfSStefano Zampini /* Set interior change in the matrix */ 63791dd7afcfSStefano Zampini if (!pcbddc->benign_change || pcbddc->fake_change) { 638048a46eb9SPierre Jolivet for (i = 0; i < pcis->n; i++) PetscCall(MatSetValue(localChangeOfBasisMatrix, i, i, 1.0, INSERT_VALUES)); 63811dd7afcfSStefano Zampini } else { 63821dd7afcfSStefano Zampini const PetscInt *ii, *jj; 63831dd7afcfSStefano Zampini PetscScalar *aa; 63841dd7afcfSStefano Zampini PetscInt n; 63851dd7afcfSStefano Zampini PetscBool flg_row; 63869566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(pcbddc->benign_change, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &flg_row)); 63879566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(pcbddc->benign_change, &aa)); 638848a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall(MatSetValues(localChangeOfBasisMatrix, 1, &i, ii[i + 1] - ii[i], jj + ii[i], aa + ii[i], INSERT_VALUES)); 63899566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(pcbddc->benign_change, &aa)); 63909566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(pcbddc->benign_change, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &flg_row)); 63911dd7afcfSStefano Zampini } 6392a717540cSStefano Zampini 6393a717540cSStefano Zampini if (pcbddc->dbg_flag) { 63949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "--------------------------------------------------------------\n")); 63959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Checking change of basis computation for subdomain %04d\n", PetscGlobalRank)); 6396a717540cSStefano Zampini } 6397a717540cSStefano Zampini 6398a717540cSStefano Zampini /* Now we loop on the constraints which need a change of basis */ 6399a717540cSStefano Zampini /* 6400a717540cSStefano Zampini Change of basis matrix is evaluated similarly to the FIRST APPROACH in 6401a717540cSStefano Zampini Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1) 6402a717540cSStefano Zampini 64037c625d9fSStefano Zampini Basic blocks of change of basis matrix T computed: 6404a717540cSStefano Zampini 64057c625d9fSStefano Zampini - By using the following block transformation if there is only a primal dof on the cc (and -pc_bddc_use_qr_single is not specified) 6406a6b551f4SStefano Zampini 6407a6b551f4SStefano Zampini | 1 0 ... 0 s_1/S | 6408a6b551f4SStefano Zampini | 0 1 ... 0 s_2/S | 6409a717540cSStefano Zampini | ... | 6410a6b551f4SStefano Zampini | 0 ... 1 s_{n-1}/S | 6411a6b551f4SStefano Zampini | -s_1/s_n ... -s_{n-1}/s_n s_n/S | 6412a717540cSStefano Zampini 6413a6b551f4SStefano Zampini with S = \sum_{i=1}^n s_i^2 6414a6b551f4SStefano Zampini NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering 6415a6b551f4SStefano Zampini in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering 6416a6b551f4SStefano Zampini 6417a6b551f4SStefano Zampini - QR decomposition of constraints otherwise 6418a717540cSStefano Zampini */ 64195a52fde0SStefano Zampini if (qr_needed && max_size_of_constraint) { 6420984c4197SStefano Zampini /* space to store Q */ 64219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_size_of_constraint * max_size_of_constraint, &qr_basis)); 64224e64d54eSstefano_zampini /* array to store scaling factors for reflectors */ 64239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_constraints, &qr_tau)); 6424984c4197SStefano Zampini /* first we issue queries for optimal work */ 64259566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_size_of_constraint, &Blas_M)); 64269566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_constraints, &Blas_N)); 64279566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_size_of_constraint, &Blas_LDA)); 6428984c4197SStefano Zampini lqr_work = -1; 6429792fecdfSBarry Smith PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&Blas_M, &Blas_N, qr_basis, &Blas_LDA, qr_tau, &lqr_work_t, &lqr_work, &lierr)); 643028b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in query to GEQRF Lapack routine %d", (int)lierr); 64319566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t), &lqr_work)); 64329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t), &qr_work)); 6433984c4197SStefano Zampini lgqr_work = -1; 64349566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_size_of_constraint, &Blas_M)); 64359566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_size_of_constraint, &Blas_N)); 64369566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_constraints, &Blas_K)); 64379566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_size_of_constraint, &Blas_LDA)); 64383f08241aSStefano Zampini if (Blas_K > Blas_M) Blas_K = Blas_M; /* adjust just for computing optimal work */ 6439792fecdfSBarry Smith PetscCallBLAS("LAPACKorgqr", LAPACKorgqr_(&Blas_M, &Blas_N, &Blas_K, qr_basis, &Blas_LDA, qr_tau, &lgqr_work_t, &lgqr_work, &lierr)); 644028b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in query to ORGQR/UNGQR Lapack routine %d", (int)lierr); 64419566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t), &lgqr_work)); 64429566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t), &gqr_work)); 6443984c4197SStefano Zampini /* array to store rhs and solution of triangular solver */ 64449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_constraints * max_constraints, &trs_rhs)); 6445a717540cSStefano Zampini /* allocating workspace for check */ 644648a46eb9SPierre Jolivet if (pcbddc->dbg_flag) PetscCall(PetscMalloc1(max_size_of_constraint * (max_constraints + max_size_of_constraint), &dbg_work)); 6447a717540cSStefano Zampini } 6448984c4197SStefano Zampini /* array to store whether a node is primal or not */ 64499566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(pcis->n_B, &is_primal)); 64509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(total_primal_vertices, &aux_primal_numbering_B)); 64519566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(pcis->BtoNmap, IS_GTOLM_DROP, total_primal_vertices, pcbddc->local_primal_ref_node, &i, aux_primal_numbering_B)); 645263a3b9bcSJacob Faibussowitsch PetscCheck(i == total_primal_vertices, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Error in boundary numbering for BDDC vertices! %" PetscInt_FMT " != %" PetscInt_FMT, total_primal_vertices, i); 645348a46eb9SPierre Jolivet for (i = 0; i < total_primal_vertices; i++) PetscCall(PetscBTSet(is_primal, aux_primal_numbering_B[i])); 64549566063dSJacob Faibussowitsch PetscCall(PetscFree(aux_primal_numbering_B)); 6455984c4197SStefano Zampini 6456a717540cSStefano Zampini /* loop on constraints and see whether or not they need a change of basis and compute it */ 64579162d606SStefano Zampini for (total_counts = n_vertices; total_counts < total_counts_cc; total_counts++) { 64589162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[total_counts + 1] - constraints_idxs_ptr[total_counts]; 64594641a718SStefano Zampini if (PetscBTLookup(change_basis, total_counts)) { 6460984c4197SStefano Zampini /* get constraint info */ 64619162d606SStefano Zampini primal_dofs = constraints_n[total_counts]; 6462984c4197SStefano Zampini dual_dofs = size_of_constraint - primal_dofs; 6463984c4197SStefano Zampini 646448a46eb9SPierre Jolivet if (pcbddc->dbg_flag) PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Constraints %" PetscInt_FMT ": %" PetscInt_FMT " need a change of basis (size %" PetscInt_FMT ")\n", total_counts, primal_dofs, size_of_constraint)); 6465984c4197SStefano Zampini 6466fa434743SStefano Zampini if (PetscBTLookup(qr_needed_idx, total_counts)) { /* QR */ 6467a717540cSStefano Zampini 6468a717540cSStefano Zampini /* copy quadrature constraints for change of basis check */ 646948a46eb9SPierre Jolivet if (pcbddc->dbg_flag) PetscCall(PetscArraycpy(dbg_work, &constraints_data[constraints_data_ptr[total_counts]], size_of_constraint * primal_dofs)); 6470984c4197SStefano Zampini /* copy temporary constraints into larger work vector (in order to store all columns of Q) */ 64719566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(qr_basis, &constraints_data[constraints_data_ptr[total_counts]], size_of_constraint * primal_dofs)); 6472984c4197SStefano Zampini 6473984c4197SStefano Zampini /* compute QR decomposition of constraints */ 64749566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_M)); 64759566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_N)); 64769566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 64779566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6478792fecdfSBarry Smith PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&Blas_M, &Blas_N, qr_basis, &Blas_LDA, qr_tau, qr_work, &lqr_work, &lierr)); 647928b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in GEQRF Lapack routine %d", (int)lierr); 64809566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 6481984c4197SStefano Zampini 6482a5b23f4aSJose E. Roman /* explicitly compute R^-T */ 64839566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(trs_rhs, primal_dofs * primal_dofs)); 6484984c4197SStefano Zampini for (j = 0; j < primal_dofs; j++) trs_rhs[j * (primal_dofs + 1)] = 1.0; 64859566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_N)); 64869566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_NRHS)); 64879566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 64889566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_LDB)); 64899566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6490792fecdfSBarry Smith PetscCallBLAS("LAPACKtrtrs", LAPACKtrtrs_("U", "T", "N", &Blas_N, &Blas_NRHS, qr_basis, &Blas_LDA, trs_rhs, &Blas_LDB, &lierr)); 649128b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in TRTRS Lapack routine %d", (int)lierr); 64929566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 6493984c4197SStefano Zampini 6494a717540cSStefano Zampini /* explicitly compute all columns of Q (Q = [Q1 | Q2]) overwriting QR factorization in qr_basis */ 64959566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_M)); 64969566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 64979566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_K)); 64989566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 64999566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6500792fecdfSBarry Smith PetscCallBLAS("LAPACKorgqr", LAPACKorgqr_(&Blas_M, &Blas_N, &Blas_K, qr_basis, &Blas_LDA, qr_tau, gqr_work, &lgqr_work, &lierr)); 650128b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ORGQR/UNGQR Lapack routine %d", (int)lierr); 65029566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 6503984c4197SStefano Zampini 6504984c4197SStefano Zampini /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints 6505984c4197SStefano Zampini i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below) 6506984c4197SStefano Zampini where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */ 65079566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_M)); 65089566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_N)); 65099566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_K)); 65109566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 65119566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_LDB)); 65129566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDC)); 65139566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6514792fecdfSBarry Smith PetscCallBLAS("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)); 65159566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 65169566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(qr_basis, &constraints_data[constraints_data_ptr[total_counts]], size_of_constraint * primal_dofs)); 6517984c4197SStefano Zampini 6518984c4197SStefano Zampini /* insert values in change of basis matrix respecting global ordering of new primal dofs */ 65199162d606SStefano Zampini start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]]; 6520984c4197SStefano Zampini /* insert cols for primal dofs */ 6521984c4197SStefano Zampini for (j = 0; j < primal_dofs; j++) { 6522984c4197SStefano Zampini start_vals = &qr_basis[j * size_of_constraint]; 65239162d606SStefano Zampini start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts] + j]; 65249566063dSJacob Faibussowitsch PetscCall(MatSetValues(localChangeOfBasisMatrix, size_of_constraint, start_rows, 1, start_cols, start_vals, INSERT_VALUES)); 6525984c4197SStefano Zampini } 6526984c4197SStefano Zampini /* insert cols for dual dofs */ 6527984c4197SStefano Zampini for (j = 0, k = 0; j < dual_dofs; k++) { 65289162d606SStefano Zampini if (!PetscBTLookup(is_primal, constraints_idxs_B[constraints_idxs_ptr[total_counts] + k])) { 6529984c4197SStefano Zampini start_vals = &qr_basis[(primal_dofs + j) * size_of_constraint]; 65309162d606SStefano Zampini start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts] + k]; 65319566063dSJacob Faibussowitsch PetscCall(MatSetValues(localChangeOfBasisMatrix, size_of_constraint, start_rows, 1, start_cols, start_vals, INSERT_VALUES)); 6532984c4197SStefano Zampini j++; 6533674ae819SStefano Zampini } 6534674ae819SStefano Zampini } 6535984c4197SStefano Zampini 6536984c4197SStefano Zampini /* check change of basis */ 6537984c4197SStefano Zampini if (pcbddc->dbg_flag) { 6538984c4197SStefano Zampini PetscInt ii, jj; 6539984c4197SStefano Zampini PetscBool valid_qr = PETSC_TRUE; 65409566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_M)); 65419566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 65429566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_K)); 65439566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 65449566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDB)); 65459566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_LDC)); 65469566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6547792fecdfSBarry Smith PetscCallBLAS("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)); 65489566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 6549984c4197SStefano Zampini for (jj = 0; jj < size_of_constraint; jj++) { 6550984c4197SStefano Zampini for (ii = 0; ii < primal_dofs; ii++) { 6551cf5a6209SStefano Zampini if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint * primal_dofs + jj * primal_dofs + ii]) > 1.e-12) valid_qr = PETSC_FALSE; 6552c068d9bbSLisandro Dalcin if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint * primal_dofs + jj * primal_dofs + ii] - (PetscReal)1) > 1.e-12) valid_qr = PETSC_FALSE; 6553674ae819SStefano Zampini } 6554674ae819SStefano Zampini } 6555984c4197SStefano Zampini if (!valid_qr) { 65569566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "\t-> wrong change of basis!\n")); 6557984c4197SStefano Zampini for (jj = 0; jj < size_of_constraint; jj++) { 6558984c4197SStefano Zampini for (ii = 0; ii < primal_dofs; ii++) { 6559cf5a6209SStefano Zampini if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint * primal_dofs + jj * primal_dofs + ii]) > 1.e-12) { 656063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "\tQr basis function %" PetscInt_FMT " is not orthogonal to constraint %" PetscInt_FMT " (%1.14e)!\n", jj, ii, (double)PetscAbsScalar(dbg_work[size_of_constraint * primal_dofs + jj * primal_dofs + ii]))); 6561674ae819SStefano Zampini } 6562c068d9bbSLisandro Dalcin if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint * primal_dofs + jj * primal_dofs + ii] - (PetscReal)1) > 1.e-12) { 656363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "\tQr basis function %" PetscInt_FMT " is not unitary w.r.t constraint %" PetscInt_FMT " (%1.14e)!\n", jj, ii, (double)PetscAbsScalar(dbg_work[size_of_constraint * primal_dofs + jj * primal_dofs + ii]))); 6564984c4197SStefano Zampini } 6565984c4197SStefano Zampini } 6566984c4197SStefano Zampini } 6567674ae819SStefano Zampini } else { 65689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "\t-> right change of basis!\n")); 6569674ae819SStefano Zampini } 6570674ae819SStefano Zampini } 6571a717540cSStefano Zampini } else { /* simple transformation block */ 6572a717540cSStefano Zampini PetscInt row, col; 6573a6b551f4SStefano Zampini PetscScalar val, norm; 6574a6b551f4SStefano Zampini 65759566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 6576792fecdfSBarry Smith PetscCallBLAS("BLASdot", norm = BLASdot_(&Blas_N, constraints_data + constraints_data_ptr[total_counts], &Blas_one, constraints_data + constraints_data_ptr[total_counts], &Blas_one)); 6577a717540cSStefano Zampini for (j = 0; j < size_of_constraint; j++) { 65789162d606SStefano Zampini PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts] + j]; 65799162d606SStefano Zampini row = constraints_idxs[constraints_idxs_ptr[total_counts] + j]; 6580bbb9e6c6SStefano Zampini if (!PetscBTLookup(is_primal, row_B)) { 65819162d606SStefano Zampini col = constraints_idxs[constraints_idxs_ptr[total_counts]]; 65829566063dSJacob Faibussowitsch PetscCall(MatSetValue(localChangeOfBasisMatrix, row, row, 1.0, INSERT_VALUES)); 65839566063dSJacob Faibussowitsch PetscCall(MatSetValue(localChangeOfBasisMatrix, row, col, constraints_data[constraints_data_ptr[total_counts] + j] / norm, INSERT_VALUES)); 6584a717540cSStefano Zampini } else { 6585a717540cSStefano Zampini for (k = 0; k < size_of_constraint; k++) { 65869162d606SStefano Zampini col = constraints_idxs[constraints_idxs_ptr[total_counts] + k]; 6587a717540cSStefano Zampini if (row != col) { 65889162d606SStefano Zampini val = -constraints_data[constraints_data_ptr[total_counts] + k] / constraints_data[constraints_data_ptr[total_counts]]; 6589a717540cSStefano Zampini } else { 65909162d606SStefano Zampini val = constraints_data[constraints_data_ptr[total_counts]] / norm; 6591a717540cSStefano Zampini } 65929566063dSJacob Faibussowitsch PetscCall(MatSetValue(localChangeOfBasisMatrix, row, col, val, INSERT_VALUES)); 6593a717540cSStefano Zampini } 6594a717540cSStefano Zampini } 6595a717540cSStefano Zampini } 659648a46eb9SPierre Jolivet if (pcbddc->dbg_flag) PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "\t-> using standard change of basis\n")); 6597a717540cSStefano Zampini } 6598984c4197SStefano Zampini } else { 659948a46eb9SPierre Jolivet if (pcbddc->dbg_flag) PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Constraint %" PetscInt_FMT " does not need a change of basis (size %" PetscInt_FMT ")\n", total_counts, size_of_constraint)); 6600674ae819SStefano Zampini } 6601674ae819SStefano Zampini } 6602a717540cSStefano Zampini 6603a717540cSStefano Zampini /* free workspace */ 6604a717540cSStefano Zampini if (qr_needed) { 66051baa6e33SBarry Smith if (pcbddc->dbg_flag) PetscCall(PetscFree(dbg_work)); 66069566063dSJacob Faibussowitsch PetscCall(PetscFree(trs_rhs)); 66079566063dSJacob Faibussowitsch PetscCall(PetscFree(qr_tau)); 66089566063dSJacob Faibussowitsch PetscCall(PetscFree(qr_work)); 66099566063dSJacob Faibussowitsch PetscCall(PetscFree(gqr_work)); 66109566063dSJacob Faibussowitsch PetscCall(PetscFree(qr_basis)); 6611674ae819SStefano Zampini } 66129566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&is_primal)); 66139566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(localChangeOfBasisMatrix, MAT_FINAL_ASSEMBLY)); 66149566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(localChangeOfBasisMatrix, MAT_FINAL_ASSEMBLY)); 6615906d46d4SStefano Zampini 6616906d46d4SStefano Zampini /* assembling of global change of variable */ 661788c03ad3SStefano Zampini if (!pcbddc->fake_change) { 6618bbb9e6c6SStefano Zampini Mat tmat; 661916f15bc4SStefano Zampini PetscInt bs; 662016f15bc4SStefano Zampini 66219566063dSJacob Faibussowitsch PetscCall(VecGetSize(pcis->vec1_global, &global_size)); 66229566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(pcis->vec1_global, &local_size)); 66239566063dSJacob Faibussowitsch PetscCall(MatDuplicate(pc->pmat, MAT_DO_NOT_COPY_VALUES, &tmat)); 66249566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(tmat, localChangeOfBasisMatrix)); 66259566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(tmat, MAT_FINAL_ASSEMBLY)); 66269566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(tmat, MAT_FINAL_ASSEMBLY)); 66279566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)pc), &pcbddc->ChangeOfBasisMatrix)); 66289566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->ChangeOfBasisMatrix, MATAIJ)); 66299566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(pc->pmat, &bs)); 66309566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(pcbddc->ChangeOfBasisMatrix, bs)); 66319566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->ChangeOfBasisMatrix, local_size, local_size, global_size, global_size)); 66329566063dSJacob Faibussowitsch PetscCall(MatISSetMPIXAIJPreallocation_Private(tmat, pcbddc->ChangeOfBasisMatrix, PETSC_TRUE)); 66339566063dSJacob Faibussowitsch PetscCall(MatConvert(tmat, MATAIJ, MAT_REUSE_MATRIX, &pcbddc->ChangeOfBasisMatrix)); 66349566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tmat)); 66359566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_global, 0.0)); 66369566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_N, 1.0)); 66379566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_N, pcis->vec1_global, ADD_VALUES, SCATTER_REVERSE)); 66389566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_N, pcis->vec1_global, ADD_VALUES, SCATTER_REVERSE)); 66399566063dSJacob Faibussowitsch PetscCall(VecReciprocal(pcis->vec1_global)); 66409566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(pcbddc->ChangeOfBasisMatrix, pcis->vec1_global, NULL)); 664188c03ad3SStefano Zampini 6642906d46d4SStefano Zampini /* check */ 6643906d46d4SStefano Zampini if (pcbddc->dbg_flag) { 6644906d46d4SStefano Zampini PetscReal error; 6645906d46d4SStefano Zampini Vec x, x_change; 6646906d46d4SStefano Zampini 66479566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_global, &x)); 66489566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_global, &x_change)); 66499566063dSJacob Faibussowitsch PetscCall(VecSetRandom(x, NULL)); 66509566063dSJacob Faibussowitsch PetscCall(VecCopy(x, pcis->vec1_global)); 66519566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, x, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD)); 66529566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, x, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD)); 66539566063dSJacob Faibussowitsch PetscCall(MatMult(localChangeOfBasisMatrix, pcis->vec1_N, pcis->vec2_N)); 66549566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, pcis->vec2_N, x, INSERT_VALUES, SCATTER_REVERSE)); 66559566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, pcis->vec2_N, x, INSERT_VALUES, SCATTER_REVERSE)); 66569566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcis->vec1_global, x_change)); 66579566063dSJacob Faibussowitsch PetscCall(VecAXPY(x, -1.0, x_change)); 66589566063dSJacob Faibussowitsch PetscCall(VecNorm(x, NORM_INFINITY, &error)); 6659049d1499SBarry Smith PetscCheck(error <= PETSC_SMALL, PetscObjectComm((PetscObject)pc), PETSC_ERR_PLIB, "Error global vs local change on N: %1.6e", (double)error); 66609566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 66619566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x_change)); 6662906d46d4SStefano Zampini } 6663b96c3477SStefano Zampini /* adapt sub_schurs computed (if any) */ 6664b96c3477SStefano Zampini if (pcbddc->use_deluxe_scaling) { 6665b96c3477SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 6666bf3a8328SStefano Zampini 666708401ef6SPierre Jolivet PetscCheck(!pcbddc->use_change_of_basis || !pcbddc->adaptive_userdefined, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot mix automatic change of basis, adaptive selection and user-defined constraints"); 6668b334f244SStefano Zampini if (sub_schurs && sub_schurs->S_Ej_all) { 6669ac632422SStefano Zampini Mat S_new, tmat; 6670bf3a8328SStefano Zampini IS is_all_N, is_V_Sall = NULL; 6671bbb9e6c6SStefano Zampini 66729566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(pcis->BtoNmap, sub_schurs->is_Ej_all, &is_all_N)); 66739566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(localChangeOfBasisMatrix, is_all_N, is_all_N, MAT_INITIAL_MATRIX, &tmat)); 6674bf3a8328SStefano Zampini if (pcbddc->deluxe_zerorows) { 6675bf3a8328SStefano Zampini ISLocalToGlobalMapping NtoSall; 6676bf3a8328SStefano Zampini IS is_V; 66779566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, pcbddc->n_vertices, pcbddc->local_primal_ref_node, PETSC_COPY_VALUES, &is_V)); 66789566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is_all_N, &NtoSall)); 66799566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(NtoSall, IS_GTOLM_DROP, is_V, &is_V_Sall)); 66809566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&NtoSall)); 66819566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_V)); 6682bf3a8328SStefano Zampini } 66839566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_all_N)); 66849566063dSJacob Faibussowitsch PetscCall(MatPtAP(sub_schurs->S_Ej_all, tmat, MAT_INITIAL_MATRIX, 1.0, &S_new)); 66859566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sub_schurs->S_Ej_all)); 66869566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)S_new)); 6687bf3a8328SStefano Zampini if (pcbddc->deluxe_zerorows) { 6688bf3a8328SStefano Zampini const PetscScalar *array; 6689bf3a8328SStefano Zampini const PetscInt *idxs_V, *idxs_all; 6690bf3a8328SStefano Zampini PetscInt i, n_V; 6691bf3a8328SStefano Zampini 66929566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumnsIS(S_new, is_V_Sall, 1., NULL, NULL)); 66939566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is_V_Sall, &n_V)); 66949566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is_V_Sall, &idxs_V)); 66959566063dSJacob Faibussowitsch PetscCall(ISGetIndices(sub_schurs->is_Ej_all, &idxs_all)); 66969566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(pcis->D, &array)); 6697b087196eSStefano Zampini for (i = 0; i < n_V; i++) { 6698b087196eSStefano Zampini PetscScalar val; 6699b087196eSStefano Zampini PetscInt idx; 6700b087196eSStefano Zampini 6701b087196eSStefano Zampini idx = idxs_V[i]; 6702b087196eSStefano Zampini val = array[idxs_all[idxs_V[i]]]; 67039566063dSJacob Faibussowitsch PetscCall(MatSetValue(S_new, idx, idx, val, INSERT_VALUES)); 6704b087196eSStefano Zampini } 67059566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(S_new, MAT_FINAL_ASSEMBLY)); 67069566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(S_new, MAT_FINAL_ASSEMBLY)); 67079566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(pcis->D, &array)); 67089566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(sub_schurs->is_Ej_all, &idxs_all)); 67099566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is_V_Sall, &idxs_V)); 6710bf3a8328SStefano Zampini } 6711ac632422SStefano Zampini sub_schurs->S_Ej_all = S_new; 67129566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_new)); 6713ac632422SStefano Zampini if (sub_schurs->sum_S_Ej_all) { 67149566063dSJacob Faibussowitsch PetscCall(MatPtAP(sub_schurs->sum_S_Ej_all, tmat, MAT_INITIAL_MATRIX, 1.0, &S_new)); 67159566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sub_schurs->sum_S_Ej_all)); 67169566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)S_new)); 67171baa6e33SBarry Smith if (pcbddc->deluxe_zerorows) PetscCall(MatZeroRowsColumnsIS(S_new, is_V_Sall, 1., NULL, NULL)); 6718ac632422SStefano Zampini sub_schurs->sum_S_Ej_all = S_new; 67199566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_new)); 6720ac632422SStefano Zampini } 67219566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_V_Sall)); 67229566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tmat)); 6723b96c3477SStefano Zampini } 6724c9db6a07SStefano Zampini /* destroy any change of basis context in sub_schurs */ 6725b334f244SStefano Zampini if (sub_schurs && sub_schurs->change) { 6726c9db6a07SStefano Zampini PetscInt i; 6727c9db6a07SStefano Zampini 672848a46eb9SPierre Jolivet for (i = 0; i < sub_schurs->n_subs; i++) PetscCall(KSPDestroy(&sub_schurs->change[i])); 67299566063dSJacob Faibussowitsch PetscCall(PetscFree(sub_schurs->change)); 6730c9db6a07SStefano Zampini } 6731b96c3477SStefano Zampini } 673216909a7fSStefano Zampini if (pcbddc->switch_static) { /* need to save the local change */ 673316909a7fSStefano Zampini pcbddc->switch_static_change = localChangeOfBasisMatrix; 673416909a7fSStefano Zampini } else { 67359566063dSJacob Faibussowitsch PetscCall(MatDestroy(&localChangeOfBasisMatrix)); 673616909a7fSStefano Zampini } 67371dd7afcfSStefano Zampini /* determine if any process has changed the pressures locally */ 673827b6a85dSStefano Zampini pcbddc->change_interior = pcbddc->benign_have_null; 673972b8c272SStefano Zampini } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */ 67409566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->ConstraintMatrix)); 674172b8c272SStefano Zampini pcbddc->ConstraintMatrix = localChangeOfBasisMatrix; 674272b8c272SStefano Zampini pcbddc->use_qr_single = qr_needed; 674372b8c272SStefano Zampini } 67441dd7afcfSStefano Zampini } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) { 674527b6a85dSStefano Zampini if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) { 67469566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix)); 6747b9b85e73SStefano Zampini pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix; 6748906d46d4SStefano Zampini } else { 67491dd7afcfSStefano Zampini Mat benign_global = NULL; 675027b6a85dSStefano Zampini if (pcbddc->benign_have_null) { 67511dd7afcfSStefano Zampini Mat M; 67521dd7afcfSStefano Zampini 67539e9b7b1fSStefano Zampini pcbddc->change_interior = PETSC_TRUE; 67549566063dSJacob Faibussowitsch PetscCall(VecCopy(matis->counter, pcis->vec1_N)); 67559566063dSJacob Faibussowitsch PetscCall(VecReciprocal(pcis->vec1_N)); 67569566063dSJacob Faibussowitsch PetscCall(MatDuplicate(pc->pmat, MAT_DO_NOT_COPY_VALUES, &benign_global)); 67579e9b7b1fSStefano Zampini if (pcbddc->benign_change) { 67589566063dSJacob Faibussowitsch PetscCall(MatDuplicate(pcbddc->benign_change, MAT_COPY_VALUES, &M)); 67599566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(M, pcis->vec1_N, NULL)); 6760906d46d4SStefano Zampini } else { 67619566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, pcis->n, pcis->n, 1, NULL, &M)); 67629566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(M, pcis->vec1_N, INSERT_VALUES)); 6763906d46d4SStefano Zampini } 67649566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(benign_global, M)); 67659566063dSJacob Faibussowitsch PetscCall(MatDestroy(&M)); 67669566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(benign_global, MAT_FINAL_ASSEMBLY)); 67679566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(benign_global, MAT_FINAL_ASSEMBLY)); 67681dd7afcfSStefano Zampini } 67691dd7afcfSStefano Zampini if (pcbddc->user_ChangeOfBasisMatrix) { 67709566063dSJacob Faibussowitsch PetscCall(MatMatMult(pcbddc->user_ChangeOfBasisMatrix, benign_global, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &pcbddc->ChangeOfBasisMatrix)); 67719566063dSJacob Faibussowitsch PetscCall(MatDestroy(&benign_global)); 677227b6a85dSStefano Zampini } else if (pcbddc->benign_have_null) { 67731dd7afcfSStefano Zampini pcbddc->ChangeOfBasisMatrix = benign_global; 67741dd7afcfSStefano Zampini } 67751dd7afcfSStefano Zampini } 677616909a7fSStefano Zampini if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */ 677716909a7fSStefano Zampini IS is_global; 677816909a7fSStefano Zampini const PetscInt *gidxs; 677916909a7fSStefano Zampini 67809566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->rmapping, &gidxs)); 67819566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), pcis->n, gidxs, PETSC_COPY_VALUES, &is_global)); 67829566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->rmapping, &gidxs)); 67839566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix, is_global, is_global, &pcbddc->switch_static_change)); 67849566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_global)); 678516909a7fSStefano Zampini } 67861dd7afcfSStefano Zampini } 678748a46eb9SPierre Jolivet if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->work_change)); 6788a717540cSStefano Zampini 678972b8c272SStefano Zampini if (!pcbddc->fake_change) { 67904f1b2e48SStefano Zampini /* add pressure dofs to set of primal nodes for numbering purposes */ 67914f1b2e48SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) { 67924f1b2e48SStefano Zampini pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i]; 67934f1b2e48SStefano Zampini pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i]; 6794019a44ceSStefano Zampini pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1; 6795019a44ceSStefano Zampini pcbddc->local_primal_size_cc++; 6796019a44ceSStefano Zampini pcbddc->local_primal_size++; 6797019a44ceSStefano Zampini } 6798019a44ceSStefano Zampini 6799019a44ceSStefano Zampini /* check if a new primal space has been introduced (also take into account benign trick) */ 6800727cdba6SStefano Zampini pcbddc->new_primal_space_local = PETSC_TRUE; 6801727cdba6SStefano Zampini if (olocal_primal_size == pcbddc->local_primal_size) { 68029566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(pcbddc->local_primal_ref_node, olocal_primal_ref_node, olocal_primal_size_cc, &pcbddc->new_primal_space_local)); 6803c1c8e736SStefano Zampini pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local); 68040e6343abSStefano Zampini if (!pcbddc->new_primal_space_local) { 68059566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(pcbddc->local_primal_ref_mult, olocal_primal_ref_mult, olocal_primal_size_cc, &pcbddc->new_primal_space_local)); 6806727cdba6SStefano Zampini pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local); 6807727cdba6SStefano Zampini } 68080e6343abSStefano Zampini } 6809727cdba6SStefano Zampini /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */ 68101c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&pcbddc->new_primal_space_local, &pcbddc->new_primal_space, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 681172b8c272SStefano Zampini } 68129566063dSJacob Faibussowitsch PetscCall(PetscFree2(olocal_primal_ref_node, olocal_primal_ref_mult)); 6813727cdba6SStefano Zampini 6814a717540cSStefano Zampini /* flush dbg viewer */ 68151baa6e33SBarry Smith if (pcbddc->dbg_flag) PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 6816a717540cSStefano Zampini 6817e310c8b4SStefano Zampini /* free workspace */ 68189566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&qr_needed_idx)); 68199566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&change_basis)); 682008122e43SStefano Zampini if (!pcbddc->adaptive_selection) { 68219566063dSJacob Faibussowitsch PetscCall(PetscFree3(constraints_idxs_ptr, constraints_data_ptr, constraints_n)); 68229566063dSJacob Faibussowitsch PetscCall(PetscFree3(constraints_data, constraints_idxs, constraints_idxs_B)); 682308122e43SStefano Zampini } else { 6824d0609cedSBarry Smith PetscCall(PetscFree5(pcbddc->adaptive_constraints_n, pcbddc->adaptive_constraints_idxs_ptr, pcbddc->adaptive_constraints_data_ptr, pcbddc->adaptive_constraints_idxs, pcbddc->adaptive_constraints_data)); 68259566063dSJacob Faibussowitsch PetscCall(PetscFree(constraints_n)); 68269566063dSJacob Faibussowitsch PetscCall(PetscFree(constraints_idxs_B)); 682708122e43SStefano Zampini } 68283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6829674ae819SStefano Zampini } 6830674ae819SStefano Zampini 6831d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCAnalyzeInterface(PC pc) 6832d71ae5a4SJacob Faibussowitsch { 683371582508SStefano Zampini ISLocalToGlobalMapping map; 6834674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 6835674ae819SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 683666da6bd7Sstefano_zampini PetscInt i, N; 683766da6bd7Sstefano_zampini PetscBool rcsr = PETSC_FALSE; 6838674ae819SStefano Zampini 6839674ae819SStefano Zampini PetscFunctionBegin; 68408af8fcf9SStefano Zampini if (pcbddc->recompute_topography) { 6841b03ebc13SStefano Zampini pcbddc->graphanalyzed = PETSC_FALSE; 68428e61c736SStefano Zampini /* Reset previously computed graph */ 68439566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphReset(pcbddc->mat_graph)); 6844674ae819SStefano Zampini /* Init local Graph struct */ 68459566063dSJacob Faibussowitsch PetscCall(MatGetSize(pc->pmat, &N, NULL)); 68469566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(pc->pmat, &map, NULL)); 68479566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphInit(pcbddc->mat_graph, map, N, pcbddc->graphmaxcount)); 6848674ae819SStefano Zampini 684948a46eb9SPierre Jolivet if (pcbddc->user_primal_vertices_local && !pcbddc->user_primal_vertices) PetscCall(PCBDDCConsistencyCheckIS(pc, MPI_LOR, &pcbddc->user_primal_vertices_local)); 6850575ad6abSStefano Zampini /* Check validity of the csr graph passed in by the user */ 68519371c9d4SSatish Balay PetscCheck(!pcbddc->mat_graph->nvtxs_csr || pcbddc->mat_graph->nvtxs_csr == pcbddc->mat_graph->nvtxs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid size of local CSR graph! Found %" PetscInt_FMT ", expected %" PetscInt_FMT, pcbddc->mat_graph->nvtxs_csr, 68529371c9d4SSatish Balay pcbddc->mat_graph->nvtxs); 68539577ea80SStefano Zampini 6854674ae819SStefano Zampini /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */ 685566da6bd7Sstefano_zampini if (!pcbddc->mat_graph->xadj && pcbddc->use_local_adj) { 68564d379d7bSStefano Zampini PetscInt *xadj, *adjncy; 68574d379d7bSStefano Zampini PetscInt nvtxs; 6858e496cd5dSStefano Zampini PetscBool flg_row = PETSC_FALSE; 6859674ae819SStefano Zampini 68609566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(matis->A, 0, PETSC_TRUE, PETSC_FALSE, &nvtxs, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &flg_row)); 68612fffb893SStefano Zampini if (flg_row) { 68629566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLocalAdjacencyGraph(pc, nvtxs, xadj, adjncy, PETSC_COPY_VALUES)); 6863b96c3477SStefano Zampini pcbddc->computed_rowadj = PETSC_TRUE; 68642fffb893SStefano Zampini } 68659566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(matis->A, 0, PETSC_TRUE, PETSC_FALSE, &nvtxs, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &flg_row)); 686666da6bd7Sstefano_zampini rcsr = PETSC_TRUE; 6867674ae819SStefano Zampini } 68681baa6e33SBarry Smith if (pcbddc->dbg_flag) PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 6869674ae819SStefano Zampini 6870ab8c8b98SStefano Zampini if (pcbddc->mat_graph->cdim && !pcbddc->mat_graph->cloc) { 6871ab8c8b98SStefano Zampini PetscReal *lcoords; 6872ab8c8b98SStefano Zampini PetscInt n; 6873ab8c8b98SStefano Zampini MPI_Datatype dimrealtype; 6874ab8c8b98SStefano Zampini 68754f819b78SStefano Zampini /* TODO: support for blocked */ 687663a3b9bcSJacob Faibussowitsch PetscCheck(pcbddc->mat_graph->cnloc == pc->pmat->rmap->n, PETSC_COMM_SELF, PETSC_ERR_USER, "Invalid number of local coordinates! Got %" PetscInt_FMT ", expected %" PetscInt_FMT, pcbddc->mat_graph->cnloc, pc->pmat->rmap->n); 68779566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(matis->A, &n, NULL)); 68789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->mat_graph->cdim * n, &lcoords)); 68799566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(pcbddc->mat_graph->cdim, MPIU_REAL, &dimrealtype)); 68809566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&dimrealtype)); 68819566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, dimrealtype, pcbddc->mat_graph->coords, lcoords, MPI_REPLACE)); 68829566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, dimrealtype, pcbddc->mat_graph->coords, lcoords, MPI_REPLACE)); 68839566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&dimrealtype)); 68849566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->mat_graph->coords)); 6885ab8c8b98SStefano Zampini 6886ab8c8b98SStefano Zampini pcbddc->mat_graph->coords = lcoords; 6887ab8c8b98SStefano Zampini pcbddc->mat_graph->cloc = PETSC_TRUE; 6888ab8c8b98SStefano Zampini pcbddc->mat_graph->cnloc = n; 6889ab8c8b98SStefano Zampini } 68909371c9d4SSatish Balay PetscCheck(!pcbddc->mat_graph->cnloc || pcbddc->mat_graph->cnloc == pcbddc->mat_graph->nvtxs, PETSC_COMM_SELF, PETSC_ERR_USER, "Invalid number of local subdomain coordinates! Got %" PetscInt_FMT ", expected %" PetscInt_FMT, pcbddc->mat_graph->cnloc, 68919371c9d4SSatish Balay pcbddc->mat_graph->nvtxs); 6892625961bdSStefano Zampini pcbddc->mat_graph->active_coords = (PetscBool)(pcbddc->corner_selection && pcbddc->mat_graph->cdim && !pcbddc->corner_selected); 6893ab8c8b98SStefano Zampini 6894674ae819SStefano Zampini /* Setup of Graph */ 68954b2aedd3SStefano Zampini pcbddc->mat_graph->commsizelimit = 0; /* don't use the COMM_SELF variant of the graph */ 68969566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphSetUp(pcbddc->mat_graph, pcbddc->vertex_size, pcbddc->NeumannBoundariesLocal, pcbddc->DirichletBoundariesLocal, pcbddc->n_ISForDofsLocal, pcbddc->ISForDofsLocal, pcbddc->user_primal_vertices_local)); 6897674ae819SStefano Zampini 68984f1b2e48SStefano Zampini /* attach info on disconnected subdomains if present */ 68994f1b2e48SStefano Zampini if (pcbddc->n_local_subs) { 690020c3699dSStefano Zampini PetscInt *local_subs, n, totn; 69014f1b2e48SStefano Zampini 69029566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(matis->A, &n, NULL)); 69039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &local_subs)); 690420c3699dSStefano Zampini for (i = 0; i < n; i++) local_subs[i] = pcbddc->n_local_subs; 69054f1b2e48SStefano Zampini for (i = 0; i < pcbddc->n_local_subs; i++) { 69064f1b2e48SStefano Zampini const PetscInt *idxs; 69074f1b2e48SStefano Zampini PetscInt nl, j; 69084f1b2e48SStefano Zampini 69099566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->local_subs[i], &nl)); 69109566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->local_subs[i], &idxs)); 691171582508SStefano Zampini for (j = 0; j < nl; j++) local_subs[idxs[j]] = i; 69129566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->local_subs[i], &idxs)); 69134f1b2e48SStefano Zampini } 691420c3699dSStefano Zampini for (i = 0, totn = 0; i < n; i++) totn = PetscMax(totn, local_subs[i]); 691520c3699dSStefano Zampini pcbddc->mat_graph->n_local_subs = totn + 1; 69164f1b2e48SStefano Zampini pcbddc->mat_graph->local_subs = local_subs; 69174f1b2e48SStefano Zampini } 69188af8fcf9SStefano Zampini } 69194f1b2e48SStefano Zampini 6920cac5312eSStefano Zampini if (!pcbddc->graphanalyzed) { 6921674ae819SStefano Zampini /* Graph's connected components analysis */ 69229566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph)); 692371582508SStefano Zampini pcbddc->graphanalyzed = PETSC_TRUE; 69244f819b78SStefano Zampini pcbddc->corner_selected = pcbddc->corner_selection; 69258af8fcf9SStefano Zampini } 692666da6bd7Sstefano_zampini if (rcsr) pcbddc->mat_graph->nvtxs_csr = 0; 69273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6928674ae819SStefano Zampini } 6929674ae819SStefano Zampini 6930d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt *nio, Vec vecs[]) 6931d71ae5a4SJacob Faibussowitsch { 6932295df10fSStefano Zampini PetscInt i, j, n; 69339a7d3425SStefano Zampini PetscScalar *alphas; 6934295df10fSStefano Zampini PetscReal norm, *onorms; 69359a7d3425SStefano Zampini 69369a7d3425SStefano Zampini PetscFunctionBegin; 6937295df10fSStefano Zampini n = *nio; 69383ba16761SJacob Faibussowitsch if (!n) PetscFunctionReturn(PETSC_SUCCESS); 69399566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n, &alphas, n, &onorms)); 69409566063dSJacob Faibussowitsch PetscCall(VecNormalize(vecs[0], &norm)); 694192cccca0SStefano Zampini if (norm < PETSC_SMALL) { 6942295df10fSStefano Zampini onorms[0] = 0.0; 69439566063dSJacob Faibussowitsch PetscCall(VecSet(vecs[0], 0.0)); 6944295df10fSStefano Zampini } else { 6945295df10fSStefano Zampini onorms[0] = norm; 694692cccca0SStefano Zampini } 6947295df10fSStefano Zampini 69488c0031efSStefano Zampini for (i = 1; i < n; i++) { 69499566063dSJacob Faibussowitsch PetscCall(VecMDot(vecs[i], i, vecs, alphas)); 69508c0031efSStefano Zampini for (j = 0; j < i; j++) alphas[j] = PetscConj(-alphas[j]); 69519566063dSJacob Faibussowitsch PetscCall(VecMAXPY(vecs[i], i, alphas, vecs)); 69529566063dSJacob Faibussowitsch PetscCall(VecNormalize(vecs[i], &norm)); 695392cccca0SStefano Zampini if (norm < PETSC_SMALL) { 6954295df10fSStefano Zampini onorms[i] = 0.0; 69559566063dSJacob Faibussowitsch PetscCall(VecSet(vecs[i], 0.0)); 6956295df10fSStefano Zampini } else { 6957295df10fSStefano Zampini onorms[i] = norm; 695892cccca0SStefano Zampini } 69599a7d3425SStefano Zampini } 6960295df10fSStefano Zampini /* push nonzero vectors at the beginning */ 6961295df10fSStefano Zampini for (i = 0; i < n; i++) { 6962295df10fSStefano Zampini if (onorms[i] == 0.0) { 6963295df10fSStefano Zampini for (j = i + 1; j < n; j++) { 6964295df10fSStefano Zampini if (onorms[j] != 0.0) { 69659566063dSJacob Faibussowitsch PetscCall(VecCopy(vecs[j], vecs[i])); 6966295df10fSStefano Zampini onorms[j] = 0.0; 6967295df10fSStefano Zampini } 6968295df10fSStefano Zampini } 6969295df10fSStefano Zampini } 6970295df10fSStefano Zampini } 6971295df10fSStefano Zampini for (i = 0, *nio = 0; i < n; i++) *nio += onorms[i] != 0.0 ? 1 : 0; 69729566063dSJacob Faibussowitsch PetscCall(PetscFree2(alphas, onorms)); 69733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 69749a7d3425SStefano Zampini } 69759a7d3425SStefano Zampini 6976d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCMatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS *is_sends, PetscBool *have_void) 6977d71ae5a4SJacob Faibussowitsch { 6978e432b41dSStefano Zampini ISLocalToGlobalMapping mapping; 697957de7509SStefano Zampini Mat A; 6980e7931f94SStefano Zampini PetscInt n_neighs, *neighs, *n_shared, **shared; 6981e7931f94SStefano Zampini PetscMPIInt size, rank, color; 698252e5ac9dSStefano Zampini PetscInt *xadj, *adjncy; 698352e5ac9dSStefano Zampini PetscInt *adjncy_wgt, *v_wgt, *ranks_send_to_idx; 6984bb360cb4SStefano Zampini PetscInt im_active, active_procs, N, n, i, j, threshold = 2; 698557de7509SStefano Zampini PetscInt void_procs, *procs_candidates = NULL; 698627b6a85dSStefano Zampini PetscInt xadj_count, *count; 698727b6a85dSStefano Zampini PetscBool ismatis, use_vwgt = PETSC_FALSE; 698827b6a85dSStefano Zampini PetscSubcomm psubcomm; 698927b6a85dSStefano Zampini MPI_Comm subcomm; 6990a57a6d2fSStefano Zampini 6991e7931f94SStefano Zampini PetscFunctionBegin; 699257de7509SStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 69939566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)mat, MATIS, &ismatis)); 699428b400f6SJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot use %s on a matrix object which is not of type MATIS", PETSC_FUNCTION_NAME); 699557de7509SStefano Zampini PetscValidLogicalCollectiveInt(mat, *n_subdomains, 2); 699657de7509SStefano Zampini PetscValidLogicalCollectiveInt(mat, redprocs, 3); 699763a3b9bcSJacob Faibussowitsch PetscCheck(*n_subdomains > 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Invalid number of subdomains requested %" PetscInt_FMT, *n_subdomains); 699857de7509SStefano Zampini 699957de7509SStefano Zampini if (have_void) *have_void = PETSC_FALSE; 70009566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 70019566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)mat), &rank)); 70029566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(mat, &A)); 70039566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &n, NULL)); 7004bb360cb4SStefano Zampini im_active = !!n; 70051c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&im_active, &active_procs, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 700657de7509SStefano Zampini void_procs = size - active_procs; 700757de7509SStefano Zampini /* get ranks of of non-active processes in mat communicator */ 700857de7509SStefano Zampini if (void_procs) { 700957de7509SStefano Zampini PetscInt ncand; 701057de7509SStefano Zampini 701157de7509SStefano Zampini if (have_void) *have_void = PETSC_TRUE; 70129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &procs_candidates)); 70139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allgather(&im_active, 1, MPIU_INT, procs_candidates, 1, MPIU_INT, PetscObjectComm((PetscObject)mat))); 701457de7509SStefano Zampini for (i = 0, ncand = 0; i < size; i++) { 7015ad540459SPierre Jolivet if (!procs_candidates[i]) procs_candidates[ncand++] = i; 701657de7509SStefano Zampini } 701757de7509SStefano Zampini /* force n_subdomains to be not greater that the number of non-active processes */ 701857de7509SStefano Zampini *n_subdomains = PetscMin(void_procs, *n_subdomains); 701957de7509SStefano Zampini } 702057de7509SStefano Zampini 7021bb360cb4SStefano Zampini /* number of subdomains requested greater than active processes or matrix size -> just shift the matrix 70229dddd249SSatish Balay number of subdomains requested 1 -> send to rank-0 or first candidate in voids */ 70239566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &N, NULL)); 7024bb360cb4SStefano Zampini if (active_procs < *n_subdomains || *n_subdomains == 1 || N <= *n_subdomains) { 702514f0bfb9SStefano Zampini PetscInt issize, isidx, dest; 702614f0bfb9SStefano Zampini if (*n_subdomains == 1) dest = 0; 702714f0bfb9SStefano Zampini else dest = rank; 702857de7509SStefano Zampini if (im_active) { 702957de7509SStefano Zampini issize = 1; 703057de7509SStefano Zampini if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */ 703114f0bfb9SStefano Zampini isidx = procs_candidates[dest]; 703257de7509SStefano Zampini } else { 703314f0bfb9SStefano Zampini isidx = dest; 703457de7509SStefano Zampini } 703557de7509SStefano Zampini } else { 703657de7509SStefano Zampini issize = 0; 703757de7509SStefano Zampini isidx = -1; 703857de7509SStefano Zampini } 7039bb360cb4SStefano Zampini if (*n_subdomains != 1) *n_subdomains = active_procs; 70409566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), issize, &isidx, PETSC_COPY_VALUES, is_sends)); 70419566063dSJacob Faibussowitsch PetscCall(PetscFree(procs_candidates)); 70423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 704357de7509SStefano Zampini } 70449566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-matis_partitioning_use_vwgt", &use_vwgt, NULL)); 70459566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, NULL, "-matis_partitioning_threshold", &threshold, NULL)); 704627b6a85dSStefano Zampini threshold = PetscMax(threshold, 2); 7047e7931f94SStefano Zampini 7048e7931f94SStefano Zampini /* Get info on mapping */ 70499566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(mat, &mapping, NULL)); 70509566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetInfo(mapping, &n_neighs, &neighs, &n_shared, &shared)); 7051e7931f94SStefano Zampini 7052e7931f94SStefano Zampini /* build local CSR graph of subdomains' connectivity */ 70539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2, &xadj)); 7054e7931f94SStefano Zampini xadj[0] = 0; 7055e7931f94SStefano Zampini xadj[1] = PetscMax(n_neighs - 1, 0); 70569566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(xadj[1], &adjncy)); 70579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(xadj[1], &adjncy_wgt)); 70589566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(n, &count)); 705927b6a85dSStefano Zampini for (i = 1; i < n_neighs; i++) 70609371c9d4SSatish Balay for (j = 0; j < n_shared[i]; j++) count[shared[i][j]] += 1; 7061e7931f94SStefano Zampini 706227b6a85dSStefano Zampini xadj_count = 0; 70632b510759SStefano Zampini for (i = 1; i < n_neighs; i++) { 706427b6a85dSStefano Zampini for (j = 0; j < n_shared[i]; j++) { 706527b6a85dSStefano Zampini if (count[shared[i][j]] < threshold) { 7066d023bfaeSStefano Zampini adjncy[xadj_count] = neighs[i]; 7067d023bfaeSStefano Zampini adjncy_wgt[xadj_count] = n_shared[i]; 7068d023bfaeSStefano Zampini xadj_count++; 706927b6a85dSStefano Zampini break; 707027b6a85dSStefano Zampini } 7071e7931f94SStefano Zampini } 7072e7931f94SStefano Zampini } 7073d023bfaeSStefano Zampini xadj[1] = xadj_count; 70749566063dSJacob Faibussowitsch PetscCall(PetscFree(count)); 70759566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreInfo(mapping, &n_neighs, &neighs, &n_shared, &shared)); 70769566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(xadj[1], adjncy, adjncy_wgt)); 7077e7931f94SStefano Zampini 70789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &ranks_send_to_idx)); 7079e7931f94SStefano Zampini 708027b6a85dSStefano Zampini /* Restrict work on active processes only */ 70819566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(im_active, &color)); 708227b6a85dSStefano Zampini if (void_procs) { 70839566063dSJacob Faibussowitsch PetscCall(PetscSubcommCreate(PetscObjectComm((PetscObject)mat), &psubcomm)); 70849566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetNumber(psubcomm, 2)); /* 2 groups, active process and not active processes */ 70859566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetTypeGeneral(psubcomm, color, rank)); 708627b6a85dSStefano Zampini subcomm = PetscSubcommChild(psubcomm); 708727b6a85dSStefano Zampini } else { 708827b6a85dSStefano Zampini psubcomm = NULL; 708927b6a85dSStefano Zampini subcomm = PetscObjectComm((PetscObject)mat); 709027b6a85dSStefano Zampini } 709127b6a85dSStefano Zampini 709227b6a85dSStefano Zampini v_wgt = NULL; 709327b6a85dSStefano Zampini if (!color) { 70949566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 70959566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 70969566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy_wgt)); 7097c8587f34SStefano Zampini } else { 709852e5ac9dSStefano Zampini Mat subdomain_adj; 709952e5ac9dSStefano Zampini IS new_ranks, new_ranks_contig; 710052e5ac9dSStefano Zampini MatPartitioning partitioner; 710127b6a85dSStefano Zampini PetscInt rstart = 0, rend = 0; 710252e5ac9dSStefano Zampini PetscInt *is_indices, *oldranks; 710357de7509SStefano Zampini PetscMPIInt size; 7104b0c7d250SStefano Zampini PetscBool aggregate; 7105b0c7d250SStefano Zampini 71069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(subcomm, &size)); 710727b6a85dSStefano Zampini if (void_procs) { 710827b6a85dSStefano Zampini PetscInt prank = rank; 71099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &oldranks)); 71109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allgather(&prank, 1, MPIU_INT, oldranks, 1, MPIU_INT, subcomm)); 711148a46eb9SPierre Jolivet for (i = 0; i < xadj[1]; i++) PetscCall(PetscFindInt(adjncy[i], size, oldranks, &adjncy[i])); 71129566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(xadj[1], adjncy, adjncy_wgt)); 711327b6a85dSStefano Zampini } else { 711427b6a85dSStefano Zampini oldranks = NULL; 711527b6a85dSStefano Zampini } 7116b0c7d250SStefano Zampini aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE); 711727b6a85dSStefano Zampini if (aggregate) { /* TODO: all this part could be made more efficient */ 7118b0c7d250SStefano Zampini PetscInt lrows, row, ncols, *cols; 7119b0c7d250SStefano Zampini PetscMPIInt nrank; 7120b0c7d250SStefano Zampini PetscScalar *vals; 7121b0c7d250SStefano Zampini 71229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(subcomm, &nrank)); 7123b0c7d250SStefano Zampini lrows = 0; 7124b0c7d250SStefano Zampini if (nrank < redprocs) { 7125b0c7d250SStefano Zampini lrows = size / redprocs; 7126b0c7d250SStefano Zampini if (nrank < size % redprocs) lrows++; 7127b0c7d250SStefano Zampini } 71289566063dSJacob Faibussowitsch PetscCall(MatCreateAIJ(subcomm, lrows, lrows, size, size, 50, NULL, 50, NULL, &subdomain_adj)); 71299566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(subdomain_adj, &rstart, &rend)); 71309566063dSJacob Faibussowitsch PetscCall(MatSetOption(subdomain_adj, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_FALSE)); 71319566063dSJacob Faibussowitsch PetscCall(MatSetOption(subdomain_adj, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 7132b0c7d250SStefano Zampini row = nrank; 7133b0c7d250SStefano Zampini ncols = xadj[1] - xadj[0]; 7134b0c7d250SStefano Zampini cols = adjncy; 71359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncols, &vals)); 7136b0c7d250SStefano Zampini for (i = 0; i < ncols; i++) vals[i] = adjncy_wgt[i]; 71379566063dSJacob Faibussowitsch PetscCall(MatSetValues(subdomain_adj, 1, &row, ncols, cols, vals, INSERT_VALUES)); 71389566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(subdomain_adj, MAT_FINAL_ASSEMBLY)); 71399566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(subdomain_adj, MAT_FINAL_ASSEMBLY)); 71409566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 71419566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 71429566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy_wgt)); 71439566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 714427b6a85dSStefano Zampini if (use_vwgt) { 714527b6a85dSStefano Zampini Vec v; 714627b6a85dSStefano Zampini const PetscScalar *array; 714727b6a85dSStefano Zampini PetscInt nl; 714827b6a85dSStefano Zampini 71499566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(subdomain_adj, &v, NULL)); 71509566063dSJacob Faibussowitsch PetscCall(VecSetValue(v, row, (PetscScalar)n, INSERT_VALUES)); 71519566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(v)); 71529566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(v)); 71539566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &nl)); 71549566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &array)); 71559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl, &v_wgt)); 715622db5ddcSStefano Zampini for (i = 0; i < nl; i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]); 71579566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &array)); 71589566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 715927b6a85dSStefano Zampini } 7160b0c7d250SStefano Zampini } else { 71619566063dSJacob Faibussowitsch PetscCall(MatCreateMPIAdj(subcomm, 1, (PetscInt)size, xadj, adjncy, adjncy_wgt, &subdomain_adj)); 716227b6a85dSStefano Zampini if (use_vwgt) { 71639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &v_wgt)); 7164bb360cb4SStefano Zampini v_wgt[0] = n; 716527b6a85dSStefano Zampini } 7166b0c7d250SStefano Zampini } 71679566063dSJacob Faibussowitsch /* PetscCall(MatView(subdomain_adj,0)); */ 7168e7931f94SStefano Zampini 7169e7931f94SStefano Zampini /* Partition */ 71709566063dSJacob Faibussowitsch PetscCall(MatPartitioningCreate(subcomm, &partitioner)); 7171ce64c636SStefano Zampini #if defined(PETSC_HAVE_PTSCOTCH) 71729566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetType(partitioner, MATPARTITIONINGPTSCOTCH)); 7173ce64c636SStefano Zampini #elif defined(PETSC_HAVE_PARMETIS) 71749566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetType(partitioner, MATPARTITIONINGPARMETIS)); 7175ce64c636SStefano Zampini #else 71769566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetType(partitioner, MATPARTITIONINGAVERAGE)); 7177ce64c636SStefano Zampini #endif 71789566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetAdjacency(partitioner, subdomain_adj)); 71791baa6e33SBarry Smith if (v_wgt) PetscCall(MatPartitioningSetVertexWeights(partitioner, v_wgt)); 718057de7509SStefano Zampini *n_subdomains = PetscMin((PetscInt)size, *n_subdomains); 71819566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetNParts(partitioner, *n_subdomains)); 71829566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetFromOptions(partitioner)); 71839566063dSJacob Faibussowitsch PetscCall(MatPartitioningApply(partitioner, &new_ranks)); 71849566063dSJacob Faibussowitsch /* PetscCall(MatPartitioningView(partitioner,0)); */ 7185e7931f94SStefano Zampini 718652e5ac9dSStefano Zampini /* renumber new_ranks to avoid "holes" in new set of processors */ 71879566063dSJacob Faibussowitsch PetscCall(ISRenumber(new_ranks, NULL, NULL, &new_ranks_contig)); 71889566063dSJacob Faibussowitsch PetscCall(ISDestroy(&new_ranks)); 71899566063dSJacob Faibussowitsch PetscCall(ISGetIndices(new_ranks_contig, (const PetscInt **)&is_indices)); 719057de7509SStefano Zampini if (!aggregate) { 719157de7509SStefano Zampini if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */ 71926bdcaf15SBarry Smith PetscAssert(oldranks, PETSC_COMM_SELF, PETSC_ERR_PLIB, "This should not happen"); 719357de7509SStefano Zampini ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]]; 719427b6a85dSStefano Zampini } else if (oldranks) { 7195b0c7d250SStefano Zampini ranks_send_to_idx[0] = oldranks[is_indices[0]]; 719627b6a85dSStefano Zampini } else { 719727b6a85dSStefano Zampini ranks_send_to_idx[0] = is_indices[0]; 719857de7509SStefano Zampini } 719928143c3dSStefano Zampini } else { 72007fb8a5e4SKarl Rupp PetscInt idx = 0; 7201b0c7d250SStefano Zampini PetscMPIInt tag; 7202b0c7d250SStefano Zampini MPI_Request *reqs; 7203b0c7d250SStefano Zampini 72049566063dSJacob Faibussowitsch PetscCall(PetscObjectGetNewTag((PetscObject)subdomain_adj, &tag)); 72059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rend - rstart, &reqs)); 720648a46eb9SPierre Jolivet for (i = rstart; i < rend; i++) PetscCallMPI(MPI_Isend(is_indices + i - rstart, 1, MPIU_INT, i, tag, subcomm, &reqs[i - rstart])); 72079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Recv(&idx, 1, MPIU_INT, MPI_ANY_SOURCE, tag, subcomm, MPI_STATUS_IGNORE)); 72089566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(rend - rstart, reqs, MPI_STATUSES_IGNORE)); 72099566063dSJacob Faibussowitsch PetscCall(PetscFree(reqs)); 721057de7509SStefano Zampini if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */ 72116bdcaf15SBarry Smith PetscAssert(oldranks, PETSC_COMM_SELF, PETSC_ERR_PLIB, "This should not happen"); 72127fb8a5e4SKarl Rupp ranks_send_to_idx[0] = procs_candidates[oldranks[idx]]; 721327b6a85dSStefano Zampini } else if (oldranks) { 72147fb8a5e4SKarl Rupp ranks_send_to_idx[0] = oldranks[idx]; 721527b6a85dSStefano Zampini } else { 72167fb8a5e4SKarl Rupp ranks_send_to_idx[0] = idx; 721728143c3dSStefano Zampini } 721857de7509SStefano Zampini } 72199566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(new_ranks_contig, (const PetscInt **)&is_indices)); 7220e7931f94SStefano Zampini /* clean up */ 72219566063dSJacob Faibussowitsch PetscCall(PetscFree(oldranks)); 72229566063dSJacob Faibussowitsch PetscCall(ISDestroy(&new_ranks_contig)); 72239566063dSJacob Faibussowitsch PetscCall(MatDestroy(&subdomain_adj)); 72249566063dSJacob Faibussowitsch PetscCall(MatPartitioningDestroy(&partitioner)); 7225e7931f94SStefano Zampini } 72269566063dSJacob Faibussowitsch PetscCall(PetscSubcommDestroy(&psubcomm)); 72279566063dSJacob Faibussowitsch PetscCall(PetscFree(procs_candidates)); 7228e7931f94SStefano Zampini 7229e7931f94SStefano Zampini /* assemble parallel IS for sends */ 7230e7931f94SStefano Zampini i = 1; 723127b6a85dSStefano Zampini if (!color) i = 0; 72329566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), i, ranks_send_to_idx, PETSC_OWN_POINTER, is_sends)); 72333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7234e7931f94SStefano Zampini } 7235e7931f94SStefano Zampini 72369371c9d4SSatish Balay typedef enum { 72379371c9d4SSatish Balay MATDENSE_PRIVATE = 0, 72389371c9d4SSatish Balay MATAIJ_PRIVATE, 72399371c9d4SSatish Balay MATBAIJ_PRIVATE, 72409371c9d4SSatish Balay MATSBAIJ_PRIVATE 72419371c9d4SSatish Balay } MatTypePrivate; 7242e7931f94SStefano Zampini 7243d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCMatISSubassemble(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[]) 7244d71ae5a4SJacob Faibussowitsch { 724570cf5478SStefano Zampini Mat local_mat; 7246e7931f94SStefano Zampini IS is_sends_internal; 72479d30be91SStefano Zampini PetscInt rows, cols, new_local_rows; 72481ae86dd6SStefano Zampini PetscInt i, bs, buf_size_idxs, buf_size_idxs_is, buf_size_vals, buf_size_vecs; 72499d30be91SStefano Zampini PetscBool ismatis, isdense, newisdense, destroy_mat; 7250e7931f94SStefano Zampini ISLocalToGlobalMapping l2gmap; 7251e7931f94SStefano Zampini PetscInt *l2gmap_indices; 7252e7931f94SStefano Zampini const PetscInt *is_indices; 7253e7931f94SStefano Zampini MatType new_local_type; 7254e7931f94SStefano Zampini /* buffers */ 7255e7931f94SStefano Zampini PetscInt *ptr_idxs, *send_buffer_idxs, *recv_buffer_idxs; 725628143c3dSStefano Zampini PetscInt *ptr_idxs_is, *send_buffer_idxs_is, *recv_buffer_idxs_is; 72579d30be91SStefano Zampini PetscInt *recv_buffer_idxs_local; 72581683a169SBarry Smith PetscScalar *ptr_vals, *recv_buffer_vals; 72591683a169SBarry Smith const PetscScalar *send_buffer_vals; 72601ae86dd6SStefano Zampini PetscScalar *ptr_vecs, *send_buffer_vecs, *recv_buffer_vecs; 7261e7931f94SStefano Zampini /* MPI */ 726228143c3dSStefano Zampini MPI_Comm comm, comm_n; 726328143c3dSStefano Zampini PetscSubcomm subcomm; 7264e569e4e1SStefano Zampini PetscMPIInt n_sends, n_recvs, size; 726528143c3dSStefano Zampini PetscMPIInt *iflags, *ilengths_idxs, *ilengths_vals, *ilengths_idxs_is; 726628143c3dSStefano Zampini PetscMPIInt *onodes, *onodes_is, *olengths_idxs, *olengths_idxs_is, *olengths_vals; 72671ae86dd6SStefano Zampini PetscMPIInt len, tag_idxs, tag_idxs_is, tag_vals, tag_vecs, source_dest; 72681ae86dd6SStefano Zampini MPI_Request *send_req_idxs, *send_req_idxs_is, *send_req_vals, *send_req_vecs; 72691ae86dd6SStefano Zampini MPI_Request *recv_req_idxs, *recv_req_idxs_is, *recv_req_vals, *recv_req_vecs; 7270e7931f94SStefano Zampini 7271e7931f94SStefano Zampini PetscFunctionBegin; 727257de7509SStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 72739566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)mat, MATIS, &ismatis)); 72745f80ce2aSJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot use %s on a matrix object which is not of type MATIS", PETSC_FUNCTION_NAME); 727557de7509SStefano Zampini PetscValidLogicalCollectiveInt(mat, n_subdomains, 3); 727657de7509SStefano Zampini PetscValidLogicalCollectiveBool(mat, restrict_comm, 4); 727757de7509SStefano Zampini PetscValidLogicalCollectiveBool(mat, restrict_full, 5); 727857de7509SStefano Zampini PetscValidLogicalCollectiveBool(mat, reuse, 6); 727957de7509SStefano Zampini PetscValidLogicalCollectiveInt(mat, nis, 8); 72801ae86dd6SStefano Zampini PetscValidLogicalCollectiveInt(mat, nvecs, 10); 72811ae86dd6SStefano Zampini if (nvecs) { 728208401ef6SPierre Jolivet PetscCheck(nvecs <= 1, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Just 1 vector supported"); 72831ae86dd6SStefano Zampini PetscValidHeaderSpecific(nnsp_vec[0], VEC_CLASSID, 11); 72841ae86dd6SStefano Zampini } 728557de7509SStefano Zampini /* further checks */ 72869566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(mat, &local_mat)); 72879566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)local_mat, MATSEQDENSE, &isdense)); 72885f80ce2aSJacob Faibussowitsch PetscCheck(isdense, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE"); 72899566063dSJacob Faibussowitsch PetscCall(MatGetSize(local_mat, &rows, &cols)); 72905f80ce2aSJacob Faibussowitsch PetscCheck(rows == cols, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Local MATIS matrices should be square"); 729157de7509SStefano Zampini if (reuse && *mat_n) { 729270cf5478SStefano Zampini PetscInt mrows, mcols, mnrows, mncols; 729357de7509SStefano Zampini PetscValidHeaderSpecific(*mat_n, MAT_CLASSID, 7); 72949566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)*mat_n, MATIS, &ismatis)); 72955f80ce2aSJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)*mat_n), PETSC_ERR_SUP, "Cannot reuse a matrix which is not of type MATIS"); 72969566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &mrows, &mcols)); 72979566063dSJacob Faibussowitsch PetscCall(MatGetSize(*mat_n, &mnrows, &mncols)); 729863a3b9bcSJacob Faibussowitsch PetscCheck(mrows == mnrows, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix! Wrong number of rows %" PetscInt_FMT " != %" PetscInt_FMT, mrows, mnrows); 729963a3b9bcSJacob Faibussowitsch PetscCheck(mcols == mncols, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix! Wrong number of cols %" PetscInt_FMT " != %" PetscInt_FMT, mcols, mncols); 730070cf5478SStefano Zampini } 73019566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(local_mat, &bs)); 7302064a246eSJacob Faibussowitsch PetscValidLogicalCollectiveInt(mat, bs, 1); 730357de7509SStefano Zampini 7304e7931f94SStefano Zampini /* prepare IS for sending if not provided */ 7305e7931f94SStefano Zampini if (!is_sends) { 73065f80ce2aSJacob Faibussowitsch PetscCheck(n_subdomains, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "You should specify either an IS or a target number of subdomains"); 73079566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISGetSubassemblingPattern(mat, &n_subdomains, 0, &is_sends_internal, NULL)); 7308c8587f34SStefano Zampini } else { 73099566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is_sends)); 7310e7931f94SStefano Zampini is_sends_internal = is_sends; 7311c8587f34SStefano Zampini } 7312e7931f94SStefano Zampini 7313e7931f94SStefano Zampini /* get comm */ 73149566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7315e7931f94SStefano Zampini 7316e7931f94SStefano Zampini /* compute number of sends */ 73179566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is_sends_internal, &i)); 73189566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(i, &n_sends)); 7319e7931f94SStefano Zampini 7320e7931f94SStefano Zampini /* compute number of receives */ 73219566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 73229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &iflags)); 73239566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(iflags, size)); 73249566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is_sends_internal, &is_indices)); 7325e7931f94SStefano Zampini for (i = 0; i < n_sends; i++) iflags[is_indices[i]] = 1; 73269566063dSJacob Faibussowitsch PetscCall(PetscGatherNumberOfMessages(comm, iflags, NULL, &n_recvs)); 73279566063dSJacob Faibussowitsch PetscCall(PetscFree(iflags)); 7328e7931f94SStefano Zampini 732928143c3dSStefano Zampini /* restrict comm if requested */ 73300a545947SLisandro Dalcin subcomm = NULL; 733128143c3dSStefano Zampini destroy_mat = PETSC_FALSE; 733228143c3dSStefano Zampini if (restrict_comm) { 7333779c1cceSStefano Zampini PetscMPIInt color, subcommsize; 7334779c1cceSStefano Zampini 733528143c3dSStefano Zampini color = 0; 733653a05cb3SStefano Zampini if (restrict_full) { 73376aad120cSJose E. Roman if (!n_recvs) color = 1; /* processes not receiving anything will not participate in new comm (full restriction) */ 733853a05cb3SStefano Zampini } else { 73396aad120cSJose E. Roman if (!n_recvs && n_sends) color = 1; /* just those processes that are sending but not receiving anything will not participate in new comm */ 734053a05cb3SStefano Zampini } 73411c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&color, &subcommsize, 1, MPI_INT, MPI_SUM, comm)); 7342e569e4e1SStefano Zampini subcommsize = size - subcommsize; 734328143c3dSStefano Zampini /* check if reuse has been requested */ 734457de7509SStefano Zampini if (reuse) { 734528143c3dSStefano Zampini if (*mat_n) { 734628143c3dSStefano Zampini PetscMPIInt subcommsize2; 73479566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n), &subcommsize2)); 73485f80ce2aSJacob Faibussowitsch PetscCheck(subcommsize == subcommsize2, PetscObjectComm((PetscObject)*mat_n), PETSC_ERR_PLIB, "Cannot reuse matrix! wrong subcomm size %d != %d", subcommsize, subcommsize2); 734928143c3dSStefano Zampini comm_n = PetscObjectComm((PetscObject)*mat_n); 735028143c3dSStefano Zampini } else { 735128143c3dSStefano Zampini comm_n = PETSC_COMM_SELF; 735228143c3dSStefano Zampini } 735328143c3dSStefano Zampini } else { /* MAT_INITIAL_MATRIX */ 7354779c1cceSStefano Zampini PetscMPIInt rank; 7355779c1cceSStefano Zampini 73569566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 73579566063dSJacob Faibussowitsch PetscCall(PetscSubcommCreate(comm, &subcomm)); 73589566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetNumber(subcomm, 2)); 73599566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetTypeGeneral(subcomm, color, rank)); 7360306c2d5bSBarry Smith comm_n = PetscSubcommChild(subcomm); 736128143c3dSStefano Zampini } 736228143c3dSStefano Zampini /* flag to destroy *mat_n if not significative */ 736328143c3dSStefano Zampini if (color) destroy_mat = PETSC_TRUE; 736428143c3dSStefano Zampini } else { 736528143c3dSStefano Zampini comm_n = comm; 736628143c3dSStefano Zampini } 736728143c3dSStefano Zampini 7368e7931f94SStefano Zampini /* prepare send/receive buffers */ 73699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &ilengths_idxs)); 73709566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(ilengths_idxs, size)); 73719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &ilengths_vals)); 73729566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(ilengths_vals, size)); 737348a46eb9SPierre Jolivet if (nis) PetscCall(PetscCalloc1(size, &ilengths_idxs_is)); 7374e7931f94SStefano Zampini 737528143c3dSStefano Zampini /* Get data from local matrices */ 7376e432b41dSStefano Zampini PetscCheck(isdense, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Subassembling of AIJ local matrices not yet implemented"); 7377e7931f94SStefano Zampini /* TODO: See below some guidelines on how to prepare the local buffers */ 7378e7931f94SStefano Zampini /* 7379e7931f94SStefano Zampini send_buffer_vals should contain the raw values of the local matrix 7380e7931f94SStefano Zampini send_buffer_idxs should contain: 7381e7931f94SStefano Zampini - MatType_PRIVATE type 7382e7931f94SStefano Zampini - PetscInt size_of_l2gmap 7383e7931f94SStefano Zampini - PetscInt global_row_indices[size_of_l2gmap] 7384e7931f94SStefano Zampini - PetscInt all_other_info_which_is_needed_to_compute_preallocation_and_set_values 7385e7931f94SStefano Zampini */ 7386e432b41dSStefano Zampini { 7387e432b41dSStefano Zampini ISLocalToGlobalMapping mapping; 7388e432b41dSStefano Zampini 73899566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(mat, &mapping, NULL)); 73909566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(local_mat, &send_buffer_vals)); 73919566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(mapping, &i)); 73929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(i + 2, &send_buffer_idxs)); 7393e7931f94SStefano Zampini send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE; 7394e7931f94SStefano Zampini send_buffer_idxs[1] = i; 73959566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(mapping, (const PetscInt **)&ptr_idxs)); 73969566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&send_buffer_idxs[2], ptr_idxs, i)); 73979566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(mapping, (const PetscInt **)&ptr_idxs)); 73989566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(i, &len)); 7399e7931f94SStefano Zampini for (i = 0; i < n_sends; i++) { 7400e7931f94SStefano Zampini ilengths_vals[is_indices[i]] = len * len; 7401e7931f94SStefano Zampini ilengths_idxs[is_indices[i]] = len + 2; 7402c8587f34SStefano Zampini } 7403c8587f34SStefano Zampini } 74049566063dSJacob Faibussowitsch PetscCall(PetscGatherMessageLengths2(comm, n_sends, n_recvs, ilengths_idxs, ilengths_vals, &onodes, &olengths_idxs, &olengths_vals)); 740528143c3dSStefano Zampini /* additional is (if any) */ 740628143c3dSStefano Zampini if (nis) { 740728143c3dSStefano Zampini PetscMPIInt psum; 740828143c3dSStefano Zampini PetscInt j; 740928143c3dSStefano Zampini for (j = 0, psum = 0; j < nis; j++) { 741028143c3dSStefano Zampini PetscInt plen; 74119566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isarray[j], &plen)); 74129566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(plen, &len)); 74136aad120cSJose E. Roman psum += len + 1; /* indices + length */ 741428143c3dSStefano Zampini } 74159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(psum, &send_buffer_idxs_is)); 741628143c3dSStefano Zampini for (j = 0, psum = 0; j < nis; j++) { 741728143c3dSStefano Zampini PetscInt plen; 741828143c3dSStefano Zampini const PetscInt *is_array_idxs; 74199566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isarray[j], &plen)); 742028143c3dSStefano Zampini send_buffer_idxs_is[psum] = plen; 74219566063dSJacob Faibussowitsch PetscCall(ISGetIndices(isarray[j], &is_array_idxs)); 74229566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&send_buffer_idxs_is[psum + 1], is_array_idxs, plen)); 74239566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(isarray[j], &is_array_idxs)); 74246aad120cSJose E. Roman psum += plen + 1; /* indices + length */ 742528143c3dSStefano Zampini } 7426ad540459SPierre Jolivet for (i = 0; i < n_sends; i++) ilengths_idxs_is[is_indices[i]] = psum; 74279566063dSJacob Faibussowitsch PetscCall(PetscGatherMessageLengths(comm, n_sends, n_recvs, ilengths_idxs_is, &onodes_is, &olengths_idxs_is)); 742828143c3dSStefano Zampini } 74299566063dSJacob Faibussowitsch PetscCall(MatISRestoreLocalMat(mat, &local_mat)); 743028143c3dSStefano Zampini 7431e7931f94SStefano Zampini buf_size_idxs = 0; 7432e7931f94SStefano Zampini buf_size_vals = 0; 743328143c3dSStefano Zampini buf_size_idxs_is = 0; 74341ae86dd6SStefano Zampini buf_size_vecs = 0; 7435e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 7436e7931f94SStefano Zampini buf_size_idxs += (PetscInt)olengths_idxs[i]; 7437e7931f94SStefano Zampini buf_size_vals += (PetscInt)olengths_vals[i]; 743828143c3dSStefano Zampini if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i]; 74391ae86dd6SStefano Zampini if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i]; 7440e7931f94SStefano Zampini } 74419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(buf_size_idxs, &recv_buffer_idxs)); 74429566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(buf_size_vals, &recv_buffer_vals)); 74439566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(buf_size_idxs_is, &recv_buffer_idxs_is)); 74449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(buf_size_vecs, &recv_buffer_vecs)); 7445e7931f94SStefano Zampini 7446e7931f94SStefano Zampini /* get new tags for clean communications */ 74479566063dSJacob Faibussowitsch PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag_idxs)); 74489566063dSJacob Faibussowitsch PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag_vals)); 74499566063dSJacob Faibussowitsch PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag_idxs_is)); 74509566063dSJacob Faibussowitsch PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag_vecs)); 7451e7931f94SStefano Zampini 7452e7931f94SStefano Zampini /* allocate for requests */ 74539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_sends, &send_req_idxs)); 74549566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_sends, &send_req_vals)); 74559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_sends, &send_req_idxs_is)); 74569566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_sends, &send_req_vecs)); 74579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_recvs, &recv_req_idxs)); 74589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_recvs, &recv_req_vals)); 74599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_recvs, &recv_req_idxs_is)); 74609566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_recvs, &recv_req_vecs)); 7461e7931f94SStefano Zampini 7462e7931f94SStefano Zampini /* communications */ 7463e7931f94SStefano Zampini ptr_idxs = recv_buffer_idxs; 7464e7931f94SStefano Zampini ptr_vals = recv_buffer_vals; 746528143c3dSStefano Zampini ptr_idxs_is = recv_buffer_idxs_is; 74661ae86dd6SStefano Zampini ptr_vecs = recv_buffer_vecs; 7467e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 7468e7931f94SStefano Zampini source_dest = onodes[i]; 74699566063dSJacob Faibussowitsch PetscCallMPI(MPI_Irecv(ptr_idxs, olengths_idxs[i], MPIU_INT, source_dest, tag_idxs, comm, &recv_req_idxs[i])); 74709566063dSJacob Faibussowitsch PetscCallMPI(MPI_Irecv(ptr_vals, olengths_vals[i], MPIU_SCALAR, source_dest, tag_vals, comm, &recv_req_vals[i])); 7471e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 7472e7931f94SStefano Zampini ptr_vals += olengths_vals[i]; 747328143c3dSStefano Zampini if (nis) { 747457de7509SStefano Zampini source_dest = onodes_is[i]; 74759566063dSJacob Faibussowitsch PetscCallMPI(MPI_Irecv(ptr_idxs_is, olengths_idxs_is[i], MPIU_INT, source_dest, tag_idxs_is, comm, &recv_req_idxs_is[i])); 747628143c3dSStefano Zampini ptr_idxs_is += olengths_idxs_is[i]; 747728143c3dSStefano Zampini } 74781ae86dd6SStefano Zampini if (nvecs) { 74791ae86dd6SStefano Zampini source_dest = onodes[i]; 74809566063dSJacob Faibussowitsch PetscCallMPI(MPI_Irecv(ptr_vecs, olengths_idxs[i] - 2, MPIU_SCALAR, source_dest, tag_vecs, comm, &recv_req_vecs[i])); 74811ae86dd6SStefano Zampini ptr_vecs += olengths_idxs[i] - 2; 74821ae86dd6SStefano Zampini } 7483e7931f94SStefano Zampini } 7484e7931f94SStefano Zampini for (i = 0; i < n_sends; i++) { 74859566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(is_indices[i], &source_dest)); 74869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Isend(send_buffer_idxs, ilengths_idxs[source_dest], MPIU_INT, source_dest, tag_idxs, comm, &send_req_idxs[i])); 74879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Isend((PetscScalar *)send_buffer_vals, ilengths_vals[source_dest], MPIU_SCALAR, source_dest, tag_vals, comm, &send_req_vals[i])); 748848a46eb9SPierre Jolivet if (nis) PetscCallMPI(MPI_Isend(send_buffer_idxs_is, ilengths_idxs_is[source_dest], MPIU_INT, source_dest, tag_idxs_is, comm, &send_req_idxs_is[i])); 74891ae86dd6SStefano Zampini if (nvecs) { 74909566063dSJacob Faibussowitsch PetscCall(VecGetArray(nnsp_vec[0], &send_buffer_vecs)); 74919566063dSJacob Faibussowitsch PetscCallMPI(MPI_Isend(send_buffer_vecs, ilengths_idxs[source_dest] - 2, MPIU_SCALAR, source_dest, tag_vecs, comm, &send_req_vecs[i])); 74921ae86dd6SStefano Zampini } 7493e7931f94SStefano Zampini } 74949566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is_sends_internal, &is_indices)); 74959566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_sends_internal)); 7496e7931f94SStefano Zampini 7497e7931f94SStefano Zampini /* assemble new l2g map */ 74989566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_recvs, recv_req_idxs, MPI_STATUSES_IGNORE)); 7499e7931f94SStefano Zampini ptr_idxs = recv_buffer_idxs; 75009d30be91SStefano Zampini new_local_rows = 0; 7501e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 75029d30be91SStefano Zampini new_local_rows += *(ptr_idxs + 1); /* second element is the local size of the l2gmap */ 7503e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 7504e7931f94SStefano Zampini } 75059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(new_local_rows, &l2gmap_indices)); 7506e7931f94SStefano Zampini ptr_idxs = recv_buffer_idxs; 75079d30be91SStefano Zampini new_local_rows = 0; 7508e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 75099566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&l2gmap_indices[new_local_rows], ptr_idxs + 2, *(ptr_idxs + 1))); 75109d30be91SStefano Zampini new_local_rows += *(ptr_idxs + 1); /* second element is the local size of the l2gmap */ 7511e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 7512e7931f94SStefano Zampini } 75139566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&new_local_rows, l2gmap_indices)); 75149566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(comm_n, 1, new_local_rows, l2gmap_indices, PETSC_COPY_VALUES, &l2gmap)); 75159566063dSJacob Faibussowitsch PetscCall(PetscFree(l2gmap_indices)); 7516e7931f94SStefano Zampini 7517e7931f94SStefano Zampini /* infer new local matrix type from received local matrices type */ 7518e7931f94SStefano Zampini /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */ 7519e7931f94SStefano 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) */ 7520e7931f94SStefano Zampini if (n_recvs) { 752128143c3dSStefano Zampini MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0]; 7522e7931f94SStefano Zampini ptr_idxs = recv_buffer_idxs; 7523e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 7524e7931f94SStefano Zampini if ((PetscInt)new_local_type_private != *ptr_idxs) { 7525e7931f94SStefano Zampini new_local_type_private = MATAIJ_PRIVATE; 7526e7931f94SStefano Zampini break; 7527e7931f94SStefano Zampini } 7528e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 7529e7931f94SStefano Zampini } 7530e7931f94SStefano Zampini switch (new_local_type_private) { 753128143c3dSStefano Zampini case MATDENSE_PRIVATE: 7532e7931f94SStefano Zampini new_local_type = MATSEQAIJ; 7533e7931f94SStefano Zampini bs = 1; 7534e7931f94SStefano Zampini break; 7535e7931f94SStefano Zampini case MATAIJ_PRIVATE: 7536e7931f94SStefano Zampini new_local_type = MATSEQAIJ; 7537e7931f94SStefano Zampini bs = 1; 7538e7931f94SStefano Zampini break; 7539d71ae5a4SJacob Faibussowitsch case MATBAIJ_PRIVATE: 7540d71ae5a4SJacob Faibussowitsch new_local_type = MATSEQBAIJ; 7541d71ae5a4SJacob Faibussowitsch break; 7542d71ae5a4SJacob Faibussowitsch case MATSBAIJ_PRIVATE: 7543d71ae5a4SJacob Faibussowitsch new_local_type = MATSEQSBAIJ; 7544d71ae5a4SJacob Faibussowitsch break; 7545d71ae5a4SJacob Faibussowitsch default: 7546d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_SUP, "Unsupported private type %d in %s", new_local_type_private, PETSC_FUNCTION_NAME); 7547e7931f94SStefano Zampini } 7548ed8ed4edSstefano_zampini } else { /* by default, new_local_type is seqaij */ 7549ed8ed4edSstefano_zampini new_local_type = MATSEQAIJ; 755028143c3dSStefano Zampini bs = 1; 7551e7931f94SStefano Zampini } 7552e7931f94SStefano Zampini 755370cf5478SStefano Zampini /* create MATIS object if needed */ 755457de7509SStefano Zampini if (!reuse) { 75559566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &rows, &cols)); 75569566063dSJacob Faibussowitsch PetscCall(MatCreateIS(comm_n, bs, PETSC_DECIDE, PETSC_DECIDE, rows, cols, l2gmap, l2gmap, mat_n)); 755770cf5478SStefano Zampini } else { 755870cf5478SStefano Zampini /* it also destroys the local matrices */ 755957de7509SStefano Zampini if (*mat_n) { 75609566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*mat_n, l2gmap, l2gmap)); 756157de7509SStefano Zampini } else { /* this is a fake object */ 75629566063dSJacob Faibussowitsch PetscCall(MatCreateIS(comm_n, bs, PETSC_DECIDE, PETSC_DECIDE, rows, cols, l2gmap, l2gmap, mat_n)); 756357de7509SStefano Zampini } 756470cf5478SStefano Zampini } 75659566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*mat_n, &local_mat)); 75669566063dSJacob Faibussowitsch PetscCall(MatSetType(local_mat, new_local_type)); 75679d30be91SStefano Zampini 75689566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_recvs, recv_req_vals, MPI_STATUSES_IGNORE)); 75699d30be91SStefano Zampini 75709d30be91SStefano Zampini /* Global to local map of received indices */ 75719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(buf_size_idxs, &recv_buffer_idxs_local)); /* needed for values insertion */ 75729566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(l2gmap, IS_GTOLM_MASK, buf_size_idxs, recv_buffer_idxs, &i, recv_buffer_idxs_local)); 75739566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&l2gmap)); 75749d30be91SStefano Zampini 75759d30be91SStefano Zampini /* restore attributes -> type of incoming data and its size */ 75769d30be91SStefano Zampini buf_size_idxs = 0; 75779d30be91SStefano Zampini for (i = 0; i < n_recvs; i++) { 75789d30be91SStefano Zampini recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs]; 75799d30be91SStefano Zampini recv_buffer_idxs_local[buf_size_idxs + 1] = recv_buffer_idxs[buf_size_idxs + 1]; 75809d30be91SStefano Zampini buf_size_idxs += (PetscInt)olengths_idxs[i]; 75819d30be91SStefano Zampini } 75829566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_buffer_idxs)); 75839d30be91SStefano Zampini 75849d30be91SStefano Zampini /* set preallocation */ 75859566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)local_mat, MATSEQDENSE, &newisdense)); 75869d30be91SStefano Zampini if (!newisdense) { 75870a545947SLisandro Dalcin PetscInt *new_local_nnz = NULL; 75889d30be91SStefano Zampini 75899d30be91SStefano Zampini ptr_idxs = recv_buffer_idxs_local; 759048a46eb9SPierre Jolivet if (n_recvs) PetscCall(PetscCalloc1(new_local_rows, &new_local_nnz)); 75919d30be91SStefano Zampini for (i = 0; i < n_recvs; i++) { 75929d30be91SStefano Zampini PetscInt j; 75939d30be91SStefano Zampini if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */ 7594ad540459SPierre Jolivet for (j = 0; j < *(ptr_idxs + 1); j++) new_local_nnz[*(ptr_idxs + 2 + j)] += *(ptr_idxs + 1); 75959d30be91SStefano Zampini } else { 75969d30be91SStefano Zampini /* TODO */ 75979d30be91SStefano Zampini } 75989d30be91SStefano Zampini ptr_idxs += olengths_idxs[i]; 75999d30be91SStefano Zampini } 76009d30be91SStefano Zampini if (new_local_nnz) { 76019d30be91SStefano Zampini for (i = 0; i < new_local_rows; i++) new_local_nnz[i] = PetscMin(new_local_nnz[i], new_local_rows); 76029566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(local_mat, 0, new_local_nnz)); 76039d30be91SStefano Zampini for (i = 0; i < new_local_rows; i++) new_local_nnz[i] /= bs; 76049566063dSJacob Faibussowitsch PetscCall(MatSeqBAIJSetPreallocation(local_mat, bs, 0, new_local_nnz)); 76059d30be91SStefano Zampini for (i = 0; i < new_local_rows; i++) new_local_nnz[i] = PetscMax(new_local_nnz[i] - i, 0); 76069566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(local_mat, bs, 0, new_local_nnz)); 76079d30be91SStefano Zampini } else { 76089566063dSJacob Faibussowitsch PetscCall(MatSetUp(local_mat)); 76099d30be91SStefano Zampini } 76109566063dSJacob Faibussowitsch PetscCall(PetscFree(new_local_nnz)); 76119d30be91SStefano Zampini } else { 76129566063dSJacob Faibussowitsch PetscCall(MatSetUp(local_mat)); 76139d30be91SStefano Zampini } 7614e7931f94SStefano Zampini 7615e7931f94SStefano Zampini /* set values */ 7616e7931f94SStefano Zampini ptr_vals = recv_buffer_vals; 76179d30be91SStefano Zampini ptr_idxs = recv_buffer_idxs_local; 7618e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 7619e7931f94SStefano Zampini if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */ 76209566063dSJacob Faibussowitsch PetscCall(MatSetOption(local_mat, MAT_ROW_ORIENTED, PETSC_FALSE)); 76219566063dSJacob Faibussowitsch PetscCall(MatSetValues(local_mat, *(ptr_idxs + 1), ptr_idxs + 2, *(ptr_idxs + 1), ptr_idxs + 2, ptr_vals, ADD_VALUES)); 76229566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(local_mat, MAT_FLUSH_ASSEMBLY)); 76239566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(local_mat, MAT_FLUSH_ASSEMBLY)); 76249566063dSJacob Faibussowitsch PetscCall(MatSetOption(local_mat, MAT_ROW_ORIENTED, PETSC_TRUE)); 762528143c3dSStefano Zampini } else { 762628143c3dSStefano Zampini /* TODO */ 7627e7931f94SStefano Zampini } 7628e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 7629e7931f94SStefano Zampini ptr_vals += olengths_vals[i]; 7630e7931f94SStefano Zampini } 76319566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(local_mat, MAT_FINAL_ASSEMBLY)); 76329566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(local_mat, MAT_FINAL_ASSEMBLY)); 76339566063dSJacob Faibussowitsch PetscCall(MatISRestoreLocalMat(*mat_n, &local_mat)); 76349566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat_n, MAT_FINAL_ASSEMBLY)); 76359566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat_n, MAT_FINAL_ASSEMBLY)); 76369566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_buffer_vals)); 7637e7931f94SStefano Zampini 7638dfd14d43SStefano Zampini #if 0 763928143c3dSStefano Zampini if (!restrict_comm) { /* check */ 7640e7931f94SStefano Zampini Vec lvec,rvec; 7641e7931f94SStefano Zampini PetscReal infty_error; 7642e7931f94SStefano Zampini 76439566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(mat,&rvec,&lvec)); 76449566063dSJacob Faibussowitsch PetscCall(VecSetRandom(rvec,NULL)); 76459566063dSJacob Faibussowitsch PetscCall(MatMult(mat,rvec,lvec)); 76469566063dSJacob Faibussowitsch PetscCall(VecScale(lvec,-1.0)); 76479566063dSJacob Faibussowitsch PetscCall(MatMultAdd(*mat_n,rvec,lvec,lvec)); 76489566063dSJacob Faibussowitsch PetscCall(VecNorm(lvec,NORM_INFINITY,&infty_error)); 76499566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error)); 76509566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rvec)); 76519566063dSJacob Faibussowitsch PetscCall(VecDestroy(&lvec)); 7652e7931f94SStefano Zampini } 765328143c3dSStefano Zampini #endif 7654e7931f94SStefano Zampini 765528143c3dSStefano Zampini /* assemble new additional is (if any) */ 765628143c3dSStefano Zampini if (nis) { 765728143c3dSStefano Zampini PetscInt **temp_idxs, *count_is, j, psum; 765828143c3dSStefano Zampini 76599566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_recvs, recv_req_idxs_is, MPI_STATUSES_IGNORE)); 76609566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nis, &count_is)); 766128143c3dSStefano Zampini ptr_idxs = recv_buffer_idxs_is; 766228143c3dSStefano Zampini psum = 0; 766328143c3dSStefano Zampini for (i = 0; i < n_recvs; i++) { 766428143c3dSStefano Zampini for (j = 0; j < nis; j++) { 766528143c3dSStefano Zampini PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */ 766628143c3dSStefano Zampini count_is[j] += plen; /* increment counting of buffer for j-th IS */ 766728143c3dSStefano Zampini psum += plen; 766828143c3dSStefano Zampini ptr_idxs += plen + 1; /* shift pointer to received data */ 766928143c3dSStefano Zampini } 767028143c3dSStefano Zampini } 76719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nis, &temp_idxs)); 76729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(psum, &temp_idxs[0])); 7673ad540459SPierre Jolivet for (i = 1; i < nis; i++) temp_idxs[i] = temp_idxs[i - 1] + count_is[i - 1]; 76749566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(count_is, nis)); 767528143c3dSStefano Zampini ptr_idxs = recv_buffer_idxs_is; 767628143c3dSStefano Zampini for (i = 0; i < n_recvs; i++) { 767728143c3dSStefano Zampini for (j = 0; j < nis; j++) { 767828143c3dSStefano Zampini PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */ 76799566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&temp_idxs[j][count_is[j]], ptr_idxs + 1, plen)); 768028143c3dSStefano Zampini count_is[j] += plen; /* increment starting point of buffer for j-th IS */ 768128143c3dSStefano Zampini ptr_idxs += plen + 1; /* shift pointer to received data */ 768228143c3dSStefano Zampini } 768328143c3dSStefano Zampini } 768428143c3dSStefano Zampini for (i = 0; i < nis; i++) { 76859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isarray[i])); 76869566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&count_is[i], temp_idxs[i])); 76879566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm_n, count_is[i], temp_idxs[i], PETSC_COPY_VALUES, &isarray[i])); 768828143c3dSStefano Zampini } 76899566063dSJacob Faibussowitsch PetscCall(PetscFree(count_is)); 76909566063dSJacob Faibussowitsch PetscCall(PetscFree(temp_idxs[0])); 76919566063dSJacob Faibussowitsch PetscCall(PetscFree(temp_idxs)); 769228143c3dSStefano Zampini } 7693e7931f94SStefano Zampini /* free workspace */ 76949566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_buffer_idxs_is)); 76959566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_sends, send_req_idxs, MPI_STATUSES_IGNORE)); 76969566063dSJacob Faibussowitsch PetscCall(PetscFree(send_buffer_idxs)); 76979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_sends, send_req_vals, MPI_STATUSES_IGNORE)); 7698e7931f94SStefano Zampini if (isdense) { 76999566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(mat, &local_mat)); 77009566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(local_mat, &send_buffer_vals)); 77019566063dSJacob Faibussowitsch PetscCall(MatISRestoreLocalMat(mat, &local_mat)); 7702e7931f94SStefano Zampini } else { 77039566063dSJacob Faibussowitsch /* PetscCall(PetscFree(send_buffer_vals)); */ 7704e7931f94SStefano Zampini } 770528143c3dSStefano Zampini if (nis) { 77069566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_sends, send_req_idxs_is, MPI_STATUSES_IGNORE)); 77079566063dSJacob Faibussowitsch PetscCall(PetscFree(send_buffer_idxs_is)); 770828143c3dSStefano Zampini } 77091ae86dd6SStefano Zampini 77101ae86dd6SStefano Zampini if (nvecs) { 77119566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_recvs, recv_req_vecs, MPI_STATUSES_IGNORE)); 77129566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_sends, send_req_vecs, MPI_STATUSES_IGNORE)); 77139566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(nnsp_vec[0], &send_buffer_vecs)); 77149566063dSJacob Faibussowitsch PetscCall(VecDestroy(&nnsp_vec[0])); 77159566063dSJacob Faibussowitsch PetscCall(VecCreate(comm_n, &nnsp_vec[0])); 77169566063dSJacob Faibussowitsch PetscCall(VecSetSizes(nnsp_vec[0], new_local_rows, PETSC_DECIDE)); 77179566063dSJacob Faibussowitsch PetscCall(VecSetType(nnsp_vec[0], VECSTANDARD)); 77181ae86dd6SStefano Zampini /* set values */ 77191ae86dd6SStefano Zampini ptr_vals = recv_buffer_vecs; 77201ae86dd6SStefano Zampini ptr_idxs = recv_buffer_idxs_local; 77219566063dSJacob Faibussowitsch PetscCall(VecGetArray(nnsp_vec[0], &send_buffer_vecs)); 77221ae86dd6SStefano Zampini for (i = 0; i < n_recvs; i++) { 77231ae86dd6SStefano Zampini PetscInt j; 7724ad540459SPierre Jolivet for (j = 0; j < *(ptr_idxs + 1); j++) send_buffer_vecs[*(ptr_idxs + 2 + j)] += *(ptr_vals + j); 77251ae86dd6SStefano Zampini ptr_idxs += olengths_idxs[i]; 77261ae86dd6SStefano Zampini ptr_vals += olengths_idxs[i] - 2; 77271ae86dd6SStefano Zampini } 77289566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(nnsp_vec[0], &send_buffer_vecs)); 77299566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(nnsp_vec[0])); 77309566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(nnsp_vec[0])); 77311ae86dd6SStefano Zampini } 77321ae86dd6SStefano Zampini 77339566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_buffer_vecs)); 77349566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_buffer_idxs_local)); 77359566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_req_idxs)); 77369566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_req_vals)); 77379566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_req_vecs)); 77389566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_req_idxs_is)); 77399566063dSJacob Faibussowitsch PetscCall(PetscFree(send_req_idxs)); 77409566063dSJacob Faibussowitsch PetscCall(PetscFree(send_req_vals)); 77419566063dSJacob Faibussowitsch PetscCall(PetscFree(send_req_vecs)); 77429566063dSJacob Faibussowitsch PetscCall(PetscFree(send_req_idxs_is)); 77439566063dSJacob Faibussowitsch PetscCall(PetscFree(ilengths_vals)); 77449566063dSJacob Faibussowitsch PetscCall(PetscFree(ilengths_idxs)); 77459566063dSJacob Faibussowitsch PetscCall(PetscFree(olengths_vals)); 77469566063dSJacob Faibussowitsch PetscCall(PetscFree(olengths_idxs)); 77479566063dSJacob Faibussowitsch PetscCall(PetscFree(onodes)); 774828143c3dSStefano Zampini if (nis) { 77499566063dSJacob Faibussowitsch PetscCall(PetscFree(ilengths_idxs_is)); 77509566063dSJacob Faibussowitsch PetscCall(PetscFree(olengths_idxs_is)); 77519566063dSJacob Faibussowitsch PetscCall(PetscFree(onodes_is)); 775228143c3dSStefano Zampini } 77539566063dSJacob Faibussowitsch PetscCall(PetscSubcommDestroy(&subcomm)); 77546aad120cSJose E. Roman if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not participate */ 77559566063dSJacob Faibussowitsch PetscCall(MatDestroy(mat_n)); 775648a46eb9SPierre Jolivet for (i = 0; i < nis; i++) PetscCall(ISDestroy(&isarray[i])); 77571ae86dd6SStefano Zampini if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */ 77589566063dSJacob Faibussowitsch PetscCall(VecDestroy(&nnsp_vec[0])); 77591ae86dd6SStefano Zampini } 776053a05cb3SStefano Zampini *mat_n = NULL; 776128143c3dSStefano Zampini } 77623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7763e7931f94SStefano Zampini } 7764a57a6d2fSStefano Zampini 776512edc857SStefano Zampini /* temporary hack into ksp private data structure */ 7766af0996ceSBarry Smith #include <petsc/private/kspimpl.h> 776712edc857SStefano Zampini 7768d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc, PetscScalar *coarse_submat_vals) 7769d71ae5a4SJacob Faibussowitsch { 7770c8587f34SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 7771c8587f34SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 777220a2ab83SStefano Zampini Mat coarse_mat, coarse_mat_is, coarse_submat_dense; 77731ae86dd6SStefano Zampini Mat coarsedivudotp = NULL; 77741e0482f5SStefano Zampini Mat coarseG, t_coarse_mat_is; 77759881197aSStefano Zampini MatNullSpace CoarseNullSpace = NULL; 777620a2ab83SStefano Zampini ISLocalToGlobalMapping coarse_islg; 77774f819b78SStefano Zampini IS coarse_is, *isarray, corners; 77786e683305SStefano Zampini PetscInt i, im_active = -1, active_procs = -1; 777930368db7SStefano Zampini PetscInt nis, nisdofs, nisneu, nisvert; 7780e569e4e1SStefano Zampini PetscInt coarse_eqs_per_proc; 7781f9eb5b7dSStefano Zampini PC pc_temp; 7782c8587f34SStefano Zampini PCType coarse_pc_type; 7783c8587f34SStefano Zampini KSPType coarse_ksp_type; 7784f9eb5b7dSStefano Zampini PetscBool multilevel_requested, multilevel_allowed; 77857274672aSStefano Zampini PetscBool coarse_reuse; 77861e0482f5SStefano Zampini PetscInt ncoarse, nedcfield; 778768457ee5SStefano Zampini PetscBool compute_vecs = PETSC_FALSE; 778822bc73bbSStefano Zampini PetscScalar *array; 778957de7509SStefano Zampini MatReuse coarse_mat_reuse; 779057de7509SStefano Zampini PetscBool restr, full_restr, have_void; 7791e569e4e1SStefano Zampini PetscMPIInt size; 7792fdc09c96SStefano Zampini 7793c8587f34SStefano Zampini PetscFunctionBegin; 77949566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_CoarseSetUp[pcbddc->current_level], pc, 0, 0, 0)); 7795c8587f34SStefano Zampini /* Assign global numbering to coarse dofs */ 779668457ee5SStefano 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 */ 7797fa7f1dd8SStefano Zampini PetscInt ocoarse_size; 77985a75c04eSSatish Balay compute_vecs = PETSC_TRUE; 77997de4f681Sstefano_zampini 78007de4f681Sstefano_zampini pcbddc->new_primal_space = PETSC_TRUE; 7801fa7f1dd8SStefano Zampini ocoarse_size = pcbddc->coarse_size; 78029566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->global_primal_indices)); 78039566063dSJacob Faibussowitsch PetscCall(PCBDDCComputePrimalNumbering(pc, &pcbddc->coarse_size, &pcbddc->global_primal_indices)); 7804f4ddd8eeSStefano Zampini /* see if we can avoid some work */ 7805fa7f1dd8SStefano Zampini if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */ 780651bea450SStefano Zampini /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */ 780751bea450SStefano Zampini if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) { 78089566063dSJacob Faibussowitsch PetscCall(KSPReset(pcbddc->coarse_ksp)); 7809fa7f1dd8SStefano Zampini coarse_reuse = PETSC_FALSE; 7810fa7f1dd8SStefano Zampini } else { /* we can safely reuse already computed coarse matrix */ 7811fa7f1dd8SStefano Zampini coarse_reuse = PETSC_TRUE; 7812f4ddd8eeSStefano Zampini } 7813fa7f1dd8SStefano Zampini } else { /* there's no coarse ksp, so we need to create the coarse matrix too */ 7814fa7f1dd8SStefano Zampini coarse_reuse = PETSC_FALSE; 7815f4ddd8eeSStefano Zampini } 781670cf5478SStefano Zampini /* reset any subassembling information */ 781748a46eb9SPierre Jolivet if (!coarse_reuse || pcbddc->recompute_topography) PetscCall(ISDestroy(&pcbddc->coarse_subassembling)); 78186e683305SStefano Zampini } else { /* primal space is unchanged, so we can reuse coarse matrix */ 7819fa7f1dd8SStefano Zampini coarse_reuse = PETSC_TRUE; 7820f4ddd8eeSStefano Zampini } 782157de7509SStefano Zampini if (coarse_reuse && pcbddc->coarse_ksp) { 78229566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(pcbddc->coarse_ksp, &coarse_mat, NULL)); 78239566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coarse_mat)); 782457de7509SStefano Zampini coarse_mat_reuse = MAT_REUSE_MATRIX; 782518a45a71SStefano Zampini } else { 782657de7509SStefano Zampini coarse_mat = NULL; 782757de7509SStefano Zampini coarse_mat_reuse = MAT_INITIAL_MATRIX; 78286e683305SStefano Zampini } 7829e7931f94SStefano Zampini 7830abbbba34SStefano Zampini /* creates temporary l2gmap and IS for coarse indexes */ 78319566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), pcbddc->local_primal_size, pcbddc->global_primal_indices, PETSC_COPY_VALUES, &coarse_is)); 78329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(coarse_is, &coarse_islg)); 7833abbbba34SStefano Zampini 7834abbbba34SStefano Zampini /* creates temporary MATIS object for coarse matrix */ 78359566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, pcbddc->local_primal_size, pcbddc->local_primal_size, coarse_submat_vals, &coarse_submat_dense)); 78369566063dSJacob Faibussowitsch PetscCall(MatCreateIS(PetscObjectComm((PetscObject)pc), 1, PETSC_DECIDE, PETSC_DECIDE, pcbddc->coarse_size, pcbddc->coarse_size, coarse_islg, coarse_islg, &t_coarse_mat_is)); 78379566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(t_coarse_mat_is, coarse_submat_dense)); 78389566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(t_coarse_mat_is, MAT_FINAL_ASSEMBLY)); 78399566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(t_coarse_mat_is, MAT_FINAL_ASSEMBLY)); 78409566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_submat_dense)); 7841abbbba34SStefano Zampini 784257de7509SStefano Zampini /* count "active" (i.e. with positive local size) and "void" processes */ 784357de7509SStefano Zampini im_active = !!(pcis->n); 78441c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&im_active, &active_procs, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)pc))); 784557de7509SStefano Zampini 784614f0bfb9SStefano Zampini /* determine number of processes partecipating to coarse solver and compute subassembling pattern */ 784728d58a37SPierre Jolivet /* restr : whether we want to exclude senders (which are not receivers) from the subassembling pattern */ 784857de7509SStefano Zampini /* full_restr : just use the receivers from the subassembling pattern */ 78499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size)); 785057de7509SStefano Zampini coarse_mat_is = NULL; 785157de7509SStefano Zampini multilevel_allowed = PETSC_FALSE; 785257de7509SStefano Zampini multilevel_requested = PETSC_FALSE; 7853e569e4e1SStefano Zampini coarse_eqs_per_proc = PetscMin(PetscMax(pcbddc->coarse_size, 1), pcbddc->coarse_eqs_per_proc); 7854ce64c636SStefano Zampini if (coarse_eqs_per_proc < 0) coarse_eqs_per_proc = pcbddc->coarse_size; 785557de7509SStefano Zampini if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE; 7856e569e4e1SStefano Zampini if (pcbddc->coarse_size <= pcbddc->coarse_eqs_limit) multilevel_requested = PETSC_FALSE; 785757de7509SStefano Zampini if (multilevel_requested) { 785857de7509SStefano Zampini ncoarse = active_procs / pcbddc->coarsening_ratio; 785957de7509SStefano Zampini restr = PETSC_FALSE; 786057de7509SStefano Zampini full_restr = PETSC_FALSE; 786157de7509SStefano Zampini } else { 7862e569e4e1SStefano Zampini ncoarse = pcbddc->coarse_size / coarse_eqs_per_proc + !!(pcbddc->coarse_size % coarse_eqs_per_proc); 786357de7509SStefano Zampini restr = PETSC_TRUE; 786457de7509SStefano Zampini full_restr = PETSC_TRUE; 786557de7509SStefano Zampini } 7866e569e4e1SStefano Zampini if (!pcbddc->coarse_size || size == 1) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE; 786757de7509SStefano Zampini ncoarse = PetscMax(1, ncoarse); 786857de7509SStefano Zampini if (!pcbddc->coarse_subassembling) { 7869a198735bSStefano Zampini if (pcbddc->coarsening_ratio > 1) { 7870bb360cb4SStefano Zampini if (multilevel_requested) { 78719566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISGetSubassemblingPattern(pc->pmat, &ncoarse, pcbddc->coarse_adj_red, &pcbddc->coarse_subassembling, &have_void)); 7872bb360cb4SStefano Zampini } else { 78739566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISGetSubassemblingPattern(t_coarse_mat_is, &ncoarse, pcbddc->coarse_adj_red, &pcbddc->coarse_subassembling, &have_void)); 7874bb360cb4SStefano Zampini } 7875a198735bSStefano Zampini } else { 78767de4f681Sstefano_zampini PetscMPIInt rank; 787728d58a37SPierre Jolivet 78789566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc), &rank)); 7879e569e4e1SStefano Zampini have_void = (active_procs == (PetscInt)size) ? PETSC_FALSE : PETSC_TRUE; 78809566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)pc), 1, rank, 1, &pcbddc->coarse_subassembling)); 7881a198735bSStefano Zampini } 788257de7509SStefano Zampini } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */ 788357de7509SStefano Zampini PetscInt psum; 788457de7509SStefano Zampini if (pcbddc->coarse_ksp) psum = 1; 788557de7509SStefano Zampini else psum = 0; 78861c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&psum, &ncoarse, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)pc))); 7887075e25bcSStefano Zampini have_void = ncoarse < size ? PETSC_TRUE : PETSC_FALSE; 788857de7509SStefano Zampini } 788957de7509SStefano Zampini /* determine if we can go multilevel */ 789057de7509SStefano Zampini if (multilevel_requested) { 789157de7509SStefano Zampini if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */ 789257de7509SStefano Zampini else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */ 789357de7509SStefano Zampini } 789457de7509SStefano Zampini if (multilevel_allowed && have_void) restr = PETSC_TRUE; 789557de7509SStefano Zampini 7896e4d548c7SStefano Zampini /* dump subassembling pattern */ 789748a46eb9SPierre Jolivet if (pcbddc->dbg_flag && multilevel_allowed) PetscCall(ISView(pcbddc->coarse_subassembling, pcbddc->dbg_viewer)); 78986e683305SStefano Zampini /* compute dofs splitting and neumann boundaries for coarse dofs */ 78991e0482f5SStefano Zampini nedcfield = -1; 79004f819b78SStefano Zampini corners = NULL; 79018966356dSPierre Jolivet if (multilevel_allowed && !coarse_reuse && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal || pcbddc->nedclocal || pcbddc->corner_selected)) { /* protects from unneeded computations */ 79026e683305SStefano Zampini PetscInt *tidxs, *tidxs2, nout, tsize, i; 79036e683305SStefano Zampini const PetscInt *idxs; 79046e683305SStefano Zampini ISLocalToGlobalMapping tmap; 79056e683305SStefano Zampini 79066e683305SStefano Zampini /* create map between primal indices (in local representative ordering) and local primal numbering */ 79079566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PETSC_COMM_SELF, 1, pcbddc->local_primal_size, pcbddc->primal_indices_local_idxs, PETSC_COPY_VALUES, &tmap)); 79086e683305SStefano Zampini /* allocate space for temporary storage */ 79099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->local_primal_size, &tidxs)); 79109566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->local_primal_size, &tidxs2)); 79116e683305SStefano Zampini /* allocate for IS array */ 79126e683305SStefano Zampini nisdofs = pcbddc->n_ISForDofsLocal; 79131e0482f5SStefano Zampini if (pcbddc->nedclocal) { 79141e0482f5SStefano Zampini if (pcbddc->nedfield > -1) { 79151e0482f5SStefano Zampini nedcfield = pcbddc->nedfield; 79161e0482f5SStefano Zampini } else { 79171e0482f5SStefano Zampini nedcfield = 0; 791863a3b9bcSJacob Faibussowitsch PetscCheck(!nisdofs, PetscObjectComm((PetscObject)pc), PETSC_ERR_PLIB, "This should not happen (%" PetscInt_FMT ")", nisdofs); 79191e0482f5SStefano Zampini nisdofs = 1; 79201e0482f5SStefano Zampini } 79211e0482f5SStefano Zampini } 79226e683305SStefano Zampini nisneu = !!pcbddc->NeumannBoundariesLocal; 792327b6a85dSStefano Zampini nisvert = 0; /* nisvert is not used */ 792430368db7SStefano Zampini nis = nisdofs + nisneu + nisvert; 79259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nis, &isarray)); 79266e683305SStefano Zampini /* dofs splitting */ 79276e683305SStefano Zampini for (i = 0; i < nisdofs; i++) { 79289566063dSJacob Faibussowitsch /* PetscCall(ISView(pcbddc->ISForDofsLocal[i],0)); */ 79291e0482f5SStefano Zampini if (nedcfield != i) { 79309566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->ISForDofsLocal[i], &tsize)); 79319566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->ISForDofsLocal[i], &idxs)); 79329566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(tmap, IS_GTOLM_DROP, tsize, idxs, &nout, tidxs)); 79339566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->ISForDofsLocal[i], &idxs)); 79341e0482f5SStefano Zampini } else { 79359566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->nedclocal, &tsize)); 79369566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->nedclocal, &idxs)); 79379566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(tmap, IS_GTOLM_DROP, tsize, idxs, &nout, tidxs)); 793863a3b9bcSJacob Faibussowitsch PetscCheck(tsize == nout, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Failed when mapping coarse nedelec field! %" PetscInt_FMT " != %" PetscInt_FMT, tsize, nout); 79399566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->nedclocal, &idxs)); 79401e0482f5SStefano Zampini } 79419566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(coarse_islg, nout, tidxs, tidxs2)); 79429566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), nout, tidxs2, PETSC_COPY_VALUES, &isarray[i])); 79439566063dSJacob Faibussowitsch /* PetscCall(ISView(isarray[i],0)); */ 79446e683305SStefano Zampini } 79456e683305SStefano Zampini /* neumann boundaries */ 79466e683305SStefano Zampini if (pcbddc->NeumannBoundariesLocal) { 79479566063dSJacob Faibussowitsch /* PetscCall(ISView(pcbddc->NeumannBoundariesLocal,0)); */ 79489566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->NeumannBoundariesLocal, &tsize)); 79499566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->NeumannBoundariesLocal, &idxs)); 79509566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(tmap, IS_GTOLM_DROP, tsize, idxs, &nout, tidxs)); 79519566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->NeumannBoundariesLocal, &idxs)); 79529566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(coarse_islg, nout, tidxs, tidxs2)); 79539566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), nout, tidxs2, PETSC_COPY_VALUES, &isarray[nisdofs])); 79549566063dSJacob Faibussowitsch /* PetscCall(ISView(isarray[nisdofs],0)); */ 79556e683305SStefano Zampini } 79564f819b78SStefano Zampini /* coordinates */ 79574f819b78SStefano Zampini if (pcbddc->corner_selected) { 79589566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &corners)); 79599566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(corners, &tsize)); 79609566063dSJacob Faibussowitsch PetscCall(ISGetIndices(corners, &idxs)); 79619566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(tmap, IS_GTOLM_DROP, tsize, idxs, &nout, tidxs)); 796263a3b9bcSJacob Faibussowitsch PetscCheck(tsize == nout, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Failed when mapping corners! %" PetscInt_FMT " != %" PetscInt_FMT, tsize, nout); 79639566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(corners, &idxs)); 79649566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &corners)); 79659566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(coarse_islg, nout, tidxs, tidxs2)); 79669566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), nout, tidxs2, PETSC_COPY_VALUES, &corners)); 79674f819b78SStefano Zampini } 79689566063dSJacob Faibussowitsch PetscCall(PetscFree(tidxs)); 79699566063dSJacob Faibussowitsch PetscCall(PetscFree(tidxs2)); 79709566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&tmap)); 79716e683305SStefano Zampini } else { 79726e683305SStefano Zampini nis = 0; 79736e683305SStefano Zampini nisdofs = 0; 79746e683305SStefano Zampini nisneu = 0; 797530368db7SStefano Zampini nisvert = 0; 79766e683305SStefano Zampini isarray = NULL; 79776e683305SStefano Zampini } 79786e683305SStefano Zampini /* destroy no longer needed map */ 79799566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&coarse_islg)); 79806e683305SStefano Zampini 798157de7509SStefano Zampini /* subassemble */ 798257de7509SStefano Zampini if (multilevel_allowed) { 79831ae86dd6SStefano Zampini Vec vp[1]; 79841ae86dd6SStefano Zampini PetscInt nvecs = 0; 798557de7509SStefano Zampini PetscBool reuse, reuser; 79861ae86dd6SStefano Zampini 798757de7509SStefano Zampini if (coarse_mat) reuse = PETSC_TRUE; 798857de7509SStefano Zampini else reuse = PETSC_FALSE; 79891c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&reuse, &reuser, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 79901ae86dd6SStefano Zampini vp[0] = NULL; 79911ae86dd6SStefano Zampini if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */ 79929566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pc), &vp[0])); 79939566063dSJacob Faibussowitsch PetscCall(VecSetSizes(vp[0], pcbddc->local_primal_size, PETSC_DECIDE)); 79949566063dSJacob Faibussowitsch PetscCall(VecSetType(vp[0], VECSTANDARD)); 79951ae86dd6SStefano Zampini nvecs = 1; 79961ae86dd6SStefano Zampini 79971ae86dd6SStefano Zampini if (pcbddc->divudotp) { 7998a198735bSStefano Zampini Mat B, loc_divudotp; 79991ae86dd6SStefano Zampini Vec v, p; 80001ae86dd6SStefano Zampini IS dummy; 80011ae86dd6SStefano Zampini PetscInt np; 80021ae86dd6SStefano Zampini 80039566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pcbddc->divudotp, &loc_divudotp)); 80049566063dSJacob Faibussowitsch PetscCall(MatGetSize(loc_divudotp, &np, NULL)); 80059566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, np, 0, 1, &dummy)); 80069566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(loc_divudotp, dummy, pcis->is_B_local, MAT_INITIAL_MATRIX, &B)); 80079566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(B, &v, &p)); 80089566063dSJacob Faibussowitsch PetscCall(VecSet(p, 1.)); 80099566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(B, p, v)); 80109566063dSJacob Faibussowitsch PetscCall(VecDestroy(&p)); 80119566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 80129566063dSJacob Faibussowitsch PetscCall(VecGetArray(vp[0], &array)); 80139566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_P, array)); 80149566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->coarse_phi_B, v, pcbddc->vec1_P)); 80159566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_P)); 80169566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(vp[0], &array)); 80179566063dSJacob Faibussowitsch PetscCall(ISDestroy(&dummy)); 80189566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 801974e2c79eSStefano Zampini } 80201ae86dd6SStefano Zampini } 80211ae86dd6SStefano Zampini if (reuser) { 80229566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISSubassemble(t_coarse_mat_is, pcbddc->coarse_subassembling, 0, restr, full_restr, PETSC_TRUE, &coarse_mat, nis, isarray, nvecs, vp)); 802374e2c79eSStefano Zampini } else { 80249566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISSubassemble(t_coarse_mat_is, pcbddc->coarse_subassembling, 0, restr, full_restr, PETSC_FALSE, &coarse_mat_is, nis, isarray, nvecs, vp)); 80251ae86dd6SStefano Zampini } 80261ae86dd6SStefano Zampini if (vp[0]) { /* vp[0] could have been placed on a different set of processes */ 80271683a169SBarry Smith PetscScalar *arraym; 80281683a169SBarry Smith const PetscScalar *arrayv; 80291ae86dd6SStefano Zampini PetscInt nl; 80309566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vp[0], &nl)); 80319566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, 1, nl, NULL, &coarsedivudotp)); 80329566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(coarsedivudotp, &arraym)); 80339566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vp[0], &arrayv)); 80349566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(arraym, arrayv, nl)); 80359566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vp[0], &arrayv)); 80369566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(coarsedivudotp, &arraym)); 80379566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vp[0])); 8038a198735bSStefano Zampini } else { 80399566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, 0, 0, 1, NULL, &coarsedivudotp)); 80401ae86dd6SStefano Zampini } 80411ae86dd6SStefano Zampini } else { 80429566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISSubassemble(t_coarse_mat_is, pcbddc->coarse_subassembling, 0, restr, full_restr, PETSC_FALSE, &coarse_mat_is, 0, NULL, 0, NULL)); 80436e683305SStefano Zampini } 804457de7509SStefano Zampini if (coarse_mat_is || coarse_mat) { 804557de7509SStefano Zampini if (!multilevel_allowed) { 80469566063dSJacob Faibussowitsch PetscCall(MatConvert(coarse_mat_is, MATAIJ, coarse_mat_reuse, &coarse_mat)); 80476e683305SStefano Zampini } else { 804857de7509SStefano Zampini /* if this matrix is present, it means we are not reusing the coarse matrix */ 804957de7509SStefano Zampini if (coarse_mat_is) { 805028b400f6SJacob Faibussowitsch PetscCheck(!coarse_mat, PetscObjectComm((PetscObject)coarse_mat_is), PETSC_ERR_PLIB, "This should not happen"); 80519566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coarse_mat_is)); 805257de7509SStefano Zampini coarse_mat = coarse_mat_is; 805357de7509SStefano Zampini } 8054779c1cceSStefano Zampini } 8055779c1cceSStefano Zampini } 80569566063dSJacob Faibussowitsch PetscCall(MatDestroy(&t_coarse_mat_is)); 80579566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_mat_is)); 80586e683305SStefano Zampini 80596e683305SStefano Zampini /* create local to global scatters for coarse problem */ 806068457ee5SStefano Zampini if (compute_vecs) { 80616e683305SStefano Zampini PetscInt lrows; 80629566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->coarse_vec)); 806357de7509SStefano Zampini if (coarse_mat) { 80649566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(coarse_mat, &lrows, NULL)); 80656e683305SStefano Zampini } else { 80666e683305SStefano Zampini lrows = 0; 80676e683305SStefano Zampini } 80689566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pc), &pcbddc->coarse_vec)); 80699566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pcbddc->coarse_vec, lrows, PETSC_DECIDE)); 80709566063dSJacob Faibussowitsch PetscCall(VecSetType(pcbddc->coarse_vec, coarse_mat ? coarse_mat->defaultvectype : VECSTANDARD)); 80719566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->coarse_loc_to_glob)); 80729566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(pcbddc->vec1_P, NULL, pcbddc->coarse_vec, coarse_is, &pcbddc->coarse_loc_to_glob)); 80736e683305SStefano Zampini } 80749566063dSJacob Faibussowitsch PetscCall(ISDestroy(&coarse_is)); 8075c8587f34SStefano Zampini 8076f9eb5b7dSStefano Zampini /* set defaults for coarse KSP and PC */ 8077f9eb5b7dSStefano Zampini if (multilevel_allowed) { 8078f9eb5b7dSStefano Zampini coarse_ksp_type = KSPRICHARDSON; 8079f9eb5b7dSStefano Zampini coarse_pc_type = PCBDDC; 8080f9eb5b7dSStefano Zampini } else { 8081f9eb5b7dSStefano Zampini coarse_ksp_type = KSPPREONLY; 8082f9eb5b7dSStefano Zampini coarse_pc_type = PCREDUNDANT; 8083c8587f34SStefano Zampini } 8084c8587f34SStefano Zampini 80856e683305SStefano Zampini /* print some info if requested */ 80866e683305SStefano Zampini if (pcbddc->dbg_flag) { 80876e683305SStefano Zampini if (!multilevel_allowed) { 80889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 80896e683305SStefano Zampini if (multilevel_requested) { 809063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Not enough active processes on level %" PetscInt_FMT " (active processes %" PetscInt_FMT ", coarsening ratio %" PetscInt_FMT ")\n", pcbddc->current_level, active_procs, pcbddc->coarsening_ratio)); 80916e683305SStefano Zampini } else if (pcbddc->max_levels) { 809263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Maximum number of requested levels reached (%" PetscInt_FMT ")\n", pcbddc->max_levels)); 80936e683305SStefano Zampini } 80949566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 80956e683305SStefano Zampini } 80966e683305SStefano Zampini } 80976e683305SStefano Zampini 80981e0482f5SStefano Zampini /* communicate coarse discrete gradient */ 80991e0482f5SStefano Zampini coarseG = NULL; 81001e0482f5SStefano Zampini if (pcbddc->nedcG && multilevel_allowed) { 81011e0482f5SStefano Zampini MPI_Comm ccomm; 81021e0482f5SStefano Zampini if (coarse_mat) { 81031e0482f5SStefano Zampini ccomm = PetscObjectComm((PetscObject)coarse_mat); 81041e0482f5SStefano Zampini } else { 81051e0482f5SStefano Zampini ccomm = MPI_COMM_NULL; 81061e0482f5SStefano Zampini } 81079566063dSJacob Faibussowitsch PetscCall(MatMPIAIJRestrict(pcbddc->nedcG, ccomm, &coarseG)); 81081e0482f5SStefano Zampini } 81091e0482f5SStefano Zampini 8110f9eb5b7dSStefano Zampini /* create the coarse KSP object only once with defaults */ 811157de7509SStefano Zampini if (coarse_mat) { 811228d58a37SPierre Jolivet PetscBool isredundant, isbddc, force, valid; 81136a1308c2SStefano Zampini PetscViewer dbg_viewer = NULL; 8114b94d7dedSBarry Smith PetscBool isset, issym, isher, isspd; 81157274672aSStefano Zampini 81166e683305SStefano Zampini if (pcbddc->dbg_flag) { 811757de7509SStefano Zampini dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat)); 81189566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIAddTab(dbg_viewer, 2 * pcbddc->current_level)); 81196e683305SStefano Zampini } 8120f9eb5b7dSStefano Zampini if (!pcbddc->coarse_ksp) { 8121312be037SStefano Zampini char prefix[256], str_level[16]; 8122e604994aSStefano Zampini size_t len; 81231e0482f5SStefano Zampini 81249566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)coarse_mat), &pcbddc->coarse_ksp)); 81259566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(pcbddc->coarse_ksp, pc->erroriffailure)); 81269566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp, (PetscObject)pc, 1)); 81279566063dSJacob Faibussowitsch PetscCall(KSPSetTolerances(pcbddc->coarse_ksp, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, 1)); 81289566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(pcbddc->coarse_ksp, coarse_mat, coarse_mat)); 81299566063dSJacob Faibussowitsch PetscCall(KSPSetType(pcbddc->coarse_ksp, coarse_ksp_type)); 81309566063dSJacob Faibussowitsch PetscCall(KSPSetNormType(pcbddc->coarse_ksp, KSP_NORM_NONE)); 81319566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &pc_temp)); 81321e0482f5SStefano Zampini /* TODO is this logic correct? should check for coarse_mat type */ 81339566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, coarse_pc_type)); 8134e604994aSStefano Zampini /* prefix */ 8135c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(prefix, "", sizeof(prefix))); 8136c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(str_level, "", sizeof(str_level))); 8137e604994aSStefano Zampini if (!pcbddc->current_level) { 81389566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(prefix, ((PetscObject)pc)->prefix, sizeof(prefix))); 81399566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, "pc_bddc_coarse_", sizeof(prefix))); 8140c8587f34SStefano Zampini } else { 81419566063dSJacob Faibussowitsch PetscCall(PetscStrlen(((PetscObject)pc)->prefix, &len)); 8142312be037SStefano Zampini if (pcbddc->current_level > 1) len -= 3; /* remove "lX_" with X level number */ 8143312be037SStefano Zampini if (pcbddc->current_level > 10) len -= 1; /* remove another char from level number */ 8144a126751eSBarry Smith /* Nonstandard use of PetscStrncpy() to copy only a portion of the string */ 81459566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(prefix, ((PetscObject)pc)->prefix, len + 1)); 81469566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(str_level, sizeof(str_level), "l%d_", (int)(pcbddc->current_level))); 81479566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, str_level, sizeof(prefix))); 8148e604994aSStefano Zampini } 81499566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(pcbddc->coarse_ksp, prefix)); 81503e3c6dadSStefano Zampini /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */ 81519566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLevel(pc_temp, pcbddc->current_level + 1)); 81529566063dSJacob Faibussowitsch PetscCall(PCBDDCSetCoarseningRatio(pc_temp, pcbddc->coarsening_ratio)); 81539566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLevels(pc_temp, pcbddc->max_levels)); 8154f9eb5b7dSStefano Zampini /* allow user customization */ 81559566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(pcbddc->coarse_ksp)); 8156e569e4e1SStefano Zampini /* get some info after set from options */ 81579566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &pc_temp)); 815828d58a37SPierre Jolivet /* multilevel cannot be done with coarse PC different from BDDC, NN, HPDDM, unless forced to */ 815928d58a37SPierre Jolivet force = PETSC_FALSE; 81609566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)pc_temp)->prefix, "-pc_type_forced", &force, NULL)); 81619566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)pc_temp, &valid, PCBDDC, PCNN, PCHPDDM, "")); 81629566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp, PCBDDC, &isbddc)); 816328d58a37SPierre Jolivet if (multilevel_allowed && !force && !valid) { 8164e569e4e1SStefano Zampini isbddc = PETSC_TRUE; 81659566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCBDDC)); 81669566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLevel(pc_temp, pcbddc->current_level + 1)); 81679566063dSJacob Faibussowitsch PetscCall(PCBDDCSetCoarseningRatio(pc_temp, pcbddc->coarsening_ratio)); 81689566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLevels(pc_temp, pcbddc->max_levels)); 81694f819b78SStefano Zampini if (pc_temp->ops->setfromoptions) { /* need to setfromoptions again, skipping the pc_type */ 8170d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)pc_temp); 8171dbbe0bcdSBarry Smith PetscCall((*pc_temp->ops->setfromoptions)(pc_temp, PetscOptionsObject)); 8172dbbe0bcdSBarry Smith PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)pc_temp, PetscOptionsObject)); 8173d0609cedSBarry Smith PetscOptionsEnd(); 81744f819b78SStefano Zampini pc_temp->setfromoptionscalled++; 81754f819b78SStefano Zampini } 8176e569e4e1SStefano Zampini } 81773e3c6dadSStefano Zampini } 81783e3c6dadSStefano Zampini /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */ 81799566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &pc_temp)); 81803e3c6dadSStefano Zampini if (nisdofs) { 81819566063dSJacob Faibussowitsch PetscCall(PCBDDCSetDofsSplitting(pc_temp, nisdofs, isarray)); 818248a46eb9SPierre Jolivet for (i = 0; i < nisdofs; i++) PetscCall(ISDestroy(&isarray[i])); 81833e3c6dadSStefano Zampini } 81843e3c6dadSStefano Zampini if (nisneu) { 81859566063dSJacob Faibussowitsch PetscCall(PCBDDCSetNeumannBoundaries(pc_temp, isarray[nisdofs])); 81869566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isarray[nisdofs])); 8187312be037SStefano Zampini } 818830368db7SStefano Zampini if (nisvert) { 81899566063dSJacob Faibussowitsch PetscCall(PCBDDCSetPrimalVerticesIS(pc_temp, isarray[nis - 1])); 81909566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isarray[nis - 1])); 819130368db7SStefano Zampini } 81921baa6e33SBarry Smith if (coarseG) PetscCall(PCBDDCSetDiscreteGradient(pc_temp, coarseG, 1, nedcfield, PETSC_FALSE, PETSC_TRUE)); 8193f9eb5b7dSStefano Zampini 8194f9eb5b7dSStefano Zampini /* get some info after set from options */ 81959566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp, PCBDDC, &isbddc)); 81964f819b78SStefano Zampini 8197b76f3995Sstefano_zampini /* multilevel can only be requested via -pc_bddc_levels or PCBDDCSetLevels */ 819848a46eb9SPierre Jolivet if (isbddc && !multilevel_allowed) PetscCall(PCSetType(pc_temp, coarse_pc_type)); 819928d58a37SPierre Jolivet /* multilevel cannot be done with coarse PC different from BDDC, NN, HPDDM, unless forced to */ 820028d58a37SPierre Jolivet force = PETSC_FALSE; 82019566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)pc_temp)->prefix, "-pc_type_forced", &force, NULL)); 82029566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)pc_temp, &valid, PCBDDC, PCNN, PCHPDDM, "")); 820348a46eb9SPierre Jolivet if (multilevel_requested && multilevel_allowed && !valid && !force) PetscCall(PCSetType(pc_temp, PCBDDC)); 82049566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp, PCREDUNDANT, &isredundant)); 82054f3a063dSStefano Zampini if (isredundant) { 82064f3a063dSStefano Zampini KSP inner_ksp; 82074f3a063dSStefano Zampini PC inner_pc; 82089326c5c6Sstefano_zampini 82099566063dSJacob Faibussowitsch PetscCall(PCRedundantGetKSP(pc_temp, &inner_ksp)); 82109566063dSJacob Faibussowitsch PetscCall(KSPGetPC(inner_ksp, &inner_pc)); 82114f3a063dSStefano Zampini } 8212f9eb5b7dSStefano Zampini 821357de7509SStefano Zampini /* parameters which miss an API */ 82149566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp, PCBDDC, &isbddc)); 821557de7509SStefano Zampini if (isbddc) { 8216720d30f9SStefano Zampini PC_BDDC *pcbddc_coarse = (PC_BDDC *)pc_temp->data; 82177274672aSStefano Zampini 8218720d30f9SStefano Zampini pcbddc_coarse->detect_disconnected = PETSC_TRUE; 821957de7509SStefano Zampini pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc; 8220e569e4e1SStefano Zampini pcbddc_coarse->coarse_eqs_limit = pcbddc->coarse_eqs_limit; 822127b6a85dSStefano Zampini pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null; 822227b6a85dSStefano Zampini if (pcbddc_coarse->benign_saddle_point) { 8223a198735bSStefano Zampini Mat coarsedivudotp_is; 8224a198735bSStefano Zampini ISLocalToGlobalMapping l2gmap, rl2g, cl2g; 8225a198735bSStefano Zampini IS row, col; 8226a198735bSStefano Zampini const PetscInt *gidxs; 8227a198735bSStefano Zampini PetscInt n, st, M, N; 8228a198735bSStefano Zampini 82299566063dSJacob Faibussowitsch PetscCall(MatGetSize(coarsedivudotp, &n, NULL)); 82309566063dSJacob Faibussowitsch PetscCallMPI(MPI_Scan(&n, &st, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)coarse_mat))); 8231a198735bSStefano Zampini st = st - n; 82329566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)coarse_mat), 1, st, 1, &row)); 82339566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(coarse_mat, &l2gmap, NULL)); 82349566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(l2gmap, &n)); 82359566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(l2gmap, &gidxs)); 82369566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat), n, gidxs, PETSC_COPY_VALUES, &col)); 82379566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(l2gmap, &gidxs)); 82389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(row, &rl2g)); 82399566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(col, &cl2g)); 82409566063dSJacob Faibussowitsch PetscCall(ISGetSize(row, &M)); 82419566063dSJacob Faibussowitsch PetscCall(MatGetSize(coarse_mat, &N, NULL)); 82429566063dSJacob Faibussowitsch PetscCall(ISDestroy(&row)); 82439566063dSJacob Faibussowitsch PetscCall(ISDestroy(&col)); 82449566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)coarse_mat), &coarsedivudotp_is)); 82459566063dSJacob Faibussowitsch PetscCall(MatSetType(coarsedivudotp_is, MATIS)); 82469566063dSJacob Faibussowitsch PetscCall(MatSetSizes(coarsedivudotp_is, PETSC_DECIDE, PETSC_DECIDE, M, N)); 82479566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(coarsedivudotp_is, rl2g, cl2g)); 82489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 82499566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 82509566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(coarsedivudotp_is, coarsedivudotp)); 82519566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarsedivudotp)); 82529566063dSJacob Faibussowitsch PetscCall(PCBDDCSetDivergenceMat(pc_temp, coarsedivudotp_is, PETSC_FALSE, NULL)); 82539566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarsedivudotp_is)); 8254720d30f9SStefano Zampini pcbddc_coarse->adaptive_userdefined = PETSC_TRUE; 8255bd2a564bSStefano Zampini if (pcbddc->adaptive_threshold[0] == 0.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE; 8256720d30f9SStefano Zampini } 8257d4d8cf7bSStefano Zampini } 82589881197aSStefano Zampini 82593301b35fSStefano Zampini /* propagate symmetry info of coarse matrix */ 82609566063dSJacob Faibussowitsch PetscCall(MatSetOption(coarse_mat, MAT_STRUCTURALLY_SYMMETRIC, PETSC_TRUE)); 8261b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(pc->pmat, &isset, &issym)); 8262b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(coarse_mat, MAT_SYMMETRIC, issym)); 8263b94d7dedSBarry Smith PetscCall(MatIsHermitianKnown(pc->pmat, &isset, &isher)); 8264b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(coarse_mat, MAT_HERMITIAN, isher)); 8265b94d7dedSBarry Smith PetscCall(MatIsSPDKnown(pc->pmat, &isset, &isspd)); 8266b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(coarse_mat, MAT_SPD, isspd)); 8267b94d7dedSBarry Smith 826848a46eb9SPierre Jolivet if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) PetscCall(MatSetOption(coarse_mat, MAT_SPD, PETSC_TRUE)); 82696e683305SStefano Zampini /* set operators */ 82709566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(coarse_mat, (PetscObject)pc, "-pc_bddc_coarse_mat_view")); 82719566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(coarse_mat, ((PetscObject)pcbddc->coarse_ksp)->prefix)); 82729566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(pcbddc->coarse_ksp, coarse_mat, coarse_mat)); 82731baa6e33SBarry Smith if (pcbddc->dbg_flag) PetscCall(PetscViewerASCIISubtractTab(dbg_viewer, 2 * pcbddc->current_level)); 82746e683305SStefano Zampini } 82759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarseG)); 82769566063dSJacob Faibussowitsch PetscCall(PetscFree(isarray)); 8277b1ecc7b1SStefano Zampini #if 0 8278b9b85e73SStefano Zampini { 8279b9b85e73SStefano Zampini PetscViewer viewer; 8280b9b85e73SStefano Zampini char filename[256]; 8281a364092eSJacob Faibussowitsch PetscCall(PetscSNPrintf(filename, PETSC_STATIC_ARRAY_LENGTH(filename), "coarse_mat_level%d.m",pcbddc->current_level)); 82829566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer)); 82839566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB)); 82849566063dSJacob Faibussowitsch PetscCall(MatView(coarse_mat,viewer)); 82859566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 82869566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 8287b9b85e73SStefano Zampini } 8288b9b85e73SStefano Zampini #endif 8289f9eb5b7dSStefano Zampini 82904f819b78SStefano Zampini if (corners) { 82914f819b78SStefano Zampini Vec gv; 82924f819b78SStefano Zampini IS is; 82934f819b78SStefano Zampini const PetscInt *idxs; 82944f819b78SStefano Zampini PetscInt i, d, N, n, cdim = pcbddc->mat_graph->cdim; 82954f819b78SStefano Zampini PetscScalar *coords; 82964f819b78SStefano Zampini 829728b400f6SJacob Faibussowitsch PetscCheck(pcbddc->mat_graph->cloc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing local coordinates"); 82989566063dSJacob Faibussowitsch PetscCall(VecGetSize(pcbddc->coarse_vec, &N)); 82999566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(pcbddc->coarse_vec, &n)); 83009566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pcbddc->coarse_vec), &gv)); 83019566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(gv, cdim)); 83029566063dSJacob Faibussowitsch PetscCall(VecSetSizes(gv, n * cdim, N * cdim)); 83039566063dSJacob Faibussowitsch PetscCall(VecSetType(gv, VECSTANDARD)); 83049566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(gv)); 83059566063dSJacob Faibussowitsch PetscCall(VecSet(gv, PETSC_MAX_REAL)); /* we only propagate coordinates from vertices constraints */ 83064f819b78SStefano Zampini 83079566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &is)); 83089566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &n)); 83099566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, &idxs)); 83109566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n * cdim, &coords)); 83114f819b78SStefano Zampini for (i = 0; i < n; i++) { 8312ad540459SPierre Jolivet for (d = 0; d < cdim; d++) coords[cdim * i + d] = pcbddc->mat_graph->coords[cdim * idxs[i] + d]; 83134f819b78SStefano Zampini } 83149566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, &idxs)); 83159566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &is)); 83164f819b78SStefano Zampini 83179566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(corners, &n)); 83189566063dSJacob Faibussowitsch PetscCall(ISGetIndices(corners, &idxs)); 83199566063dSJacob Faibussowitsch PetscCall(VecSetValuesBlocked(gv, n, idxs, coords, INSERT_VALUES)); 83209566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(corners, &idxs)); 83219566063dSJacob Faibussowitsch PetscCall(PetscFree(coords)); 83229566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(gv)); 83239566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(gv)); 83249566063dSJacob Faibussowitsch PetscCall(VecGetArray(gv, &coords)); 83254f819b78SStefano Zampini if (pcbddc->coarse_ksp) { 83264f819b78SStefano Zampini PC coarse_pc; 83274f819b78SStefano Zampini PetscBool isbddc; 83284f819b78SStefano Zampini 83299566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &coarse_pc)); 83309566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)coarse_pc, PCBDDC, &isbddc)); 83314f819b78SStefano Zampini if (isbddc) { /* coarse coordinates have PETSC_MAX_REAL, specific for BDDC */ 83324f819b78SStefano Zampini PetscReal *realcoords; 83334f819b78SStefano Zampini 83349566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(gv, &n)); 83354f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX) 83369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &realcoords)); 83374f819b78SStefano Zampini for (i = 0; i < n; i++) realcoords[i] = PetscRealPart(coords[i]); 83384f819b78SStefano Zampini #else 83394f819b78SStefano Zampini realcoords = coords; 83404f819b78SStefano Zampini #endif 83419566063dSJacob Faibussowitsch PetscCall(PCSetCoordinates(coarse_pc, cdim, n / cdim, realcoords)); 83424f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX) 83439566063dSJacob Faibussowitsch PetscCall(PetscFree(realcoords)); 83444f819b78SStefano Zampini #endif 83454f819b78SStefano Zampini } 83464f819b78SStefano Zampini } 83479566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(gv, &coords)); 83489566063dSJacob Faibussowitsch PetscCall(VecDestroy(&gv)); 83494f819b78SStefano Zampini } 83509566063dSJacob Faibussowitsch PetscCall(ISDestroy(&corners)); 83514f819b78SStefano Zampini 835298a51de6SStefano Zampini if (pcbddc->coarse_ksp) { 835398a51de6SStefano Zampini Vec crhs, csol; 835404708bb6SStefano Zampini 83559566063dSJacob Faibussowitsch PetscCall(KSPGetSolution(pcbddc->coarse_ksp, &csol)); 83569566063dSJacob Faibussowitsch PetscCall(KSPGetRhs(pcbddc->coarse_ksp, &crhs)); 835748a46eb9SPierre Jolivet if (!csol) PetscCall(MatCreateVecs(coarse_mat, &((pcbddc->coarse_ksp)->vec_sol), NULL)); 835848a46eb9SPierre Jolivet if (!crhs) PetscCall(MatCreateVecs(coarse_mat, NULL, &((pcbddc->coarse_ksp)->vec_rhs))); 8359b0f5fe93SStefano Zampini } 83609566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarsedivudotp)); 8361b0f5fe93SStefano Zampini 8362b0f5fe93SStefano Zampini /* compute null space for coarse solver if the benign trick has been requested */ 8363b0f5fe93SStefano Zampini if (pcbddc->benign_null) { 83649566063dSJacob Faibussowitsch PetscCall(VecSet(pcbddc->vec1_P, 0.)); 836548a46eb9SPierre Jolivet for (i = 0; i < pcbddc->benign_n; i++) PetscCall(VecSetValue(pcbddc->vec1_P, pcbddc->local_primal_size - pcbddc->benign_n + i, 1.0, INSERT_VALUES)); 83669566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(pcbddc->vec1_P)); 83679566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(pcbddc->vec1_P)); 83689566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob, pcbddc->vec1_P, pcbddc->coarse_vec, INSERT_VALUES, SCATTER_FORWARD)); 83699566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob, pcbddc->vec1_P, pcbddc->coarse_vec, INSERT_VALUES, SCATTER_FORWARD)); 8370b0f5fe93SStefano Zampini if (coarse_mat) { 8371b0f5fe93SStefano Zampini Vec nullv; 8372b0f5fe93SStefano Zampini PetscScalar *array, *array2; 8373b0f5fe93SStefano Zampini PetscInt nl; 8374b0f5fe93SStefano Zampini 83759566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(coarse_mat, &nullv, NULL)); 83769566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(nullv, &nl)); 83779566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(pcbddc->coarse_vec, (const PetscScalar **)&array)); 83789566063dSJacob Faibussowitsch PetscCall(VecGetArray(nullv, &array2)); 83799566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(array2, array, nl)); 83809566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(nullv, &array2)); 83819566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(pcbddc->coarse_vec, (const PetscScalar **)&array)); 83829566063dSJacob Faibussowitsch PetscCall(VecNormalize(nullv, NULL)); 83839566063dSJacob Faibussowitsch PetscCall(MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat), PETSC_FALSE, 1, &nullv, &CoarseNullSpace)); 83849566063dSJacob Faibussowitsch PetscCall(VecDestroy(&nullv)); 8385b0f5fe93SStefano Zampini } 8386b0f5fe93SStefano Zampini } 83879566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_CoarseSetUp[pcbddc->current_level], pc, 0, 0, 0)); 8388b0f5fe93SStefano Zampini 83899566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_CoarseSolver[pcbddc->current_level], pc, 0, 0, 0)); 8390b0f5fe93SStefano Zampini if (pcbddc->coarse_ksp) { 8391b0f5fe93SStefano Zampini PetscBool ispreonly; 8392b0f5fe93SStefano Zampini 8393b0f5fe93SStefano Zampini if (CoarseNullSpace) { 8394b0f5fe93SStefano Zampini PetscBool isnull; 83957c625d9fSStefano Zampini 83969566063dSJacob Faibussowitsch PetscCall(MatNullSpaceTest(CoarseNullSpace, coarse_mat, &isnull)); 83971baa6e33SBarry Smith if (isnull) PetscCall(MatSetNullSpace(coarse_mat, CoarseNullSpace)); 8398bef83e63SStefano Zampini /* TODO: add local nullspaces (if any) */ 8399b0f5fe93SStefano Zampini } 8400b0f5fe93SStefano Zampini /* setup coarse ksp */ 84019566063dSJacob Faibussowitsch PetscCall(KSPSetUp(pcbddc->coarse_ksp)); 8402cbcc2c2aSStefano Zampini /* Check coarse problem if in debug mode or if solving with an iterative method */ 84039566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp, KSPPREONLY, &ispreonly)); 84046e683305SStefano Zampini if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates)) { 8405c8587f34SStefano Zampini KSP check_ksp; 84062b510759SStefano Zampini KSPType check_ksp_type; 8407c8587f34SStefano Zampini PC check_pc; 84086e683305SStefano Zampini Vec check_vec, coarse_vec; 84096a1308c2SStefano Zampini PetscReal abs_infty_error, infty_error, lambda_min = 1.0, lambda_max = 1.0; 84102b510759SStefano Zampini PetscInt its; 84116e683305SStefano Zampini PetscBool compute_eigs; 84126e683305SStefano Zampini PetscReal *eigs_r, *eigs_c; 84136e683305SStefano Zampini PetscInt neigs; 84148e185a42SStefano Zampini const char *prefix; 8415c8587f34SStefano Zampini 84162b510759SStefano Zampini /* Create ksp object suitable for estimation of extreme eigenvalues */ 84179566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp), &check_ksp)); 84189566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)check_ksp, (PetscObject)pcbddc->coarse_ksp, 0)); 84199566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(pcbddc->coarse_ksp, PETSC_FALSE)); 84209566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(check_ksp, coarse_mat, coarse_mat)); 84219566063dSJacob Faibussowitsch PetscCall(KSPSetTolerances(check_ksp, 1.e-12, 1.e-12, PETSC_DEFAULT, pcbddc->coarse_size)); 8422e4d548c7SStefano Zampini /* prevent from setup unneeded object */ 84239566063dSJacob Faibussowitsch PetscCall(KSPGetPC(check_ksp, &check_pc)); 84249566063dSJacob Faibussowitsch PetscCall(PCSetType(check_pc, PCNONE)); 84252b510759SStefano Zampini if (ispreonly) { 84262b510759SStefano Zampini check_ksp_type = KSPPREONLY; 84276e683305SStefano Zampini compute_eigs = PETSC_FALSE; 84282b510759SStefano Zampini } else { 8429cbcc2c2aSStefano Zampini check_ksp_type = KSPGMRES; 84306e683305SStefano Zampini compute_eigs = PETSC_TRUE; 8431c8587f34SStefano Zampini } 84329566063dSJacob Faibussowitsch PetscCall(KSPSetType(check_ksp, check_ksp_type)); 84339566063dSJacob Faibussowitsch PetscCall(KSPSetComputeSingularValues(check_ksp, compute_eigs)); 84349566063dSJacob Faibussowitsch PetscCall(KSPSetComputeEigenvalues(check_ksp, compute_eigs)); 84359566063dSJacob Faibussowitsch PetscCall(KSPGMRESSetRestart(check_ksp, pcbddc->coarse_size + 1)); 84369566063dSJacob Faibussowitsch PetscCall(KSPGetOptionsPrefix(pcbddc->coarse_ksp, &prefix)); 84379566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(check_ksp, prefix)); 84389566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(check_ksp, "check_")); 84399566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(check_ksp)); 84409566063dSJacob Faibussowitsch PetscCall(KSPSetUp(check_ksp)); 84419566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &check_pc)); 84429566063dSJacob Faibussowitsch PetscCall(KSPSetPC(check_ksp, check_pc)); 8443c8587f34SStefano Zampini /* create random vec */ 84449566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(coarse_mat, &coarse_vec, &check_vec)); 84459566063dSJacob Faibussowitsch PetscCall(VecSetRandom(check_vec, NULL)); 84469566063dSJacob Faibussowitsch PetscCall(MatMult(coarse_mat, check_vec, coarse_vec)); 8447c8587f34SStefano Zampini /* solve coarse problem */ 84489566063dSJacob Faibussowitsch PetscCall(KSPSolve(check_ksp, coarse_vec, coarse_vec)); 84499566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(check_ksp, pc, coarse_vec)); 8450cbcc2c2aSStefano Zampini /* set eigenvalue estimation if preonly has not been requested */ 84516e683305SStefano Zampini if (compute_eigs) { 84529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->coarse_size + 1, &eigs_r)); 84539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->coarse_size + 1, &eigs_c)); 84549566063dSJacob Faibussowitsch PetscCall(KSPComputeEigenvalues(check_ksp, pcbddc->coarse_size + 1, eigs_r, eigs_c, &neigs)); 84551ae86dd6SStefano Zampini if (neigs) { 84566e683305SStefano Zampini lambda_max = eigs_r[neigs - 1]; 84576e683305SStefano Zampini lambda_min = eigs_r[0]; 84586e683305SStefano Zampini if (pcbddc->use_coarse_estimates) { 84592701bc32SStefano Zampini if (lambda_max >= lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */ 84609566063dSJacob Faibussowitsch PetscCall(KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp, lambda_max + PETSC_SMALL, lambda_min)); 84619566063dSJacob Faibussowitsch PetscCall(KSPRichardsonSetScale(pcbddc->coarse_ksp, 2.0 / (lambda_max + lambda_min))); 8462cbcc2c2aSStefano Zampini } 8463c8587f34SStefano Zampini } 8464c8587f34SStefano Zampini } 84651ae86dd6SStefano Zampini } 8466cbcc2c2aSStefano Zampini 8467c8587f34SStefano Zampini /* check coarse problem residual error */ 84686e683305SStefano Zampini if (pcbddc->dbg_flag) { 84696e683305SStefano Zampini PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp)); 84709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIAddTab(dbg_viewer, 2 * (pcbddc->current_level + 1))); 84719566063dSJacob Faibussowitsch PetscCall(VecAXPY(check_vec, -1.0, coarse_vec)); 84729566063dSJacob Faibussowitsch PetscCall(VecNorm(check_vec, NORM_INFINITY, &infty_error)); 84739566063dSJacob Faibussowitsch PetscCall(MatMult(coarse_mat, check_vec, coarse_vec)); 84749566063dSJacob Faibussowitsch PetscCall(VecNorm(coarse_vec, NORM_INFINITY, &abs_infty_error)); 84759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(dbg_viewer, "Coarse problem details (use estimates %d)\n", pcbddc->use_coarse_estimates)); 84769566063dSJacob Faibussowitsch PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp), dbg_viewer)); 84779566063dSJacob Faibussowitsch PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc), dbg_viewer)); 847863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(dbg_viewer, "Coarse problem exact infty_error : %1.6e\n", (double)infty_error)); 847963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(dbg_viewer, "Coarse problem residual infty_error: %1.6e\n", (double)abs_infty_error)); 848048a46eb9SPierre Jolivet if (CoarseNullSpace) PetscCall(PetscViewerASCIIPrintf(dbg_viewer, "Coarse problem is singular\n")); 84816e683305SStefano Zampini if (compute_eigs) { 84826e683305SStefano Zampini PetscReal lambda_max_s, lambda_min_s; 8483b03ebc13SStefano Zampini KSPConvergedReason reason; 84849566063dSJacob Faibussowitsch PetscCall(KSPGetType(check_ksp, &check_ksp_type)); 84859566063dSJacob Faibussowitsch PetscCall(KSPGetIterationNumber(check_ksp, &its)); 84869566063dSJacob Faibussowitsch PetscCall(KSPGetConvergedReason(check_ksp, &reason)); 84879566063dSJacob Faibussowitsch PetscCall(KSPComputeExtremeSingularValues(check_ksp, &lambda_max_s, &lambda_min_s)); 848863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(dbg_viewer, "Coarse problem eigenvalues (estimated with %" PetscInt_FMT " iterations of %s, conv reason %d): %1.6e %1.6e (%1.6e %1.6e)\n", its, check_ksp_type, reason, (double)lambda_min, (double)lambda_max, (double)lambda_min_s, (double)lambda_max_s)); 848948a46eb9SPierre Jolivet for (i = 0; i < neigs; i++) PetscCall(PetscViewerASCIIPrintf(dbg_viewer, "%1.6e %1.6ei\n", (double)eigs_r[i], (double)eigs_c[i])); 84906e683305SStefano Zampini } 84919566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(dbg_viewer)); 84929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISubtractTab(dbg_viewer, 2 * (pcbddc->current_level + 1))); 84936e683305SStefano Zampini } 84949566063dSJacob Faibussowitsch PetscCall(VecDestroy(&check_vec)); 84959566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coarse_vec)); 84969566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&check_ksp)); 84976e683305SStefano Zampini if (compute_eigs) { 84989566063dSJacob Faibussowitsch PetscCall(PetscFree(eigs_r)); 84999566063dSJacob Faibussowitsch PetscCall(PetscFree(eigs_c)); 8500c8587f34SStefano Zampini } 85016e683305SStefano Zampini } 85026e683305SStefano Zampini } 85039566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&CoarseNullSpace)); 8504cbcc2c2aSStefano Zampini /* print additional info */ 8505cbcc2c2aSStefano Zampini if (pcbddc->dbg_flag) { 85066e683305SStefano Zampini /* waits until all processes reaches this point */ 85079566063dSJacob Faibussowitsch PetscCall(PetscBarrier((PetscObject)pc)); 850863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Coarse solver setup completed at level %" PetscInt_FMT "\n", pcbddc->current_level)); 85099566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 8510cbcc2c2aSStefano Zampini } 8511cbcc2c2aSStefano Zampini 85122b510759SStefano Zampini /* free memory */ 85139566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_mat)); 85149566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_CoarseSolver[pcbddc->current_level], pc, 0, 0, 0)); 85153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8516c8587f34SStefano Zampini } 8517674ae819SStefano Zampini 8518d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCComputePrimalNumbering(PC pc, PetscInt *coarse_size_n, PetscInt **local_primal_indices_n) 8519d71ae5a4SJacob Faibussowitsch { 8520f34684f1SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 8521f34684f1SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 8522f34684f1SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 8523dc456d91SStefano Zampini IS subset, subset_mult, subset_n; 8524dc456d91SStefano Zampini PetscInt local_size, coarse_size = 0; 852573be2a3aSStefano Zampini PetscInt *local_primal_indices = NULL; 8526dc456d91SStefano Zampini const PetscInt *t_local_primal_indices; 8527f34684f1SStefano Zampini 8528f34684f1SStefano Zampini PetscFunctionBegin; 8529f34684f1SStefano Zampini /* Compute global number of coarse dofs */ 853008401ef6SPierre Jolivet PetscCheck(!pcbddc->local_primal_size || pcbddc->local_primal_ref_node, PETSC_COMM_SELF, PETSC_ERR_PLIB, "BDDC ConstraintsSetUp should be called first"); 85319566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)), pcbddc->local_primal_size_cc, pcbddc->local_primal_ref_node, PETSC_COPY_VALUES, &subset_n)); 85329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(pcis->mapping, subset_n, &subset)); 85339566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subset_n)); 85349566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)(pc->pmat)), pcbddc->local_primal_size_cc, pcbddc->local_primal_ref_mult, PETSC_COPY_VALUES, &subset_mult)); 85359566063dSJacob Faibussowitsch PetscCall(ISRenumber(subset, subset_mult, &coarse_size, &subset_n)); 85369566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subset)); 85379566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subset_mult)); 85389566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(subset_n, &local_size)); 853963a3b9bcSJacob Faibussowitsch PetscCheck(local_size == pcbddc->local_primal_size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of local primal indices computed %" PetscInt_FMT " != %" PetscInt_FMT, local_size, pcbddc->local_primal_size); 85409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(local_size, &local_primal_indices)); 85419566063dSJacob Faibussowitsch PetscCall(ISGetIndices(subset_n, &t_local_primal_indices)); 85429566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(local_primal_indices, t_local_primal_indices, local_size)); 85439566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(subset_n, &t_local_primal_indices)); 85449566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subset_n)); 8545f34684f1SStefano Zampini 8546f34684f1SStefano Zampini /* check numbering */ 8547f34684f1SStefano Zampini if (pcbddc->dbg_flag) { 8548019a44ceSStefano Zampini PetscScalar coarsesum, *array, *array2; 8549dc456d91SStefano Zampini PetscInt i; 8550b9b85e73SStefano Zampini PetscBool set_error = PETSC_FALSE, set_error_reduced = PETSC_FALSE; 8551f34684f1SStefano Zampini 85529566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 85539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 85549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Check coarse indices\n")); 85559566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 8556019a44ceSStefano Zampini /* counter */ 85579566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_global, 0.0)); 85589566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_N, 1.0)); 85599566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_N, pcis->vec1_global, ADD_VALUES, SCATTER_REVERSE)); 85609566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_N, pcis->vec1_global, ADD_VALUES, SCATTER_REVERSE)); 85619566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_global, pcis->vec2_N, INSERT_VALUES, SCATTER_FORWARD)); 85629566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_global, pcis->vec2_N, INSERT_VALUES, SCATTER_FORWARD)); 85639566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_N, 0.0)); 856448a46eb9SPierre Jolivet for (i = 0; i < pcbddc->local_primal_size; i++) PetscCall(VecSetValue(pcis->vec1_N, pcbddc->primal_indices_local_idxs[i], 1.0, INSERT_VALUES)); 85659566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(pcis->vec1_N)); 85669566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(pcis->vec1_N)); 85679566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_global, 0.0)); 85689566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_N, pcis->vec1_global, ADD_VALUES, SCATTER_REVERSE)); 85699566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_N, pcis->vec1_global, ADD_VALUES, SCATTER_REVERSE)); 85709566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_global, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD)); 85719566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_global, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD)); 85729566063dSJacob Faibussowitsch PetscCall(VecGetArray(pcis->vec1_N, &array)); 85739566063dSJacob Faibussowitsch PetscCall(VecGetArray(pcis->vec2_N, &array2)); 8574f34684f1SStefano Zampini for (i = 0; i < pcis->n; i++) { 8575019a44ceSStefano Zampini if (array[i] != 0.0 && array[i] != array2[i]) { 85762c66d082SStefano Zampini PetscInt owned = (PetscInt)PetscRealPart(array[i]), gi; 857775c01103SStefano Zampini PetscInt neigh = (PetscInt)PetscRealPart(array2[i]); 8578b9b85e73SStefano Zampini set_error = PETSC_TRUE; 85799566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(pcis->mapping, 1, &i, &gi)); 858063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d: local index %" PetscInt_FMT " (gid %" PetscInt_FMT ") owned by %" PetscInt_FMT " processes instead of %" PetscInt_FMT "!\n", PetscGlobalRank, i, gi, owned, neigh)); 8581f34684f1SStefano Zampini } 8582f34684f1SStefano Zampini } 85839566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pcis->vec2_N, &array2)); 85841c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&set_error, &set_error_reduced, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 85859566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 8586f34684f1SStefano Zampini for (i = 0; i < pcis->n; i++) { 8587f34684f1SStefano Zampini if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0 / PetscRealPart(array[i]); 8588f34684f1SStefano Zampini } 85899566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pcis->vec1_N, &array)); 85909566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_global, 0.0)); 85919566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_N, pcis->vec1_global, ADD_VALUES, SCATTER_REVERSE)); 85929566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_N, pcis->vec1_global, ADD_VALUES, SCATTER_REVERSE)); 85939566063dSJacob Faibussowitsch PetscCall(VecSum(pcis->vec1_global, &coarsesum)); 859463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Size of coarse problem is %" PetscInt_FMT " (%lf)\n", coarse_size, (double)PetscRealPart(coarsesum))); 8595b9b85e73SStefano Zampini if (pcbddc->dbg_flag > 1 || set_error_reduced) { 8596ca8b9ea9SStefano Zampini PetscInt *gidxs; 8597ca8b9ea9SStefano Zampini 85989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->local_primal_size, &gidxs)); 85999566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(pcis->mapping, pcbddc->local_primal_size, pcbddc->primal_indices_local_idxs, gidxs)); 86009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Distribution of local primal indices\n")); 86019566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 86029566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d\n", PetscGlobalRank)); 8603f34684f1SStefano Zampini for (i = 0; i < pcbddc->local_primal_size; i++) { 860463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "local_primal_indices[%" PetscInt_FMT "]=%" PetscInt_FMT " (%" PetscInt_FMT ",%" PetscInt_FMT ")\n", i, local_primal_indices[i], pcbddc->primal_indices_local_idxs[i], gidxs[i])); 8605f34684f1SStefano Zampini } 86069566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 86079566063dSJacob Faibussowitsch PetscCall(PetscFree(gidxs)); 8608f34684f1SStefano Zampini } 86099566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 86109566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 861128b400f6SJacob Faibussowitsch PetscCheck(!set_error_reduced, PetscObjectComm((PetscObject)pc), PETSC_ERR_PLIB, "BDDC Numbering of coarse dofs failed"); 8612f34684f1SStefano Zampini } 86136080607fSStefano Zampini 8614f34684f1SStefano Zampini /* get back data */ 8615f34684f1SStefano Zampini *coarse_size_n = coarse_size; 8616f34684f1SStefano Zampini *local_primal_indices_n = local_primal_indices; 86173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8618674ae819SStefano Zampini } 8619674ae819SStefano Zampini 8620d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx, Vec gwork, Vec lwork, IS globalis, IS *localis) 8621d71ae5a4SJacob Faibussowitsch { 8622e456f2a8SStefano Zampini IS localis_t; 8623a7dc3881SStefano Zampini PetscInt i, lsize, *idxs, n; 8624e456f2a8SStefano Zampini PetscScalar *vals; 8625e456f2a8SStefano Zampini 8626e456f2a8SStefano Zampini PetscFunctionBegin; 8627a7dc3881SStefano Zampini /* get indices in local ordering exploiting local to global map */ 86289566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(globalis, &lsize)); 86299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(lsize, &vals)); 8630e456f2a8SStefano Zampini for (i = 0; i < lsize; i++) vals[i] = 1.0; 86319566063dSJacob Faibussowitsch PetscCall(ISGetIndices(globalis, (const PetscInt **)&idxs)); 86329566063dSJacob Faibussowitsch PetscCall(VecSet(gwork, 0.0)); 86339566063dSJacob Faibussowitsch PetscCall(VecSet(lwork, 0.0)); 86341035eff8SStefano Zampini if (idxs) { /* multilevel guard */ 86359566063dSJacob Faibussowitsch PetscCall(VecSetOption(gwork, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE)); 86369566063dSJacob Faibussowitsch PetscCall(VecSetValues(gwork, lsize, idxs, vals, INSERT_VALUES)); 86371035eff8SStefano Zampini } 86389566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(gwork)); 86399566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(globalis, (const PetscInt **)&idxs)); 86409566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 86419566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(gwork)); 8642a7dc3881SStefano Zampini /* now compute set in local ordering */ 86439566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(g2l_ctx, gwork, lwork, INSERT_VALUES, SCATTER_FORWARD)); 86449566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(g2l_ctx, gwork, lwork, INSERT_VALUES, SCATTER_FORWARD)); 86459566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(lwork, (const PetscScalar **)&vals)); 86469566063dSJacob Faibussowitsch PetscCall(VecGetSize(lwork, &n)); 8647a7dc3881SStefano Zampini for (i = 0, lsize = 0; i < n; i++) { 8648ad540459SPierre Jolivet if (PetscRealPart(vals[i]) > 0.5) lsize++; 8649e456f2a8SStefano Zampini } 86509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(lsize, &idxs)); 8651a7dc3881SStefano Zampini for (i = 0, lsize = 0; i < n; i++) { 8652ad540459SPierre Jolivet if (PetscRealPart(vals[i]) > 0.5) idxs[lsize++] = i; 8653e456f2a8SStefano Zampini } 86549566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(lwork, (const PetscScalar **)&vals)); 86559566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)gwork), lsize, idxs, PETSC_OWN_POINTER, &localis_t)); 8656e456f2a8SStefano Zampini *localis = localis_t; 86573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8658e456f2a8SStefano Zampini } 8659906d46d4SStefano Zampini 8660d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCComputeFakeChange(PC pc, PetscBool constraints, PCBDDCGraph graph, PCBDDCSubSchurs schurs, Mat *change, IS *change_primal, IS *change_primal_mult, PetscBool *change_with_qr) 8661d71ae5a4SJacob Faibussowitsch { 86627c625d9fSStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 86637c625d9fSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 86647c625d9fSStefano Zampini PC_IS *pcisf; 86657c625d9fSStefano Zampini PC_BDDC *pcbddcf; 86667c625d9fSStefano Zampini PC pcf; 86677c625d9fSStefano Zampini 86687c625d9fSStefano Zampini PetscFunctionBegin; 86697c625d9fSStefano Zampini PetscCall(PCCreate(PetscObjectComm((PetscObject)pc), &pcf)); 86707c625d9fSStefano Zampini PetscCall(PCSetOperators(pcf, pc->mat, pc->pmat)); 86717c625d9fSStefano Zampini PetscCall(PCSetType(pcf, PCBDDC)); 86727c625d9fSStefano Zampini 86737c625d9fSStefano Zampini pcisf = (PC_IS *)pcf->data; 867432fe681dSStefano Zampini pcbddcf = (PC_BDDC *)pcf->data; 867532fe681dSStefano Zampini 86767c625d9fSStefano Zampini pcisf->is_B_local = pcis->is_B_local; 86777c625d9fSStefano Zampini pcisf->vec1_N = pcis->vec1_N; 86787c625d9fSStefano Zampini pcisf->BtoNmap = pcis->BtoNmap; 86797c625d9fSStefano Zampini pcisf->n = pcis->n; 86807c625d9fSStefano Zampini pcisf->n_B = pcis->n_B; 86817c625d9fSStefano Zampini 86827c625d9fSStefano Zampini PetscCall(PetscFree(pcbddcf->mat_graph)); 868332fe681dSStefano Zampini PetscCall(PetscFree(pcbddcf->sub_schurs)); 86847c625d9fSStefano Zampini pcbddcf->mat_graph = graph ? graph : pcbddc->mat_graph; 868532fe681dSStefano Zampini pcbddcf->sub_schurs = schurs; 868632fe681dSStefano Zampini pcbddcf->adaptive_selection = schurs ? PETSC_TRUE : PETSC_FALSE; 868732fe681dSStefano Zampini pcbddcf->adaptive_threshold[0] = pcbddc->adaptive_threshold[0]; 868832fe681dSStefano Zampini pcbddcf->adaptive_threshold[1] = pcbddc->adaptive_threshold[1]; 868932fe681dSStefano Zampini pcbddcf->adaptive_nmin = pcbddc->adaptive_nmin; 869032fe681dSStefano Zampini pcbddcf->adaptive_nmax = pcbddc->adaptive_nmax; 86917c625d9fSStefano Zampini pcbddcf->use_faces = PETSC_TRUE; 869232fe681dSStefano Zampini pcbddcf->use_change_of_basis = (PetscBool)!constraints; 869332fe681dSStefano Zampini pcbddcf->use_change_on_faces = (PetscBool)!constraints; 869432fe681dSStefano Zampini pcbddcf->use_qr_single = (PetscBool)!constraints; 86957c625d9fSStefano Zampini pcbddcf->fake_change = PETSC_TRUE; 869632fe681dSStefano Zampini pcbddcf->dbg_flag = pcbddc->dbg_flag; 869732fe681dSStefano Zampini 869832fe681dSStefano Zampini PetscCall(PCBDDCAdaptiveSelection(pcf)); 86997c625d9fSStefano Zampini PetscCall(PCBDDCConstraintsSetUp(pcf)); 87007c625d9fSStefano Zampini 87017c625d9fSStefano Zampini *change = pcbddcf->ConstraintMatrix; 87027c625d9fSStefano Zampini if (change_primal) PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc->pmat), pcbddcf->local_primal_size_cc, pcbddcf->local_primal_ref_node, PETSC_COPY_VALUES, change_primal)); 87037c625d9fSStefano Zampini if (change_primal_mult) PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc->pmat), pcbddcf->local_primal_size_cc, pcbddcf->local_primal_ref_mult, PETSC_COPY_VALUES, change_primal_mult)); 87047c625d9fSStefano Zampini if (change_with_qr) *change_with_qr = pcbddcf->use_qr_single; 87057c625d9fSStefano Zampini 870632fe681dSStefano Zampini if (schurs) pcbddcf->sub_schurs = NULL; 87077c625d9fSStefano Zampini pcbddcf->ConstraintMatrix = NULL; 870832fe681dSStefano Zampini pcbddcf->mat_graph = NULL; 870932fe681dSStefano Zampini pcisf->is_B_local = NULL; 871032fe681dSStefano Zampini pcisf->vec1_N = NULL; 871132fe681dSStefano Zampini pcisf->BtoNmap = NULL; 87127c625d9fSStefano Zampini PetscCall(PCDestroy(&pcf)); 87133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 87147c625d9fSStefano Zampini } 87157c625d9fSStefano Zampini 8716d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpSubSchurs(PC pc) 8717d71ae5a4SJacob Faibussowitsch { 8718a64f4aa4SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 8719b96c3477SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 8720b96c3477SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 8721a64f4aa4SStefano Zampini Mat S_j; 8722b96c3477SStefano Zampini PetscInt *used_xadj, *used_adjncy; 8723b96c3477SStefano Zampini PetscBool free_used_adj; 8724b96c3477SStefano Zampini 8725b96c3477SStefano Zampini PetscFunctionBegin; 87269566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Schurs[pcbddc->current_level], pc, 0, 0, 0)); 8727b96c3477SStefano Zampini /* decide the adjacency to be used for determining internal problems for local schur on subsets */ 8728b96c3477SStefano Zampini free_used_adj = PETSC_FALSE; 872908122e43SStefano Zampini if (pcbddc->sub_schurs_layers == -1) { 8730b96c3477SStefano Zampini used_xadj = NULL; 8731b96c3477SStefano Zampini used_adjncy = NULL; 8732b96c3477SStefano Zampini } else { 873308122e43SStefano Zampini if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) { 873408122e43SStefano Zampini used_xadj = pcbddc->mat_graph->xadj; 873508122e43SStefano Zampini used_adjncy = pcbddc->mat_graph->adjncy; 873608122e43SStefano Zampini } else if (pcbddc->computed_rowadj) { 8737b96c3477SStefano Zampini used_xadj = pcbddc->mat_graph->xadj; 8738b96c3477SStefano Zampini used_adjncy = pcbddc->mat_graph->adjncy; 8739b96c3477SStefano Zampini } else { 87402fffb893SStefano Zampini PetscBool flg_row = PETSC_FALSE; 8741b96c3477SStefano Zampini const PetscInt *xadj, *adjncy; 8742b96c3477SStefano Zampini PetscInt nvtxs; 8743b96c3477SStefano Zampini 87449566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(pcbddc->local_mat, 0, PETSC_TRUE, PETSC_FALSE, &nvtxs, &xadj, &adjncy, &flg_row)); 87452fffb893SStefano Zampini if (flg_row) { 87469566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nvtxs + 1, &used_xadj, xadj[nvtxs], &used_adjncy)); 87479566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(used_xadj, xadj, nvtxs + 1)); 87489566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(used_adjncy, adjncy, xadj[nvtxs])); 8749b96c3477SStefano Zampini free_used_adj = PETSC_TRUE; 87502fffb893SStefano Zampini } else { 87512fffb893SStefano Zampini pcbddc->sub_schurs_layers = -1; 87522fffb893SStefano Zampini used_xadj = NULL; 87532fffb893SStefano Zampini used_adjncy = NULL; 87542fffb893SStefano Zampini } 87559566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(pcbddc->local_mat, 0, PETSC_TRUE, PETSC_FALSE, &nvtxs, &xadj, &adjncy, &flg_row)); 8756b96c3477SStefano Zampini } 8757b96c3477SStefano Zampini } 8758d5574798SStefano Zampini 8759d5574798SStefano Zampini /* setup sub_schurs data */ 87609566063dSJacob Faibussowitsch PetscCall(MatCreateSchurComplement(pcis->A_II, pcis->pA_II, pcis->A_IB, pcis->A_BI, pcis->A_BB, &S_j)); 8761df4d28bfSStefano Zampini if (!sub_schurs->schur_explicit) { 8762df4d28bfSStefano Zampini /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */ 87639566063dSJacob Faibussowitsch PetscCall(MatSchurComplementSetKSP(S_j, pcbddc->ksp_D)); 87649566063dSJacob Faibussowitsch PetscCall(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)); 8765a64f4aa4SStefano Zampini } else { 876672b8c272SStefano Zampini Mat change = NULL; 87679d54b7f4SStefano Zampini Vec scaling = NULL; 8768111315fdSstefano_zampini IS change_primal = NULL, iP; 8769111315fdSstefano_zampini PetscInt benign_n; 8770111315fdSstefano_zampini PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis; 87717ebab0bbSStefano Zampini PetscBool need_change = PETSC_FALSE; 8772111315fdSstefano_zampini PetscBool discrete_harmonic = PETSC_FALSE; 8773a3df083aSStefano Zampini 87745feab87aSStefano Zampini if (!pcbddc->use_vertices && reuse_solvers) { 87755feab87aSStefano Zampini PetscInt n_vertices; 87765feab87aSStefano Zampini 87779566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->is_vertices, &n_vertices)); 87782034aafcSStefano Zampini reuse_solvers = (PetscBool)!n_vertices; 87795feab87aSStefano Zampini } 8780a3df083aSStefano Zampini if (!pcbddc->benign_change_explicit) { 8781a3df083aSStefano Zampini benign_n = pcbddc->benign_n; 8782ca92afb2SStefano Zampini } else { 8783a3df083aSStefano Zampini benign_n = 0; 8784ca92afb2SStefano Zampini } 8785b7ab4a40SStefano Zampini /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc. 8786b7ab4a40SStefano Zampini We need a global reduction to avoid possible deadlocks. 8787b7ab4a40SStefano Zampini We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */ 878872b8c272SStefano Zampini if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) { 878922db5ddcSStefano Zampini PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change); 87901c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&have_loc_change, &need_change, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 879122db5ddcSStefano Zampini need_change = (PetscBool)(!need_change); 8792b7ab4a40SStefano Zampini } 87937c625d9fSStefano Zampini /* If the user defines additional constraints, we import them here */ 8794b7ab4a40SStefano Zampini if (need_change) { 879528b400f6SJacob Faibussowitsch PetscCheck(!pcbddc->sub_schurs_rebuild, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot compute change of basis with a different graph"); 879632fe681dSStefano Zampini PetscCall(PCBDDCComputeFakeChange(pc, PETSC_FALSE, NULL, NULL, &change, &change_primal, NULL, &sub_schurs->change_with_qr)); 879788c03ad3SStefano Zampini } 87989d54b7f4SStefano Zampini if (!pcbddc->use_deluxe_scaling) scaling = pcis->D; 8799111315fdSstefano_zampini 88009566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_iP", (PetscObject *)&iP)); 8801111315fdSstefano_zampini if (iP) { 8802d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)iP), sub_schurs->prefix, "BDDC sub_schurs options", "PC"); 88039566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-sub_schurs_discrete_harmonic", NULL, NULL, discrete_harmonic, &discrete_harmonic, NULL)); 8804d0609cedSBarry Smith PetscOptionsEnd(); 8805111315fdSstefano_zampini } 8806111315fdSstefano_zampini if (discrete_harmonic) { 8807111315fdSstefano_zampini Mat A; 88089566063dSJacob Faibussowitsch PetscCall(MatDuplicate(pcbddc->local_mat, MAT_COPY_VALUES, &A)); 88099566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumnsIS(A, iP, 1.0, NULL, NULL)); 88109566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A, "__KSPFETIDP_iP", (PetscObject)iP)); 88119371c9d4SSatish Balay PetscCall(PCBDDCSubSchursSetUp(sub_schurs, A, 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, 88129371c9d4SSatish Balay pcbddc->benign_zerodiag_subs, change, change_primal)); 88139566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 8814111315fdSstefano_zampini } else { 88159371c9d4SSatish Balay PetscCall(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, 88169371c9d4SSatish Balay pcbddc->benign_p0_lidx, pcbddc->benign_zerodiag_subs, change, change_primal)); 8817111315fdSstefano_zampini } 88189566063dSJacob Faibussowitsch PetscCall(MatDestroy(&change)); 88199566063dSJacob Faibussowitsch PetscCall(ISDestroy(&change_primal)); 8820ca92afb2SStefano Zampini } 88219566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_j)); 8822b96c3477SStefano Zampini 8823b96c3477SStefano Zampini /* free adjacency */ 88241baa6e33SBarry Smith if (free_used_adj) PetscCall(PetscFree2(used_xadj, used_adjncy)); 88259566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Schurs[pcbddc->current_level], pc, 0, 0, 0)); 88263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8827b96c3477SStefano Zampini } 8828b96c3477SStefano Zampini 8829d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCInitSubSchurs(PC pc) 8830d71ae5a4SJacob Faibussowitsch { 8831b96c3477SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 8832b96c3477SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 8833b96c3477SStefano Zampini PCBDDCGraph graph; 8834b96c3477SStefano Zampini 8835b96c3477SStefano Zampini PetscFunctionBegin; 8836b96c3477SStefano Zampini /* attach interface graph for determining subsets */ 883708122e43SStefano Zampini if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */ 88383301b35fSStefano Zampini IS verticesIS, verticescomm; 88393301b35fSStefano Zampini PetscInt vsize, *idxs; 8840b96c3477SStefano Zampini 88419566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &verticesIS)); 88429566063dSJacob Faibussowitsch PetscCall(ISGetSize(verticesIS, &vsize)); 88439566063dSJacob Faibussowitsch PetscCall(ISGetIndices(verticesIS, (const PetscInt **)&idxs)); 88449566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), vsize, idxs, PETSC_COPY_VALUES, &verticescomm)); 88459566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(verticesIS, (const PetscInt **)&idxs)); 88469566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &verticesIS)); 88479566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphCreate(&graph)); 88489566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphInit(graph, pcbddc->mat_graph->l2gmap, pcbddc->mat_graph->nvtxs_global, pcbddc->graphmaxcount)); 88499566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphSetUp(graph, pcbddc->mat_graph->custom_minimal_size, NULL, pcbddc->DirichletBoundariesLocal, 0, NULL, verticescomm)); 88509566063dSJacob Faibussowitsch PetscCall(ISDestroy(&verticescomm)); 88519566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphComputeConnectedComponents(graph)); 8852b96c3477SStefano Zampini } else { 8853b96c3477SStefano Zampini graph = pcbddc->mat_graph; 8854b96c3477SStefano Zampini } 8855e4d548c7SStefano Zampini /* print some info */ 88565c643e28SStefano Zampini if (pcbddc->dbg_flag && !pcbddc->sub_schurs_rebuild) { 8857e4d548c7SStefano Zampini IS vertices; 8858e4d548c7SStefano Zampini PetscInt nv, nedges, nfaces; 88599566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphASCIIView(graph, pcbddc->dbg_flag, pcbddc->dbg_viewer)); 88609566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(graph, &nfaces, NULL, &nedges, NULL, &vertices)); 88619566063dSJacob Faibussowitsch PetscCall(ISGetSize(vertices, &nv)); 88629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 88639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "--------------------------------------------------------------\n")); 886463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate vertices (%d)\n", PetscGlobalRank, nv, pcbddc->use_vertices)); 886563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate edges (%d)\n", PetscGlobalRank, nedges, pcbddc->use_edges)); 886663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate faces (%d)\n", PetscGlobalRank, nfaces, pcbddc->use_faces)); 88679566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 88689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer)); 88699566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(graph, &nfaces, NULL, &nedges, NULL, &vertices)); 8870e4d548c7SStefano Zampini } 8871b96c3477SStefano Zampini 8872b96c3477SStefano Zampini /* sub_schurs init */ 887348a46eb9SPierre Jolivet if (!pcbddc->sub_schurs) PetscCall(PCBDDCSubSchursCreate(&pcbddc->sub_schurs)); 887432fe681dSStefano Zampini PetscCall(PCBDDCSubSchursInit(pcbddc->sub_schurs, ((PetscObject)pc)->prefix, pcis->is_I_local, pcis->is_B_local, graph, pcis->BtoNmap, pcbddc->sub_schurs_rebuild, PETSC_FALSE)); 8875a64f4aa4SStefano Zampini 8876b96c3477SStefano Zampini /* free graph struct */ 887748a46eb9SPierre Jolivet if (pcbddc->sub_schurs_rebuild) PetscCall(PCBDDCGraphDestroy(&graph)); 88783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8879b96c3477SStefano Zampini } 8880fa34dd3eSStefano Zampini 8881d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCCheckOperator(PC pc) 8882d71ae5a4SJacob Faibussowitsch { 8883fa34dd3eSStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 8884fa34dd3eSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 8885fa34dd3eSStefano Zampini 8886fa34dd3eSStefano Zampini PetscFunctionBegin; 8887fa34dd3eSStefano Zampini if (pcbddc->n_vertices == pcbddc->local_primal_size) { 8888fa34dd3eSStefano Zampini IS zerodiag = NULL; 88894f1b2e48SStefano Zampini Mat S_j, B0_B = NULL; 8890fa34dd3eSStefano Zampini Vec dummy_vec = NULL, vec_check_B, vec_scale_P; 88914f1b2e48SStefano Zampini PetscScalar *p0_check, *array, *array2; 889275c01103SStefano Zampini PetscReal norm; 8893fa34dd3eSStefano Zampini PetscInt i; 8894fa34dd3eSStefano Zampini 8895fa34dd3eSStefano Zampini /* B0 and B0_B */ 8896fa34dd3eSStefano Zampini if (zerodiag) { 8897fa34dd3eSStefano Zampini IS dummy; 8898fa34dd3eSStefano Zampini 88999566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pcbddc->benign_n, 0, 1, &dummy)); 89009566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->benign_B0, dummy, pcis->is_B_local, MAT_INITIAL_MATRIX, &B0_B)); 89019566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(B0_B, NULL, &dummy_vec)); 89029566063dSJacob Faibussowitsch PetscCall(ISDestroy(&dummy)); 8903fa34dd3eSStefano Zampini } 8904fa34dd3eSStefano Zampini /* I need a primal vector to scale primal nodes since BDDC sums contibutions */ 89059566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcbddc->vec1_P, &vec_scale_P)); 89069566063dSJacob Faibussowitsch PetscCall(VecSet(pcbddc->vec1_P, 1.0)); 89079566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob, pcbddc->vec1_P, pcbddc->coarse_vec, ADD_VALUES, SCATTER_FORWARD)); 89089566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob, pcbddc->vec1_P, pcbddc->coarse_vec, ADD_VALUES, SCATTER_FORWARD)); 89099566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob, pcbddc->coarse_vec, vec_scale_P, INSERT_VALUES, SCATTER_REVERSE)); 89109566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob, pcbddc->coarse_vec, vec_scale_P, INSERT_VALUES, SCATTER_REVERSE)); 89119566063dSJacob Faibussowitsch PetscCall(VecReciprocal(vec_scale_P)); 8912fa34dd3eSStefano Zampini /* S_j */ 89139566063dSJacob Faibussowitsch PetscCall(MatCreateSchurComplement(pcis->A_II, pcis->pA_II, pcis->A_IB, pcis->A_BI, pcis->A_BB, &S_j)); 89149566063dSJacob Faibussowitsch PetscCall(MatSchurComplementSetKSP(S_j, pcbddc->ksp_D)); 8915fa34dd3eSStefano Zampini 8916fa34dd3eSStefano Zampini /* mimic vector in \widetilde{W}_\Gamma */ 89179566063dSJacob Faibussowitsch PetscCall(VecSetRandom(pcis->vec1_N, NULL)); 8918fa34dd3eSStefano Zampini /* continuous in primal space */ 89199566063dSJacob Faibussowitsch PetscCall(VecSetRandom(pcbddc->coarse_vec, NULL)); 89209566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob, pcbddc->coarse_vec, pcbddc->vec1_P, INSERT_VALUES, SCATTER_REVERSE)); 89219566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob, pcbddc->coarse_vec, pcbddc->vec1_P, INSERT_VALUES, SCATTER_REVERSE)); 89229566063dSJacob Faibussowitsch PetscCall(VecGetArray(pcbddc->vec1_P, &array)); 89239566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pcbddc->benign_n, &p0_check)); 89244f1b2e48SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) p0_check[i] = array[pcbddc->local_primal_size - pcbddc->benign_n + i]; 89259566063dSJacob Faibussowitsch PetscCall(VecSetValues(pcis->vec1_N, pcbddc->local_primal_size, pcbddc->local_primal_ref_node, array, INSERT_VALUES)); 89269566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pcbddc->vec1_P, &array)); 89279566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(pcis->vec1_N)); 89289566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(pcis->vec1_N)); 89299566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec1_N, pcis->vec2_B, INSERT_VALUES, SCATTER_FORWARD)); 89309566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec1_N, pcis->vec2_B, INSERT_VALUES, SCATTER_FORWARD)); 89319566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec2_B, &vec_check_B)); 89329566063dSJacob Faibussowitsch PetscCall(VecCopy(pcis->vec2_B, vec_check_B)); 8933fa34dd3eSStefano Zampini 8934fa34dd3eSStefano Zampini /* assemble rhs for coarse problem */ 8935fa34dd3eSStefano Zampini /* widetilde{S}_\Gamma w_\Gamma + \widetilde{B0}^T_B p0 */ 8936fa34dd3eSStefano Zampini /* local with Schur */ 89379566063dSJacob Faibussowitsch PetscCall(MatMult(S_j, pcis->vec2_B, pcis->vec1_B)); 8938fa34dd3eSStefano Zampini if (zerodiag) { 89399566063dSJacob Faibussowitsch PetscCall(VecGetArray(dummy_vec, &array)); 89404f1b2e48SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) array[i] = p0_check[i]; 89419566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(dummy_vec, &array)); 89429566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(B0_B, dummy_vec, pcis->vec1_B, pcis->vec1_B)); 8943fa34dd3eSStefano Zampini } 8944fa34dd3eSStefano Zampini /* sum on primal nodes the local contributions */ 89459566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 89469566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 89479566063dSJacob Faibussowitsch PetscCall(VecGetArray(pcis->vec1_N, &array)); 89489566063dSJacob Faibussowitsch PetscCall(VecGetArray(pcbddc->vec1_P, &array2)); 8949fa34dd3eSStefano Zampini for (i = 0; i < pcbddc->local_primal_size; i++) array2[i] = array[pcbddc->local_primal_ref_node[i]]; 89509566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pcbddc->vec1_P, &array2)); 89519566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pcis->vec1_N, &array)); 89529566063dSJacob Faibussowitsch PetscCall(VecSet(pcbddc->coarse_vec, 0.)); 89539566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob, pcbddc->vec1_P, pcbddc->coarse_vec, ADD_VALUES, SCATTER_FORWARD)); 89549566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob, pcbddc->vec1_P, pcbddc->coarse_vec, ADD_VALUES, SCATTER_FORWARD)); 89559566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob, pcbddc->coarse_vec, pcbddc->vec1_P, INSERT_VALUES, SCATTER_REVERSE)); 89569566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob, pcbddc->coarse_vec, pcbddc->vec1_P, INSERT_VALUES, SCATTER_REVERSE)); 89579566063dSJacob Faibussowitsch PetscCall(VecGetArray(pcbddc->vec1_P, &array)); 8958fa34dd3eSStefano Zampini /* scale primal nodes (BDDC sums contibutions) */ 89599566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(pcbddc->vec1_P, vec_scale_P, pcbddc->vec1_P)); 89609566063dSJacob Faibussowitsch PetscCall(VecSetValues(pcis->vec1_N, pcbddc->local_primal_size, pcbddc->local_primal_ref_node, array, INSERT_VALUES)); 89619566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pcbddc->vec1_P, &array)); 89629566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(pcis->vec1_N)); 89639566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(pcis->vec1_N)); 89649566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec1_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 89659566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec1_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 8966fa34dd3eSStefano Zampini /* global: \widetilde{B0}_B w_\Gamma */ 8967fa34dd3eSStefano Zampini if (zerodiag) { 89689566063dSJacob Faibussowitsch PetscCall(MatMult(B0_B, pcis->vec2_B, dummy_vec)); 89699566063dSJacob Faibussowitsch PetscCall(VecGetArray(dummy_vec, &array)); 89704f1b2e48SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) pcbddc->benign_p0[i] = array[i]; 89719566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(dummy_vec, &array)); 8972fa34dd3eSStefano Zampini } 8973fa34dd3eSStefano Zampini /* BDDC */ 89749566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_D, 0.)); 89759566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(pc, PETSC_FALSE)); 8976fa34dd3eSStefano Zampini 89779566063dSJacob Faibussowitsch PetscCall(VecCopy(pcis->vec1_B, pcis->vec2_B)); 89789566063dSJacob Faibussowitsch PetscCall(VecAXPY(pcis->vec1_B, -1.0, vec_check_B)); 89799566063dSJacob Faibussowitsch PetscCall(VecNorm(pcis->vec1_B, NORM_INFINITY, &norm)); 898063a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] BDDC local error is %1.4e\n", PetscGlobalRank, (double)norm)); 898148a46eb9SPierre Jolivet for (i = 0; i < pcbddc->benign_n; i++) PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%d] BDDC p0[%" PetscInt_FMT "] error is %1.4e\n", PetscGlobalRank, i, (double)PetscAbsScalar(pcbddc->benign_p0[i] - p0_check[i]))); 89829566063dSJacob Faibussowitsch PetscCall(PetscFree(p0_check)); 89839566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vec_scale_P)); 89849566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vec_check_B)); 89859566063dSJacob Faibussowitsch PetscCall(VecDestroy(&dummy_vec)); 89869566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_j)); 89879566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B0_B)); 8988fa34dd3eSStefano Zampini } 89893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8990fa34dd3eSStefano Zampini } 89911e0482f5SStefano Zampini 89921e0482f5SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h> 8993d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMPIAIJRestrict(Mat A, MPI_Comm ccomm, Mat *B) 8994d71ae5a4SJacob Faibussowitsch { 89951e0482f5SStefano Zampini Mat At; 89961e0482f5SStefano Zampini IS rows; 89971e0482f5SStefano Zampini PetscInt rst, ren; 89981e0482f5SStefano Zampini PetscLayout rmap; 89991e0482f5SStefano Zampini 90001e0482f5SStefano Zampini PetscFunctionBegin; 90011e0482f5SStefano Zampini rst = ren = 0; 90021e0482f5SStefano Zampini if (ccomm != MPI_COMM_NULL) { 90039566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(ccomm, &rmap)); 90049566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetSize(rmap, A->rmap->N)); 90059566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(rmap, 1)); 90069566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rmap)); 90079566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rmap, &rst, &ren)); 90081e0482f5SStefano Zampini } 90099566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), ren - rst, rst, 1, &rows)); 90109566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, rows, NULL, MAT_INITIAL_MATRIX, &At)); 90119566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rows)); 90121e0482f5SStefano Zampini 90131e0482f5SStefano Zampini if (ccomm != MPI_COMM_NULL) { 90141e0482f5SStefano Zampini Mat_MPIAIJ *a, *b; 90151e0482f5SStefano Zampini IS from, to; 90161e0482f5SStefano Zampini Vec gvec; 90171e0482f5SStefano Zampini PetscInt lsize; 90181e0482f5SStefano Zampini 90199566063dSJacob Faibussowitsch PetscCall(MatCreate(ccomm, B)); 90209566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B, ren - rst, PETSC_DECIDE, PETSC_DECIDE, At->cmap->N)); 90219566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, MATAIJ)); 90229566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&((*B)->rmap))); 90239566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp((*B)->cmap)); 90241e0482f5SStefano Zampini a = (Mat_MPIAIJ *)At->data; 90251e0482f5SStefano Zampini b = (Mat_MPIAIJ *)(*B)->data; 90269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(ccomm, &b->size)); 90279566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(ccomm, &b->rank)); 90289566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)a->A)); 90299566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)a->B)); 90301e0482f5SStefano Zampini b->A = a->A; 90311e0482f5SStefano Zampini b->B = a->B; 90321e0482f5SStefano Zampini 90331e0482f5SStefano Zampini b->donotstash = a->donotstash; 90341e0482f5SStefano Zampini b->roworiented = a->roworiented; 90350a545947SLisandro Dalcin b->rowindices = NULL; 90360a545947SLisandro Dalcin b->rowvalues = NULL; 90371e0482f5SStefano Zampini b->getrowactive = PETSC_FALSE; 90381e0482f5SStefano Zampini 90391e0482f5SStefano Zampini (*B)->rmap = rmap; 90401e0482f5SStefano Zampini (*B)->factortype = A->factortype; 90411e0482f5SStefano Zampini (*B)->assembled = PETSC_TRUE; 90421e0482f5SStefano Zampini (*B)->insertmode = NOT_SET_VALUES; 90431e0482f5SStefano Zampini (*B)->preallocated = PETSC_TRUE; 90441e0482f5SStefano Zampini 90451e0482f5SStefano Zampini if (a->colmap) { 90461e0482f5SStefano Zampini #if defined(PETSC_USE_CTABLE) 9047eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIDuplicate(a->colmap, &b->colmap)); 90481e0482f5SStefano Zampini #else 90499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(At->cmap->N, &b->colmap)); 90509566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(b->colmap, a->colmap, At->cmap->N)); 90511e0482f5SStefano Zampini #endif 90520a545947SLisandro Dalcin } else b->colmap = NULL; 90531e0482f5SStefano Zampini if (a->garray) { 90541e0482f5SStefano Zampini PetscInt len; 90551e0482f5SStefano Zampini len = a->B->cmap->n; 90569566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(len + 1, &b->garray)); 90579566063dSJacob Faibussowitsch if (len) PetscCall(PetscArraycpy(b->garray, a->garray, len)); 90580a545947SLisandro Dalcin } else b->garray = NULL; 90591e0482f5SStefano Zampini 90609566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)a->lvec)); 90611e0482f5SStefano Zampini b->lvec = a->lvec; 90621e0482f5SStefano Zampini 90631e0482f5SStefano Zampini /* cannot use VecScatterCopy */ 90649566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(b->lvec, &lsize)); 90659566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(ccomm, lsize, b->garray, PETSC_USE_POINTER, &from)); 90669566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, lsize, 0, 1, &to)); 90679566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(*B, &gvec, NULL)); 90689566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(gvec, from, b->lvec, to, &b->Mvctx)); 90699566063dSJacob Faibussowitsch PetscCall(ISDestroy(&from)); 90709566063dSJacob Faibussowitsch PetscCall(ISDestroy(&to)); 90719566063dSJacob Faibussowitsch PetscCall(VecDestroy(&gvec)); 90721e0482f5SStefano Zampini } 90739566063dSJacob Faibussowitsch PetscCall(MatDestroy(&At)); 90743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 90751e0482f5SStefano Zampini } 9076