11cf9b237SStefano Zampini #include <../src/mat/impls/aij/seq/aij.h> 25e5bbd0aSStefano Zampini #include <petsc/private/pcbddcimpl.h> 35e5bbd0aSStefano Zampini #include <petsc/private/pcbddcprivateimpl.h> 49de2952eSStefano Zampini #include <petsc/private/kernels/blockinvert.h> 5837cedc9SStefano Zampini #include <../src/mat/impls/dense/seq/dense.h> 6c80a6c00SStefano Zampini #include <petscdmplex.h> 7674ae819SStefano Zampini #include <petscblaslapack.h> 8daf8a457SStefano Zampini #include <petsc/private/sfimpl.h> 9c80a6c00SStefano Zampini #include <petsc/private/dmpleximpl.h> 107620a527SStefano Zampini #include <petscdmda.h> 11674ae819SStefano Zampini 121e0482f5SStefano Zampini static PetscErrorCode MatMPIAIJRestrict(Mat, MPI_Comm, Mat *); 131e0482f5SStefano Zampini 14f498cd09SStefano Zampini /* if range is true, it returns B s.t. span{B} = range(A) 15f498cd09SStefano Zampini if range is false, it returns B s.t. range(B) _|_ range(A) */ 16ba38deedSJacob Faibussowitsch static PetscErrorCode MatDenseOrthogonalRangeOrComplement(Mat A, PetscBool range, PetscInt lw, PetscScalar *work, PetscReal *rwork, Mat *B) 17d71ae5a4SJacob Faibussowitsch { 18a13144ffSStefano Zampini PetscScalar *uwork, *data, *U, ds = 0.; 19a13144ffSStefano Zampini PetscReal *sing; 20a13144ffSStefano Zampini PetscBLASInt bM, bN, lwork, lierr, di = 1; 21a13144ffSStefano Zampini PetscInt ulw, i, nr, nc, n; 22abee2b68SSebastian Grimberg #if defined(PETSC_USE_COMPLEX) 23abee2b68SSebastian Grimberg PetscReal *rwork2; 24abee2b68SSebastian Grimberg #endif 25a13144ffSStefano Zampini 26a13144ffSStefano Zampini PetscFunctionBegin; 279566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &nr, &nc)); 283ba16761SJacob Faibussowitsch if (!nr || !nc) PetscFunctionReturn(PETSC_SUCCESS); 29a13144ffSStefano Zampini 30a13144ffSStefano Zampini /* workspace */ 31a13144ffSStefano Zampini if (!work) { 32a13144ffSStefano Zampini ulw = PetscMax(PetscMax(1, 5 * PetscMin(nr, nc)), 3 * PetscMin(nr, nc) + PetscMax(nr, nc)); 339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ulw, &uwork)); 34a13144ffSStefano Zampini } else { 35a13144ffSStefano Zampini ulw = lw; 36a13144ffSStefano Zampini uwork = work; 37a13144ffSStefano Zampini } 38a13144ffSStefano Zampini n = PetscMin(nr, nc); 39a13144ffSStefano Zampini if (!rwork) { 409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &sing)); 41a13144ffSStefano Zampini } else { 42a13144ffSStefano Zampini sing = rwork; 43a13144ffSStefano Zampini } 44a13144ffSStefano Zampini 45a13144ffSStefano Zampini /* SVD */ 469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nr * nr, &U)); 479566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(nr, &bM)); 489566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(nc, &bN)); 499566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(ulw, &lwork)); 509566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(A, &data)); 519566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 52abee2b68SSebastian Grimberg #if !defined(PETSC_USE_COMPLEX) 53792fecdfSBarry Smith PetscCallBLAS("LAPACKgesvd", LAPACKgesvd_("A", "N", &bM, &bN, data, &bM, sing, U, &bM, &ds, &di, uwork, &lwork, &lierr)); 54abee2b68SSebastian Grimberg #else 559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(5 * n, &rwork2)); 56792fecdfSBarry Smith PetscCallBLAS("LAPACKgesvd", LAPACKgesvd_("A", "N", &bM, &bN, data, &bM, sing, U, &bM, &ds, &di, uwork, &lwork, rwork2, &lierr)); 579566063dSJacob Faibussowitsch PetscCall(PetscFree(rwork2)); 58abee2b68SSebastian Grimberg #endif 599566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 6028b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in GESVD Lapack routine %d", (int)lierr); 619566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(A, &data)); 629371c9d4SSatish Balay for (i = 0; i < n; i++) 639371c9d4SSatish Balay if (sing[i] < PETSC_SMALL) break; 6448a46eb9SPierre Jolivet if (!rwork) PetscCall(PetscFree(sing)); 6548a46eb9SPierre Jolivet if (!work) PetscCall(PetscFree(uwork)); 66a13144ffSStefano Zampini /* create B */ 67f498cd09SStefano Zampini if (!range) { 689566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, nr, nr - i, NULL, B)); 699566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(*B, &data)); 709566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data, U + nr * i, (nr - i) * nr)); 71f498cd09SStefano Zampini } else { 729566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, nr, i, NULL, B)); 739566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(*B, &data)); 749566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data, U, i * nr)); 75f498cd09SStefano Zampini } 769566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(*B, &data)); 779566063dSJacob Faibussowitsch PetscCall(PetscFree(U)); 783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 79a13144ffSStefano Zampini } 80a13144ffSStefano Zampini 811e0482f5SStefano Zampini /* TODO REMOVE */ 821e0482f5SStefano Zampini #if defined(PRINT_GDET) 831e0482f5SStefano Zampini static int inc = 0; 841e0482f5SStefano Zampini static int lev = 0; 851e0482f5SStefano Zampini #endif 861e0482f5SStefano Zampini 87ba38deedSJacob Faibussowitsch static PetscErrorCode PCBDDCComputeNedelecChangeEdge(Mat lG, IS edge, IS extrow, IS extcol, IS corners, Mat *Gins, Mat *GKins, PetscScalar cvals[2], PetscScalar *work, PetscReal *rwork) 88d71ae5a4SJacob Faibussowitsch { 89a13144ffSStefano Zampini Mat GE, GEd; 90a13144ffSStefano Zampini PetscInt rsize, csize, esize; 91a13144ffSStefano Zampini PetscScalar *ptr; 92a13144ffSStefano Zampini 93a13144ffSStefano Zampini PetscFunctionBegin; 949566063dSJacob Faibussowitsch PetscCall(ISGetSize(edge, &esize)); 953ba16761SJacob Faibussowitsch if (!esize) PetscFunctionReturn(PETSC_SUCCESS); 969566063dSJacob Faibussowitsch PetscCall(ISGetSize(extrow, &rsize)); 979566063dSJacob Faibussowitsch PetscCall(ISGetSize(extcol, &csize)); 98a13144ffSStefano Zampini 99a13144ffSStefano Zampini /* gradients */ 100a13144ffSStefano Zampini ptr = work + 5 * esize; 1019566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lG, extrow, extcol, MAT_INITIAL_MATRIX, &GE)); 1029566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, rsize, csize, ptr, Gins)); 1039566063dSJacob Faibussowitsch PetscCall(MatConvert(GE, MATSEQDENSE, MAT_REUSE_MATRIX, Gins)); 1049566063dSJacob Faibussowitsch PetscCall(MatDestroy(&GE)); 105a13144ffSStefano Zampini 106a13144ffSStefano Zampini /* constants */ 107a13144ffSStefano Zampini ptr += rsize * csize; 1089566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, esize, csize, ptr, &GEd)); 1099566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lG, edge, extcol, MAT_INITIAL_MATRIX, &GE)); 1109566063dSJacob Faibussowitsch PetscCall(MatConvert(GE, MATSEQDENSE, MAT_REUSE_MATRIX, &GEd)); 1119566063dSJacob Faibussowitsch PetscCall(MatDestroy(&GE)); 1129566063dSJacob Faibussowitsch PetscCall(MatDenseOrthogonalRangeOrComplement(GEd, PETSC_FALSE, 5 * esize, work, rwork, GKins)); 1139566063dSJacob Faibussowitsch PetscCall(MatDestroy(&GEd)); 1141e0482f5SStefano Zampini 1151e0482f5SStefano Zampini if (corners) { 1161e0482f5SStefano Zampini Mat GEc; 1171683a169SBarry Smith const PetscScalar *vals; 1181683a169SBarry Smith PetscScalar v; 1191e0482f5SStefano Zampini 1209566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lG, edge, corners, MAT_INITIAL_MATRIX, &GEc)); 1219566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(GEc, *GKins, MAT_INITIAL_MATRIX, 1.0, &GEd)); 1229566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(GEd, &vals)); 123a8f51744SPierre Jolivet /* v = PetscAbsScalar(vals[0]); */ 124637e8532SStefano Zampini v = 1.; 1251e0482f5SStefano Zampini cvals[0] = vals[0] / v; 1261e0482f5SStefano Zampini cvals[1] = vals[1] / v; 1279566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(GEd, &vals)); 1289566063dSJacob Faibussowitsch PetscCall(MatScale(*GKins, 1. / v)); 1291e0482f5SStefano Zampini #if defined(PRINT_GDET) 1301e0482f5SStefano Zampini { 1311e0482f5SStefano Zampini PetscViewer viewer; 1321e0482f5SStefano Zampini char filename[256]; 133a364092eSJacob Faibussowitsch PetscCall(PetscSNPrintf(filename, PETSC_STATIC_ARRAY_LENGTH(filename), "Gdet_l%d_r%d_cc%d.m", lev, PetscGlobalRank, inc++)); 1349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF, filename, &viewer)); 1359566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_MATLAB)); 1369566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)GEc, "GEc")); 1379566063dSJacob Faibussowitsch PetscCall(MatView(GEc, viewer)); 138f4f49eeaSPierre Jolivet PetscCall(PetscObjectSetName((PetscObject)*GKins, "GK")); 1399566063dSJacob Faibussowitsch PetscCall(MatView(*GKins, viewer)); 1409566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)GEd, "Gproj")); 1419566063dSJacob Faibussowitsch PetscCall(MatView(GEd, viewer)); 1429566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 1431e0482f5SStefano Zampini } 1441e0482f5SStefano Zampini #endif 1459566063dSJacob Faibussowitsch PetscCall(MatDestroy(&GEd)); 1469566063dSJacob Faibussowitsch PetscCall(MatDestroy(&GEc)); 1471e0482f5SStefano Zampini } 1483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 149a13144ffSStefano Zampini } 150a13144ffSStefano Zampini 1519de2952eSStefano Zampini static PetscErrorCode MatAIJExtractRows(Mat, IS, Mat *); 1529de2952eSStefano Zampini 153d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCNedelecSupport(PC pc) 154d71ae5a4SJacob Faibussowitsch { 155a13144ffSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 156a13144ffSStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 1570569b399SStefano Zampini Mat G, T, conn, lG, lGt, lGis, lGall, lGe, lGinit; 158a13144ffSStefano Zampini PetscSF sfv; 1591e0482f5SStefano Zampini ISLocalToGlobalMapping el2g, vl2g, fl2g, al2g; 160a13144ffSStefano Zampini MPI_Comm comm; 161c2151214SStefano Zampini IS lned, primals, allprimals, nedfieldlocal; 162c2151214SStefano Zampini IS *eedges, *extrows, *extcols, *alleedges; 1637d871cd7SStefano Zampini PetscBT btv, bte, btvc, btb, btbd, btvcand, btvi, btee, bter; 164a13144ffSStefano Zampini PetscScalar *vals, *work; 165a13144ffSStefano Zampini PetscReal *rwork; 166a13144ffSStefano Zampini const PetscInt *idxs, *ii, *jj, *iit, *jjt; 1671e0482f5SStefano Zampini PetscInt ne, nv, Lv, order, n, field; 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 /* one ref for the destruction of al2g, one for el2g */ 3039566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)al2g)); 3049566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)al2g)); 3051e0482f5SStefano Zampini el2g = al2g; 306c2151214SStefano Zampini fl2g = NULL; 307c2151214SStefano Zampini } 308a13144ffSStefano Zampini 309213b8bfaSStefano Zampini /* Start communication to drop connections for interior edges (for cc analysis only) */ 3109566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_leafdata, n)); 3119566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_rootdata, pc->pmat->rmap->n)); 312c2151214SStefano Zampini if (nedfieldlocal) { 3139566063dSJacob Faibussowitsch PetscCall(ISGetIndices(nedfieldlocal, &idxs)); 314c2151214SStefano Zampini for (i = 0; i < ne; i++) matis->sf_leafdata[idxs[i]] = 1; 3159566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(nedfieldlocal, &idxs)); 316c2151214SStefano Zampini } else { 317c2151214SStefano Zampini for (i = 0; i < ne; i++) matis->sf_leafdata[i] = 1; 318c2151214SStefano Zampini } 3199566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, matis->sf_leafdata, matis->sf_rootdata, MPI_SUM)); 3209566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, matis->sf_leafdata, matis->sf_rootdata, MPI_SUM)); 321213b8bfaSStefano Zampini 322213b8bfaSStefano Zampini if (!singular) { /* drop connections with interior edges to avoid unneeded communications and memory movements */ 3239566063dSJacob Faibussowitsch PetscCall(MatDuplicate(pcbddc->discretegradient, MAT_COPY_VALUES, &G)); 3249566063dSJacob Faibussowitsch PetscCall(MatSetOption(G, MAT_KEEP_NONZERO_PATTERN, PETSC_FALSE)); 3251e0482f5SStefano Zampini if (global) { 3261e0482f5SStefano Zampini PetscInt rst; 3271e0482f5SStefano Zampini 3289566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(G, &rst, NULL)); 329c2151214SStefano Zampini for (i = 0, cum = 0; i < pc->pmat->rmap->n; i++) { 330ad540459SPierre Jolivet if (matis->sf_rootdata[i] < 2) matis->sf_rootdata[cum++] = i + rst; 331c2151214SStefano Zampini } 3329566063dSJacob Faibussowitsch PetscCall(MatSetOption(G, MAT_NO_OFF_PROC_ZERO_ROWS, PETSC_TRUE)); 3339566063dSJacob Faibussowitsch PetscCall(MatZeroRows(G, cum, matis->sf_rootdata, 0., NULL, NULL)); 3341e0482f5SStefano Zampini } else { 3351e0482f5SStefano Zampini PetscInt *tbz; 3361e0482f5SStefano Zampini 3379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ne, &tbz)); 3389566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 3399566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 3409566063dSJacob Faibussowitsch PetscCall(ISGetIndices(nedfieldlocal, &idxs)); 3411e0482f5SStefano Zampini for (i = 0, cum = 0; i < ne; i++) 3429371c9d4SSatish Balay if (matis->sf_leafdata[idxs[i]] == 1) tbz[cum++] = i; 3439566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(nedfieldlocal, &idxs)); 3449566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(el2g, cum, tbz, tbz)); 3459566063dSJacob Faibussowitsch PetscCall(MatZeroRows(G, cum, tbz, 0., NULL, NULL)); 3469566063dSJacob Faibussowitsch PetscCall(PetscFree(tbz)); 3471e0482f5SStefano Zampini } 348213b8bfaSStefano Zampini } else { /* we need the entire G to infer the nullspace */ 3499566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->discretegradient)); 350213b8bfaSStefano Zampini G = pcbddc->discretegradient; 351213b8bfaSStefano Zampini } 352a13144ffSStefano Zampini 353a13144ffSStefano Zampini /* Extract subdomain relevant rows of G */ 3549566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(el2g, &idxs)); 3559566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, ne, idxs, PETSC_USE_POINTER, &lned)); 3569de2952eSStefano Zampini PetscCall(MatAIJExtractRows(G, lned, &lGall)); 3579de2952eSStefano Zampini /* PetscCall(MatCreateSubMatrix(G, lned, NULL, MAT_INITIAL_MATRIX, &lGall)); */ 3589566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(el2g, &idxs)); 3599566063dSJacob Faibussowitsch PetscCall(ISDestroy(&lned)); 3609566063dSJacob Faibussowitsch PetscCall(MatConvert(lGall, MATIS, MAT_INITIAL_MATRIX, &lGis)); 3619566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGall)); 3629566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(lGis, &lG)); 363a13144ffSStefano Zampini 3649de2952eSStefano Zampini if (matis->allow_repeated) { /* multi-element support */ 3659de2952eSStefano Zampini Mat *lGn, B; 3669de2952eSStefano Zampini IS *is_rows, *tcols, tmap, nmap; 3679de2952eSStefano Zampini PetscInt subnv; 3689de2952eSStefano Zampini const PetscInt *subvidxs; 3699de2952eSStefano Zampini ISLocalToGlobalMapping mapn; 3709de2952eSStefano Zampini 3719de2952eSStefano Zampini PetscCall(PetscCalloc1(pcbddc->n_local_subs * pcbddc->n_local_subs, &lGn)); 3729de2952eSStefano Zampini PetscCall(PetscMalloc1(pcbddc->n_local_subs, &is_rows)); 3739de2952eSStefano Zampini PetscCall(PetscMalloc1(pcbddc->n_local_subs, &tcols)); 3749de2952eSStefano Zampini for (PetscInt i = 0; i < pcbddc->n_local_subs; i++) { 3759de2952eSStefano Zampini if (fl2g) { 3769de2952eSStefano Zampini PetscCall(ISGlobalToLocalMappingApplyIS(fl2g, IS_GTOLM_MASK, pcbddc->local_subs[i], &is_rows[i])); 3779de2952eSStefano Zampini } else { 3789de2952eSStefano Zampini PetscCall(PetscObjectReference((PetscObject)pcbddc->local_subs[i])); 3799de2952eSStefano Zampini is_rows[i] = pcbddc->local_subs[i]; 3809de2952eSStefano Zampini } 3819de2952eSStefano Zampini PetscCall(MatCreateSubMatrix(lG, is_rows[i], NULL, MAT_INITIAL_MATRIX, &lGn[i * (1 + pcbddc->n_local_subs)])); 3829de2952eSStefano Zampini PetscCall(MatSeqAIJCompactOutExtraColumns_SeqAIJ(lGn[i * (1 + pcbddc->n_local_subs)], &mapn)); 3839de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingGetSize(mapn, &subnv)); 3849de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingGetIndices(mapn, &subvidxs)); 3859de2952eSStefano Zampini PetscCall(ISCreateGeneral(PETSC_COMM_SELF, subnv, subvidxs, PETSC_COPY_VALUES, &tcols[i])); 3869de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingRestoreIndices(mapn, &subvidxs)); 3879de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingDestroy(&mapn)); 3889de2952eSStefano Zampini } 3899de2952eSStefano Zampini 3909de2952eSStefano Zampini /* Create new MATIS with repeated vertices */ 3919de2952eSStefano Zampini PetscCall(MatCreate(comm, &B)); 3929de2952eSStefano Zampini PetscCall(MatSetSizes(B, lGis->rmap->n, lGis->cmap->n, lGis->rmap->N, lGis->cmap->N)); 3939de2952eSStefano Zampini PetscCall(MatSetType(B, MATIS)); 3949de2952eSStefano Zampini PetscCall(MatISSetAllowRepeated(B, PETSC_TRUE)); 3959de2952eSStefano Zampini PetscCall(ISConcatenate(PETSC_COMM_SELF, pcbddc->n_local_subs, tcols, &tmap)); 3969de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingApplyIS(lGis->cmap->mapping, tmap, &nmap)); 3979de2952eSStefano Zampini PetscCall(ISDestroy(&tmap)); 3989de2952eSStefano Zampini PetscCall(ISGetLocalSize(nmap, &subnv)); 3999de2952eSStefano Zampini PetscCall(ISGetIndices(nmap, &subvidxs)); 4009de2952eSStefano Zampini PetscCall(ISCreateGeneral(comm, subnv, subvidxs, PETSC_USE_POINTER, &tmap)); 4019de2952eSStefano Zampini PetscCall(ISRestoreIndices(nmap, &subvidxs)); 4029de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingCreateIS(tmap, &mapn)); 4039de2952eSStefano Zampini PetscCall(ISDestroy(&tmap)); 4049de2952eSStefano Zampini PetscCall(ISDestroy(&nmap)); 4059de2952eSStefano Zampini PetscCall(MatSetLocalToGlobalMapping(B, lGis->rmap->mapping, mapn)); 4069de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingDestroy(&mapn)); 4079de2952eSStefano Zampini PetscCall(MatCreateNest(PETSC_COMM_SELF, pcbddc->n_local_subs, is_rows, pcbddc->n_local_subs, NULL, lGn, &lG)); 4089de2952eSStefano Zampini for (PetscInt i = 0; i < pcbddc->n_local_subs; i++) { 4099de2952eSStefano Zampini PetscCall(MatDestroy(&lGn[i * (1 + pcbddc->n_local_subs)])); 4109de2952eSStefano Zampini PetscCall(ISDestroy(&is_rows[i])); 4119de2952eSStefano Zampini PetscCall(ISDestroy(&tcols[i])); 4129de2952eSStefano Zampini } 4139de2952eSStefano Zampini PetscCall(MatConvert(lG, MATSEQAIJ, MAT_INPLACE_MATRIX, &lG)); 4149de2952eSStefano Zampini PetscCall(PetscFree(lGn)); 4159de2952eSStefano Zampini PetscCall(PetscFree(is_rows)); 4169de2952eSStefano Zampini PetscCall(PetscFree(tcols)); 4179de2952eSStefano Zampini PetscCall(MatISSetLocalMat(B, lG)); 4189de2952eSStefano Zampini PetscCall(MatDestroy(&lG)); 4199de2952eSStefano Zampini 4209de2952eSStefano Zampini PetscCall(MatDestroy(&lGis)); 4219de2952eSStefano Zampini lGis = B; 4229de2952eSStefano Zampini } 4239de2952eSStefano Zampini 424213b8bfaSStefano Zampini /* SF for nodal dofs communications */ 4259566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(G, NULL, &Lv)); 4269566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(lGis, NULL, &vl2g)); 4279566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)vl2g)); 4289566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(vl2g, &nv)); 4299566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &sfv)); 4309566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(vl2g, &idxs)); 4319566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(sfv, lGis->cmap, nv, NULL, PETSC_OWN_POINTER, idxs)); 4329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(vl2g, &idxs)); 433213b8bfaSStefano Zampini i = singular ? 2 : 1; 4349566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(i * nv, &sfvleaves, i * Lv, &sfvroots)); 435a13144ffSStefano Zampini 4361e0482f5SStefano Zampini /* Destroy temporary G created in MATIS format and modified G */ 4379de2952eSStefano Zampini PetscCall(MatISGetLocalMat(lGis, &lG)); 4389566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)lG)); 4399566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGis)); 4409566063dSJacob Faibussowitsch PetscCall(MatDestroy(&G)); 441a13144ffSStefano Zampini 442213b8bfaSStefano Zampini if (print) { 4439566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)lG, "initial_lG")); 4449566063dSJacob Faibussowitsch PetscCall(MatView(lG, NULL)); 445213b8bfaSStefano Zampini } 446213b8bfaSStefano Zampini 447213b8bfaSStefano Zampini /* Save lG for values insertion in change of basis */ 4489566063dSJacob Faibussowitsch PetscCall(MatDuplicate(lG, MAT_COPY_VALUES, &lGinit)); 4490569b399SStefano Zampini 450a13144ffSStefano Zampini /* Analyze the edge-nodes connections (duplicate lG) */ 4519566063dSJacob Faibussowitsch PetscCall(MatDuplicate(lG, MAT_COPY_VALUES, &lGe)); 4529566063dSJacob Faibussowitsch PetscCall(MatSetOption(lGe, MAT_KEEP_NONZERO_PATTERN, PETSC_FALSE)); 4539566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(nv, &btv)); 4549566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(ne, &bte)); 4559566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(ne, &btb)); 4569566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(ne, &btbd)); 4579566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(nv, &btvcand)); 458a13144ffSStefano Zampini /* need to import the boundary specification to ensure the 459a13144ffSStefano Zampini proper detection of coarse edges' endpoints */ 460a13144ffSStefano Zampini if (pcbddc->DirichletBoundariesLocal) { 461c2151214SStefano Zampini IS is; 462c2151214SStefano Zampini 463c2151214SStefano Zampini if (fl2g) { 4649566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(fl2g, IS_GTOLM_MASK, pcbddc->DirichletBoundariesLocal, &is)); 465c2151214SStefano Zampini } else { 466c2151214SStefano Zampini is = pcbddc->DirichletBoundariesLocal; 467c2151214SStefano Zampini } 4689566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &cum)); 4699566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, &idxs)); 470a13144ffSStefano Zampini for (i = 0; i < cum; i++) { 4719de2952eSStefano Zampini if (idxs[i] >= 0 && idxs[i] < ne) { 4729566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btb, idxs[i])); 4739566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btbd, idxs[i])); 474a13144ffSStefano Zampini } 475a13144ffSStefano Zampini } 4769566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, &idxs)); 47748a46eb9SPierre Jolivet if (fl2g) PetscCall(ISDestroy(&is)); 478a13144ffSStefano Zampini } 479a13144ffSStefano Zampini if (pcbddc->NeumannBoundariesLocal) { 480c2151214SStefano Zampini IS is; 481c2151214SStefano Zampini 482c2151214SStefano Zampini if (fl2g) { 4839566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(fl2g, IS_GTOLM_MASK, pcbddc->NeumannBoundariesLocal, &is)); 484c2151214SStefano Zampini } else { 485c2151214SStefano Zampini is = pcbddc->NeumannBoundariesLocal; 486c2151214SStefano Zampini } 4879566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &cum)); 4889566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, &idxs)); 489a13144ffSStefano Zampini for (i = 0; i < cum; i++) { 4909de2952eSStefano Zampini if (idxs[i] >= 0 && idxs[i] < ne) PetscCall(PetscBTSet(btb, idxs[i])); 491a13144ffSStefano Zampini } 4929566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, &idxs)); 49348a46eb9SPierre Jolivet if (fl2g) PetscCall(ISDestroy(&is)); 494c2151214SStefano Zampini } 495c2151214SStefano Zampini 496213b8bfaSStefano Zampini /* Count neighs per dof */ 4979de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingGetNodeInfo(el2g, NULL, &ecount, NULL)); 4989de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingGetNodeInfo(vl2g, NULL, &vcount, NULL)); 499637e8532SStefano Zampini 5007d871cd7SStefano Zampini /* need to remove coarse faces' dofs and coarse edges' dirichlet dofs 5017d871cd7SStefano Zampini for proper detection of coarse edges' endpoints */ 5029566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(ne, &btee)); 50362b0c6f7SStefano Zampini for (i = 0; i < ne; i++) { 50448a46eb9SPierre Jolivet if ((ecount[i] > 2 && !PetscBTLookup(btbd, i)) || (ecount[i] == 2 && PetscBTLookup(btb, i))) PetscCall(PetscBTSet(btee, i)); 50562b0c6f7SStefano Zampini } 5069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ne, &marks)); 50762b0c6f7SStefano Zampini if (!conforming) { 5089566063dSJacob Faibussowitsch PetscCall(MatTranspose(lGe, MAT_INITIAL_MATRIX, &lGt)); 5099566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 51062b0c6f7SStefano Zampini } 5119566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGe, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 5129566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(lGe, &vals)); 51362b0c6f7SStefano Zampini cum = 0; 514a13144ffSStefano Zampini for (i = 0; i < ne; i++) { 515dec27d64SStefano Zampini /* eliminate rows corresponding to edge dofs belonging to coarse faces */ 51662b0c6f7SStefano Zampini if (!PetscBTLookup(btee, i)) { 517a13144ffSStefano Zampini marks[cum++] = i; 518dec27d64SStefano Zampini continue; 519dec27d64SStefano Zampini } 520dec27d64SStefano Zampini /* set badly connected edge dofs as primal */ 52162b0c6f7SStefano Zampini if (!conforming) { 52262b0c6f7SStefano Zampini if (ii[i + 1] - ii[i] != order + 1) { /* every row of G on the coarse edge should list order+1 nodal dofs */ 523a13144ffSStefano Zampini marks[cum++] = i; 5249566063dSJacob Faibussowitsch PetscCall(PetscBTSet(bte, i)); 52548a46eb9SPierre Jolivet for (j = ii[i]; j < ii[i + 1]; j++) PetscCall(PetscBTSet(btv, jj[j])); 52662b0c6f7SStefano Zampini } else { 527aaa8cc7dSPierre Jolivet /* every edge dofs should be connected through a certain number of nodal dofs 52862b0c6f7SStefano Zampini to other edge dofs belonging to coarse edges 52962b0c6f7SStefano Zampini - at most 2 endpoints 53062b0c6f7SStefano Zampini - order-1 interior nodal dofs 53162b0c6f7SStefano Zampini - no undefined nodal dofs (nconn < order) 53262b0c6f7SStefano Zampini */ 53362b0c6f7SStefano Zampini PetscInt ends = 0, ints = 0, undef = 0; 53462b0c6f7SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 53562b0c6f7SStefano Zampini PetscInt v = jj[j], k; 53662b0c6f7SStefano Zampini PetscInt nconn = iit[v + 1] - iit[v]; 5379371c9d4SSatish Balay for (k = iit[v]; k < iit[v + 1]; k++) 5389371c9d4SSatish Balay if (!PetscBTLookup(btee, jjt[k])) nconn--; 53962b0c6f7SStefano Zampini if (nconn > order) ends++; 54062b0c6f7SStefano Zampini else if (nconn == order) ints++; 54162b0c6f7SStefano Zampini else undef++; 54262b0c6f7SStefano Zampini } 54362b0c6f7SStefano Zampini if (undef || ends > 2 || ints != order - 1) { 54462b0c6f7SStefano Zampini marks[cum++] = i; 5459566063dSJacob Faibussowitsch PetscCall(PetscBTSet(bte, i)); 54648a46eb9SPierre Jolivet for (j = ii[i]; j < ii[i + 1]; j++) PetscCall(PetscBTSet(btv, jj[j])); 54762b0c6f7SStefano Zampini } 54862b0c6f7SStefano Zampini } 549a13144ffSStefano Zampini } 550dec27d64SStefano Zampini /* We assume the order on the element edge is ii[i+1]-ii[i]-1 */ 551dec27d64SStefano Zampini if (!order && ii[i + 1] != ii[i]) { 552dec27d64SStefano Zampini PetscScalar val = 1. / (ii[i + 1] - ii[i] - 1); 553dec27d64SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) vals[j] = val; 554a13144ffSStefano Zampini } 555dec27d64SStefano Zampini } 5569566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btee)); 5579566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(lGe, &vals)); 5589566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGe, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 55962b0c6f7SStefano Zampini if (!conforming) { 5609566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 5619566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGt)); 56262b0c6f7SStefano Zampini } 5639566063dSJacob Faibussowitsch PetscCall(MatZeroRows(lGe, cum, marks, 0., NULL, NULL)); 564637e8532SStefano Zampini 5659de2952eSStefano Zampini if (matis->allow_repeated) { /* assign a uniq global id to edge local subsets and communicate it with nodal space */ 5669de2952eSStefano Zampini PetscSF emlsf, vmlsf; 5679de2952eSStefano Zampini PetscInt *eleaves, *vleaves, *meleaves, *mvleaves; 5689de2952eSStefano Zampini PetscInt cum_subs = 0, n_subs = pcbddc->n_local_subs, bs, emnr, emnl, vmnr, vmnl; 5699de2952eSStefano Zampini 5709de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockSize(el2g, &bs)); 5719de2952eSStefano Zampini PetscCheck(bs == 1, comm, PETSC_ERR_SUP, "Not coded"); 5729de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockSize(vl2g, &bs)); 5739de2952eSStefano Zampini PetscCheck(bs == 1, comm, PETSC_ERR_SUP, "Not coded"); 5749de2952eSStefano Zampini 5759de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockMultiLeavesSF(el2g, &emlsf)); 5769de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockMultiLeavesSF(vl2g, &vmlsf)); 5779de2952eSStefano Zampini 5789de2952eSStefano Zampini PetscCall(PetscSFGetGraph(emlsf, &emnr, &emnl, NULL, NULL)); 5799de2952eSStefano Zampini for (i = 0, j = 0; i < ne; i++) j += ecount[i]; 5809de2952eSStefano Zampini PetscCheck(emnr == ne, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of roots in edge multi-leaves SF %" PetscInt_FMT " != %" PetscInt_FMT, emnr, ne); 5819de2952eSStefano Zampini PetscCheck(emnl == j, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of leaves in edge multi-leaves SF %" PetscInt_FMT " != %" PetscInt_FMT, emnl, j); 5829de2952eSStefano Zampini 5839de2952eSStefano Zampini PetscCall(PetscSFGetGraph(vmlsf, &vmnr, &vmnl, NULL, NULL)); 5849de2952eSStefano Zampini for (i = 0, j = 0; i < nv; i++) j += vcount[i]; 5859de2952eSStefano Zampini PetscCheck(vmnr == nv, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of roots in nodal multi-leaves SF %" PetscInt_FMT " != %" PetscInt_FMT, vmnr, nv); 5869de2952eSStefano Zampini PetscCheck(vmnl == j, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of leaves in nodal multi-leaves SF %" PetscInt_FMT " != %" PetscInt_FMT, vmnl, j); 5879de2952eSStefano Zampini 5889de2952eSStefano Zampini PetscCall(PetscMalloc1(ne, &eleaves)); 5899de2952eSStefano Zampini PetscCall(PetscMalloc1(nv, &vleaves)); 5909de2952eSStefano Zampini for (i = 0; i < ne; i++) eleaves[i] = -1; 5919de2952eSStefano Zampini for (i = 0; i < nv; i++) vleaves[i] = -1; 5929de2952eSStefano Zampini PetscCall(PetscMalloc1(emnl, &meleaves)); 5939de2952eSStefano Zampini PetscCall(PetscMalloc1(vmnl, &mvleaves)); 5949de2952eSStefano Zampini 5959de2952eSStefano Zampini PetscCallMPI(MPI_Exscan(&n_subs, &cum_subs, 1, MPIU_INT, MPI_SUM, comm)); 5969de2952eSStefano Zampini PetscCall(MatGetRowIJ(lGe, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 5979de2952eSStefano Zampini for (i = 0; i < n_subs; i++) { 5989de2952eSStefano Zampini const PetscInt *idxs; 5999de2952eSStefano Zampini const PetscInt subid = cum_subs + i; 6009de2952eSStefano Zampini PetscInt ns; 6019de2952eSStefano Zampini 6029de2952eSStefano Zampini PetscCall(ISGetLocalSize(pcbddc->local_subs[i], &ns)); 6039de2952eSStefano Zampini PetscCall(ISGetIndices(pcbddc->local_subs[i], &idxs)); 6049de2952eSStefano Zampini for (j = 0; j < ns; j++) { 6059de2952eSStefano Zampini const PetscInt e = idxs[j]; 6069de2952eSStefano Zampini 6079de2952eSStefano Zampini eleaves[e] = subid; 6089de2952eSStefano Zampini for (PetscInt k = ii[e]; k < ii[e + 1]; k++) vleaves[jj[k]] = subid; 6099de2952eSStefano Zampini } 6109de2952eSStefano Zampini PetscCall(ISRestoreIndices(pcbddc->local_subs[i], &idxs)); 6119de2952eSStefano Zampini } 6129de2952eSStefano Zampini PetscCall(MatRestoreRowIJ(lGe, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 6139de2952eSStefano Zampini PetscCall(PetscSFBcastBegin(emlsf, MPIU_INT, eleaves, meleaves, MPI_REPLACE)); 6149de2952eSStefano Zampini PetscCall(PetscSFBcastEnd(emlsf, MPIU_INT, eleaves, meleaves, MPI_REPLACE)); 6159de2952eSStefano Zampini PetscCall(PetscSFBcastBegin(vmlsf, MPIU_INT, vleaves, mvleaves, MPI_REPLACE)); 6169de2952eSStefano Zampini PetscCall(PetscSFBcastEnd(vmlsf, MPIU_INT, vleaves, mvleaves, MPI_REPLACE)); 6179de2952eSStefano Zampini PetscCall(PetscFree(eleaves)); 6189de2952eSStefano Zampini PetscCall(PetscFree(vleaves)); 6199de2952eSStefano Zampini 6209de2952eSStefano Zampini PetscCall(PetscMalloc1(ne + 1, &eneighs)); 6219de2952eSStefano Zampini eneighs[0] = meleaves; 6229de2952eSStefano Zampini for (i = 1; i < ne; i++) { 6239de2952eSStefano Zampini PetscCall(PetscSortInt(ecount[i - 1], eneighs[i - 1])); 6249de2952eSStefano Zampini eneighs[i] = eneighs[i - 1] + ecount[i - 1]; 6259de2952eSStefano Zampini } 6269de2952eSStefano Zampini PetscCall(PetscMalloc1(nv + 1, &vneighs)); 6279de2952eSStefano Zampini vneighs[0] = mvleaves; 6289de2952eSStefano Zampini for (i = 1; i < nv; i++) { 6299de2952eSStefano Zampini PetscCall(PetscSortInt(vcount[i - 1], vneighs[i - 1])); 6309de2952eSStefano Zampini vneighs[i] = vneighs[i - 1] + vcount[i - 1]; 6319de2952eSStefano Zampini } 6329de2952eSStefano Zampini } else { 6339de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingGetNodeInfo(el2g, NULL, NULL, &eneighs)); 6349de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingGetNodeInfo(vl2g, NULL, NULL, &vneighs)); 6359de2952eSStefano Zampini } 6369de2952eSStefano Zampini 637b03ebc13SStefano Zampini /* identify splitpoints and corner candidates */ 6389566063dSJacob Faibussowitsch PetscCall(MatTranspose(lGe, MAT_INITIAL_MATRIX, &lGt)); 639a13144ffSStefano Zampini if (print) { 6409566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)lGe, "edgerestr_lG")); 6419566063dSJacob Faibussowitsch PetscCall(MatView(lGe, NULL)); 6429566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)lGt, "edgerestr_lGt")); 6439566063dSJacob Faibussowitsch PetscCall(MatView(lGt, NULL)); 644a13144ffSStefano Zampini } 6459566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 6469566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(lGt, &vals)); 647a13144ffSStefano Zampini for (i = 0; i < nv; i++) { 648637e8532SStefano Zampini PetscInt ord = order, test = ii[i + 1] - ii[i], vc = vcount[i]; 6497d871cd7SStefano Zampini PetscBool sneighs = PETSC_TRUE, bdir = PETSC_FALSE; 650b03ebc13SStefano Zampini if (!order) { /* variable order */ 651dec27d64SStefano Zampini PetscReal vorder = 0.; 652dec27d64SStefano Zampini 653dec27d64SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) vorder += PetscRealPart(vals[j]); 654dec27d64SStefano Zampini test = PetscFloorReal(vorder + 10. * PETSC_SQRT_MACHINE_EPSILON); 65563a3b9bcSJacob Faibussowitsch PetscCheck(vorder - test <= PETSC_SQRT_MACHINE_EPSILON, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected value for vorder: %g (%" PetscInt_FMT ")", (double)vorder, test); 656dec27d64SStefano Zampini ord = 1; 657dec27d64SStefano Zampini } 6586bdcaf15SBarry 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); 659637e8532SStefano Zampini for (j = ii[i]; j < ii[i + 1] && sneighs; j++) { 6609de2952eSStefano Zampini const PetscInt e = jj[j]; 6619de2952eSStefano Zampini 6629de2952eSStefano Zampini if (PetscBTLookup(btbd, e)) { 6637d871cd7SStefano Zampini bdir = PETSC_TRUE; 6647d871cd7SStefano Zampini break; 6657d871cd7SStefano Zampini } 6669de2952eSStefano Zampini if (vc != ecount[e]) { 667637e8532SStefano Zampini sneighs = PETSC_FALSE; 668637e8532SStefano Zampini } else { 6699de2952eSStefano Zampini const PetscInt *vn = vneighs[i], *en = eneighs[e]; 6709de2952eSStefano Zampini 6719de2952eSStefano Zampini for (PetscInt k = 0; k < vc; k++) { 672637e8532SStefano Zampini if (vn[k] != en[k]) { 673637e8532SStefano Zampini sneighs = PETSC_FALSE; 674637e8532SStefano Zampini break; 675637e8532SStefano Zampini } 676637e8532SStefano Zampini } 677637e8532SStefano Zampini } 678637e8532SStefano Zampini } 6797d871cd7SStefano Zampini if (!sneighs || test >= 3 * ord || bdir) { /* splitpoints */ 6803ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, "SPLITPOINT %" PetscInt_FMT " (%s %s %s)\n", i, PetscBools[!sneighs], PetscBools[test >= 3 * ord], PetscBools[bdir])); 6819566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, i)); 682dec27d64SStefano Zampini } else if (test == ord) { 683b03ebc13SStefano Zampini if (order == 1 || (!order && ii[i + 1] - ii[i] == 1)) { 6843ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, "ENDPOINT %" PetscInt_FMT "\n", i)); 6859566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, i)); 686a13144ffSStefano Zampini } else { 6873ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, "CORNER CANDIDATE %" PetscInt_FMT "\n", i)); 6889566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btvcand, i)); 689a13144ffSStefano Zampini } 690a13144ffSStefano Zampini } 691a13144ffSStefano Zampini } 6929566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btbd)); 693b03ebc13SStefano Zampini 694b03ebc13SStefano Zampini /* a candidate is valid if it is connected to another candidate via a non-primal edge dof */ 695b03ebc13SStefano Zampini if (order != 1) { 6963ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, "INSPECTING CANDIDATES\n")); 6979566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGe, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 698b03ebc13SStefano Zampini for (i = 0; i < nv; i++) { 699b03ebc13SStefano Zampini if (PetscBTLookup(btvcand, i)) { 700b03ebc13SStefano Zampini PetscBool found = PETSC_FALSE; 701b03ebc13SStefano Zampini for (j = ii[i]; j < ii[i + 1] && !found; j++) { 702b03ebc13SStefano Zampini PetscInt k, e = jj[j]; 703b03ebc13SStefano Zampini if (PetscBTLookup(bte, e)) continue; 704b03ebc13SStefano Zampini for (k = iit[e]; k < iit[e + 1]; k++) { 705b03ebc13SStefano Zampini PetscInt v = jjt[k]; 706b03ebc13SStefano Zampini if (v != i && PetscBTLookup(btvcand, v)) { 707b03ebc13SStefano Zampini found = PETSC_TRUE; 708b03ebc13SStefano Zampini break; 709b03ebc13SStefano Zampini } 710b03ebc13SStefano Zampini } 711b03ebc13SStefano Zampini } 712b03ebc13SStefano Zampini if (!found) { 7133ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " CANDIDATE %" PetscInt_FMT " CLEARED\n", i)); 7149566063dSJacob Faibussowitsch PetscCall(PetscBTClear(btvcand, i)); 715b03ebc13SStefano Zampini } else { 7163ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " CANDIDATE %" PetscInt_FMT " ACCEPTED\n", i)); 717b03ebc13SStefano Zampini } 718b03ebc13SStefano Zampini } 719b03ebc13SStefano Zampini } 7209566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGe, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 721b03ebc13SStefano Zampini } 7229566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(lGt, &vals)); 7239566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 7249566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGe)); 725a13144ffSStefano Zampini 726a13144ffSStefano Zampini /* Get the local G^T explicitly */ 7279566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGt)); 7289566063dSJacob Faibussowitsch PetscCall(MatTranspose(lG, MAT_INITIAL_MATRIX, &lGt)); 7299566063dSJacob Faibussowitsch PetscCall(MatSetOption(lGt, MAT_KEEP_NONZERO_PATTERN, PETSC_FALSE)); 730a13144ffSStefano Zampini 7319de2952eSStefano Zampini /* Mark shared nodal dofs */ 7329566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(nv, &btvi)); 7339de2952eSStefano Zampini for (i = 0; i < nv; i++) { 7349de2952eSStefano Zampini if (vcount[i] > 1) PetscCall(PetscBTSet(btvi, i)); 735a13144ffSStefano Zampini } 7369de2952eSStefano Zampini 7379de2952eSStefano Zampini if (matis->allow_repeated) { 7389de2952eSStefano Zampini PetscCall(PetscFree(eneighs[0])); 7399de2952eSStefano Zampini PetscCall(PetscFree(vneighs[0])); 7409de2952eSStefano Zampini PetscCall(PetscFree(eneighs)); 7419de2952eSStefano Zampini PetscCall(PetscFree(vneighs)); 7429de2952eSStefano Zampini } 7439de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(el2g, NULL, &ecount, &eneighs)); 7449de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(vl2g, NULL, &vcount, &vneighs)); 745a13144ffSStefano Zampini 746a13144ffSStefano Zampini /* communicate corners and splitpoints */ 7479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nv, &vmarks)); 7489566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(sfvleaves, nv)); 7499566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(sfvroots, Lv)); 7509371c9d4SSatish Balay for (i = 0; i < nv; i++) 7519371c9d4SSatish Balay if (PetscUnlikely(PetscBTLookup(btv, i))) sfvleaves[i] = 1; 752a13144ffSStefano Zampini 753a13144ffSStefano Zampini if (print) { 754a13144ffSStefano Zampini IS tbz; 755a13144ffSStefano Zampini 756a13144ffSStefano Zampini cum = 0; 757a13144ffSStefano Zampini for (i = 0; i < nv; i++) 7589371c9d4SSatish Balay if (sfvleaves[i]) vmarks[cum++] = i; 759a13144ffSStefano Zampini 7609566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cum, vmarks, PETSC_COPY_VALUES, &tbz)); 7619566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)tbz, "corners_to_be_zeroed_local")); 7629566063dSJacob Faibussowitsch PetscCall(ISView(tbz, NULL)); 7639566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tbz)); 764a13144ffSStefano Zampini } 765a13144ffSStefano Zampini 7669566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(sfv, MPIU_INT, sfvleaves, sfvroots, MPI_SUM)); 7679566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(sfv, MPIU_INT, sfvleaves, sfvroots, MPI_SUM)); 7689566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfv, MPIU_INT, sfvroots, sfvleaves, MPI_REPLACE)); 7699566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfv, MPIU_INT, sfvroots, sfvleaves, MPI_REPLACE)); 770a13144ffSStefano Zampini 7714e64d54eSstefano_zampini /* Zero rows of lGt corresponding to identified corners 7724e64d54eSstefano_zampini and interior nodal dofs */ 773a13144ffSStefano Zampini cum = 0; 774a13144ffSStefano Zampini for (i = 0; i < nv; i++) { 775a13144ffSStefano Zampini if (sfvleaves[i]) { 776a13144ffSStefano Zampini vmarks[cum++] = i; 7779566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, i)); 7789de2952eSStefano Zampini } else if (!PetscBTLookup(btvi, i)) vmarks[cum++] = i; 779a13144ffSStefano Zampini } 7809566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btvi)); 781a13144ffSStefano Zampini if (print) { 782a13144ffSStefano Zampini IS tbz; 783a13144ffSStefano Zampini 7849566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cum, vmarks, PETSC_COPY_VALUES, &tbz)); 7859566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)tbz, "corners_to_be_zeroed_with_interior")); 7869566063dSJacob Faibussowitsch PetscCall(ISView(tbz, NULL)); 7879566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tbz)); 788a13144ffSStefano Zampini } 7899566063dSJacob Faibussowitsch PetscCall(MatZeroRows(lGt, cum, vmarks, 0., NULL, NULL)); 7909566063dSJacob Faibussowitsch PetscCall(PetscFree(vmarks)); 7919566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfv)); 7929566063dSJacob Faibussowitsch PetscCall(PetscFree2(sfvleaves, sfvroots)); 793a13144ffSStefano Zampini 794a13144ffSStefano Zampini /* Recompute G */ 7959566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lG)); 7969566063dSJacob Faibussowitsch PetscCall(MatTranspose(lGt, MAT_INITIAL_MATRIX, &lG)); 797a13144ffSStefano Zampini if (print) { 7989566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)lG, "used_lG")); 7999566063dSJacob Faibussowitsch PetscCall(MatView(lG, NULL)); 8009566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)lGt, "used_lGt")); 8019566063dSJacob Faibussowitsch PetscCall(MatView(lGt, NULL)); 802a13144ffSStefano Zampini } 803a13144ffSStefano Zampini 804a13144ffSStefano Zampini /* Get primal dofs (if any) */ 805a13144ffSStefano Zampini cum = 0; 806a13144ffSStefano Zampini for (i = 0; i < ne; i++) { 807a13144ffSStefano Zampini if (PetscUnlikely(PetscBTLookup(bte, i))) marks[cum++] = i; 808a13144ffSStefano Zampini } 8091baa6e33SBarry Smith if (fl2g) PetscCall(ISLocalToGlobalMappingApply(fl2g, cum, marks, marks)); 8109566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, cum, marks, PETSC_COPY_VALUES, &primals)); 811a13144ffSStefano Zampini if (print) { 8129566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)primals, "prescribed_primal_dofs")); 8139566063dSJacob Faibussowitsch PetscCall(ISView(primals, NULL)); 814a13144ffSStefano Zampini } 8159566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&bte)); 816c2151214SStefano Zampini /* TODO: what if the user passed in some of them ? */ 8179566063dSJacob Faibussowitsch PetscCall(PCBDDCSetPrimalVerticesLocalIS(pc, primals)); 8189566063dSJacob Faibussowitsch PetscCall(ISDestroy(&primals)); 819a13144ffSStefano Zampini 820a13144ffSStefano Zampini /* Compute edge connectivity */ 8219566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)lG, "econn_")); 8224222ddf1SHong Zhang 8234222ddf1SHong Zhang /* Symbolic conn = lG*lGt */ 8249566063dSJacob Faibussowitsch PetscCall(MatProductCreate(lG, lGt, NULL, &conn)); 8259566063dSJacob Faibussowitsch PetscCall(MatProductSetType(conn, MATPRODUCT_AB)); 8269566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(conn, "default")); 8279566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(conn, PETSC_DEFAULT)); 8289566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)conn, "econn_")); 8299566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(conn)); 8309566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(conn)); 8319566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 832c2151214SStefano Zampini if (fl2g) { 833c2151214SStefano Zampini PetscBT btf; 834c2151214SStefano Zampini PetscInt *iia, *jja, *iiu, *jju; 835c2151214SStefano Zampini PetscBool rest = PETSC_FALSE, free = PETSC_FALSE; 836c2151214SStefano Zampini 837c2151214SStefano Zampini /* create CSR for all local dofs */ 8389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n + 1, &iia)); 839c2151214SStefano Zampini if (pcbddc->mat_graph->nvtxs_csr) { /* the user has passed in a CSR graph */ 84063a3b9bcSJacob 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); 841c2151214SStefano Zampini iiu = pcbddc->mat_graph->xadj; 842c2151214SStefano Zampini jju = pcbddc->mat_graph->adjncy; 843c2151214SStefano Zampini } else if (pcbddc->use_local_adj) { 844c2151214SStefano Zampini rest = PETSC_TRUE; 8459566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(matis->A, 0, PETSC_TRUE, PETSC_FALSE, &i, (const PetscInt **)&iiu, (const PetscInt **)&jju, &done)); 846c2151214SStefano Zampini } else { 847c2151214SStefano Zampini free = PETSC_TRUE; 8489566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n + 1, &iiu, n, &jju)); 849c2151214SStefano Zampini iiu[0] = 0; 850c2151214SStefano Zampini for (i = 0; i < n; i++) { 851c2151214SStefano Zampini iiu[i + 1] = i + 1; 852c2151214SStefano Zampini jju[i] = -1; 853d904f53bSStefano Zampini } 854c2151214SStefano Zampini } 855c2151214SStefano Zampini 856c2151214SStefano Zampini /* import sizes of CSR */ 857c2151214SStefano Zampini iia[0] = 0; 858c2151214SStefano Zampini for (i = 0; i < n; i++) iia[i + 1] = iiu[i + 1] - iiu[i]; 859c2151214SStefano Zampini 860c2151214SStefano Zampini /* overwrite entries corresponding to the Nedelec field */ 8619566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(n, &btf)); 8629566063dSJacob Faibussowitsch PetscCall(ISGetIndices(nedfieldlocal, &idxs)); 863c2151214SStefano Zampini for (i = 0; i < ne; i++) { 8649566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btf, idxs[i])); 865c2151214SStefano Zampini iia[idxs[i] + 1] = ii[i + 1] - ii[i]; 866c2151214SStefano Zampini } 867c2151214SStefano Zampini 868c2151214SStefano Zampini /* iia in CSR */ 869c2151214SStefano Zampini for (i = 0; i < n; i++) iia[i + 1] += iia[i]; 870c2151214SStefano Zampini 871c2151214SStefano Zampini /* jja in CSR */ 8729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(iia[n], &jja)); 873c2151214SStefano Zampini for (i = 0; i < n; i++) 874c2151214SStefano Zampini if (!PetscBTLookup(btf, i)) 8759371c9d4SSatish Balay for (j = 0; j < iiu[i + 1] - iiu[i]; j++) jja[iia[i] + j] = jju[iiu[i] + j]; 876c2151214SStefano Zampini 877c2151214SStefano Zampini /* map edge dofs connectivity */ 8781e0482f5SStefano Zampini if (jj) { 8799566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(fl2g, ii[ne], jj, (PetscInt *)jj)); 880c2151214SStefano Zampini for (i = 0; i < ne; i++) { 881c2151214SStefano Zampini PetscInt e = idxs[i]; 882c2151214SStefano Zampini for (j = 0; j < ii[i + 1] - ii[i]; j++) jja[iia[e] + j] = jj[ii[i] + j]; 883c2151214SStefano Zampini } 8841e0482f5SStefano Zampini } 8859566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(nedfieldlocal, &idxs)); 8869566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLocalAdjacencyGraph(pc, n, iia, jja, PETSC_OWN_POINTER)); 88748a46eb9SPierre Jolivet if (rest) PetscCall(MatRestoreRowIJ(matis->A, 0, PETSC_TRUE, PETSC_FALSE, &i, (const PetscInt **)&iiu, (const PetscInt **)&jju, &done)); 8881baa6e33SBarry Smith if (free) PetscCall(PetscFree2(iiu, jju)); 8899566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btf)); 890c2151214SStefano Zampini } else { 8919566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLocalAdjacencyGraph(pc, n, ii, jj, PETSC_USE_POINTER)); 892c2151214SStefano Zampini } 893c2151214SStefano Zampini 894a13144ffSStefano Zampini /* Analyze interface for edge dofs */ 8959566063dSJacob Faibussowitsch PetscCall(PCBDDCAnalyzeInterface(pc)); 896213b8bfaSStefano Zampini pcbddc->mat_graph->twodim = PETSC_FALSE; 897a13144ffSStefano Zampini 898a13144ffSStefano Zampini /* Get coarse edges in the edge space */ 8999566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, NULL, NULL, &nee, &alleedges, &allprimals)); 9009566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 901a13144ffSStefano Zampini 902c2151214SStefano Zampini if (fl2g) { 9039566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(fl2g, IS_GTOLM_DROP, allprimals, &primals)); 9049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nee, &eedges)); 90548a46eb9SPierre Jolivet for (i = 0; i < nee; i++) PetscCall(ISGlobalToLocalMappingApplyIS(fl2g, IS_GTOLM_DROP, alleedges[i], &eedges[i])); 906c2151214SStefano Zampini } else { 907c2151214SStefano Zampini eedges = alleedges; 908c2151214SStefano Zampini primals = allprimals; 909c2151214SStefano Zampini } 910c2151214SStefano Zampini 911a13144ffSStefano Zampini /* Mark fine edge dofs with their coarse edge id */ 9129566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(marks, ne)); 9139566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(primals, &cum)); 9149566063dSJacob Faibussowitsch PetscCall(ISGetIndices(primals, &idxs)); 915c2151214SStefano Zampini for (i = 0; i < cum; i++) marks[idxs[i]] = nee + 1; 9169566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(primals, &idxs)); 917c2151214SStefano Zampini if (print) { 9189566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)primals, "obtained_primal_dofs")); 9199566063dSJacob Faibussowitsch PetscCall(ISView(primals, NULL)); 920c2151214SStefano Zampini } 921c2151214SStefano Zampini 922c2151214SStefano Zampini maxsize = 0; 923a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 924a13144ffSStefano Zampini PetscInt size, mark = i + 1; 925a13144ffSStefano Zampini 9269566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 9279566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 928a13144ffSStefano Zampini for (j = 0; j < size; j++) marks[idxs[j]] = mark; 9299566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 930a13144ffSStefano Zampini maxsize = PetscMax(maxsize, size); 931a13144ffSStefano Zampini } 932a13144ffSStefano Zampini 933a13144ffSStefano Zampini /* Find coarse edge endpoints */ 9349566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lG, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 9359566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 936a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 937a13144ffSStefano Zampini PetscInt mark = i + 1, size; 938a13144ffSStefano Zampini 9399566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 9401e0482f5SStefano Zampini if (!size && nedfieldlocal) continue; 94163a3b9bcSJacob Faibussowitsch PetscCheck(size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected zero sized edge %" PetscInt_FMT, i); 9429566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 943a13144ffSStefano Zampini if (print) { 94463a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "ENDPOINTS ANALYSIS EDGE %" PetscInt_FMT "\n", i)); 9459566063dSJacob Faibussowitsch PetscCall(ISView(eedges[i], NULL)); 946a13144ffSStefano Zampini } 947a13144ffSStefano Zampini for (j = 0; j < size; j++) { 948a13144ffSStefano Zampini PetscInt k, ee = idxs[j]; 9493ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " idx %" PetscInt_FMT "\n", ee)); 950a13144ffSStefano Zampini for (k = ii[ee]; k < ii[ee + 1]; k++) { 9513ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " inspect %" PetscInt_FMT "\n", jj[k])); 952a13144ffSStefano Zampini if (PetscBTLookup(btv, jj[k])) { 9533ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " corner found (already set) %" PetscInt_FMT "\n", jj[k])); 954a13144ffSStefano Zampini } else if (PetscBTLookup(btvcand, jj[k])) { /* is it ok? */ 955a13144ffSStefano Zampini PetscInt k2; 956a13144ffSStefano Zampini PetscBool corner = PETSC_FALSE; 957a13144ffSStefano Zampini for (k2 = iit[jj[k]]; k2 < iit[jj[k] + 1]; k2++) { 9583ba16761SJacob 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]))); 959c2151214SStefano Zampini /* it's a corner if either is connected with an edge dof belonging to a different cc or 960c2151214SStefano Zampini if the edge dof lie on the natural part of the boundary */ 961c2151214SStefano Zampini if ((marks[jjt[k2]] && marks[jjt[k2]] != mark) || (!marks[jjt[k2]] && PetscBTLookup(btb, jjt[k2]))) { 962a13144ffSStefano Zampini corner = PETSC_TRUE; 963a13144ffSStefano Zampini break; 964a13144ffSStefano Zampini } 965a13144ffSStefano Zampini } 966a13144ffSStefano Zampini if (corner) { /* found the nodal dof corresponding to the endpoint of the edge */ 9673ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " corner found %" PetscInt_FMT "\n", jj[k])); 9689566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, jj[k])); 969a13144ffSStefano Zampini } else { 9703ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " no corners found\n")); 971a13144ffSStefano Zampini } 972a13144ffSStefano Zampini } 973a13144ffSStefano Zampini } 974a13144ffSStefano Zampini } 9759566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 976a13144ffSStefano Zampini } 9779566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 9789566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lG, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 9799566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btb)); 980a13144ffSStefano Zampini 981a13144ffSStefano Zampini /* Reset marked primal dofs */ 9829566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(primals, &cum)); 9839566063dSJacob Faibussowitsch PetscCall(ISGetIndices(primals, &idxs)); 984a13144ffSStefano Zampini for (i = 0; i < cum; i++) marks[idxs[i]] = 0; 9859566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(primals, &idxs)); 986a13144ffSStefano Zampini 9870569b399SStefano Zampini /* Now use the initial lG */ 9889566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lG)); 9899566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGt)); 9900569b399SStefano Zampini lG = lGinit; 9919566063dSJacob Faibussowitsch PetscCall(MatTranspose(lG, MAT_INITIAL_MATRIX, &lGt)); 9920569b399SStefano Zampini 993a13144ffSStefano Zampini /* Compute extended cols indices */ 9949566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(nv, &btvc)); 9959566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(nee, &bter)); 9969566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lG, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 9979566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetMaxRowNonzeros(lG, &i)); 998a13144ffSStefano Zampini i *= maxsize; 9999566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nee, &extcols)); 10009566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(i, &extrow, i, &gidxs)); 1001a13144ffSStefano Zampini eerr = PETSC_FALSE; 1002a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 1003b03ebc13SStefano Zampini PetscInt size, found = 0; 1004a13144ffSStefano Zampini 1005a13144ffSStefano Zampini cum = 0; 10069566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 10071e0482f5SStefano Zampini if (!size && nedfieldlocal) continue; 100863a3b9bcSJacob Faibussowitsch PetscCheck(size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected zero sized edge %" PetscInt_FMT, i); 10099566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 10109566063dSJacob Faibussowitsch PetscCall(PetscBTMemzero(nv, btvc)); 1011a13144ffSStefano Zampini for (j = 0; j < size; j++) { 1012a13144ffSStefano Zampini PetscInt k, ee = idxs[j]; 1013b03ebc13SStefano Zampini for (k = ii[ee]; k < ii[ee + 1]; k++) { 1014b03ebc13SStefano Zampini PetscInt vv = jj[k]; 1015b03ebc13SStefano Zampini if (!PetscBTLookup(btv, vv)) extrow[cum++] = vv; 1016b03ebc13SStefano Zampini else if (!PetscBTLookupSet(btvc, vv)) found++; 1017b03ebc13SStefano Zampini } 1018a13144ffSStefano Zampini } 10199566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 10209566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&cum, extrow)); 10219566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(vl2g, cum, extrow, gidxs)); 10229566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(cum, gidxs, extrow)); 10239566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cum, extrow, PETSC_COPY_VALUES, &extcols[i])); 1024a13144ffSStefano Zampini /* it may happen that endpoints are not defined at this point 1025a13144ffSStefano Zampini if it is the case, mark this edge for a second pass */ 1026b03ebc13SStefano Zampini if (cum != size - 1 || found != 2) { 10279566063dSJacob Faibussowitsch PetscCall(PetscBTSet(bter, i)); 1028a13144ffSStefano Zampini if (print) { 10299566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)eedges[i], "error_edge")); 10309566063dSJacob Faibussowitsch PetscCall(ISView(eedges[i], NULL)); 10319566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)extcols[i], "error_extcol")); 10329566063dSJacob Faibussowitsch PetscCall(ISView(extcols[i], NULL)); 1033a13144ffSStefano Zampini } 1034a13144ffSStefano Zampini eerr = PETSC_TRUE; 1035a13144ffSStefano Zampini } 1036a13144ffSStefano Zampini } 103728b400f6SJacob Faibussowitsch /* PetscCheck(!eerr,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL FIRST PASS"); */ 10381c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&eerr, &done, 1, MPIU_BOOL, MPI_LOR, comm)); 1039a13144ffSStefano Zampini if (done) { 1040a13144ffSStefano Zampini PetscInt *newprimals; 1041a13144ffSStefano Zampini 10429566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ne, &newprimals)); 10439566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(primals, &cum)); 10449566063dSJacob Faibussowitsch PetscCall(ISGetIndices(primals, &idxs)); 10459566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(newprimals, idxs, cum)); 10469566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(primals, &idxs)); 10479566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 10483ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, "DOING SECOND PASS (eerr %s)\n", PetscBools[eerr])); 1049a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 1050b03ebc13SStefano Zampini PetscBool has_candidates = PETSC_FALSE; 1051b03ebc13SStefano Zampini if (PetscBTLookup(bter, i)) { 1052a13144ffSStefano Zampini PetscInt size, mark = i + 1; 1053a13144ffSStefano Zampini 10549566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 10559566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 1056c2151214SStefano Zampini /* for (j=0;j<size;j++) newprimals[cum++] = idxs[j]; */ 1057a13144ffSStefano Zampini for (j = 0; j < size; j++) { 1058a13144ffSStefano Zampini PetscInt k, ee = idxs[j]; 10593ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, "Inspecting edge dof %" PetscInt_FMT " [%" PetscInt_FMT " %" PetscInt_FMT ")\n", ee, ii[ee], ii[ee + 1])); 1060a13144ffSStefano Zampini for (k = ii[ee]; k < ii[ee + 1]; k++) { 1061a13144ffSStefano Zampini /* set all candidates located on the edge as corners */ 1062a13144ffSStefano Zampini if (PetscBTLookup(btvcand, jj[k])) { 1063a13144ffSStefano Zampini PetscInt k2, vv = jj[k]; 1064b03ebc13SStefano Zampini has_candidates = PETSC_TRUE; 10653ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Candidate set to vertex %" PetscInt_FMT "\n", vv)); 10669566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, vv)); 1067a13144ffSStefano Zampini /* set all edge dofs connected to candidate as primals */ 1068a13144ffSStefano Zampini for (k2 = iit[vv]; k2 < iit[vv + 1]; k2++) { 1069a13144ffSStefano Zampini if (marks[jjt[k2]] == mark) { 1070a13144ffSStefano Zampini PetscInt k3, ee2 = jjt[k2]; 10713ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Connected edge dof set to primal %" PetscInt_FMT "\n", ee2)); 1072a13144ffSStefano Zampini newprimals[cum++] = ee2; 1073a13144ffSStefano Zampini /* finally set the new corners */ 1074a13144ffSStefano Zampini for (k3 = ii[ee2]; k3 < ii[ee2 + 1]; k3++) { 10753ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Connected nodal dof set to vertex %" PetscInt_FMT "\n", jj[k3])); 10769566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, jj[k3])); 1077a13144ffSStefano Zampini } 1078a13144ffSStefano Zampini } 1079a13144ffSStefano Zampini } 1080b03ebc13SStefano Zampini } else { 10813ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Not a candidate vertex %" PetscInt_FMT "\n", jj[k])); 1082a13144ffSStefano Zampini } 1083a13144ffSStefano Zampini } 1084a13144ffSStefano Zampini } 1085b03ebc13SStefano Zampini if (!has_candidates) { /* circular edge */ 1086b03ebc13SStefano Zampini PetscInt k, ee = idxs[0], *tmarks; 1087b03ebc13SStefano Zampini 10889566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(ne, &tmarks)); 10893ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Circular edge %" PetscInt_FMT "\n", i)); 1090b03ebc13SStefano Zampini for (k = ii[ee]; k < ii[ee + 1]; k++) { 1091b03ebc13SStefano Zampini PetscInt k2; 10923ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Set to corner %" PetscInt_FMT "\n", jj[k])); 10939566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, jj[k])); 1094b03ebc13SStefano Zampini for (k2 = iit[jj[k]]; k2 < iit[jj[k] + 1]; k2++) tmarks[jjt[k2]]++; 1095b03ebc13SStefano Zampini } 1096b03ebc13SStefano Zampini for (j = 0; j < size; j++) { 1097b03ebc13SStefano Zampini if (tmarks[idxs[j]] > 1) { 10983ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Edge dof set to primal %" PetscInt_FMT "\n", idxs[j])); 1099b03ebc13SStefano Zampini newprimals[cum++] = idxs[j]; 1100b03ebc13SStefano Zampini } 1101b03ebc13SStefano Zampini } 11029566063dSJacob Faibussowitsch PetscCall(PetscFree(tmarks)); 1103b03ebc13SStefano Zampini } 11049566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 1105a13144ffSStefano Zampini } 11069566063dSJacob Faibussowitsch PetscCall(ISDestroy(&extcols[i])); 1107a13144ffSStefano Zampini } 11089566063dSJacob Faibussowitsch PetscCall(PetscFree(extcols)); 11099566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 11109566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&cum, newprimals)); 1111c2151214SStefano Zampini if (fl2g) { 11129566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(fl2g, cum, newprimals, newprimals)); 11139566063dSJacob Faibussowitsch PetscCall(ISDestroy(&primals)); 111448a46eb9SPierre Jolivet for (i = 0; i < nee; i++) PetscCall(ISDestroy(&eedges[i])); 11159566063dSJacob Faibussowitsch PetscCall(PetscFree(eedges)); 1116c2151214SStefano Zampini } 11179566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, NULL, NULL, &nee, &alleedges, &allprimals)); 11189566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, cum, newprimals, PETSC_COPY_VALUES, &primals)); 11199566063dSJacob Faibussowitsch PetscCall(PetscFree(newprimals)); 11209566063dSJacob Faibussowitsch PetscCall(PCBDDCSetPrimalVerticesLocalIS(pc, primals)); 11219566063dSJacob Faibussowitsch PetscCall(ISDestroy(&primals)); 11229566063dSJacob Faibussowitsch PetscCall(PCBDDCAnalyzeInterface(pc)); 1123213b8bfaSStefano Zampini pcbddc->mat_graph->twodim = PETSC_FALSE; 11249566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, NULL, NULL, &nee, &alleedges, &allprimals)); 1125c2151214SStefano Zampini if (fl2g) { 11269566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(fl2g, IS_GTOLM_DROP, allprimals, &primals)); 11279566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nee, &eedges)); 112848a46eb9SPierre Jolivet for (i = 0; i < nee; i++) PetscCall(ISGlobalToLocalMappingApplyIS(fl2g, IS_GTOLM_DROP, alleedges[i], &eedges[i])); 1129c2151214SStefano Zampini } else { 1130c2151214SStefano Zampini eedges = alleedges; 1131c2151214SStefano Zampini primals = allprimals; 1132c2151214SStefano Zampini } 11339566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nee, &extcols)); 1134a13144ffSStefano Zampini 1135a13144ffSStefano Zampini /* Mark again */ 11369566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(marks, ne)); 1137a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 1138a13144ffSStefano Zampini PetscInt size, mark = i + 1; 1139a13144ffSStefano Zampini 11409566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 11419566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 1142a13144ffSStefano Zampini for (j = 0; j < size; j++) marks[idxs[j]] = mark; 11439566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 1144a13144ffSStefano Zampini } 1145a13144ffSStefano Zampini if (print) { 11469566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)primals, "obtained_primal_dofs_secondpass")); 11479566063dSJacob Faibussowitsch PetscCall(ISView(primals, NULL)); 1148a13144ffSStefano Zampini } 1149a13144ffSStefano Zampini 1150a13144ffSStefano Zampini /* Recompute extended cols */ 1151a13144ffSStefano Zampini eerr = PETSC_FALSE; 1152a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 1153a13144ffSStefano Zampini PetscInt size; 1154a13144ffSStefano Zampini 1155a13144ffSStefano Zampini cum = 0; 11569566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 11571e0482f5SStefano Zampini if (!size && nedfieldlocal) continue; 115863a3b9bcSJacob Faibussowitsch PetscCheck(size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected zero sized edge %" PetscInt_FMT, i); 11599566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 1160a13144ffSStefano Zampini for (j = 0; j < size; j++) { 1161a13144ffSStefano Zampini PetscInt k, ee = idxs[j]; 11629371c9d4SSatish Balay for (k = ii[ee]; k < ii[ee + 1]; k++) 11639371c9d4SSatish Balay if (!PetscBTLookup(btv, jj[k])) extrow[cum++] = jj[k]; 1164a13144ffSStefano Zampini } 11659566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 11669566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&cum, extrow)); 11679566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(vl2g, cum, extrow, gidxs)); 11689566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(cum, gidxs, extrow)); 11699566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cum, extrow, PETSC_COPY_VALUES, &extcols[i])); 1170a13144ffSStefano Zampini if (cum != size - 1) { 1171a13144ffSStefano Zampini if (print) { 11729566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)eedges[i], "error_edge_secondpass")); 11739566063dSJacob Faibussowitsch PetscCall(ISView(eedges[i], NULL)); 11749566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)extcols[i], "error_extcol_secondpass")); 11759566063dSJacob Faibussowitsch PetscCall(ISView(extcols[i], NULL)); 1176a13144ffSStefano Zampini } 1177a13144ffSStefano Zampini eerr = PETSC_TRUE; 1178a13144ffSStefano Zampini } 1179a13144ffSStefano Zampini } 1180a13144ffSStefano Zampini } 11819566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lG, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 11829566063dSJacob Faibussowitsch PetscCall(PetscFree2(extrow, gidxs)); 11839566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&bter)); 11849566063dSJacob Faibussowitsch if (print) PetscCall(PCBDDCGraphASCIIView(pcbddc->mat_graph, 5, PETSC_VIEWER_STDOUT_SELF)); 1185a13144ffSStefano Zampini /* an error should not occur at this point */ 118628b400f6SJacob Faibussowitsch PetscCheck(!eerr, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected SIZE OF EDGE > EXTCOL SECOND PASS"); 1187a13144ffSStefano Zampini 11884e64d54eSstefano_zampini /* Check the number of endpoints */ 11899566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lG, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 11909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2 * nee, &corners)); 11919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nee, &cedges)); 11924e64d54eSstefano_zampini for (i = 0; i < nee; i++) { 1193b03ebc13SStefano Zampini PetscInt size, found = 0, gc[2]; 11944e64d54eSstefano_zampini 1195b03ebc13SStefano Zampini /* init with defaults */ 1196b03ebc13SStefano Zampini cedges[i] = corners[i * 2] = corners[i * 2 + 1] = -1; 11979566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 11981e0482f5SStefano Zampini if (!size && nedfieldlocal) continue; 119963a3b9bcSJacob Faibussowitsch PetscCheck(size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected zero sized edge %" PetscInt_FMT, i); 12009566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 12019566063dSJacob Faibussowitsch PetscCall(PetscBTMemzero(nv, btvc)); 12024e64d54eSstefano_zampini for (j = 0; j < size; j++) { 12034e64d54eSstefano_zampini PetscInt k, ee = idxs[j]; 12044e64d54eSstefano_zampini for (k = ii[ee]; k < ii[ee + 1]; k++) { 12054e64d54eSstefano_zampini PetscInt vv = jj[k]; 12064e64d54eSstefano_zampini if (PetscBTLookup(btv, vv) && !PetscBTLookupSet(btvc, vv)) { 1207467446fbSPierre Jolivet PetscCheck(found != 2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Found more than two corners for edge %" PetscInt_FMT, i); 1208b03ebc13SStefano Zampini corners[i * 2 + found++] = vv; 12094e64d54eSstefano_zampini } 12104e64d54eSstefano_zampini } 12114e64d54eSstefano_zampini } 1212b03ebc13SStefano Zampini if (found != 2) { 1213b03ebc13SStefano Zampini PetscInt e; 1214b03ebc13SStefano Zampini if (fl2g) { 12159566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(fl2g, 1, idxs, &e)); 1216b03ebc13SStefano Zampini } else { 1217b03ebc13SStefano Zampini e = idxs[0]; 1218b03ebc13SStefano Zampini } 121963a3b9bcSJacob 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]); 1220b03ebc13SStefano Zampini } 1221eee23b56SStefano Zampini 1222eee23b56SStefano Zampini /* get primal dof index on this coarse edge */ 12239566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(vl2g, 2, corners + 2 * i, gc)); 1224b03ebc13SStefano Zampini if (gc[0] > gc[1]) { 1225b03ebc13SStefano Zampini PetscInt swap = corners[2 * i]; 1226b03ebc13SStefano Zampini corners[2 * i] = corners[2 * i + 1]; 1227b03ebc13SStefano Zampini corners[2 * i + 1] = swap; 1228b03ebc13SStefano Zampini } 1229eee23b56SStefano Zampini cedges[i] = idxs[size - 1]; 12309566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 12313ba16761SJacob 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])); 12324e64d54eSstefano_zampini } 12339566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lG, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 12349566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btvc)); 12354e64d54eSstefano_zampini 123676bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 1237a13144ffSStefano Zampini /* Inspects columns of lG (rows of lGt) and make sure the change of basis will 1238a13144ffSStefano Zampini not interfere with neighbouring coarse edges */ 12399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nee + 1, &emarks)); 12409566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 1241a13144ffSStefano Zampini for (i = 0; i < nv; i++) { 1242a13144ffSStefano Zampini PetscInt emax = 0, eemax = 0; 1243a13144ffSStefano Zampini 1244a13144ffSStefano Zampini if (ii[i + 1] == ii[i] || PetscBTLookup(btv, i)) continue; 12459566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(emarks, nee + 1)); 1246a13144ffSStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) emarks[marks[jj[j]]]++; 1247a13144ffSStefano Zampini for (j = 1; j < nee + 1; j++) { 1248a13144ffSStefano Zampini if (emax < emarks[j]) { 1249a13144ffSStefano Zampini emax = emarks[j]; 1250a13144ffSStefano Zampini eemax = j; 1251a13144ffSStefano Zampini } 1252a13144ffSStefano Zampini } 1253a13144ffSStefano Zampini /* not relevant for edges */ 1254a13144ffSStefano Zampini if (!eemax) continue; 1255a13144ffSStefano Zampini 1256a13144ffSStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 12577a46b595SBarry 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]); 1258a13144ffSStefano Zampini } 1259a13144ffSStefano Zampini } 12609566063dSJacob Faibussowitsch PetscCall(PetscFree(emarks)); 12619566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 126276bd3646SJed Brown } 1263a13144ffSStefano Zampini 1264a13144ffSStefano Zampini /* Compute extended rows indices for edge blocks of the change of basis */ 12659566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 12669566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetMaxRowNonzeros(lGt, &extmem)); 1267a13144ffSStefano Zampini extmem *= maxsize; 12689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(extmem * nee, &extrow)); 12699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nee, &extrows)); 12709566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nee, &extrowcum)); 1271a13144ffSStefano Zampini for (i = 0; i < nv; i++) { 1272a13144ffSStefano Zampini PetscInt mark = 0, size, start; 1273213b8bfaSStefano Zampini 1274a13144ffSStefano Zampini if (ii[i + 1] == ii[i] || PetscBTLookup(btv, i)) continue; 1275a13144ffSStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) 12769371c9d4SSatish Balay if (marks[jj[j]] && !mark) mark = marks[jj[j]]; 1277a13144ffSStefano Zampini 1278a13144ffSStefano Zampini /* not relevant */ 1279a13144ffSStefano Zampini if (!mark) continue; 1280a13144ffSStefano Zampini 1281a13144ffSStefano Zampini /* import extended row */ 1282a13144ffSStefano Zampini mark--; 1283a13144ffSStefano Zampini start = mark * extmem + extrowcum[mark]; 1284a13144ffSStefano Zampini size = ii[i + 1] - ii[i]; 128563a3b9bcSJacob Faibussowitsch PetscCheck(extrowcum[mark] + size <= extmem, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Not enough memory allocated %" PetscInt_FMT " > %" PetscInt_FMT, extrowcum[mark] + size, extmem); 12869566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(extrow + start, jj + ii[i], size)); 1287a13144ffSStefano Zampini extrowcum[mark] += size; 1288a13144ffSStefano Zampini } 12899566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 12909566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGt)); 12919566063dSJacob Faibussowitsch PetscCall(PetscFree(marks)); 1292213b8bfaSStefano Zampini 1293213b8bfaSStefano Zampini /* Compress extrows */ 1294a13144ffSStefano Zampini cum = 0; 1295a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 1296a13144ffSStefano Zampini PetscInt size = extrowcum[i], *start = extrow + i * extmem; 12979566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&size, start)); 12989566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, size, start, PETSC_USE_POINTER, &extrows[i])); 1299a13144ffSStefano Zampini cum = PetscMax(cum, size); 1300a13144ffSStefano Zampini } 13019566063dSJacob Faibussowitsch PetscCall(PetscFree(extrowcum)); 13029566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btv)); 13039566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btvcand)); 1304a13144ffSStefano Zampini 1305a13144ffSStefano Zampini /* Workspace for lapack inner calls and VecSetValues */ 13069566063dSJacob Faibussowitsch PetscCall(PetscMalloc2((5 + cum + maxsize) * maxsize, &work, maxsize, &rwork)); 1307a13144ffSStefano Zampini 1308a13144ffSStefano Zampini /* Create change of basis matrix (preallocation can be improved) */ 13099566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &T)); 13109de2952eSStefano Zampini PetscCall(MatSetLayouts(T, pc->mat->rmap, pc->mat->cmap)); 13119566063dSJacob Faibussowitsch PetscCall(MatSetType(T, MATAIJ)); 13129de2952eSStefano Zampini PetscCall(MatSeqAIJSetPreallocation(T, maxsize, NULL)); 13139de2952eSStefano Zampini PetscCall(MatMPIAIJSetPreallocation(T, maxsize, NULL, maxsize, NULL)); 13149566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(T, al2g, al2g)); 13159566063dSJacob Faibussowitsch PetscCall(MatSetOption(T, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 13169566063dSJacob Faibussowitsch PetscCall(MatSetOption(T, MAT_ROW_ORIENTED, PETSC_FALSE)); 13179566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&al2g)); 1318a13144ffSStefano Zampini 1319a13144ffSStefano Zampini /* Defaults to identity */ 13209de2952eSStefano Zampini for (i = pc->mat->rmap->rstart; i < pc->mat->rmap->rend; i++) PetscCall(MatSetValue(T, i, i, 1.0, INSERT_VALUES)); 1321a13144ffSStefano Zampini 13221e0482f5SStefano Zampini /* Create discrete gradient for the coarser level if needed */ 13239566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->nedcG)); 13249566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->nedclocal)); 13251e0482f5SStefano Zampini if (pcbddc->current_level < pcbddc->max_levels) { 13261e0482f5SStefano Zampini ISLocalToGlobalMapping cel2g, cvl2g; 13271e0482f5SStefano Zampini IS wis, gwis; 13281e0482f5SStefano Zampini PetscInt cnv, cne; 13291e0482f5SStefano Zampini 13309566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, nee, cedges, PETSC_COPY_VALUES, &wis)); 13311e0482f5SStefano Zampini if (fl2g) { 13329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(fl2g, wis, &pcbddc->nedclocal)); 13331e0482f5SStefano Zampini } else { 13349566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)wis)); 13351e0482f5SStefano Zampini pcbddc->nedclocal = wis; 13361e0482f5SStefano Zampini } 13379566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(el2g, wis, &gwis)); 13389566063dSJacob Faibussowitsch PetscCall(ISDestroy(&wis)); 13399566063dSJacob Faibussowitsch PetscCall(ISRenumber(gwis, NULL, &cne, &wis)); 13409566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(wis, &cel2g)); 13419566063dSJacob Faibussowitsch PetscCall(ISDestroy(&wis)); 13429566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gwis)); 13431e0482f5SStefano Zampini 13449566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, 2 * nee, corners, PETSC_USE_POINTER, &wis)); 13459566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(vl2g, wis, &gwis)); 13469566063dSJacob Faibussowitsch PetscCall(ISDestroy(&wis)); 13479566063dSJacob Faibussowitsch PetscCall(ISRenumber(gwis, NULL, &cnv, &wis)); 13489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(wis, &cvl2g)); 13499566063dSJacob Faibussowitsch PetscCall(ISDestroy(&wis)); 13509566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gwis)); 13511e0482f5SStefano Zampini 13529566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &pcbddc->nedcG)); 13539566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->nedcG, PETSC_DECIDE, PETSC_DECIDE, cne, cnv)); 13549566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->nedcG, MATAIJ)); 13559566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(pcbddc->nedcG, 2, NULL)); 13569566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(pcbddc->nedcG, 2, NULL, 2, NULL)); 13579566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(pcbddc->nedcG, cel2g, cvl2g)); 13589566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cel2g)); 13599566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cvl2g)); 13601e0482f5SStefano Zampini } 13619566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&vl2g)); 13621e0482f5SStefano Zampini 13631e0482f5SStefano Zampini #if defined(PRINT_GDET) 13641e0482f5SStefano Zampini inc = 0; 13651e0482f5SStefano Zampini lev = pcbddc->current_level; 13661e0482f5SStefano Zampini #endif 1367213b8bfaSStefano Zampini 1368213b8bfaSStefano Zampini /* Insert values in the change of basis matrix */ 1369a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 1370a13144ffSStefano Zampini Mat Gins = NULL, GKins = NULL; 13711e0482f5SStefano Zampini IS cornersis = NULL; 13721e0482f5SStefano Zampini PetscScalar cvals[2]; 1373a13144ffSStefano Zampini 137448a46eb9SPierre Jolivet if (pcbddc->nedcG) PetscCall(ISCreateGeneral(PETSC_COMM_SELF, 2, corners + 2 * i, PETSC_USE_POINTER, &cornersis)); 13759566063dSJacob Faibussowitsch PetscCall(PCBDDCComputeNedelecChangeEdge(lG, eedges[i], extrows[i], extcols[i], cornersis, &Gins, &GKins, cvals, work, rwork)); 1376a13144ffSStefano Zampini if (Gins && GKins) { 13771683a169SBarry Smith const PetscScalar *data; 1378a13144ffSStefano Zampini const PetscInt *rows, *cols; 1379a13144ffSStefano Zampini PetscInt nrh, nch, nrc, ncc; 1380a13144ffSStefano Zampini 13819566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &cols)); 1382a13144ffSStefano Zampini /* H1 */ 13839566063dSJacob Faibussowitsch PetscCall(ISGetIndices(extrows[i], &rows)); 13849566063dSJacob Faibussowitsch PetscCall(MatGetSize(Gins, &nrh, &nch)); 13859566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(Gins, &data)); 13869566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(T, nrh, rows, nch, cols, data, INSERT_VALUES)); 13879566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(Gins, &data)); 13889566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(extrows[i], &rows)); 1389a13144ffSStefano Zampini /* complement */ 13909566063dSJacob Faibussowitsch PetscCall(MatGetSize(GKins, &nrc, &ncc)); 139163a3b9bcSJacob Faibussowitsch PetscCheck(ncc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Constant function has not been generated for coarse edge %" PetscInt_FMT, i); 139263a3b9bcSJacob 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); 139363a3b9bcSJacob 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); 13949566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(GKins, &data)); 13959566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(T, nrc, cols, ncc, cols + nch, data, INSERT_VALUES)); 13969566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(GKins, &data)); 13971e0482f5SStefano Zampini 13981e0482f5SStefano Zampini /* coarse discrete gradient */ 13991e0482f5SStefano Zampini if (pcbddc->nedcG) { 14001e0482f5SStefano Zampini PetscInt cols[2]; 14011e0482f5SStefano Zampini 14021e0482f5SStefano Zampini cols[0] = 2 * i; 14031e0482f5SStefano Zampini cols[1] = 2 * i + 1; 14049566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(pcbddc->nedcG, 1, &i, 2, cols, cvals, INSERT_VALUES)); 14051e0482f5SStefano Zampini } 14069566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &cols)); 1407a13144ffSStefano Zampini } 14089566063dSJacob Faibussowitsch PetscCall(ISDestroy(&extrows[i])); 14099566063dSJacob Faibussowitsch PetscCall(ISDestroy(&extcols[i])); 14109566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cornersis)); 14119566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Gins)); 14129566063dSJacob Faibussowitsch PetscCall(MatDestroy(&GKins)); 1413a13144ffSStefano Zampini } 14149566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&el2g)); 1415a13144ffSStefano Zampini 1416a13144ffSStefano Zampini /* Start assembling */ 14179566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(T, MAT_FINAL_ASSEMBLY)); 14181baa6e33SBarry Smith if (pcbddc->nedcG) PetscCall(MatAssemblyBegin(pcbddc->nedcG, MAT_FINAL_ASSEMBLY)); 1419a13144ffSStefano Zampini 1420a13144ffSStefano Zampini /* Free */ 1421c2151214SStefano Zampini if (fl2g) { 14229566063dSJacob Faibussowitsch PetscCall(ISDestroy(&primals)); 142348a46eb9SPierre Jolivet for (i = 0; i < nee; i++) PetscCall(ISDestroy(&eedges[i])); 14249566063dSJacob Faibussowitsch PetscCall(PetscFree(eedges)); 1425c2151214SStefano Zampini } 1426eee23b56SStefano Zampini 1427eee23b56SStefano Zampini /* hack mat_graph with primal dofs on the coarse edges */ 1428eee23b56SStefano Zampini { 1429eee23b56SStefano Zampini PCBDDCGraph graph = pcbddc->mat_graph; 1430eee23b56SStefano Zampini PetscInt *oqueue = graph->queue; 1431eee23b56SStefano Zampini PetscInt *ocptr = graph->cptr; 1432eee23b56SStefano Zampini PetscInt ncc, *idxs; 1433eee23b56SStefano Zampini 1434eee23b56SStefano Zampini /* find first primal edge */ 1435eee23b56SStefano Zampini if (pcbddc->nedclocal) { 14369566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->nedclocal, (const PetscInt **)&idxs)); 1437eee23b56SStefano Zampini } else { 14381baa6e33SBarry Smith if (fl2g) PetscCall(ISLocalToGlobalMappingApply(fl2g, nee, cedges, cedges)); 1439eee23b56SStefano Zampini idxs = cedges; 1440eee23b56SStefano Zampini } 1441eee23b56SStefano Zampini cum = 0; 1442eee23b56SStefano Zampini while (cum < nee && cedges[cum] < 0) cum++; 1443eee23b56SStefano Zampini 1444eee23b56SStefano Zampini /* adapt connected components */ 14459566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(graph->nvtxs + 1, &graph->cptr, ocptr[graph->ncc], &graph->queue)); 1446eee23b56SStefano Zampini graph->cptr[0] = 0; 1447eee23b56SStefano Zampini for (i = 0, ncc = 0; i < graph->ncc; i++) { 1448eee23b56SStefano Zampini PetscInt lc = ocptr[i + 1] - ocptr[i]; 1449eee23b56SStefano Zampini if (cum != nee && oqueue[ocptr[i + 1] - 1] == cedges[cum]) { /* this cc has a primal dof */ 1450eee23b56SStefano Zampini graph->cptr[ncc + 1] = graph->cptr[ncc] + 1; 1451eee23b56SStefano Zampini graph->queue[graph->cptr[ncc]] = cedges[cum]; 1452eee23b56SStefano Zampini ncc++; 1453eee23b56SStefano Zampini lc--; 1454eee23b56SStefano Zampini cum++; 1455eee23b56SStefano Zampini while (cum < nee && cedges[cum] < 0) cum++; 1456eee23b56SStefano Zampini } 1457eee23b56SStefano Zampini graph->cptr[ncc + 1] = graph->cptr[ncc] + lc; 1458eee23b56SStefano Zampini for (j = 0; j < lc; j++) graph->queue[graph->cptr[ncc] + j] = oqueue[ocptr[i] + j]; 1459eee23b56SStefano Zampini ncc++; 1460eee23b56SStefano Zampini } 1461eee23b56SStefano Zampini graph->ncc = ncc; 146248a46eb9SPierre Jolivet if (pcbddc->nedclocal) PetscCall(ISRestoreIndices(pcbddc->nedclocal, (const PetscInt **)&idxs)); 14639566063dSJacob Faibussowitsch PetscCall(PetscFree2(ocptr, oqueue)); 1464eee23b56SStefano Zampini } 14659566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&fl2g)); 14669566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, NULL, NULL, &nee, &alleedges, &allprimals)); 14679566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphResetCSR(pcbddc->mat_graph)); 14689566063dSJacob Faibussowitsch PetscCall(MatDestroy(&conn)); 1469eee23b56SStefano Zampini 14709566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nedfieldlocal)); 14719566063dSJacob Faibussowitsch PetscCall(PetscFree(extrow)); 14729566063dSJacob Faibussowitsch PetscCall(PetscFree2(work, rwork)); 14739566063dSJacob Faibussowitsch PetscCall(PetscFree(corners)); 14749566063dSJacob Faibussowitsch PetscCall(PetscFree(cedges)); 14759566063dSJacob Faibussowitsch PetscCall(PetscFree(extrows)); 14769566063dSJacob Faibussowitsch PetscCall(PetscFree(extcols)); 14779566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lG)); 1478a13144ffSStefano Zampini 1479a13144ffSStefano Zampini /* Complete assembling */ 14809566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(T, MAT_FINAL_ASSEMBLY)); 14819de2952eSStefano Zampini PetscCall(MatViewFromOptions(T, (PetscObject)pc, "-pc_bddc_nedelec_change_view")); 14821e0482f5SStefano Zampini if (pcbddc->nedcG) { 14839566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->nedcG, MAT_FINAL_ASSEMBLY)); 1484*a4cdd7efSStefano Zampini PetscCall(MatViewFromOptions(pcbddc->nedcG, (PetscObject)pc, "-pc_bddc_nedelec_coarse_change_view")); 14851e0482f5SStefano Zampini } 1486a13144ffSStefano Zampini 1487a13144ffSStefano Zampini /* set change of basis */ 14889566063dSJacob Faibussowitsch PetscCall(PCBDDCSetChangeOfBasisMat(pc, T, singular)); 14899566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 14903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1491a13144ffSStefano Zampini } 1492a13144ffSStefano Zampini 1493d8203eabSStefano Zampini /* the near-null space of BDDC carries information on quadrature weights, 1494d8203eabSStefano Zampini and these can be collinear -> so cheat with MatNullSpaceCreate 1495d8203eabSStefano Zampini and create a suitable set of basis vectors first */ 1496d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCNullSpaceCreate(MPI_Comm comm, PetscBool has_const, PetscInt nvecs, Vec quad_vecs[], MatNullSpace *nnsp) 1497d71ae5a4SJacob Faibussowitsch { 1498d8203eabSStefano Zampini PetscInt i; 1499d8203eabSStefano Zampini 1500d8203eabSStefano Zampini PetscFunctionBegin; 1501d8203eabSStefano Zampini for (i = 0; i < nvecs; i++) { 1502d8203eabSStefano Zampini PetscInt first, last; 1503d8203eabSStefano Zampini 15049566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(quad_vecs[i], &first, &last)); 15057827d75bSBarry Smith PetscCheck(last - first >= 2 * nvecs || !has_const, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented"); 1506d8203eabSStefano Zampini if (i >= first && i < last) { 1507d8203eabSStefano Zampini PetscScalar *data; 15089566063dSJacob Faibussowitsch PetscCall(VecGetArray(quad_vecs[i], &data)); 1509d8203eabSStefano Zampini if (!has_const) { 1510d8203eabSStefano Zampini data[i - first] = 1.; 1511d8203eabSStefano Zampini } else { 151286fa73c5SStefano Zampini data[2 * i - first] = 1. / PetscSqrtReal(2.); 151386fa73c5SStefano Zampini data[2 * i - first + 1] = -1. / PetscSqrtReal(2.); 1514d8203eabSStefano Zampini } 15159566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(quad_vecs[i], &data)); 1516d8203eabSStefano Zampini } 15179566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)quad_vecs[i])); 1518d8203eabSStefano Zampini } 15199566063dSJacob Faibussowitsch PetscCall(MatNullSpaceCreate(comm, has_const, nvecs, quad_vecs, nnsp)); 1520d8203eabSStefano Zampini for (i = 0; i < nvecs; i++) { /* reset vectors */ 1521d8203eabSStefano Zampini PetscInt first, last; 15229566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(quad_vecs[i])); 15239566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(quad_vecs[i], &first, &last)); 1524d8203eabSStefano Zampini if (i >= first && i < last) { 1525d8203eabSStefano Zampini PetscScalar *data; 15269566063dSJacob Faibussowitsch PetscCall(VecGetArray(quad_vecs[i], &data)); 1527d8203eabSStefano Zampini if (!has_const) { 1528d8203eabSStefano Zampini data[i - first] = 0.; 1529d8203eabSStefano Zampini } else { 153086fa73c5SStefano Zampini data[2 * i - first] = 0.; 153186fa73c5SStefano Zampini data[2 * i - first + 1] = 0.; 1532d8203eabSStefano Zampini } 15339566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(quad_vecs[i], &data)); 1534d8203eabSStefano Zampini } 15359566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)quad_vecs[i])); 15369566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(quad_vecs[i])); 1537d8203eabSStefano Zampini } 15383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1539d8203eabSStefano Zampini } 1540d8203eabSStefano Zampini 1541d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, PetscBool transpose, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp) 1542d71ae5a4SJacob Faibussowitsch { 1543a198735bSStefano Zampini Mat loc_divudotp; 15449de2952eSStefano Zampini Vec p, v, quad_vec; 15458ae0ca82SStefano Zampini ISLocalToGlobalMapping map; 15469de2952eSStefano Zampini PetscScalar *array; 1547669cc0f4SStefano Zampini 1548669cc0f4SStefano Zampini PetscFunctionBegin; 15499566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, &quad_vec, NULL)); 15508ae0ca82SStefano Zampini if (!transpose) { 15519566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(A, &map, NULL)); 15528ae0ca82SStefano Zampini } else { 15539566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(A, NULL, &map)); 15548ae0ca82SStefano Zampini } 15559de2952eSStefano Zampini PetscCall(PCBDDCNullSpaceCreate(PetscObjectComm((PetscObject)A), PETSC_FALSE, 1, &quad_vec, nnsp)); 15569de2952eSStefano Zampini PetscCall(VecLockReadPop(quad_vec)); 15579de2952eSStefano Zampini PetscCall(VecSetLocalToGlobalMapping(quad_vec, map)); 1558d8203eabSStefano Zampini 1559669cc0f4SStefano Zampini /* compute local quad vec */ 15609566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(divudotp, &loc_divudotp)); 15618ae0ca82SStefano Zampini if (!transpose) { 15629566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(loc_divudotp, &v, &p)); 15638ae0ca82SStefano Zampini } else { 15649566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(loc_divudotp, &p, &v)); 15658ae0ca82SStefano Zampini } 15669de2952eSStefano Zampini /* the assumption here is that the constant vector interpolates the constant on the L2 conforming space */ 15679566063dSJacob Faibussowitsch PetscCall(VecSet(p, 1.)); 15688ae0ca82SStefano Zampini if (!transpose) { 15699566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(loc_divudotp, p, v)); 15708ae0ca82SStefano Zampini } else { 15719566063dSJacob Faibussowitsch PetscCall(MatMult(loc_divudotp, p, v)); 15728ae0ca82SStefano Zampini } 15739de2952eSStefano Zampini PetscCall(VecDestroy(&p)); 1574fa23a32eSStefano Zampini if (vl2l) { 1575187c917aSStefano Zampini Mat lA; 1576187c917aSStefano Zampini VecScatter sc; 15779de2952eSStefano Zampini Vec vins; 1578187c917aSStefano Zampini 15799566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A, &lA)); 15809566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(lA, &vins, NULL)); 15819566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(v, NULL, vins, vl2l, &sc)); 15829566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sc, v, vins, INSERT_VALUES, SCATTER_FORWARD)); 15839566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sc, v, vins, INSERT_VALUES, SCATTER_FORWARD)); 15849566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sc)); 15859566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 15869de2952eSStefano Zampini v = vins; 1587669cc0f4SStefano Zampini } 15889de2952eSStefano Zampini 15899de2952eSStefano Zampini /* mask summation of interface values */ 15909de2952eSStefano Zampini PetscInt n, *mmask, *mask, *idxs, nmr, nr; 15919de2952eSStefano Zampini const PetscInt *degree; 15929de2952eSStefano Zampini PetscSF msf; 15939de2952eSStefano Zampini 15949de2952eSStefano Zampini PetscCall(VecGetLocalSize(v, &n)); 15959de2952eSStefano Zampini PetscCall(PetscSFGetGraph(graph->interface_subset_sf, &nr, NULL, NULL, NULL)); 15969de2952eSStefano Zampini PetscCall(PetscSFGetMultiSF(graph->interface_subset_sf, &msf)); 15979de2952eSStefano Zampini PetscCall(PetscSFGetGraph(msf, &nmr, NULL, NULL, NULL)); 15989de2952eSStefano Zampini PetscCall(PetscCalloc3(nmr, &mmask, n, &mask, n, &idxs)); 15999de2952eSStefano Zampini PetscCall(PetscSFComputeDegreeBegin(graph->interface_subset_sf, °ree)); 16009de2952eSStefano Zampini PetscCall(PetscSFComputeDegreeEnd(graph->interface_subset_sf, °ree)); 16019de2952eSStefano Zampini for (PetscInt i = 0, c = 0; i < nr; i++) { 16029de2952eSStefano Zampini mmask[c] = 1; 16039de2952eSStefano Zampini c += degree[i]; 16049de2952eSStefano Zampini } 16059de2952eSStefano Zampini PetscCall(PetscSFScatterBegin(graph->interface_subset_sf, MPIU_INT, mmask, mask)); 16069de2952eSStefano Zampini PetscCall(PetscSFScatterEnd(graph->interface_subset_sf, MPIU_INT, mmask, mask)); 16079de2952eSStefano Zampini PetscCall(VecGetArray(v, &array)); 16089de2952eSStefano Zampini for (PetscInt i = 0; i < n; i++) { 16099de2952eSStefano Zampini array[i] *= mask[i]; 16109de2952eSStefano Zampini idxs[i] = i; 16119de2952eSStefano Zampini } 16129de2952eSStefano Zampini PetscCall(VecSetValuesLocal(quad_vec, n, idxs, array, ADD_VALUES)); 16139de2952eSStefano Zampini PetscCall(VecRestoreArray(v, &array)); 16149de2952eSStefano Zampini PetscCall(PetscFree3(mmask, mask, idxs)); 16159de2952eSStefano Zampini PetscCall(VecDestroy(&v)); 16169de2952eSStefano Zampini PetscCall(VecAssemblyBegin(quad_vec)); 16179de2952eSStefano Zampini PetscCall(VecAssemblyEnd(quad_vec)); 16189de2952eSStefano Zampini PetscCall(VecViewFromOptions(quad_vec, NULL, "-pc_bddc_quad_vec_view")); 16199de2952eSStefano Zampini PetscCall(VecLockReadPush(quad_vec)); 16209de2952eSStefano Zampini PetscCall(VecDestroy(&quad_vec)); 16213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1622669cc0f4SStefano Zampini } 1623669cc0f4SStefano Zampini 1624d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCAddPrimalVerticesLocalIS(PC pc, IS primalv) 1625d71ae5a4SJacob Faibussowitsch { 16267620a527SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 16277620a527SStefano Zampini 16287620a527SStefano Zampini PetscFunctionBegin; 16297620a527SStefano Zampini if (primalv) { 16307620a527SStefano Zampini if (pcbddc->user_primal_vertices_local) { 16317620a527SStefano Zampini IS list[2], newp; 16327620a527SStefano Zampini 16337620a527SStefano Zampini list[0] = primalv; 16347620a527SStefano Zampini list[1] = pcbddc->user_primal_vertices_local; 16359566063dSJacob Faibussowitsch PetscCall(ISConcatenate(PetscObjectComm((PetscObject)pc), 2, list, &newp)); 16369566063dSJacob Faibussowitsch PetscCall(ISSortRemoveDups(newp)); 16379566063dSJacob Faibussowitsch PetscCall(ISDestroy(&list[1])); 16387620a527SStefano Zampini pcbddc->user_primal_vertices_local = newp; 16397620a527SStefano Zampini } else { 16409566063dSJacob Faibussowitsch PetscCall(PCBDDCSetPrimalVerticesLocalIS(pc, primalv)); 16417620a527SStefano Zampini } 16427620a527SStefano Zampini } 16433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16447620a527SStefano Zampini } 1645669cc0f4SStefano Zampini 1646d71ae5a4SJacob Faibussowitsch static PetscErrorCode func_coords_private(PetscInt dim, PetscReal t, const PetscReal X[], PetscInt Nf, PetscScalar *out, void *ctx) 1647d71ae5a4SJacob Faibussowitsch { 16481c7a958bSStefano Zampini PetscInt f, *comp = (PetscInt *)ctx; 16491c7a958bSStefano Zampini 16501c7a958bSStefano Zampini PetscFunctionBegin; 16511c7a958bSStefano Zampini for (f = 0; f < Nf; f++) out[f] = X[*comp]; 16523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16531c7a958bSStefano Zampini } 1654674ae819SStefano Zampini 1655d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc) 1656d71ae5a4SJacob Faibussowitsch { 16571f4df5f7SStefano Zampini Vec local, global; 16581f4df5f7SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 16591f4df5f7SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 16605c5e10d6SStefano Zampini PetscBool monolithic = PETSC_FALSE; 16611f4df5f7SStefano Zampini 16621f4df5f7SStefano Zampini PetscFunctionBegin; 1663d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)pc), ((PetscObject)pc)->prefix, "BDDC topology options", "PC"); 16649566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_monolithic", "Discard any information on dofs splitting", NULL, monolithic, &monolithic, NULL)); 1665d0609cedSBarry Smith PetscOptionsEnd(); 16661f4df5f7SStefano Zampini /* need to convert from global to local topology information and remove references to information in global ordering */ 16679566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(pc->pmat, &global, NULL)); 16689566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(matis->A, &local, NULL)); 16699566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(global, PETSC_TRUE)); 16709566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(local, PETSC_TRUE)); 16716a8fc67bSStefano Zampini if (monolithic) { /* just get block size to properly compute vertices */ 167248a46eb9SPierre Jolivet if (pcbddc->vertex_size == 1) PetscCall(MatGetBlockSize(pc->pmat, &pcbddc->vertex_size)); 16736a8fc67bSStefano Zampini goto boundary; 16746a8fc67bSStefano Zampini } 16755c5e10d6SStefano Zampini 16761f4df5f7SStefano Zampini if (pcbddc->user_provided_isfordofs) { 16771f4df5f7SStefano Zampini if (pcbddc->n_ISForDofs) { 16781f4df5f7SStefano Zampini PetscInt i; 16790c85b387SStefano Zampini 16809566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->n_ISForDofs, &pcbddc->ISForDofsLocal)); 16811f4df5f7SStefano Zampini for (i = 0; i < pcbddc->n_ISForDofs; i++) { 16820c85b387SStefano Zampini PetscInt bs; 16830c85b387SStefano Zampini 16849566063dSJacob Faibussowitsch PetscCall(PCBDDCGlobalToLocal(matis->rctx, global, local, pcbddc->ISForDofs[i], &pcbddc->ISForDofsLocal[i])); 16859566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(pcbddc->ISForDofs[i], &bs)); 16869566063dSJacob Faibussowitsch PetscCall(ISSetBlockSize(pcbddc->ISForDofsLocal[i], bs)); 16879566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->ISForDofs[i])); 16881f4df5f7SStefano Zampini } 16891f4df5f7SStefano Zampini pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs; 16901f4df5f7SStefano Zampini pcbddc->n_ISForDofs = 0; 16919566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->ISForDofs)); 16921f4df5f7SStefano Zampini } 16931f4df5f7SStefano Zampini } else { 169421ef3d20SStefano Zampini if (!pcbddc->n_ISForDofsLocal) { /* field split not present */ 169521ef3d20SStefano Zampini DM dm; 169621ef3d20SStefano Zampini 16979566063dSJacob Faibussowitsch PetscCall(MatGetDM(pc->pmat, &dm)); 169848a46eb9SPierre Jolivet if (!dm) PetscCall(PCGetDM(pc, &dm)); 169921ef3d20SStefano Zampini if (dm) { 170021ef3d20SStefano Zampini IS *fields; 170121ef3d20SStefano Zampini PetscInt nf, i; 17020c85b387SStefano Zampini 17039566063dSJacob Faibussowitsch PetscCall(DMCreateFieldDecomposition(dm, &nf, NULL, &fields, NULL)); 17049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nf, &pcbddc->ISForDofsLocal)); 170521ef3d20SStefano Zampini for (i = 0; i < nf; i++) { 17060c85b387SStefano Zampini PetscInt bs; 17070c85b387SStefano Zampini 17089566063dSJacob Faibussowitsch PetscCall(PCBDDCGlobalToLocal(matis->rctx, global, local, fields[i], &pcbddc->ISForDofsLocal[i])); 17099566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(fields[i], &bs)); 17109566063dSJacob Faibussowitsch PetscCall(ISSetBlockSize(pcbddc->ISForDofsLocal[i], bs)); 17119566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fields[i])); 171221ef3d20SStefano Zampini } 17139566063dSJacob Faibussowitsch PetscCall(PetscFree(fields)); 171421ef3d20SStefano Zampini pcbddc->n_ISForDofsLocal = nf; 171521ef3d20SStefano Zampini } else { /* See if MATIS has fields attached by the conversion from MatNest */ 171621ef3d20SStefano Zampini PetscContainer c; 171721ef3d20SStefano Zampini 17189566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc->pmat, "_convert_nest_lfields", (PetscObject *)&c)); 171921ef3d20SStefano Zampini if (c) { 172021ef3d20SStefano Zampini MatISLocalFields lf; 17219566063dSJacob Faibussowitsch PetscCall(PetscContainerGetPointer(c, (void **)&lf)); 17229566063dSJacob Faibussowitsch PetscCall(PCBDDCSetDofsSplittingLocal(pc, lf->nr, lf->rf)); 172321ef3d20SStefano Zampini } else { /* fallback, create the default fields if bs > 1 */ 17241f4df5f7SStefano Zampini PetscInt i, n = matis->A->rmap->n; 17259566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(pc->pmat, &i)); 172621ef3d20SStefano Zampini if (i > 1) { 1727986cdee1SStefano Zampini pcbddc->n_ISForDofsLocal = i; 17289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->n_ISForDofsLocal, &pcbddc->ISForDofsLocal)); 172948a46eb9SPierre 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])); 17301f4df5f7SStefano Zampini } 173121ef3d20SStefano Zampini } 173221ef3d20SStefano Zampini } 17337a0e7b2cSstefano_zampini } else { 17347a0e7b2cSstefano_zampini PetscInt i; 173548a46eb9SPierre Jolivet for (i = 0; i < pcbddc->n_ISForDofsLocal; i++) PetscCall(PCBDDCConsistencyCheckIS(pc, MPI_LAND, &pcbddc->ISForDofsLocal[i])); 17361f4df5f7SStefano Zampini } 1737986cdee1SStefano Zampini } 17381f4df5f7SStefano Zampini 17395c5e10d6SStefano Zampini boundary: 17401f4df5f7SStefano Zampini if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) { 17419566063dSJacob Faibussowitsch PetscCall(PCBDDCGlobalToLocal(matis->rctx, global, local, pcbddc->DirichletBoundaries, &pcbddc->DirichletBoundariesLocal)); 17427a0e7b2cSstefano_zampini } else if (pcbddc->DirichletBoundariesLocal) { 17439566063dSJacob Faibussowitsch PetscCall(PCBDDCConsistencyCheckIS(pc, MPI_LAND, &pcbddc->DirichletBoundariesLocal)); 17441f4df5f7SStefano Zampini } 17451f4df5f7SStefano Zampini if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) { 17469566063dSJacob Faibussowitsch PetscCall(PCBDDCGlobalToLocal(matis->rctx, global, local, pcbddc->NeumannBoundaries, &pcbddc->NeumannBoundariesLocal)); 17477a0e7b2cSstefano_zampini } else if (pcbddc->NeumannBoundariesLocal) { 17489566063dSJacob Faibussowitsch PetscCall(PCBDDCConsistencyCheckIS(pc, MPI_LOR, &pcbddc->NeumannBoundariesLocal)); 17491f4df5f7SStefano Zampini } 175048a46eb9SPierre 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)); 17519566063dSJacob Faibussowitsch PetscCall(VecDestroy(&global)); 17529566063dSJacob Faibussowitsch PetscCall(VecDestroy(&local)); 17539de2952eSStefano Zampini /* detect local disconnected subdomains if requested or needed */ 17549de2952eSStefano Zampini if (pcbddc->detect_disconnected || matis->allow_repeated) { 17557620a527SStefano Zampini IS primalv = NULL; 17567620a527SStefano Zampini PetscInt i; 17578361f951SStefano Zampini PetscBool filter = pcbddc->detect_disconnected_filter; 17587a0e7b2cSstefano_zampini 175948a46eb9SPierre Jolivet for (i = 0; i < pcbddc->n_local_subs; i++) PetscCall(ISDestroy(&pcbddc->local_subs[i])); 17609566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->local_subs)); 17619566063dSJacob Faibussowitsch PetscCall(PCBDDCDetectDisconnectedComponents(pc, filter, &pcbddc->n_local_subs, &pcbddc->local_subs, &primalv)); 17629566063dSJacob Faibussowitsch PetscCall(PCBDDCAddPrimalVerticesLocalIS(pc, primalv)); 17639566063dSJacob Faibussowitsch PetscCall(ISDestroy(&primalv)); 17647620a527SStefano Zampini } 17657620a527SStefano Zampini /* early stage corner detection */ 17667620a527SStefano Zampini { 17677620a527SStefano Zampini DM dm; 17687620a527SStefano Zampini 17699566063dSJacob Faibussowitsch PetscCall(MatGetDM(pc->pmat, &dm)); 177048a46eb9SPierre Jolivet if (!dm) PetscCall(PCGetDM(pc, &dm)); 17717620a527SStefano Zampini if (dm) { 17727620a527SStefano Zampini PetscBool isda; 17737620a527SStefano Zampini 17749566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMDA, &isda)); 17757620a527SStefano Zampini if (isda) { 17767620a527SStefano Zampini ISLocalToGlobalMapping l2l; 17777620a527SStefano Zampini IS corners; 17787620a527SStefano Zampini Mat lA; 17794f819b78SStefano Zampini PetscBool gl, lo; 17807620a527SStefano Zampini 17814f819b78SStefano Zampini { 17824f819b78SStefano Zampini Vec cvec; 17834f819b78SStefano Zampini const PetscScalar *coords; 17844f819b78SStefano Zampini PetscInt dof, n, cdim; 17854f819b78SStefano Zampini PetscBool memc = PETSC_TRUE; 17864f819b78SStefano Zampini 17879566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL)); 17889566063dSJacob Faibussowitsch PetscCall(DMGetCoordinates(dm, &cvec)); 17899566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(cvec, &n)); 17909566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(cvec, &cdim)); 17914f819b78SStefano Zampini n /= cdim; 17929566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->mat_graph->coords)); 17939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dof * n * cdim, &pcbddc->mat_graph->coords)); 17949566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cvec, &coords)); 17954f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX) 17964f819b78SStefano Zampini memc = PETSC_FALSE; 17974f819b78SStefano Zampini #endif 17984f819b78SStefano Zampini if (dof != 1) memc = PETSC_FALSE; 17994f819b78SStefano Zampini if (memc) { 18009566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pcbddc->mat_graph->coords, coords, cdim * n * dof)); 18014f819b78SStefano Zampini } else { /* BDDC graph does not use any blocked information, we need to replicate the data */ 18024f819b78SStefano Zampini PetscReal *bcoords = pcbddc->mat_graph->coords; 18034f819b78SStefano Zampini PetscInt i, b, d; 18044f819b78SStefano Zampini 18054f819b78SStefano Zampini for (i = 0; i < n; i++) { 18064f819b78SStefano Zampini for (b = 0; b < dof; b++) { 1807ad540459SPierre Jolivet for (d = 0; d < cdim; d++) bcoords[i * dof * cdim + b * cdim + d] = PetscRealPart(coords[i * cdim + d]); 18084f819b78SStefano Zampini } 18094f819b78SStefano Zampini } 18104f819b78SStefano Zampini } 18119566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(cvec, &coords)); 18124f819b78SStefano Zampini pcbddc->mat_graph->cdim = cdim; 18134f819b78SStefano Zampini pcbddc->mat_graph->cnloc = dof * n; 18144f819b78SStefano Zampini pcbddc->mat_graph->cloc = PETSC_FALSE; 18154f819b78SStefano Zampini } 18169566063dSJacob Faibussowitsch PetscCall(DMDAGetSubdomainCornersIS(dm, &corners)); 18179566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->pmat, &lA)); 18189566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(lA, &l2l, NULL)); 18199566063dSJacob Faibussowitsch PetscCall(MatISRestoreLocalMat(pc->pmat, &lA)); 18204f819b78SStefano Zampini lo = (PetscBool)(l2l && corners); 18211c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&lo, &gl, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)pc))); 18224f819b78SStefano Zampini if (gl) { /* From PETSc's DMDA */ 18237620a527SStefano Zampini const PetscInt *idx; 182472ed36d8SStefano Zampini PetscInt dof, bs, *idxout, n; 18257620a527SStefano Zampini 18269566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL)); 18279566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(l2l, &bs)); 18289566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(corners, &n)); 18299566063dSJacob Faibussowitsch PetscCall(ISGetIndices(corners, &idx)); 183072ed36d8SStefano Zampini if (bs == dof) { 18319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &idxout)); 18329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(l2l, n, idx, idxout)); 183372ed36d8SStefano Zampini } else { /* the original DMDA local-to-local map have been modified */ 183472ed36d8SStefano Zampini PetscInt i, d; 183572ed36d8SStefano Zampini 18369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dof * n, &idxout)); 18379371c9d4SSatish Balay for (i = 0; i < n; i++) 18389371c9d4SSatish Balay for (d = 0; d < dof; d++) idxout[dof * i + d] = dof * idx[i] + d; 18399566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(l2l, dof * n, idxout, idxout)); 184072ed36d8SStefano Zampini 184172ed36d8SStefano Zampini bs = 1; 184272ed36d8SStefano Zampini n *= dof; 184372ed36d8SStefano Zampini } 18449566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(corners, &idx)); 18459566063dSJacob Faibussowitsch PetscCall(DMDARestoreSubdomainCornersIS(dm, &corners)); 18469566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)pc), bs, n, idxout, PETSC_OWN_POINTER, &corners)); 18479566063dSJacob Faibussowitsch PetscCall(PCBDDCAddPrimalVerticesLocalIS(pc, corners)); 18489566063dSJacob Faibussowitsch PetscCall(ISDestroy(&corners)); 18491c7a958bSStefano Zampini pcbddc->corner_selected = PETSC_TRUE; 18504f819b78SStefano Zampini pcbddc->corner_selection = PETSC_TRUE; 18514f819b78SStefano Zampini } 185248a46eb9SPierre Jolivet if (corners) PetscCall(DMDARestoreSubdomainCornersIS(dm, &corners)); 18537620a527SStefano Zampini } 18547620a527SStefano Zampini } 18557620a527SStefano Zampini } 18561c7a958bSStefano Zampini if (pcbddc->corner_selection && !pcbddc->mat_graph->cdim) { 18571c7a958bSStefano Zampini DM dm; 18581c7a958bSStefano Zampini 18599566063dSJacob Faibussowitsch PetscCall(MatGetDM(pc->pmat, &dm)); 186048a46eb9SPierre Jolivet if (!dm) PetscCall(PCGetDM(pc, &dm)); 18614f819b78SStefano Zampini if (dm) { /* this can get very expensive, I need to find a faster alternative */ 18621c7a958bSStefano Zampini Vec vcoords; 18631c7a958bSStefano Zampini PetscSection section; 18641c7a958bSStefano Zampini PetscReal *coords; 18651c7a958bSStefano Zampini PetscInt d, cdim, nl, nf, **ctxs; 18661c7a958bSStefano Zampini PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal *, PetscInt, PetscScalar *, void *); 186751ab8ad6SStefano Zampini /* debug coordinates */ 186851ab8ad6SStefano Zampini PetscViewer viewer; 186951ab8ad6SStefano Zampini PetscBool flg; 187051ab8ad6SStefano Zampini PetscViewerFormat format; 187151ab8ad6SStefano Zampini const char *prefix; 18721c7a958bSStefano Zampini 18739566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 18749566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 18759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &nf)); 18769566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dm, &vcoords)); 18779566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vcoords, &nl)); 18789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl * cdim, &coords)); 18799566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nf, &funcs, nf, &ctxs)); 18809566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nf, &ctxs[0])); 18811c7a958bSStefano Zampini for (d = 0; d < nf; d++) funcs[d] = func_coords_private; 18821c7a958bSStefano Zampini for (d = 1; d < nf; d++) ctxs[d] = ctxs[d - 1] + 1; 188351ab8ad6SStefano Zampini 188451ab8ad6SStefano Zampini /* debug coordinates */ 188551ab8ad6SStefano Zampini PetscCall(PCGetOptionsPrefix(pc, &prefix)); 188651ab8ad6SStefano Zampini PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)vcoords), ((PetscObject)vcoords)->options, prefix, "-pc_bddc_coords_vec_view", &viewer, &format, &flg)); 188751ab8ad6SStefano Zampini if (flg) PetscCall(PetscViewerPushFormat(viewer, format)); 18881c7a958bSStefano Zampini for (d = 0; d < cdim; d++) { 18891c7a958bSStefano Zampini PetscInt i; 18901c7a958bSStefano Zampini const PetscScalar *v; 189151ab8ad6SStefano Zampini char name[16]; 18921c7a958bSStefano Zampini 18931c7a958bSStefano Zampini for (i = 0; i < nf; i++) ctxs[i][0] = d; 189451ab8ad6SStefano Zampini PetscCall(PetscSNPrintf(name, sizeof(name), "bddc_coords_%d", (int)d)); 189551ab8ad6SStefano Zampini PetscCall(PetscObjectSetName((PetscObject)vcoords, name)); 18969566063dSJacob Faibussowitsch PetscCall(DMProjectFunction(dm, 0.0, funcs, (void **)ctxs, INSERT_VALUES, vcoords)); 189751ab8ad6SStefano Zampini if (flg) PetscCall(VecView(vcoords, viewer)); 18989566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vcoords, &v)); 18991c7a958bSStefano Zampini for (i = 0; i < nl; i++) coords[i * cdim + d] = PetscRealPart(v[i]); 19009566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vcoords, &v)); 19011c7a958bSStefano Zampini } 19029566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vcoords)); 19039566063dSJacob Faibussowitsch PetscCall(PCSetCoordinates(pc, cdim, nl, coords)); 19049566063dSJacob Faibussowitsch PetscCall(PetscFree(coords)); 19059566063dSJacob Faibussowitsch PetscCall(PetscFree(ctxs[0])); 19069566063dSJacob Faibussowitsch PetscCall(PetscFree2(funcs, ctxs)); 190751ab8ad6SStefano Zampini if (flg) { 190851ab8ad6SStefano Zampini PetscCall(PetscViewerPopFormat(viewer)); 1909cd791dc2SBarry Smith PetscCall(PetscOptionsRestoreViewer(&viewer)); 191051ab8ad6SStefano Zampini } 19111c7a958bSStefano Zampini } 19121c7a958bSStefano Zampini } 19133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19147a0e7b2cSstefano_zampini } 19157a0e7b2cSstefano_zampini 1916d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCConsistencyCheckIS(PC pc, MPI_Op mop, IS *is) 1917d71ae5a4SJacob Faibussowitsch { 1918f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)pc->pmat->data; 19197a0e7b2cSstefano_zampini IS nis; 19207a0e7b2cSstefano_zampini const PetscInt *idxs; 19217a0e7b2cSstefano_zampini PetscInt i, nd, n = matis->A->rmap->n, *nidxs, nnd; 19227a0e7b2cSstefano_zampini 19237a0e7b2cSstefano_zampini PetscFunctionBegin; 19247827d75bSBarry Smith PetscCheck(mop == MPI_LAND || mop == MPI_LOR, PetscObjectComm((PetscObject)(pc)), PETSC_ERR_SUP, "Supported are MPI_LAND and MPI_LOR"); 19257a0e7b2cSstefano_zampini if (mop == MPI_LAND) { 19267a0e7b2cSstefano_zampini /* init rootdata with true */ 19271bd50df1SStefano Zampini for (i = 0; i < pc->pmat->rmap->n; i++) matis->sf_rootdata[i] = 1; 19287a0e7b2cSstefano_zampini } else { 19299566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_rootdata, pc->pmat->rmap->n)); 19307a0e7b2cSstefano_zampini } 19319566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_leafdata, n)); 19329566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(*is, &nd)); 19339566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*is, &idxs)); 19347a0e7b2cSstefano_zampini for (i = 0; i < nd; i++) 19359371c9d4SSatish Balay if (-1 < idxs[i] && idxs[i] < n) matis->sf_leafdata[idxs[i]] = 1; 19369566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*is, &idxs)); 19379566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, matis->sf_leafdata, matis->sf_rootdata, mop)); 19389566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, matis->sf_leafdata, matis->sf_rootdata, mop)); 19399566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 19409566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 19417a0e7b2cSstefano_zampini if (mop == MPI_LAND) { 19429566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nd, &nidxs)); 19437a0e7b2cSstefano_zampini } else { 19449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &nidxs)); 19457a0e7b2cSstefano_zampini } 19467a0e7b2cSstefano_zampini for (i = 0, nnd = 0; i < n; i++) 19479371c9d4SSatish Balay if (matis->sf_leafdata[i]) nidxs[nnd++] = i; 1948f4f49eeaSPierre Jolivet PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)*is), nnd, nidxs, PETSC_OWN_POINTER, &nis)); 19499566063dSJacob Faibussowitsch PetscCall(ISDestroy(is)); 19507a0e7b2cSstefano_zampini *is = nis; 19513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19521f4df5f7SStefano Zampini } 19531f4df5f7SStefano Zampini 1954d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignRemoveInterior(PC pc, Vec r, Vec z) 1955d71ae5a4SJacob Faibussowitsch { 1956f4f49eeaSPierre Jolivet PC_IS *pcis = (PC_IS *)pc->data; 1957f4f49eeaSPierre Jolivet PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 19583e589ea0SStefano Zampini 19593e589ea0SStefano Zampini PetscFunctionBegin; 19603ba16761SJacob Faibussowitsch if (!pcbddc->benign_have_null) PetscFunctionReturn(PETSC_SUCCESS); 19613e589ea0SStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 19623e589ea0SStefano Zampini Vec swap; 19633e589ea0SStefano Zampini 19649566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, r, pcbddc->work_change)); 19653e589ea0SStefano Zampini swap = pcbddc->work_change; 19663e589ea0SStefano Zampini pcbddc->work_change = r; 19673e589ea0SStefano Zampini r = swap; 19683e589ea0SStefano Zampini } 19699566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 19709566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 19719566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 19729566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D)); 19739566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 19749566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D)); 19759566063dSJacob Faibussowitsch PetscCall(VecSet(z, 0.)); 19769566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE)); 19779566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE)); 19783e589ea0SStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 1979f913dca9SStefano Zampini pcbddc->work_change = r; 19809566063dSJacob Faibussowitsch PetscCall(VecCopy(z, pcbddc->work_change)); 19819566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcbddc->work_change, z)); 19823e589ea0SStefano Zampini } 19833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19843e589ea0SStefano Zampini } 19853e589ea0SStefano Zampini 1986ba38deedSJacob Faibussowitsch static PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose) 1987d71ae5a4SJacob Faibussowitsch { 1988a3df083aSStefano Zampini PCBDDCBenignMatMult_ctx ctx; 1989a3df083aSStefano Zampini PetscBool apply_right, apply_left, reset_x; 1990a3df083aSStefano Zampini 1991a3df083aSStefano Zampini PetscFunctionBegin; 19929566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(A, &ctx)); 1993a3df083aSStefano Zampini if (transpose) { 1994a3df083aSStefano Zampini apply_right = ctx->apply_left; 1995a3df083aSStefano Zampini apply_left = ctx->apply_right; 1996a3df083aSStefano Zampini } else { 1997a3df083aSStefano Zampini apply_right = ctx->apply_right; 1998a3df083aSStefano Zampini apply_left = ctx->apply_left; 1999a3df083aSStefano Zampini } 2000a3df083aSStefano Zampini reset_x = PETSC_FALSE; 2001a3df083aSStefano Zampini if (apply_right) { 2002a3df083aSStefano Zampini const PetscScalar *ax; 2003a3df083aSStefano Zampini PetscInt nl, i; 2004a3df083aSStefano Zampini 20059566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(x, &nl)); 20069566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &ax)); 20079566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(ctx->work, ax, nl)); 20089566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &ax)); 2009a3df083aSStefano Zampini for (i = 0; i < ctx->benign_n; i++) { 2010a3df083aSStefano Zampini PetscScalar sum, val; 2011a3df083aSStefano Zampini const PetscInt *idxs; 2012a3df083aSStefano Zampini PetscInt nz, j; 20139566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(ctx->benign_zerodiag_subs[i], &nz)); 20149566063dSJacob Faibussowitsch PetscCall(ISGetIndices(ctx->benign_zerodiag_subs[i], &idxs)); 2015a3df083aSStefano Zampini sum = 0.; 2016a3df083aSStefano Zampini if (ctx->apply_p0) { 2017a3df083aSStefano Zampini val = ctx->work[idxs[nz - 1]]; 2018a3df083aSStefano Zampini for (j = 0; j < nz - 1; j++) { 2019a3df083aSStefano Zampini sum += ctx->work[idxs[j]]; 2020a3df083aSStefano Zampini ctx->work[idxs[j]] += val; 2021a3df083aSStefano Zampini } 2022a3df083aSStefano Zampini } else { 2023ad540459SPierre Jolivet for (j = 0; j < nz - 1; j++) sum += ctx->work[idxs[j]]; 2024a3df083aSStefano Zampini } 2025a3df083aSStefano Zampini ctx->work[idxs[nz - 1]] -= sum; 20269566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(ctx->benign_zerodiag_subs[i], &idxs)); 2027a3df083aSStefano Zampini } 20289566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(x, ctx->work)); 2029a3df083aSStefano Zampini reset_x = PETSC_TRUE; 2030a3df083aSStefano Zampini } 2031a3df083aSStefano Zampini if (transpose) { 20329566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(ctx->A, x, y)); 2033a3df083aSStefano Zampini } else { 20349566063dSJacob Faibussowitsch PetscCall(MatMult(ctx->A, x, y)); 2035a3df083aSStefano Zampini } 20361baa6e33SBarry Smith if (reset_x) PetscCall(VecResetArray(x)); 2037a3df083aSStefano Zampini if (apply_left) { 2038a3df083aSStefano Zampini PetscScalar *ay; 2039a3df083aSStefano Zampini PetscInt i; 2040a3df083aSStefano Zampini 20419566063dSJacob Faibussowitsch PetscCall(VecGetArray(y, &ay)); 2042a3df083aSStefano Zampini for (i = 0; i < ctx->benign_n; i++) { 2043a3df083aSStefano Zampini PetscScalar sum, val; 2044a3df083aSStefano Zampini const PetscInt *idxs; 2045a3df083aSStefano Zampini PetscInt nz, j; 20469566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(ctx->benign_zerodiag_subs[i], &nz)); 20479566063dSJacob Faibussowitsch PetscCall(ISGetIndices(ctx->benign_zerodiag_subs[i], &idxs)); 2048a3df083aSStefano Zampini val = -ay[idxs[nz - 1]]; 2049a3df083aSStefano Zampini if (ctx->apply_p0) { 2050a3df083aSStefano Zampini sum = 0.; 2051a3df083aSStefano Zampini for (j = 0; j < nz - 1; j++) { 2052a3df083aSStefano Zampini sum += ay[idxs[j]]; 2053a3df083aSStefano Zampini ay[idxs[j]] += val; 2054a3df083aSStefano Zampini } 2055a3df083aSStefano Zampini ay[idxs[nz - 1]] += sum; 2056a3df083aSStefano Zampini } else { 2057ad540459SPierre Jolivet for (j = 0; j < nz - 1; j++) ay[idxs[j]] += val; 2058a3df083aSStefano Zampini ay[idxs[nz - 1]] = 0.; 2059a3df083aSStefano Zampini } 20609566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(ctx->benign_zerodiag_subs[i], &idxs)); 2061a3df083aSStefano Zampini } 20629566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(y, &ay)); 2063a3df083aSStefano Zampini } 20643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2065a3df083aSStefano Zampini } 2066a3df083aSStefano Zampini 2067ba38deedSJacob Faibussowitsch static PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y) 2068d71ae5a4SJacob Faibussowitsch { 2069a3df083aSStefano Zampini PetscFunctionBegin; 20709566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignMatMult_Private_Private(A, x, y, PETSC_TRUE)); 20713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2072a3df083aSStefano Zampini } 2073a3df083aSStefano Zampini 2074ba38deedSJacob Faibussowitsch static PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y) 2075d71ae5a4SJacob Faibussowitsch { 2076a3df083aSStefano Zampini PetscFunctionBegin; 20779566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignMatMult_Private_Private(A, x, y, PETSC_FALSE)); 20783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2079a3df083aSStefano Zampini } 2080a3df083aSStefano Zampini 2081d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore) 2082d71ae5a4SJacob Faibussowitsch { 2083a3df083aSStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 2084a3df083aSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 2085a3df083aSStefano Zampini PCBDDCBenignMatMult_ctx ctx; 2086a3df083aSStefano Zampini 2087a3df083aSStefano Zampini PetscFunctionBegin; 2088a3df083aSStefano Zampini if (!restore) { 20891dd7afcfSStefano Zampini Mat A_IB, A_BI; 2090a3df083aSStefano Zampini PetscScalar *work; 2091b334f244SStefano Zampini PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL; 2092a3df083aSStefano Zampini 209328b400f6SJacob Faibussowitsch PetscCheck(!pcbddc->benign_original_mat, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Benign original mat has not been restored"); 20943ba16761SJacob Faibussowitsch if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(PETSC_SUCCESS); 20959566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n, &work)); 20969566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &A_IB)); 20979566063dSJacob Faibussowitsch PetscCall(MatSetSizes(A_IB, pcis->n - pcis->n_B, pcis->n_B, PETSC_DECIDE, PETSC_DECIDE)); 20989566063dSJacob Faibussowitsch PetscCall(MatSetType(A_IB, MATSHELL)); 20999566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(A_IB, MATOP_MULT, (void (*)(void))PCBDDCBenignMatMult_Private)); 21009566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(A_IB, MATOP_MULT_TRANSPOSE, (void (*)(void))PCBDDCBenignMatMultTranspose_Private)); 21019566063dSJacob Faibussowitsch PetscCall(PetscNew(&ctx)); 21029566063dSJacob Faibussowitsch PetscCall(MatShellSetContext(A_IB, ctx)); 2103a3df083aSStefano Zampini ctx->apply_left = PETSC_TRUE; 2104a3df083aSStefano Zampini ctx->apply_right = PETSC_FALSE; 2105a3df083aSStefano Zampini ctx->apply_p0 = PETSC_FALSE; 2106a3df083aSStefano Zampini ctx->benign_n = pcbddc->benign_n; 2107059032f7SStefano Zampini if (reuse) { 2108a3df083aSStefano Zampini ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs; 21091dd7afcfSStefano Zampini ctx->free = PETSC_FALSE; 2110059032f7SStefano Zampini } else { /* TODO: could be optimized for successive solves */ 2111059032f7SStefano Zampini ISLocalToGlobalMapping N_to_D; 2112059032f7SStefano Zampini PetscInt i; 2113059032f7SStefano Zampini 21149566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(pcis->is_I_local, &N_to_D)); 21159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->benign_n, &ctx->benign_zerodiag_subs)); 211648a46eb9SPierre 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])); 21179566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&N_to_D)); 21181dd7afcfSStefano Zampini ctx->free = PETSC_TRUE; 2119059032f7SStefano Zampini } 2120a3df083aSStefano Zampini ctx->A = pcis->A_IB; 2121a3df083aSStefano Zampini ctx->work = work; 21229566063dSJacob Faibussowitsch PetscCall(MatSetUp(A_IB)); 21239566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A_IB, MAT_FINAL_ASSEMBLY)); 21249566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A_IB, MAT_FINAL_ASSEMBLY)); 2125a3df083aSStefano Zampini pcis->A_IB = A_IB; 2126a3df083aSStefano Zampini 2127a3df083aSStefano Zampini /* A_BI as A_IB^T */ 21289566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(A_IB, &A_BI)); 2129a3df083aSStefano Zampini pcbddc->benign_original_mat = pcis->A_BI; 2130a3df083aSStefano Zampini pcis->A_BI = A_BI; 2131a3df083aSStefano Zampini } else { 21323ba16761SJacob Faibussowitsch if (!pcbddc->benign_original_mat) PetscFunctionReturn(PETSC_SUCCESS); 21339566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(pcis->A_IB, &ctx)); 21349566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_IB)); 2135a3df083aSStefano Zampini pcis->A_IB = ctx->A; 21361dd7afcfSStefano Zampini ctx->A = NULL; 21379566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_BI)); 21381dd7afcfSStefano Zampini pcis->A_BI = pcbddc->benign_original_mat; 21391dd7afcfSStefano Zampini pcbddc->benign_original_mat = NULL; 21401dd7afcfSStefano Zampini if (ctx->free) { 2141059032f7SStefano Zampini PetscInt i; 214248a46eb9SPierre Jolivet for (i = 0; i < ctx->benign_n; i++) PetscCall(ISDestroy(&ctx->benign_zerodiag_subs[i])); 21439566063dSJacob Faibussowitsch PetscCall(PetscFree(ctx->benign_zerodiag_subs)); 2144059032f7SStefano Zampini } 21459566063dSJacob Faibussowitsch PetscCall(PetscFree(ctx->work)); 21469566063dSJacob Faibussowitsch PetscCall(PetscFree(ctx)); 2147a3df083aSStefano Zampini } 21483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2149a3df083aSStefano Zampini } 2150a3df083aSStefano Zampini 2151a3df083aSStefano Zampini /* used just in bddc debug mode */ 2152ba38deedSJacob Faibussowitsch static PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B) 2153d71ae5a4SJacob Faibussowitsch { 2154a3df083aSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 2155a3df083aSStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 2156a3df083aSStefano Zampini Mat An; 2157a3df083aSStefano Zampini 2158a3df083aSStefano Zampini PetscFunctionBegin; 21599566063dSJacob Faibussowitsch PetscCall(MatPtAP(matis->A, pcbddc->benign_change, MAT_INITIAL_MATRIX, 2.0, &An)); 21609566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns(An, pcbddc->benign_n, pcbddc->benign_p0_lidx, 1.0, NULL, NULL)); 2161a3df083aSStefano Zampini if (is1) { 21629566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(An, is1, is2, MAT_INITIAL_MATRIX, B)); 21639566063dSJacob Faibussowitsch PetscCall(MatDestroy(&An)); 2164a3df083aSStefano Zampini } else { 2165a3df083aSStefano Zampini *B = An; 2166a3df083aSStefano Zampini } 21673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2168a3df083aSStefano Zampini } 2169a3df083aSStefano Zampini 21701cf9b237SStefano Zampini /* TODO: add reuse flag */ 2171d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B) 2172d71ae5a4SJacob Faibussowitsch { 21731cf9b237SStefano Zampini Mat Bt; 21741cf9b237SStefano Zampini PetscScalar *a, *bdata; 21751cf9b237SStefano Zampini const PetscInt *ii, *ij; 21761cf9b237SStefano Zampini PetscInt m, n, i, nnz, *bii, *bij; 21771cf9b237SStefano Zampini PetscBool flg_row; 21781cf9b237SStefano Zampini 21791cf9b237SStefano Zampini PetscFunctionBegin; 21809566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &n, &m)); 21819566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &ij, &flg_row)); 21829566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &a)); 21831cf9b237SStefano Zampini nnz = n; 21841cf9b237SStefano Zampini for (i = 0; i < ii[n]; i++) { 21851cf9b237SStefano Zampini if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++; 21861cf9b237SStefano Zampini } 21879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n + 1, &bii)); 21889566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &bij)); 21899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &bdata)); 21901cf9b237SStefano Zampini nnz = 0; 21911cf9b237SStefano Zampini bii[0] = 0; 21921cf9b237SStefano Zampini for (i = 0; i < n; i++) { 21931cf9b237SStefano Zampini PetscInt j; 21941cf9b237SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 21951cf9b237SStefano Zampini PetscScalar entry = a[j]; 21963272d46bSStefano Zampini if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || (n == m && ij[j] == i)) { 21971cf9b237SStefano Zampini bij[nnz] = ij[j]; 21981cf9b237SStefano Zampini bdata[nnz] = entry; 21991cf9b237SStefano Zampini nnz++; 22001cf9b237SStefano Zampini } 22011cf9b237SStefano Zampini } 22021cf9b237SStefano Zampini bii[i + 1] = nnz; 22031cf9b237SStefano Zampini } 22049566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &a)); 22059566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A), n, m, bii, bij, bdata, &Bt)); 22069566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &ij, &flg_row)); 22071cf9b237SStefano Zampini { 2208f4f49eeaSPierre Jolivet Mat_SeqAIJ *b = (Mat_SeqAIJ *)Bt->data; 22091cf9b237SStefano Zampini b->free_a = PETSC_TRUE; 22101cf9b237SStefano Zampini b->free_ij = PETSC_TRUE; 22111cf9b237SStefano Zampini } 221248a46eb9SPierre Jolivet if (*B == A) PetscCall(MatDestroy(&A)); 22131cf9b237SStefano Zampini *B = Bt; 22143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22151cf9b237SStefano Zampini } 22161cf9b237SStefano Zampini 2217d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCDetectDisconnectedComponents(PC pc, PetscBool filter, PetscInt *ncc, IS *cc[], IS *primalv) 2218d71ae5a4SJacob Faibussowitsch { 2219c80a6c00SStefano Zampini Mat B = NULL; 2220c80a6c00SStefano Zampini DM dm; 22214f1b2e48SStefano Zampini IS is_dummy, *cc_n; 22224f1b2e48SStefano Zampini ISLocalToGlobalMapping l2gmap_dummy; 22234f1b2e48SStefano Zampini PCBDDCGraph graph; 2224c80a6c00SStefano Zampini PetscInt *xadj_filtered = NULL, *adjncy_filtered = NULL; 22254f1b2e48SStefano Zampini PetscInt i, n; 22264f1b2e48SStefano Zampini PetscInt *xadj, *adjncy; 2227c80a6c00SStefano Zampini PetscBool isplex = PETSC_FALSE; 22284f1b2e48SStefano Zampini 22294f1b2e48SStefano Zampini PetscFunctionBegin; 2230a2eca866SStefano Zampini if (ncc) *ncc = 0; 2231a2eca866SStefano Zampini if (cc) *cc = NULL; 2232a2eca866SStefano Zampini if (primalv) *primalv = NULL; 22339566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphCreate(&graph)); 22349566063dSJacob Faibussowitsch PetscCall(MatGetDM(pc->pmat, &dm)); 223548a46eb9SPierre Jolivet if (!dm) PetscCall(PCGetDM(pc, &dm)); 2236f9635d15SStefano Zampini if (dm) PetscCall(PetscObjectTypeCompareAny((PetscObject)dm, &isplex, DMPLEX, DMP4EST, DMP8EST, "")); 22378361f951SStefano Zampini if (filter) isplex = PETSC_FALSE; 22388361f951SStefano Zampini 2239c80a6c00SStefano Zampini if (isplex) { /* this code has been modified from plexpartition.c */ 2240c80a6c00SStefano Zampini PetscInt p, pStart, pEnd, a, adjSize, idx, size, nroots; 2241c80a6c00SStefano Zampini PetscInt *adj = NULL; 2242c80a6c00SStefano Zampini IS cellNumbering; 2243c80a6c00SStefano Zampini const PetscInt *cellNum; 2244c80a6c00SStefano Zampini PetscBool useCone, useClosure; 2245c80a6c00SStefano Zampini PetscSection section; 2246c80a6c00SStefano Zampini PetscSegBuffer adjBuffer; 2247c80a6c00SStefano Zampini PetscSF sfPoint; 2248c80a6c00SStefano Zampini 2249f9635d15SStefano Zampini PetscCall(DMConvert(dm, DMPLEX, &dm)); 22509566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd)); 22519566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 22529566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL)); 2253c80a6c00SStefano Zampini /* Build adjacency graph via a section/segbuffer */ 22549566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 22559566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 22569566063dSJacob Faibussowitsch PetscCall(PetscSegBufferCreate(sizeof(PetscInt), 1000, &adjBuffer)); 2257c80a6c00SStefano Zampini /* Always use FVM adjacency to create partitioner graph */ 22589566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 22599566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE)); 22609566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellNumbering(dm, &cellNumbering)); 22619566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cellNumbering, &cellNum)); 2262c80a6c00SStefano Zampini for (n = 0, p = pStart; p < pEnd; p++) { 2263c80a6c00SStefano Zampini /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 22649371c9d4SSatish Balay if (nroots > 0) { 22659371c9d4SSatish Balay if (cellNum[p] < 0) continue; 22669371c9d4SSatish Balay } 2267c80a6c00SStefano Zampini adjSize = PETSC_DETERMINE; 22689566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj)); 2269c80a6c00SStefano Zampini for (a = 0; a < adjSize; ++a) { 2270c80a6c00SStefano Zampini const PetscInt point = adj[a]; 22715cef3d0dSStefano Zampini if (pStart <= point && point < pEnd) { 2272c80a6c00SStefano Zampini PetscInt *PETSC_RESTRICT pBuf; 22739566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(section, p, 1)); 22749566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGetInts(adjBuffer, 1, &pBuf)); 2275c80a6c00SStefano Zampini *pBuf = point; 2276c80a6c00SStefano Zampini } 2277c80a6c00SStefano Zampini } 2278c80a6c00SStefano Zampini n++; 2279c80a6c00SStefano Zampini } 22809566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dm, useCone, useClosure)); 2281c80a6c00SStefano Zampini /* Derive CSR graph from section/segbuffer */ 22829566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 22839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &size)); 22849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n + 1, &xadj)); 2285c80a6c00SStefano Zampini for (idx = 0, p = pStart; p < pEnd; p++) { 22869371c9d4SSatish Balay if (nroots > 0) { 22879371c9d4SSatish Balay if (cellNum[p] < 0) continue; 22889371c9d4SSatish Balay } 2289f4f49eeaSPierre Jolivet PetscCall(PetscSectionGetOffset(section, p, &xadj[idx++])); 2290c80a6c00SStefano Zampini } 2291c80a6c00SStefano Zampini xadj[n] = size; 22929566063dSJacob Faibussowitsch PetscCall(PetscSegBufferExtractAlloc(adjBuffer, &adjncy)); 2293c80a6c00SStefano Zampini /* Clean up */ 22949566063dSJacob Faibussowitsch PetscCall(PetscSegBufferDestroy(&adjBuffer)); 22959566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 22969566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 2297c80a6c00SStefano Zampini graph->xadj = xadj; 2298c80a6c00SStefano Zampini graph->adjncy = adjncy; 2299c80a6c00SStefano Zampini } else { 2300c80a6c00SStefano Zampini Mat A; 23018361f951SStefano Zampini PetscBool isseqaij, flg_row; 2302c80a6c00SStefano Zampini 23039566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->pmat, &A)); 230463c961adSStefano Zampini if (!A->rmap->N || !A->cmap->N) { 23059566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphDestroy(&graph)); 23063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 230763c961adSStefano Zampini } 23089566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isseqaij)); 23094f1b2e48SStefano Zampini if (!isseqaij && filter) { 23101cf9b237SStefano Zampini PetscBool isseqdense; 23111cf9b237SStefano Zampini 23129566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATSEQDENSE, &isseqdense)); 23131cf9b237SStefano Zampini if (!isseqdense) { 23149566063dSJacob Faibussowitsch PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &B)); 23151cf9b237SStefano Zampini } else { /* TODO: rectangular case and LDA */ 23161cf9b237SStefano Zampini PetscScalar *array; 23171cf9b237SStefano Zampini PetscReal chop = 1.e-6; 23181cf9b237SStefano Zampini 23199566063dSJacob Faibussowitsch PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &B)); 23209566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(B, &array)); 23219566063dSJacob Faibussowitsch PetscCall(MatGetSize(B, &n, NULL)); 23221cf9b237SStefano Zampini for (i = 0; i < n; i++) { 23231cf9b237SStefano Zampini PetscInt j; 23241cf9b237SStefano Zampini for (j = i + 1; j < n; j++) { 23251cf9b237SStefano Zampini PetscReal thresh = chop * (PetscAbsScalar(array[i * (n + 1)]) + PetscAbsScalar(array[j * (n + 1)])); 23261cf9b237SStefano Zampini if (PetscAbsScalar(array[i * n + j]) < thresh) array[i * n + j] = 0.; 23271cf9b237SStefano Zampini if (PetscAbsScalar(array[j * n + i]) < thresh) array[j * n + i] = 0.; 23281cf9b237SStefano Zampini } 23291cf9b237SStefano Zampini } 23309566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(B, &array)); 23319566063dSJacob Faibussowitsch PetscCall(MatConvert(B, MATSEQAIJ, MAT_INPLACE_MATRIX, &B)); 23321cf9b237SStefano Zampini } 23334f1b2e48SStefano Zampini } else { 23349566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 23354f1b2e48SStefano Zampini B = A; 23364f1b2e48SStefano Zampini } 23379566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(B, 0, PETSC_TRUE, PETSC_FALSE, &n, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &flg_row)); 23384f1b2e48SStefano Zampini 23394f1b2e48SStefano Zampini /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */ 23404f1b2e48SStefano Zampini if (filter) { 23414f1b2e48SStefano Zampini PetscScalar *data; 23424f1b2e48SStefano Zampini PetscInt j, cum; 23434f1b2e48SStefano Zampini 23449566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(n + 1, &xadj_filtered, xadj[n], &adjncy_filtered)); 23459566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(B, &data)); 23464f1b2e48SStefano Zampini cum = 0; 23474f1b2e48SStefano Zampini for (i = 0; i < n; i++) { 23484f1b2e48SStefano Zampini PetscInt t; 23494f1b2e48SStefano Zampini 23504f1b2e48SStefano Zampini for (j = xadj[i]; j < xadj[i + 1]; j++) { 2351ad540459SPierre Jolivet if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) continue; 23524f1b2e48SStefano Zampini adjncy_filtered[cum + xadj_filtered[i]++] = adjncy[j]; 23534f1b2e48SStefano Zampini } 23544f1b2e48SStefano Zampini t = xadj_filtered[i]; 23554f1b2e48SStefano Zampini xadj_filtered[i] = cum; 23564f1b2e48SStefano Zampini cum += t; 23574f1b2e48SStefano Zampini } 23589566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(B, &data)); 23594f1b2e48SStefano Zampini graph->xadj = xadj_filtered; 23604f1b2e48SStefano Zampini graph->adjncy = adjncy_filtered; 23614f1b2e48SStefano Zampini } else { 23624f1b2e48SStefano Zampini graph->xadj = xadj; 23634f1b2e48SStefano Zampini graph->adjncy = adjncy; 23644f1b2e48SStefano Zampini } 2365c80a6c00SStefano Zampini } 2366c80a6c00SStefano Zampini /* compute local connected components using PCBDDCGraph */ 23679de2952eSStefano Zampini graph->seq_graph = PETSC_TRUE; /* analyze local connected components (i.e. disconnected subdomains) irrespective of dofs count */ 23689566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, n, 0, 1, &is_dummy)); 23699566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is_dummy, &l2gmap_dummy)); 23709566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_dummy)); 23719566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphInit(graph, l2gmap_dummy, n, PETSC_MAX_INT)); 23729566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&l2gmap_dummy)); 23739566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphSetUp(graph, 1, NULL, NULL, 0, NULL, NULL)); 23749566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphComputeConnectedComponents(graph)); 2375c80a6c00SStefano Zampini 23764f1b2e48SStefano Zampini /* partial clean up */ 23779566063dSJacob Faibussowitsch PetscCall(PetscFree2(xadj_filtered, adjncy_filtered)); 2378c80a6c00SStefano Zampini if (B) { 2379c80a6c00SStefano Zampini PetscBool flg_row; 23809566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(B, 0, PETSC_TRUE, PETSC_FALSE, &n, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &flg_row)); 23819566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 23824f1b2e48SStefano Zampini } 2383c80a6c00SStefano Zampini if (isplex) { 23849566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 23859566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 2386c80a6c00SStefano Zampini } 23874f1b2e48SStefano Zampini 23884f1b2e48SStefano Zampini /* get back data */ 2389c80a6c00SStefano Zampini if (isplex) { 2390c80a6c00SStefano Zampini if (ncc) *ncc = graph->ncc; 2391c80a6c00SStefano Zampini if (cc || primalv) { 2392c80a6c00SStefano Zampini Mat A; 2393f9635d15SStefano Zampini PetscBT btv, btvt, btvc; 2394c80a6c00SStefano Zampini PetscSection subSection; 2395c80a6c00SStefano Zampini PetscInt *ids, cum, cump, *cids, *pids; 2396f9635d15SStefano Zampini PetscInt dim, cStart, cEnd, fStart, fEnd, vStart, vEnd, pStart, pEnd; 2397c80a6c00SStefano Zampini 2398f9635d15SStefano Zampini PetscCall(DMGetDimension(dm, &dim)); 23999566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubdomainSection(dm, &subSection)); 2400f9635d15SStefano Zampini PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 2401f9635d15SStefano Zampini PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 2402f9635d15SStefano Zampini PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 2403f9635d15SStefano Zampini PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 24049566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->pmat, &A)); 24059566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(A->rmap->n, &ids, graph->ncc + 1, &cids, A->rmap->n, &pids)); 24069566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(A->rmap->n, &btv)); 24079566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(A->rmap->n, &btvt)); 2408f9635d15SStefano Zampini PetscCall(PetscBTCreate(pEnd - pStart, &btvc)); 2409f9635d15SStefano Zampini 2410f9635d15SStefano Zampini /* First see if we find corners for the subdomains, i.e. a vertex 2411f9635d15SStefano Zampini shared by at least dim subdomain boundary faces. This does not 2412f9635d15SStefano Zampini cover all the possible cases with simplices but it is enough 2413f9635d15SStefano Zampini for tensor cells */ 2414f9635d15SStefano Zampini if (vStart != fStart && dim <= 3) { 2415f9635d15SStefano Zampini for (PetscInt c = cStart; c < cEnd; c++) { 2416f9635d15SStefano Zampini PetscInt nf, cnt = 0, mcnt = dim, *cfaces; 2417f9635d15SStefano Zampini const PetscInt *faces; 2418f9635d15SStefano Zampini 2419f9635d15SStefano Zampini PetscCall(DMPlexGetConeSize(dm, c, &nf)); 2420f9635d15SStefano Zampini PetscCall(DMGetWorkArray(dm, nf, MPIU_INT, &cfaces)); 2421f9635d15SStefano Zampini PetscCall(DMPlexGetCone(dm, c, &faces)); 2422f9635d15SStefano Zampini for (PetscInt f = 0; f < nf; f++) { 2423f9635d15SStefano Zampini PetscInt nc, ff; 2424f9635d15SStefano Zampini 2425f9635d15SStefano Zampini PetscCall(DMPlexGetSupportSize(dm, faces[f], &nc)); 2426f9635d15SStefano Zampini PetscCall(DMPlexGetTreeParent(dm, faces[f], &ff, NULL)); 2427f9635d15SStefano Zampini if (nc == 1 && faces[f] == ff) cfaces[cnt++] = faces[f]; 2428f9635d15SStefano Zampini } 2429f9635d15SStefano Zampini if (cnt >= mcnt) { 2430f9635d15SStefano Zampini PetscInt size, *closure = NULL; 2431f9635d15SStefano Zampini 2432f9635d15SStefano Zampini PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &size, &closure)); 2433f9635d15SStefano Zampini for (PetscInt k = 0; k < 2 * size; k += 2) { 2434f9635d15SStefano Zampini PetscInt v = closure[k]; 2435f9635d15SStefano Zampini if (v >= vStart && v < vEnd) { 2436f9635d15SStefano Zampini PetscInt vsize, *vclosure = NULL; 2437f9635d15SStefano Zampini 2438f9635d15SStefano Zampini cnt = 0; 2439f9635d15SStefano Zampini PetscCall(DMPlexGetTransitiveClosure(dm, v, PETSC_FALSE, &vsize, &vclosure)); 2440f9635d15SStefano Zampini for (PetscInt vk = 0; vk < 2 * vsize; vk += 2) { 2441f9635d15SStefano Zampini PetscInt f = vclosure[vk]; 2442f9635d15SStefano Zampini if (f >= fStart && f < fEnd) { 2443f9635d15SStefano Zampini PetscInt nc, ff; 2444f9635d15SStefano Zampini PetscBool valid = PETSC_FALSE; 2445f9635d15SStefano Zampini 2446f9635d15SStefano Zampini for (PetscInt fk = 0; fk < nf; fk++) 2447f9635d15SStefano Zampini if (f == cfaces[fk]) valid = PETSC_TRUE; 2448f9635d15SStefano Zampini if (!valid) continue; 2449f9635d15SStefano Zampini PetscCall(DMPlexGetSupportSize(dm, f, &nc)); 2450f9635d15SStefano Zampini PetscCall(DMPlexGetTreeParent(dm, f, &ff, NULL)); 2451f9635d15SStefano Zampini if (nc == 1 && f == ff) cnt++; 2452f9635d15SStefano Zampini } 2453f9635d15SStefano Zampini } 2454f9635d15SStefano Zampini if (cnt >= mcnt) PetscCall(PetscBTSet(btvc, v - pStart)); 2455f9635d15SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure(dm, v, PETSC_FALSE, &vsize, &vclosure)); 2456f9635d15SStefano Zampini } 2457f9635d15SStefano Zampini } 2458f9635d15SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &size, &closure)); 2459f9635d15SStefano Zampini } 2460f9635d15SStefano Zampini PetscCall(DMRestoreWorkArray(dm, nf, MPIU_INT, &cfaces)); 2461f9635d15SStefano Zampini } 2462f9635d15SStefano Zampini } 2463c80a6c00SStefano Zampini 2464c80a6c00SStefano Zampini cids[0] = 0; 2465c80a6c00SStefano Zampini for (i = 0, cump = 0, cum = 0; i < graph->ncc; i++) { 2466c80a6c00SStefano Zampini PetscInt j; 2467c80a6c00SStefano Zampini 24689566063dSJacob Faibussowitsch PetscCall(PetscBTMemzero(A->rmap->n, btvt)); 2469c80a6c00SStefano Zampini for (j = graph->cptr[i]; j < graph->cptr[i + 1]; j++) { 2470c80a6c00SStefano Zampini PetscInt k, size, *closure = NULL, cell = graph->queue[j]; 2471c80a6c00SStefano Zampini 24729566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &size, &closure)); 2473c80a6c00SStefano Zampini for (k = 0; k < 2 * size; k += 2) { 247420c3699dSStefano Zampini PetscInt s, pp, p = closure[k], off, dof, cdof; 2475c80a6c00SStefano Zampini 24769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(subSection, p, &cdof)); 24779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(subSection, p, &off)); 24789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subSection, p, &dof)); 2479c80a6c00SStefano Zampini for (s = 0; s < dof - cdof; s++) { 2480c80a6c00SStefano Zampini if (PetscBTLookupSet(btvt, off + s)) continue; 2481f9635d15SStefano Zampini if (PetscBTLookup(btvc, p - pStart)) pids[cump++] = off + s; /* subdomain corner */ 2482f9635d15SStefano Zampini else if (!PetscBTLookup(btv, off + s)) ids[cum++] = off + s; 2483e432b41dSStefano Zampini else pids[cump++] = off + s; /* cross-vertex */ 2484c80a6c00SStefano Zampini } 24859566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL)); 248620c3699dSStefano Zampini if (pp != p) { 24879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(subSection, pp, &cdof)); 24889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(subSection, pp, &off)); 24899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subSection, pp, &dof)); 249020c3699dSStefano Zampini for (s = 0; s < dof - cdof; s++) { 249120c3699dSStefano Zampini if (PetscBTLookupSet(btvt, off + s)) continue; 2492f9635d15SStefano Zampini if (PetscBTLookup(btvc, pp - pStart)) pids[cump++] = off + s; /* subdomain corner */ 2493f9635d15SStefano Zampini else if (!PetscBTLookup(btv, off + s)) ids[cum++] = off + s; 2494e432b41dSStefano Zampini else pids[cump++] = off + s; /* cross-vertex */ 249520c3699dSStefano Zampini } 249620c3699dSStefano Zampini } 2497c80a6c00SStefano Zampini } 24989566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &size, &closure)); 2499c80a6c00SStefano Zampini } 2500c80a6c00SStefano Zampini cids[i + 1] = cum; 2501c80a6c00SStefano Zampini /* mark dofs as already assigned */ 250248a46eb9SPierre Jolivet for (j = cids[i]; j < cids[i + 1]; j++) PetscCall(PetscBTSet(btv, ids[j])); 2503c80a6c00SStefano Zampini } 2504c80a6c00SStefano Zampini if (cc) { 25059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(graph->ncc, &cc_n)); 250648a46eb9SPierre 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])); 2507c80a6c00SStefano Zampini *cc = cc_n; 2508c80a6c00SStefano Zampini } 25091baa6e33SBarry Smith if (primalv) PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), cump, pids, PETSC_COPY_VALUES, primalv)); 25109566063dSJacob Faibussowitsch PetscCall(PetscFree3(ids, cids, pids)); 25119566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btv)); 25129566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btvt)); 2513f9635d15SStefano Zampini PetscCall(PetscBTDestroy(&btvc)); 2514f9635d15SStefano Zampini PetscCall(DMDestroy(&dm)); 2515c80a6c00SStefano Zampini } 2516c80a6c00SStefano Zampini } else { 25171cf9b237SStefano Zampini if (ncc) *ncc = graph->ncc; 25181cf9b237SStefano Zampini if (cc) { 25199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(graph->ncc, &cc_n)); 252048a46eb9SPierre 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])); 25214f1b2e48SStefano Zampini *cc = cc_n; 25221cf9b237SStefano Zampini } 2523c80a6c00SStefano Zampini } 25244f1b2e48SStefano Zampini /* clean up graph */ 25250a545947SLisandro Dalcin graph->xadj = NULL; 25260a545947SLisandro Dalcin graph->adjncy = NULL; 25279566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphDestroy(&graph)); 25283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25294f1b2e48SStefano Zampini } 25304f1b2e48SStefano Zampini 2531d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag) 2532d71ae5a4SJacob Faibussowitsch { 25335408967cSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 2534f4f49eeaSPierre Jolivet PC_IS *pcis = (PC_IS *)pc->data; 2535dee84bffSStefano Zampini IS dirIS = NULL; 25364f1b2e48SStefano Zampini PetscInt i; 25375408967cSStefano Zampini 25385408967cSStefano Zampini PetscFunctionBegin; 25399566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph, &dirIS)); 25405408967cSStefano Zampini if (zerodiag) { 25415408967cSStefano Zampini Mat A; 25425408967cSStefano Zampini Vec vec3_N; 25435408967cSStefano Zampini PetscScalar *vals; 25445408967cSStefano Zampini const PetscInt *idxs; 2545d12d3064SStefano Zampini PetscInt nz, *count; 25465408967cSStefano Zampini 25475408967cSStefano Zampini /* p0 */ 25489566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_N, 0.)); 25499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n, &vals)); 25509566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zerodiag, &nz)); 25519566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zerodiag, &idxs)); 25524f1b2e48SStefano Zampini for (i = 0; i < nz; i++) vals[i] = 1.; 25539566063dSJacob Faibussowitsch PetscCall(VecSetValues(pcis->vec1_N, nz, idxs, vals, INSERT_VALUES)); 25549566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(pcis->vec1_N)); 25559566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(pcis->vec1_N)); 25565408967cSStefano Zampini /* v_I */ 25579566063dSJacob Faibussowitsch PetscCall(VecSetRandom(pcis->vec2_N, NULL)); 25585408967cSStefano Zampini for (i = 0; i < nz; i++) vals[i] = 0.; 25599566063dSJacob Faibussowitsch PetscCall(VecSetValues(pcis->vec2_N, nz, idxs, vals, INSERT_VALUES)); 25609566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zerodiag, &idxs)); 25619566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_B_local, &idxs)); 25625408967cSStefano Zampini for (i = 0; i < pcis->n_B; i++) vals[i] = 0.; 25639566063dSJacob Faibussowitsch PetscCall(VecSetValues(pcis->vec2_N, pcis->n_B, idxs, vals, INSERT_VALUES)); 25649566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_B_local, &idxs)); 25655408967cSStefano Zampini if (dirIS) { 25665408967cSStefano Zampini PetscInt n; 25675408967cSStefano Zampini 25689566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(dirIS, &n)); 25699566063dSJacob Faibussowitsch PetscCall(ISGetIndices(dirIS, &idxs)); 25705408967cSStefano Zampini for (i = 0; i < n; i++) vals[i] = 0.; 25719566063dSJacob Faibussowitsch PetscCall(VecSetValues(pcis->vec2_N, n, idxs, vals, INSERT_VALUES)); 25729566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(dirIS, &idxs)); 25735408967cSStefano Zampini } 25749566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(pcis->vec2_N)); 25759566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(pcis->vec2_N)); 25769566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_N, &vec3_N)); 25779566063dSJacob Faibussowitsch PetscCall(VecSet(vec3_N, 0.)); 25789566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->pmat, &A)); 25799566063dSJacob Faibussowitsch PetscCall(MatMult(A, pcis->vec1_N, vec3_N)); 25809566063dSJacob Faibussowitsch PetscCall(VecDot(vec3_N, pcis->vec2_N, &vals[0])); 25817827d75bSBarry 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])); 25829566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 25839566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vec3_N)); 2584d12d3064SStefano Zampini 2585d12d3064SStefano Zampini /* there should not be any pressure dofs lying on the interface */ 25869566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pcis->n, &count)); 25879566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_B_local, &idxs)); 2588d12d3064SStefano Zampini for (i = 0; i < pcis->n_B; i++) count[idxs[i]]++; 25899566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_B_local, &idxs)); 25909566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zerodiag, &idxs)); 259163a3b9bcSJacob 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]); 25929566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zerodiag, &idxs)); 25939566063dSJacob Faibussowitsch PetscCall(PetscFree(count)); 25945408967cSStefano Zampini } 25959566063dSJacob Faibussowitsch PetscCall(ISDestroy(&dirIS)); 25965408967cSStefano Zampini 25975408967cSStefano Zampini /* check PCBDDCBenignGetOrSetP0 */ 25989566063dSJacob Faibussowitsch PetscCall(VecSetRandom(pcis->vec1_global, NULL)); 25994f1b2e48SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) pcbddc->benign_p0[i] = -PetscGlobalRank - i; 26009566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc, pcis->vec1_global, PETSC_FALSE)); 26014f1b2e48SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) pcbddc->benign_p0[i] = 1; 26029566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc, pcis->vec1_global, PETSC_TRUE)); 2603f2a566d8SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) { 2604f2a566d8SStefano Zampini PetscInt val = PetscRealPart(pcbddc->benign_p0[i]); 260563a3b9bcSJacob 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)); 2606f2a566d8SStefano Zampini } 26073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 26085408967cSStefano Zampini } 26095408967cSStefano Zampini 2610d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, PetscBool reuse, IS *zerodiaglocal) 2611d71ae5a4SJacob Faibussowitsch { 2612339f8db1SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 2613f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)pc->pmat->data; 26143b03f7bbSStefano Zampini IS pressures = NULL, zerodiag = NULL, *bzerodiag = NULL, zerodiag_save, *zerodiag_subs; 26153b03f7bbSStefano Zampini PetscInt nz, n, benign_n, bsp = 1; 26164edc6404Sstefano_zampini PetscInt *interior_dofs, n_interior_dofs, nneu; 26174edc6404Sstefano_zampini PetscBool sorted, have_null, has_null_pressures, recompute_zerodiag, checkb; 2618339f8db1SStefano Zampini 2619339f8db1SStefano Zampini PetscFunctionBegin; 26203b03f7bbSStefano Zampini if (reuse) goto project_b0; 26219566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pcbddc->benign_sf)); 26229566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->benign_B0)); 262348a46eb9SPierre Jolivet for (n = 0; n < pcbddc->benign_n; n++) PetscCall(ISDestroy(&pcbddc->benign_zerodiag_subs[n])); 26249566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->benign_zerodiag_subs)); 26253b03f7bbSStefano Zampini has_null_pressures = PETSC_TRUE; 26263b03f7bbSStefano Zampini have_null = PETSC_TRUE; 26273b03f7bbSStefano Zampini /* if a local information on dofs is present, gets pressure dofs from command line (uses the last field is not provided) 26283b03f7bbSStefano Zampini Without local information, it uses only the zerodiagonal dofs (ok if the pressure block is all zero and it is a scalar field) 26294f1b2e48SStefano Zampini Checks if all the pressure dofs in each subdomain have a zero diagonal 26304f1b2e48SStefano Zampini If not, a change of basis on pressures is not needed 26311ae86dd6SStefano Zampini since the local Schur complements are already SPD 26324f1b2e48SStefano Zampini */ 263340fa8d13SStefano Zampini if (pcbddc->n_ISForDofsLocal) { 26347fbe2174Sstefano_zampini IS iP = NULL; 26353b03f7bbSStefano Zampini PetscInt p, *pp; 26363b03f7bbSStefano Zampini PetscBool flg; 26374f1b2e48SStefano Zampini 26389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->n_ISForDofsLocal, &pp)); 26393b03f7bbSStefano Zampini n = pcbddc->n_ISForDofsLocal; 2640d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)pc), ((PetscObject)pc)->prefix, "BDDC benign options", "PC"); 26419566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-pc_bddc_pressure_field", "Field id for pressures", NULL, pp, &n, &flg)); 2642d0609cedSBarry Smith PetscOptionsEnd(); 26433b03f7bbSStefano Zampini if (!flg) { 26443b03f7bbSStefano Zampini n = 1; 26453b03f7bbSStefano Zampini pp[0] = pcbddc->n_ISForDofsLocal - 1; 26463b03f7bbSStefano Zampini } 26473b03f7bbSStefano Zampini 26483b03f7bbSStefano Zampini bsp = 0; 26493b03f7bbSStefano Zampini for (p = 0; p < n; p++) { 26503b03f7bbSStefano Zampini PetscInt bs; 26513b03f7bbSStefano Zampini 265263a3b9bcSJacob 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]); 26539566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(pcbddc->ISForDofsLocal[pp[p]], &bs)); 26543b03f7bbSStefano Zampini bsp += bs; 26553b03f7bbSStefano Zampini } 26569566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bsp, &bzerodiag)); 26573b03f7bbSStefano Zampini bsp = 0; 26583b03f7bbSStefano Zampini for (p = 0; p < n; p++) { 26593b03f7bbSStefano Zampini const PetscInt *idxs; 26603b03f7bbSStefano Zampini PetscInt b, bs, npl, *bidxs; 26613b03f7bbSStefano Zampini 26629566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(pcbddc->ISForDofsLocal[pp[p]], &bs)); 26639566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->ISForDofsLocal[pp[p]], &npl)); 26649566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->ISForDofsLocal[pp[p]], &idxs)); 26659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(npl / bs, &bidxs)); 26663b03f7bbSStefano Zampini for (b = 0; b < bs; b++) { 26673b03f7bbSStefano Zampini PetscInt i; 26683b03f7bbSStefano Zampini 26693b03f7bbSStefano Zampini for (i = 0; i < npl / bs; i++) bidxs[i] = idxs[bs * i + b]; 26709566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, npl / bs, bidxs, PETSC_COPY_VALUES, &bzerodiag[bsp])); 26713b03f7bbSStefano Zampini bsp++; 26723b03f7bbSStefano Zampini } 26739566063dSJacob Faibussowitsch PetscCall(PetscFree(bidxs)); 26749566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->ISForDofsLocal[pp[p]], &idxs)); 26753b03f7bbSStefano Zampini } 26769566063dSJacob Faibussowitsch PetscCall(ISConcatenate(PETSC_COMM_SELF, bsp, bzerodiag, &pressures)); 26773b03f7bbSStefano Zampini 26787fbe2174Sstefano_zampini /* remove zeroed out pressures if we are setting up a BDDC solver for a saddle-point FETI-DP */ 26799566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lP", (PetscObject *)&iP)); 26807fbe2174Sstefano_zampini if (iP) { 26817fbe2174Sstefano_zampini IS newpressures; 26827fbe2174Sstefano_zampini 26839566063dSJacob Faibussowitsch PetscCall(ISDifference(pressures, iP, &newpressures)); 26849566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pressures)); 26857fbe2174Sstefano_zampini pressures = newpressures; 26867fbe2174Sstefano_zampini } 26879566063dSJacob Faibussowitsch PetscCall(ISSorted(pressures, &sorted)); 268848a46eb9SPierre Jolivet if (!sorted) PetscCall(ISSort(pressures)); 26899566063dSJacob Faibussowitsch PetscCall(PetscFree(pp)); 269040fa8d13SStefano Zampini } 26913b03f7bbSStefano Zampini 269297d764eeSStefano Zampini /* pcis has not been setup yet, so get the local size from the subdomain matrix */ 26939566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pcbddc->local_mat, &n, NULL)); 269427b6a85dSStefano Zampini if (!n) pcbddc->benign_change_explicit = PETSC_TRUE; 26959566063dSJacob Faibussowitsch PetscCall(MatFindZeroDiagonals(pcbddc->local_mat, &zerodiag)); 26969566063dSJacob Faibussowitsch PetscCall(ISSorted(zerodiag, &sorted)); 269748a46eb9SPierre Jolivet if (!sorted) PetscCall(ISSort(zerodiag)); 26989566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)zerodiag)); 26994edc6404Sstefano_zampini zerodiag_save = zerodiag; 27009566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zerodiag, &nz)); 27014f1b2e48SStefano Zampini if (!nz) { 27024f1b2e48SStefano Zampini if (n) have_null = PETSC_FALSE; 27034f1b2e48SStefano Zampini has_null_pressures = PETSC_FALSE; 27049566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zerodiag)); 270540fa8d13SStefano Zampini } 27064f1b2e48SStefano Zampini recompute_zerodiag = PETSC_FALSE; 27073b03f7bbSStefano Zampini 27084f1b2e48SStefano Zampini /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */ 27094f1b2e48SStefano Zampini zerodiag_subs = NULL; 27103b03f7bbSStefano Zampini benign_n = 0; 27111f4df5f7SStefano Zampini n_interior_dofs = 0; 27121f4df5f7SStefano Zampini interior_dofs = NULL; 27134edc6404Sstefano_zampini nneu = 0; 271448a46eb9SPierre Jolivet if (pcbddc->NeumannBoundariesLocal) PetscCall(ISGetLocalSize(pcbddc->NeumannBoundariesLocal, &nneu)); 27153369cb78Sstefano_zampini checkb = (PetscBool)(!pcbddc->NeumannBoundariesLocal || pcbddc->current_level); 27164edc6404Sstefano_zampini if (checkb) { /* need to compute interior nodes */ 27179de2952eSStefano Zampini PetscInt n, i; 27189de2952eSStefano Zampini PetscInt *count; 27199de2952eSStefano Zampini ISLocalToGlobalMapping mapping; 27201f4df5f7SStefano Zampini 27219de2952eSStefano Zampini PetscCall(MatISGetLocalToGlobalMapping(pc->pmat, &mapping, NULL)); 27229de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingGetNodeInfo(mapping, &n, &count, NULL)); 27239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &interior_dofs)); 27241f4df5f7SStefano Zampini for (i = 0; i < n; i++) 27259de2952eSStefano Zampini if (count[i] < 2) interior_dofs[n_interior_dofs++] = i; 27269de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(mapping, &n, &count, NULL)); 27271f4df5f7SStefano Zampini } 27284f1b2e48SStefano Zampini if (has_null_pressures) { 27294f1b2e48SStefano Zampini IS *subs; 27304edc6404Sstefano_zampini PetscInt nsubs, i, j, nl; 27311f4df5f7SStefano Zampini const PetscInt *idxs; 27321f4df5f7SStefano Zampini PetscScalar *array; 27331f4df5f7SStefano Zampini Vec *work; 27344f1b2e48SStefano Zampini 27354f1b2e48SStefano Zampini subs = pcbddc->local_subs; 27364f1b2e48SStefano Zampini nsubs = pcbddc->n_local_subs; 27371f4df5f7SStefano 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) */ 27384edc6404Sstefano_zampini if (checkb) { 27399566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(matis->y, 2, &work)); 27409566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zerodiag, &nl)); 27419566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zerodiag, &idxs)); 27421f4df5f7SStefano Zampini /* work[0] = 1_p */ 27439566063dSJacob Faibussowitsch PetscCall(VecSet(work[0], 0.)); 27449566063dSJacob Faibussowitsch PetscCall(VecGetArray(work[0], &array)); 27451f4df5f7SStefano Zampini for (j = 0; j < nl; j++) array[idxs[j]] = 1.; 27469566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(work[0], &array)); 27471f4df5f7SStefano Zampini /* work[0] = 1_v */ 27489566063dSJacob Faibussowitsch PetscCall(VecSet(work[1], 1.)); 27499566063dSJacob Faibussowitsch PetscCall(VecGetArray(work[1], &array)); 27501f4df5f7SStefano Zampini for (j = 0; j < nl; j++) array[idxs[j]] = 0.; 27519566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(work[1], &array)); 27529566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zerodiag, &idxs)); 27531f4df5f7SStefano Zampini } 27543b03f7bbSStefano Zampini 27553b03f7bbSStefano Zampini if (nsubs > 1 || bsp > 1) { 27563b03f7bbSStefano Zampini IS *is; 27573b03f7bbSStefano Zampini PetscInt b, totb; 27583b03f7bbSStefano Zampini 27593b03f7bbSStefano Zampini totb = bsp; 27603b03f7bbSStefano Zampini is = bsp > 1 ? bzerodiag : &zerodiag; 27613b03f7bbSStefano Zampini nsubs = PetscMax(nsubs, 1); 27629566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nsubs * totb, &zerodiag_subs)); 27633b03f7bbSStefano Zampini for (b = 0; b < totb; b++) { 27644f1b2e48SStefano Zampini for (i = 0; i < nsubs; i++) { 27654f1b2e48SStefano Zampini ISLocalToGlobalMapping l2g; 27664f1b2e48SStefano Zampini IS t_zerodiag_subs; 27674f1b2e48SStefano Zampini PetscInt nl; 27684f1b2e48SStefano Zampini 27693b03f7bbSStefano Zampini if (subs) { 27709566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(subs[i], &l2g)); 27713b03f7bbSStefano Zampini } else { 27723b03f7bbSStefano Zampini IS tis; 27733b03f7bbSStefano Zampini 27749566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pcbddc->local_mat, &nl, NULL)); 27759566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, nl, 0, 1, &tis)); 27769566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(tis, &l2g)); 27779566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tis)); 27783b03f7bbSStefano Zampini } 27799566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(l2g, IS_GTOLM_DROP, is[b], &t_zerodiag_subs)); 27809566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(t_zerodiag_subs, &nl)); 27814f1b2e48SStefano Zampini if (nl) { 27824f1b2e48SStefano Zampini PetscBool valid = PETSC_TRUE; 27834f1b2e48SStefano Zampini 27844edc6404Sstefano_zampini if (checkb) { 27859566063dSJacob Faibussowitsch PetscCall(VecSet(matis->x, 0)); 27869566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(subs[i], &nl)); 27879566063dSJacob Faibussowitsch PetscCall(ISGetIndices(subs[i], &idxs)); 27889566063dSJacob Faibussowitsch PetscCall(VecGetArray(matis->x, &array)); 27891f4df5f7SStefano Zampini for (j = 0; j < nl; j++) array[idxs[j]] = 1.; 27909566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(matis->x, &array)); 27919566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(subs[i], &idxs)); 27929566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(matis->x, work[0], matis->x)); 27939566063dSJacob Faibussowitsch PetscCall(MatMult(matis->A, matis->x, matis->y)); 27949566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(matis->y, work[1], matis->y)); 27959566063dSJacob Faibussowitsch PetscCall(VecGetArray(matis->y, &array)); 27961f4df5f7SStefano Zampini for (j = 0; j < n_interior_dofs; j++) { 27971f4df5f7SStefano Zampini if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) { 27981f4df5f7SStefano Zampini valid = PETSC_FALSE; 27991f4df5f7SStefano Zampini break; 28001f4df5f7SStefano Zampini } 28011f4df5f7SStefano Zampini } 28029566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(matis->y, &array)); 28031f4df5f7SStefano Zampini } 28046632bad2Sstefano_zampini if (valid && nneu) { 28056632bad2Sstefano_zampini const PetscInt *idxs; 28061f4df5f7SStefano Zampini PetscInt nzb; 28071f4df5f7SStefano Zampini 28089566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->NeumannBoundariesLocal, &idxs)); 28099566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(l2g, IS_GTOLM_DROP, nneu, idxs, &nzb, NULL)); 28109566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->NeumannBoundariesLocal, &idxs)); 28111f4df5f7SStefano Zampini if (nzb) valid = PETSC_FALSE; 28121f4df5f7SStefano Zampini } 28131f4df5f7SStefano Zampini if (valid && pressures) { 28143b03f7bbSStefano Zampini IS t_pressure_subs, tmp; 28153b03f7bbSStefano Zampini PetscInt i1, i2; 28163b03f7bbSStefano Zampini 28179566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(l2g, IS_GTOLM_DROP, pressures, &t_pressure_subs)); 28189566063dSJacob Faibussowitsch PetscCall(ISEmbed(t_zerodiag_subs, t_pressure_subs, PETSC_TRUE, &tmp)); 28199566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(tmp, &i1)); 28209566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(t_zerodiag_subs, &i2)); 28213b03f7bbSStefano Zampini if (i2 != i1) valid = PETSC_FALSE; 28229566063dSJacob Faibussowitsch PetscCall(ISDestroy(&t_pressure_subs)); 28239566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tmp)); 28244f1b2e48SStefano Zampini } 28254f1b2e48SStefano Zampini if (valid) { 28269566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(l2g, t_zerodiag_subs, &zerodiag_subs[benign_n])); 28273b03f7bbSStefano Zampini benign_n++; 28283b03f7bbSStefano Zampini } else recompute_zerodiag = PETSC_TRUE; 28294f1b2e48SStefano Zampini } 28309566063dSJacob Faibussowitsch PetscCall(ISDestroy(&t_zerodiag_subs)); 28319566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&l2g)); 28324f1b2e48SStefano Zampini } 28333b03f7bbSStefano Zampini } 28344f1b2e48SStefano Zampini } else { /* there's just one subdomain (or zero if they have not been detected */ 28354f1b2e48SStefano Zampini PetscBool valid = PETSC_TRUE; 28361f4df5f7SStefano Zampini 28376632bad2Sstefano_zampini if (nneu) valid = PETSC_FALSE; 283848a46eb9SPierre Jolivet if (valid && pressures) PetscCall(ISEqual(pressures, zerodiag, &valid)); 28394edc6404Sstefano_zampini if (valid && checkb) { 28409566063dSJacob Faibussowitsch PetscCall(MatMult(matis->A, work[0], matis->x)); 28419566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(matis->x, work[1], matis->x)); 28429566063dSJacob Faibussowitsch PetscCall(VecGetArray(matis->x, &array)); 28431f4df5f7SStefano Zampini for (j = 0; j < n_interior_dofs; j++) { 28441f4df5f7SStefano Zampini if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) { 28451f4df5f7SStefano Zampini valid = PETSC_FALSE; 28461f4df5f7SStefano Zampini break; 28471f4df5f7SStefano Zampini } 28481f4df5f7SStefano Zampini } 28499566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(matis->x, &array)); 28501f4df5f7SStefano Zampini } 28514f1b2e48SStefano Zampini if (valid) { 28523b03f7bbSStefano Zampini benign_n = 1; 28539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(benign_n, &zerodiag_subs)); 28549566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)zerodiag)); 28554f1b2e48SStefano Zampini zerodiag_subs[0] = zerodiag; 28564f1b2e48SStefano Zampini } 28574f1b2e48SStefano Zampini } 285848a46eb9SPierre Jolivet if (checkb) PetscCall(VecDestroyVecs(2, &work)); 28591f4df5f7SStefano Zampini } 28609566063dSJacob Faibussowitsch PetscCall(PetscFree(interior_dofs)); 28614f1b2e48SStefano Zampini 28623b03f7bbSStefano Zampini if (!benign_n) { 2863b9b0e38cSStefano Zampini PetscInt n; 2864b9b0e38cSStefano Zampini 28659566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zerodiag)); 28664f1b2e48SStefano Zampini recompute_zerodiag = PETSC_FALSE; 28679566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pcbddc->local_mat, &n, NULL)); 286876a58201SStefano Zampini if (n) have_null = PETSC_FALSE; 2869b9b0e38cSStefano Zampini } 28704f1b2e48SStefano Zampini 28714f1b2e48SStefano Zampini /* final check for null pressures */ 287248a46eb9SPierre Jolivet if (zerodiag && pressures) PetscCall(ISEqual(pressures, zerodiag, &have_null)); 28734f1b2e48SStefano Zampini 28744f1b2e48SStefano Zampini if (recompute_zerodiag) { 28759566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zerodiag)); 28763b03f7bbSStefano Zampini if (benign_n == 1) { 28779566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)zerodiag_subs[0])); 28784f1b2e48SStefano Zampini zerodiag = zerodiag_subs[0]; 28794f1b2e48SStefano Zampini } else { 28804f1b2e48SStefano Zampini PetscInt i, nzn, *new_idxs; 28814f1b2e48SStefano Zampini 28824f1b2e48SStefano Zampini nzn = 0; 28833b03f7bbSStefano Zampini for (i = 0; i < benign_n; i++) { 28844f1b2e48SStefano Zampini PetscInt ns; 28859566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zerodiag_subs[i], &ns)); 28864f1b2e48SStefano Zampini nzn += ns; 28874f1b2e48SStefano Zampini } 28889566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nzn, &new_idxs)); 28894f1b2e48SStefano Zampini nzn = 0; 28903b03f7bbSStefano Zampini for (i = 0; i < benign_n; i++) { 28914f1b2e48SStefano Zampini PetscInt ns, *idxs; 28929566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zerodiag_subs[i], &ns)); 28939566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zerodiag_subs[i], (const PetscInt **)&idxs)); 28949566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(new_idxs + nzn, idxs, ns)); 28959566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zerodiag_subs[i], (const PetscInt **)&idxs)); 28964f1b2e48SStefano Zampini nzn += ns; 28974f1b2e48SStefano Zampini } 28989566063dSJacob Faibussowitsch PetscCall(PetscSortInt(nzn, new_idxs)); 28999566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nzn, new_idxs, PETSC_OWN_POINTER, &zerodiag)); 29004f1b2e48SStefano Zampini } 29014f1b2e48SStefano Zampini have_null = PETSC_FALSE; 29024f1b2e48SStefano Zampini } 29034f1b2e48SStefano Zampini 29043b03f7bbSStefano Zampini /* determines if the coarse solver will be singular or not */ 29051c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&have_null, &pcbddc->benign_null, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)pc))); 29063b03f7bbSStefano Zampini 2907669cc0f4SStefano Zampini /* Prepare matrix to compute no-net-flux */ 2908a198735bSStefano Zampini if (pcbddc->compute_nonetflux && !pcbddc->divudotp) { 2909a198735bSStefano Zampini Mat A, loc_divudotp; 2910a198735bSStefano Zampini ISLocalToGlobalMapping rl2g, cl2g, l2gmap; 2911a198735bSStefano Zampini IS row, col, isused = NULL; 2912a198735bSStefano Zampini PetscInt M, N, n, st, n_isused; 2913a198735bSStefano Zampini 29141f4df5f7SStefano Zampini if (pressures) { 29151f4df5f7SStefano Zampini isused = pressures; 29161f4df5f7SStefano Zampini } else { 29174edc6404Sstefano_zampini isused = zerodiag_save; 29181f4df5f7SStefano Zampini } 29199566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(pc->pmat, &l2gmap, NULL)); 29209566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->pmat, &A)); 29219566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &n, NULL)); 29227827d75bSBarry 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"); 2923a198735bSStefano Zampini n_isused = 0; 292448a46eb9SPierre Jolivet if (isused) PetscCall(ISGetLocalSize(isused, &n_isused)); 29259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Scan(&n_isused, &st, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)pc))); 2926a198735bSStefano Zampini st = st - n_isused; 29271ae86dd6SStefano Zampini if (n) { 2928a198735bSStefano Zampini const PetscInt *gidxs; 2929a198735bSStefano Zampini 29309566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, isused, NULL, MAT_INITIAL_MATRIX, &loc_divudotp)); 29319566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(l2gmap, &gidxs)); 2932a198735bSStefano Zampini /* TODO: extend ISCreateStride with st = PETSC_DECIDE */ 29339566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)pc), n_isused, st, 1, &row)); 29349566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), n, gidxs, PETSC_COPY_VALUES, &col)); 29359566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(l2gmap, &gidxs)); 29361ae86dd6SStefano Zampini } else { 29379566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, 0, 0, 1, NULL, &loc_divudotp)); 29389566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)pc), n_isused, st, 1, &row)); 29399566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), 0, NULL, PETSC_COPY_VALUES, &col)); 2940a198735bSStefano Zampini } 29419566063dSJacob Faibussowitsch PetscCall(MatGetSize(pc->pmat, NULL, &N)); 29429566063dSJacob Faibussowitsch PetscCall(ISGetSize(row, &M)); 29439566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(row, &rl2g)); 29449566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(col, &cl2g)); 29459566063dSJacob Faibussowitsch PetscCall(ISDestroy(&row)); 29469566063dSJacob Faibussowitsch PetscCall(ISDestroy(&col)); 29479566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)pc), &pcbddc->divudotp)); 29489566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->divudotp, MATIS)); 29499566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->divudotp, PETSC_DECIDE, PETSC_DECIDE, M, N)); 29509566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(pcbddc->divudotp, rl2g, cl2g)); 29519566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 29529566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 29539566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(pcbddc->divudotp, loc_divudotp)); 29549566063dSJacob Faibussowitsch PetscCall(MatDestroy(&loc_divudotp)); 29559566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pcbddc->divudotp, MAT_FINAL_ASSEMBLY)); 29569566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->divudotp, MAT_FINAL_ASSEMBLY)); 29571ae86dd6SStefano Zampini } 29589566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zerodiag_save)); 29599566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pressures)); 29603b03f7bbSStefano Zampini if (bzerodiag) { 29613b03f7bbSStefano Zampini PetscInt i; 2962b3afcdbeSStefano Zampini 296348a46eb9SPierre Jolivet for (i = 0; i < bsp; i++) PetscCall(ISDestroy(&bzerodiag[i])); 29649566063dSJacob Faibussowitsch PetscCall(PetscFree(bzerodiag)); 29653b03f7bbSStefano Zampini } 29663b03f7bbSStefano Zampini pcbddc->benign_n = benign_n; 29673b03f7bbSStefano Zampini pcbddc->benign_zerodiag_subs = zerodiag_subs; 29683b03f7bbSStefano Zampini 29693b03f7bbSStefano Zampini /* determines if the problem has subdomains with 0 pressure block */ 29703b03f7bbSStefano Zampini have_null = (PetscBool)(!!pcbddc->benign_n); 29711c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&have_null, &pcbddc->benign_have_null, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 29723b03f7bbSStefano Zampini 29733b03f7bbSStefano Zampini project_b0: 29749566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pcbddc->local_mat, &n, NULL)); 2975b3afcdbeSStefano Zampini /* change of basis and p0 dofs */ 29763b03f7bbSStefano Zampini if (pcbddc->benign_n) { 29774f1b2e48SStefano Zampini PetscInt i, s, *nnz; 29784f1b2e48SStefano Zampini 2979339f8db1SStefano Zampini /* local change of basis for pressures */ 29809566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->benign_change)); 29819566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat), &pcbddc->benign_change)); 29829566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->benign_change, MATAIJ)); 29839566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->benign_change, n, n, PETSC_DECIDE, PETSC_DECIDE)); 29849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &nnz)); 2985aa0d93e9SStefano Zampini for (i = 0; i < n; i++) nnz[i] = 1; /* defaults to identity */ 29864f1b2e48SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) { 2987aa0d93e9SStefano Zampini const PetscInt *idxs; 29884f1b2e48SStefano Zampini PetscInt nzs, j; 29894f1b2e48SStefano Zampini 29909566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[i], &nzs)); 29919566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->benign_zerodiag_subs[i], &idxs)); 29924f1b2e48SStefano Zampini for (j = 0; j < nzs - 1; j++) nnz[idxs[j]] = 2; /* change on pressures */ 29934f1b2e48SStefano Zampini nnz[idxs[nzs - 1]] = nzs; /* last local pressure dof in subdomain */ 29949566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->benign_zerodiag_subs[i], &idxs)); 29954f1b2e48SStefano Zampini } 29969566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(pcbddc->benign_change, 0, nnz)); 29979566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->benign_change, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 29989566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 2999aa0d93e9SStefano Zampini /* set identity by default */ 300048a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall(MatSetValue(pcbddc->benign_change, i, i, 1., INSERT_VALUES)); 30019566063dSJacob Faibussowitsch PetscCall(PetscFree3(pcbddc->benign_p0_lidx, pcbddc->benign_p0_gidx, pcbddc->benign_p0)); 30029566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(pcbddc->benign_n, &pcbddc->benign_p0_lidx, pcbddc->benign_n, &pcbddc->benign_p0_gidx, pcbddc->benign_n, &pcbddc->benign_p0)); 3003339f8db1SStefano Zampini /* set change on pressures */ 30044f1b2e48SStefano Zampini for (s = 0; s < pcbddc->benign_n; s++) { 30054f1b2e48SStefano Zampini PetscScalar *array; 3006aa0d93e9SStefano Zampini const PetscInt *idxs; 30074f1b2e48SStefano Zampini PetscInt nzs; 30084f1b2e48SStefano Zampini 30099566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[s], &nzs)); 30109566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->benign_zerodiag_subs[s], &idxs)); 30114f1b2e48SStefano Zampini for (i = 0; i < nzs - 1; i++) { 3012339f8db1SStefano Zampini PetscScalar vals[2]; 3013339f8db1SStefano Zampini PetscInt cols[2]; 3014339f8db1SStefano Zampini 3015339f8db1SStefano Zampini cols[0] = idxs[i]; 30164f1b2e48SStefano Zampini cols[1] = idxs[nzs - 1]; 3017339f8db1SStefano Zampini vals[0] = 1.; 3018b0f5fe93SStefano Zampini vals[1] = 1.; 30199566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->benign_change, 1, cols, 2, cols, vals, INSERT_VALUES)); 3020339f8db1SStefano Zampini } 30219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nzs, &array)); 30224f1b2e48SStefano Zampini for (i = 0; i < nzs - 1; i++) array[i] = -1.; 30234f1b2e48SStefano Zampini array[nzs - 1] = 1.; 30249566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->benign_change, 1, idxs + nzs - 1, nzs, idxs, array, INSERT_VALUES)); 30254f1b2e48SStefano Zampini /* store local idxs for p0 */ 30264f1b2e48SStefano Zampini pcbddc->benign_p0_lidx[s] = idxs[nzs - 1]; 30279566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->benign_zerodiag_subs[s], &idxs)); 30289566063dSJacob Faibussowitsch PetscCall(PetscFree(array)); 30294f1b2e48SStefano Zampini } 30309566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pcbddc->benign_change, MAT_FINAL_ASSEMBLY)); 30319566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->benign_change, MAT_FINAL_ASSEMBLY)); 30323b03f7bbSStefano Zampini 3033a3df083aSStefano Zampini /* project if needed */ 3034a3df083aSStefano Zampini if (pcbddc->benign_change_explicit) { 30351dd7afcfSStefano Zampini Mat M; 30361dd7afcfSStefano Zampini 30379566063dSJacob Faibussowitsch PetscCall(MatPtAP(pcbddc->local_mat, pcbddc->benign_change, MAT_INITIAL_MATRIX, 2.0, &M)); 30389566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 30399566063dSJacob Faibussowitsch PetscCall(MatSeqAIJCompress(M, &pcbddc->local_mat)); 30409566063dSJacob Faibussowitsch PetscCall(MatDestroy(&M)); 3041a3df083aSStefano Zampini } 30424f1b2e48SStefano Zampini /* store global idxs for p0 */ 30439566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(matis->rmapping, pcbddc->benign_n, pcbddc->benign_p0_lidx, pcbddc->benign_p0_gidx)); 3044339f8db1SStefano Zampini } 3045339f8db1SStefano Zampini *zerodiaglocal = zerodiag; 30463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3047339f8db1SStefano Zampini } 3048339f8db1SStefano Zampini 3049d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get) 3050d71ae5a4SJacob Faibussowitsch { 3051efc2fbd9SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 3052de9d7bd0SStefano Zampini PetscScalar *array; 3053efc2fbd9SStefano Zampini 3054efc2fbd9SStefano Zampini PetscFunctionBegin; 3055efc2fbd9SStefano Zampini if (!pcbddc->benign_sf) { 30569566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)pc), &pcbddc->benign_sf)); 30579566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(pcbddc->benign_sf, pc->pmat->rmap, pcbddc->benign_n, NULL, PETSC_OWN_POINTER, pcbddc->benign_p0_gidx)); 3058efc2fbd9SStefano Zampini } 3059de9d7bd0SStefano Zampini if (get) { 30609566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, (const PetscScalar **)&array)); 30619566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pcbddc->benign_sf, MPIU_SCALAR, array, pcbddc->benign_p0, MPI_REPLACE)); 30629566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pcbddc->benign_sf, MPIU_SCALAR, array, pcbddc->benign_p0, MPI_REPLACE)); 30639566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, (const PetscScalar **)&array)); 3064de9d7bd0SStefano Zampini } else { 30659566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 30669566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(pcbddc->benign_sf, MPIU_SCALAR, pcbddc->benign_p0, array, MPI_REPLACE)); 30679566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(pcbddc->benign_sf, MPIU_SCALAR, pcbddc->benign_p0, array, MPI_REPLACE)); 30689566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 3069efc2fbd9SStefano Zampini } 30703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3071efc2fbd9SStefano Zampini } 3072efc2fbd9SStefano Zampini 3073d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop) 3074d71ae5a4SJacob Faibussowitsch { 3075c263805aSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 3076c263805aSStefano Zampini 3077c263805aSStefano Zampini PetscFunctionBegin; 3078c263805aSStefano Zampini /* TODO: add error checking 3079c263805aSStefano Zampini - avoid nested pop (or push) calls. 3080c263805aSStefano Zampini - cannot push before pop. 30811c604dc7SStefano Zampini - cannot call this if pcbddc->local_mat is NULL 3082c263805aSStefano Zampini */ 30833ba16761SJacob Faibussowitsch if (!pcbddc->benign_n) PetscFunctionReturn(PETSC_SUCCESS); 3084c263805aSStefano Zampini if (pop) { 3085a3df083aSStefano Zampini if (pcbddc->benign_change_explicit) { 30864f1b2e48SStefano Zampini IS is_p0; 30874f1b2e48SStefano Zampini MatReuse reuse; 3088c263805aSStefano Zampini 3089c263805aSStefano Zampini /* extract B_0 */ 30904f1b2e48SStefano Zampini reuse = MAT_INITIAL_MATRIX; 3091ad540459SPierre Jolivet if (pcbddc->benign_B0) reuse = MAT_REUSE_MATRIX; 30929566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, pcbddc->benign_n, pcbddc->benign_p0_lidx, PETSC_COPY_VALUES, &is_p0)); 30939566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, is_p0, NULL, reuse, &pcbddc->benign_B0)); 3094c263805aSStefano Zampini /* remove rows and cols from local problem */ 30959566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->local_mat, MAT_KEEP_NONZERO_PATTERN, PETSC_TRUE)); 30969566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->local_mat, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_FALSE)); 30979566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumnsIS(pcbddc->local_mat, is_p0, 1.0, NULL, NULL)); 30989566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_p0)); 3099a3df083aSStefano Zampini } else { 3100a3df083aSStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 3101a3df083aSStefano Zampini PetscScalar *vals; 3102a3df083aSStefano Zampini PetscInt i, n, *idxs_ins; 3103a3df083aSStefano Zampini 31049566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(matis->y, &n)); 31059566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n, &idxs_ins, n, &vals)); 3106a3df083aSStefano Zampini if (!pcbddc->benign_B0) { 31070b5adadeSStefano Zampini PetscInt *nnz; 31089566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat), &pcbddc->benign_B0)); 31099566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->benign_B0, MATAIJ)); 31109566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->benign_B0, pcbddc->benign_n, n, PETSC_DECIDE, PETSC_DECIDE)); 31119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->benign_n, &nnz)); 3112331e053bSStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) { 31139566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[i], &nnz[i])); 3114331e053bSStefano Zampini nnz[i] = n - nnz[i]; 3115331e053bSStefano Zampini } 31169566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(pcbddc->benign_B0, 0, nnz)); 31179566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->benign_B0, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 31189566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 3119331e053bSStefano Zampini } 3120a3df083aSStefano Zampini 3121a3df083aSStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) { 3122a3df083aSStefano Zampini PetscScalar *array; 3123a3df083aSStefano Zampini PetscInt *idxs, j, nz, cum; 3124a3df083aSStefano Zampini 31259566063dSJacob Faibussowitsch PetscCall(VecSet(matis->x, 0.)); 31269566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[i], &nz)); 31279566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->benign_zerodiag_subs[i], (const PetscInt **)&idxs)); 3128a3df083aSStefano Zampini for (j = 0; j < nz; j++) vals[j] = 1.; 31299566063dSJacob Faibussowitsch PetscCall(VecSetValues(matis->x, nz, idxs, vals, INSERT_VALUES)); 31309566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(matis->x)); 31319566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(matis->x)); 31329566063dSJacob Faibussowitsch PetscCall(VecSet(matis->y, 0.)); 31339566063dSJacob Faibussowitsch PetscCall(MatMult(matis->A, matis->x, matis->y)); 31349566063dSJacob Faibussowitsch PetscCall(VecGetArray(matis->y, &array)); 3135a3df083aSStefano Zampini cum = 0; 3136a3df083aSStefano Zampini for (j = 0; j < n; j++) { 313722db5ddcSStefano Zampini if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) { 3138a3df083aSStefano Zampini vals[cum] = array[j]; 3139a3df083aSStefano Zampini idxs_ins[cum] = j; 3140a3df083aSStefano Zampini cum++; 3141a3df083aSStefano Zampini } 3142a3df083aSStefano Zampini } 31439566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->benign_B0, 1, &i, cum, idxs_ins, vals, INSERT_VALUES)); 31449566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(matis->y, &array)); 31459566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->benign_zerodiag_subs[i], (const PetscInt **)&idxs)); 3146a3df083aSStefano Zampini } 31479566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pcbddc->benign_B0, MAT_FINAL_ASSEMBLY)); 31489566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->benign_B0, MAT_FINAL_ASSEMBLY)); 31499566063dSJacob Faibussowitsch PetscCall(PetscFree2(idxs_ins, vals)); 3150a3df083aSStefano Zampini } 3151c263805aSStefano Zampini } else { /* push */ 31524f1b2e48SStefano Zampini 31530fdf79fbSJacob Faibussowitsch PetscCheck(pcbddc->benign_change_explicit, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Cannot push B0!"); 31540fdf79fbSJacob Faibussowitsch for (PetscInt i = 0; i < pcbddc->benign_n; i++) { 31554f1b2e48SStefano Zampini PetscScalar *B0_vals; 31564f1b2e48SStefano Zampini PetscInt *B0_cols, B0_ncol; 31574f1b2e48SStefano Zampini 31589566063dSJacob Faibussowitsch PetscCall(MatGetRow(pcbddc->benign_B0, i, &B0_ncol, (const PetscInt **)&B0_cols, (const PetscScalar **)&B0_vals)); 31599566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->local_mat, 1, pcbddc->benign_p0_lidx + i, B0_ncol, B0_cols, B0_vals, INSERT_VALUES)); 31609566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->local_mat, B0_ncol, B0_cols, 1, pcbddc->benign_p0_lidx + i, B0_vals, INSERT_VALUES)); 31619566063dSJacob Faibussowitsch PetscCall(MatSetValue(pcbddc->local_mat, pcbddc->benign_p0_lidx[i], pcbddc->benign_p0_lidx[i], 0.0, INSERT_VALUES)); 31629566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(pcbddc->benign_B0, i, &B0_ncol, (const PetscInt **)&B0_cols, (const PetscScalar **)&B0_vals)); 31634f1b2e48SStefano Zampini } 31649566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pcbddc->local_mat, MAT_FINAL_ASSEMBLY)); 31659566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->local_mat, MAT_FINAL_ASSEMBLY)); 3166c263805aSStefano Zampini } 31673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3168c263805aSStefano Zampini } 3169c263805aSStefano Zampini 3170d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCAdaptiveSelection(PC pc) 3171d71ae5a4SJacob Faibussowitsch { 3172b1b3d7a2SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 317308122e43SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 317408122e43SStefano Zampini PetscBLASInt B_dummyint, B_neigs, B_ierr, B_lwork; 317508122e43SStefano Zampini PetscBLASInt *B_iwork, *B_ifail; 317608122e43SStefano Zampini PetscScalar *work, lwork; 317708122e43SStefano Zampini PetscScalar *St, *S, *eigv; 317808122e43SStefano Zampini PetscScalar *Sarray, *Starray; 3179bd2a564bSStefano Zampini PetscReal *eigs, thresh, lthresh, uthresh; 31801b968477SStefano Zampini PetscInt i, nmax, nmin, nv, cum, mss, cum2, cumarray, maxneigs; 318132fe681dSStefano Zampini PetscBool allocated_S_St, upart; 318208122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 318308122e43SStefano Zampini PetscReal *rwork; 318408122e43SStefano Zampini #endif 3185b1b3d7a2SStefano Zampini 3186b1b3d7a2SStefano Zampini PetscFunctionBegin; 31873ba16761SJacob Faibussowitsch if (!pcbddc->adaptive_selection) PetscFunctionReturn(PETSC_SUCCESS); 318828b400f6SJacob Faibussowitsch PetscCheck(sub_schurs, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Adaptive selection of constraints requires SubSchurs data"); 318932fe681dSStefano 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"); 31909371c9d4SSatish 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, 31919371c9d4SSatish Balay sub_schurs->is_posdef); 31929566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_AdaptiveSetUp[pcbddc->current_level], pc, 0, 0, 0)); 319306a4e24aSStefano Zampini 3194fd14bc51SStefano Zampini if (pcbddc->dbg_flag) { 319532fe681dSStefano Zampini if (!pcbddc->dbg_viewer) pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc)); 31969566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 31979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 31989566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Check adaptive selection of constraints\n")); 31999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 3200fd14bc51SStefano Zampini } 3201fd14bc51SStefano Zampini 320248a46eb9SPierre 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)); 3203e496cd5dSStefano Zampini 320408122e43SStefano Zampini /* max size of subsets */ 320508122e43SStefano Zampini mss = 0; 320608122e43SStefano Zampini for (i = 0; i < sub_schurs->n_subs; i++) { 320708122e43SStefano Zampini PetscInt subset_size; 3208862806e4SStefano Zampini 32099566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->is_subs[i], &subset_size)); 321008122e43SStefano Zampini mss = PetscMax(mss, subset_size); 321108122e43SStefano Zampini } 321208122e43SStefano Zampini 321308122e43SStefano Zampini /* min/max and threshold */ 321408122e43SStefano Zampini nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss; 3215f6f667cfSStefano Zampini nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0; 321608122e43SStefano Zampini nmax = PetscMax(nmin, nmax); 3217f6f667cfSStefano Zampini allocated_S_St = PETSC_FALSE; 3218bd2a564bSStefano Zampini if (nmin || !sub_schurs->is_posdef) { /* XXX */ 3219f6f667cfSStefano Zampini allocated_S_St = PETSC_TRUE; 3220f6f667cfSStefano Zampini } 322108122e43SStefano Zampini 322208122e43SStefano Zampini /* allocate lapack workspace */ 322308122e43SStefano Zampini cum = cum2 = 0; 322408122e43SStefano Zampini maxneigs = 0; 322508122e43SStefano Zampini for (i = 0; i < sub_schurs->n_subs; i++) { 322608122e43SStefano Zampini PetscInt n, subset_size; 3227f6f667cfSStefano Zampini 32289566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->is_subs[i], &subset_size)); 322908122e43SStefano Zampini n = PetscMin(subset_size, nmax); 32309162d606SStefano Zampini cum += subset_size; 32319162d606SStefano Zampini cum2 += subset_size * n; 323208122e43SStefano Zampini maxneigs = PetscMax(maxneigs, n); 323308122e43SStefano Zampini } 32347ebab0bbSStefano Zampini lwork = 0; 323508122e43SStefano Zampini if (mss) { 32367ebab0bbSStefano Zampini PetscScalar sdummy = 0.; 323708122e43SStefano Zampini PetscBLASInt B_itype = 1; 32387ebab0bbSStefano Zampini PetscBLASInt B_N = mss, idummy = 0; 32397ebab0bbSStefano Zampini PetscReal rdummy = 0., zero = 0.0; 32404c6709b3SStefano Zampini PetscReal eps = 0.0; /* dlamch? */ 324108122e43SStefano Zampini 32420fdf79fbSJacob Faibussowitsch PetscCheck(sub_schurs->is_symmetric, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not yet implemented"); 324308122e43SStefano Zampini B_lwork = -1; 32447ebab0bbSStefano Zampini /* some implementations may complain about NULL pointers, even if we are querying */ 32457ebab0bbSStefano Zampini S = &sdummy; 32467ebab0bbSStefano Zampini St = &sdummy; 32477ebab0bbSStefano Zampini eigs = &rdummy; 32487ebab0bbSStefano Zampini eigv = &sdummy; 32497ebab0bbSStefano Zampini B_iwork = &idummy; 32507ebab0bbSStefano Zampini B_ifail = &idummy; 3251d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX) 32527ebab0bbSStefano Zampini rwork = &rdummy; 3253d1710679SStefano Zampini #endif 32548bec7fa6SStefano Zampini thresh = 1.0; 32559566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 325608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 3257792fecdfSBarry 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)); 325808122e43SStefano Zampini #else 3259792fecdfSBarry 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)); 326008122e43SStefano Zampini #endif 326108401ef6SPierre Jolivet PetscCheck(B_ierr == 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in query to SYGVX Lapack routine %d", (int)B_ierr); 32629566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 326308122e43SStefano Zampini } 326408122e43SStefano Zampini 326508122e43SStefano Zampini nv = 0; 3266d62866d3SStefano 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) */ 32679566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->is_vertices, &nv)); 326808122e43SStefano Zampini } 32699566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(lwork), &B_lwork)); 327048a46eb9SPierre Jolivet if (allocated_S_St) PetscCall(PetscMalloc2(mss * mss, &S, mss * mss, &St)); 32719566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(mss * mss, &eigv, mss, &eigs, B_lwork, &work, 5 * mss, &B_iwork, mss, &B_ifail)); 327208122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 32739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(7 * mss, &rwork)); 327408122e43SStefano Zampini #endif 32759371c9d4SSatish 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, 32769371c9d4SSatish Balay &pcbddc->adaptive_constraints_data)); 32779566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(pcbddc->adaptive_constraints_n, nv + sub_schurs->n_subs)); 327808122e43SStefano Zampini 327908122e43SStefano Zampini maxneigs = 0; 328072b8c272SStefano Zampini cum = cumarray = 0; 32819162d606SStefano Zampini pcbddc->adaptive_constraints_idxs_ptr[0] = 0; 32829162d606SStefano Zampini pcbddc->adaptive_constraints_data_ptr[0] = 0; 3283d62866d3SStefano Zampini if (sub_schurs->is_vertices && pcbddc->use_vertices) { 328408122e43SStefano Zampini const PetscInt *idxs; 328508122e43SStefano Zampini 32869566063dSJacob Faibussowitsch PetscCall(ISGetIndices(sub_schurs->is_vertices, &idxs)); 328708122e43SStefano Zampini for (cum = 0; cum < nv; cum++) { 328808122e43SStefano Zampini pcbddc->adaptive_constraints_n[cum] = 1; 328908122e43SStefano Zampini pcbddc->adaptive_constraints_idxs[cum] = idxs[cum]; 329008122e43SStefano Zampini pcbddc->adaptive_constraints_data[cum] = 1.0; 32919162d606SStefano Zampini pcbddc->adaptive_constraints_idxs_ptr[cum + 1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + 1; 32929162d606SStefano Zampini pcbddc->adaptive_constraints_data_ptr[cum + 1] = pcbddc->adaptive_constraints_data_ptr[cum] + 1; 329308122e43SStefano Zampini } 32949566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(sub_schurs->is_vertices, &idxs)); 329508122e43SStefano Zampini } 329608122e43SStefano Zampini 329708122e43SStefano Zampini if (mss) { /* multilevel */ 329832fe681dSStefano Zampini if (sub_schurs->gdsw) { 329932fe681dSStefano Zampini PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_all, &Sarray)); 330032fe681dSStefano Zampini PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all, &Starray)); 330132fe681dSStefano Zampini } else { 33029566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all, &Sarray)); 33039566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all, &Starray)); 330408122e43SStefano Zampini } 330532fe681dSStefano Zampini } 330608122e43SStefano Zampini 3307bd2a564bSStefano Zampini lthresh = pcbddc->adaptive_threshold[0]; 3308bd2a564bSStefano Zampini uthresh = pcbddc->adaptive_threshold[1]; 330932fe681dSStefano Zampini upart = pcbddc->use_deluxe_scaling; 331008122e43SStefano Zampini for (i = 0; i < sub_schurs->n_subs; i++) { 331108122e43SStefano Zampini const PetscInt *idxs; 33129d54b7f4SStefano Zampini PetscReal upper, lower; 3313862806e4SStefano Zampini PetscInt j, subset_size, eigs_start = 0; 331408122e43SStefano Zampini PetscBLASInt B_N; 3315aff50787SStefano Zampini PetscBool same_data = PETSC_FALSE; 3316bd2a564bSStefano Zampini PetscBool scal = PETSC_FALSE; 331708122e43SStefano Zampini 331832fe681dSStefano Zampini if (upart) { 33199d54b7f4SStefano Zampini upper = PETSC_MAX_REAL; 3320bd2a564bSStefano Zampini lower = uthresh; 33219d54b7f4SStefano Zampini } else { 332232fe681dSStefano Zampini if (sub_schurs->gdsw) { 332332fe681dSStefano Zampini upper = uthresh; 332432fe681dSStefano Zampini lower = PETSC_MIN_REAL; 332532fe681dSStefano Zampini } else { 332628b400f6SJacob Faibussowitsch PetscCheck(sub_schurs->is_posdef, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not yet implemented without deluxe scaling"); 3327bd2a564bSStefano Zampini upper = 1. / uthresh; 33289d54b7f4SStefano Zampini lower = 0.; 33299d54b7f4SStefano Zampini } 333032fe681dSStefano Zampini } 33319566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->is_subs[i], &subset_size)); 33329566063dSJacob Faibussowitsch PetscCall(ISGetIndices(sub_schurs->is_subs[i], &idxs)); 33339566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(subset_size, &B_N)); 3334bd2a564bSStefano Zampini /* this is experimental: we assume the dofs have been properly grouped to have 3335bd2a564bSStefano Zampini the diagonal blocks Schur complements either positive or negative definite (true for Stokes) */ 3336bd2a564bSStefano Zampini if (!sub_schurs->is_posdef) { 3337bd2a564bSStefano Zampini Mat T; 3338bd2a564bSStefano Zampini 3339bd2a564bSStefano Zampini for (j = 0; j < subset_size; j++) { 3340bd2a564bSStefano Zampini if (PetscRealPart(*(Sarray + cumarray + j * (subset_size + 1))) < 0.0) { 33419566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, subset_size, subset_size, Sarray + cumarray, &T)); 33429566063dSJacob Faibussowitsch PetscCall(MatScale(T, -1.0)); 33439566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 33449566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, subset_size, subset_size, Starray + cumarray, &T)); 33459566063dSJacob Faibussowitsch PetscCall(MatScale(T, -1.0)); 33469566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 3347bd2a564bSStefano Zampini if (sub_schurs->change_primal_sub) { 3348bd2a564bSStefano Zampini PetscInt nz, k; 3349bd2a564bSStefano Zampini const PetscInt *idxs; 3350bd2a564bSStefano Zampini 33519566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->change_primal_sub[i], &nz)); 33529566063dSJacob Faibussowitsch PetscCall(ISGetIndices(sub_schurs->change_primal_sub[i], &idxs)); 3353bd2a564bSStefano Zampini for (k = 0; k < nz; k++) { 3354bd2a564bSStefano Zampini *(Sarray + cumarray + idxs[k] * (subset_size + 1)) *= -1.0; 3355bd2a564bSStefano Zampini *(Starray + cumarray + idxs[k] * (subset_size + 1)) = 0.0; 3356bd2a564bSStefano Zampini } 33579566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(sub_schurs->change_primal_sub[i], &idxs)); 3358bd2a564bSStefano Zampini } 3359bd2a564bSStefano Zampini scal = PETSC_TRUE; 3360bd2a564bSStefano Zampini break; 3361bd2a564bSStefano Zampini } 3362bd2a564bSStefano Zampini } 3363bd2a564bSStefano Zampini } 3364bd2a564bSStefano Zampini 3365f6f667cfSStefano Zampini if (allocated_S_St) { /* S and S_t should be copied since we could need them later */ 3366bd2a564bSStefano Zampini if (sub_schurs->is_symmetric) { 3367aff50787SStefano Zampini PetscInt j, k; 3368580bdb30SBarry Smith if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscArraycmp() later */ 33699566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(S, subset_size * subset_size)); 33709566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(St, subset_size * subset_size)); 337108122e43SStefano Zampini } 337208122e43SStefano Zampini for (j = 0; j < subset_size; j++) { 3373aff50787SStefano Zampini for (k = j; k < subset_size; k++) { 3374aff50787SStefano Zampini S[j * subset_size + k] = Sarray[cumarray + j * subset_size + k]; 3375aff50787SStefano Zampini St[j * subset_size + k] = Starray[cumarray + j * subset_size + k]; 3376aff50787SStefano Zampini } 337708122e43SStefano Zampini } 337808122e43SStefano Zampini } else { 33799566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 33809566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 338108122e43SStefano Zampini } 33828bec7fa6SStefano Zampini } else { 3383f6f667cfSStefano Zampini S = Sarray + cumarray; 3384f6f667cfSStefano Zampini St = Starray + cumarray; 33858bec7fa6SStefano Zampini } 3386aff50787SStefano Zampini /* see if we can save some work */ 338748a46eb9SPierre Jolivet if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) PetscCall(PetscArraycmp(S, St, subset_size * subset_size, &same_data)); 3388aff50787SStefano Zampini 3389b7ab4a40SStefano Zampini if (same_data && !sub_schurs->change) { /* there's no need of constraints here */ 3390aff50787SStefano Zampini B_neigs = 0; 3391aff50787SStefano Zampini } else { 339208122e43SStefano Zampini PetscBLASInt B_itype = 1; 3393f6f667cfSStefano Zampini PetscBLASInt B_IL, B_IU; 33944c6709b3SStefano Zampini PetscReal eps = -1.0; /* dlamch? */ 33959552c7c7SStefano Zampini PetscInt nmin_s; 3396bd2a564bSStefano Zampini PetscBool compute_range; 3397bd2a564bSStefano Zampini 33980fdf79fbSJacob Faibussowitsch PetscCheck(sub_schurs->is_symmetric, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not yet implemented"); 33999036ceccSStefano Zampini B_neigs = 0; 3400bd2a564bSStefano Zampini compute_range = (PetscBool)!same_data; 3401bd2a564bSStefano Zampini if (nmin >= subset_size) compute_range = PETSC_FALSE; 340208122e43SStefano Zampini 3403fd14bc51SStefano Zampini if (pcbddc->dbg_flag) { 3404*a4cdd7efSStefano Zampini PetscInt nc = 0, c = pcbddc->mat_graph->nodes[idxs[0]].count, w = pcbddc->mat_graph->nodes[idxs[0]].which_dof; 3405d16cbb6bSStefano Zampini 340648a46eb9SPierre Jolivet if (sub_schurs->change_primal_sub) PetscCall(ISGetLocalSize(sub_schurs->change_primal_sub[i], &nc)); 34079de2952eSStefano Zampini PetscCall( 34089de2952eSStefano Zampini 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, sub_schurs->n_subs, subset_size, c, w, compute_range, nc)); 3409b7ab4a40SStefano Zampini } 3410b7ab4a40SStefano Zampini 34119566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 3412b7ab4a40SStefano Zampini if (compute_range) { 3413d16cbb6bSStefano Zampini /* ask for eigenvalues larger than thresh */ 3414bd2a564bSStefano Zampini if (sub_schurs->is_posdef) { 341508122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 3416792fecdfSBarry 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)); 341708122e43SStefano Zampini #else 3418792fecdfSBarry 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)); 341908122e43SStefano Zampini #endif 34209566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 3421bd2a564bSStefano Zampini } else { /* no theory so far, but it works nicely */ 34229036ceccSStefano Zampini PetscInt recipe = 0, recipe_m = 1; 3423bd2a564bSStefano Zampini PetscReal bb[2]; 3424bd2a564bSStefano Zampini 34259566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)pc)->prefix, "-pc_bddc_adaptive_recipe", &recipe, NULL)); 3426bd2a564bSStefano Zampini switch (recipe) { 3427bd2a564bSStefano Zampini case 0: 34289371c9d4SSatish Balay if (scal) { 34299371c9d4SSatish Balay bb[0] = PETSC_MIN_REAL; 34309371c9d4SSatish Balay bb[1] = lthresh; 34319371c9d4SSatish Balay } else { 34329371c9d4SSatish Balay bb[0] = uthresh; 34339371c9d4SSatish Balay bb[1] = PETSC_MAX_REAL; 34349371c9d4SSatish Balay } 3435bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3436792fecdfSBarry 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)); 3437bd2a564bSStefano Zampini #else 3438792fecdfSBarry 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)); 3439bd2a564bSStefano Zampini #endif 34409566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 3441bd2a564bSStefano Zampini break; 3442d71ae5a4SJacob Faibussowitsch case 1: 3443d71ae5a4SJacob Faibussowitsch bb[0] = PETSC_MIN_REAL; 3444d71ae5a4SJacob Faibussowitsch bb[1] = lthresh * lthresh; 3445bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3446792fecdfSBarry 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)); 3447bd2a564bSStefano Zampini #else 3448792fecdfSBarry 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)); 3449bd2a564bSStefano Zampini #endif 34509566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 3451bd2a564bSStefano Zampini if (!scal) { 34529036ceccSStefano Zampini PetscBLASInt B_neigs2 = 0; 3453bd2a564bSStefano Zampini 34549371c9d4SSatish Balay bb[0] = PetscMax(lthresh * lthresh, uthresh); 34559371c9d4SSatish Balay bb[1] = PETSC_MAX_REAL; 34569566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 34579566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 3458bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3459792fecdfSBarry 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)); 3460bd2a564bSStefano Zampini #else 3461792fecdfSBarry 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)); 3462bd2a564bSStefano Zampini #endif 34639566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 3464bd2a564bSStefano Zampini B_neigs += B_neigs2; 3465bd2a564bSStefano Zampini } 3466bd2a564bSStefano Zampini break; 34679036ceccSStefano Zampini case 2: 34689036ceccSStefano Zampini if (scal) { 34699036ceccSStefano Zampini bb[0] = PETSC_MIN_REAL; 34709036ceccSStefano Zampini bb[1] = 0; 34719036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3472792fecdfSBarry 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)); 34739036ceccSStefano Zampini #else 3474792fecdfSBarry 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)); 34759036ceccSStefano Zampini #endif 34769566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 34779036ceccSStefano Zampini } else { 34789036ceccSStefano Zampini PetscBLASInt B_neigs2 = 0; 347913bcc0bdSJacob Faibussowitsch PetscBool do_copy = PETSC_FALSE; 34809036ceccSStefano Zampini 34819036ceccSStefano Zampini lthresh = PetscMax(lthresh, 0.0); 34829036ceccSStefano Zampini if (lthresh > 0.0) { 34839036ceccSStefano Zampini bb[0] = PETSC_MIN_REAL; 34849036ceccSStefano Zampini bb[1] = lthresh * lthresh; 34859036ceccSStefano Zampini 348613bcc0bdSJacob Faibussowitsch do_copy = PETSC_TRUE; 34879036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3488792fecdfSBarry 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)); 34899036ceccSStefano Zampini #else 3490792fecdfSBarry 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)); 34919036ceccSStefano Zampini #endif 34929566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 34939036ceccSStefano Zampini } 34949036ceccSStefano Zampini bb[0] = PetscMax(lthresh * lthresh, uthresh); 34959036ceccSStefano Zampini bb[1] = PETSC_MAX_REAL; 349613bcc0bdSJacob Faibussowitsch if (do_copy) { 34979566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 34989566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 34999036ceccSStefano Zampini } 35009036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3501792fecdfSBarry 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)); 35029036ceccSStefano Zampini #else 3503792fecdfSBarry 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)); 35049036ceccSStefano Zampini #endif 35059566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 35069036ceccSStefano Zampini B_neigs += B_neigs2; 35079036ceccSStefano Zampini } 35089036ceccSStefano Zampini break; 35099036ceccSStefano Zampini case 3: 35109036ceccSStefano Zampini if (scal) { 35119566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)pc)->prefix, "-pc_bddc_adaptive_recipe3_min_scal", &recipe_m, NULL)); 35129036ceccSStefano Zampini } else { 35139566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)pc)->prefix, "-pc_bddc_adaptive_recipe3_min", &recipe_m, NULL)); 35149036ceccSStefano Zampini } 35159036ceccSStefano Zampini if (!scal) { 35169036ceccSStefano Zampini bb[0] = uthresh; 35179036ceccSStefano Zampini bb[1] = PETSC_MAX_REAL; 35189036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3519792fecdfSBarry 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)); 35209036ceccSStefano Zampini #else 3521792fecdfSBarry 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)); 35229036ceccSStefano Zampini #endif 35239566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 35249036ceccSStefano Zampini } 35259036ceccSStefano Zampini if (recipe_m > 0 && B_N - B_neigs > 0) { 35269036ceccSStefano Zampini PetscBLASInt B_neigs2 = 0; 35279036ceccSStefano Zampini 35289036ceccSStefano Zampini B_IL = 1; 35299566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(PetscMin(recipe_m, B_N - B_neigs), &B_IU)); 35309566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 35319566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 35329036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3533792fecdfSBarry 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)); 35349036ceccSStefano Zampini #else 3535792fecdfSBarry 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)); 35369036ceccSStefano Zampini #endif 35379566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 35389036ceccSStefano Zampini B_neigs += B_neigs2; 35399036ceccSStefano Zampini } 35409036ceccSStefano Zampini break; 3541d71ae5a4SJacob Faibussowitsch case 4: 3542d71ae5a4SJacob Faibussowitsch bb[0] = PETSC_MIN_REAL; 3543d71ae5a4SJacob Faibussowitsch bb[1] = lthresh; 354448cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX) 3545792fecdfSBarry 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)); 354648cebe81SStefano Zampini #else 3547792fecdfSBarry 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)); 354848cebe81SStefano Zampini #endif 35499566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 355048cebe81SStefano Zampini { 355148cebe81SStefano Zampini PetscBLASInt B_neigs2 = 0; 355248cebe81SStefano Zampini 35539371c9d4SSatish Balay bb[0] = PetscMax(lthresh + PETSC_SMALL, uthresh); 35549371c9d4SSatish Balay bb[1] = PETSC_MAX_REAL; 35559566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 35569566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 355748cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX) 3558792fecdfSBarry 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)); 355948cebe81SStefano Zampini #else 3560792fecdfSBarry 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)); 356148cebe81SStefano Zampini #endif 35629566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 356348cebe81SStefano Zampini B_neigs += B_neigs2; 356448cebe81SStefano Zampini } 356548cebe81SStefano Zampini break; 356680db8efeSStefano Zampini case 5: /* same as before: first compute all eigenvalues, then filter */ 356780db8efeSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3568792fecdfSBarry 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)); 356980db8efeSStefano Zampini #else 3570792fecdfSBarry 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)); 357180db8efeSStefano Zampini #endif 35729566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 357380db8efeSStefano Zampini { 357480db8efeSStefano Zampini PetscInt e, k, ne; 357580db8efeSStefano Zampini for (e = 0, ne = 0; e < B_neigs; e++) { 357680db8efeSStefano Zampini if (eigs[e] < lthresh || eigs[e] > uthresh) { 357780db8efeSStefano Zampini for (k = 0; k < B_N; k++) S[ne * B_N + k] = eigv[e * B_N + k]; 357880db8efeSStefano Zampini eigs[ne] = eigs[e]; 357980db8efeSStefano Zampini ne++; 358080db8efeSStefano Zampini } 358180db8efeSStefano Zampini } 35829566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(eigv, S, B_N * ne)); 358380db8efeSStefano Zampini B_neigs = ne; 358480db8efeSStefano Zampini } 358580db8efeSStefano Zampini break; 3586d71ae5a4SJacob Faibussowitsch default: 3587d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Unknown recipe %" PetscInt_FMT, recipe); 3588bd2a564bSStefano Zampini } 3589bd2a564bSStefano Zampini } 3590bd2a564bSStefano Zampini } else if (!same_data) { /* this is just to see all the eigenvalues */ 3591d16cbb6bSStefano Zampini B_IU = PetscMax(1, PetscMin(B_N, nmax)); 3592d16cbb6bSStefano Zampini B_IL = 1; 3593d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3594792fecdfSBarry 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)); 3595d16cbb6bSStefano Zampini #else 3596792fecdfSBarry 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)); 3597d16cbb6bSStefano Zampini #endif 35989566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 3599b03ebc13SStefano Zampini } else { /* same_data is true, so just get the adaptive functional requested by the user */ 3600b7ab4a40SStefano Zampini PetscInt k; 360128b400f6SJacob Faibussowitsch PetscCheck(sub_schurs->change_primal_sub, PETSC_COMM_SELF, PETSC_ERR_PLIB, "This should not happen"); 36029566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->change_primal_sub[i], &nmax)); 36039566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(nmax, &B_neigs)); 3604b7ab4a40SStefano Zampini nmin = nmax; 36059566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(eigv, subset_size * nmax)); 3606b7ab4a40SStefano Zampini for (k = 0; k < nmax; k++) { 3607b7ab4a40SStefano Zampini eigs[k] = 1. / PETSC_SMALL; 3608b7ab4a40SStefano Zampini eigv[k * (subset_size + 1)] = 1.0; 3609b7ab4a40SStefano Zampini } 3610d16cbb6bSStefano Zampini } 36119566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 361208122e43SStefano Zampini if (B_ierr) { 361363a3b9bcSJacob Faibussowitsch PetscCheck(B_ierr >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in SYGVX Lapack routine: illegal value for argument %" PetscBLASInt_FMT, -B_ierr); 361463a3b9bcSJacob 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); 361563a3b9bcSJacob 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); 361608122e43SStefano Zampini } 361708122e43SStefano Zampini 361808122e43SStefano Zampini if (B_neigs > nmax) { 361948a46eb9SPierre Jolivet if (pcbddc->dbg_flag) PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " found %" PetscBLASInt_FMT " eigs, more than maximum required %" PetscInt_FMT ".\n", B_neigs, nmax)); 362032fe681dSStefano Zampini if (upart) eigs_start = scal ? 0 : B_neigs - nmax; 362108122e43SStefano Zampini B_neigs = nmax; 362208122e43SStefano Zampini } 362308122e43SStefano Zampini 36249552c7c7SStefano Zampini nmin_s = PetscMin(nmin, B_N); 36259552c7c7SStefano Zampini if (B_neigs < nmin_s) { 36269036ceccSStefano Zampini PetscBLASInt B_neigs2 = 0; 362708122e43SStefano Zampini 362832fe681dSStefano Zampini if (upart) { 3629bd2a564bSStefano Zampini if (scal) { 3630bd2a564bSStefano Zampini B_IU = nmin_s; 3631bd2a564bSStefano Zampini B_IL = B_neigs + 1; 3632bd2a564bSStefano Zampini } else { 3633f6f667cfSStefano Zampini B_IL = B_N - nmin_s + 1; 36349d54b7f4SStefano Zampini B_IU = B_N - B_neigs; 3635bd2a564bSStefano Zampini } 36369d54b7f4SStefano Zampini } else { 36379d54b7f4SStefano Zampini B_IL = B_neigs + 1; 36389d54b7f4SStefano Zampini B_IU = nmin_s; 36399d54b7f4SStefano Zampini } 3640fd14bc51SStefano Zampini if (pcbddc->dbg_flag) { 364163a3b9bcSJacob 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)); 3642fd14bc51SStefano Zampini } 3643bd2a564bSStefano Zampini if (sub_schurs->is_symmetric) { 36441ae86dd6SStefano Zampini PetscInt j, k; 364508122e43SStefano Zampini for (j = 0; j < subset_size; j++) { 36461ae86dd6SStefano Zampini for (k = j; k < subset_size; k++) { 36471ae86dd6SStefano Zampini S[j * subset_size + k] = Sarray[cumarray + j * subset_size + k]; 36481ae86dd6SStefano Zampini St[j * subset_size + k] = Starray[cumarray + j * subset_size + k]; 364908122e43SStefano Zampini } 365008122e43SStefano Zampini } 365108122e43SStefano Zampini } else { 36529566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 36539566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 365408122e43SStefano Zampini } 36559566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 365608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 3657792fecdfSBarry 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)); 365808122e43SStefano Zampini #else 3659792fecdfSBarry 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)); 366008122e43SStefano Zampini #endif 36619566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 36629566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 366308122e43SStefano Zampini B_neigs += B_neigs2; 366408122e43SStefano Zampini } 366508122e43SStefano Zampini if (B_ierr) { 366663a3b9bcSJacob Faibussowitsch PetscCheck(B_ierr >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in SYGVX Lapack routine: illegal value for argument %" PetscBLASInt_FMT, -B_ierr); 366763a3b9bcSJacob 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); 366863a3b9bcSJacob 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); 366908122e43SStefano Zampini } 3670fd14bc51SStefano Zampini if (pcbddc->dbg_flag) { 367163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " -> Got %" PetscBLASInt_FMT " eigs\n", B_neigs)); 367208122e43SStefano Zampini for (j = 0; j < B_neigs; j++) { 367332fe681dSStefano Zampini if (!sub_schurs->gdsw) { 367408122e43SStefano Zampini if (eigs[j] == 0.0) { 36759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " Inf\n")); 367608122e43SStefano Zampini } else { 367732fe681dSStefano Zampini if (upart) { 367863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.6e\n", (double)eigs[j + eigs_start])); 36799d54b7f4SStefano Zampini } else { 368063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.6e\n", (double)(1. / eigs[j + eigs_start]))); 36819d54b7f4SStefano Zampini } 3682fd14bc51SStefano Zampini } 368332fe681dSStefano Zampini } else { 368432fe681dSStefano Zampini double pg = (double)eigs[j + eigs_start]; 368532fe681dSStefano Zampini if (pg < 2 * PETSC_SMALL) pg = 0.0; 368632fe681dSStefano Zampini PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.6e\n", pg)); 368732fe681dSStefano Zampini } 368808122e43SStefano Zampini } 368908122e43SStefano Zampini } 3690aff50787SStefano Zampini } 36916c3e6151SStefano Zampini /* change the basis back to the original one */ 36926c3e6151SStefano Zampini if (sub_schurs->change) { 369372b8c272SStefano Zampini Mat change, phi, phit; 36946c3e6151SStefano Zampini 369503dfb2d7SStefano Zampini if (pcbddc->dbg_flag > 2) { 36966c3e6151SStefano Zampini PetscInt ii; 36976c3e6151SStefano Zampini for (ii = 0; ii < B_neigs; ii++) { 369863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " -> Eigenvector (old basis) %" PetscInt_FMT "/%" PetscBLASInt_FMT " (%" PetscBLASInt_FMT ")\n", ii, B_neigs, B_N)); 36996c3e6151SStefano Zampini for (j = 0; j < B_N; j++) { 3700684229deSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3701684229deSStefano Zampini PetscReal r = PetscRealPart(eigv[(ii + eigs_start) * subset_size + j]); 3702684229deSStefano Zampini PetscReal c = PetscImaginaryPart(eigv[(ii + eigs_start) * subset_size + j]); 370363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.4e + %1.4e i\n", (double)r, (double)c)); 3704684229deSStefano Zampini #else 370563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.4e\n", (double)(eigv[(ii + eigs_start) * subset_size + j]))); 3706684229deSStefano Zampini #endif 37076c3e6151SStefano Zampini } 37086c3e6151SStefano Zampini } 37096c3e6151SStefano Zampini } 37109566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(sub_schurs->change[i], &change, NULL)); 37119566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, subset_size, B_neigs, eigv + eigs_start * subset_size, &phit)); 37129566063dSJacob Faibussowitsch PetscCall(MatMatMult(change, phit, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &phi)); 37139566063dSJacob Faibussowitsch PetscCall(MatCopy(phi, phit, SAME_NONZERO_PATTERN)); 37149566063dSJacob Faibussowitsch PetscCall(MatDestroy(&phit)); 37159566063dSJacob Faibussowitsch PetscCall(MatDestroy(&phi)); 37166c3e6151SStefano Zampini } 37178bec7fa6SStefano Zampini maxneigs = PetscMax(B_neigs, maxneigs); 37188bec7fa6SStefano Zampini pcbddc->adaptive_constraints_n[i + nv] = B_neigs; 37199162d606SStefano Zampini if (B_neigs) { 37209566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pcbddc->adaptive_constraints_data + pcbddc->adaptive_constraints_data_ptr[cum], eigv + eigs_start * subset_size, B_neigs * subset_size)); 3721fd14bc51SStefano Zampini 3722fd14bc51SStefano Zampini if (pcbddc->dbg_flag > 1) { 37239552c7c7SStefano Zampini PetscInt ii; 37249552c7c7SStefano Zampini for (ii = 0; ii < B_neigs; ii++) { 372563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " -> Eigenvector %" PetscInt_FMT "/%" PetscBLASInt_FMT " (%" PetscBLASInt_FMT ")\n", ii, B_neigs, B_N)); 37269552c7c7SStefano Zampini for (j = 0; j < B_N; j++) { 3727ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3728ac47001eSStefano Zampini PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii * subset_size + j + pcbddc->adaptive_constraints_data_ptr[cum]]); 3729ac47001eSStefano Zampini PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii * subset_size + j + pcbddc->adaptive_constraints_data_ptr[cum]]); 373063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.4e + %1.4e i\n", (double)r, (double)c)); 3731ac47001eSStefano Zampini #else 373263a3b9bcSJacob 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]]))); 3733ac47001eSStefano Zampini #endif 37349552c7c7SStefano Zampini } 37359552c7c7SStefano Zampini } 3736fd14bc51SStefano Zampini } 37379566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pcbddc->adaptive_constraints_idxs + pcbddc->adaptive_constraints_idxs_ptr[cum], idxs, subset_size)); 37389162d606SStefano Zampini pcbddc->adaptive_constraints_idxs_ptr[cum + 1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size; 37399162d606SStefano Zampini pcbddc->adaptive_constraints_data_ptr[cum + 1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size * B_neigs; 37409162d606SStefano Zampini cum++; 374108122e43SStefano Zampini } 37429566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(sub_schurs->is_subs[i], &idxs)); 374308122e43SStefano Zampini /* shift for next computation */ 374408122e43SStefano Zampini cumarray += subset_size * subset_size; 374508122e43SStefano Zampini } 37461baa6e33SBarry Smith if (pcbddc->dbg_flag) PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 374708122e43SStefano Zampini 374808122e43SStefano Zampini if (mss) { 374932fe681dSStefano Zampini if (sub_schurs->gdsw) { 375032fe681dSStefano Zampini PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_all, &Sarray)); 375132fe681dSStefano Zampini PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all, &Starray)); 375232fe681dSStefano Zampini } else { 37539566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all, &Sarray)); 37549566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all, &Starray)); 3755f6f667cfSStefano Zampini /* destroy matrices (junk) */ 37569566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sub_schurs->sum_S_Ej_inv_all)); 37579566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sub_schurs->sum_S_Ej_tilda_all)); 375808122e43SStefano Zampini } 375932fe681dSStefano Zampini } 37601baa6e33SBarry Smith if (allocated_S_St) PetscCall(PetscFree2(S, St)); 37619566063dSJacob Faibussowitsch PetscCall(PetscFree5(eigv, eigs, work, B_iwork, B_ifail)); 376208122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 37639566063dSJacob Faibussowitsch PetscCall(PetscFree(rwork)); 376408122e43SStefano Zampini #endif 376508122e43SStefano Zampini if (pcbddc->dbg_flag) { 37661b968477SStefano Zampini PetscInt maxneigs_r; 37671c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&maxneigs, &maxneigs_r, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)pc))); 376863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Maximum number of constraints per cc %" PetscInt_FMT "\n", maxneigs_r)); 376908122e43SStefano Zampini } 37709566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_AdaptiveSetUp[pcbddc->current_level], pc, 0, 0, 0)); 37713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 377208122e43SStefano Zampini } 3773b1b3d7a2SStefano Zampini 3774d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpSolvers(PC pc) 3775d71ae5a4SJacob Faibussowitsch { 37769de2952eSStefano Zampini Mat coarse_submat; 3777c8587f34SStefano Zampini 3778c8587f34SStefano Zampini PetscFunctionBegin; 3779f4ddd8eeSStefano Zampini /* Setup local scatters R_to_B and (optionally) R_to_D */ 37805e8657edSStefano Zampini /* PCBDDCSetUpLocalWorkVectors should be called first! */ 37819566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpLocalScatters(pc)); 3782c8587f34SStefano Zampini 3783684f6988SStefano Zampini /* Setup local neumann solver ksp_R */ 37840fccc4e9SStefano Zampini /* PCBDDCSetUpLocalScatters should be called first! */ 37859566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpLocalSolvers(pc, PETSC_FALSE, PETSC_TRUE)); 3786c8587f34SStefano Zampini 37878629588bSStefano Zampini /* 37888629588bSStefano Zampini Setup local correction and local part of coarse basis. 37898629588bSStefano Zampini Gives back the dense local part of the coarse matrix in column major ordering 37908629588bSStefano Zampini */ 37919de2952eSStefano Zampini PetscCall(PCBDDCSetUpCorrection(pc, &coarse_submat)); 37928629588bSStefano Zampini 37938629588bSStefano Zampini /* Compute total number of coarse nodes and setup coarse solver */ 37949de2952eSStefano Zampini PetscCall(PCBDDCSetUpCoarseSolver(pc, coarse_submat)); 37959de2952eSStefano Zampini PetscCall(MatDestroy(&coarse_submat)); 37963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3797c8587f34SStefano Zampini } 3798c8587f34SStefano Zampini 3799d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCResetCustomization(PC pc) 3800d71ae5a4SJacob Faibussowitsch { 3801674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 3802674ae819SStefano Zampini 3803674ae819SStefano Zampini PetscFunctionBegin; 38049566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices)); 38059566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local)); 38069566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundaries)); 38079566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal)); 38089566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundaries)); 38099566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&pcbddc->onearnullspace)); 38109566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->onearnullvecs_state)); 38119566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal)); 38129566063dSJacob Faibussowitsch PetscCall(PCBDDCSetDofsSplitting(pc, 0, NULL)); 38139566063dSJacob Faibussowitsch PetscCall(PCBDDCSetDofsSplittingLocal(pc, 0, NULL)); 38143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3815674ae819SStefano Zampini } 3816674ae819SStefano Zampini 3817d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCResetTopography(PC pc) 3818d71ae5a4SJacob Faibussowitsch { 3819674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 38204f1b2e48SStefano Zampini PetscInt i; 3821674ae819SStefano Zampini 3822674ae819SStefano Zampini PetscFunctionBegin; 38239566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->nedcG)); 38249566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->nedclocal)); 38259566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->discretegradient)); 38269566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->user_ChangeOfBasisMatrix)); 38279566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->ChangeOfBasisMatrix)); 38289566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->switch_static_change)); 38299566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->work_change)); 38309566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->ConstraintMatrix)); 38319566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->divudotp)); 38329566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->divudotp_vl2l)); 38339566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphDestroy(&pcbddc->mat_graph)); 383448a46eb9SPierre Jolivet for (i = 0; i < pcbddc->n_local_subs; i++) PetscCall(ISDestroy(&pcbddc->local_subs[i])); 3835e68a0315Sstefano_zampini pcbddc->n_local_subs = 0; 38369566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->local_subs)); 38379566063dSJacob Faibussowitsch PetscCall(PCBDDCSubSchursDestroy(&pcbddc->sub_schurs)); 3838c703fcc7SStefano Zampini pcbddc->graphanalyzed = PETSC_FALSE; 38398af8fcf9SStefano Zampini pcbddc->recompute_topography = PETSC_TRUE; 38401c7a958bSStefano Zampini pcbddc->corner_selected = PETSC_FALSE; 38413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3842674ae819SStefano Zampini } 3843674ae819SStefano Zampini 3844d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCResetSolvers(PC pc) 3845d71ae5a4SJacob Faibussowitsch { 3846674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 3847674ae819SStefano Zampini 3848674ae819SStefano Zampini PetscFunctionBegin; 38499566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->coarse_vec)); 38509566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_phi_B)); 38519566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_phi_D)); 38529566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_psi_B)); 38539566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_psi_D)); 38549566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_P)); 38559566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_C)); 38569566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_auxmat2)); 38579566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_auxmat1)); 38589566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_R)); 38599566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec2_R)); 38609566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->is_R_local)); 38619566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->R_to_B)); 38629566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->R_to_D)); 38639566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->coarse_loc_to_glob)); 38649566063dSJacob Faibussowitsch PetscCall(KSPReset(pcbddc->ksp_D)); 38659566063dSJacob Faibussowitsch PetscCall(KSPReset(pcbddc->ksp_R)); 38669566063dSJacob Faibussowitsch PetscCall(KSPReset(pcbddc->coarse_ksp)); 38679566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 38689566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->primal_indices_local_idxs)); 38699566063dSJacob Faibussowitsch PetscCall(PetscFree2(pcbddc->local_primal_ref_node, pcbddc->local_primal_ref_mult)); 38709566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->global_primal_indices)); 38719566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->coarse_subassembling)); 38729566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->benign_change)); 38739566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->benign_vec)); 38749566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignShellMat(pc, PETSC_TRUE)); 38759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->benign_B0)); 38769566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pcbddc->benign_sf)); 3877ca92afb2SStefano Zampini if (pcbddc->benign_zerodiag_subs) { 3878ca92afb2SStefano Zampini PetscInt i; 387948a46eb9SPierre Jolivet for (i = 0; i < pcbddc->benign_n; i++) PetscCall(ISDestroy(&pcbddc->benign_zerodiag_subs[i])); 38809566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->benign_zerodiag_subs)); 3881ca92afb2SStefano Zampini } 38829566063dSJacob Faibussowitsch PetscCall(PetscFree3(pcbddc->benign_p0_lidx, pcbddc->benign_p0_gidx, pcbddc->benign_p0)); 38833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3884674ae819SStefano Zampini } 3885674ae819SStefano Zampini 3886d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc) 3887d71ae5a4SJacob Faibussowitsch { 38886bfb1811SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 38896bfb1811SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 38906bfb1811SStefano Zampini VecType impVecType; 38914f1b2e48SStefano Zampini PetscInt n_constraints, n_R, old_size; 38926bfb1811SStefano Zampini 38936bfb1811SStefano Zampini PetscFunctionBegin; 38944f1b2e48SStefano Zampini n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices; 3895b371cd4fSStefano Zampini n_R = pcis->n - pcbddc->n_vertices; 38969566063dSJacob Faibussowitsch PetscCall(VecGetType(pcis->vec1_N, &impVecType)); 3897e7b262bdSStefano Zampini /* local work vectors (try to avoid unneeded work)*/ 3898e7b262bdSStefano Zampini /* R nodes */ 3899e7b262bdSStefano Zampini old_size = -1; 390048a46eb9SPierre Jolivet if (pcbddc->vec1_R) PetscCall(VecGetSize(pcbddc->vec1_R, &old_size)); 3901e7b262bdSStefano Zampini if (n_R != old_size) { 39029566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_R)); 39039566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec2_R)); 39049566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N), &pcbddc->vec1_R)); 39059566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pcbddc->vec1_R, PETSC_DECIDE, n_R)); 39069566063dSJacob Faibussowitsch PetscCall(VecSetType(pcbddc->vec1_R, impVecType)); 39079566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcbddc->vec1_R, &pcbddc->vec2_R)); 3908e7b262bdSStefano Zampini } 3909e7b262bdSStefano Zampini /* local primal dofs */ 3910e7b262bdSStefano Zampini old_size = -1; 391148a46eb9SPierre Jolivet if (pcbddc->vec1_P) PetscCall(VecGetSize(pcbddc->vec1_P, &old_size)); 3912e9189074SStefano Zampini if (pcbddc->local_primal_size != old_size) { 39139566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_P)); 39149566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N), &pcbddc->vec1_P)); 39159566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pcbddc->vec1_P, PETSC_DECIDE, pcbddc->local_primal_size)); 39169566063dSJacob Faibussowitsch PetscCall(VecSetType(pcbddc->vec1_P, impVecType)); 3917e7b262bdSStefano Zampini } 3918e7b262bdSStefano Zampini /* local explicit constraints */ 3919e7b262bdSStefano Zampini old_size = -1; 392048a46eb9SPierre Jolivet if (pcbddc->vec1_C) PetscCall(VecGetSize(pcbddc->vec1_C, &old_size)); 3921e7b262bdSStefano Zampini if (n_constraints && n_constraints != old_size) { 39229566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_C)); 39239566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N), &pcbddc->vec1_C)); 39249566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pcbddc->vec1_C, PETSC_DECIDE, n_constraints)); 39259566063dSJacob Faibussowitsch PetscCall(VecSetType(pcbddc->vec1_C, impVecType)); 392683b7ccabSStefano Zampini } 39273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 39286bfb1811SStefano Zampini } 39296bfb1811SStefano Zampini 39309de2952eSStefano Zampini static PetscErrorCode MatSetValuesSubMat(Mat A, Mat S, PetscInt nr, const PetscInt rows[], PetscInt nc, const PetscInt cols[], InsertMode imode) 3931d71ae5a4SJacob Faibussowitsch { 39329de2952eSStefano Zampini PetscBool flg; 39339de2952eSStefano Zampini const PetscScalar *a; 39349de2952eSStefano Zampini 39359de2952eSStefano Zampini PetscFunctionBegin; 39369de2952eSStefano Zampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)S, MATSEQDENSE, &flg)); 39379de2952eSStefano Zampini if (flg) { 39389de2952eSStefano Zampini PetscCall(MatDenseGetArrayRead(S, &a)); 39399de2952eSStefano Zampini PetscCall(MatSetOption(A, MAT_ROW_ORIENTED, PETSC_FALSE)); 39409de2952eSStefano Zampini PetscCall(MatSetValues(A, nr, rows, nc, cols, a, imode)); 39419de2952eSStefano Zampini PetscCall(MatSetOption(A, MAT_ROW_ORIENTED, PETSC_TRUE)); 39429de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayRead(S, &a)); 39439de2952eSStefano Zampini } else { 39449de2952eSStefano Zampini const PetscInt *ii, *jj; 39459de2952eSStefano Zampini PetscInt n; 39469de2952eSStefano Zampini PetscInt buf[8192], *bufc = NULL; 39479de2952eSStefano Zampini PetscBool freeb = PETSC_FALSE; 39489de2952eSStefano Zampini Mat Sm = S; 39499de2952eSStefano Zampini 39509de2952eSStefano Zampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)S, MATSEQAIJ, &flg)); 39519de2952eSStefano Zampini if (!flg) PetscCall(MatConvert(S, MATSEQAIJ, MAT_INITIAL_MATRIX, &Sm)); 39529de2952eSStefano Zampini else PetscCall(PetscObjectReference((PetscObject)S)); 39539de2952eSStefano Zampini PetscCall(MatSeqAIJGetArrayRead(Sm, &a)); 39549de2952eSStefano Zampini PetscCall(MatGetRowIJ(Sm, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &flg)); 39559de2952eSStefano Zampini PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Cannot get IJ structure"); 39569de2952eSStefano Zampini if (nc <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 39579de2952eSStefano Zampini bufc = buf; 39589de2952eSStefano Zampini } else { 39599de2952eSStefano Zampini PetscCall(PetscMalloc1(nc, &bufc)); 39609de2952eSStefano Zampini freeb = PETSC_TRUE; 39619de2952eSStefano Zampini } 39629de2952eSStefano Zampini 39639de2952eSStefano Zampini for (PetscInt i = 0; i < n; i++) { 39649de2952eSStefano Zampini const PetscInt nci = ii[i + 1] - ii[i]; 39659de2952eSStefano Zampini 39669de2952eSStefano Zampini for (PetscInt j = 0; j < nci; j++) bufc[j] = cols[jj[ii[i] + j]]; 39679de2952eSStefano Zampini PetscCall(MatSetValues(A, 1, rows + i, nci, bufc, a + ii[i], imode)); 39689de2952eSStefano Zampini } 39699de2952eSStefano Zampini PetscCall(MatRestoreRowIJ(Sm, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &flg)); 39709de2952eSStefano Zampini PetscCall(MatSeqAIJRestoreArrayRead(Sm, &a)); 39719de2952eSStefano Zampini PetscCall(MatDestroy(&Sm)); 39729de2952eSStefano Zampini if (freeb) PetscCall(PetscFree(bufc)); 39739de2952eSStefano Zampini } 39749de2952eSStefano Zampini PetscCall(MatAssemblyBegin(A, MAT_FLUSH_ASSEMBLY)); 39759de2952eSStefano Zampini PetscCall(MatAssemblyEnd(A, MAT_FLUSH_ASSEMBLY)); 39769de2952eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 39779de2952eSStefano Zampini } 39789de2952eSStefano Zampini 39799de2952eSStefano Zampini static PetscErrorCode MatCreateSeqAIJFromDenseExpand(Mat D, PetscInt n, const PetscInt j[], Mat *mat) 39809de2952eSStefano Zampini { 39819de2952eSStefano Zampini Mat_SeqAIJ *aij; 39829de2952eSStefano Zampini PetscInt *ii, *jj; 39839de2952eSStefano Zampini PetscScalar *aa; 39849de2952eSStefano Zampini PetscInt nnz = 0, m, nc; 39859de2952eSStefano Zampini const PetscScalar *a; 39869de2952eSStefano Zampini const PetscScalar zero = 0.0; 39879de2952eSStefano Zampini 39889de2952eSStefano Zampini PetscFunctionBegin; 39899de2952eSStefano Zampini PetscCall(MatGetLocalSize(D, &m, &nc)); 39909de2952eSStefano Zampini PetscCall(MatDenseGetArrayRead(D, &a)); 39919de2952eSStefano Zampini PetscCall(PetscMalloc1(m + 1, &ii)); 39929de2952eSStefano Zampini PetscCall(PetscMalloc1(m * nc, &jj)); 39939de2952eSStefano Zampini PetscCall(PetscMalloc1(m * nc, &aa)); 39949de2952eSStefano Zampini ii[0] = 0; 39959de2952eSStefano Zampini for (PetscInt k = 0; k < m; k++) { 39969de2952eSStefano Zampini for (PetscInt s = 0; s < nc; s++) { 39979de2952eSStefano Zampini const PetscInt c = s + k * nc; 39989de2952eSStefano Zampini const PetscScalar v = a[k + s * m]; 39999de2952eSStefano Zampini 40009de2952eSStefano Zampini if (PetscUnlikely(j[c] < 0 || v == zero)) continue; 40019de2952eSStefano Zampini jj[nnz] = j[c]; 40029de2952eSStefano Zampini aa[nnz] = a[k + s * m]; 40039de2952eSStefano Zampini nnz++; 40049de2952eSStefano Zampini } 40059de2952eSStefano Zampini ii[k + 1] = nnz; 40069de2952eSStefano Zampini } 40079de2952eSStefano Zampini 40089de2952eSStefano Zampini PetscCall(MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)D), m, n, ii, jj, aa, mat)); 40099de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayRead(D, &a)); 40109de2952eSStefano Zampini 40119de2952eSStefano Zampini aij = (Mat_SeqAIJ *)(*mat)->data; 40129de2952eSStefano Zampini aij->free_a = PETSC_TRUE; 40139de2952eSStefano Zampini aij->free_ij = PETSC_TRUE; 40149de2952eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 40159de2952eSStefano Zampini } 40169de2952eSStefano Zampini 40179de2952eSStefano Zampini /* adapted from MatInvertVariableBlockDiagonal_SeqAIJ */ 40189de2952eSStefano Zampini static PetscErrorCode MatSeqAIJInvertVariableBlockDiagonalMat(Mat A, PetscInt nblocks, const PetscInt *bsizes, Mat *B) 40199de2952eSStefano Zampini { 40209de2952eSStefano Zampini PetscInt n = A->rmap->n, ncnt = 0, ncnt2 = 0, bsizemax = 0, *v_pivots = NULL; 40219de2952eSStefano Zampini const PetscBool allowzeropivot = PETSC_FALSE; 40229de2952eSStefano Zampini PetscBool zeropivotdetected = PETSC_FALSE; 40239de2952eSStefano Zampini const PetscReal shift = 0.0; 40249de2952eSStefano Zampini PetscInt ipvt[5], *ii, *jj, *indi, *indj; 40259de2952eSStefano Zampini PetscScalar work[25], *v_work = NULL, *aa, *diag; 40269de2952eSStefano Zampini PetscLogDouble flops = 0.0; 40279de2952eSStefano Zampini 40289de2952eSStefano Zampini PetscFunctionBegin; 40299de2952eSStefano Zampini PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Not for rectangular matrices"); 40309de2952eSStefano Zampini for (PetscInt i = 0; i < nblocks; i++) { 40319de2952eSStefano Zampini ncnt += bsizes[i]; 40329de2952eSStefano Zampini ncnt2 += PetscSqr(bsizes[i]); 40339de2952eSStefano Zampini } 40349de2952eSStefano Zampini PetscCheck(ncnt == n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total blocksizes %" PetscInt_FMT " doesn't match number matrix rows %" PetscInt_FMT, ncnt, n); 40359de2952eSStefano Zampini for (PetscInt i = 0; i < nblocks; i++) bsizemax = PetscMax(bsizemax, bsizes[i]); 40369de2952eSStefano Zampini if (bsizemax > 7) PetscCall(PetscMalloc2(bsizemax, &v_work, bsizemax, &v_pivots)); 40379de2952eSStefano Zampini 40389de2952eSStefano Zampini PetscCall(PetscMalloc1(n + 1, &ii)); 40399de2952eSStefano Zampini PetscCall(PetscMalloc1(ncnt2, &jj)); 40409de2952eSStefano Zampini PetscCall(PetscCalloc1(ncnt2, &aa)); 40419de2952eSStefano Zampini 40429de2952eSStefano Zampini ncnt = 0; 40439de2952eSStefano Zampini ii[0] = 0; 40449de2952eSStefano Zampini indi = ii; 40459de2952eSStefano Zampini indj = jj; 40469de2952eSStefano Zampini diag = aa; 40479de2952eSStefano Zampini for (PetscInt i = 0; i < nblocks; i++) { 40489de2952eSStefano Zampini const PetscInt bs = bsizes[i]; 40499de2952eSStefano Zampini 40509de2952eSStefano Zampini for (PetscInt k = 0; k < bs; k++) { 40519de2952eSStefano Zampini indi[k + 1] = indi[k] + bs; 40529de2952eSStefano Zampini for (PetscInt j = 0; j < bs; j++) indj[k * bs + j] = ncnt + j; 40539de2952eSStefano Zampini } 40549de2952eSStefano Zampini PetscCall(MatGetValues(A, bs, indj, bs, indj, diag)); 40559de2952eSStefano Zampini switch (bs) { 40569de2952eSStefano Zampini case 1: 40579de2952eSStefano Zampini *diag = 1.0 / (*diag); 40589de2952eSStefano Zampini break; 40599de2952eSStefano Zampini case 2: 40609de2952eSStefano Zampini PetscCall(PetscKernel_A_gets_inverse_A_2(diag, shift, allowzeropivot, &zeropivotdetected)); 40619de2952eSStefano Zampini break; 40629de2952eSStefano Zampini case 3: 40639de2952eSStefano Zampini PetscCall(PetscKernel_A_gets_inverse_A_3(diag, shift, allowzeropivot, &zeropivotdetected)); 40649de2952eSStefano Zampini break; 40659de2952eSStefano Zampini case 4: 40669de2952eSStefano Zampini PetscCall(PetscKernel_A_gets_inverse_A_4(diag, shift, allowzeropivot, &zeropivotdetected)); 40679de2952eSStefano Zampini break; 40689de2952eSStefano Zampini case 5: 40699de2952eSStefano Zampini PetscCall(PetscKernel_A_gets_inverse_A_5(diag, ipvt, work, shift, allowzeropivot, &zeropivotdetected)); 40709de2952eSStefano Zampini break; 40719de2952eSStefano Zampini case 6: 40729de2952eSStefano Zampini PetscCall(PetscKernel_A_gets_inverse_A_6(diag, shift, allowzeropivot, &zeropivotdetected)); 40739de2952eSStefano Zampini break; 40749de2952eSStefano Zampini case 7: 40759de2952eSStefano Zampini PetscCall(PetscKernel_A_gets_inverse_A_7(diag, shift, allowzeropivot, &zeropivotdetected)); 40769de2952eSStefano Zampini break; 40779de2952eSStefano Zampini default: 40789de2952eSStefano Zampini PetscCall(PetscKernel_A_gets_inverse_A(bs, diag, v_pivots, v_work, allowzeropivot, &zeropivotdetected)); 40799de2952eSStefano Zampini } 40809de2952eSStefano Zampini ncnt += bs; 40819de2952eSStefano Zampini flops += 2.0 * PetscPowInt(bs, 3) / 3.0; 40829de2952eSStefano Zampini diag += bs * bs; 40839de2952eSStefano Zampini indj += bs * bs; 40849de2952eSStefano Zampini indi += bs; 40859de2952eSStefano Zampini } 40869de2952eSStefano Zampini PetscCall(PetscLogFlops(flops)); 40879de2952eSStefano Zampini PetscCall(PetscFree2(v_work, v_pivots)); 40889de2952eSStefano Zampini PetscCall(MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A), n, n, ii, jj, aa, B)); 40899de2952eSStefano Zampini { 40909de2952eSStefano Zampini Mat_SeqAIJ *aij = (Mat_SeqAIJ *)(*B)->data; 40919de2952eSStefano Zampini aij->free_a = PETSC_TRUE; 40929de2952eSStefano Zampini aij->free_ij = PETSC_TRUE; 40939de2952eSStefano Zampini } 40949de2952eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 40959de2952eSStefano Zampini } 40969de2952eSStefano Zampini 40979de2952eSStefano Zampini static PetscErrorCode MatDenseScatter(Mat A, PetscSF sf, Mat B) 40989de2952eSStefano Zampini { 40999de2952eSStefano Zampini const PetscScalar *rarr; 41009de2952eSStefano Zampini PetscScalar *larr; 41019de2952eSStefano Zampini PetscSF vsf; 41029de2952eSStefano Zampini PetscInt n, rld, lld; 41039de2952eSStefano Zampini 41049de2952eSStefano Zampini PetscFunctionBegin; 41059de2952eSStefano Zampini PetscCall(MatGetSize(A, NULL, &n)); 41069de2952eSStefano Zampini PetscCall(MatDenseGetLDA(A, &rld)); 41079de2952eSStefano Zampini PetscCall(MatDenseGetLDA(B, &lld)); 41089de2952eSStefano Zampini PetscCall(MatDenseGetArrayRead(A, &rarr)); 41099de2952eSStefano Zampini PetscCall(MatDenseGetArrayWrite(B, &larr)); 41109de2952eSStefano Zampini PetscCall(PetscSFCreateStridedSF(sf, n, rld, lld, &vsf)); 41119de2952eSStefano Zampini PetscCall(PetscSFBcastBegin(vsf, MPIU_SCALAR, rarr, larr, MPI_REPLACE)); 41129de2952eSStefano Zampini PetscCall(PetscSFBcastEnd(vsf, MPIU_SCALAR, rarr, larr, MPI_REPLACE)); 41139de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayRead(A, &rarr)); 41149de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayWrite(B, &larr)); 41159de2952eSStefano Zampini PetscCall(PetscSFDestroy(&vsf)); 41169de2952eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 41179de2952eSStefano Zampini } 41189de2952eSStefano Zampini 41199de2952eSStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, Mat *coarse_submat) 41209de2952eSStefano Zampini { 412188ebb749SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 412288ebb749SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 41239de2952eSStefano Zampini PCBDDCGraph graph = pcbddc->mat_graph; 4124d62866d3SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 412525084f0cSStefano Zampini /* submatrices of local problem */ 41269de2952eSStefano Zampini Mat A_RV = NULL, A_VR, A_VV, local_auxmat2_R = NULL; 412706656605SStefano Zampini /* submatrices of local coarse problem */ 41289de2952eSStefano Zampini Mat S_CV = NULL, S_VC = NULL, S_CC = NULL; 412925084f0cSStefano Zampini /* working matrices */ 413006656605SStefano Zampini Mat C_CR; 41319de2952eSStefano Zampini 413225084f0cSStefano Zampini /* additional working stuff */ 413306656605SStefano Zampini PC pc_R; 41349de2952eSStefano Zampini IS is_R, is_V, is_C; 41359de2952eSStefano Zampini const PetscInt *idx_V, *idx_C; 4136c58f9fdbSStefano Zampini Mat F, Brhs = NULL; 41375cbda25cSStefano Zampini Vec dummy_vec; 41387ebab0bbSStefano Zampini PetscBool isLU, isCHOL, need_benign_correction, sparserhs; 413906656605SStefano Zampini PetscInt *idx_V_B; 41409de2952eSStefano Zampini PetscInt lda_rhs, n_vertices, n_constraints, *p0_lidx_I; 41419de2952eSStefano Zampini PetscInt n_eff_vertices, n_eff_constraints; 414206656605SStefano Zampini PetscInt i, n_R, n_D, n_B; 414306656605SStefano Zampini PetscScalar one = 1.0, m_one = -1.0; 414488ebb749SStefano Zampini 41459de2952eSStefano Zampini /* Multi-element support */ 41469de2952eSStefano Zampini PetscBool multi_element = graph->multi_element; 41479de2952eSStefano Zampini PetscInt *V_to_eff_V = NULL, *C_to_eff_C = NULL; 41489de2952eSStefano Zampini PetscInt *B_eff_V_J = NULL, *R_eff_V_J = NULL, *B_eff_C_J = NULL, *R_eff_C_J = NULL; 41499de2952eSStefano Zampini IS is_C_perm = NULL; 41509de2952eSStefano Zampini PetscInt n_C_bss = 0, *C_bss = NULL; 41519de2952eSStefano Zampini Mat coarse_phi_multi; 41529de2952eSStefano Zampini 415388ebb749SStefano Zampini PetscFunctionBegin; 41547827d75bSBarry 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"); 41559566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_CorrectionSetUp[pcbddc->current_level], pc, 0, 0, 0)); 4156ffd830a3SStefano Zampini 4157ffd830a3SStefano Zampini /* Set Non-overlapping dimensions */ 4158b371cd4fSStefano Zampini n_vertices = pcbddc->n_vertices; 41594f1b2e48SStefano Zampini n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices; 4160b371cd4fSStefano Zampini n_B = pcis->n_B; 4161b371cd4fSStefano Zampini n_D = pcis->n - n_B; 416288ebb749SStefano Zampini n_R = pcis->n - n_vertices; 416388ebb749SStefano Zampini 416488ebb749SStefano Zampini /* vertices in boundary numbering */ 41659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_vertices, &idx_V_B)); 41669566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(pcis->BtoNmap, IS_GTOLM_DROP, n_vertices, pcbddc->local_primal_ref_node, &i, idx_V_B)); 416763a3b9bcSJacob 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); 416888ebb749SStefano Zampini 41699de2952eSStefano Zampini /* these two cases still need to be optimized */ 41709de2952eSStefano Zampini if (pcbddc->benign_saddle_point || !pcbddc->symmetric_primal) multi_element = PETSC_FALSE; 41719de2952eSStefano Zampini 417206656605SStefano Zampini /* Subdomain contribution (Non-overlapping) to coarse matrix */ 41739de2952eSStefano Zampini if (multi_element) { 41749de2952eSStefano Zampini PetscCheck(!pcbddc->benign_n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not yet implemented"); 41759de2952eSStefano Zampini 41769de2952eSStefano Zampini PetscCall(MatCreate(PETSC_COMM_SELF, coarse_submat)); 41779de2952eSStefano Zampini PetscCall(MatSetSizes(*coarse_submat, pcbddc->local_primal_size, pcbddc->local_primal_size, pcbddc->local_primal_size, pcbddc->local_primal_size)); 41789de2952eSStefano Zampini PetscCall(MatSetType(*coarse_submat, MATSEQAIJ)); 41799de2952eSStefano Zampini PetscCall(MatSetOption(*coarse_submat, MAT_IGNORE_ZERO_ENTRIES, PETSC_TRUE)); 41809de2952eSStefano Zampini PetscCall(MatSetOption(*coarse_submat, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 41819de2952eSStefano Zampini 41829de2952eSStefano Zampini /* group vertices and constraints by subdomain id */ 41839de2952eSStefano Zampini const PetscInt *vidxs = pcbddc->primal_indices_local_idxs; 41849de2952eSStefano Zampini const PetscInt *cidxs = pcbddc->primal_indices_local_idxs + n_vertices; 41859de2952eSStefano Zampini PetscInt *count_eff, *V_eff_to_V, *C_eff_to_C, *nnz; 41869de2952eSStefano Zampini PetscInt n_el = PetscMax(graph->n_local_subs, 1); 41879de2952eSStefano Zampini 41889de2952eSStefano Zampini PetscCall(PetscCalloc1(2 * n_el, &count_eff)); 41899de2952eSStefano Zampini PetscCall(PetscMalloc1(n_vertices, &V_to_eff_V)); 41909de2952eSStefano Zampini PetscCall(PetscMalloc1(n_constraints, &C_to_eff_C)); 41919de2952eSStefano Zampini for (PetscInt i = 0; i < n_vertices; i++) { 41929de2952eSStefano Zampini PetscInt s = 2 * graph->nodes[vidxs[i]].local_sub; 41939de2952eSStefano Zampini 41949de2952eSStefano Zampini V_to_eff_V[i] = count_eff[s]; 41959de2952eSStefano Zampini count_eff[s] += 1; 41969de2952eSStefano Zampini } 41979de2952eSStefano Zampini for (PetscInt i = 0; i < n_constraints; i++) { 41989de2952eSStefano Zampini PetscInt s = 2 * graph->nodes[cidxs[i]].local_sub + 1; 41999de2952eSStefano Zampini 42009de2952eSStefano Zampini C_to_eff_C[i] = count_eff[s]; 42019de2952eSStefano Zampini count_eff[s] += 1; 42029de2952eSStefano Zampini } 42039de2952eSStefano Zampini 42049de2952eSStefano Zampini /* preallocation */ 42059de2952eSStefano Zampini PetscCall(PetscMalloc1(n_vertices + n_constraints, &nnz)); 42069de2952eSStefano Zampini for (PetscInt i = 0; i < n_vertices; i++) { 42079de2952eSStefano Zampini PetscInt s = 2 * graph->nodes[vidxs[i]].local_sub; 42089de2952eSStefano Zampini 42099de2952eSStefano Zampini nnz[i] = count_eff[s] + count_eff[s + 1]; 42109de2952eSStefano Zampini } 42119de2952eSStefano Zampini for (PetscInt i = 0; i < n_constraints; i++) { 42129de2952eSStefano Zampini PetscInt s = 2 * graph->nodes[cidxs[i]].local_sub; 42139de2952eSStefano Zampini 42149de2952eSStefano Zampini nnz[i + n_vertices] = count_eff[s] + count_eff[s + 1]; 42159de2952eSStefano Zampini } 42169de2952eSStefano Zampini PetscCall(MatSeqAIJSetPreallocation(*coarse_submat, 0, nnz)); 42179de2952eSStefano Zampini PetscCall(PetscFree(nnz)); 42189de2952eSStefano Zampini 42199de2952eSStefano Zampini n_eff_vertices = 0; 42209de2952eSStefano Zampini n_eff_constraints = 0; 42219de2952eSStefano Zampini for (PetscInt i = 0; i < n_el; i++) { 42229de2952eSStefano Zampini n_eff_vertices = PetscMax(n_eff_vertices, count_eff[2 * i]); 42239de2952eSStefano Zampini n_eff_constraints = PetscMax(n_eff_constraints, count_eff[2 * i + 1]); 42249de2952eSStefano Zampini count_eff[2 * i] = 0; 42259de2952eSStefano Zampini count_eff[2 * i + 1] = 0; 42269de2952eSStefano Zampini } 42279de2952eSStefano Zampini 42289de2952eSStefano Zampini const PetscInt *idx; 42299de2952eSStefano Zampini PetscCall(PetscMalloc2(n_el * n_eff_vertices, &V_eff_to_V, n_el * n_eff_constraints, &C_eff_to_C)); 42309de2952eSStefano Zampini 42319de2952eSStefano Zampini for (PetscInt i = 0; i < n_vertices; i++) { 42329de2952eSStefano Zampini const PetscInt e = graph->nodes[vidxs[i]].local_sub; 42339de2952eSStefano Zampini const PetscInt s = 2 * e; 42349de2952eSStefano Zampini 42359de2952eSStefano Zampini V_eff_to_V[e * n_eff_vertices + count_eff[s]] = i; 42369de2952eSStefano Zampini count_eff[s] += 1; 42379de2952eSStefano Zampini } 42389de2952eSStefano Zampini for (PetscInt i = 0; i < n_constraints; i++) { 42399de2952eSStefano Zampini const PetscInt e = graph->nodes[cidxs[i]].local_sub; 42409de2952eSStefano Zampini const PetscInt s = 2 * e + 1; 42419de2952eSStefano Zampini 42429de2952eSStefano Zampini C_eff_to_C[e * n_eff_constraints + count_eff[s]] = i; 42439de2952eSStefano Zampini count_eff[s] += 1; 42449de2952eSStefano Zampini } 42459de2952eSStefano Zampini 42469de2952eSStefano Zampini PetscCall(PetscMalloc1(n_R * n_eff_vertices, &R_eff_V_J)); 42479de2952eSStefano Zampini PetscCall(PetscMalloc1(n_R * n_eff_constraints, &R_eff_C_J)); 42489de2952eSStefano Zampini PetscCall(PetscMalloc1(n_B * n_eff_vertices, &B_eff_V_J)); 42499de2952eSStefano Zampini PetscCall(PetscMalloc1(n_B * n_eff_constraints, &B_eff_C_J)); 42509de2952eSStefano Zampini for (PetscInt i = 0; i < n_R * n_eff_vertices; i++) R_eff_V_J[i] = -1; 42519de2952eSStefano Zampini for (PetscInt i = 0; i < n_R * n_eff_constraints; i++) R_eff_C_J[i] = -1; 42529de2952eSStefano Zampini for (PetscInt i = 0; i < n_B * n_eff_vertices; i++) B_eff_V_J[i] = -1; 42539de2952eSStefano Zampini for (PetscInt i = 0; i < n_B * n_eff_constraints; i++) B_eff_C_J[i] = -1; 42549de2952eSStefano Zampini 42559de2952eSStefano Zampini PetscCall(ISGetIndices(pcbddc->is_R_local, &idx)); 42569de2952eSStefano Zampini for (PetscInt i = 0; i < n_R; i++) { 42579de2952eSStefano Zampini const PetscInt e = graph->nodes[idx[i]].local_sub; 42589de2952eSStefano Zampini const PetscInt s = 2 * e; 42599de2952eSStefano Zampini PetscInt j; 42609de2952eSStefano Zampini 42619de2952eSStefano Zampini for (j = 0; j < count_eff[s]; j++) R_eff_V_J[i * n_eff_vertices + j] = V_eff_to_V[e * n_eff_vertices + j]; 42629de2952eSStefano Zampini for (j = 0; j < count_eff[s + 1]; j++) R_eff_C_J[i * n_eff_constraints + j] = C_eff_to_C[e * n_eff_constraints + j]; 42639de2952eSStefano Zampini } 42649de2952eSStefano Zampini PetscCall(ISRestoreIndices(pcbddc->is_R_local, &idx)); 42659de2952eSStefano Zampini PetscCall(ISGetIndices(pcis->is_B_local, &idx)); 42669de2952eSStefano Zampini for (PetscInt i = 0; i < n_B; i++) { 42679de2952eSStefano Zampini const PetscInt e = graph->nodes[idx[i]].local_sub; 42689de2952eSStefano Zampini const PetscInt s = 2 * e; 42699de2952eSStefano Zampini PetscInt j; 42709de2952eSStefano Zampini 42719de2952eSStefano Zampini for (j = 0; j < count_eff[s]; j++) B_eff_V_J[i * n_eff_vertices + j] = V_eff_to_V[e * n_eff_vertices + j]; 42729de2952eSStefano Zampini for (j = 0; j < count_eff[s + 1]; j++) B_eff_C_J[i * n_eff_constraints + j] = C_eff_to_C[e * n_eff_constraints + j]; 42739de2952eSStefano Zampini } 42749de2952eSStefano Zampini PetscCall(ISRestoreIndices(pcis->is_B_local, &idx)); 42759de2952eSStefano Zampini 42769de2952eSStefano Zampini /* permutation and blocksizes for block invert of S_CC */ 42779de2952eSStefano Zampini PetscInt *idxp; 42789de2952eSStefano Zampini 42799de2952eSStefano Zampini PetscCall(PetscMalloc1(n_constraints, &idxp)); 42809de2952eSStefano Zampini PetscCall(PetscMalloc1(n_el, &C_bss)); 42819de2952eSStefano Zampini n_C_bss = 0; 42829de2952eSStefano Zampini for (PetscInt e = 0, cnt = 0; e < n_el; e++) { 42839de2952eSStefano Zampini const PetscInt nc = count_eff[2 * e + 1]; 42849de2952eSStefano Zampini 42859de2952eSStefano Zampini if (nc) C_bss[n_C_bss++] = nc; 42869de2952eSStefano Zampini for (PetscInt c = 0; c < nc; c++) { idxp[cnt + c] = C_eff_to_C[e * n_eff_constraints + c]; } 42879de2952eSStefano Zampini cnt += nc; 42889de2952eSStefano Zampini } 42899de2952eSStefano Zampini 42909de2952eSStefano Zampini PetscCall(ISCreateGeneral(PETSC_COMM_SELF, n_constraints, idxp, PETSC_OWN_POINTER, &is_C_perm)); 42919de2952eSStefano Zampini 42929de2952eSStefano Zampini PetscCall(PetscFree2(V_eff_to_V, C_eff_to_C)); 42939de2952eSStefano Zampini PetscCall(PetscFree(count_eff)); 42949de2952eSStefano Zampini } else { 42959de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, pcbddc->local_primal_size, pcbddc->local_primal_size, NULL, coarse_submat)); 42969de2952eSStefano Zampini n_eff_constraints = n_constraints; 42979de2952eSStefano Zampini n_eff_vertices = n_vertices; 42989de2952eSStefano Zampini } 429906656605SStefano Zampini 430006656605SStefano Zampini /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */ 43019566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_R, &pc_R)); 43029566063dSJacob Faibussowitsch PetscCall(PCSetUp(pc_R)); 43039566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_R, PCLU, &isLU)); 43049566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_R, PCCHOLESKY, &isCHOL)); 4305ffd830a3SStefano Zampini lda_rhs = n_R; 4306a3df083aSStefano Zampini need_benign_correction = PETSC_FALSE; 43077ebab0bbSStefano Zampini if (isLU || isCHOL) { 43089566063dSJacob Faibussowitsch PetscCall(PCFactorGetMatrix(pc_R, &F)); 4309b334f244SStefano Zampini } else if (sub_schurs && sub_schurs->reuse_solver) { 4310df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 4311d62866d3SStefano Zampini MatFactorType type; 4312d62866d3SStefano Zampini 4313df4d28bfSStefano Zampini F = reuse_solver->F; 43149566063dSJacob Faibussowitsch PetscCall(MatGetFactorType(F, &type)); 4315d62866d3SStefano Zampini if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE; 43167ebab0bbSStefano Zampini if (type == MAT_FACTOR_LU) isLU = PETSC_TRUE; 43179566063dSJacob Faibussowitsch PetscCall(MatGetSize(F, &lda_rhs, NULL)); 431822db5ddcSStefano Zampini need_benign_correction = (PetscBool)(!!reuse_solver->benign_n); 43197ebab0bbSStefano Zampini } else F = NULL; 432006656605SStefano Zampini 4321c58f9fdbSStefano Zampini /* determine if we can use a sparse right-hand side */ 4322c58f9fdbSStefano Zampini sparserhs = PETSC_FALSE; 43239de2952eSStefano Zampini if (F && !multi_element) { 4324ea799195SBarry Smith MatSolverType solver; 4325c58f9fdbSStefano Zampini 43269566063dSJacob Faibussowitsch PetscCall(MatFactorGetSolverType(F, &solver)); 43279566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(solver, MATSOLVERMUMPS, &sparserhs)); 4328c58f9fdbSStefano Zampini } 4329c58f9fdbSStefano Zampini 43305cbda25cSStefano Zampini /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */ 43315cbda25cSStefano Zampini dummy_vec = NULL; 43325cbda25cSStefano Zampini if (need_benign_correction && lda_rhs != n_R && F) { 43339566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N), &dummy_vec)); 43349566063dSJacob Faibussowitsch PetscCall(VecSetSizes(dummy_vec, lda_rhs, PETSC_DECIDE)); 43359566063dSJacob Faibussowitsch PetscCall(VecSetType(dummy_vec, ((PetscObject)pcis->vec1_N)->type_name)); 43365cbda25cSStefano Zampini } 43375cbda25cSStefano Zampini 43389566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_auxmat1)); 43399566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_auxmat2)); 43407ebab0bbSStefano Zampini 43419de2952eSStefano Zampini PetscCall(ISCreateStride(PETSC_COMM_SELF, n_R, 0, 1, &is_R)); 43429de2952eSStefano Zampini PetscCall(ISCreateStride(PETSC_COMM_SELF, n_vertices, 0, 1, &is_V)); 43439de2952eSStefano Zampini PetscCall(ISCreateStride(PETSC_COMM_SELF, n_constraints, n_vertices, 1, &is_C)); 43449de2952eSStefano Zampini PetscCall(ISGetIndices(is_V, &idx_V)); 43459de2952eSStefano Zampini PetscCall(ISGetIndices(is_C, &idx_C)); 43469de2952eSStefano Zampini 434788ebb749SStefano Zampini /* Precompute stuffs needed for preprocessing and application of BDDC*/ 434888ebb749SStefano Zampini if (n_constraints) { 43499de2952eSStefano Zampini Mat C_B; 435006656605SStefano Zampini 435125084f0cSStefano Zampini /* Extract constraints on R nodes: C_{CR} */ 43529de2952eSStefano Zampini PetscCall(MatCreateSubMatrix(pcbddc->ConstraintMatrix, is_C, pcbddc->is_R_local, MAT_INITIAL_MATRIX, &C_CR)); 43539de2952eSStefano Zampini PetscCall(MatCreateSubMatrix(pcbddc->ConstraintMatrix, is_C, pcis->is_B_local, MAT_INITIAL_MATRIX, &C_B)); 435488ebb749SStefano Zampini 435580677318SStefano Zampini /* Assemble local_auxmat2_R = (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */ 435680677318SStefano Zampini /* Assemble pcbddc->local_auxmat2 = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */ 4357c58f9fdbSStefano Zampini if (!sparserhs) { 43589de2952eSStefano Zampini PetscScalar *marr; 43599de2952eSStefano Zampini 43609de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, lda_rhs, n_eff_constraints, NULL, &Brhs)); 43619de2952eSStefano Zampini PetscCall(MatDenseGetArrayWrite(Brhs, &marr)); 436288ebb749SStefano Zampini for (i = 0; i < n_constraints; i++) { 436306656605SStefano Zampini const PetscScalar *row_cmat_values; 436406656605SStefano Zampini const PetscInt *row_cmat_indices; 43659de2952eSStefano Zampini PetscInt size_of_constraint, j, col = C_to_eff_C ? C_to_eff_C[i] : i; 436688ebb749SStefano Zampini 43679566063dSJacob Faibussowitsch PetscCall(MatGetRow(C_CR, i, &size_of_constraint, &row_cmat_indices, &row_cmat_values)); 43689de2952eSStefano Zampini for (j = 0; j < size_of_constraint; j++) marr[row_cmat_indices[j] + col * lda_rhs] = -row_cmat_values[j]; 43699566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(C_CR, i, &size_of_constraint, &row_cmat_indices, &row_cmat_values)); 437006656605SStefano Zampini } 43719de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayWrite(Brhs, &marr)); 4372c58f9fdbSStefano Zampini } else { 4373c58f9fdbSStefano Zampini Mat tC_CR; 4374c58f9fdbSStefano Zampini 43759566063dSJacob Faibussowitsch PetscCall(MatScale(C_CR, -1.0)); 4376c58f9fdbSStefano Zampini if (lda_rhs != n_R) { 4377c58f9fdbSStefano Zampini PetscScalar *aa; 4378c58f9fdbSStefano Zampini PetscInt r, *ii, *jj; 4379c58f9fdbSStefano Zampini PetscBool done; 4380c58f9fdbSStefano Zampini 43819566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(C_CR, 0, PETSC_FALSE, PETSC_FALSE, &r, (const PetscInt **)&ii, (const PetscInt **)&jj, &done)); 438228b400f6SJacob Faibussowitsch PetscCheck(done, PETSC_COMM_SELF, PETSC_ERR_PLIB, "GetRowIJ failed"); 43839566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(C_CR, &aa)); 43849566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, n_constraints, lda_rhs, ii, jj, aa, &tC_CR)); 43859566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(C_CR, 0, PETSC_FALSE, PETSC_FALSE, &r, (const PetscInt **)&ii, (const PetscInt **)&jj, &done)); 438628b400f6SJacob Faibussowitsch PetscCheck(done, PETSC_COMM_SELF, PETSC_ERR_PLIB, "RestoreRowIJ failed"); 4387c58f9fdbSStefano Zampini } else { 43889566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)C_CR)); 4389c58f9fdbSStefano Zampini tC_CR = C_CR; 4390c58f9fdbSStefano Zampini } 43919566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(tC_CR, &Brhs)); 43929566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tC_CR)); 4393c58f9fdbSStefano Zampini } 43949de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, lda_rhs, n_eff_constraints, NULL, &local_auxmat2_R)); 439506656605SStefano Zampini if (F) { 4396a3df083aSStefano Zampini if (need_benign_correction) { 4397df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 4398a3df083aSStefano Zampini 439972b8c272SStefano Zampini /* rhs is already zero on interior dofs, no need to change the rhs */ 44009566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(reuse_solver->benign_save_vals, pcbddc->benign_n)); 4401a3df083aSStefano Zampini } 44029566063dSJacob Faibussowitsch PetscCall(MatMatSolve(F, Brhs, local_auxmat2_R)); 4403a3df083aSStefano Zampini if (need_benign_correction) { 4404a3df083aSStefano Zampini PetscScalar *marr; 4405df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 4406a3df083aSStefano Zampini 44079de2952eSStefano Zampini /* XXX multi_element? */ 44089566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(local_auxmat2_R, &marr)); 44095cbda25cSStefano Zampini if (lda_rhs != n_R) { 44109de2952eSStefano Zampini for (i = 0; i < n_eff_constraints; i++) { 44119566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dummy_vec, marr + i * lda_rhs)); 44129566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, dummy_vec, NULL, PETSC_TRUE, PETSC_TRUE)); 44139566063dSJacob Faibussowitsch PetscCall(VecResetArray(dummy_vec)); 44145cbda25cSStefano Zampini } 44155cbda25cSStefano Zampini } else { 44169de2952eSStefano Zampini for (i = 0; i < n_eff_constraints; i++) { 44179566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, marr + i * lda_rhs)); 44189566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, pcbddc->vec1_R, NULL, PETSC_TRUE, PETSC_TRUE)); 44199566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 4420a3df083aSStefano Zampini } 44215cbda25cSStefano Zampini } 44229566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(local_auxmat2_R, &marr)); 4423a3df083aSStefano Zampini } 442406656605SStefano Zampini } else { 44259de2952eSStefano Zampini const PetscScalar *barr; 442680677318SStefano Zampini PetscScalar *marr; 442780677318SStefano Zampini 44289de2952eSStefano Zampini PetscCall(MatDenseGetArrayRead(Brhs, &barr)); 44299566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(local_auxmat2_R, &marr)); 44309de2952eSStefano Zampini for (i = 0; i < n_eff_constraints; i++) { 44319de2952eSStefano Zampini PetscCall(VecPlaceArray(pcbddc->vec1_R, barr + i * lda_rhs)); 44329566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec2_R, marr + i * lda_rhs)); 44339566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec2_R)); 44349566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec2_R)); 44359566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 44369566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec2_R)); 443706656605SStefano Zampini } 44389de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayRead(Brhs, &barr)); 44399566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(local_auxmat2_R, &marr)); 444006656605SStefano Zampini } 44411baa6e33SBarry Smith if (sparserhs) PetscCall(MatScale(C_CR, -1.0)); 44429566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Brhs)); 44439de2952eSStefano Zampini /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR})^{-1} */ 444480677318SStefano Zampini if (!pcbddc->switch_static) { 44459de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_B, n_eff_constraints, NULL, &pcbddc->local_auxmat2)); 44469de2952eSStefano Zampini for (i = 0; i < n_eff_constraints; i++) { 4447ab2d12f3SJunchao Zhang Vec r, b; 44489566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVecRead(local_auxmat2_R, i, &r)); 44499566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVec(pcbddc->local_auxmat2, i, &b)); 44509566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, r, b, INSERT_VALUES, SCATTER_FORWARD)); 44519566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, r, b, INSERT_VALUES, SCATTER_FORWARD)); 44529566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVec(pcbddc->local_auxmat2, i, &b)); 44539566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVecRead(local_auxmat2_R, i, &r)); 445480677318SStefano Zampini } 44559de2952eSStefano Zampini if (multi_element) { 44569de2952eSStefano Zampini Mat T; 4457ffd830a3SStefano Zampini 44589de2952eSStefano Zampini PetscCall(MatCreateSeqAIJFromDenseExpand(local_auxmat2_R, n_constraints, R_eff_C_J, &T)); 44599de2952eSStefano Zampini PetscCall(MatDestroy(&local_auxmat2_R)); 44609de2952eSStefano Zampini local_auxmat2_R = T; 44619de2952eSStefano Zampini PetscCall(MatCreateSeqAIJFromDenseExpand(pcbddc->local_auxmat2, n_constraints, B_eff_C_J, &T)); 44629de2952eSStefano Zampini PetscCall(MatDestroy(&pcbddc->local_auxmat2)); 44639de2952eSStefano Zampini pcbddc->local_auxmat2 = T; 44649de2952eSStefano Zampini } 44659de2952eSStefano Zampini PetscCall(MatMatMult(C_B, pcbddc->local_auxmat2, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &S_CC)); 44669de2952eSStefano Zampini } else { 44679de2952eSStefano Zampini if (multi_element) { 44689de2952eSStefano Zampini Mat T; 44699de2952eSStefano Zampini 44709de2952eSStefano Zampini PetscCall(MatCreateSeqAIJFromDenseExpand(local_auxmat2_R, n_constraints, R_eff_C_J, &T)); 44719de2952eSStefano Zampini PetscCall(MatDestroy(&local_auxmat2_R)); 44729de2952eSStefano Zampini local_auxmat2_R = T; 44739de2952eSStefano Zampini } 44749de2952eSStefano Zampini if (lda_rhs != n_R) { 44759de2952eSStefano Zampini PetscCall(MatCreateSubMatrix(local_auxmat2_R, is_R, NULL, MAT_INITIAL_MATRIX, &pcbddc->local_auxmat2)); 4476ffd830a3SStefano Zampini } else { 44779566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)local_auxmat2_R)); 447880677318SStefano Zampini pcbddc->local_auxmat2 = local_auxmat2_R; 4479ffd830a3SStefano Zampini } 44809de2952eSStefano Zampini PetscCall(MatMatMult(C_CR, pcbddc->local_auxmat2, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &S_CC)); 448180677318SStefano Zampini } 44829de2952eSStefano Zampini PetscCall(MatScale(S_CC, m_one)); 44839de2952eSStefano Zampini if (multi_element) { 44849de2952eSStefano Zampini Mat T, T2; 44859de2952eSStefano Zampini IS isp, ispi; 44869de2952eSStefano Zampini 44879de2952eSStefano Zampini isp = is_C_perm; 44889de2952eSStefano Zampini 44899de2952eSStefano Zampini PetscCall(ISInvertPermutation(isp, PETSC_DECIDE, &ispi)); 44909de2952eSStefano Zampini PetscCall(MatPermute(S_CC, isp, isp, &T)); 44919de2952eSStefano Zampini PetscCall(MatSeqAIJInvertVariableBlockDiagonalMat(T, n_C_bss, C_bss, &T2)); 44929de2952eSStefano Zampini PetscCall(MatDestroy(&T)); 44939de2952eSStefano Zampini PetscCall(MatDestroy(&S_CC)); 44949de2952eSStefano Zampini PetscCall(MatPermute(T2, ispi, ispi, &S_CC)); 44959de2952eSStefano Zampini PetscCall(MatDestroy(&T2)); 44969de2952eSStefano Zampini PetscCall(ISDestroy(&ispi)); 449780677318SStefano Zampini } else { 44989de2952eSStefano Zampini if (isCHOL) { 44999de2952eSStefano Zampini PetscCall(MatCholeskyFactor(S_CC, NULL, NULL)); 45009de2952eSStefano Zampini } else { 45019de2952eSStefano Zampini PetscCall(MatLUFactor(S_CC, NULL, NULL, NULL)); 450280677318SStefano Zampini } 45039de2952eSStefano Zampini PetscCall(MatSeqDenseInvertFactors_Private(S_CC)); 45049de2952eSStefano Zampini } 450580677318SStefano Zampini /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */ 45069de2952eSStefano Zampini PetscCall(MatMatMult(S_CC, C_B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &pcbddc->local_auxmat1)); 45079566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C_B)); 45089de2952eSStefano Zampini PetscCall(MatSetValuesSubMat(*coarse_submat, S_CC, n_constraints, idx_C, n_constraints, idx_C, INSERT_VALUES)); 4509f4ddd8eeSStefano Zampini } 4510fc227af8SStefano Zampini 4511fc227af8SStefano Zampini /* Get submatrices from subdomain matrix */ 451288ebb749SStefano Zampini if (n_vertices) { 45137ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 45147ebab0bbSStefano Zampini PetscBool oldpin; 45157ebab0bbSStefano Zampini #endif 451606656605SStefano Zampini IS is_aux; 45173a50541eSStefano Zampini 4518b334f244SStefano Zampini if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */ 45196816873aSStefano Zampini IS tis; 45206816873aSStefano Zampini 45219566063dSJacob Faibussowitsch PetscCall(ISDuplicate(pcbddc->is_R_local, &tis)); 45229566063dSJacob Faibussowitsch PetscCall(ISSort(tis)); 45239566063dSJacob Faibussowitsch PetscCall(ISComplement(tis, 0, pcis->n, &is_aux)); 45249566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tis)); 45256816873aSStefano Zampini } else { 45269566063dSJacob Faibussowitsch PetscCall(ISComplement(pcbddc->is_R_local, 0, pcis->n, &is_aux)); 45276816873aSStefano Zampini } 45287ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 4529b470e4b4SRichard Tran Mills oldpin = pcbddc->local_mat->boundtocpu; 45307ebab0bbSStefano Zampini #endif 45319566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(pcbddc->local_mat, PETSC_TRUE)); 45329566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcbddc->is_R_local, is_aux, MAT_INITIAL_MATRIX, &A_RV)); 45339566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, is_aux, pcbddc->is_R_local, MAT_INITIAL_MATRIX, &A_VR)); 45349de2952eSStefano Zampini /* TODO REMOVE: MatMatMult(A_VR,A_RRmA_RV) below may raise an error */ 45359566063dSJacob Faibussowitsch PetscCall(MatConvert(A_VR, MATSEQAIJ, MAT_INPLACE_MATRIX, &A_VR)); 45369566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, is_aux, is_aux, MAT_INITIAL_MATRIX, &A_VV)); 45377ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 45389566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(pcbddc->local_mat, oldpin)); 45397ebab0bbSStefano Zampini #endif 45409566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_aux)); 454188ebb749SStefano Zampini } 45429de2952eSStefano Zampini PetscCall(ISDestroy(&is_C_perm)); 45439de2952eSStefano Zampini PetscCall(PetscFree(C_bss)); 454488ebb749SStefano Zampini 45454f1b2e48SStefano Zampini p0_lidx_I = NULL; 45464f1b2e48SStefano Zampini if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) { 4547d12edf2fSStefano Zampini const PetscInt *idxs; 4548d12edf2fSStefano Zampini 45499566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_I_local, &idxs)); 45509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->benign_n, &p0_lidx_I)); 455148a46eb9SPierre 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])); 45529566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_I_local, &idxs)); 4553d12edf2fSStefano Zampini } 4554d16cbb6bSStefano Zampini 45559de2952eSStefano Zampini /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */ 45569de2952eSStefano Zampini 45579de2952eSStefano Zampini /* Matrices of coarse basis functions (local) */ 45589de2952eSStefano Zampini PetscCall(MatDestroy(&pcbddc->coarse_phi_B)); 45599de2952eSStefano Zampini PetscCall(MatDestroy(&pcbddc->coarse_psi_B)); 45609de2952eSStefano Zampini PetscCall(MatDestroy(&pcbddc->coarse_phi_D)); 45619de2952eSStefano Zampini PetscCall(MatDestroy(&pcbddc->coarse_psi_D)); 45629de2952eSStefano Zampini if (!multi_element) { 45639de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_B, pcbddc->local_primal_size, NULL, &pcbddc->coarse_phi_B)); 45649de2952eSStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_D, pcbddc->local_primal_size, NULL, &pcbddc->coarse_phi_D)); 45659de2952eSStefano Zampini coarse_phi_multi = NULL; 45669de2952eSStefano Zampini } else { /* Create temporary NEST matrix to hold coarse basis functions blocks */ 45679de2952eSStefano Zampini IS is_rows[2] = {pcbddc->is_R_local, NULL}; 45689de2952eSStefano Zampini IS is_cols[2] = {is_V, is_C}; 45699de2952eSStefano Zampini 45709de2952eSStefano Zampini PetscCall(ISCreateGeneral(PETSC_COMM_SELF, n_vertices, pcbddc->local_primal_ref_node, PETSC_USE_POINTER, &is_rows[1])); 45719de2952eSStefano Zampini PetscCall(MatCreateNest(PETSC_COMM_SELF, 2, is_rows, 2, is_cols, NULL, &coarse_phi_multi)); 45729de2952eSStefano Zampini PetscCall(ISDestroy(&is_rows[1])); 45739de2952eSStefano Zampini } 45749de2952eSStefano Zampini 457506656605SStefano Zampini /* vertices */ 457606656605SStefano Zampini if (n_vertices) { 4577c58f9fdbSStefano Zampini PetscBool restoreavr = PETSC_FALSE; 45789de2952eSStefano Zampini Mat A_RRmA_RV = NULL; 457916f15bc4SStefano Zampini 45809de2952eSStefano Zampini PetscCall(MatSetValuesSubMat(*coarse_submat, A_VV, n_vertices, idx_V, n_vertices, idx_V, ADD_VALUES)); 45819de2952eSStefano Zampini PetscCall(MatDestroy(&A_VV)); 458204708bb6SStefano Zampini 458316f15bc4SStefano Zampini if (n_R) { 45849de2952eSStefano Zampini Mat A_RV_bcorr = NULL, S_VV; 458506656605SStefano Zampini 45869566063dSJacob Faibussowitsch PetscCall(MatScale(A_RV, m_one)); 458714393ed6SStefano Zampini if (need_benign_correction) { 458814393ed6SStefano Zampini ISLocalToGlobalMapping RtoN; 458914393ed6SStefano Zampini IS is_p0; 459014393ed6SStefano Zampini PetscInt *idxs_p0, n; 459114393ed6SStefano Zampini 45929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->benign_n, &idxs_p0)); 45939566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local, &RtoN)); 45949566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(RtoN, IS_GTOLM_DROP, pcbddc->benign_n, pcbddc->benign_p0_lidx, &n, idxs_p0)); 459563a3b9bcSJacob 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); 45969566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&RtoN)); 45979566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, n, idxs_p0, PETSC_OWN_POINTER, &is_p0)); 45989566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A_RV, is_p0, NULL, MAT_INITIAL_MATRIX, &A_RV_bcorr)); 45999566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_p0)); 460014393ed6SStefano Zampini } 460114393ed6SStefano Zampini 46029de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, lda_rhs, n_eff_vertices, NULL, &A_RRmA_RV)); 4603c58f9fdbSStefano Zampini if (!sparserhs || need_benign_correction) { 46049de2952eSStefano Zampini if (lda_rhs == n_R && !multi_element) { 46059566063dSJacob Faibussowitsch PetscCall(MatConvert(A_RV, MATDENSE, MAT_INPLACE_MATRIX, &A_RV)); 4606ffd830a3SStefano Zampini } else { 46079de2952eSStefano Zampini Mat T; 4608ca92afb2SStefano Zampini PetscScalar *av, *array; 4609ca92afb2SStefano Zampini const PetscInt *xadj, *adjncy; 4610ca92afb2SStefano Zampini PetscInt n; 4611ca92afb2SStefano Zampini PetscBool flg_row; 4612ffd830a3SStefano Zampini 46139de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, lda_rhs, n_eff_vertices, NULL, &T)); 46149de2952eSStefano Zampini PetscCall(MatDenseGetArrayWrite(T, &array)); 46159566063dSJacob Faibussowitsch PetscCall(MatConvert(A_RV, MATSEQAIJ, MAT_INPLACE_MATRIX, &A_RV)); 46169566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A_RV, 0, PETSC_FALSE, PETSC_FALSE, &n, &xadj, &adjncy, &flg_row)); 46179566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A_RV, &av)); 4618ca92afb2SStefano Zampini for (i = 0; i < n; i++) { 4619ca92afb2SStefano Zampini PetscInt j; 46209de2952eSStefano Zampini for (j = xadj[i]; j < xadj[i + 1]; j++) array[lda_rhs * (V_to_eff_V ? V_to_eff_V[adjncy[j]] : adjncy[j]) + i] = av[j]; 4621ffd830a3SStefano Zampini } 46229566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A_RV, 0, PETSC_FALSE, PETSC_FALSE, &n, &xadj, &adjncy, &flg_row)); 46239de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayWrite(T, &array)); 46249566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RV)); 46259de2952eSStefano Zampini A_RV = T; 4626ffd830a3SStefano Zampini } 4627a3df083aSStefano Zampini if (need_benign_correction) { 4628df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 4629a3df083aSStefano Zampini PetscScalar *marr; 4630a3df083aSStefano Zampini 46319de2952eSStefano Zampini /* XXX multi_element */ 46329566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(A_RV, &marr)); 463314393ed6SStefano Zampini /* need \Phi^T A_RV = (I+L)A_RV, L given by 463414393ed6SStefano Zampini 463514393ed6SStefano Zampini | 0 0 0 | (V) 463614393ed6SStefano Zampini L = | 0 0 -1 | (P-p0) 463714393ed6SStefano Zampini | 0 0 -1 | (p0) 463814393ed6SStefano Zampini 463914393ed6SStefano Zampini */ 4640df4d28bfSStefano Zampini for (i = 0; i < reuse_solver->benign_n; i++) { 464114393ed6SStefano Zampini const PetscScalar *vals; 464214393ed6SStefano Zampini const PetscInt *idxs, *idxs_zero; 464314393ed6SStefano Zampini PetscInt n, j, nz; 464414393ed6SStefano Zampini 46459566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i], &nz)); 46469566063dSJacob Faibussowitsch PetscCall(ISGetIndices(reuse_solver->benign_zerodiag_subs[i], &idxs_zero)); 46479566063dSJacob Faibussowitsch PetscCall(MatGetRow(A_RV_bcorr, i, &n, &idxs, &vals)); 464814393ed6SStefano Zampini for (j = 0; j < n; j++) { 464914393ed6SStefano Zampini PetscScalar val = vals[j]; 465014393ed6SStefano Zampini PetscInt k, col = idxs[j]; 465114393ed6SStefano Zampini for (k = 0; k < nz; k++) marr[idxs_zero[k] + lda_rhs * col] -= val; 465214393ed6SStefano Zampini } 46539566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(A_RV_bcorr, i, &n, &idxs, &vals)); 46549566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i], &idxs_zero)); 465514393ed6SStefano Zampini } 46569566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(A_RV, &marr)); 465772b8c272SStefano Zampini } 46589566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A_RV)); 4659c58f9fdbSStefano Zampini Brhs = A_RV; 4660c58f9fdbSStefano Zampini } else { 4661c58f9fdbSStefano Zampini Mat tA_RVT, A_RVT; 4662c58f9fdbSStefano Zampini 4663c58f9fdbSStefano Zampini if (!pcbddc->symmetric_primal) { 4664fb6280fbSStefano Zampini /* A_RV already scaled by -1 */ 46659566063dSJacob Faibussowitsch PetscCall(MatTranspose(A_RV, MAT_INITIAL_MATRIX, &A_RVT)); 4666c58f9fdbSStefano Zampini } else { 4667c58f9fdbSStefano Zampini restoreavr = PETSC_TRUE; 46689566063dSJacob Faibussowitsch PetscCall(MatScale(A_VR, -1.0)); 46699566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A_VR)); 4670c58f9fdbSStefano Zampini A_RVT = A_VR; 4671c58f9fdbSStefano Zampini } 4672c58f9fdbSStefano Zampini if (lda_rhs != n_R) { 4673c58f9fdbSStefano Zampini PetscScalar *aa; 4674c58f9fdbSStefano Zampini PetscInt r, *ii, *jj; 4675c58f9fdbSStefano Zampini PetscBool done; 4676c58f9fdbSStefano Zampini 46779566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A_RVT, 0, PETSC_FALSE, PETSC_FALSE, &r, (const PetscInt **)&ii, (const PetscInt **)&jj, &done)); 467828b400f6SJacob Faibussowitsch PetscCheck(done, PETSC_COMM_SELF, PETSC_ERR_PLIB, "GetRowIJ failed"); 46799566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A_RVT, &aa)); 46809566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, n_vertices, lda_rhs, ii, jj, aa, &tA_RVT)); 46819566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A_RVT, 0, PETSC_FALSE, PETSC_FALSE, &r, (const PetscInt **)&ii, (const PetscInt **)&jj, &done)); 468228b400f6SJacob Faibussowitsch PetscCheck(done, PETSC_COMM_SELF, PETSC_ERR_PLIB, "RestoreRowIJ failed"); 4683c58f9fdbSStefano Zampini } else { 46849566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A_RVT)); 4685c58f9fdbSStefano Zampini tA_RVT = A_RVT; 4686c58f9fdbSStefano Zampini } 46879566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(tA_RVT, &Brhs)); 46889566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tA_RVT)); 46899566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RVT)); 4690c58f9fdbSStefano Zampini } 469172b8c272SStefano Zampini if (F) { 469214393ed6SStefano Zampini /* need to correct the rhs */ 469372b8c272SStefano Zampini if (need_benign_correction) { 469472b8c272SStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 469572b8c272SStefano Zampini PetscScalar *marr; 469672b8c272SStefano Zampini 46979566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(Brhs, &marr)); 46985cbda25cSStefano Zampini if (lda_rhs != n_R) { 46999de2952eSStefano Zampini for (i = 0; i < n_eff_vertices; i++) { 47009566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dummy_vec, marr + i * lda_rhs)); 47019566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, dummy_vec, NULL, PETSC_FALSE, PETSC_TRUE)); 47029566063dSJacob Faibussowitsch PetscCall(VecResetArray(dummy_vec)); 47035cbda25cSStefano Zampini } 47045cbda25cSStefano Zampini } else { 47059de2952eSStefano Zampini for (i = 0; i < n_eff_vertices; i++) { 47069566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, marr + i * lda_rhs)); 47079566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, pcbddc->vec1_R, NULL, PETSC_FALSE, PETSC_TRUE)); 47089566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 4709a3df083aSStefano Zampini } 47105cbda25cSStefano Zampini } 47119566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(Brhs, &marr)); 4712a3df083aSStefano Zampini } 47139566063dSJacob Faibussowitsch PetscCall(MatMatSolve(F, Brhs, A_RRmA_RV)); 47141baa6e33SBarry Smith if (restoreavr) PetscCall(MatScale(A_VR, -1.0)); 471514393ed6SStefano Zampini /* need to correct the solution */ 4716a3df083aSStefano Zampini if (need_benign_correction) { 4717df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 4718a3df083aSStefano Zampini PetscScalar *marr; 4719a3df083aSStefano Zampini 47209566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(A_RRmA_RV, &marr)); 47215cbda25cSStefano Zampini if (lda_rhs != n_R) { 47229de2952eSStefano Zampini for (i = 0; i < n_eff_vertices; i++) { 47239566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dummy_vec, marr + i * lda_rhs)); 47249566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, dummy_vec, NULL, PETSC_TRUE, PETSC_TRUE)); 47259566063dSJacob Faibussowitsch PetscCall(VecResetArray(dummy_vec)); 47265cbda25cSStefano Zampini } 47275cbda25cSStefano Zampini } else { 47289de2952eSStefano Zampini for (i = 0; i < n_eff_vertices; i++) { 47299566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, marr + i * lda_rhs)); 47309566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, pcbddc->vec1_R, NULL, PETSC_TRUE, PETSC_TRUE)); 47319566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 4732a3df083aSStefano Zampini } 47335cbda25cSStefano Zampini } 47349566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(A_RRmA_RV, &marr)); 4735a3df083aSStefano Zampini } 473606656605SStefano Zampini } else { 47379de2952eSStefano Zampini const PetscScalar *barr; 47389de2952eSStefano Zampini PetscScalar *marr; 47399de2952eSStefano Zampini 47409de2952eSStefano Zampini PetscCall(MatDenseGetArrayRead(Brhs, &barr)); 47419de2952eSStefano Zampini PetscCall(MatDenseGetArray(A_RRmA_RV, &marr)); 47429de2952eSStefano Zampini for (i = 0; i < n_eff_vertices; i++) { 47439de2952eSStefano Zampini PetscCall(VecPlaceArray(pcbddc->vec1_R, barr + i * lda_rhs)); 47449de2952eSStefano Zampini PetscCall(VecPlaceArray(pcbddc->vec2_R, marr + i * lda_rhs)); 47459566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec2_R)); 47469566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec2_R)); 47479566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 47489566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec2_R)); 474906656605SStefano Zampini } 47509de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayRead(Brhs, &barr)); 47519de2952eSStefano Zampini PetscCall(MatDenseRestoreArray(A_RRmA_RV, &marr)); 475206656605SStefano Zampini } 47539566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RV)); 47549566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Brhs)); 4755ffd830a3SStefano Zampini /* S_VV and S_CV */ 475606656605SStefano Zampini if (n_constraints) { 475706656605SStefano Zampini Mat B; 475880677318SStefano Zampini 47599de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_B, n_eff_vertices, NULL, &B)); 47609de2952eSStefano Zampini PetscCall(MatDenseScatter(A_RRmA_RV, pcbddc->R_to_B, B)); 47619de2952eSStefano Zampini 47629de2952eSStefano Zampini /* S_CV = pcbddc->local_auxmat1 * B */ 47639de2952eSStefano Zampini if (multi_element) { 47649de2952eSStefano Zampini Mat T; 47659de2952eSStefano Zampini 47669de2952eSStefano Zampini PetscCall(MatCreateSeqAIJFromDenseExpand(B, n_vertices, B_eff_V_J, &T)); 47679de2952eSStefano Zampini PetscCall(MatDestroy(&B)); 47689de2952eSStefano Zampini B = T; 476980677318SStefano Zampini } 47709de2952eSStefano Zampini PetscCall(MatProductCreate(pcbddc->local_auxmat1, B, NULL, &S_CV)); 47719566063dSJacob Faibussowitsch PetscCall(MatProductSetType(S_CV, MATPRODUCT_AB)); 47729566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(S_CV)); 47739566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(S_CV)); 47749566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(S_CV)); 47759566063dSJacob Faibussowitsch PetscCall(MatProductClear(S_CV)); 47769566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 47779de2952eSStefano Zampini 47789de2952eSStefano Zampini /* B = local_auxmat2_R * S_CV */ 47799de2952eSStefano Zampini PetscCall(MatProductCreate(local_auxmat2_R, S_CV, NULL, &B)); 47809566063dSJacob Faibussowitsch PetscCall(MatProductSetType(B, MATPRODUCT_AB)); 47819566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(B)); 47829566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(B)); 47839566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(B)); 47844222ddf1SHong Zhang 47859566063dSJacob Faibussowitsch PetscCall(MatScale(S_CV, m_one)); 47869de2952eSStefano Zampini PetscCall(MatSetValuesSubMat(*coarse_submat, S_CV, n_constraints, idx_C, n_vertices, idx_V, INSERT_VALUES)); 478714393ed6SStefano Zampini 47889de2952eSStefano Zampini if (multi_element) { 47899de2952eSStefano Zampini Mat T; 47909de2952eSStefano Zampini 47919de2952eSStefano Zampini PetscCall(MatCreateSeqAIJFromDenseExpand(A_RRmA_RV, n_vertices, R_eff_V_J, &T)); 47929de2952eSStefano Zampini PetscCall(MatDestroy(&A_RRmA_RV)); 47939de2952eSStefano Zampini A_RRmA_RV = T; 47949de2952eSStefano Zampini } 47959de2952eSStefano Zampini PetscCall(MatAXPY(A_RRmA_RV, 1.0, B, UNKNOWN_NONZERO_PATTERN)); /* XXX ? */ 47969de2952eSStefano Zampini PetscCall(MatDestroy(&B)); 47979de2952eSStefano Zampini } else if (multi_element) { 47989de2952eSStefano Zampini Mat T; 47999de2952eSStefano Zampini 48009de2952eSStefano Zampini PetscCall(MatCreateSeqAIJFromDenseExpand(A_RRmA_RV, n_vertices, R_eff_V_J, &T)); 48019de2952eSStefano Zampini PetscCall(MatDestroy(&A_RRmA_RV)); 48029de2952eSStefano Zampini A_RRmA_RV = T; 48039de2952eSStefano Zampini } 48049de2952eSStefano Zampini 48059de2952eSStefano Zampini if (lda_rhs != n_R) { 48069de2952eSStefano Zampini Mat T; 48079de2952eSStefano Zampini 48089de2952eSStefano Zampini PetscCall(MatCreateSubMatrix(A_RRmA_RV, is_R, NULL, MAT_INITIAL_MATRIX, &T)); 48099de2952eSStefano Zampini PetscCall(MatDestroy(&A_RRmA_RV)); 48109de2952eSStefano Zampini A_RRmA_RV = T; 48119de2952eSStefano Zampini } 48129de2952eSStefano Zampini 48139de2952eSStefano Zampini /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */ 48149de2952eSStefano Zampini if (need_benign_correction) { /* XXX SPARSE */ 48159de2952eSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 48169de2952eSStefano Zampini PetscScalar *sums; 48179de2952eSStefano Zampini const PetscScalar *marr; 48189de2952eSStefano Zampini 48199de2952eSStefano Zampini PetscCall(MatDenseGetArrayRead(A_RRmA_RV, &marr)); 48209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_vertices, &sums)); 4821df4d28bfSStefano Zampini for (i = 0; i < reuse_solver->benign_n; i++) { 482214393ed6SStefano Zampini const PetscScalar *vals; 482314393ed6SStefano Zampini const PetscInt *idxs, *idxs_zero; 482414393ed6SStefano Zampini PetscInt n, j, nz; 482514393ed6SStefano Zampini 48269566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i], &nz)); 48279566063dSJacob Faibussowitsch PetscCall(ISGetIndices(reuse_solver->benign_zerodiag_subs[i], &idxs_zero)); 482814393ed6SStefano Zampini for (j = 0; j < n_vertices; j++) { 482914393ed6SStefano Zampini sums[j] = 0.; 48309de2952eSStefano Zampini for (PetscInt k = 0; k < nz; k++) sums[j] += marr[idxs_zero[k] + j * n_R]; 483114393ed6SStefano Zampini } 48329566063dSJacob Faibussowitsch PetscCall(MatGetRow(A_RV_bcorr, i, &n, &idxs, &vals)); 483314393ed6SStefano Zampini for (j = 0; j < n; j++) { 483414393ed6SStefano Zampini PetscScalar val = vals[j]; 48359de2952eSStefano Zampini for (PetscInt k = 0; k < n_vertices; k++) PetscCall(MatSetValue(*coarse_submat, idx_V[idxs[j]], idx_V[k], val * sums[k], ADD_VALUES)); 483614393ed6SStefano Zampini } 48379566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(A_RV_bcorr, i, &n, &idxs, &vals)); 48389566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i], &idxs_zero)); 483914393ed6SStefano Zampini } 48409566063dSJacob Faibussowitsch PetscCall(PetscFree(sums)); 48419566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RV_bcorr)); 48429de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayRead(A_RRmA_RV, &marr)); 484314393ed6SStefano Zampini } 48449de2952eSStefano Zampini 48459de2952eSStefano Zampini PetscCall(MatMatMult(A_VR, A_RRmA_RV, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &S_VV)); 48469de2952eSStefano Zampini PetscCall(MatSetValuesSubMat(*coarse_submat, S_VV, n_vertices, idx_V, n_vertices, idx_V, ADD_VALUES)); 48479de2952eSStefano Zampini PetscCall(MatDestroy(&S_VV)); 4848d16cbb6bSStefano Zampini } 4849d16cbb6bSStefano Zampini 485006656605SStefano Zampini /* coarse basis functions */ 48519de2952eSStefano Zampini if (coarse_phi_multi) { 48529de2952eSStefano Zampini Mat Vid; 485316f15bc4SStefano Zampini 48549de2952eSStefano Zampini PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, n_vertices, n_vertices, 1, NULL, &Vid)); 48559de2952eSStefano Zampini PetscCall(MatShift_Basic(Vid, 1.0)); 48569de2952eSStefano Zampini PetscCall(MatNestSetSubMat(coarse_phi_multi, 0, 0, A_RRmA_RV)); 48579de2952eSStefano Zampini PetscCall(MatNestSetSubMat(coarse_phi_multi, 1, 0, Vid)); 48589de2952eSStefano Zampini PetscCall(MatDestroy(&Vid)); 48599de2952eSStefano Zampini } else { 48609de2952eSStefano Zampini if (A_RRmA_RV) { 48619de2952eSStefano Zampini PetscCall(MatDenseScatter(A_RRmA_RV, pcbddc->R_to_B, pcbddc->coarse_phi_B)); 486206656605SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 48639de2952eSStefano Zampini PetscCall(MatDenseScatter(A_RRmA_RV, pcbddc->R_to_D, pcbddc->coarse_phi_D)); 48649de2952eSStefano Zampini if (pcbddc->benign_n) { 48659de2952eSStefano Zampini for (i = 0; i < n_vertices; i++) { PetscCall(MatSetValues(pcbddc->coarse_phi_D, pcbddc->benign_n, p0_lidx_I, 1, &i, NULL, INSERT_VALUES)); } 4866ab2d12f3SJunchao Zhang } 486706656605SStefano Zampini } 486806656605SStefano Zampini } 48699de2952eSStefano Zampini for (i = 0; i < n_vertices; i++) PetscCall(MatSetValues(pcbddc->coarse_phi_B, 1, &idx_V_B[i], 1, &i, &one, INSERT_VALUES)); 48709de2952eSStefano Zampini PetscCall(MatAssemblyBegin(pcbddc->coarse_phi_B, MAT_FINAL_ASSEMBLY)); 48719de2952eSStefano Zampini PetscCall(MatAssemblyEnd(pcbddc->coarse_phi_B, MAT_FINAL_ASSEMBLY)); 48729de2952eSStefano Zampini } 48739de2952eSStefano Zampini PetscCall(MatDestroy(&A_RRmA_RV)); 48749de2952eSStefano Zampini } 48759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RV)); 48769566063dSJacob Faibussowitsch PetscCall(VecDestroy(&dummy_vec)); 487706656605SStefano Zampini 487806656605SStefano Zampini if (n_constraints) { 48799de2952eSStefano Zampini Mat B, B2; 488006656605SStefano Zampini 48819566063dSJacob Faibussowitsch PetscCall(MatScale(S_CC, m_one)); 48829de2952eSStefano Zampini PetscCall(MatProductCreate(local_auxmat2_R, S_CC, NULL, &B)); 48839566063dSJacob Faibussowitsch PetscCall(MatProductSetType(B, MATPRODUCT_AB)); 48849566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(B)); 48859566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(B)); 48869566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(B)); 4887a961b312SStefano Zampini 488806656605SStefano Zampini if (n_vertices) { 488903dfb2d7SStefano Zampini if (isCHOL || need_benign_correction) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */ 48909de2952eSStefano Zampini PetscCall(MatTranspose(S_CV, MAT_INITIAL_MATRIX, &S_VC)); 489180677318SStefano Zampini } else { 4892ffd830a3SStefano Zampini if (lda_rhs != n_R) { 48939de2952eSStefano Zampini Mat tB; 489406656605SStefano Zampini 48959de2952eSStefano Zampini PetscCall(MatCreateSubMatrix(B, is_R, NULL, MAT_INITIAL_MATRIX, &tB)); 48969de2952eSStefano Zampini PetscCall(MatDestroy(&B)); 48979de2952eSStefano Zampini B = tB; 48989de2952eSStefano Zampini } 48999de2952eSStefano Zampini PetscCall(MatMatMult(A_VR, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &S_VC)); 49009de2952eSStefano Zampini } 49019de2952eSStefano Zampini PetscCall(MatSetValuesSubMat(*coarse_submat, S_VC, n_vertices, idx_V, n_constraints, idx_C, INSERT_VALUES)); 49029de2952eSStefano Zampini } 49039de2952eSStefano Zampini 49049de2952eSStefano Zampini /* coarse basis functions */ 49059de2952eSStefano Zampini if (coarse_phi_multi) { 49069de2952eSStefano Zampini PetscCall(MatNestSetSubMat(coarse_phi_multi, 0, 1, B)); 49079de2952eSStefano Zampini } else { 49089de2952eSStefano Zampini PetscCall(MatDenseGetSubMatrix(pcbddc->coarse_phi_B, PETSC_DECIDE, PETSC_DECIDE, n_vertices, n_vertices + n_constraints, &B2)); 49099de2952eSStefano Zampini PetscCall(MatDenseScatter(B, pcbddc->R_to_B, B2)); 49109de2952eSStefano Zampini PetscCall(MatDenseRestoreSubMatrix(pcbddc->coarse_phi_B, &B2)); 491106656605SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 49129de2952eSStefano Zampini PetscCall(MatDenseGetSubMatrix(pcbddc->coarse_phi_D, PETSC_DECIDE, PETSC_DECIDE, n_vertices, n_vertices + n_constraints, &B2)); 49139de2952eSStefano Zampini PetscCall(MatDenseScatter(B, pcbddc->R_to_D, B2)); 49149de2952eSStefano Zampini if (pcbddc->benign_n) { 49159de2952eSStefano Zampini for (i = 0; i < n_constraints; i++) { PetscCall(MatSetValues(B2, pcbddc->benign_n, p0_lidx_I, 1, &i, NULL, INSERT_VALUES)); } 491606656605SStefano Zampini } 49179de2952eSStefano Zampini PetscCall(MatDenseRestoreSubMatrix(pcbddc->coarse_phi_D, &B2)); 491806656605SStefano Zampini } 491906656605SStefano Zampini } 49209de2952eSStefano Zampini PetscCall(MatDestroy(&B)); 49219de2952eSStefano Zampini } 49229de2952eSStefano Zampini 49239de2952eSStefano Zampini /* assemble sparse coarse basis functions */ 49249de2952eSStefano Zampini if (coarse_phi_multi) { 49259de2952eSStefano Zampini Mat T; 49269de2952eSStefano Zampini 49279de2952eSStefano Zampini PetscCall(MatConvert(coarse_phi_multi, MATSEQAIJ, MAT_INITIAL_MATRIX, &T)); 49289de2952eSStefano Zampini PetscCall(MatDestroy(&coarse_phi_multi)); 49299de2952eSStefano Zampini PetscCall(MatCreateSubMatrix(T, pcis->is_B_local, NULL, MAT_INITIAL_MATRIX, &pcbddc->coarse_phi_B)); 49309de2952eSStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { PetscCall(MatCreateSubMatrix(T, pcis->is_I_local, NULL, MAT_INITIAL_MATRIX, &pcbddc->coarse_phi_D)); } 49319de2952eSStefano Zampini PetscCall(MatDestroy(&T)); 49329de2952eSStefano Zampini } 49339de2952eSStefano Zampini PetscCall(MatDestroy(&local_auxmat2_R)); 49349566063dSJacob Faibussowitsch PetscCall(PetscFree(p0_lidx_I)); 493572b8c272SStefano Zampini 493672b8c272SStefano Zampini /* coarse matrix entries relative to B_0 */ 493772b8c272SStefano Zampini if (pcbddc->benign_n) { 493872b8c272SStefano Zampini Mat B0_B, B0_BPHI; 493972b8c272SStefano Zampini IS is_dummy; 49401683a169SBarry Smith const PetscScalar *data; 494172b8c272SStefano Zampini PetscInt j; 494272b8c272SStefano Zampini 49439566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pcbddc->benign_n, 0, 1, &is_dummy)); 49449566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->benign_B0, is_dummy, pcis->is_B_local, MAT_INITIAL_MATRIX, &B0_B)); 49459566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_dummy)); 49469566063dSJacob Faibussowitsch PetscCall(MatMatMult(B0_B, pcbddc->coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &B0_BPHI)); 49479566063dSJacob Faibussowitsch PetscCall(MatConvert(B0_BPHI, MATSEQDENSE, MAT_INPLACE_MATRIX, &B0_BPHI)); 49489566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(B0_BPHI, &data)); 494972b8c272SStefano Zampini for (j = 0; j < pcbddc->benign_n; j++) { 495072b8c272SStefano Zampini PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j; 495172b8c272SStefano Zampini for (i = 0; i < pcbddc->local_primal_size; i++) { 49529de2952eSStefano Zampini PetscCall(MatSetValue(*coarse_submat, primal_idx, i, data[i * pcbddc->benign_n + j], INSERT_VALUES)); 49539de2952eSStefano Zampini PetscCall(MatSetValue(*coarse_submat, i, primal_idx, data[i * pcbddc->benign_n + j], INSERT_VALUES)); 495472b8c272SStefano Zampini } 495572b8c272SStefano Zampini } 49569566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(B0_BPHI, &data)); 49579566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B0_B)); 49589566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B0_BPHI)); 495972b8c272SStefano Zampini } 4960019a44ceSStefano Zampini 496106656605SStefano Zampini /* compute other basis functions for non-symmetric problems */ 49623301b35fSStefano Zampini if (!pcbddc->symmetric_primal) { 4963ffd830a3SStefano Zampini Mat B_V = NULL, B_C = NULL; 49649de2952eSStefano Zampini PetscScalar *marray, *work; 496506656605SStefano Zampini 49669de2952eSStefano Zampini /* TODO multi_element MatDenseScatter */ 496706656605SStefano Zampini if (n_constraints) { 4968ffd830a3SStefano Zampini Mat S_CCT, C_CRT; 496906656605SStefano Zampini 49709de2952eSStefano Zampini PetscCall(MatScale(S_CC, m_one)); 49719566063dSJacob Faibussowitsch PetscCall(MatTranspose(C_CR, MAT_INITIAL_MATRIX, &C_CRT)); 49729566063dSJacob Faibussowitsch PetscCall(MatTranspose(S_CC, MAT_INITIAL_MATRIX, &S_CCT)); 49739566063dSJacob Faibussowitsch PetscCall(MatMatMult(C_CRT, S_CCT, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &B_C)); 49749de2952eSStefano Zampini PetscCall(MatConvert(B_C, MATDENSE, MAT_INPLACE_MATRIX, &B_C)); 49759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_CCT)); 497606656605SStefano Zampini if (n_vertices) { 4977ffd830a3SStefano Zampini Mat S_VCT; 497806656605SStefano Zampini 49799566063dSJacob Faibussowitsch PetscCall(MatTranspose(S_VC, MAT_INITIAL_MATRIX, &S_VCT)); 49809566063dSJacob Faibussowitsch PetscCall(MatMatMult(C_CRT, S_VCT, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &B_V)); 49819566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_VCT)); 49829de2952eSStefano Zampini PetscCall(MatConvert(B_V, MATDENSE, MAT_INPLACE_MATRIX, &B_V)); 498306656605SStefano Zampini } 49849566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C_CRT)); 49855b782168SStefano Zampini } else { 49869566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_R, n_vertices, NULL, &B_V)); 498706656605SStefano Zampini } 498816f15bc4SStefano Zampini if (n_vertices && n_R) { 4989ffd830a3SStefano Zampini PetscScalar *av, *marray; 4990ffd830a3SStefano Zampini const PetscInt *xadj, *adjncy; 4991ffd830a3SStefano Zampini PetscInt n; 4992ffd830a3SStefano Zampini PetscBool flg_row; 499306656605SStefano Zampini 4994ffd830a3SStefano Zampini /* B_V = B_V - A_VR^T */ 49959566063dSJacob Faibussowitsch PetscCall(MatConvert(A_VR, MATSEQAIJ, MAT_INPLACE_MATRIX, &A_VR)); 49969566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A_VR, 0, PETSC_FALSE, PETSC_FALSE, &n, &xadj, &adjncy, &flg_row)); 49979566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A_VR, &av)); 49989566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(B_V, &marray)); 4999ffd830a3SStefano Zampini for (i = 0; i < n; i++) { 5000ffd830a3SStefano Zampini PetscInt j; 5001ffd830a3SStefano Zampini for (j = xadj[i]; j < xadj[i + 1]; j++) marray[i * n_R + adjncy[j]] -= av[j]; 5002ffd830a3SStefano Zampini } 50039566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(B_V, &marray)); 50049566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A_VR, 0, PETSC_FALSE, PETSC_FALSE, &n, &xadj, &adjncy, &flg_row)); 50059566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_VR)); 500606656605SStefano Zampini } 500706656605SStefano Zampini 5008ffd830a3SStefano Zampini /* currently there's no support for MatTransposeMatSolve(F,B,X) */ 50099de2952eSStefano Zampini PetscCall(PetscMalloc1(n_R * pcbddc->local_primal_size, &work)); 5010abc8f43dSstefano_zampini if (n_vertices) { 50119566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(B_V, &marray)); 5012ffd830a3SStefano Zampini for (i = 0; i < n_vertices; i++) { 50139566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, marray + i * n_R)); 50149566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec2_R, work + i * n_R)); 50159566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec2_R)); 50169566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec2_R)); 50179566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 50189566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec2_R)); 501906656605SStefano Zampini } 50209566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(B_V, &marray)); 5021abc8f43dSstefano_zampini } 50225b782168SStefano Zampini if (B_C) { 50239566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(B_C, &marray)); 5024ffd830a3SStefano Zampini for (i = n_vertices; i < n_constraints + n_vertices; i++) { 50259566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, marray + (i - n_vertices) * n_R)); 50269566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec2_R, work + i * n_R)); 50279566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec2_R)); 50289566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec2_R)); 50299566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 50309566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec2_R)); 503106656605SStefano Zampini } 50329566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(B_C, &marray)); 50335b782168SStefano Zampini } 503406656605SStefano Zampini /* coarse basis functions */ 50359de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_B, pcbddc->local_primal_size, NULL, &pcbddc->coarse_psi_B)); 50369de2952eSStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_D, pcbddc->local_primal_size, NULL, &pcbddc->coarse_psi_D)); 503706656605SStefano Zampini for (i = 0; i < pcbddc->local_primal_size; i++) { 5038ab2d12f3SJunchao Zhang Vec v; 503906656605SStefano Zampini 50409566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, work + i * n_R)); 50419566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVec(pcbddc->coarse_psi_B, i, &v)); 50429566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 50439566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 504406656605SStefano Zampini if (i < n_vertices) { 5045ab2d12f3SJunchao Zhang PetscScalar one = 1.0; 50469566063dSJacob Faibussowitsch PetscCall(VecSetValues(v, 1, &idx_V_B[i], &one, INSERT_VALUES)); 50479566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(v)); 50489566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(v)); 504906656605SStefano Zampini } 50509566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_psi_B, i, &v)); 505106656605SStefano Zampini 505206656605SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 50539566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVec(pcbddc->coarse_psi_D, i, &v)); 50549566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_D, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 50559566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_D, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 50569566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_psi_D, i, &v)); 505706656605SStefano Zampini } 50589566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 505906656605SStefano Zampini } 50609566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B_V)); 50619566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B_C)); 50629de2952eSStefano Zampini PetscCall(PetscFree(work)); 50639de2952eSStefano Zampini } else { 50649de2952eSStefano Zampini PetscCall(PetscObjectReference((PetscObject)pcbddc->coarse_phi_B)); 50659de2952eSStefano Zampini pcbddc->coarse_psi_B = pcbddc->coarse_phi_B; 50669de2952eSStefano Zampini PetscCall(PetscObjectReference((PetscObject)pcbddc->coarse_phi_D)); 50679de2952eSStefano Zampini pcbddc->coarse_psi_D = pcbddc->coarse_phi_D; 506806656605SStefano Zampini } 50699de2952eSStefano Zampini PetscCall(MatAssemblyBegin(*coarse_submat, MAT_FINAL_ASSEMBLY)); 50709de2952eSStefano Zampini PetscCall(MatAssemblyEnd(*coarse_submat, MAT_FINAL_ASSEMBLY)); 5071a6e023c1Sstefano_zampini 5072d62866d3SStefano Zampini /* free memory */ 50739de2952eSStefano Zampini PetscCall(PetscFree(V_to_eff_V)); 50749de2952eSStefano Zampini PetscCall(PetscFree(C_to_eff_C)); 50759de2952eSStefano Zampini PetscCall(PetscFree(R_eff_V_J)); 50769de2952eSStefano Zampini PetscCall(PetscFree(R_eff_C_J)); 50779de2952eSStefano Zampini PetscCall(PetscFree(B_eff_V_J)); 50789de2952eSStefano Zampini PetscCall(PetscFree(B_eff_C_J)); 50799de2952eSStefano Zampini PetscCall(ISDestroy(&is_R)); 50809de2952eSStefano Zampini PetscCall(ISRestoreIndices(is_V, &idx_V)); 50819de2952eSStefano Zampini PetscCall(ISRestoreIndices(is_C, &idx_C)); 50829de2952eSStefano Zampini PetscCall(ISDestroy(&is_V)); 50839de2952eSStefano Zampini PetscCall(ISDestroy(&is_C)); 50849566063dSJacob Faibussowitsch PetscCall(PetscFree(idx_V_B)); 50859566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_CV)); 50869566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_VC)); 50879566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_CC)); 508848a46eb9SPierre Jolivet if (n_vertices) PetscCall(MatDestroy(&A_VR)); 508948a46eb9SPierre Jolivet if (n_constraints) PetscCall(MatDestroy(&C_CR)); 50909566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_CorrectionSetUp[pcbddc->current_level], pc, 0, 0, 0)); 50918ead10e4SStefano Zampini 5092da81f932SPierre Jolivet /* Checking coarse_sub_mat and coarse basis functions */ 509388ebb749SStefano Zampini /* Symmetric case : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */ 509488ebb749SStefano Zampini /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */ 5095d12edf2fSStefano Zampini if (pcbddc->dbg_flag) { 509625084f0cSStefano Zampini Mat AUXMAT, TM1, TM2, TM3, TM4; 509788ebb749SStefano Zampini Mat coarse_phi_D, coarse_phi_B; 509888ebb749SStefano Zampini Mat coarse_psi_D, coarse_psi_B; 509988ebb749SStefano Zampini Mat A_II, A_BB, A_IB, A_BI; 51008bec7fa6SStefano Zampini Mat C_B, CPHI; 51018bec7fa6SStefano Zampini IS is_dummy; 51028bec7fa6SStefano Zampini Vec mones; 510388ebb749SStefano Zampini MatType checkmattype = MATSEQAIJ; 510488ebb749SStefano Zampini PetscReal real_value; 510588ebb749SStefano Zampini 5106a3df083aSStefano Zampini if (pcbddc->benign_n && !pcbddc->benign_change_explicit) { 5107a3df083aSStefano Zampini Mat A; 51089566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignProject(pc, NULL, NULL, &A)); 51099566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, pcis->is_I_local, pcis->is_I_local, MAT_INITIAL_MATRIX, &A_II)); 51109566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, pcis->is_I_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &A_IB)); 51119566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, pcis->is_B_local, pcis->is_I_local, MAT_INITIAL_MATRIX, &A_BI)); 51129566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, pcis->is_B_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &A_BB)); 51139566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 5114a3df083aSStefano Zampini } else { 51159566063dSJacob Faibussowitsch PetscCall(MatConvert(pcis->A_II, checkmattype, MAT_INITIAL_MATRIX, &A_II)); 51169566063dSJacob Faibussowitsch PetscCall(MatConvert(pcis->A_IB, checkmattype, MAT_INITIAL_MATRIX, &A_IB)); 51179566063dSJacob Faibussowitsch PetscCall(MatConvert(pcis->A_BI, checkmattype, MAT_INITIAL_MATRIX, &A_BI)); 51189566063dSJacob Faibussowitsch PetscCall(MatConvert(pcis->A_BB, checkmattype, MAT_INITIAL_MATRIX, &A_BB)); 5119a3df083aSStefano Zampini } 51209566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->coarse_phi_D, checkmattype, MAT_INITIAL_MATRIX, &coarse_phi_D)); 51219566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->coarse_phi_B, checkmattype, MAT_INITIAL_MATRIX, &coarse_phi_B)); 5122ffd830a3SStefano Zampini if (!pcbddc->symmetric_primal) { 51239566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->coarse_psi_D, checkmattype, MAT_INITIAL_MATRIX, &coarse_psi_D)); 51249566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->coarse_psi_B, checkmattype, MAT_INITIAL_MATRIX, &coarse_psi_B)); 512588ebb749SStefano Zampini } 51269566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 51279566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Check coarse sub mat computation (symmetric %d)\n", pcbddc->symmetric_primal)); 51289566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 5129ffd830a3SStefano Zampini if (!pcbddc->symmetric_primal) { 51309566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_II, coarse_phi_D, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 51319566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_psi_D, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM1)); 51329566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 51339566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_BB, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 51349566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_psi_B, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM2)); 51359566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 51369566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_IB, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 51379566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_psi_D, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM3)); 51389566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 51399566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_BI, coarse_phi_D, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 51409566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_psi_B, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM4)); 51419566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 514288ebb749SStefano Zampini } else { 51439566063dSJacob Faibussowitsch PetscCall(MatPtAP(A_II, coarse_phi_D, MAT_INITIAL_MATRIX, 1.0, &TM1)); 51449566063dSJacob Faibussowitsch PetscCall(MatPtAP(A_BB, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &TM2)); 51459566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_IB, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 51469566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_phi_D, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM3)); 51479566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 51489566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_BI, coarse_phi_D, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 51499566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_phi_B, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM4)); 51509566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 515188ebb749SStefano Zampini } 51529566063dSJacob Faibussowitsch PetscCall(MatAXPY(TM1, one, TM2, DIFFERENT_NONZERO_PATTERN)); 51539566063dSJacob Faibussowitsch PetscCall(MatAXPY(TM1, one, TM3, DIFFERENT_NONZERO_PATTERN)); 51549566063dSJacob Faibussowitsch PetscCall(MatAXPY(TM1, one, TM4, DIFFERENT_NONZERO_PATTERN)); 51559566063dSJacob Faibussowitsch PetscCall(MatConvert(TM1, MATSEQDENSE, MAT_INPLACE_MATRIX, &TM1)); 51564f1b2e48SStefano Zampini if (pcbddc->benign_n) { 5157fc227af8SStefano Zampini Mat B0_B, B0_BPHI; 51581683a169SBarry Smith const PetscScalar *data2; 51591683a169SBarry Smith PetscScalar *data; 51604f1b2e48SStefano Zampini PetscInt j; 5161d12edf2fSStefano Zampini 51629566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pcbddc->benign_n, 0, 1, &is_dummy)); 51639566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->benign_B0, is_dummy, pcis->is_B_local, MAT_INITIAL_MATRIX, &B0_B)); 51649566063dSJacob Faibussowitsch PetscCall(MatMatMult(B0_B, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &B0_BPHI)); 51659566063dSJacob Faibussowitsch PetscCall(MatConvert(B0_BPHI, MATSEQDENSE, MAT_INPLACE_MATRIX, &B0_BPHI)); 51669566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(TM1, &data)); 51679566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(B0_BPHI, &data2)); 51684f1b2e48SStefano Zampini for (j = 0; j < pcbddc->benign_n; j++) { 51694f1b2e48SStefano Zampini PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j; 5170d12edf2fSStefano Zampini for (i = 0; i < pcbddc->local_primal_size; i++) { 51714f1b2e48SStefano Zampini data[primal_idx * pcbddc->local_primal_size + i] += data2[i * pcbddc->benign_n + j]; 51724f1b2e48SStefano Zampini data[i * pcbddc->local_primal_size + primal_idx] += data2[i * pcbddc->benign_n + j]; 51734f1b2e48SStefano Zampini } 5174d12edf2fSStefano Zampini } 51759566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(TM1, &data)); 51769566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(B0_BPHI, &data2)); 51779566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B0_B)); 51789566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_dummy)); 51799566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B0_BPHI)); 5180d12edf2fSStefano Zampini } 51819de2952eSStefano Zampini PetscCall(MatAXPY(TM1, m_one, *coarse_submat, DIFFERENT_NONZERO_PATTERN)); 51829566063dSJacob Faibussowitsch PetscCall(MatNorm(TM1, NORM_FROBENIUS, &real_value)); 51839566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 518463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d matrix error % 1.14e\n", PetscGlobalRank, (double)real_value)); 51858bec7fa6SStefano Zampini 51868bec7fa6SStefano Zampini /* check constraints */ 51879566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pcbddc->local_primal_size - pcbddc->benign_n, 0, 1, &is_dummy)); 51889566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->ConstraintMatrix, is_dummy, pcis->is_B_local, MAT_INITIAL_MATRIX, &C_B)); 51894f1b2e48SStefano Zampini if (!pcbddc->benign_n) { /* TODO: add benign case */ 51909566063dSJacob Faibussowitsch PetscCall(MatMatMult(C_B, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &CPHI)); 5191a00504b5SStefano Zampini } else { 5192a00504b5SStefano Zampini PetscScalar *data; 5193a00504b5SStefano Zampini Mat tmat; 51949566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(pcbddc->coarse_phi_B, &data)); 51959566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, pcis->n_B, pcbddc->local_primal_size - pcbddc->benign_n, data, &tmat)); 51969566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(pcbddc->coarse_phi_B, &data)); 51979566063dSJacob Faibussowitsch PetscCall(MatMatMult(C_B, tmat, MAT_INITIAL_MATRIX, 1.0, &CPHI)); 51989566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tmat)); 5199a00504b5SStefano Zampini } 52009566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(CPHI, &mones, NULL)); 52019566063dSJacob Faibussowitsch PetscCall(VecSet(mones, -1.0)); 52029566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(CPHI, mones, ADD_VALUES)); 52039566063dSJacob Faibussowitsch PetscCall(MatNorm(CPHI, NORM_FROBENIUS, &real_value)); 520463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d phi constraints error % 1.14e\n", PetscGlobalRank, (double)real_value)); 5205ffd830a3SStefano Zampini if (!pcbddc->symmetric_primal) { 52069566063dSJacob Faibussowitsch PetscCall(MatMatMult(C_B, coarse_psi_B, MAT_REUSE_MATRIX, 1.0, &CPHI)); 52079566063dSJacob Faibussowitsch PetscCall(VecSet(mones, -1.0)); 52089566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(CPHI, mones, ADD_VALUES)); 52099566063dSJacob Faibussowitsch PetscCall(MatNorm(CPHI, NORM_FROBENIUS, &real_value)); 521063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d psi constraints error % 1.14e\n", PetscGlobalRank, (double)real_value)); 521188ebb749SStefano Zampini } 52129566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C_B)); 52139566063dSJacob Faibussowitsch PetscCall(MatDestroy(&CPHI)); 52149566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_dummy)); 52159566063dSJacob Faibussowitsch PetscCall(VecDestroy(&mones)); 52169566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 52179566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_II)); 52189566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_BB)); 52199566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_IB)); 52209566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_BI)); 52219566063dSJacob Faibussowitsch PetscCall(MatDestroy(&TM1)); 52229566063dSJacob Faibussowitsch PetscCall(MatDestroy(&TM2)); 52239566063dSJacob Faibussowitsch PetscCall(MatDestroy(&TM3)); 52249566063dSJacob Faibussowitsch PetscCall(MatDestroy(&TM4)); 52259566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_phi_D)); 52269566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_phi_B)); 5227ffd830a3SStefano Zampini if (!pcbddc->symmetric_primal) { 52289566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_psi_D)); 52299566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_psi_B)); 523088ebb749SStefano Zampini } 523188ebb749SStefano Zampini } 52327ebab0bbSStefano Zampini 52339de2952eSStefano Zampini #if 0 52349de2952eSStefano Zampini { 52359de2952eSStefano Zampini PetscViewer viewer; 52369de2952eSStefano Zampini char filename[256]; 52379de2952eSStefano Zampini 52389de2952eSStefano Zampini PetscCall(PetscSNPrintf(filename, PETSC_STATIC_ARRAY_LENGTH(filename), "details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level)); 52399de2952eSStefano Zampini PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer)); 52409de2952eSStefano Zampini PetscCall(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB)); 52419de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)*coarse_submat,"coarse submat")); 52429de2952eSStefano Zampini PetscCall(MatView(*coarse_submat,viewer)); 52439de2952eSStefano Zampini if (pcbddc->coarse_phi_B) { 52449de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B")); 52459de2952eSStefano Zampini PetscCall(MatView(pcbddc->coarse_phi_B,viewer)); 52469de2952eSStefano Zampini } 52479de2952eSStefano Zampini if (pcbddc->coarse_phi_D) { 52489de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D")); 52499de2952eSStefano Zampini PetscCall(MatView(pcbddc->coarse_phi_D,viewer)); 52509de2952eSStefano Zampini } 52519de2952eSStefano Zampini if (pcbddc->coarse_psi_B) { 52529de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B")); 52539de2952eSStefano Zampini PetscCall(MatView(pcbddc->coarse_psi_B,viewer)); 52549de2952eSStefano Zampini } 52559de2952eSStefano Zampini if (pcbddc->coarse_psi_D) { 52569de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D")); 52579de2952eSStefano Zampini PetscCall(MatView(pcbddc->coarse_psi_D,viewer)); 52589de2952eSStefano Zampini } 52599de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcbddc->local_mat,"A")); 52609de2952eSStefano Zampini PetscCall(MatView(pcbddc->local_mat,viewer)); 52619de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcbddc->ConstraintMatrix,"C")); 52629de2952eSStefano Zampini PetscCall(MatView(pcbddc->ConstraintMatrix,viewer)); 52639de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcis->is_I_local,"I")); 52649de2952eSStefano Zampini PetscCall(ISView(pcis->is_I_local,viewer)); 52659de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcis->is_B_local,"B")); 52669de2952eSStefano Zampini PetscCall(ISView(pcis->is_B_local,viewer)); 52679de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcbddc->is_R_local,"R")); 52689de2952eSStefano Zampini PetscCall(ISView(pcbddc->is_R_local,viewer)); 52699de2952eSStefano Zampini PetscCall(PetscOptionsRestoreViewer(&viewer)); 52709de2952eSStefano Zampini } 52719de2952eSStefano Zampini #endif 52729de2952eSStefano Zampini 52739de2952eSStefano Zampini /* device support */ 52749de2952eSStefano Zampini { 52759de2952eSStefano Zampini PetscBool iscuda, iship, iskokkos; 52769de2952eSStefano Zampini MatType mtype = NULL; 52779de2952eSStefano Zampini 52789de2952eSStefano Zampini PetscCall(PetscObjectTypeCompareAny((PetscObject)pcis->vec1_N, &iscuda, VECCUDA, VECMPICUDA, VECSEQCUDA, "")); 52799de2952eSStefano Zampini PetscCall(PetscObjectTypeCompareAny((PetscObject)pcis->vec1_N, &iship, VECHIP, VECMPIHIP, VECSEQHIP, "")); 52809de2952eSStefano Zampini PetscCall(PetscObjectTypeCompareAny((PetscObject)pcis->vec1_N, &iskokkos, VECKOKKOS, VECMPIKOKKOS, VECSEQKOKKOS, "")); 52819de2952eSStefano Zampini if (iskokkos) { 52829de2952eSStefano Zampini if (PetscDefined(HAVE_MACRO_KOKKOS_ENABLE_CUDA)) iscuda = PETSC_TRUE; 52839de2952eSStefano Zampini else if (PetscDefined(HAVE_MACRO_KOKKOS_ENABLE_HIP)) iship = PETSC_TRUE; 52849de2952eSStefano Zampini } 52859de2952eSStefano Zampini if (iskokkos) mtype = multi_element ? MATSEQAIJKOKKOS : (iscuda ? MATSEQDENSECUDA : MATSEQDENSEHIP); 52869de2952eSStefano Zampini else if (iship) mtype = multi_element ? MATSEQAIJHIPSPARSE : MATSEQDENSEHIP; 52879de2952eSStefano Zampini else if (iscuda) mtype = multi_element ? MATSEQAIJCUSPARSE : MATSEQDENSECUDA; 52889de2952eSStefano Zampini if (mtype) { 52899de2952eSStefano Zampini if (pcbddc->local_auxmat1) PetscCall(MatConvert(pcbddc->local_auxmat1, mtype, MAT_INPLACE_MATRIX, &pcbddc->local_auxmat1)); 52909de2952eSStefano Zampini if (pcbddc->local_auxmat2) PetscCall(MatConvert(pcbddc->local_auxmat2, mtype, MAT_INPLACE_MATRIX, &pcbddc->local_auxmat2)); 52919de2952eSStefano Zampini if (pcbddc->coarse_phi_B) PetscCall(MatConvert(pcbddc->coarse_phi_B, mtype, MAT_INPLACE_MATRIX, &pcbddc->coarse_phi_B)); 52929de2952eSStefano Zampini if (pcbddc->coarse_phi_D) PetscCall(MatConvert(pcbddc->coarse_phi_D, mtype, MAT_INPLACE_MATRIX, &pcbddc->coarse_phi_D)); 52939de2952eSStefano Zampini if (pcbddc->coarse_psi_B) PetscCall(MatConvert(pcbddc->coarse_psi_B, mtype, MAT_INPLACE_MATRIX, &pcbddc->coarse_psi_B)); 52949de2952eSStefano Zampini if (pcbddc->coarse_psi_D) PetscCall(MatConvert(pcbddc->coarse_psi_D, mtype, MAT_INPLACE_MATRIX, &pcbddc->coarse_psi_D)); 52957ebab0bbSStefano Zampini } 52967ebab0bbSStefano Zampini } 52973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 529888ebb749SStefano Zampini } 529988ebb749SStefano Zampini 5300d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat *B) 5301d71ae5a4SJacob Faibussowitsch { 5302d65f70fdSStefano Zampini Mat *work_mat; 5303d65f70fdSStefano Zampini IS isrow_s, iscol_s; 5304d65f70fdSStefano Zampini PetscBool rsorted, csorted; 5305c43ebad9SStefano Zampini PetscInt rsize, *idxs_perm_r = NULL, csize, *idxs_perm_c = NULL; 5306aa0d41d4SStefano Zampini 5307aa0d41d4SStefano Zampini PetscFunctionBegin; 53089566063dSJacob Faibussowitsch PetscCall(ISSorted(isrow, &rsorted)); 53099566063dSJacob Faibussowitsch PetscCall(ISSorted(iscol, &csorted)); 53109566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isrow, &rsize)); 53119566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(iscol, &csize)); 5312aa0d41d4SStefano Zampini 5313d65f70fdSStefano Zampini if (!rsorted) { 5314906d46d4SStefano Zampini const PetscInt *idxs; 5315906d46d4SStefano Zampini PetscInt *idxs_sorted, i; 5316aa0d41d4SStefano Zampini 53179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rsize, &idxs_perm_r)); 53189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rsize, &idxs_sorted)); 5319ad540459SPierre Jolivet for (i = 0; i < rsize; i++) idxs_perm_r[i] = i; 53209566063dSJacob Faibussowitsch PetscCall(ISGetIndices(isrow, &idxs)); 53219566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithPermutation(rsize, idxs, idxs_perm_r)); 5322ad540459SPierre Jolivet for (i = 0; i < rsize; i++) idxs_sorted[i] = idxs[idxs_perm_r[i]]; 53239566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(isrow, &idxs)); 53249566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, rsize, idxs_sorted, PETSC_OWN_POINTER, &isrow_s)); 5325d65f70fdSStefano Zampini } else { 53269566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)isrow)); 5327d65f70fdSStefano Zampini isrow_s = isrow; 5328aa0d41d4SStefano Zampini } 5329906d46d4SStefano Zampini 5330d65f70fdSStefano Zampini if (!csorted) { 5331d65f70fdSStefano Zampini if (isrow == iscol) { 53329566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)isrow_s)); 5333d65f70fdSStefano Zampini iscol_s = isrow_s; 5334d65f70fdSStefano Zampini } else { 5335d65f70fdSStefano Zampini const PetscInt *idxs; 5336d65f70fdSStefano Zampini PetscInt *idxs_sorted, i; 5337906d46d4SStefano Zampini 53389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(csize, &idxs_perm_c)); 53399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(csize, &idxs_sorted)); 5340ad540459SPierre Jolivet for (i = 0; i < csize; i++) idxs_perm_c[i] = i; 53419566063dSJacob Faibussowitsch PetscCall(ISGetIndices(iscol, &idxs)); 53429566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithPermutation(csize, idxs, idxs_perm_c)); 5343ad540459SPierre Jolivet for (i = 0; i < csize; i++) idxs_sorted[i] = idxs[idxs_perm_c[i]]; 53449566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(iscol, &idxs)); 53459566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, csize, idxs_sorted, PETSC_OWN_POINTER, &iscol_s)); 5346d65f70fdSStefano Zampini } 5347d65f70fdSStefano Zampini } else { 53489566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)iscol)); 5349d65f70fdSStefano Zampini iscol_s = iscol; 5350d65f70fdSStefano Zampini } 5351d65f70fdSStefano Zampini 53529566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(A, 1, &isrow_s, &iscol_s, MAT_INITIAL_MATRIX, &work_mat)); 5353d65f70fdSStefano Zampini 5354d65f70fdSStefano Zampini if (!rsorted || !csorted) { 5355906d46d4SStefano Zampini Mat new_mat; 5356d65f70fdSStefano Zampini IS is_perm_r, is_perm_c; 5357906d46d4SStefano Zampini 5358d65f70fdSStefano Zampini if (!rsorted) { 5359d65f70fdSStefano Zampini PetscInt *idxs_r, i; 53609566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rsize, &idxs_r)); 5361ad540459SPierre Jolivet for (i = 0; i < rsize; i++) idxs_r[idxs_perm_r[i]] = i; 53629566063dSJacob Faibussowitsch PetscCall(PetscFree(idxs_perm_r)); 53639566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, rsize, idxs_r, PETSC_OWN_POINTER, &is_perm_r)); 5364d65f70fdSStefano Zampini } else { 53659566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, rsize, 0, 1, &is_perm_r)); 5366906d46d4SStefano Zampini } 53679566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(is_perm_r)); 5368d65f70fdSStefano Zampini 5369d65f70fdSStefano Zampini if (!csorted) { 5370d65f70fdSStefano Zampini if (isrow_s == iscol_s) { 53719566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is_perm_r)); 5372d65f70fdSStefano Zampini is_perm_c = is_perm_r; 5373d65f70fdSStefano Zampini } else { 5374d65f70fdSStefano Zampini PetscInt *idxs_c, i; 537528b400f6SJacob Faibussowitsch PetscCheck(idxs_perm_c, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Permutation array not present"); 53769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(csize, &idxs_c)); 5377ad540459SPierre Jolivet for (i = 0; i < csize; i++) idxs_c[idxs_perm_c[i]] = i; 53789566063dSJacob Faibussowitsch PetscCall(PetscFree(idxs_perm_c)); 53799566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, csize, idxs_c, PETSC_OWN_POINTER, &is_perm_c)); 5380d65f70fdSStefano Zampini } 5381d65f70fdSStefano Zampini } else { 53829566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, csize, 0, 1, &is_perm_c)); 5383d65f70fdSStefano Zampini } 53849566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(is_perm_c)); 5385d65f70fdSStefano Zampini 53869566063dSJacob Faibussowitsch PetscCall(MatPermute(work_mat[0], is_perm_r, is_perm_c, &new_mat)); 53879566063dSJacob Faibussowitsch PetscCall(MatDestroy(&work_mat[0])); 5388d65f70fdSStefano Zampini work_mat[0] = new_mat; 53899566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_perm_r)); 53909566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_perm_c)); 5391d65f70fdSStefano Zampini } 5392d65f70fdSStefano Zampini 53939566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)work_mat[0])); 5394d65f70fdSStefano Zampini *B = work_mat[0]; 53959566063dSJacob Faibussowitsch PetscCall(MatDestroyMatrices(1, &work_mat)); 53969566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isrow_s)); 53979566063dSJacob Faibussowitsch PetscCall(ISDestroy(&iscol_s)); 53983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5399d65f70fdSStefano Zampini } 5400d65f70fdSStefano Zampini 5401d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix) 5402d71ae5a4SJacob Faibussowitsch { 5403aa0d41d4SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 54045e8657edSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 5405022d8d2bSstefano_zampini Mat new_mat, lA; 54065e8657edSStefano Zampini IS is_local, is_global; 5407d65f70fdSStefano Zampini PetscInt local_size; 5408b94d7dedSBarry Smith PetscBool isseqaij, issym, isset; 5409aa0d41d4SStefano Zampini 5410aa0d41d4SStefano Zampini PetscFunctionBegin; 54119566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 54129566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A, &local_size, NULL)); 54139de2952eSStefano Zampini if (pcbddc->mat_graph->multi_element) { 54149de2952eSStefano Zampini Mat *mats, *bdiags; 54159de2952eSStefano Zampini IS *gsubs; 54169de2952eSStefano Zampini PetscInt nsubs = pcbddc->n_local_subs; 54179de2952eSStefano Zampini 54189de2952eSStefano Zampini PetscCall(PetscCalloc1(nsubs * nsubs, &mats)); 54199de2952eSStefano Zampini PetscCall(PetscMalloc1(nsubs, &gsubs)); 54209de2952eSStefano Zampini for (PetscInt i = 0; i < nsubs; i++) PetscCall(ISLocalToGlobalMappingApplyIS(matis->rmapping, pcbddc->local_subs[i], &gsubs[i])); 54219de2952eSStefano Zampini PetscCall(MatCreateSubMatrices(ChangeOfBasisMatrix, nsubs, gsubs, gsubs, MAT_INITIAL_MATRIX, &bdiags)); 54229de2952eSStefano Zampini for (PetscInt i = 0; i < nsubs; i++) PetscCall(ISDestroy(&gsubs[i])); 54239de2952eSStefano Zampini PetscCall(PetscFree(gsubs)); 54249de2952eSStefano Zampini 54259de2952eSStefano Zampini for (PetscInt i = 0; i < nsubs; i++) mats[i * (1 + nsubs)] = bdiags[i]; 54269de2952eSStefano Zampini PetscCall(MatCreateNest(PETSC_COMM_SELF, nsubs, pcbddc->local_subs, nsubs, pcbddc->local_subs, mats, &new_mat)); 54279de2952eSStefano Zampini PetscCall(MatConvert(new_mat, MATSEQAIJ, MAT_INPLACE_MATRIX, &new_mat)); 54289de2952eSStefano Zampini PetscCall(MatDestroySubMatrices(nsubs, &bdiags)); 54299de2952eSStefano Zampini PetscCall(PetscFree(mats)); 54309de2952eSStefano Zampini } else { 54319566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)matis->A), local_size, 0, 1, &is_local)); 54329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(matis->rmapping, is_local, &is_global)); 54339566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_local)); 54349566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrixUnsorted(ChangeOfBasisMatrix, is_global, is_global, &new_mat)); 54359566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_global)); 54369de2952eSStefano Zampini } 5437906d46d4SStefano Zampini if (pcbddc->dbg_flag) { 5438906d46d4SStefano Zampini Vec x, x_change; 5439906d46d4SStefano Zampini PetscReal error; 5440906d46d4SStefano Zampini 54419566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(ChangeOfBasisMatrix, &x, &x_change)); 54429566063dSJacob Faibussowitsch PetscCall(VecSetRandom(x, NULL)); 54439566063dSJacob Faibussowitsch PetscCall(MatMult(ChangeOfBasisMatrix, x, x_change)); 54449566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->cctx, x, matis->x, INSERT_VALUES, SCATTER_FORWARD)); 54459566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->cctx, x, matis->x, INSERT_VALUES, SCATTER_FORWARD)); 54469566063dSJacob Faibussowitsch PetscCall(MatMult(new_mat, matis->x, matis->y)); 544788428137SStefano Zampini if (!pcbddc->change_interior) { 544888428137SStefano Zampini const PetscScalar *x, *y, *v; 544988428137SStefano Zampini PetscReal lerror = 0.; 545088428137SStefano Zampini PetscInt i; 545188428137SStefano Zampini 54529566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(matis->x, &x)); 54539566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(matis->y, &y)); 54549566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(matis->counter, &v)); 545588428137SStefano Zampini for (i = 0; i < local_size; i++) 54569371c9d4SSatish Balay if (PetscRealPart(v[i]) < 1.5 && PetscAbsScalar(x[i] - y[i]) > lerror) lerror = PetscAbsScalar(x[i] - y[i]); 54579566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(matis->x, &x)); 54589566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(matis->y, &y)); 54599566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(matis->counter, &v)); 54601c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&lerror, &error, 1, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)pc))); 5461637e8532SStefano Zampini if (error > PETSC_SMALL) { 5462637e8532SStefano Zampini if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) { 546363a3b9bcSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_PLIB, "Error global vs local change on I: %1.6e", (double)error); 5464637e8532SStefano Zampini } else { 546563a3b9bcSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "Error global vs local change on I: %1.6e", (double)error); 5466637e8532SStefano Zampini } 5467637e8532SStefano Zampini } 546888428137SStefano Zampini } 54699566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, matis->y, x, INSERT_VALUES, SCATTER_REVERSE)); 54709566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, matis->y, x, INSERT_VALUES, SCATTER_REVERSE)); 54719566063dSJacob Faibussowitsch PetscCall(VecAXPY(x, -1.0, x_change)); 54729566063dSJacob Faibussowitsch PetscCall(VecNorm(x, NORM_INFINITY, &error)); 5473637e8532SStefano Zampini if (error > PETSC_SMALL) { 5474637e8532SStefano Zampini if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) { 547563a3b9bcSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_PLIB, "Error global vs local change on N: %1.6e", (double)error); 5476637e8532SStefano Zampini } else { 547763a3b9bcSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "Error global vs local change on N: %1.6e", (double)error); 5478637e8532SStefano Zampini } 5479637e8532SStefano Zampini } 54809566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 54819566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x_change)); 5482906d46d4SStefano Zampini } 5483906d46d4SStefano Zampini 5484022d8d2bSstefano_zampini /* lA is present if we are setting up an inner BDDC for a saddle point FETI-DP */ 54859566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lA", (PetscObject *)&lA)); 5486022d8d2bSstefano_zampini 548722d5777bSStefano Zampini /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */ 54889566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQAIJ, &isseqaij)); 548922d5777bSStefano Zampini if (isseqaij) { 54909566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 54919566063dSJacob Faibussowitsch PetscCall(MatPtAP(matis->A, new_mat, MAT_INITIAL_MATRIX, 2.0, &pcbddc->local_mat)); 5492022d8d2bSstefano_zampini if (lA) { 5493022d8d2bSstefano_zampini Mat work; 54949566063dSJacob Faibussowitsch PetscCall(MatPtAP(lA, new_mat, MAT_INITIAL_MATRIX, 2.0, &work)); 54959566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_lA", (PetscObject)work)); 54969566063dSJacob Faibussowitsch PetscCall(MatDestroy(&work)); 5497022d8d2bSstefano_zampini } 5498aa0d41d4SStefano Zampini } else { 5499a00504b5SStefano Zampini Mat work_mat; 55001cf9b237SStefano Zampini 55019566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 55029566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &work_mat)); 55039566063dSJacob Faibussowitsch PetscCall(MatPtAP(work_mat, new_mat, MAT_INITIAL_MATRIX, 2.0, &pcbddc->local_mat)); 55049566063dSJacob Faibussowitsch PetscCall(MatDestroy(&work_mat)); 5505022d8d2bSstefano_zampini if (lA) { 5506022d8d2bSstefano_zampini Mat work; 55079566063dSJacob Faibussowitsch PetscCall(MatConvert(lA, MATSEQAIJ, MAT_INITIAL_MATRIX, &work_mat)); 55089566063dSJacob Faibussowitsch PetscCall(MatPtAP(work_mat, new_mat, MAT_INITIAL_MATRIX, 2.0, &work)); 55099566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_lA", (PetscObject)work)); 55109566063dSJacob Faibussowitsch PetscCall(MatDestroy(&work)); 5511022d8d2bSstefano_zampini } 5512aa0d41d4SStefano Zampini } 5513b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(matis->A, &isset, &issym)); 5514b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(pcbddc->local_mat, MAT_SYMMETRIC, issym)); 55159566063dSJacob Faibussowitsch PetscCall(MatDestroy(&new_mat)); 55163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5517aa0d41d4SStefano Zampini } 5518aa0d41d4SStefano Zampini 5519d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpLocalScatters(PC pc) 5520d71ae5a4SJacob Faibussowitsch { 5521f4f49eeaSPierre Jolivet PC_IS *pcis = (PC_IS *)pc->data; 5522a64d13efSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 5523d62866d3SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 552453892102SStefano Zampini PetscInt *idx_R_local = NULL; 55253a50541eSStefano Zampini PetscInt n_vertices, i, j, n_R, n_D, n_B; 55263a50541eSStefano Zampini PetscInt vbs, bs; 55276816873aSStefano Zampini PetscBT bitmask = NULL; 5528a64d13efSStefano Zampini 5529a64d13efSStefano Zampini PetscFunctionBegin; 5530b23d619eSStefano Zampini /* 5531b23d619eSStefano Zampini No need to setup local scatters if 5532b23d619eSStefano Zampini - primal space is unchanged 5533b23d619eSStefano Zampini AND 5534b23d619eSStefano Zampini - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains) 5535b23d619eSStefano Zampini AND 5536b23d619eSStefano Zampini - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine 5537b23d619eSStefano Zampini */ 55383ba16761SJacob Faibussowitsch if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) PetscFunctionReturn(PETSC_SUCCESS); 5539f4ddd8eeSStefano Zampini /* destroy old objects */ 55409566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->is_R_local)); 55419566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->R_to_B)); 55429566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->R_to_D)); 5543a64d13efSStefano Zampini /* Set Non-overlapping dimensions */ 5544b371cd4fSStefano Zampini n_B = pcis->n_B; 5545b371cd4fSStefano Zampini n_D = pcis->n - n_B; 5546b371cd4fSStefano Zampini n_vertices = pcbddc->n_vertices; 55473a50541eSStefano Zampini 5548e602f447SPierre Jolivet /* Dohrmann's notation: dofs split in R (Remaining: all dofs but the vertices) and V (Vertices) */ 55496816873aSStefano Zampini 555053892102SStefano Zampini /* create auxiliary bitmask and allocate workspace */ 5551b334f244SStefano Zampini if (!sub_schurs || !sub_schurs->reuse_solver) { 55529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n - n_vertices, &idx_R_local)); 55539566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(pcis->n, &bitmask)); 555448a46eb9SPierre Jolivet for (i = 0; i < n_vertices; i++) PetscCall(PetscBTSet(bitmask, pcbddc->local_primal_ref_node[i])); 55554641a718SStefano Zampini 5556a64d13efSStefano Zampini for (i = 0, n_R = 0; i < pcis->n; i++) { 5557ad540459SPierre Jolivet if (!PetscBTLookup(bitmask, i)) idx_R_local[n_R++] = i; 5558a64d13efSStefano Zampini } 5559df4d28bfSStefano Zampini } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */ 5560df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 55616816873aSStefano Zampini 55629566063dSJacob Faibussowitsch PetscCall(ISGetIndices(reuse_solver->is_R, (const PetscInt **)&idx_R_local)); 55639566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(reuse_solver->is_R, &n_R)); 55646816873aSStefano Zampini } 55653a50541eSStefano Zampini 55663a50541eSStefano Zampini /* Block code */ 55673a50541eSStefano Zampini vbs = 1; 55689566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(pcbddc->local_mat, &bs)); 55693a50541eSStefano Zampini if (bs > 1 && !(n_vertices % bs)) { 55703a50541eSStefano Zampini PetscBool is_blocked = PETSC_TRUE; 55713a50541eSStefano Zampini PetscInt *vary; 5572b334f244SStefano Zampini if (!sub_schurs || !sub_schurs->reuse_solver) { 55739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n / bs, &vary)); 55749566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(vary, pcis->n / bs)); 5575d3df7717SStefano Zampini /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */ 5576d3df7717SStefano 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 */ 55770e6343abSStefano Zampini for (i = 0; i < n_vertices; i++) vary[pcbddc->local_primal_ref_node[i] / bs]++; 5578d3df7717SStefano Zampini for (i = 0; i < pcis->n / bs; i++) { 55793a50541eSStefano Zampini if (vary[i] != 0 && vary[i] != bs) { 55803a50541eSStefano Zampini is_blocked = PETSC_FALSE; 55813a50541eSStefano Zampini break; 55823a50541eSStefano Zampini } 55833a50541eSStefano Zampini } 55849566063dSJacob Faibussowitsch PetscCall(PetscFree(vary)); 5585d3df7717SStefano Zampini } else { 5586d3df7717SStefano Zampini /* Verify directly the R set */ 5587d3df7717SStefano Zampini for (i = 0; i < n_R / bs; i++) { 5588d3df7717SStefano Zampini PetscInt j, node = idx_R_local[bs * i]; 5589d3df7717SStefano Zampini for (j = 1; j < bs; j++) { 5590d3df7717SStefano Zampini if (node != idx_R_local[bs * i + j] - j) { 5591d3df7717SStefano Zampini is_blocked = PETSC_FALSE; 5592d3df7717SStefano Zampini break; 5593d3df7717SStefano Zampini } 5594d3df7717SStefano Zampini } 5595d3df7717SStefano Zampini } 5596d3df7717SStefano Zampini } 55973a50541eSStefano Zampini if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */ 55983a50541eSStefano Zampini vbs = bs; 5599ad540459SPierre Jolivet for (i = 0; i < n_R / vbs; i++) idx_R_local[i] = idx_R_local[vbs * i] / vbs; 56003a50541eSStefano Zampini } 56013a50541eSStefano Zampini } 56029566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF, vbs, n_R / vbs, idx_R_local, PETSC_COPY_VALUES, &pcbddc->is_R_local)); 5603b334f244SStefano Zampini if (sub_schurs && sub_schurs->reuse_solver) { 5604df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 560553892102SStefano Zampini 56069566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(reuse_solver->is_R, (const PetscInt **)&idx_R_local)); 56079566063dSJacob Faibussowitsch PetscCall(ISDestroy(&reuse_solver->is_R)); 56089566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->is_R_local)); 5609df4d28bfSStefano Zampini reuse_solver->is_R = pcbddc->is_R_local; 561053892102SStefano Zampini } else { 56119566063dSJacob Faibussowitsch PetscCall(PetscFree(idx_R_local)); 561253892102SStefano Zampini } 5613a64d13efSStefano Zampini 5614a64d13efSStefano Zampini /* print some info if requested */ 5615a64d13efSStefano Zampini if (pcbddc->dbg_flag) { 56169566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 56179566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 56189566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 56199566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d local dimensions\n", PetscGlobalRank)); 562063a3b9bcSJacob 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)); 56219371c9d4SSatish 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, 56229371c9d4SSatish Balay pcbddc->local_primal_size - n_vertices - pcbddc->benign_n, pcbddc->local_primal_size)); 56239566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 5624a64d13efSStefano Zampini } 5625a64d13efSStefano Zampini 5626a64d13efSStefano Zampini /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */ 5627b334f244SStefano Zampini if (!sub_schurs || !sub_schurs->reuse_solver) { 56286816873aSStefano Zampini IS is_aux1, is_aux2; 56296816873aSStefano Zampini PetscInt *aux_array1, *aux_array2, *is_indices, *idx_R_local; 56306816873aSStefano Zampini 56319566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->is_R_local, (const PetscInt **)&idx_R_local)); 56329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n_B - n_vertices, &aux_array1)); 56339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n_B - n_vertices, &aux_array2)); 56349566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_I_local, (const PetscInt **)&is_indices)); 563548a46eb9SPierre Jolivet for (i = 0; i < n_D; i++) PetscCall(PetscBTSet(bitmask, is_indices[i])); 56369566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_I_local, (const PetscInt **)&is_indices)); 5637a64d13efSStefano Zampini for (i = 0, j = 0; i < n_R; i++) { 5638ad540459SPierre Jolivet if (!PetscBTLookup(bitmask, idx_R_local[i])) aux_array1[j++] = i; 5639a64d13efSStefano Zampini } 56409566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, aux_array1, PETSC_OWN_POINTER, &is_aux1)); 56419566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_B_local, (const PetscInt **)&is_indices)); 5642a64d13efSStefano Zampini for (i = 0, j = 0; i < n_B; i++) { 5643ad540459SPierre Jolivet if (!PetscBTLookup(bitmask, is_indices[i])) aux_array2[j++] = i; 5644a64d13efSStefano Zampini } 56459566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_B_local, (const PetscInt **)&is_indices)); 56469566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, aux_array2, PETSC_OWN_POINTER, &is_aux2)); 56479566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(pcbddc->vec1_R, is_aux1, pcis->vec1_B, is_aux2, &pcbddc->R_to_B)); 56489566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_aux1)); 56499566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_aux2)); 5650a64d13efSStefano Zampini 56518eeda7d8SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 56529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_D, &aux_array1)); 5653a64d13efSStefano Zampini for (i = 0, j = 0; i < n_R; i++) { 5654ad540459SPierre Jolivet if (PetscBTLookup(bitmask, idx_R_local[i])) aux_array1[j++] = i; 5655a64d13efSStefano Zampini } 56569566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, aux_array1, PETSC_OWN_POINTER, &is_aux1)); 56579566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(pcbddc->vec1_R, is_aux1, pcis->vec1_D, (IS)0, &pcbddc->R_to_D)); 56589566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_aux1)); 5659a64d13efSStefano Zampini } 56609566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&bitmask)); 56619566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->is_R_local, (const PetscInt **)&idx_R_local)); 5662d62866d3SStefano Zampini } else { 5663df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 56646816873aSStefano Zampini IS tis; 56656816873aSStefano Zampini PetscInt schur_size; 56666816873aSStefano Zampini 56679566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(reuse_solver->is_B, &schur_size)); 56689566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, schur_size, n_D, 1, &tis)); 56699566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(pcbddc->vec1_R, tis, pcis->vec1_B, reuse_solver->is_B, &pcbddc->R_to_B)); 56709566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tis)); 56716816873aSStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 56729566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, n_D, 0, 1, &tis)); 56739566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(pcbddc->vec1_R, tis, pcis->vec1_D, (IS)0, &pcbddc->R_to_D)); 56749566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tis)); 5675d62866d3SStefano Zampini } 5676d62866d3SStefano Zampini } 56773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5678a64d13efSStefano Zampini } 5679a64d13efSStefano Zampini 5680d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatNullSpacePropagateAny_Private(Mat A, IS is, Mat B) 5681d71ae5a4SJacob Faibussowitsch { 568292cccca0SStefano Zampini MatNullSpace NullSpace; 568392cccca0SStefano Zampini Mat dmat; 568492cccca0SStefano Zampini const Vec *nullvecs; 568592cccca0SStefano Zampini Vec v, v2, *nullvecs2; 56866d9e27e4SStefano Zampini VecScatter sct = NULL; 5687eb06acf8SStefano Zampini PetscContainer c; 5688eb06acf8SStefano Zampini PetscScalar *ddata; 5689295df10fSStefano Zampini PetscInt k, nnsp_size, bsiz, bsiz2, n, N, bs; 569092cccca0SStefano Zampini PetscBool nnsp_has_cnst; 569192cccca0SStefano Zampini 569292cccca0SStefano Zampini PetscFunctionBegin; 56936d9e27e4SStefano Zampini if (!is && !B) { /* MATIS */ 56946d9e27e4SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 56956d9e27e4SStefano Zampini 569648a46eb9SPierre Jolivet if (!B) PetscCall(MatISGetLocalMat(A, &B)); 56976d9e27e4SStefano Zampini sct = matis->cctx; 56989566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)sct)); 56996d9e27e4SStefano Zampini } else { 57009566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(B, &NullSpace)); 570148a46eb9SPierre Jolivet if (!NullSpace) PetscCall(MatGetNearNullSpace(B, &NullSpace)); 57023ba16761SJacob Faibussowitsch if (NullSpace) PetscFunctionReturn(PETSC_SUCCESS); 57036d9e27e4SStefano Zampini } 57049566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(A, &NullSpace)); 570548a46eb9SPierre Jolivet if (!NullSpace) PetscCall(MatGetNearNullSpace(A, &NullSpace)); 57063ba16761SJacob Faibussowitsch if (!NullSpace) PetscFunctionReturn(PETSC_SUCCESS); 57076d9e27e4SStefano Zampini 57089566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, &v, NULL)); 57099566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(B, &v2, NULL)); 571048a46eb9SPierre Jolivet if (!sct) PetscCall(VecScatterCreate(v, is, v2, NULL, &sct)); 57119566063dSJacob Faibussowitsch PetscCall(MatNullSpaceGetVecs(NullSpace, &nnsp_has_cnst, &nnsp_size, (const Vec **)&nullvecs)); 5712295df10fSStefano Zampini bsiz = bsiz2 = nnsp_size + !!nnsp_has_cnst; 57139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bsiz, &nullvecs2)); 57149566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(v2, &bs)); 57159566063dSJacob Faibussowitsch PetscCall(VecGetSize(v2, &N)); 57169566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v2, &n)); 57179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n * bsiz, &ddata)); 571892cccca0SStefano Zampini for (k = 0; k < nnsp_size; k++) { 57199566063dSJacob Faibussowitsch PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)B), bs, n, N, ddata + n * k, &nullvecs2[k])); 57209566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sct, nullvecs[k], nullvecs2[k], INSERT_VALUES, SCATTER_FORWARD)); 57219566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sct, nullvecs[k], nullvecs2[k], INSERT_VALUES, SCATTER_FORWARD)); 572292cccca0SStefano Zampini } 572392cccca0SStefano Zampini if (nnsp_has_cnst) { 57249566063dSJacob Faibussowitsch PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)B), bs, n, N, ddata + n * nnsp_size, &nullvecs2[nnsp_size])); 57259566063dSJacob Faibussowitsch PetscCall(VecSet(nullvecs2[nnsp_size], 1.0)); 572692cccca0SStefano Zampini } 57279566063dSJacob Faibussowitsch PetscCall(PCBDDCOrthonormalizeVecs(&bsiz2, nullvecs2)); 57289566063dSJacob Faibussowitsch PetscCall(MatNullSpaceCreate(PetscObjectComm((PetscObject)B), PETSC_FALSE, bsiz2, nullvecs2, &NullSpace)); 5729295df10fSStefano Zampini 57309566063dSJacob Faibussowitsch PetscCall(MatCreateDense(PetscObjectComm((PetscObject)B), n, PETSC_DECIDE, N, bsiz2, ddata, &dmat)); 57319566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &c)); 57329566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(c, ddata)); 57339566063dSJacob Faibussowitsch PetscCall(PetscContainerSetUserDestroy(c, PetscContainerUserDestroyDefault)); 57349566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dmat, "_PBDDC_Null_dmat_arr", (PetscObject)c)); 57359566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&c)); 57369566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)NullSpace, "_PBDDC_Null_dmat", (PetscObject)dmat)); 57379566063dSJacob Faibussowitsch PetscCall(MatDestroy(&dmat)); 5738eb06acf8SStefano Zampini 573948a46eb9SPierre Jolivet for (k = 0; k < bsiz; k++) PetscCall(VecDestroy(&nullvecs2[k])); 57409566063dSJacob Faibussowitsch PetscCall(PetscFree(nullvecs2)); 57419566063dSJacob Faibussowitsch PetscCall(MatSetNearNullSpace(B, NullSpace)); 57429566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&NullSpace)); 57439566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 57449566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v2)); 57459566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sct)); 57463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 574792cccca0SStefano Zampini } 5748304d26faSStefano Zampini 5749d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann) 5750d71ae5a4SJacob Faibussowitsch { 5751304d26faSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 5752304d26faSStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 5753304d26faSStefano Zampini PC pc_temp; 5754304d26faSStefano Zampini Mat A_RR; 575592cccca0SStefano Zampini MatNullSpace nnsp; 5756f4ddd8eeSStefano Zampini MatReuse reuse; 5757304d26faSStefano Zampini PetscScalar m_one = -1.0; 5758304d26faSStefano Zampini PetscReal value; 575904708bb6SStefano Zampini PetscInt n_D, n_R; 5760b94d7dedSBarry Smith PetscBool issbaij, opts, isset, issym; 57610a545947SLisandro Dalcin void (*f)(void) = NULL; 5762312be037SStefano Zampini char dir_prefix[256], neu_prefix[256], str_level[16]; 5763e604994aSStefano Zampini size_t len; 5764304d26faSStefano Zampini 5765304d26faSStefano Zampini PetscFunctionBegin; 57669566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_LocalSolvers[pcbddc->current_level], pc, 0, 0, 0)); 57676d9e27e4SStefano Zampini /* approximate solver, propagate NearNullSpace if needed */ 57686d9e27e4SStefano Zampini if (!pc->setupcalled && (pcbddc->NullSpace_corr[0] || pcbddc->NullSpace_corr[2])) { 57696d9e27e4SStefano Zampini MatNullSpace gnnsp1, gnnsp2; 57706d9e27e4SStefano Zampini PetscBool lhas, ghas; 57716d9e27e4SStefano Zampini 57729566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pcbddc->local_mat, &nnsp)); 57739566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pc->pmat, &gnnsp1)); 57749566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(pc->pmat, &gnnsp2)); 57756d9e27e4SStefano Zampini lhas = nnsp ? PETSC_TRUE : PETSC_FALSE; 57761c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&lhas, &ghas, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 577748a46eb9SPierre Jolivet if (!ghas && (gnnsp1 || gnnsp2)) PetscCall(MatNullSpacePropagateAny_Private(pc->pmat, NULL, NULL)); 57786d9e27e4SStefano Zampini } 57796d9e27e4SStefano Zampini 5780e604994aSStefano Zampini /* compute prefixes */ 5781c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(dir_prefix, "", sizeof(dir_prefix))); 5782c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(neu_prefix, "", sizeof(neu_prefix))); 5783e604994aSStefano Zampini if (!pcbddc->current_level) { 57849566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(dir_prefix, ((PetscObject)pc)->prefix, sizeof(dir_prefix))); 57859566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(neu_prefix, ((PetscObject)pc)->prefix, sizeof(neu_prefix))); 57869566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(dir_prefix, "pc_bddc_dirichlet_", sizeof(dir_prefix))); 57879566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(neu_prefix, "pc_bddc_neumann_", sizeof(neu_prefix))); 5788e604994aSStefano Zampini } else { 5789f4f49eeaSPierre Jolivet PetscCall(PetscSNPrintf(str_level, sizeof(str_level), "l%d_", (int)pcbddc->current_level)); 57909566063dSJacob Faibussowitsch PetscCall(PetscStrlen(((PetscObject)pc)->prefix, &len)); 5791e604994aSStefano Zampini len -= 15; /* remove "pc_bddc_coarse_" */ 5792312be037SStefano Zampini if (pcbddc->current_level > 1) len -= 3; /* remove "lX_" with X level number */ 5793312be037SStefano Zampini if (pcbddc->current_level > 10) len -= 1; /* remove another char from level number */ 5794a126751eSBarry Smith /* Nonstandard use of PetscStrncpy() to only copy a portion of the input string */ 57959566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(dir_prefix, ((PetscObject)pc)->prefix, len + 1)); 57969566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(neu_prefix, ((PetscObject)pc)->prefix, len + 1)); 57979566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(dir_prefix, "pc_bddc_dirichlet_", sizeof(dir_prefix))); 57989566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(neu_prefix, "pc_bddc_neumann_", sizeof(neu_prefix))); 57999566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(dir_prefix, str_level, sizeof(dir_prefix))); 58009566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(neu_prefix, str_level, sizeof(neu_prefix))); 5801e604994aSStefano Zampini } 5802e604994aSStefano Zampini 5803304d26faSStefano Zampini /* DIRICHLET PROBLEM */ 5804684f6988SStefano Zampini if (dirichlet) { 5805d5574798SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 5806450f8f5eSStefano Zampini if (pcbddc->benign_n && !pcbddc->benign_change_explicit) { 58077827d75bSBarry Smith PetscCheck(sub_schurs && sub_schurs->reuse_solver, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not yet implemented"); 5808450f8f5eSStefano Zampini if (pcbddc->dbg_flag) { 5809a3df083aSStefano Zampini Mat A_IIn; 5810a3df083aSStefano Zampini 58119566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignProject(pc, pcis->is_I_local, pcis->is_I_local, &A_IIn)); 58129566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_II)); 5813a3df083aSStefano Zampini pcis->A_II = A_IIn; 5814a3df083aSStefano Zampini } 5815450f8f5eSStefano Zampini } 5816b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(pcbddc->local_mat, &isset, &issym)); 5817b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(pcis->A_II, MAT_SYMMETRIC, issym)); 5818b94d7dedSBarry Smith 5819ac78edfcSStefano Zampini /* Matrix for Dirichlet problem is pcis->A_II */ 5820964fefecSStefano Zampini n_D = pcis->n - pcis->n_B; 582192cccca0SStefano Zampini opts = PETSC_FALSE; 5822304d26faSStefano Zampini if (!pcbddc->ksp_D) { /* create object if not yet build */ 582392cccca0SStefano Zampini opts = PETSC_TRUE; 58249566063dSJacob Faibussowitsch PetscCall(KSPCreate(PETSC_COMM_SELF, &pcbddc->ksp_D)); 58253821be0aSBarry Smith PetscCall(KSPSetNestLevel(pcbddc->ksp_D, pc->kspnestlevel)); 58269566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D, (PetscObject)pc, 1)); 5827304d26faSStefano Zampini /* default */ 58289566063dSJacob Faibussowitsch PetscCall(KSPSetType(pcbddc->ksp_D, KSPPREONLY)); 58299566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(pcbddc->ksp_D, dir_prefix)); 58309566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pcis->pA_II, MATSEQSBAIJ, &issbaij)); 58319566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_D, &pc_temp)); 58329577ea80SStefano Zampini if (issbaij) { 58339566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCCHOLESKY)); 58349577ea80SStefano Zampini } else { 58359566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCLU)); 58369577ea80SStefano Zampini } 58379566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(pcbddc->ksp_D, pc->erroriffailure)); 583892cccca0SStefano Zampini } 58399566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(pcis->pA_II, ((PetscObject)pcbddc->ksp_D)->prefix)); 58409de2952eSStefano Zampini PetscCall(MatViewFromOptions(pcis->pA_II, NULL, "-mat_view")); 58419566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(pcbddc->ksp_D, pcis->A_II, pcis->pA_II)); 5842304d26faSStefano Zampini /* Allow user's customization */ 58431baa6e33SBarry Smith if (opts) PetscCall(KSPSetFromOptions(pcbddc->ksp_D)); 58449566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pcis->pA_II, &nnsp)); 58456d9e27e4SStefano Zampini if (pcbddc->NullSpace_corr[0] && !nnsp) { /* approximate solver, propagate NearNullSpace */ 58469566063dSJacob Faibussowitsch PetscCall(MatNullSpacePropagateAny_Private(pcbddc->local_mat, pcis->is_I_local, pcis->pA_II)); 584792cccca0SStefano Zampini } 58489566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pcis->pA_II, &nnsp)); 58499566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_D, &pc_temp)); 58509566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)pc_temp, "PCSetCoordinates_C", &f)); 585192cccca0SStefano Zampini if (f && pcbddc->mat_graph->cloc && !nnsp) { 5852cd18cfedSStefano Zampini PetscReal *coords = pcbddc->mat_graph->coords, *scoords; 5853cd18cfedSStefano Zampini const PetscInt *idxs; 5854cd18cfedSStefano Zampini PetscInt cdim = pcbddc->mat_graph->cdim, nl, i, d; 5855cd18cfedSStefano Zampini 58569566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcis->is_I_local, &nl)); 58579566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_I_local, &idxs)); 58589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl * cdim, &scoords)); 5859cd18cfedSStefano Zampini for (i = 0; i < nl; i++) { 5860ad540459SPierre Jolivet for (d = 0; d < cdim; d++) scoords[i * cdim + d] = coords[idxs[i] * cdim + d]; 5861cd18cfedSStefano Zampini } 58629566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_I_local, &idxs)); 58639566063dSJacob Faibussowitsch PetscCall(PCSetCoordinates(pc_temp, cdim, nl, scoords)); 58649566063dSJacob Faibussowitsch PetscCall(PetscFree(scoords)); 5865cd18cfedSStefano Zampini } 5866b334f244SStefano Zampini if (sub_schurs && sub_schurs->reuse_solver) { 5867df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 5868d62866d3SStefano Zampini 58699566063dSJacob Faibussowitsch PetscCall(KSPSetPC(pcbddc->ksp_D, reuse_solver->interior_solver)); 5870d5574798SStefano Zampini } 587192cccca0SStefano Zampini 5872304d26faSStefano Zampini /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */ 5873304d26faSStefano Zampini if (!n_D) { 58749566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_D, &pc_temp)); 58759566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCNONE)); 5876304d26faSStefano Zampini } 58779566063dSJacob Faibussowitsch PetscCall(KSPSetUp(pcbddc->ksp_D)); 5878304d26faSStefano Zampini /* set ksp_D into pcis data */ 58799566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->ksp_D)); 58809566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&pcis->ksp_D)); 5881304d26faSStefano Zampini pcis->ksp_D = pcbddc->ksp_D; 5882684f6988SStefano Zampini } 5883304d26faSStefano Zampini 5884304d26faSStefano Zampini /* NEUMANN PROBLEM */ 58850a545947SLisandro Dalcin A_RR = NULL; 5886684f6988SStefano Zampini if (neumann) { 5887d62866d3SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 588804708bb6SStefano Zampini PetscInt ibs, mbs; 5889b94d7dedSBarry Smith PetscBool issbaij, reuse_neumann_solver, isset, issym; 589004708bb6SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 58910aa714b2SStefano Zampini 58920aa714b2SStefano Zampini reuse_neumann_solver = PETSC_FALSE; 58930aa714b2SStefano Zampini if (sub_schurs && sub_schurs->reuse_solver) { 58940aa714b2SStefano Zampini IS iP; 58950aa714b2SStefano Zampini 58960aa714b2SStefano Zampini reuse_neumann_solver = PETSC_TRUE; 58979566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)sub_schurs->A, "__KSPFETIDP_iP", (PetscObject *)&iP)); 58980aa714b2SStefano Zampini if (iP) reuse_neumann_solver = PETSC_FALSE; 58990aa714b2SStefano Zampini } 5900f4ddd8eeSStefano Zampini /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */ 59019566063dSJacob Faibussowitsch PetscCall(ISGetSize(pcbddc->is_R_local, &n_R)); 5902f4ddd8eeSStefano Zampini if (pcbddc->ksp_R) { /* already created ksp */ 5903f4ddd8eeSStefano Zampini PetscInt nn_R; 59049566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(pcbddc->ksp_R, NULL, &A_RR)); 59059566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A_RR)); 59069566063dSJacob Faibussowitsch PetscCall(MatGetSize(A_RR, &nn_R, NULL)); 5907f4ddd8eeSStefano Zampini if (nn_R != n_R) { /* old ksp is not reusable, so reset it */ 59089566063dSJacob Faibussowitsch PetscCall(KSPReset(pcbddc->ksp_R)); 59099566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 5910f4ddd8eeSStefano Zampini reuse = MAT_INITIAL_MATRIX; 5911f4ddd8eeSStefano Zampini } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */ 5912727cdba6SStefano Zampini if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */ 59139566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 5914f4ddd8eeSStefano Zampini reuse = MAT_INITIAL_MATRIX; 5915f4ddd8eeSStefano Zampini } else { /* safe to reuse the matrix */ 5916f4ddd8eeSStefano Zampini reuse = MAT_REUSE_MATRIX; 5917f4ddd8eeSStefano Zampini } 5918f4ddd8eeSStefano Zampini } 5919f4ddd8eeSStefano Zampini /* last check */ 5920d1e9a80fSBarry Smith if (pc->flag == DIFFERENT_NONZERO_PATTERN) { 59219566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 5922f4ddd8eeSStefano Zampini reuse = MAT_INITIAL_MATRIX; 5923f4ddd8eeSStefano Zampini } 5924f4ddd8eeSStefano Zampini } else { /* first time, so we need to create the matrix */ 5925f4ddd8eeSStefano Zampini reuse = MAT_INITIAL_MATRIX; 5926f4ddd8eeSStefano Zampini } 5927365a3a41SStefano Zampini /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection 5928365a3a41SStefano Zampini TODO: Get Rid of these conversions */ 59299566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(pcbddc->local_mat, &mbs)); 59309566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(pcbddc->is_R_local, &ibs)); 59319566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pcbddc->local_mat, MATSEQSBAIJ, &issbaij)); 593204708bb6SStefano Zampini if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */ 593304708bb6SStefano Zampini if (matis->A == pcbddc->local_mat) { 59349566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 59359566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &pcbddc->local_mat)); 5936af732b37SStefano Zampini } else { 59379566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->local_mat, MATSEQAIJ, MAT_INPLACE_MATRIX, &pcbddc->local_mat)); 59386816873aSStefano Zampini } 59394cf0e950SBarry Smith } else if (issbaij) { /* need to convert to BAIJ to get off-diagonal blocks */ 594004708bb6SStefano Zampini if (matis->A == pcbddc->local_mat) { 59419566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 59429566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, mbs > 1 ? MATSEQBAIJ : MATSEQAIJ, MAT_INITIAL_MATRIX, &pcbddc->local_mat)); 594304708bb6SStefano Zampini } else { 59449566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->local_mat, mbs > 1 ? MATSEQBAIJ : MATSEQAIJ, MAT_INPLACE_MATRIX, &pcbddc->local_mat)); 594504708bb6SStefano Zampini } 594604708bb6SStefano Zampini } 5947a00504b5SStefano Zampini /* extract A_RR */ 59480aa714b2SStefano Zampini if (reuse_neumann_solver) { 5949a00504b5SStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 5950a00504b5SStefano Zampini 5951a00504b5SStefano Zampini if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */ 59529566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 5953a00504b5SStefano Zampini if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */ 59549566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignProject(pc, pcbddc->is_R_local, pcbddc->is_R_local, &A_RR)); 595516e386b8SStefano Zampini } else { 59569566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcbddc->is_R_local, pcbddc->is_R_local, MAT_INITIAL_MATRIX, &A_RR)); 5957a00504b5SStefano Zampini } 5958a00504b5SStefano Zampini } else { 59599566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 59609566063dSJacob Faibussowitsch PetscCall(PCGetOperators(reuse_solver->correction_solver, &A_RR, NULL)); 59619566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A_RR)); 5962a00504b5SStefano Zampini } 5963a00504b5SStefano Zampini } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */ 59649566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcbddc->is_R_local, pcbddc->is_R_local, reuse, &A_RR)); 596516e386b8SStefano Zampini } 5966b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(pcbddc->local_mat, &isset, &issym)); 5967b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(A_RR, MAT_SYMMETRIC, issym)); 596892cccca0SStefano Zampini opts = PETSC_FALSE; 5969f4ddd8eeSStefano Zampini if (!pcbddc->ksp_R) { /* create object if not present */ 597092cccca0SStefano Zampini opts = PETSC_TRUE; 59719566063dSJacob Faibussowitsch PetscCall(KSPCreate(PETSC_COMM_SELF, &pcbddc->ksp_R)); 59723821be0aSBarry Smith PetscCall(KSPSetNestLevel(pcbddc->ksp_R, pc->kspnestlevel)); 59739566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R, (PetscObject)pc, 1)); 5974304d26faSStefano Zampini /* default */ 59759566063dSJacob Faibussowitsch PetscCall(KSPSetType(pcbddc->ksp_R, KSPPREONLY)); 59769566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(pcbddc->ksp_R, neu_prefix)); 59779566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_R, &pc_temp)); 59789566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A_RR, MATSEQSBAIJ, &issbaij)); 59799577ea80SStefano Zampini if (issbaij) { 59809566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCCHOLESKY)); 59819577ea80SStefano Zampini } else { 59829566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCLU)); 59839577ea80SStefano Zampini } 59849566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(pcbddc->ksp_R, pc->erroriffailure)); 598592cccca0SStefano Zampini } 59869566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(A_RR, ((PetscObject)pcbddc->ksp_R)->prefix)); 59879de2952eSStefano Zampini PetscCall(MatViewFromOptions(A_RR, NULL, "-mat_view")); 59889de2952eSStefano Zampini PetscCall(KSPSetOperators(pcbddc->ksp_R, A_RR, A_RR)); 598992cccca0SStefano Zampini if (opts) { /* Allow user's customization once */ 59909566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(pcbddc->ksp_R)); 599192cccca0SStefano Zampini } 59929566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(A_RR, &nnsp)); 59936d9e27e4SStefano Zampini if (pcbddc->NullSpace_corr[2] && !nnsp) { /* approximate solver, propagate NearNullSpace */ 59949566063dSJacob Faibussowitsch PetscCall(MatNullSpacePropagateAny_Private(pcbddc->local_mat, pcbddc->is_R_local, A_RR)); 599592cccca0SStefano Zampini } 59969566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(A_RR, &nnsp)); 59979566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_R, &pc_temp)); 59989566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)pc_temp, "PCSetCoordinates_C", &f)); 599992cccca0SStefano Zampini if (f && pcbddc->mat_graph->cloc && !nnsp) { 6000cd18cfedSStefano Zampini PetscReal *coords = pcbddc->mat_graph->coords, *scoords; 6001cd18cfedSStefano Zampini const PetscInt *idxs; 6002cd18cfedSStefano Zampini PetscInt cdim = pcbddc->mat_graph->cdim, nl, i, d; 6003cd18cfedSStefano Zampini 60049566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->is_R_local, &nl)); 60059566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->is_R_local, &idxs)); 60069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl * cdim, &scoords)); 6007cd18cfedSStefano Zampini for (i = 0; i < nl; i++) { 6008ad540459SPierre Jolivet for (d = 0; d < cdim; d++) scoords[i * cdim + d] = coords[idxs[i] * cdim + d]; 6009cd18cfedSStefano Zampini } 60109566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->is_R_local, &idxs)); 60119566063dSJacob Faibussowitsch PetscCall(PCSetCoordinates(pc_temp, cdim, nl, scoords)); 60129566063dSJacob Faibussowitsch PetscCall(PetscFree(scoords)); 6013cd18cfedSStefano Zampini } 601492cccca0SStefano Zampini 6015304d26faSStefano Zampini /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */ 6016304d26faSStefano Zampini if (!n_R) { 60179566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_R, &pc_temp)); 60189566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCNONE)); 6019304d26faSStefano Zampini } 6020df4d28bfSStefano Zampini /* Reuse solver if it is present */ 60210aa714b2SStefano Zampini if (reuse_neumann_solver) { 6022df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 6023d62866d3SStefano Zampini 60249566063dSJacob Faibussowitsch PetscCall(KSPSetPC(pcbddc->ksp_R, reuse_solver->correction_solver)); 6025d62866d3SStefano Zampini } 60269566063dSJacob Faibussowitsch PetscCall(KSPSetUp(pcbddc->ksp_R)); 6027684f6988SStefano Zampini } 6028304d26faSStefano Zampini 6029684f6988SStefano Zampini if (pcbddc->dbg_flag) { 60309566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 60319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 60329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 6033684f6988SStefano Zampini } 60349566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_LocalSolvers[pcbddc->current_level], pc, 0, 0, 0)); 6035c7017625SStefano Zampini 6036c7017625SStefano Zampini /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */ 603748a46eb9SPierre Jolivet if (pcbddc->NullSpace_corr[0]) PetscCall(PCBDDCSetUseExactDirichlet(pc, PETSC_FALSE)); 603848a46eb9SPierre Jolivet if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) PetscCall(PCBDDCNullSpaceAssembleCorrection(pc, PETSC_TRUE, pcbddc->NullSpace_corr[1])); 603948a46eb9SPierre Jolivet if (neumann && pcbddc->NullSpace_corr[2]) PetscCall(PCBDDCNullSpaceAssembleCorrection(pc, PETSC_FALSE, pcbddc->NullSpace_corr[3])); 6040c7017625SStefano Zampini /* check Dirichlet and Neumann solvers */ 6041c7017625SStefano Zampini if (pcbddc->dbg_flag) { 6042684f6988SStefano Zampini if (dirichlet) { /* Dirichlet */ 60439566063dSJacob Faibussowitsch PetscCall(VecSetRandom(pcis->vec1_D, NULL)); 60449566063dSJacob Faibussowitsch PetscCall(MatMult(pcis->A_II, pcis->vec1_D, pcis->vec2_D)); 60459566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec2_D, pcis->vec2_D)); 60469566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D)); 60479566063dSJacob Faibussowitsch PetscCall(VecAXPY(pcis->vec1_D, m_one, pcis->vec2_D)); 60489566063dSJacob Faibussowitsch PetscCall(VecNorm(pcis->vec1_D, NORM_INFINITY, &value)); 6049f4f49eeaSPierre Jolivet PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d infinity error for Dirichlet solve (%s) = % 1.14e \n", PetscGlobalRank, ((PetscObject)pcbddc->ksp_D)->prefix, (double)value)); 60509566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 6051304d26faSStefano Zampini } 6052684f6988SStefano Zampini if (neumann) { /* Neumann */ 60539566063dSJacob Faibussowitsch PetscCall(VecSetRandom(pcbddc->vec1_R, NULL)); 60549566063dSJacob Faibussowitsch PetscCall(MatMult(A_RR, pcbddc->vec1_R, pcbddc->vec2_R)); 60559566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_R, pcbddc->vec2_R, pcbddc->vec2_R)); 60569566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec2_R)); 60579566063dSJacob Faibussowitsch PetscCall(VecAXPY(pcbddc->vec1_R, m_one, pcbddc->vec2_R)); 60589566063dSJacob Faibussowitsch PetscCall(VecNorm(pcbddc->vec1_R, NORM_INFINITY, &value)); 6059f4f49eeaSPierre Jolivet PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d infinity error for Neumann solve (%s) = % 1.14e\n", PetscGlobalRank, ((PetscObject)pcbddc->ksp_R)->prefix, (double)value)); 60609566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 6061304d26faSStefano Zampini } 6062684f6988SStefano Zampini } 60635cbda25cSStefano Zampini /* free Neumann problem's matrix */ 60649566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 60653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6066304d26faSStefano Zampini } 6067304d26faSStefano Zampini 6068d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose) 6069d71ae5a4SJacob Faibussowitsch { 6070f4f49eeaSPierre Jolivet PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 6071be83ff47SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 6072b334f244SStefano Zampini PetscBool reuse_solver = sub_schurs ? (sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE) : PETSC_FALSE; 6073674ae819SStefano Zampini 6074674ae819SStefano Zampini PetscFunctionBegin; 607548a46eb9SPierre Jolivet if (!reuse_solver) PetscCall(VecSet(pcbddc->vec1_R, 0.)); 607680677318SStefano Zampini if (!pcbddc->switch_static) { 607780677318SStefano Zampini if (applytranspose && pcbddc->local_auxmat1) { 60789566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->local_auxmat2, inout_B, pcbddc->vec1_C)); 60799566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(pcbddc->local_auxmat1, pcbddc->vec1_C, inout_B, inout_B)); 608020c7b377SStefano Zampini } 6081b334f244SStefano Zampini if (!reuse_solver) { 60829566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 60839566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 608420c7b377SStefano Zampini } else { 6085df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 6086be83ff47SStefano Zampini 60879566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(reuse_solver->correction_scatter_B, inout_B, reuse_solver->rhs_B, INSERT_VALUES, SCATTER_FORWARD)); 60889566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(reuse_solver->correction_scatter_B, inout_B, reuse_solver->rhs_B, INSERT_VALUES, SCATTER_FORWARD)); 608920c7b377SStefano Zampini } 6090be83ff47SStefano Zampini } else { 60919566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 60929566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 60939566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_D, inout_D, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 60949566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_D, inout_D, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 609580677318SStefano Zampini if (applytranspose && pcbddc->local_auxmat1) { 60969566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->local_auxmat2, pcbddc->vec1_R, pcbddc->vec1_C)); 60979566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(pcbddc->local_auxmat1, pcbddc->vec1_C, inout_B, inout_B)); 60989566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 60999566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 6100674ae819SStefano Zampini } 6101674ae819SStefano Zampini } 61029566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][1], pc, 0, 0, 0)); 6103b334f244SStefano Zampini if (!reuse_solver || pcbddc->switch_static) { 610480677318SStefano Zampini if (applytranspose) { 61059566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec1_R)); 610680677318SStefano Zampini } else { 61079566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec1_R)); 610880677318SStefano Zampini } 61099566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec1_R)); 6110be83ff47SStefano Zampini } else { 6111df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 6112be83ff47SStefano Zampini 6113be83ff47SStefano Zampini if (applytranspose) { 61149566063dSJacob Faibussowitsch PetscCall(MatFactorSolveSchurComplementTranspose(reuse_solver->F, reuse_solver->rhs_B, reuse_solver->sol_B)); 6115be83ff47SStefano Zampini } else { 61169566063dSJacob Faibussowitsch PetscCall(MatFactorSolveSchurComplement(reuse_solver->F, reuse_solver->rhs_B, reuse_solver->sol_B)); 6117be83ff47SStefano Zampini } 6118be83ff47SStefano Zampini } 61199566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][1], pc, 0, 0, 0)); 61209566063dSJacob Faibussowitsch PetscCall(VecSet(inout_B, 0.)); 612180677318SStefano Zampini if (!pcbddc->switch_static) { 6122b334f244SStefano Zampini if (!reuse_solver) { 61239566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 61249566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 6125be83ff47SStefano Zampini } else { 6126df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 6127be83ff47SStefano Zampini 61289566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(reuse_solver->correction_scatter_B, reuse_solver->sol_B, inout_B, INSERT_VALUES, SCATTER_REVERSE)); 61299566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(reuse_solver->correction_scatter_B, reuse_solver->sol_B, inout_B, INSERT_VALUES, SCATTER_REVERSE)); 6130be83ff47SStefano Zampini } 613180677318SStefano Zampini if (!applytranspose && pcbddc->local_auxmat1) { 61329566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->local_auxmat1, inout_B, pcbddc->vec1_C)); 61339566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pcbddc->local_auxmat2, pcbddc->vec1_C, inout_B, inout_B)); 613480677318SStefano Zampini } 613580677318SStefano Zampini } else { 61369566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 61379566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 61389566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_D, pcbddc->vec1_R, inout_D, INSERT_VALUES, SCATTER_FORWARD)); 61399566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_D, pcbddc->vec1_R, inout_D, INSERT_VALUES, SCATTER_FORWARD)); 614080677318SStefano Zampini if (!applytranspose && pcbddc->local_auxmat1) { 61419566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->local_auxmat1, inout_B, pcbddc->vec1_C)); 61429566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pcbddc->local_auxmat2, pcbddc->vec1_C, pcbddc->vec1_R, pcbddc->vec1_R)); 614380677318SStefano Zampini } 61449566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 61459566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 61469566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_D, pcbddc->vec1_R, inout_D, INSERT_VALUES, SCATTER_FORWARD)); 61479566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_D, pcbddc->vec1_R, inout_D, INSERT_VALUES, SCATTER_FORWARD)); 6148674ae819SStefano Zampini } 61493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6150674ae819SStefano Zampini } 6151674ae819SStefano Zampini 6152dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */ 6153d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose) 6154d71ae5a4SJacob Faibussowitsch { 6155f4f49eeaSPierre Jolivet PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 6156f4f49eeaSPierre Jolivet PC_IS *pcis = (PC_IS *)pc->data; 6157674ae819SStefano Zampini const PetscScalar zero = 0.0; 6158674ae819SStefano Zampini 6159674ae819SStefano Zampini PetscFunctionBegin; 6160dc359a40SStefano Zampini /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */ 61614fee134fSStefano Zampini if (!pcbddc->benign_apply_coarse_only) { 6162dc359a40SStefano Zampini if (applytranspose) { 61639566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->coarse_phi_B, pcis->vec1_B, pcbddc->vec1_P)); 61649566063dSJacob Faibussowitsch if (pcbddc->switch_static) PetscCall(MatMultTransposeAdd(pcbddc->coarse_phi_D, pcis->vec1_D, pcbddc->vec1_P, pcbddc->vec1_P)); 6165dc359a40SStefano Zampini } else { 61669566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->coarse_psi_B, pcis->vec1_B, pcbddc->vec1_P)); 61679566063dSJacob Faibussowitsch if (pcbddc->switch_static) PetscCall(MatMultTransposeAdd(pcbddc->coarse_psi_D, pcis->vec1_D, pcbddc->vec1_P, pcbddc->vec1_P)); 616815aaf578SStefano Zampini } 61694fee134fSStefano Zampini } else { 61709566063dSJacob Faibussowitsch PetscCall(VecSet(pcbddc->vec1_P, zero)); 61714fee134fSStefano Zampini } 6172efc2fbd9SStefano Zampini 6173efc2fbd9SStefano Zampini /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */ 61744f1b2e48SStefano Zampini if (pcbddc->benign_n) { 6175efc2fbd9SStefano Zampini PetscScalar *array; 61764f1b2e48SStefano Zampini PetscInt j; 6177efc2fbd9SStefano Zampini 61789566063dSJacob Faibussowitsch PetscCall(VecGetArray(pcbddc->vec1_P, &array)); 61794f1b2e48SStefano Zampini for (j = 0; j < pcbddc->benign_n; j++) array[pcbddc->local_primal_size - pcbddc->benign_n + j] += pcbddc->benign_p0[j]; 61809566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pcbddc->vec1_P, &array)); 6181efc2fbd9SStefano Zampini } 6182efc2fbd9SStefano Zampini 618312edc857SStefano Zampini /* start communications from local primal nodes to rhs of coarse solver */ 61849566063dSJacob Faibussowitsch PetscCall(VecSet(pcbddc->coarse_vec, zero)); 61859566063dSJacob Faibussowitsch PetscCall(PCBDDCScatterCoarseDataBegin(pc, ADD_VALUES, SCATTER_FORWARD)); 61869566063dSJacob Faibussowitsch PetscCall(PCBDDCScatterCoarseDataEnd(pc, ADD_VALUES, SCATTER_FORWARD)); 618712edc857SStefano Zampini 61889f00e9b4SStefano Zampini /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */ 6189a1cb837bSStefano Zampini PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][2], pc, 0, 0, 0)); 619012edc857SStefano Zampini if (pcbddc->coarse_ksp) { 619151694757SStefano Zampini Mat coarse_mat; 6192964fefecSStefano Zampini Vec rhs, sol; 619351694757SStefano Zampini MatNullSpace nullsp; 619427b6a85dSStefano Zampini PetscBool isbddc = PETSC_FALSE; 6195964fefecSStefano Zampini 619627b6a85dSStefano Zampini if (pcbddc->benign_have_null) { 619727b6a85dSStefano Zampini PC coarse_pc; 619827b6a85dSStefano Zampini 61999566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &coarse_pc)); 62009566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)coarse_pc, PCBDDC, &isbddc)); 620127b6a85dSStefano Zampini /* we need to propagate to coarser levels the need for a possible benign correction */ 620227b6a85dSStefano Zampini if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) { 6203f4f49eeaSPierre Jolivet PC_BDDC *coarsepcbddc = (PC_BDDC *)coarse_pc->data; 620427b6a85dSStefano Zampini coarsepcbddc->benign_skip_correction = PETSC_FALSE; 62053bca92a6SStefano Zampini coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE; 620627b6a85dSStefano Zampini } 620727b6a85dSStefano Zampini } 62089566063dSJacob Faibussowitsch PetscCall(KSPGetRhs(pcbddc->coarse_ksp, &rhs)); 62099566063dSJacob Faibussowitsch PetscCall(KSPGetSolution(pcbddc->coarse_ksp, &sol)); 62109566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(pcbddc->coarse_ksp, &coarse_mat, NULL)); 621112edc857SStefano Zampini if (applytranspose) { 621228b400f6SJacob Faibussowitsch PetscCheck(!pcbddc->benign_apply_coarse_only, PetscObjectComm((PetscObject)pcbddc->coarse_ksp), PETSC_ERR_SUP, "Not yet implemented"); 62139566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->coarse_ksp, rhs, sol)); 62149566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->coarse_ksp, pc, sol)); 62159566063dSJacob Faibussowitsch PetscCall(MatGetTransposeNullSpace(coarse_mat, &nullsp)); 62161baa6e33SBarry Smith if (nullsp) PetscCall(MatNullSpaceRemove(nullsp, sol)); 62172701bc32SStefano Zampini } else { 62189566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(coarse_mat, &nullsp)); 62191f4df5f7SStefano Zampini if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */ 62202701bc32SStefano Zampini PC coarse_pc; 62212701bc32SStefano Zampini 62221baa6e33SBarry Smith if (nullsp) PetscCall(MatNullSpaceRemove(nullsp, rhs)); 62239566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &coarse_pc)); 62249566063dSJacob Faibussowitsch PetscCall(PCPreSolve(coarse_pc, pcbddc->coarse_ksp)); 62259566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignRemoveInterior(coarse_pc, rhs, sol)); 62269566063dSJacob Faibussowitsch PetscCall(PCPostSolve(coarse_pc, pcbddc->coarse_ksp)); 622712edc857SStefano Zampini } else { 62289566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->coarse_ksp, rhs, sol)); 62299566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->coarse_ksp, pc, sol)); 62301baa6e33SBarry Smith if (nullsp) PetscCall(MatNullSpaceRemove(nullsp, sol)); 623112edc857SStefano Zampini } 62322701bc32SStefano Zampini } 62331d82a3b6SStefano Zampini /* we don't need the benign correction at coarser levels anymore */ 623427b6a85dSStefano Zampini if (pcbddc->benign_have_null && isbddc) { 623527b6a85dSStefano Zampini PC coarse_pc; 623627b6a85dSStefano Zampini PC_BDDC *coarsepcbddc; 623727b6a85dSStefano Zampini 62389566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &coarse_pc)); 6239f4f49eeaSPierre Jolivet coarsepcbddc = (PC_BDDC *)coarse_pc->data; 624027b6a85dSStefano Zampini coarsepcbddc->benign_skip_correction = PETSC_TRUE; 62413bca92a6SStefano Zampini coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE; 624227b6a85dSStefano Zampini } 624312edc857SStefano Zampini } 6244a1cb837bSStefano Zampini PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][2], pc, 0, 0, 0)); 6245674ae819SStefano Zampini 6246674ae819SStefano Zampini /* Local solution on R nodes */ 6247a1cb837bSStefano Zampini if (!pcbddc->benign_apply_coarse_only) PetscCall(PCBDDCSolveSubstructureCorrection(pc, pcis->vec1_B, pcis->vec1_D, applytranspose)); 62489f00e9b4SStefano Zampini /* communications from coarse sol to local primal nodes */ 62499566063dSJacob Faibussowitsch PetscCall(PCBDDCScatterCoarseDataBegin(pc, INSERT_VALUES, SCATTER_REVERSE)); 62509566063dSJacob Faibussowitsch PetscCall(PCBDDCScatterCoarseDataEnd(pc, INSERT_VALUES, SCATTER_REVERSE)); 6251674ae819SStefano Zampini 62524fee134fSStefano Zampini /* Sum contributions from the two levels */ 62534fee134fSStefano Zampini if (!pcbddc->benign_apply_coarse_only) { 6254dc359a40SStefano Zampini if (applytranspose) { 62559566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pcbddc->coarse_psi_B, pcbddc->vec1_P, pcis->vec1_B, pcis->vec1_B)); 62569566063dSJacob Faibussowitsch if (pcbddc->switch_static) PetscCall(MatMultAdd(pcbddc->coarse_psi_D, pcbddc->vec1_P, pcis->vec1_D, pcis->vec1_D)); 6257dc359a40SStefano Zampini } else { 62589566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pcbddc->coarse_phi_B, pcbddc->vec1_P, pcis->vec1_B, pcis->vec1_B)); 62599566063dSJacob Faibussowitsch if (pcbddc->switch_static) PetscCall(MatMultAdd(pcbddc->coarse_phi_D, pcbddc->vec1_P, pcis->vec1_D, pcis->vec1_D)); 6260dc359a40SStefano Zampini } 6261efc2fbd9SStefano Zampini /* store p0 */ 62624f1b2e48SStefano Zampini if (pcbddc->benign_n) { 6263efc2fbd9SStefano Zampini PetscScalar *array; 62644f1b2e48SStefano Zampini PetscInt j; 6265efc2fbd9SStefano Zampini 62669566063dSJacob Faibussowitsch PetscCall(VecGetArray(pcbddc->vec1_P, &array)); 62674f1b2e48SStefano Zampini for (j = 0; j < pcbddc->benign_n; j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size - pcbddc->benign_n + j]; 62689566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pcbddc->vec1_P, &array)); 6269efc2fbd9SStefano Zampini } 62704fee134fSStefano Zampini } else { /* expand the coarse solution */ 62714fee134fSStefano Zampini if (applytranspose) { 62729566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->coarse_psi_B, pcbddc->vec1_P, pcis->vec1_B)); 62734fee134fSStefano Zampini } else { 62749566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->coarse_phi_B, pcbddc->vec1_P, pcis->vec1_B)); 62754fee134fSStefano Zampini } 62764fee134fSStefano Zampini } 62773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6278674ae819SStefano Zampini } 6279674ae819SStefano Zampini 6280d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc, InsertMode imode, ScatterMode smode) 6281d71ae5a4SJacob Faibussowitsch { 6282f4f49eeaSPierre Jolivet PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 628312edc857SStefano Zampini Vec from, to; 62847ebab0bbSStefano Zampini const PetscScalar *array; 6285674ae819SStefano Zampini 6286674ae819SStefano Zampini PetscFunctionBegin; 628712edc857SStefano Zampini if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */ 628812edc857SStefano Zampini from = pcbddc->coarse_vec; 628912edc857SStefano Zampini to = pcbddc->vec1_P; 629012edc857SStefano Zampini if (pcbddc->coarse_ksp) { /* get array from coarse processes */ 629112edc857SStefano Zampini Vec tvec; 629258da7f69SStefano Zampini 62939566063dSJacob Faibussowitsch PetscCall(KSPGetRhs(pcbddc->coarse_ksp, &tvec)); 62949566063dSJacob Faibussowitsch PetscCall(VecResetArray(tvec)); 62959566063dSJacob Faibussowitsch PetscCall(KSPGetSolution(pcbddc->coarse_ksp, &tvec)); 62969566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(tvec, &array)); 62979566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(from, array)); 62989566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(tvec, &array)); 629912edc857SStefano Zampini } 6300dd8e379bSPierre Jolivet } else { /* from local to global -> put data in coarse right-hand side */ 630112edc857SStefano Zampini from = pcbddc->vec1_P; 630212edc857SStefano Zampini to = pcbddc->coarse_vec; 630312edc857SStefano Zampini } 63049566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob, from, to, imode, smode)); 63053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6306674ae819SStefano Zampini } 6307674ae819SStefano Zampini 6308d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode) 6309d71ae5a4SJacob Faibussowitsch { 6310f4f49eeaSPierre Jolivet PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 631112edc857SStefano Zampini Vec from, to; 63127ebab0bbSStefano Zampini const PetscScalar *array; 6313674ae819SStefano Zampini 6314674ae819SStefano Zampini PetscFunctionBegin; 631512edc857SStefano Zampini if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */ 631612edc857SStefano Zampini from = pcbddc->coarse_vec; 631712edc857SStefano Zampini to = pcbddc->vec1_P; 6318dd8e379bSPierre Jolivet } else { /* from local to global -> put data in coarse right-hand side */ 631912edc857SStefano Zampini from = pcbddc->vec1_P; 632012edc857SStefano Zampini to = pcbddc->coarse_vec; 632112edc857SStefano Zampini } 63229566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob, from, to, imode, smode)); 632312edc857SStefano Zampini if (smode == SCATTER_FORWARD) { 632412edc857SStefano Zampini if (pcbddc->coarse_ksp) { /* get array from coarse processes */ 632512edc857SStefano Zampini Vec tvec; 632658da7f69SStefano Zampini 63279566063dSJacob Faibussowitsch PetscCall(KSPGetRhs(pcbddc->coarse_ksp, &tvec)); 63289566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(to, &array)); 63299566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(tvec, array)); 63309566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(to, &array)); 633158da7f69SStefano Zampini } 633258da7f69SStefano Zampini } else { 633358da7f69SStefano Zampini if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */ 63349566063dSJacob Faibussowitsch PetscCall(VecResetArray(from)); 633512edc857SStefano Zampini } 633612edc857SStefano Zampini } 63373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6338674ae819SStefano Zampini } 6339674ae819SStefano Zampini 6340d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCConstraintsSetUp(PC pc) 6341d71ae5a4SJacob Faibussowitsch { 6342f4f49eeaSPierre Jolivet PC_IS *pcis = (PC_IS *)pc->data; 6343674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 6344674ae819SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 6345984c4197SStefano Zampini /* one and zero */ 6346984c4197SStefano Zampini PetscScalar one = 1.0, zero = 0.0; 6347984c4197SStefano Zampini /* space to store constraints and their local indices */ 63489162d606SStefano Zampini PetscScalar *constraints_data; 63499162d606SStefano Zampini PetscInt *constraints_idxs, *constraints_idxs_B; 63509162d606SStefano Zampini PetscInt *constraints_idxs_ptr, *constraints_data_ptr; 63519162d606SStefano Zampini PetscInt *constraints_n; 6352984c4197SStefano Zampini /* iterators */ 6353b3d85658SStefano Zampini PetscInt i, j, k, total_counts, total_counts_cc, cum; 6354984c4197SStefano Zampini /* BLAS integers */ 6355e310c8b4SStefano Zampini PetscBLASInt lwork, lierr; 6356e310c8b4SStefano Zampini PetscBLASInt Blas_N, Blas_M, Blas_K, Blas_one = 1; 6357c4303822SStefano Zampini PetscBLASInt Blas_LDA, Blas_LDB, Blas_LDC; 6358727cdba6SStefano Zampini /* reuse */ 63590e6343abSStefano Zampini PetscInt olocal_primal_size, olocal_primal_size_cc; 63600e6343abSStefano Zampini PetscInt *olocal_primal_ref_node, *olocal_primal_ref_mult; 6361984c4197SStefano Zampini /* change of basis */ 6362b3d85658SStefano Zampini PetscBool qr_needed; 63639162d606SStefano Zampini PetscBT change_basis, qr_needed_idx; 6364984c4197SStefano Zampini /* auxiliary stuff */ 636564efe560SStefano Zampini PetscInt *nnz, *is_indices; 63668a0068c3SStefano Zampini PetscInt ncc; 6367984c4197SStefano Zampini /* some quantities */ 636845a1bb75SStefano Zampini PetscInt n_vertices, total_primal_vertices, valid_constraints; 6369a58a30b4SStefano Zampini PetscInt size_of_constraint, max_size_of_constraint = 0, max_constraints, temp_constraints; 637057715f18SStefano Zampini PetscReal tol; /* tolerance for retaining eigenmodes */ 6371984c4197SStefano Zampini 6372674ae819SStefano Zampini PetscFunctionBegin; 637357715f18SStefano Zampini tol = PetscSqrtReal(PETSC_SMALL); 63748e61c736SStefano Zampini /* Destroy Mat objects computed previously */ 63759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->ChangeOfBasisMatrix)); 63769566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->ConstraintMatrix)); 63779566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->switch_static_change)); 6378088faed8SStefano Zampini /* save info on constraints from previous setup (if any) */ 6379088faed8SStefano Zampini olocal_primal_size = pcbddc->local_primal_size; 63800e6343abSStefano Zampini olocal_primal_size_cc = pcbddc->local_primal_size_cc; 63819566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(olocal_primal_size_cc, &olocal_primal_ref_node, olocal_primal_size_cc, &olocal_primal_ref_mult)); 63829566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(olocal_primal_ref_node, pcbddc->local_primal_ref_node, olocal_primal_size_cc)); 63839566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(olocal_primal_ref_mult, pcbddc->local_primal_ref_mult, olocal_primal_size_cc)); 63849566063dSJacob Faibussowitsch PetscCall(PetscFree2(pcbddc->local_primal_ref_node, pcbddc->local_primal_ref_mult)); 63859566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->primal_indices_local_idxs)); 6386cf5a6209SStefano Zampini 6387cf5a6209SStefano Zampini if (!pcbddc->adaptive_selection) { 63889162d606SStefano Zampini IS ISForVertices, *ISForFaces, *ISForEdges; 6389cf5a6209SStefano Zampini MatNullSpace nearnullsp; 6390cf5a6209SStefano Zampini const Vec *nearnullvecs; 6391cf5a6209SStefano Zampini Vec *localnearnullsp; 6392cf5a6209SStefano Zampini PetscScalar *array; 639332fe681dSStefano Zampini PetscInt n_ISForFaces, n_ISForEdges, nnsp_size, o_nf, o_ne; 6394cf5a6209SStefano Zampini PetscBool nnsp_has_cnst; 6395674ae819SStefano Zampini /* LAPACK working arrays for SVD or POD */ 6396b3d85658SStefano Zampini PetscBool skip_lapack, boolforchange; 6397674ae819SStefano Zampini PetscScalar *work; 6398674ae819SStefano Zampini PetscReal *singular_vals; 6399674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX) 6400674ae819SStefano Zampini PetscReal *rwork; 6401674ae819SStefano Zampini #endif 640255080a34SStefano Zampini PetscScalar *temp_basis = NULL, *correlation_mat = NULL; 6403964fefecSStefano Zampini PetscBLASInt dummy_int = 1; 6404964fefecSStefano Zampini PetscScalar dummy_scalar = 1.; 640555080a34SStefano Zampini PetscBool use_pod = PETSC_FALSE; 6406674ae819SStefano Zampini 640755080a34SStefano Zampini /* MKL SVD with same input gives different results on different processes! */ 6408b88df2e7SBarry Smith #if defined(PETSC_MISSING_LAPACK_GESVD) || defined(PETSC_HAVE_MKL_LIBS) 640955080a34SStefano Zampini use_pod = PETSC_TRUE; 641055080a34SStefano Zampini #endif 6411674ae819SStefano Zampini /* Get index sets for faces, edges and vertices from graph */ 64129566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, &n_ISForFaces, &ISForFaces, &n_ISForEdges, &ISForEdges, &ISForVertices)); 641332fe681dSStefano Zampini o_nf = n_ISForFaces; 641432fe681dSStefano Zampini o_ne = n_ISForEdges; 641532fe681dSStefano Zampini n_vertices = 0; 641632fe681dSStefano Zampini if (ISForVertices) PetscCall(ISGetSize(ISForVertices, &n_vertices)); 6417e4d548c7SStefano Zampini /* print some info */ 64185c643e28SStefano Zampini if (pcbddc->dbg_flag && (!pcbddc->sub_schurs || pcbddc->sub_schurs_rebuild)) { 641932fe681dSStefano Zampini if (!pcbddc->dbg_viewer) pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc)); 64209566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphASCIIView(pcbddc->mat_graph, pcbddc->dbg_flag, pcbddc->dbg_viewer)); 64219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 64229566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "--------------------------------------------------------------\n")); 642332fe681dSStefano Zampini PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate vertices (%d)\n", PetscGlobalRank, n_vertices, pcbddc->use_vertices)); 642463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate edges (%d)\n", PetscGlobalRank, n_ISForEdges, pcbddc->use_edges)); 642563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate faces (%d)\n", PetscGlobalRank, n_ISForFaces, pcbddc->use_faces)); 64269566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 64279566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer)); 6428e4d548c7SStefano Zampini } 6429e4d548c7SStefano Zampini 643032fe681dSStefano Zampini if (!pcbddc->use_vertices) n_vertices = 0; 643132fe681dSStefano Zampini if (!pcbddc->use_edges) n_ISForEdges = 0; 643232fe681dSStefano Zampini if (!pcbddc->use_faces) n_ISForFaces = 0; 643370022509SStefano Zampini 6434674ae819SStefano Zampini /* check if near null space is attached to global mat */ 64356d9e27e4SStefano Zampini if (pcbddc->use_nnsp) { 64369566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pc->pmat, &nearnullsp)); 64376d9e27e4SStefano Zampini } else nearnullsp = NULL; 64386d9e27e4SStefano Zampini 6439674ae819SStefano Zampini if (nearnullsp) { 64409566063dSJacob Faibussowitsch PetscCall(MatNullSpaceGetVecs(nearnullsp, &nnsp_has_cnst, &nnsp_size, &nearnullvecs)); 6441f4ddd8eeSStefano Zampini /* remove any stored info */ 64429566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&pcbddc->onearnullspace)); 64439566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->onearnullvecs_state)); 6444f4ddd8eeSStefano Zampini /* store information for BDDC solver reuse */ 64459566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)nearnullsp)); 6446f4ddd8eeSStefano Zampini pcbddc->onearnullspace = nearnullsp; 64479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnsp_size, &pcbddc->onearnullvecs_state)); 644848a46eb9SPierre Jolivet for (i = 0; i < nnsp_size; i++) PetscCall(PetscObjectStateGet((PetscObject)nearnullvecs[i], &pcbddc->onearnullvecs_state[i])); 6449984c4197SStefano Zampini } else { /* if near null space is not provided BDDC uses constants by default */ 6450984c4197SStefano Zampini nnsp_size = 0; 6451674ae819SStefano Zampini nnsp_has_cnst = PETSC_TRUE; 6452674ae819SStefano Zampini } 6453984c4197SStefano Zampini /* get max number of constraints on a single cc */ 6454984c4197SStefano Zampini max_constraints = nnsp_size; 6455984c4197SStefano Zampini if (nnsp_has_cnst) max_constraints++; 6456984c4197SStefano Zampini 6457674ae819SStefano Zampini /* 6458674ae819SStefano Zampini Evaluate maximum storage size needed by the procedure 64599162d606SStefano Zampini - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]" 64609162d606SStefano Zampini - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]" 64619162d606SStefano Zampini There can be multiple constraints per connected component 6462674ae819SStefano Zampini */ 64639162d606SStefano Zampini ncc = n_vertices + n_ISForFaces + n_ISForEdges; 64649566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(ncc + 1, &constraints_idxs_ptr, ncc + 1, &constraints_data_ptr, ncc, &constraints_n)); 64659162d606SStefano Zampini 64669162d606SStefano Zampini total_counts = n_ISForFaces + n_ISForEdges; 64679162d606SStefano Zampini total_counts *= max_constraints; 6468674ae819SStefano Zampini total_counts += n_vertices; 64699566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(total_counts, &change_basis)); 64709162d606SStefano Zampini 6471674ae819SStefano Zampini total_counts = 0; 6472674ae819SStefano Zampini max_size_of_constraint = 0; 6473674ae819SStefano Zampini for (i = 0; i < n_ISForEdges + n_ISForFaces; i++) { 64749162d606SStefano Zampini IS used_is; 6475674ae819SStefano Zampini if (i < n_ISForEdges) { 64769162d606SStefano Zampini used_is = ISForEdges[i]; 6477674ae819SStefano Zampini } else { 64789162d606SStefano Zampini used_is = ISForFaces[i - n_ISForEdges]; 6479674ae819SStefano Zampini } 64809566063dSJacob Faibussowitsch PetscCall(ISGetSize(used_is, &j)); 6481674ae819SStefano Zampini total_counts += j; 6482674ae819SStefano Zampini max_size_of_constraint = PetscMax(j, max_size_of_constraint); 6483674ae819SStefano Zampini } 64849566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(total_counts * max_constraints + n_vertices, &constraints_data, total_counts + n_vertices, &constraints_idxs, total_counts + n_vertices, &constraints_idxs_B)); 64859162d606SStefano Zampini 6486984c4197SStefano Zampini /* get local part of global near null space vectors */ 64879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnsp_size, &localnearnullsp)); 6488984c4197SStefano Zampini for (k = 0; k < nnsp_size; k++) { 64899566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_N, &localnearnullsp[k])); 64909566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, nearnullvecs[k], localnearnullsp[k], INSERT_VALUES, SCATTER_FORWARD)); 64919566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, nearnullvecs[k], localnearnullsp[k], INSERT_VALUES, SCATTER_FORWARD)); 6492984c4197SStefano Zampini } 6493674ae819SStefano Zampini 6494242a89d7SStefano Zampini /* whether or not to skip lapack calls */ 6495242a89d7SStefano Zampini skip_lapack = PETSC_TRUE; 6496a773dcb8SStefano Zampini if (n_ISForFaces + n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE; 6497242a89d7SStefano Zampini 6498984c4197SStefano Zampini /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */ 6499a773dcb8SStefano Zampini if (!skip_lapack) { 6500674ae819SStefano Zampini PetscScalar temp_work; 6501911cabfeSStefano Zampini 650255080a34SStefano Zampini if (use_pod) { 6503984c4197SStefano Zampini /* Proper Orthogonal Decomposition (POD) using the snapshot method */ 65049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_constraints * max_constraints, &correlation_mat)); 65059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_constraints, &singular_vals)); 65069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_size_of_constraint * max_constraints, &temp_basis)); 6507674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX) 65089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(3 * max_constraints, &rwork)); 6509674ae819SStefano Zampini #endif 6510674ae819SStefano Zampini /* now we evaluate the optimal workspace using query with lwork=-1 */ 65119566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_constraints, &Blas_N)); 65129566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_constraints, &Blas_LDA)); 6513674ae819SStefano Zampini lwork = -1; 65149566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6515674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX) 6516792fecdfSBarry Smith PetscCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &Blas_N, correlation_mat, &Blas_LDA, singular_vals, &temp_work, &lwork, &lierr)); 6517674ae819SStefano Zampini #else 6518792fecdfSBarry Smith PetscCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &Blas_N, correlation_mat, &Blas_LDA, singular_vals, &temp_work, &lwork, rwork, &lierr)); 6519674ae819SStefano Zampini #endif 65209566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 652128b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in query to SYEV Lapack routine %d", (int)lierr); 652255080a34SStefano Zampini } else { 652355080a34SStefano Zampini #if !defined(PETSC_MISSING_LAPACK_GESVD) 6524674ae819SStefano Zampini /* SVD */ 6525674ae819SStefano Zampini PetscInt max_n, min_n; 6526674ae819SStefano Zampini max_n = max_size_of_constraint; 6527984c4197SStefano Zampini min_n = max_constraints; 6528984c4197SStefano Zampini if (max_size_of_constraint < max_constraints) { 6529674ae819SStefano Zampini min_n = max_size_of_constraint; 6530984c4197SStefano Zampini max_n = max_constraints; 6531674ae819SStefano Zampini } 65329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(min_n, &singular_vals)); 6533674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX) 65349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(5 * min_n, &rwork)); 6535674ae819SStefano Zampini #endif 6536674ae819SStefano Zampini /* now we evaluate the optimal workspace using query with lwork=-1 */ 6537674ae819SStefano Zampini lwork = -1; 65389566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_n, &Blas_M)); 65399566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(min_n, &Blas_N)); 65409566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_n, &Blas_LDA)); 65419566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6542674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX) 6543792fecdfSBarry 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)); 6544674ae819SStefano Zampini #else 6545792fecdfSBarry 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)); 6546674ae819SStefano Zampini #endif 65479566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 654828b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in query to GESVD Lapack routine %d", (int)lierr); 654955080a34SStefano Zampini #else 655055080a34SStefano Zampini SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "This should not happen"); 6551984c4197SStefano Zampini #endif /* on missing GESVD */ 655255080a34SStefano Zampini } 6553674ae819SStefano Zampini /* Allocate optimal workspace */ 65549566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(temp_work), &lwork)); 65559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(lwork, &work)); 6556674ae819SStefano Zampini } 6557674ae819SStefano Zampini /* Now we can loop on constraining sets */ 6558674ae819SStefano Zampini total_counts = 0; 65599162d606SStefano Zampini constraints_idxs_ptr[0] = 0; 65609162d606SStefano Zampini constraints_data_ptr[0] = 0; 6561674ae819SStefano Zampini /* vertices */ 65629162d606SStefano Zampini if (n_vertices) { 65639566063dSJacob Faibussowitsch PetscCall(ISGetIndices(ISForVertices, (const PetscInt **)&is_indices)); 65649566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(constraints_idxs, is_indices, n_vertices)); 6565674ae819SStefano Zampini for (i = 0; i < n_vertices; i++) { 65669162d606SStefano Zampini constraints_n[total_counts] = 1; 65679162d606SStefano Zampini constraints_data[total_counts] = 1.0; 65689162d606SStefano Zampini constraints_idxs_ptr[total_counts + 1] = constraints_idxs_ptr[total_counts] + 1; 65699162d606SStefano Zampini constraints_data_ptr[total_counts + 1] = constraints_data_ptr[total_counts] + 1; 6570674ae819SStefano Zampini total_counts++; 6571674ae819SStefano Zampini } 65729566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(ISForVertices, (const PetscInt **)&is_indices)); 6573674ae819SStefano Zampini } 6574984c4197SStefano Zampini 6575674ae819SStefano Zampini /* edges and faces */ 65769162d606SStefano Zampini total_counts_cc = total_counts; 6577911cabfeSStefano Zampini for (ncc = 0; ncc < n_ISForEdges + n_ISForFaces; ncc++) { 65789162d606SStefano Zampini IS used_is; 65799162d606SStefano Zampini PetscBool idxs_copied = PETSC_FALSE; 65809162d606SStefano Zampini 6581911cabfeSStefano Zampini if (ncc < n_ISForEdges) { 65829162d606SStefano Zampini used_is = ISForEdges[ncc]; 6583984c4197SStefano Zampini boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */ 6584674ae819SStefano Zampini } else { 65859162d606SStefano Zampini used_is = ISForFaces[ncc - n_ISForEdges]; 6586984c4197SStefano Zampini boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */ 6587674ae819SStefano Zampini } 6588674ae819SStefano Zampini temp_constraints = 0; /* zero the number of constraints I have on this conn comp */ 65899162d606SStefano Zampini 65909566063dSJacob Faibussowitsch PetscCall(ISGetSize(used_is, &size_of_constraint)); 659132fe681dSStefano Zampini if (!size_of_constraint) continue; 65929566063dSJacob Faibussowitsch PetscCall(ISGetIndices(used_is, (const PetscInt **)&is_indices)); 6593674ae819SStefano Zampini if (nnsp_has_cnst) { 65945b08dc53SStefano Zampini PetscScalar quad_value; 65959162d606SStefano Zampini 65969566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc], is_indices, size_of_constraint)); 65979162d606SStefano Zampini idxs_copied = PETSC_TRUE; 65989162d606SStefano Zampini 6599a773dcb8SStefano Zampini if (!pcbddc->use_nnsp_true) { 6600674ae819SStefano Zampini quad_value = (PetscScalar)(1.0 / PetscSqrtReal((PetscReal)size_of_constraint)); 6601a773dcb8SStefano Zampini } else { 6602a773dcb8SStefano Zampini quad_value = 1.0; 6603a773dcb8SStefano Zampini } 6604ad540459SPierre Jolivet for (j = 0; j < size_of_constraint; j++) constraints_data[constraints_data_ptr[total_counts_cc] + j] = quad_value; 66059162d606SStefano Zampini temp_constraints++; 6606674ae819SStefano Zampini total_counts++; 6607674ae819SStefano Zampini } 6608674ae819SStefano Zampini for (k = 0; k < nnsp_size; k++) { 6609984c4197SStefano Zampini PetscReal real_value; 66109162d606SStefano Zampini PetscScalar *ptr_to_data; 66119162d606SStefano Zampini 66129566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(localnearnullsp[k], (const PetscScalar **)&array)); 66139162d606SStefano Zampini ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc] + temp_constraints * size_of_constraint]; 6614ad540459SPierre Jolivet for (j = 0; j < size_of_constraint; j++) ptr_to_data[j] = array[is_indices[j]]; 66159566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(localnearnullsp[k], (const PetscScalar **)&array)); 6616984c4197SStefano Zampini /* check if array is null on the connected component */ 66179566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 6618792fecdfSBarry Smith PetscCallBLAS("BLASasum", real_value = BLASasum_(&Blas_N, ptr_to_data, &Blas_one)); 661957715f18SStefano Zampini if (real_value > tol * size_of_constraint) { /* keep indices and values */ 6620674ae819SStefano Zampini temp_constraints++; 6621674ae819SStefano Zampini total_counts++; 66229162d606SStefano Zampini if (!idxs_copied) { 66239566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc], is_indices, size_of_constraint)); 66249162d606SStefano Zampini idxs_copied = PETSC_TRUE; 6625674ae819SStefano Zampini } 6626674ae819SStefano Zampini } 66279162d606SStefano Zampini } 66289566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(used_is, (const PetscInt **)&is_indices)); 662945a1bb75SStefano Zampini valid_constraints = temp_constraints; 6630eb97c9d2SStefano Zampini if (!pcbddc->use_nnsp_true && temp_constraints) { 6631a773dcb8SStefano Zampini if (temp_constraints == 1) { /* just normalize the constraint */ 66329162d606SStefano Zampini PetscScalar norm, *ptr_to_data; 66339162d606SStefano Zampini 66349162d606SStefano Zampini ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]]; 66359566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 6636792fecdfSBarry Smith PetscCallBLAS("BLASdot", norm = BLASdot_(&Blas_N, ptr_to_data, &Blas_one, ptr_to_data, &Blas_one)); 6637a773dcb8SStefano Zampini norm = 1.0 / PetscSqrtReal(PetscRealPart(norm)); 6638792fecdfSBarry Smith PetscCallBLAS("BLASscal", BLASscal_(&Blas_N, &norm, ptr_to_data, &Blas_one)); 6639a773dcb8SStefano Zampini } else { /* perform SVD */ 66409162d606SStefano Zampini PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]]; 6641674ae819SStefano Zampini 664255080a34SStefano Zampini if (use_pod) { 6643984c4197SStefano Zampini /* SVD: Y = U*S*V^H -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag 6644984c4197SStefano Zampini POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2) 6645984c4197SStefano Zampini -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined 6646984c4197SStefano Zampini the constraints basis will differ (by a complex factor with absolute value equal to 1) 6647984c4197SStefano Zampini from that computed using LAPACKgesvd 6648984c4197SStefano Zampini -> This is due to a different computation of eigenvectors in LAPACKheev 6649984c4197SStefano Zampini -> The quality of the POD-computed basis will be the same */ 66509566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(correlation_mat, temp_constraints * temp_constraints)); 6651674ae819SStefano Zampini /* Store upper triangular part of correlation matrix */ 66529566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 66539566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6654674ae819SStefano Zampini for (j = 0; j < temp_constraints; j++) { 665548a46eb9SPierre 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)); 6656674ae819SStefano Zampini } 6657e310c8b4SStefano Zampini /* compute eigenvalues and eigenvectors of correlation matrix */ 66589566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_N)); 66599566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_LDA)); 6660674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX) 6661792fecdfSBarry Smith PetscCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &Blas_N, correlation_mat, &Blas_LDA, singular_vals, work, &lwork, &lierr)); 6662674ae819SStefano Zampini #else 6663792fecdfSBarry Smith PetscCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &Blas_N, correlation_mat, &Blas_LDA, singular_vals, work, &lwork, rwork, &lierr)); 6664674ae819SStefano Zampini #endif 66659566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 666628b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in SYEV Lapack routine %d", (int)lierr); 6667984c4197SStefano Zampini /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */ 6668674ae819SStefano Zampini j = 0; 666987b3baaaSStefano Zampini while (j < temp_constraints && singular_vals[j] / singular_vals[temp_constraints - 1] < tol) j++; 6670674ae819SStefano Zampini total_counts = total_counts - j; 667145a1bb75SStefano Zampini valid_constraints = temp_constraints - j; 6672e310c8b4SStefano Zampini /* scale and copy POD basis into used quadrature memory */ 66739566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_M)); 66749566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_N)); 66759566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_K)); 66769566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 66779566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_LDB)); 66789566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDC)); 6679674ae819SStefano Zampini if (j < temp_constraints) { 6680984c4197SStefano Zampini PetscInt ii; 6681984c4197SStefano Zampini for (k = j; k < temp_constraints; k++) singular_vals[k] = 1.0 / PetscSqrtReal(singular_vals[k]); 66829566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6683792fecdfSBarry 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)); 66849566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 6685984c4197SStefano Zampini for (k = 0; k < temp_constraints - j; k++) { 6686ad540459SPierre 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]; 6687674ae819SStefano Zampini } 6688674ae819SStefano Zampini } 668955080a34SStefano Zampini } else { 669055080a34SStefano Zampini #if !defined(PETSC_MISSING_LAPACK_GESVD) 66919566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_M)); 66929566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_N)); 66939566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 66949566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6695674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX) 6696792fecdfSBarry 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)); 6697674ae819SStefano Zampini #else 6698792fecdfSBarry 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)); 6699674ae819SStefano Zampini #endif 670028b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in GESVD Lapack routine %d", (int)lierr); 67019566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 6702984c4197SStefano Zampini /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */ 6703e310c8b4SStefano Zampini k = temp_constraints; 6704e310c8b4SStefano Zampini if (k > size_of_constraint) k = size_of_constraint; 6705674ae819SStefano Zampini j = 0; 670687b3baaaSStefano Zampini while (j < k && singular_vals[k - j - 1] / singular_vals[0] < tol) j++; 670745a1bb75SStefano Zampini valid_constraints = k - j; 6708911cabfeSStefano Zampini total_counts = total_counts - temp_constraints + valid_constraints; 670955080a34SStefano Zampini #else 671055080a34SStefano Zampini SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "This should not happen"); 6711984c4197SStefano Zampini #endif /* on missing GESVD */ 6712674ae819SStefano Zampini } 6713a773dcb8SStefano Zampini } 671455080a34SStefano Zampini } 67159162d606SStefano Zampini /* update pointers information */ 67169162d606SStefano Zampini if (valid_constraints) { 67179162d606SStefano Zampini constraints_n[total_counts_cc] = valid_constraints; 67189162d606SStefano Zampini constraints_idxs_ptr[total_counts_cc + 1] = constraints_idxs_ptr[total_counts_cc] + size_of_constraint; 67199162d606SStefano Zampini constraints_data_ptr[total_counts_cc + 1] = constraints_data_ptr[total_counts_cc] + size_of_constraint * valid_constraints; 67209162d606SStefano Zampini /* set change_of_basis flag */ 67213ba16761SJacob Faibussowitsch if (boolforchange) PetscCall(PetscBTSet(change_basis, total_counts_cc)); 6722b3d85658SStefano Zampini total_counts_cc++; 672345a1bb75SStefano Zampini } 672445a1bb75SStefano Zampini } 6725984c4197SStefano Zampini /* free workspace */ 67268f1c130eSStefano Zampini if (!skip_lapack) { 67279566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 6728984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX) 67299566063dSJacob Faibussowitsch PetscCall(PetscFree(rwork)); 6730984c4197SStefano Zampini #endif 67319566063dSJacob Faibussowitsch PetscCall(PetscFree(singular_vals)); 67329566063dSJacob Faibussowitsch PetscCall(PetscFree(correlation_mat)); 67339566063dSJacob Faibussowitsch PetscCall(PetscFree(temp_basis)); 6734984c4197SStefano Zampini } 673548a46eb9SPierre Jolivet for (k = 0; k < nnsp_size; k++) PetscCall(VecDestroy(&localnearnullsp[k])); 67369566063dSJacob Faibussowitsch PetscCall(PetscFree(localnearnullsp)); 6737cf5a6209SStefano Zampini /* free index sets of faces, edges and vertices */ 673832fe681dSStefano Zampini PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, &o_nf, &ISForFaces, &o_ne, &ISForEdges, &ISForVertices)); 673908122e43SStefano Zampini } else { 674008122e43SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 6741984c4197SStefano Zampini 674208122e43SStefano Zampini total_counts = 0; 674308122e43SStefano Zampini n_vertices = 0; 674448a46eb9SPierre Jolivet if (sub_schurs->is_vertices && pcbddc->use_vertices) PetscCall(ISGetLocalSize(sub_schurs->is_vertices, &n_vertices)); 674508122e43SStefano Zampini max_constraints = 0; 67469162d606SStefano Zampini total_counts_cc = 0; 674708122e43SStefano Zampini for (i = 0; i < sub_schurs->n_subs + n_vertices; i++) { 674808122e43SStefano Zampini total_counts += pcbddc->adaptive_constraints_n[i]; 67499162d606SStefano Zampini if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++; 675008122e43SStefano Zampini max_constraints = PetscMax(max_constraints, pcbddc->adaptive_constraints_n[i]); 675108122e43SStefano Zampini } 67529162d606SStefano Zampini constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr; 67539162d606SStefano Zampini constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr; 67549162d606SStefano Zampini constraints_idxs = pcbddc->adaptive_constraints_idxs; 67559162d606SStefano Zampini constraints_data = pcbddc->adaptive_constraints_data; 675674d5cdf7SStefano Zampini /* constraints_n differs from pcbddc->adaptive_constraints_n */ 67579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(total_counts_cc, &constraints_n)); 67589162d606SStefano Zampini total_counts_cc = 0; 67599162d606SStefano Zampini for (i = 0; i < sub_schurs->n_subs + n_vertices; i++) { 6760ad540459SPierre Jolivet if (pcbddc->adaptive_constraints_n[i]) constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i]; 676108122e43SStefano Zampini } 676208122e43SStefano Zampini 67638bec7fa6SStefano Zampini max_size_of_constraint = 0; 67649162d606SStefano 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]); 67659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(constraints_idxs_ptr[total_counts_cc], &constraints_idxs_B)); 676608122e43SStefano Zampini /* Change of basis */ 67679566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(total_counts_cc, &change_basis)); 676808122e43SStefano Zampini if (pcbddc->use_change_of_basis) { 676908122e43SStefano Zampini for (i = 0; i < sub_schurs->n_subs; i++) { 677048a46eb9SPierre Jolivet if (PetscBTLookup(sub_schurs->is_edge, i) || pcbddc->use_change_on_faces) PetscCall(PetscBTSet(change_basis, i + n_vertices)); 677108122e43SStefano Zampini } 677208122e43SStefano Zampini } 677308122e43SStefano Zampini } 6774984c4197SStefano Zampini pcbddc->local_primal_size = total_counts; 67759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->local_primal_size + pcbddc->benign_n, &pcbddc->primal_indices_local_idxs)); 677608122e43SStefano Zampini 67779162d606SStefano Zampini /* map constraints_idxs in boundary numbering */ 677832fe681dSStefano Zampini if (pcbddc->use_change_of_basis) { 67799566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(pcis->BtoNmap, IS_GTOLM_DROP, constraints_idxs_ptr[total_counts_cc], constraints_idxs, &i, constraints_idxs_B)); 678063a3b9bcSJacob 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); 678132fe681dSStefano Zampini } 6782674ae819SStefano Zampini 6783674ae819SStefano Zampini /* Create constraint matrix */ 67849566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &pcbddc->ConstraintMatrix)); 67859566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->ConstraintMatrix, MATAIJ)); 67869566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->ConstraintMatrix, pcbddc->local_primal_size, pcis->n, pcbddc->local_primal_size, pcis->n)); 6787984c4197SStefano Zampini 6788984c4197SStefano Zampini /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */ 6789a717540cSStefano Zampini /* determine if a QR strategy is needed for change of basis */ 67905a52fde0SStefano Zampini qr_needed = pcbddc->use_qr_single; 67919566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(total_counts_cc, &qr_needed_idx)); 6792984c4197SStefano Zampini total_primal_vertices = 0; 6793b3d85658SStefano Zampini pcbddc->local_primal_size_cc = 0; 67949162d606SStefano Zampini for (i = 0; i < total_counts_cc; i++) { 67959162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[i + 1] - constraints_idxs_ptr[i]; 679672b8c272SStefano Zampini if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) { 67979162d606SStefano Zampini pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]]; 6798b3d85658SStefano Zampini pcbddc->local_primal_size_cc += 1; 679964efe560SStefano Zampini } else if (PetscBTLookup(change_basis, i)) { 6800ad540459SPierre Jolivet for (k = 0; k < constraints_n[i]; k++) pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i] + k]; 6801b3d85658SStefano Zampini pcbddc->local_primal_size_cc += constraints_n[i]; 680291af6908SStefano Zampini if (constraints_n[i] > 1 || pcbddc->use_qr_single) { 68033ba16761SJacob Faibussowitsch PetscCall(PetscBTSet(qr_needed_idx, i)); 6804a717540cSStefano Zampini qr_needed = PETSC_TRUE; 6805a717540cSStefano Zampini } 6806fa434743SStefano Zampini } else { 6807b3d85658SStefano Zampini pcbddc->local_primal_size_cc += 1; 6808fa434743SStefano Zampini } 6809a717540cSStefano Zampini } 6810b371cd4fSStefano Zampini /* note that the local variable n_vertices used below stores the number of pointwise constraints */ 6811b371cd4fSStefano Zampini pcbddc->n_vertices = total_primal_vertices; 6812674ae819SStefano Zampini /* permute indices in order to have a sorted set of vertices */ 68139566063dSJacob Faibussowitsch PetscCall(PetscSortInt(total_primal_vertices, pcbddc->primal_indices_local_idxs)); 68149566063dSJacob 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)); 68159566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pcbddc->local_primal_ref_node, pcbddc->primal_indices_local_idxs, total_primal_vertices)); 68160e6343abSStefano Zampini for (i = 0; i < total_primal_vertices; i++) pcbddc->local_primal_ref_mult[i] = 1; 6817984c4197SStefano Zampini 6818984c4197SStefano Zampini /* nonzero structure of constraint matrix */ 681974d5cdf7SStefano Zampini /* and get reference dof for local constraints */ 68209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->local_primal_size, &nnz)); 6821984c4197SStefano Zampini for (i = 0; i < total_primal_vertices; i++) nnz[i] = 1; 682274d5cdf7SStefano Zampini 6823984c4197SStefano Zampini j = total_primal_vertices; 682474d5cdf7SStefano Zampini total_counts = total_primal_vertices; 6825b3d85658SStefano Zampini cum = total_primal_vertices; 68269162d606SStefano Zampini for (i = n_vertices; i < total_counts_cc; i++) { 68274641a718SStefano Zampini if (!PetscBTLookup(change_basis, i)) { 6828b3d85658SStefano Zampini pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]]; 6829b3d85658SStefano Zampini pcbddc->local_primal_ref_mult[cum] = constraints_n[i]; 6830b3d85658SStefano Zampini cum++; 68319162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[i + 1] - constraints_idxs_ptr[i]; 683274d5cdf7SStefano Zampini for (k = 0; k < constraints_n[i]; k++) { 683374d5cdf7SStefano Zampini pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i] + k]; 683474d5cdf7SStefano Zampini nnz[j + k] = size_of_constraint; 683574d5cdf7SStefano Zampini } 68369162d606SStefano Zampini j += constraints_n[i]; 6837674ae819SStefano Zampini } 6838674ae819SStefano Zampini } 68399566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix, 0, nnz)); 68409566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->ConstraintMatrix, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 68419566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 6842088faed8SStefano Zampini 6843674ae819SStefano Zampini /* set values in constraint matrix */ 684448a46eb9SPierre Jolivet for (i = 0; i < total_primal_vertices; i++) PetscCall(MatSetValue(pcbddc->ConstraintMatrix, i, pcbddc->local_primal_ref_node[i], 1.0, INSERT_VALUES)); 6845984c4197SStefano Zampini total_counts = total_primal_vertices; 68469162d606SStefano Zampini for (i = n_vertices; i < total_counts_cc; i++) { 68474641a718SStefano Zampini if (!PetscBTLookup(change_basis, i)) { 68489162d606SStefano Zampini PetscInt *cols; 68499162d606SStefano Zampini 68509162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[i + 1] - constraints_idxs_ptr[i]; 68519162d606SStefano Zampini cols = constraints_idxs + constraints_idxs_ptr[i]; 68529162d606SStefano Zampini for (k = 0; k < constraints_n[i]; k++) { 68539162d606SStefano Zampini PetscInt row = total_counts + k; 68549162d606SStefano Zampini PetscScalar *vals; 68559162d606SStefano Zampini 68569162d606SStefano Zampini vals = constraints_data + constraints_data_ptr[i] + k * size_of_constraint; 68579566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->ConstraintMatrix, 1, &row, size_of_constraint, cols, vals, INSERT_VALUES)); 68589162d606SStefano Zampini } 68599162d606SStefano Zampini total_counts += constraints_n[i]; 6860674ae819SStefano Zampini } 6861674ae819SStefano Zampini } 6862674ae819SStefano Zampini /* assembling */ 68639566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pcbddc->ConstraintMatrix, MAT_FINAL_ASSEMBLY)); 68649566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->ConstraintMatrix, MAT_FINAL_ASSEMBLY)); 68659566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(pcbddc->ConstraintMatrix, (PetscObject)pc, "-pc_bddc_constraint_mat_view")); 6866088faed8SStefano Zampini 6867674ae819SStefano Zampini /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */ 6868674ae819SStefano Zampini if (pcbddc->use_change_of_basis) { 6869026de310SStefano Zampini /* dual and primal dofs on a single cc */ 6870984c4197SStefano Zampini PetscInt dual_dofs, primal_dofs; 6871984c4197SStefano Zampini /* working stuff for GEQRF */ 68725a52fde0SStefano Zampini PetscScalar *qr_basis = NULL, *qr_tau = NULL, *qr_work = NULL, lqr_work_t; 6873984c4197SStefano Zampini PetscBLASInt lqr_work; 6874984c4197SStefano Zampini /* working stuff for UNGQR */ 68753c377650SSatish Balay PetscScalar *gqr_work = NULL, lgqr_work_t = 0.0; 6876984c4197SStefano Zampini PetscBLASInt lgqr_work; 6877984c4197SStefano Zampini /* working stuff for TRTRS */ 68785a52fde0SStefano Zampini PetscScalar *trs_rhs = NULL; 68793f08241aSStefano Zampini PetscBLASInt Blas_NRHS; 6880984c4197SStefano Zampini /* pointers for values insertion into change of basis matrix */ 6881984c4197SStefano Zampini PetscInt *start_rows, *start_cols; 6882984c4197SStefano Zampini PetscScalar *start_vals; 6883984c4197SStefano Zampini /* working stuff for values insertion */ 68844641a718SStefano Zampini PetscBT is_primal; 688564efe560SStefano Zampini PetscInt *aux_primal_numbering_B; 6886906d46d4SStefano Zampini /* matrix sizes */ 6887906d46d4SStefano Zampini PetscInt global_size, local_size; 6888906d46d4SStefano Zampini /* temporary change of basis */ 6889906d46d4SStefano Zampini Mat localChangeOfBasisMatrix; 6890cf5a6209SStefano Zampini /* extra space for debugging */ 68915a52fde0SStefano Zampini PetscScalar *dbg_work = NULL; 6892984c4197SStefano Zampini 68939566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &localChangeOfBasisMatrix)); 68949566063dSJacob Faibussowitsch PetscCall(MatSetType(localChangeOfBasisMatrix, MATAIJ)); 68959566063dSJacob Faibussowitsch PetscCall(MatSetSizes(localChangeOfBasisMatrix, pcis->n, pcis->n, pcis->n, pcis->n)); 6896906d46d4SStefano Zampini /* nonzeros for local mat */ 68979566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n, &nnz)); 68981dd7afcfSStefano Zampini if (!pcbddc->benign_change || pcbddc->fake_change) { 6899bbb9e6c6SStefano Zampini for (i = 0; i < pcis->n; i++) nnz[i] = 1; 69001dd7afcfSStefano Zampini } else { 69011dd7afcfSStefano Zampini const PetscInt *ii; 69021dd7afcfSStefano Zampini PetscInt n; 69031dd7afcfSStefano Zampini PetscBool flg_row; 69049566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(pcbddc->benign_change, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, NULL, &flg_row)); 69051dd7afcfSStefano Zampini for (i = 0; i < n; i++) nnz[i] = ii[i + 1] - ii[i]; 69069566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(pcbddc->benign_change, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, NULL, &flg_row)); 69071dd7afcfSStefano Zampini } 69089162d606SStefano Zampini for (i = n_vertices; i < total_counts_cc; i++) { 6909a717540cSStefano Zampini if (PetscBTLookup(change_basis, i)) { 69109162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[i + 1] - constraints_idxs_ptr[i]; 6911a717540cSStefano Zampini if (PetscBTLookup(qr_needed_idx, i)) { 69129162d606SStefano Zampini for (j = 0; j < size_of_constraint; j++) nnz[constraints_idxs[constraints_idxs_ptr[i] + j]] = size_of_constraint; 6913a717540cSStefano Zampini } else { 69149162d606SStefano Zampini nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint; 69159162d606SStefano Zampini for (j = 1; j < size_of_constraint; j++) nnz[constraints_idxs[constraints_idxs_ptr[i] + j]] = 2; 6916a717540cSStefano Zampini } 6917a717540cSStefano Zampini } 6918a717540cSStefano Zampini } 69199566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(localChangeOfBasisMatrix, 0, nnz)); 69209566063dSJacob Faibussowitsch PetscCall(MatSetOption(localChangeOfBasisMatrix, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 69219566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 69221dd7afcfSStefano Zampini /* Set interior change in the matrix */ 69231dd7afcfSStefano Zampini if (!pcbddc->benign_change || pcbddc->fake_change) { 692448a46eb9SPierre Jolivet for (i = 0; i < pcis->n; i++) PetscCall(MatSetValue(localChangeOfBasisMatrix, i, i, 1.0, INSERT_VALUES)); 69251dd7afcfSStefano Zampini } else { 69261dd7afcfSStefano Zampini const PetscInt *ii, *jj; 69271dd7afcfSStefano Zampini PetscScalar *aa; 69281dd7afcfSStefano Zampini PetscInt n; 69291dd7afcfSStefano Zampini PetscBool flg_row; 69309566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(pcbddc->benign_change, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &flg_row)); 69319566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(pcbddc->benign_change, &aa)); 693248a46eb9SPierre 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)); 69339566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(pcbddc->benign_change, &aa)); 69349566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(pcbddc->benign_change, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &flg_row)); 69351dd7afcfSStefano Zampini } 6936a717540cSStefano Zampini 6937a717540cSStefano Zampini if (pcbddc->dbg_flag) { 69389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "--------------------------------------------------------------\n")); 69399566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Checking change of basis computation for subdomain %04d\n", PetscGlobalRank)); 6940a717540cSStefano Zampini } 6941a717540cSStefano Zampini 6942a717540cSStefano Zampini /* Now we loop on the constraints which need a change of basis */ 6943a717540cSStefano Zampini /* 6944a717540cSStefano Zampini Change of basis matrix is evaluated similarly to the FIRST APPROACH in 6945a717540cSStefano Zampini Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1) 6946a717540cSStefano Zampini 69477c625d9fSStefano Zampini Basic blocks of change of basis matrix T computed: 6948a717540cSStefano Zampini 69497c625d9fSStefano 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) 6950a6b551f4SStefano Zampini 6951a6b551f4SStefano Zampini | 1 0 ... 0 s_1/S | 6952a6b551f4SStefano Zampini | 0 1 ... 0 s_2/S | 6953a717540cSStefano Zampini | ... | 6954a6b551f4SStefano Zampini | 0 ... 1 s_{n-1}/S | 6955a6b551f4SStefano Zampini | -s_1/s_n ... -s_{n-1}/s_n s_n/S | 6956a717540cSStefano Zampini 6957a6b551f4SStefano Zampini with S = \sum_{i=1}^n s_i^2 6958a6b551f4SStefano Zampini NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering 6959a6b551f4SStefano Zampini in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering 6960a6b551f4SStefano Zampini 6961a6b551f4SStefano Zampini - QR decomposition of constraints otherwise 6962a717540cSStefano Zampini */ 69635a52fde0SStefano Zampini if (qr_needed && max_size_of_constraint) { 6964984c4197SStefano Zampini /* space to store Q */ 69659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_size_of_constraint * max_size_of_constraint, &qr_basis)); 69664e64d54eSstefano_zampini /* array to store scaling factors for reflectors */ 69679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_constraints, &qr_tau)); 6968984c4197SStefano Zampini /* first we issue queries for optimal work */ 69699566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_size_of_constraint, &Blas_M)); 69709566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_constraints, &Blas_N)); 69719566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_size_of_constraint, &Blas_LDA)); 6972984c4197SStefano Zampini lqr_work = -1; 6973792fecdfSBarry Smith PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&Blas_M, &Blas_N, qr_basis, &Blas_LDA, qr_tau, &lqr_work_t, &lqr_work, &lierr)); 697428b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in query to GEQRF Lapack routine %d", (int)lierr); 69759566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t), &lqr_work)); 697659b05608SBarry Smith PetscCall(PetscMalloc1(lqr_work, &qr_work)); 6977984c4197SStefano Zampini lgqr_work = -1; 69789566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_size_of_constraint, &Blas_M)); 69799566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_size_of_constraint, &Blas_N)); 69809566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_constraints, &Blas_K)); 69819566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_size_of_constraint, &Blas_LDA)); 69823f08241aSStefano Zampini if (Blas_K > Blas_M) Blas_K = Blas_M; /* adjust just for computing optimal work */ 6983792fecdfSBarry Smith PetscCallBLAS("LAPACKorgqr", LAPACKorgqr_(&Blas_M, &Blas_N, &Blas_K, qr_basis, &Blas_LDA, qr_tau, &lgqr_work_t, &lgqr_work, &lierr)); 698428b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in query to ORGQR/UNGQR Lapack routine %d", (int)lierr); 69859566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t), &lgqr_work)); 698659b05608SBarry Smith PetscCall(PetscMalloc1(lgqr_work, &gqr_work)); 6987984c4197SStefano Zampini /* array to store rhs and solution of triangular solver */ 69889566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_constraints * max_constraints, &trs_rhs)); 6989a717540cSStefano Zampini /* allocating workspace for check */ 699048a46eb9SPierre Jolivet if (pcbddc->dbg_flag) PetscCall(PetscMalloc1(max_size_of_constraint * (max_constraints + max_size_of_constraint), &dbg_work)); 6991a717540cSStefano Zampini } 6992984c4197SStefano Zampini /* array to store whether a node is primal or not */ 69939566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(pcis->n_B, &is_primal)); 69949566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(total_primal_vertices, &aux_primal_numbering_B)); 69959566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(pcis->BtoNmap, IS_GTOLM_DROP, total_primal_vertices, pcbddc->local_primal_ref_node, &i, aux_primal_numbering_B)); 699663a3b9bcSJacob 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); 699748a46eb9SPierre Jolivet for (i = 0; i < total_primal_vertices; i++) PetscCall(PetscBTSet(is_primal, aux_primal_numbering_B[i])); 69989566063dSJacob Faibussowitsch PetscCall(PetscFree(aux_primal_numbering_B)); 6999984c4197SStefano Zampini 7000a717540cSStefano Zampini /* loop on constraints and see whether or not they need a change of basis and compute it */ 70019162d606SStefano Zampini for (total_counts = n_vertices; total_counts < total_counts_cc; total_counts++) { 70029162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[total_counts + 1] - constraints_idxs_ptr[total_counts]; 70034641a718SStefano Zampini if (PetscBTLookup(change_basis, total_counts)) { 7004984c4197SStefano Zampini /* get constraint info */ 70059162d606SStefano Zampini primal_dofs = constraints_n[total_counts]; 7006984c4197SStefano Zampini dual_dofs = size_of_constraint - primal_dofs; 7007984c4197SStefano Zampini 700848a46eb9SPierre 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)); 7009984c4197SStefano Zampini 7010fa434743SStefano Zampini if (PetscBTLookup(qr_needed_idx, total_counts)) { /* QR */ 7011a717540cSStefano Zampini 7012a717540cSStefano Zampini /* copy quadrature constraints for change of basis check */ 701348a46eb9SPierre Jolivet if (pcbddc->dbg_flag) PetscCall(PetscArraycpy(dbg_work, &constraints_data[constraints_data_ptr[total_counts]], size_of_constraint * primal_dofs)); 7014984c4197SStefano Zampini /* copy temporary constraints into larger work vector (in order to store all columns of Q) */ 70159566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(qr_basis, &constraints_data[constraints_data_ptr[total_counts]], size_of_constraint * primal_dofs)); 7016984c4197SStefano Zampini 7017984c4197SStefano Zampini /* compute QR decomposition of constraints */ 70189566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_M)); 70199566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_N)); 70209566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 70219566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 7022792fecdfSBarry Smith PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&Blas_M, &Blas_N, qr_basis, &Blas_LDA, qr_tau, qr_work, &lqr_work, &lierr)); 702328b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in GEQRF Lapack routine %d", (int)lierr); 70249566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 7025984c4197SStefano Zampini 7026a5b23f4aSJose E. Roman /* explicitly compute R^-T */ 70279566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(trs_rhs, primal_dofs * primal_dofs)); 7028984c4197SStefano Zampini for (j = 0; j < primal_dofs; j++) trs_rhs[j * (primal_dofs + 1)] = 1.0; 70299566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_N)); 70309566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_NRHS)); 70319566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 70329566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_LDB)); 70339566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 7034792fecdfSBarry Smith PetscCallBLAS("LAPACKtrtrs", LAPACKtrtrs_("U", "T", "N", &Blas_N, &Blas_NRHS, qr_basis, &Blas_LDA, trs_rhs, &Blas_LDB, &lierr)); 703528b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in TRTRS Lapack routine %d", (int)lierr); 70369566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 7037984c4197SStefano Zampini 7038a717540cSStefano Zampini /* explicitly compute all columns of Q (Q = [Q1 | Q2]) overwriting QR factorization in qr_basis */ 70399566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_M)); 70409566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 70419566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_K)); 70429566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 70439566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 7044792fecdfSBarry Smith PetscCallBLAS("LAPACKorgqr", LAPACKorgqr_(&Blas_M, &Blas_N, &Blas_K, qr_basis, &Blas_LDA, qr_tau, gqr_work, &lgqr_work, &lierr)); 704528b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ORGQR/UNGQR Lapack routine %d", (int)lierr); 70469566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 7047984c4197SStefano Zampini 7048984c4197SStefano Zampini /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints 7049984c4197SStefano Zampini i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below) 7050984c4197SStefano Zampini where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */ 70519566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_M)); 70529566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_N)); 70539566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_K)); 70549566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 70559566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_LDB)); 70569566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDC)); 70579566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 7058792fecdfSBarry 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)); 70599566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 70609566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(qr_basis, &constraints_data[constraints_data_ptr[total_counts]], size_of_constraint * primal_dofs)); 7061984c4197SStefano Zampini 7062984c4197SStefano Zampini /* insert values in change of basis matrix respecting global ordering of new primal dofs */ 70639162d606SStefano Zampini start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]]; 7064984c4197SStefano Zampini /* insert cols for primal dofs */ 7065984c4197SStefano Zampini for (j = 0; j < primal_dofs; j++) { 7066984c4197SStefano Zampini start_vals = &qr_basis[j * size_of_constraint]; 70679162d606SStefano Zampini start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts] + j]; 70689566063dSJacob Faibussowitsch PetscCall(MatSetValues(localChangeOfBasisMatrix, size_of_constraint, start_rows, 1, start_cols, start_vals, INSERT_VALUES)); 7069984c4197SStefano Zampini } 7070984c4197SStefano Zampini /* insert cols for dual dofs */ 7071984c4197SStefano Zampini for (j = 0, k = 0; j < dual_dofs; k++) { 70729162d606SStefano Zampini if (!PetscBTLookup(is_primal, constraints_idxs_B[constraints_idxs_ptr[total_counts] + k])) { 7073984c4197SStefano Zampini start_vals = &qr_basis[(primal_dofs + j) * size_of_constraint]; 70749162d606SStefano Zampini start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts] + k]; 70759566063dSJacob Faibussowitsch PetscCall(MatSetValues(localChangeOfBasisMatrix, size_of_constraint, start_rows, 1, start_cols, start_vals, INSERT_VALUES)); 7076984c4197SStefano Zampini j++; 7077674ae819SStefano Zampini } 7078674ae819SStefano Zampini } 7079984c4197SStefano Zampini 7080984c4197SStefano Zampini /* check change of basis */ 7081984c4197SStefano Zampini if (pcbddc->dbg_flag) { 7082984c4197SStefano Zampini PetscInt ii, jj; 7083984c4197SStefano Zampini PetscBool valid_qr = PETSC_TRUE; 70849566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_M)); 70859566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 70869566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_K)); 70879566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 70889566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDB)); 70899566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_LDC)); 70909566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 7091792fecdfSBarry 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)); 70929566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 7093984c4197SStefano Zampini for (jj = 0; jj < size_of_constraint; jj++) { 7094984c4197SStefano Zampini for (ii = 0; ii < primal_dofs; ii++) { 7095cf5a6209SStefano Zampini if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint * primal_dofs + jj * primal_dofs + ii]) > 1.e-12) valid_qr = PETSC_FALSE; 7096c068d9bbSLisandro 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; 7097674ae819SStefano Zampini } 7098674ae819SStefano Zampini } 7099984c4197SStefano Zampini if (!valid_qr) { 71009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "\t-> wrong change of basis!\n")); 7101984c4197SStefano Zampini for (jj = 0; jj < size_of_constraint; jj++) { 7102984c4197SStefano Zampini for (ii = 0; ii < primal_dofs; ii++) { 7103cf5a6209SStefano Zampini if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint * primal_dofs + jj * primal_dofs + ii]) > 1.e-12) { 710463a3b9bcSJacob 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]))); 7105674ae819SStefano Zampini } 7106c068d9bbSLisandro Dalcin if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint * primal_dofs + jj * primal_dofs + ii] - (PetscReal)1) > 1.e-12) { 710763a3b9bcSJacob 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]))); 7108984c4197SStefano Zampini } 7109984c4197SStefano Zampini } 7110984c4197SStefano Zampini } 7111674ae819SStefano Zampini } else { 71129566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "\t-> right change of basis!\n")); 7113674ae819SStefano Zampini } 7114674ae819SStefano Zampini } 7115a717540cSStefano Zampini } else { /* simple transformation block */ 7116a717540cSStefano Zampini PetscInt row, col; 7117a6b551f4SStefano Zampini PetscScalar val, norm; 7118a6b551f4SStefano Zampini 71199566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 7120792fecdfSBarry 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)); 7121a717540cSStefano Zampini for (j = 0; j < size_of_constraint; j++) { 71229162d606SStefano Zampini PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts] + j]; 71239162d606SStefano Zampini row = constraints_idxs[constraints_idxs_ptr[total_counts] + j]; 7124bbb9e6c6SStefano Zampini if (!PetscBTLookup(is_primal, row_B)) { 71259162d606SStefano Zampini col = constraints_idxs[constraints_idxs_ptr[total_counts]]; 71269566063dSJacob Faibussowitsch PetscCall(MatSetValue(localChangeOfBasisMatrix, row, row, 1.0, INSERT_VALUES)); 71279566063dSJacob Faibussowitsch PetscCall(MatSetValue(localChangeOfBasisMatrix, row, col, constraints_data[constraints_data_ptr[total_counts] + j] / norm, INSERT_VALUES)); 7128a717540cSStefano Zampini } else { 7129a717540cSStefano Zampini for (k = 0; k < size_of_constraint; k++) { 71309162d606SStefano Zampini col = constraints_idxs[constraints_idxs_ptr[total_counts] + k]; 7131a717540cSStefano Zampini if (row != col) { 71329162d606SStefano Zampini val = -constraints_data[constraints_data_ptr[total_counts] + k] / constraints_data[constraints_data_ptr[total_counts]]; 7133a717540cSStefano Zampini } else { 71349162d606SStefano Zampini val = constraints_data[constraints_data_ptr[total_counts]] / norm; 7135a717540cSStefano Zampini } 71369566063dSJacob Faibussowitsch PetscCall(MatSetValue(localChangeOfBasisMatrix, row, col, val, INSERT_VALUES)); 7137a717540cSStefano Zampini } 7138a717540cSStefano Zampini } 7139a717540cSStefano Zampini } 714048a46eb9SPierre Jolivet if (pcbddc->dbg_flag) PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "\t-> using standard change of basis\n")); 7141a717540cSStefano Zampini } 7142984c4197SStefano Zampini } else { 714348a46eb9SPierre 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)); 7144674ae819SStefano Zampini } 7145674ae819SStefano Zampini } 7146a717540cSStefano Zampini 7147a717540cSStefano Zampini /* free workspace */ 7148a717540cSStefano Zampini if (qr_needed) { 71491baa6e33SBarry Smith if (pcbddc->dbg_flag) PetscCall(PetscFree(dbg_work)); 71509566063dSJacob Faibussowitsch PetscCall(PetscFree(trs_rhs)); 71519566063dSJacob Faibussowitsch PetscCall(PetscFree(qr_tau)); 71529566063dSJacob Faibussowitsch PetscCall(PetscFree(qr_work)); 71539566063dSJacob Faibussowitsch PetscCall(PetscFree(gqr_work)); 71549566063dSJacob Faibussowitsch PetscCall(PetscFree(qr_basis)); 7155674ae819SStefano Zampini } 71569566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&is_primal)); 71579566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(localChangeOfBasisMatrix, MAT_FINAL_ASSEMBLY)); 71589566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(localChangeOfBasisMatrix, MAT_FINAL_ASSEMBLY)); 7159906d46d4SStefano Zampini 7160906d46d4SStefano Zampini /* assembling of global change of variable */ 716188c03ad3SStefano Zampini if (!pcbddc->fake_change) { 7162bbb9e6c6SStefano Zampini Mat tmat; 716316f15bc4SStefano Zampini PetscInt bs; 716416f15bc4SStefano Zampini 71659566063dSJacob Faibussowitsch PetscCall(VecGetSize(pcis->vec1_global, &global_size)); 71669566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(pcis->vec1_global, &local_size)); 71679566063dSJacob Faibussowitsch PetscCall(MatDuplicate(pc->pmat, MAT_DO_NOT_COPY_VALUES, &tmat)); 71689566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(tmat, localChangeOfBasisMatrix)); 71699566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(tmat, MAT_FINAL_ASSEMBLY)); 71709566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(tmat, MAT_FINAL_ASSEMBLY)); 71719566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)pc), &pcbddc->ChangeOfBasisMatrix)); 71729566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->ChangeOfBasisMatrix, MATAIJ)); 71739566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(pc->pmat, &bs)); 71749566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(pcbddc->ChangeOfBasisMatrix, bs)); 71759566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->ChangeOfBasisMatrix, local_size, local_size, global_size, global_size)); 71769566063dSJacob Faibussowitsch PetscCall(MatISSetMPIXAIJPreallocation_Private(tmat, pcbddc->ChangeOfBasisMatrix, PETSC_TRUE)); 71779566063dSJacob Faibussowitsch PetscCall(MatConvert(tmat, MATAIJ, MAT_REUSE_MATRIX, &pcbddc->ChangeOfBasisMatrix)); 71789566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tmat)); 71799566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_global, 0.0)); 71809566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_N, 1.0)); 71819566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_N, pcis->vec1_global, ADD_VALUES, SCATTER_REVERSE)); 71829566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_N, pcis->vec1_global, ADD_VALUES, SCATTER_REVERSE)); 71839566063dSJacob Faibussowitsch PetscCall(VecReciprocal(pcis->vec1_global)); 71849566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(pcbddc->ChangeOfBasisMatrix, pcis->vec1_global, NULL)); 718588c03ad3SStefano Zampini 7186906d46d4SStefano Zampini /* check */ 7187906d46d4SStefano Zampini if (pcbddc->dbg_flag) { 7188906d46d4SStefano Zampini PetscReal error; 7189906d46d4SStefano Zampini Vec x, x_change; 7190906d46d4SStefano Zampini 71919566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_global, &x)); 71929566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_global, &x_change)); 71939566063dSJacob Faibussowitsch PetscCall(VecSetRandom(x, NULL)); 71949566063dSJacob Faibussowitsch PetscCall(VecCopy(x, pcis->vec1_global)); 71959566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, x, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD)); 71969566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, x, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD)); 71979566063dSJacob Faibussowitsch PetscCall(MatMult(localChangeOfBasisMatrix, pcis->vec1_N, pcis->vec2_N)); 71989566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, pcis->vec2_N, x, INSERT_VALUES, SCATTER_REVERSE)); 71999566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, pcis->vec2_N, x, INSERT_VALUES, SCATTER_REVERSE)); 72009566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcis->vec1_global, x_change)); 72019566063dSJacob Faibussowitsch PetscCall(VecAXPY(x, -1.0, x_change)); 72029566063dSJacob Faibussowitsch PetscCall(VecNorm(x, NORM_INFINITY, &error)); 7203049d1499SBarry Smith PetscCheck(error <= PETSC_SMALL, PetscObjectComm((PetscObject)pc), PETSC_ERR_PLIB, "Error global vs local change on N: %1.6e", (double)error); 72049566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 72059566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x_change)); 7206906d46d4SStefano Zampini } 7207b96c3477SStefano Zampini /* adapt sub_schurs computed (if any) */ 7208b96c3477SStefano Zampini if (pcbddc->use_deluxe_scaling) { 7209b96c3477SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 7210bf3a8328SStefano Zampini 721108401ef6SPierre 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"); 7212b334f244SStefano Zampini if (sub_schurs && sub_schurs->S_Ej_all) { 7213ac632422SStefano Zampini Mat S_new, tmat; 7214bf3a8328SStefano Zampini IS is_all_N, is_V_Sall = NULL; 7215bbb9e6c6SStefano Zampini 72169566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(pcis->BtoNmap, sub_schurs->is_Ej_all, &is_all_N)); 72179566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(localChangeOfBasisMatrix, is_all_N, is_all_N, MAT_INITIAL_MATRIX, &tmat)); 7218bf3a8328SStefano Zampini if (pcbddc->deluxe_zerorows) { 7219bf3a8328SStefano Zampini ISLocalToGlobalMapping NtoSall; 7220bf3a8328SStefano Zampini IS is_V; 72219566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, pcbddc->n_vertices, pcbddc->local_primal_ref_node, PETSC_COPY_VALUES, &is_V)); 72229566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is_all_N, &NtoSall)); 72239566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(NtoSall, IS_GTOLM_DROP, is_V, &is_V_Sall)); 72249566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&NtoSall)); 72259566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_V)); 7226bf3a8328SStefano Zampini } 72279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_all_N)); 72289566063dSJacob Faibussowitsch PetscCall(MatPtAP(sub_schurs->S_Ej_all, tmat, MAT_INITIAL_MATRIX, 1.0, &S_new)); 72299566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sub_schurs->S_Ej_all)); 72309566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)S_new)); 7231bf3a8328SStefano Zampini if (pcbddc->deluxe_zerorows) { 7232bf3a8328SStefano Zampini const PetscScalar *array; 7233bf3a8328SStefano Zampini const PetscInt *idxs_V, *idxs_all; 7234bf3a8328SStefano Zampini PetscInt i, n_V; 7235bf3a8328SStefano Zampini 72369566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumnsIS(S_new, is_V_Sall, 1., NULL, NULL)); 72379566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is_V_Sall, &n_V)); 72389566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is_V_Sall, &idxs_V)); 72399566063dSJacob Faibussowitsch PetscCall(ISGetIndices(sub_schurs->is_Ej_all, &idxs_all)); 72409566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(pcis->D, &array)); 7241b087196eSStefano Zampini for (i = 0; i < n_V; i++) { 7242b087196eSStefano Zampini PetscScalar val; 7243b087196eSStefano Zampini PetscInt idx; 7244b087196eSStefano Zampini 7245b087196eSStefano Zampini idx = idxs_V[i]; 7246b087196eSStefano Zampini val = array[idxs_all[idxs_V[i]]]; 72479566063dSJacob Faibussowitsch PetscCall(MatSetValue(S_new, idx, idx, val, INSERT_VALUES)); 7248b087196eSStefano Zampini } 72499566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(S_new, MAT_FINAL_ASSEMBLY)); 72509566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(S_new, MAT_FINAL_ASSEMBLY)); 72519566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(pcis->D, &array)); 72529566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(sub_schurs->is_Ej_all, &idxs_all)); 72539566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is_V_Sall, &idxs_V)); 7254bf3a8328SStefano Zampini } 7255ac632422SStefano Zampini sub_schurs->S_Ej_all = S_new; 72569566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_new)); 7257ac632422SStefano Zampini if (sub_schurs->sum_S_Ej_all) { 72589566063dSJacob Faibussowitsch PetscCall(MatPtAP(sub_schurs->sum_S_Ej_all, tmat, MAT_INITIAL_MATRIX, 1.0, &S_new)); 72599566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sub_schurs->sum_S_Ej_all)); 72609566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)S_new)); 72611baa6e33SBarry Smith if (pcbddc->deluxe_zerorows) PetscCall(MatZeroRowsColumnsIS(S_new, is_V_Sall, 1., NULL, NULL)); 7262ac632422SStefano Zampini sub_schurs->sum_S_Ej_all = S_new; 72639566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_new)); 7264ac632422SStefano Zampini } 72659566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_V_Sall)); 72669566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tmat)); 7267b96c3477SStefano Zampini } 7268c9db6a07SStefano Zampini /* destroy any change of basis context in sub_schurs */ 7269b334f244SStefano Zampini if (sub_schurs && sub_schurs->change) { 7270c9db6a07SStefano Zampini PetscInt i; 7271c9db6a07SStefano Zampini 727248a46eb9SPierre Jolivet for (i = 0; i < sub_schurs->n_subs; i++) PetscCall(KSPDestroy(&sub_schurs->change[i])); 72739566063dSJacob Faibussowitsch PetscCall(PetscFree(sub_schurs->change)); 7274c9db6a07SStefano Zampini } 7275b96c3477SStefano Zampini } 727616909a7fSStefano Zampini if (pcbddc->switch_static) { /* need to save the local change */ 727716909a7fSStefano Zampini pcbddc->switch_static_change = localChangeOfBasisMatrix; 727816909a7fSStefano Zampini } else { 72799566063dSJacob Faibussowitsch PetscCall(MatDestroy(&localChangeOfBasisMatrix)); 728016909a7fSStefano Zampini } 72811dd7afcfSStefano Zampini /* determine if any process has changed the pressures locally */ 728227b6a85dSStefano Zampini pcbddc->change_interior = pcbddc->benign_have_null; 728372b8c272SStefano Zampini } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */ 72849566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->ConstraintMatrix)); 728572b8c272SStefano Zampini pcbddc->ConstraintMatrix = localChangeOfBasisMatrix; 728672b8c272SStefano Zampini pcbddc->use_qr_single = qr_needed; 728772b8c272SStefano Zampini } 72881dd7afcfSStefano Zampini } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) { 728927b6a85dSStefano Zampini if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) { 72909566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix)); 7291b9b85e73SStefano Zampini pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix; 7292906d46d4SStefano Zampini } else { 72931dd7afcfSStefano Zampini Mat benign_global = NULL; 729427b6a85dSStefano Zampini if (pcbddc->benign_have_null) { 72951dd7afcfSStefano Zampini Mat M; 72961dd7afcfSStefano Zampini 72979e9b7b1fSStefano Zampini pcbddc->change_interior = PETSC_TRUE; 72989566063dSJacob Faibussowitsch PetscCall(VecCopy(matis->counter, pcis->vec1_N)); 72999566063dSJacob Faibussowitsch PetscCall(VecReciprocal(pcis->vec1_N)); 73009566063dSJacob Faibussowitsch PetscCall(MatDuplicate(pc->pmat, MAT_DO_NOT_COPY_VALUES, &benign_global)); 73019e9b7b1fSStefano Zampini if (pcbddc->benign_change) { 73029566063dSJacob Faibussowitsch PetscCall(MatDuplicate(pcbddc->benign_change, MAT_COPY_VALUES, &M)); 73039566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(M, pcis->vec1_N, NULL)); 7304906d46d4SStefano Zampini } else { 73059566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, pcis->n, pcis->n, 1, NULL, &M)); 73069566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(M, pcis->vec1_N, INSERT_VALUES)); 7307906d46d4SStefano Zampini } 73089566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(benign_global, M)); 73099566063dSJacob Faibussowitsch PetscCall(MatDestroy(&M)); 73109566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(benign_global, MAT_FINAL_ASSEMBLY)); 73119566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(benign_global, MAT_FINAL_ASSEMBLY)); 73121dd7afcfSStefano Zampini } 73131dd7afcfSStefano Zampini if (pcbddc->user_ChangeOfBasisMatrix) { 73149566063dSJacob Faibussowitsch PetscCall(MatMatMult(pcbddc->user_ChangeOfBasisMatrix, benign_global, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &pcbddc->ChangeOfBasisMatrix)); 73159566063dSJacob Faibussowitsch PetscCall(MatDestroy(&benign_global)); 731627b6a85dSStefano Zampini } else if (pcbddc->benign_have_null) { 73171dd7afcfSStefano Zampini pcbddc->ChangeOfBasisMatrix = benign_global; 73181dd7afcfSStefano Zampini } 73191dd7afcfSStefano Zampini } 732016909a7fSStefano Zampini if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */ 732116909a7fSStefano Zampini IS is_global; 732216909a7fSStefano Zampini const PetscInt *gidxs; 732316909a7fSStefano Zampini 73249566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->rmapping, &gidxs)); 73259566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), pcis->n, gidxs, PETSC_COPY_VALUES, &is_global)); 73269566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->rmapping, &gidxs)); 73279566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix, is_global, is_global, &pcbddc->switch_static_change)); 73289566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_global)); 732916909a7fSStefano Zampini } 73301dd7afcfSStefano Zampini } 733148a46eb9SPierre Jolivet if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->work_change)); 7332a717540cSStefano Zampini 733372b8c272SStefano Zampini if (!pcbddc->fake_change) { 73344f1b2e48SStefano Zampini /* add pressure dofs to set of primal nodes for numbering purposes */ 73354f1b2e48SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) { 73364f1b2e48SStefano Zampini pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i]; 73374f1b2e48SStefano Zampini pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i]; 7338019a44ceSStefano Zampini pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1; 7339019a44ceSStefano Zampini pcbddc->local_primal_size_cc++; 7340019a44ceSStefano Zampini pcbddc->local_primal_size++; 7341019a44ceSStefano Zampini } 7342019a44ceSStefano Zampini 7343019a44ceSStefano Zampini /* check if a new primal space has been introduced (also take into account benign trick) */ 7344727cdba6SStefano Zampini pcbddc->new_primal_space_local = PETSC_TRUE; 7345727cdba6SStefano Zampini if (olocal_primal_size == pcbddc->local_primal_size) { 73469566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(pcbddc->local_primal_ref_node, olocal_primal_ref_node, olocal_primal_size_cc, &pcbddc->new_primal_space_local)); 7347c1c8e736SStefano Zampini pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local); 73480e6343abSStefano Zampini if (!pcbddc->new_primal_space_local) { 73499566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(pcbddc->local_primal_ref_mult, olocal_primal_ref_mult, olocal_primal_size_cc, &pcbddc->new_primal_space_local)); 7350727cdba6SStefano Zampini pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local); 7351727cdba6SStefano Zampini } 73520e6343abSStefano Zampini } 7353727cdba6SStefano Zampini /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */ 73541c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&pcbddc->new_primal_space_local, &pcbddc->new_primal_space, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 735572b8c272SStefano Zampini } 73569566063dSJacob Faibussowitsch PetscCall(PetscFree2(olocal_primal_ref_node, olocal_primal_ref_mult)); 7357727cdba6SStefano Zampini 7358a717540cSStefano Zampini /* flush dbg viewer */ 73591baa6e33SBarry Smith if (pcbddc->dbg_flag) PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 7360a717540cSStefano Zampini 7361e310c8b4SStefano Zampini /* free workspace */ 73629566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&qr_needed_idx)); 73639566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&change_basis)); 736408122e43SStefano Zampini if (!pcbddc->adaptive_selection) { 73659566063dSJacob Faibussowitsch PetscCall(PetscFree3(constraints_idxs_ptr, constraints_data_ptr, constraints_n)); 73669566063dSJacob Faibussowitsch PetscCall(PetscFree3(constraints_data, constraints_idxs, constraints_idxs_B)); 736708122e43SStefano Zampini } else { 7368d0609cedSBarry 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)); 73699566063dSJacob Faibussowitsch PetscCall(PetscFree(constraints_n)); 73709566063dSJacob Faibussowitsch PetscCall(PetscFree(constraints_idxs_B)); 737108122e43SStefano Zampini } 73723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7373674ae819SStefano Zampini } 7374674ae819SStefano Zampini 7375d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCAnalyzeInterface(PC pc) 7376d71ae5a4SJacob Faibussowitsch { 737771582508SStefano Zampini ISLocalToGlobalMapping map; 7378674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 7379674ae819SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 738066da6bd7Sstefano_zampini PetscInt i, N; 738166da6bd7Sstefano_zampini PetscBool rcsr = PETSC_FALSE; 7382674ae819SStefano Zampini 7383674ae819SStefano Zampini PetscFunctionBegin; 73848af8fcf9SStefano Zampini if (pcbddc->recompute_topography) { 7385b03ebc13SStefano Zampini pcbddc->graphanalyzed = PETSC_FALSE; 73868e61c736SStefano Zampini /* Reset previously computed graph */ 73879566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphReset(pcbddc->mat_graph)); 7388674ae819SStefano Zampini /* Init local Graph struct */ 73899566063dSJacob Faibussowitsch PetscCall(MatGetSize(pc->pmat, &N, NULL)); 73909566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(pc->pmat, &map, NULL)); 73919566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphInit(pcbddc->mat_graph, map, N, pcbddc->graphmaxcount)); 7392674ae819SStefano Zampini 739348a46eb9SPierre Jolivet if (pcbddc->user_primal_vertices_local && !pcbddc->user_primal_vertices) PetscCall(PCBDDCConsistencyCheckIS(pc, MPI_LOR, &pcbddc->user_primal_vertices_local)); 7394575ad6abSStefano Zampini /* Check validity of the csr graph passed in by the user */ 73959371c9d4SSatish 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, 73969371c9d4SSatish Balay pcbddc->mat_graph->nvtxs); 73979577ea80SStefano Zampini 7398674ae819SStefano Zampini /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */ 739966da6bd7Sstefano_zampini if (!pcbddc->mat_graph->xadj && pcbddc->use_local_adj) { 74004d379d7bSStefano Zampini PetscInt *xadj, *adjncy; 74014d379d7bSStefano Zampini PetscInt nvtxs; 74029de2952eSStefano Zampini PetscBool flg_row; 74039de2952eSStefano Zampini Mat A; 7404674ae819SStefano Zampini 74059de2952eSStefano Zampini PetscCall(PetscObjectReference((PetscObject)matis->A)); 74069de2952eSStefano Zampini A = matis->A; 74079de2952eSStefano Zampini for (PetscInt i = 0; i < pcbddc->local_adj_square; i++) { 74089de2952eSStefano Zampini Mat AtA; 74099de2952eSStefano Zampini 74109de2952eSStefano Zampini PetscCall(MatProductCreate(A, A, NULL, &AtA)); 74119de2952eSStefano Zampini PetscCall(MatSetOptionsPrefix(AtA, "pc_bddc_graph_")); 74129de2952eSStefano Zampini PetscCall(MatProductSetType(AtA, MATPRODUCT_AtB)); 74139de2952eSStefano Zampini PetscCall(MatProductSetFromOptions(AtA)); 74149de2952eSStefano Zampini PetscCall(MatProductSymbolic(AtA)); 74159de2952eSStefano Zampini PetscCall(MatProductClear(AtA)); 74169de2952eSStefano Zampini /* we only need the sparsity, cheat and tell PETSc the matrix has been assembled */ 74179de2952eSStefano Zampini AtA->assembled = PETSC_TRUE; 74189de2952eSStefano Zampini PetscCall(MatDestroy(&A)); 74199de2952eSStefano Zampini A = AtA; 74209de2952eSStefano Zampini } 74219de2952eSStefano Zampini PetscCall(MatGetRowIJ(A, 0, PETSC_TRUE, PETSC_FALSE, &nvtxs, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &flg_row)); 74222fffb893SStefano Zampini if (flg_row) { 74239566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLocalAdjacencyGraph(pc, nvtxs, xadj, adjncy, PETSC_COPY_VALUES)); 7424b96c3477SStefano Zampini pcbddc->computed_rowadj = PETSC_TRUE; 74259de2952eSStefano Zampini PetscCall(MatRestoreRowIJ(A, 0, PETSC_TRUE, PETSC_FALSE, &nvtxs, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &flg_row)); 742666da6bd7Sstefano_zampini rcsr = PETSC_TRUE; 7427674ae819SStefano Zampini } 74289de2952eSStefano Zampini PetscCall(MatDestroy(&A)); 74299de2952eSStefano Zampini } 74301baa6e33SBarry Smith if (pcbddc->dbg_flag) PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 7431674ae819SStefano Zampini 7432ab8c8b98SStefano Zampini if (pcbddc->mat_graph->cdim && !pcbddc->mat_graph->cloc) { 7433ab8c8b98SStefano Zampini PetscReal *lcoords; 7434ab8c8b98SStefano Zampini PetscInt n; 7435ab8c8b98SStefano Zampini MPI_Datatype dimrealtype; 7436ab8c8b98SStefano Zampini 74374f819b78SStefano Zampini /* TODO: support for blocked */ 743863a3b9bcSJacob 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); 74399566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(matis->A, &n, NULL)); 74409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->mat_graph->cdim * n, &lcoords)); 74419566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(pcbddc->mat_graph->cdim, MPIU_REAL, &dimrealtype)); 74429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&dimrealtype)); 74439566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, dimrealtype, pcbddc->mat_graph->coords, lcoords, MPI_REPLACE)); 74449566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, dimrealtype, pcbddc->mat_graph->coords, lcoords, MPI_REPLACE)); 74459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&dimrealtype)); 74469566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->mat_graph->coords)); 7447ab8c8b98SStefano Zampini 7448ab8c8b98SStefano Zampini pcbddc->mat_graph->coords = lcoords; 7449ab8c8b98SStefano Zampini pcbddc->mat_graph->cloc = PETSC_TRUE; 7450ab8c8b98SStefano Zampini pcbddc->mat_graph->cnloc = n; 7451ab8c8b98SStefano Zampini } 74529371c9d4SSatish 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, 74539371c9d4SSatish Balay pcbddc->mat_graph->nvtxs); 7454625961bdSStefano Zampini pcbddc->mat_graph->active_coords = (PetscBool)(pcbddc->corner_selection && pcbddc->mat_graph->cdim && !pcbddc->corner_selected); 7455ab8c8b98SStefano Zampini 74564f1b2e48SStefano Zampini /* attach info on disconnected subdomains if present */ 74574f1b2e48SStefano Zampini if (pcbddc->n_local_subs) { 745820c3699dSStefano Zampini PetscInt *local_subs, n, totn; 74594f1b2e48SStefano Zampini 74609566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(matis->A, &n, NULL)); 74619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &local_subs)); 746220c3699dSStefano Zampini for (i = 0; i < n; i++) local_subs[i] = pcbddc->n_local_subs; 74634f1b2e48SStefano Zampini for (i = 0; i < pcbddc->n_local_subs; i++) { 74644f1b2e48SStefano Zampini const PetscInt *idxs; 74654f1b2e48SStefano Zampini PetscInt nl, j; 74664f1b2e48SStefano Zampini 74679566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->local_subs[i], &nl)); 74689566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->local_subs[i], &idxs)); 746971582508SStefano Zampini for (j = 0; j < nl; j++) local_subs[idxs[j]] = i; 74709566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->local_subs[i], &idxs)); 74714f1b2e48SStefano Zampini } 747220c3699dSStefano Zampini for (i = 0, totn = 0; i < n; i++) totn = PetscMax(totn, local_subs[i]); 747320c3699dSStefano Zampini pcbddc->mat_graph->n_local_subs = totn + 1; 74744f1b2e48SStefano Zampini pcbddc->mat_graph->local_subs = local_subs; 74754f1b2e48SStefano Zampini } 74769de2952eSStefano Zampini 74779de2952eSStefano Zampini /* Setup of Graph */ 74789de2952eSStefano Zampini PetscCall(PCBDDCGraphSetUp(pcbddc->mat_graph, pcbddc->vertex_size, pcbddc->NeumannBoundariesLocal, pcbddc->DirichletBoundariesLocal, pcbddc->n_ISForDofsLocal, pcbddc->ISForDofsLocal, pcbddc->user_primal_vertices_local)); 74798af8fcf9SStefano Zampini } 74804f1b2e48SStefano Zampini 7481cac5312eSStefano Zampini if (!pcbddc->graphanalyzed) { 7482674ae819SStefano Zampini /* Graph's connected components analysis */ 74839566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph)); 748471582508SStefano Zampini pcbddc->graphanalyzed = PETSC_TRUE; 74854f819b78SStefano Zampini pcbddc->corner_selected = pcbddc->corner_selection; 74868af8fcf9SStefano Zampini } 748766da6bd7Sstefano_zampini if (rcsr) pcbddc->mat_graph->nvtxs_csr = 0; 74883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7489674ae819SStefano Zampini } 7490674ae819SStefano Zampini 7491d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt *nio, Vec vecs[]) 7492d71ae5a4SJacob Faibussowitsch { 7493295df10fSStefano Zampini PetscInt i, j, n; 74949a7d3425SStefano Zampini PetscScalar *alphas; 7495295df10fSStefano Zampini PetscReal norm, *onorms; 74969a7d3425SStefano Zampini 74979a7d3425SStefano Zampini PetscFunctionBegin; 7498295df10fSStefano Zampini n = *nio; 74993ba16761SJacob Faibussowitsch if (!n) PetscFunctionReturn(PETSC_SUCCESS); 75009566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n, &alphas, n, &onorms)); 75019566063dSJacob Faibussowitsch PetscCall(VecNormalize(vecs[0], &norm)); 750292cccca0SStefano Zampini if (norm < PETSC_SMALL) { 7503295df10fSStefano Zampini onorms[0] = 0.0; 75049566063dSJacob Faibussowitsch PetscCall(VecSet(vecs[0], 0.0)); 7505295df10fSStefano Zampini } else { 7506295df10fSStefano Zampini onorms[0] = norm; 750792cccca0SStefano Zampini } 7508295df10fSStefano Zampini 75098c0031efSStefano Zampini for (i = 1; i < n; i++) { 75109566063dSJacob Faibussowitsch PetscCall(VecMDot(vecs[i], i, vecs, alphas)); 75118c0031efSStefano Zampini for (j = 0; j < i; j++) alphas[j] = PetscConj(-alphas[j]); 75129566063dSJacob Faibussowitsch PetscCall(VecMAXPY(vecs[i], i, alphas, vecs)); 75139566063dSJacob Faibussowitsch PetscCall(VecNormalize(vecs[i], &norm)); 751492cccca0SStefano Zampini if (norm < PETSC_SMALL) { 7515295df10fSStefano Zampini onorms[i] = 0.0; 75169566063dSJacob Faibussowitsch PetscCall(VecSet(vecs[i], 0.0)); 7517295df10fSStefano Zampini } else { 7518295df10fSStefano Zampini onorms[i] = norm; 751992cccca0SStefano Zampini } 75209a7d3425SStefano Zampini } 7521295df10fSStefano Zampini /* push nonzero vectors at the beginning */ 7522295df10fSStefano Zampini for (i = 0; i < n; i++) { 7523295df10fSStefano Zampini if (onorms[i] == 0.0) { 7524295df10fSStefano Zampini for (j = i + 1; j < n; j++) { 7525295df10fSStefano Zampini if (onorms[j] != 0.0) { 75269566063dSJacob Faibussowitsch PetscCall(VecCopy(vecs[j], vecs[i])); 7527295df10fSStefano Zampini onorms[j] = 0.0; 7528295df10fSStefano Zampini } 7529295df10fSStefano Zampini } 7530295df10fSStefano Zampini } 7531295df10fSStefano Zampini } 7532295df10fSStefano Zampini for (i = 0, *nio = 0; i < n; i++) *nio += onorms[i] != 0.0 ? 1 : 0; 75339566063dSJacob Faibussowitsch PetscCall(PetscFree2(alphas, onorms)); 75343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 75359a7d3425SStefano Zampini } 75369a7d3425SStefano Zampini 7537ba38deedSJacob Faibussowitsch static PetscErrorCode PCBDDCMatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS *is_sends, PetscBool *have_void) 7538d71ae5a4SJacob Faibussowitsch { 7539e432b41dSStefano Zampini ISLocalToGlobalMapping mapping; 754057de7509SStefano Zampini Mat A; 7541e7931f94SStefano Zampini PetscInt n_neighs, *neighs, *n_shared, **shared; 7542e7931f94SStefano Zampini PetscMPIInt size, rank, color; 754352e5ac9dSStefano Zampini PetscInt *xadj, *adjncy; 754452e5ac9dSStefano Zampini PetscInt *adjncy_wgt, *v_wgt, *ranks_send_to_idx; 7545bb360cb4SStefano Zampini PetscInt im_active, active_procs, N, n, i, j, threshold = 2; 754657de7509SStefano Zampini PetscInt void_procs, *procs_candidates = NULL; 754727b6a85dSStefano Zampini PetscInt xadj_count, *count; 754827b6a85dSStefano Zampini PetscBool ismatis, use_vwgt = PETSC_FALSE; 754927b6a85dSStefano Zampini PetscSubcomm psubcomm; 755027b6a85dSStefano Zampini MPI_Comm subcomm; 7551a57a6d2fSStefano Zampini 7552e7931f94SStefano Zampini PetscFunctionBegin; 755357de7509SStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 75549566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)mat, MATIS, &ismatis)); 755528b400f6SJacob 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); 755657de7509SStefano Zampini PetscValidLogicalCollectiveInt(mat, *n_subdomains, 2); 755757de7509SStefano Zampini PetscValidLogicalCollectiveInt(mat, redprocs, 3); 755863a3b9bcSJacob Faibussowitsch PetscCheck(*n_subdomains > 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Invalid number of subdomains requested %" PetscInt_FMT, *n_subdomains); 755957de7509SStefano Zampini 756057de7509SStefano Zampini if (have_void) *have_void = PETSC_FALSE; 75619566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 75629566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)mat), &rank)); 75639566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(mat, &A)); 75649566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &n, NULL)); 7565bb360cb4SStefano Zampini im_active = !!n; 75661c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&im_active, &active_procs, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 756757de7509SStefano Zampini void_procs = size - active_procs; 756815229ffcSPierre Jolivet /* get ranks of non-active processes in mat communicator */ 756957de7509SStefano Zampini if (void_procs) { 757057de7509SStefano Zampini PetscInt ncand; 757157de7509SStefano Zampini 757257de7509SStefano Zampini if (have_void) *have_void = PETSC_TRUE; 75739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &procs_candidates)); 75749566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allgather(&im_active, 1, MPIU_INT, procs_candidates, 1, MPIU_INT, PetscObjectComm((PetscObject)mat))); 757557de7509SStefano Zampini for (i = 0, ncand = 0; i < size; i++) { 7576ad540459SPierre Jolivet if (!procs_candidates[i]) procs_candidates[ncand++] = i; 757757de7509SStefano Zampini } 757857de7509SStefano Zampini /* force n_subdomains to be not greater that the number of non-active processes */ 757957de7509SStefano Zampini *n_subdomains = PetscMin(void_procs, *n_subdomains); 758057de7509SStefano Zampini } 758157de7509SStefano Zampini 7582bb360cb4SStefano Zampini /* number of subdomains requested greater than active processes or matrix size -> just shift the matrix 75839dddd249SSatish Balay number of subdomains requested 1 -> send to rank-0 or first candidate in voids */ 75849566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &N, NULL)); 7585bb360cb4SStefano Zampini if (active_procs < *n_subdomains || *n_subdomains == 1 || N <= *n_subdomains) { 758614f0bfb9SStefano Zampini PetscInt issize, isidx, dest; 758714f0bfb9SStefano Zampini if (*n_subdomains == 1) dest = 0; 758814f0bfb9SStefano Zampini else dest = rank; 758957de7509SStefano Zampini if (im_active) { 759057de7509SStefano Zampini issize = 1; 759157de7509SStefano Zampini if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */ 759214f0bfb9SStefano Zampini isidx = procs_candidates[dest]; 759357de7509SStefano Zampini } else { 759414f0bfb9SStefano Zampini isidx = dest; 759557de7509SStefano Zampini } 759657de7509SStefano Zampini } else { 759757de7509SStefano Zampini issize = 0; 759857de7509SStefano Zampini isidx = -1; 759957de7509SStefano Zampini } 7600bb360cb4SStefano Zampini if (*n_subdomains != 1) *n_subdomains = active_procs; 76019566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), issize, &isidx, PETSC_COPY_VALUES, is_sends)); 76029566063dSJacob Faibussowitsch PetscCall(PetscFree(procs_candidates)); 76033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 760457de7509SStefano Zampini } 76059de2952eSStefano Zampini PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)A)->prefix, "-mat_is_partitioning_use_vwgt", &use_vwgt, NULL)); 76069de2952eSStefano Zampini PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)A)->prefix, "-mat_is_partitioning_threshold", &threshold, NULL)); 760727b6a85dSStefano Zampini threshold = PetscMax(threshold, 2); 7608e7931f94SStefano Zampini 7609e7931f94SStefano Zampini /* Get info on mapping */ 76109566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(mat, &mapping, NULL)); 76119566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetInfo(mapping, &n_neighs, &neighs, &n_shared, &shared)); 7612e7931f94SStefano Zampini 7613e7931f94SStefano Zampini /* build local CSR graph of subdomains' connectivity */ 76149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2, &xadj)); 7615e7931f94SStefano Zampini xadj[0] = 0; 7616e7931f94SStefano Zampini xadj[1] = PetscMax(n_neighs - 1, 0); 76179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(xadj[1], &adjncy)); 76189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(xadj[1], &adjncy_wgt)); 76199566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(n, &count)); 762027b6a85dSStefano Zampini for (i = 1; i < n_neighs; i++) 76219371c9d4SSatish Balay for (j = 0; j < n_shared[i]; j++) count[shared[i][j]] += 1; 7622e7931f94SStefano Zampini 762327b6a85dSStefano Zampini xadj_count = 0; 76242b510759SStefano Zampini for (i = 1; i < n_neighs; i++) { 762527b6a85dSStefano Zampini for (j = 0; j < n_shared[i]; j++) { 762627b6a85dSStefano Zampini if (count[shared[i][j]] < threshold) { 7627d023bfaeSStefano Zampini adjncy[xadj_count] = neighs[i]; 7628d023bfaeSStefano Zampini adjncy_wgt[xadj_count] = n_shared[i]; 7629d023bfaeSStefano Zampini xadj_count++; 763027b6a85dSStefano Zampini break; 763127b6a85dSStefano Zampini } 7632e7931f94SStefano Zampini } 7633e7931f94SStefano Zampini } 7634d023bfaeSStefano Zampini xadj[1] = xadj_count; 76359566063dSJacob Faibussowitsch PetscCall(PetscFree(count)); 76369566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreInfo(mapping, &n_neighs, &neighs, &n_shared, &shared)); 76379566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(xadj[1], adjncy, adjncy_wgt)); 7638e7931f94SStefano Zampini 76399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &ranks_send_to_idx)); 7640e7931f94SStefano Zampini 764127b6a85dSStefano Zampini /* Restrict work on active processes only */ 76429566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(im_active, &color)); 764327b6a85dSStefano Zampini if (void_procs) { 76449566063dSJacob Faibussowitsch PetscCall(PetscSubcommCreate(PetscObjectComm((PetscObject)mat), &psubcomm)); 76459566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetNumber(psubcomm, 2)); /* 2 groups, active process and not active processes */ 76469566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetTypeGeneral(psubcomm, color, rank)); 764727b6a85dSStefano Zampini subcomm = PetscSubcommChild(psubcomm); 764827b6a85dSStefano Zampini } else { 764927b6a85dSStefano Zampini psubcomm = NULL; 765027b6a85dSStefano Zampini subcomm = PetscObjectComm((PetscObject)mat); 765127b6a85dSStefano Zampini } 765227b6a85dSStefano Zampini 765327b6a85dSStefano Zampini v_wgt = NULL; 765427b6a85dSStefano Zampini if (!color) { 76559566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 76569566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 76579566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy_wgt)); 7658c8587f34SStefano Zampini } else { 765952e5ac9dSStefano Zampini Mat subdomain_adj; 766052e5ac9dSStefano Zampini IS new_ranks, new_ranks_contig; 766152e5ac9dSStefano Zampini MatPartitioning partitioner; 766227b6a85dSStefano Zampini PetscInt rstart = 0, rend = 0; 766352e5ac9dSStefano Zampini PetscInt *is_indices, *oldranks; 766457de7509SStefano Zampini PetscMPIInt size; 7665b0c7d250SStefano Zampini PetscBool aggregate; 7666b0c7d250SStefano Zampini 76679566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(subcomm, &size)); 766827b6a85dSStefano Zampini if (void_procs) { 766927b6a85dSStefano Zampini PetscInt prank = rank; 76709566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &oldranks)); 76719566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allgather(&prank, 1, MPIU_INT, oldranks, 1, MPIU_INT, subcomm)); 767248a46eb9SPierre Jolivet for (i = 0; i < xadj[1]; i++) PetscCall(PetscFindInt(adjncy[i], size, oldranks, &adjncy[i])); 76739566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(xadj[1], adjncy, adjncy_wgt)); 767427b6a85dSStefano Zampini } else { 767527b6a85dSStefano Zampini oldranks = NULL; 767627b6a85dSStefano Zampini } 7677b0c7d250SStefano Zampini aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE); 767827b6a85dSStefano Zampini if (aggregate) { /* TODO: all this part could be made more efficient */ 7679b0c7d250SStefano Zampini PetscInt lrows, row, ncols, *cols; 7680b0c7d250SStefano Zampini PetscMPIInt nrank; 7681b0c7d250SStefano Zampini PetscScalar *vals; 7682b0c7d250SStefano Zampini 76839566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(subcomm, &nrank)); 7684b0c7d250SStefano Zampini lrows = 0; 7685b0c7d250SStefano Zampini if (nrank < redprocs) { 7686b0c7d250SStefano Zampini lrows = size / redprocs; 7687b0c7d250SStefano Zampini if (nrank < size % redprocs) lrows++; 7688b0c7d250SStefano Zampini } 76899566063dSJacob Faibussowitsch PetscCall(MatCreateAIJ(subcomm, lrows, lrows, size, size, 50, NULL, 50, NULL, &subdomain_adj)); 76909566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(subdomain_adj, &rstart, &rend)); 76919566063dSJacob Faibussowitsch PetscCall(MatSetOption(subdomain_adj, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_FALSE)); 76929566063dSJacob Faibussowitsch PetscCall(MatSetOption(subdomain_adj, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 7693b0c7d250SStefano Zampini row = nrank; 7694b0c7d250SStefano Zampini ncols = xadj[1] - xadj[0]; 7695b0c7d250SStefano Zampini cols = adjncy; 76969566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncols, &vals)); 7697b0c7d250SStefano Zampini for (i = 0; i < ncols; i++) vals[i] = adjncy_wgt[i]; 76989566063dSJacob Faibussowitsch PetscCall(MatSetValues(subdomain_adj, 1, &row, ncols, cols, vals, INSERT_VALUES)); 76999566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(subdomain_adj, MAT_FINAL_ASSEMBLY)); 77009566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(subdomain_adj, MAT_FINAL_ASSEMBLY)); 77019566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 77029566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 77039566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy_wgt)); 77049566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 770527b6a85dSStefano Zampini if (use_vwgt) { 770627b6a85dSStefano Zampini Vec v; 770727b6a85dSStefano Zampini const PetscScalar *array; 770827b6a85dSStefano Zampini PetscInt nl; 770927b6a85dSStefano Zampini 77109566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(subdomain_adj, &v, NULL)); 77119566063dSJacob Faibussowitsch PetscCall(VecSetValue(v, row, (PetscScalar)n, INSERT_VALUES)); 77129566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(v)); 77139566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(v)); 77149566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &nl)); 77159566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &array)); 77169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl, &v_wgt)); 771722db5ddcSStefano Zampini for (i = 0; i < nl; i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]); 77189566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &array)); 77199566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 772027b6a85dSStefano Zampini } 7721b0c7d250SStefano Zampini } else { 77229566063dSJacob Faibussowitsch PetscCall(MatCreateMPIAdj(subcomm, 1, (PetscInt)size, xadj, adjncy, adjncy_wgt, &subdomain_adj)); 772327b6a85dSStefano Zampini if (use_vwgt) { 77249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &v_wgt)); 7725bb360cb4SStefano Zampini v_wgt[0] = n; 772627b6a85dSStefano Zampini } 7727b0c7d250SStefano Zampini } 77289566063dSJacob Faibussowitsch /* PetscCall(MatView(subdomain_adj,0)); */ 7729e7931f94SStefano Zampini 7730e7931f94SStefano Zampini /* Partition */ 77319566063dSJacob Faibussowitsch PetscCall(MatPartitioningCreate(subcomm, &partitioner)); 7732ce64c636SStefano Zampini #if defined(PETSC_HAVE_PTSCOTCH) 77339566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetType(partitioner, MATPARTITIONINGPTSCOTCH)); 7734ce64c636SStefano Zampini #elif defined(PETSC_HAVE_PARMETIS) 77359566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetType(partitioner, MATPARTITIONINGPARMETIS)); 7736ce64c636SStefano Zampini #else 77379566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetType(partitioner, MATPARTITIONINGAVERAGE)); 7738ce64c636SStefano Zampini #endif 77399566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetAdjacency(partitioner, subdomain_adj)); 77401baa6e33SBarry Smith if (v_wgt) PetscCall(MatPartitioningSetVertexWeights(partitioner, v_wgt)); 774157de7509SStefano Zampini *n_subdomains = PetscMin((PetscInt)size, *n_subdomains); 77429566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetNParts(partitioner, *n_subdomains)); 77439566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetFromOptions(partitioner)); 77449566063dSJacob Faibussowitsch PetscCall(MatPartitioningApply(partitioner, &new_ranks)); 77459566063dSJacob Faibussowitsch /* PetscCall(MatPartitioningView(partitioner,0)); */ 7746e7931f94SStefano Zampini 774752e5ac9dSStefano Zampini /* renumber new_ranks to avoid "holes" in new set of processors */ 77489566063dSJacob Faibussowitsch PetscCall(ISRenumber(new_ranks, NULL, NULL, &new_ranks_contig)); 77499566063dSJacob Faibussowitsch PetscCall(ISDestroy(&new_ranks)); 77509566063dSJacob Faibussowitsch PetscCall(ISGetIndices(new_ranks_contig, (const PetscInt **)&is_indices)); 775157de7509SStefano Zampini if (!aggregate) { 775257de7509SStefano Zampini if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */ 77536bdcaf15SBarry Smith PetscAssert(oldranks, PETSC_COMM_SELF, PETSC_ERR_PLIB, "This should not happen"); 775457de7509SStefano Zampini ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]]; 775527b6a85dSStefano Zampini } else if (oldranks) { 7756b0c7d250SStefano Zampini ranks_send_to_idx[0] = oldranks[is_indices[0]]; 775727b6a85dSStefano Zampini } else { 775827b6a85dSStefano Zampini ranks_send_to_idx[0] = is_indices[0]; 775957de7509SStefano Zampini } 776028143c3dSStefano Zampini } else { 77617fb8a5e4SKarl Rupp PetscInt idx = 0; 7762b0c7d250SStefano Zampini PetscMPIInt tag; 7763b0c7d250SStefano Zampini MPI_Request *reqs; 7764b0c7d250SStefano Zampini 77659566063dSJacob Faibussowitsch PetscCall(PetscObjectGetNewTag((PetscObject)subdomain_adj, &tag)); 77669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rend - rstart, &reqs)); 776748a46eb9SPierre Jolivet for (i = rstart; i < rend; i++) PetscCallMPI(MPI_Isend(is_indices + i - rstart, 1, MPIU_INT, i, tag, subcomm, &reqs[i - rstart])); 77689566063dSJacob Faibussowitsch PetscCallMPI(MPI_Recv(&idx, 1, MPIU_INT, MPI_ANY_SOURCE, tag, subcomm, MPI_STATUS_IGNORE)); 77699566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(rend - rstart, reqs, MPI_STATUSES_IGNORE)); 77709566063dSJacob Faibussowitsch PetscCall(PetscFree(reqs)); 777157de7509SStefano Zampini if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */ 77726bdcaf15SBarry Smith PetscAssert(oldranks, PETSC_COMM_SELF, PETSC_ERR_PLIB, "This should not happen"); 77737fb8a5e4SKarl Rupp ranks_send_to_idx[0] = procs_candidates[oldranks[idx]]; 777427b6a85dSStefano Zampini } else if (oldranks) { 77757fb8a5e4SKarl Rupp ranks_send_to_idx[0] = oldranks[idx]; 777627b6a85dSStefano Zampini } else { 77777fb8a5e4SKarl Rupp ranks_send_to_idx[0] = idx; 777828143c3dSStefano Zampini } 777957de7509SStefano Zampini } 77809566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(new_ranks_contig, (const PetscInt **)&is_indices)); 7781e7931f94SStefano Zampini /* clean up */ 77829566063dSJacob Faibussowitsch PetscCall(PetscFree(oldranks)); 77839566063dSJacob Faibussowitsch PetscCall(ISDestroy(&new_ranks_contig)); 77849566063dSJacob Faibussowitsch PetscCall(MatDestroy(&subdomain_adj)); 77859566063dSJacob Faibussowitsch PetscCall(MatPartitioningDestroy(&partitioner)); 7786e7931f94SStefano Zampini } 77879566063dSJacob Faibussowitsch PetscCall(PetscSubcommDestroy(&psubcomm)); 77889566063dSJacob Faibussowitsch PetscCall(PetscFree(procs_candidates)); 7789e7931f94SStefano Zampini 7790e7931f94SStefano Zampini /* assemble parallel IS for sends */ 7791e7931f94SStefano Zampini i = 1; 779227b6a85dSStefano Zampini if (!color) i = 0; 77939566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), i, ranks_send_to_idx, PETSC_OWN_POINTER, is_sends)); 77943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7795e7931f94SStefano Zampini } 7796e7931f94SStefano Zampini 77979371c9d4SSatish Balay typedef enum { 77989371c9d4SSatish Balay MATDENSE_PRIVATE = 0, 77999371c9d4SSatish Balay MATAIJ_PRIVATE, 78009371c9d4SSatish Balay MATBAIJ_PRIVATE, 78019371c9d4SSatish Balay MATSBAIJ_PRIVATE 78029371c9d4SSatish Balay } MatTypePrivate; 7803e7931f94SStefano Zampini 7804ba38deedSJacob Faibussowitsch static 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[]) 7805d71ae5a4SJacob Faibussowitsch { 780670cf5478SStefano Zampini Mat local_mat; 7807e7931f94SStefano Zampini IS is_sends_internal; 78089d30be91SStefano Zampini PetscInt rows, cols, new_local_rows; 78091ae86dd6SStefano Zampini PetscInt i, bs, buf_size_idxs, buf_size_idxs_is, buf_size_vals, buf_size_vecs; 78109d30be91SStefano Zampini PetscBool ismatis, isdense, newisdense, destroy_mat; 7811e7931f94SStefano Zampini ISLocalToGlobalMapping l2gmap; 7812e7931f94SStefano Zampini PetscInt *l2gmap_indices; 7813e7931f94SStefano Zampini const PetscInt *is_indices; 7814e7931f94SStefano Zampini MatType new_local_type; 7815e7931f94SStefano Zampini /* buffers */ 7816e7931f94SStefano Zampini PetscInt *ptr_idxs, *send_buffer_idxs, *recv_buffer_idxs; 781728143c3dSStefano Zampini PetscInt *ptr_idxs_is, *send_buffer_idxs_is, *recv_buffer_idxs_is; 78189d30be91SStefano Zampini PetscInt *recv_buffer_idxs_local; 78191683a169SBarry Smith PetscScalar *ptr_vals, *recv_buffer_vals; 78201683a169SBarry Smith const PetscScalar *send_buffer_vals; 78211ae86dd6SStefano Zampini PetscScalar *ptr_vecs, *send_buffer_vecs, *recv_buffer_vecs; 7822e7931f94SStefano Zampini /* MPI */ 782328143c3dSStefano Zampini MPI_Comm comm, comm_n; 782428143c3dSStefano Zampini PetscSubcomm subcomm; 7825e569e4e1SStefano Zampini PetscMPIInt n_sends, n_recvs, size; 782628143c3dSStefano Zampini PetscMPIInt *iflags, *ilengths_idxs, *ilengths_vals, *ilengths_idxs_is; 782728143c3dSStefano Zampini PetscMPIInt *onodes, *onodes_is, *olengths_idxs, *olengths_idxs_is, *olengths_vals; 78281ae86dd6SStefano Zampini PetscMPIInt len, tag_idxs, tag_idxs_is, tag_vals, tag_vecs, source_dest; 78291ae86dd6SStefano Zampini MPI_Request *send_req_idxs, *send_req_idxs_is, *send_req_vals, *send_req_vecs; 78301ae86dd6SStefano Zampini MPI_Request *recv_req_idxs, *recv_req_idxs_is, *recv_req_vals, *recv_req_vecs; 7831e7931f94SStefano Zampini 7832e7931f94SStefano Zampini PetscFunctionBegin; 783357de7509SStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 78349566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)mat, MATIS, &ismatis)); 78355f80ce2aSJacob 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); 783657de7509SStefano Zampini PetscValidLogicalCollectiveInt(mat, n_subdomains, 3); 783757de7509SStefano Zampini PetscValidLogicalCollectiveBool(mat, restrict_comm, 4); 783857de7509SStefano Zampini PetscValidLogicalCollectiveBool(mat, restrict_full, 5); 783957de7509SStefano Zampini PetscValidLogicalCollectiveBool(mat, reuse, 6); 784057de7509SStefano Zampini PetscValidLogicalCollectiveInt(mat, nis, 8); 78411ae86dd6SStefano Zampini PetscValidLogicalCollectiveInt(mat, nvecs, 10); 78421ae86dd6SStefano Zampini if (nvecs) { 784308401ef6SPierre Jolivet PetscCheck(nvecs <= 1, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Just 1 vector supported"); 78441ae86dd6SStefano Zampini PetscValidHeaderSpecific(nnsp_vec[0], VEC_CLASSID, 11); 78451ae86dd6SStefano Zampini } 784657de7509SStefano Zampini /* further checks */ 78479566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(mat, &local_mat)); 78489566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)local_mat, MATSEQDENSE, &isdense)); 78499de2952eSStefano Zampini /* XXX hack for multi_element */ 78509de2952eSStefano Zampini if (!isdense) PetscCall(MatConvert(local_mat, MATDENSE, MAT_INPLACE_MATRIX, &local_mat)); 78519de2952eSStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)local_mat, MATSEQDENSE, &isdense)); 78525f80ce2aSJacob Faibussowitsch PetscCheck(isdense, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE"); 78539de2952eSStefano Zampini 78549566063dSJacob Faibussowitsch PetscCall(MatGetSize(local_mat, &rows, &cols)); 78555f80ce2aSJacob Faibussowitsch PetscCheck(rows == cols, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Local MATIS matrices should be square"); 785657de7509SStefano Zampini if (reuse && *mat_n) { 785770cf5478SStefano Zampini PetscInt mrows, mcols, mnrows, mncols; 785857de7509SStefano Zampini PetscValidHeaderSpecific(*mat_n, MAT_CLASSID, 7); 78599566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)*mat_n, MATIS, &ismatis)); 78605f80ce2aSJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)*mat_n), PETSC_ERR_SUP, "Cannot reuse a matrix which is not of type MATIS"); 78619566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &mrows, &mcols)); 78629566063dSJacob Faibussowitsch PetscCall(MatGetSize(*mat_n, &mnrows, &mncols)); 786363a3b9bcSJacob Faibussowitsch PetscCheck(mrows == mnrows, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix! Wrong number of rows %" PetscInt_FMT " != %" PetscInt_FMT, mrows, mnrows); 786463a3b9bcSJacob Faibussowitsch PetscCheck(mcols == mncols, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix! Wrong number of cols %" PetscInt_FMT " != %" PetscInt_FMT, mcols, mncols); 786570cf5478SStefano Zampini } 78669566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(local_mat, &bs)); 7867064a246eSJacob Faibussowitsch PetscValidLogicalCollectiveInt(mat, bs, 1); 786857de7509SStefano Zampini 7869e7931f94SStefano Zampini /* prepare IS for sending if not provided */ 7870e7931f94SStefano Zampini if (!is_sends) { 78715f80ce2aSJacob Faibussowitsch PetscCheck(n_subdomains, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "You should specify either an IS or a target number of subdomains"); 78729566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISGetSubassemblingPattern(mat, &n_subdomains, 0, &is_sends_internal, NULL)); 7873c8587f34SStefano Zampini } else { 78749566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is_sends)); 7875e7931f94SStefano Zampini is_sends_internal = is_sends; 7876c8587f34SStefano Zampini } 7877e7931f94SStefano Zampini 7878e7931f94SStefano Zampini /* get comm */ 78799566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7880e7931f94SStefano Zampini 7881e7931f94SStefano Zampini /* compute number of sends */ 78829566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is_sends_internal, &i)); 78839566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(i, &n_sends)); 7884e7931f94SStefano Zampini 7885e7931f94SStefano Zampini /* compute number of receives */ 78869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 78879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &iflags)); 78889566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(iflags, size)); 78899566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is_sends_internal, &is_indices)); 7890e7931f94SStefano Zampini for (i = 0; i < n_sends; i++) iflags[is_indices[i]] = 1; 78919566063dSJacob Faibussowitsch PetscCall(PetscGatherNumberOfMessages(comm, iflags, NULL, &n_recvs)); 78929566063dSJacob Faibussowitsch PetscCall(PetscFree(iflags)); 7893e7931f94SStefano Zampini 789428143c3dSStefano Zampini /* restrict comm if requested */ 78950a545947SLisandro Dalcin subcomm = NULL; 789628143c3dSStefano Zampini destroy_mat = PETSC_FALSE; 789728143c3dSStefano Zampini if (restrict_comm) { 7898779c1cceSStefano Zampini PetscMPIInt color, subcommsize; 7899779c1cceSStefano Zampini 790028143c3dSStefano Zampini color = 0; 790153a05cb3SStefano Zampini if (restrict_full) { 79026aad120cSJose E. Roman if (!n_recvs) color = 1; /* processes not receiving anything will not participate in new comm (full restriction) */ 790353a05cb3SStefano Zampini } else { 79046aad120cSJose 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 */ 790553a05cb3SStefano Zampini } 79061c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&color, &subcommsize, 1, MPI_INT, MPI_SUM, comm)); 7907e569e4e1SStefano Zampini subcommsize = size - subcommsize; 790828143c3dSStefano Zampini /* check if reuse has been requested */ 790957de7509SStefano Zampini if (reuse) { 791028143c3dSStefano Zampini if (*mat_n) { 791128143c3dSStefano Zampini PetscMPIInt subcommsize2; 79129566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n), &subcommsize2)); 79135f80ce2aSJacob Faibussowitsch PetscCheck(subcommsize == subcommsize2, PetscObjectComm((PetscObject)*mat_n), PETSC_ERR_PLIB, "Cannot reuse matrix! wrong subcomm size %d != %d", subcommsize, subcommsize2); 791428143c3dSStefano Zampini comm_n = PetscObjectComm((PetscObject)*mat_n); 791528143c3dSStefano Zampini } else { 791628143c3dSStefano Zampini comm_n = PETSC_COMM_SELF; 791728143c3dSStefano Zampini } 791828143c3dSStefano Zampini } else { /* MAT_INITIAL_MATRIX */ 7919779c1cceSStefano Zampini PetscMPIInt rank; 7920779c1cceSStefano Zampini 79219566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 79229566063dSJacob Faibussowitsch PetscCall(PetscSubcommCreate(comm, &subcomm)); 79239566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetNumber(subcomm, 2)); 79249566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetTypeGeneral(subcomm, color, rank)); 7925306c2d5bSBarry Smith comm_n = PetscSubcommChild(subcomm); 792628143c3dSStefano Zampini } 792728143c3dSStefano Zampini /* flag to destroy *mat_n if not significative */ 792828143c3dSStefano Zampini if (color) destroy_mat = PETSC_TRUE; 792928143c3dSStefano Zampini } else { 793028143c3dSStefano Zampini comm_n = comm; 793128143c3dSStefano Zampini } 793228143c3dSStefano Zampini 7933e7931f94SStefano Zampini /* prepare send/receive buffers */ 79349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &ilengths_idxs)); 79359566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(ilengths_idxs, size)); 79369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &ilengths_vals)); 79379566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(ilengths_vals, size)); 793848a46eb9SPierre Jolivet if (nis) PetscCall(PetscCalloc1(size, &ilengths_idxs_is)); 7939e7931f94SStefano Zampini 794028143c3dSStefano Zampini /* Get data from local matrices */ 7941e432b41dSStefano Zampini PetscCheck(isdense, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Subassembling of AIJ local matrices not yet implemented"); 7942e7931f94SStefano Zampini /* TODO: See below some guidelines on how to prepare the local buffers */ 7943e7931f94SStefano Zampini /* 7944e7931f94SStefano Zampini send_buffer_vals should contain the raw values of the local matrix 7945e7931f94SStefano Zampini send_buffer_idxs should contain: 7946e7931f94SStefano Zampini - MatType_PRIVATE type 7947e7931f94SStefano Zampini - PetscInt size_of_l2gmap 7948e7931f94SStefano Zampini - PetscInt global_row_indices[size_of_l2gmap] 7949e7931f94SStefano Zampini - PetscInt all_other_info_which_is_needed_to_compute_preallocation_and_set_values 7950e7931f94SStefano Zampini */ 7951e432b41dSStefano Zampini { 7952e432b41dSStefano Zampini ISLocalToGlobalMapping mapping; 7953e432b41dSStefano Zampini 79549566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(mat, &mapping, NULL)); 79559566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(local_mat, &send_buffer_vals)); 79569566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(mapping, &i)); 79579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(i + 2, &send_buffer_idxs)); 7958e7931f94SStefano Zampini send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE; 7959e7931f94SStefano Zampini send_buffer_idxs[1] = i; 79609566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(mapping, (const PetscInt **)&ptr_idxs)); 79619566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&send_buffer_idxs[2], ptr_idxs, i)); 79629566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(mapping, (const PetscInt **)&ptr_idxs)); 79639566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(i, &len)); 7964e7931f94SStefano Zampini for (i = 0; i < n_sends; i++) { 7965e7931f94SStefano Zampini ilengths_vals[is_indices[i]] = len * len; 7966e7931f94SStefano Zampini ilengths_idxs[is_indices[i]] = len + 2; 7967c8587f34SStefano Zampini } 7968c8587f34SStefano Zampini } 79699566063dSJacob Faibussowitsch PetscCall(PetscGatherMessageLengths2(comm, n_sends, n_recvs, ilengths_idxs, ilengths_vals, &onodes, &olengths_idxs, &olengths_vals)); 797028143c3dSStefano Zampini /* additional is (if any) */ 797128143c3dSStefano Zampini if (nis) { 797228143c3dSStefano Zampini PetscMPIInt psum; 797328143c3dSStefano Zampini PetscInt j; 797428143c3dSStefano Zampini for (j = 0, psum = 0; j < nis; j++) { 797528143c3dSStefano Zampini PetscInt plen; 79769566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isarray[j], &plen)); 79779566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(plen, &len)); 79786aad120cSJose E. Roman psum += len + 1; /* indices + length */ 797928143c3dSStefano Zampini } 79809566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(psum, &send_buffer_idxs_is)); 798128143c3dSStefano Zampini for (j = 0, psum = 0; j < nis; j++) { 798228143c3dSStefano Zampini PetscInt plen; 798328143c3dSStefano Zampini const PetscInt *is_array_idxs; 79849566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isarray[j], &plen)); 798528143c3dSStefano Zampini send_buffer_idxs_is[psum] = plen; 79869566063dSJacob Faibussowitsch PetscCall(ISGetIndices(isarray[j], &is_array_idxs)); 79879566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&send_buffer_idxs_is[psum + 1], is_array_idxs, plen)); 79889566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(isarray[j], &is_array_idxs)); 79896aad120cSJose E. Roman psum += plen + 1; /* indices + length */ 799028143c3dSStefano Zampini } 7991ad540459SPierre Jolivet for (i = 0; i < n_sends; i++) ilengths_idxs_is[is_indices[i]] = psum; 79929566063dSJacob Faibussowitsch PetscCall(PetscGatherMessageLengths(comm, n_sends, n_recvs, ilengths_idxs_is, &onodes_is, &olengths_idxs_is)); 799328143c3dSStefano Zampini } 79949566063dSJacob Faibussowitsch PetscCall(MatISRestoreLocalMat(mat, &local_mat)); 799528143c3dSStefano Zampini 7996e7931f94SStefano Zampini buf_size_idxs = 0; 7997e7931f94SStefano Zampini buf_size_vals = 0; 799828143c3dSStefano Zampini buf_size_idxs_is = 0; 79991ae86dd6SStefano Zampini buf_size_vecs = 0; 8000e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 8001e7931f94SStefano Zampini buf_size_idxs += (PetscInt)olengths_idxs[i]; 8002e7931f94SStefano Zampini buf_size_vals += (PetscInt)olengths_vals[i]; 800328143c3dSStefano Zampini if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i]; 80041ae86dd6SStefano Zampini if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i]; 8005e7931f94SStefano Zampini } 80069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(buf_size_idxs, &recv_buffer_idxs)); 80079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(buf_size_vals, &recv_buffer_vals)); 80089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(buf_size_idxs_is, &recv_buffer_idxs_is)); 80099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(buf_size_vecs, &recv_buffer_vecs)); 8010e7931f94SStefano Zampini 8011e7931f94SStefano Zampini /* get new tags for clean communications */ 80129566063dSJacob Faibussowitsch PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag_idxs)); 80139566063dSJacob Faibussowitsch PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag_vals)); 80149566063dSJacob Faibussowitsch PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag_idxs_is)); 80159566063dSJacob Faibussowitsch PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag_vecs)); 8016e7931f94SStefano Zampini 8017e7931f94SStefano Zampini /* allocate for requests */ 80189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_sends, &send_req_idxs)); 80199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_sends, &send_req_vals)); 80209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_sends, &send_req_idxs_is)); 80219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_sends, &send_req_vecs)); 80229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_recvs, &recv_req_idxs)); 80239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_recvs, &recv_req_vals)); 80249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_recvs, &recv_req_idxs_is)); 80259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_recvs, &recv_req_vecs)); 8026e7931f94SStefano Zampini 8027e7931f94SStefano Zampini /* communications */ 8028e7931f94SStefano Zampini ptr_idxs = recv_buffer_idxs; 8029e7931f94SStefano Zampini ptr_vals = recv_buffer_vals; 803028143c3dSStefano Zampini ptr_idxs_is = recv_buffer_idxs_is; 80311ae86dd6SStefano Zampini ptr_vecs = recv_buffer_vecs; 8032e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 8033e7931f94SStefano Zampini source_dest = onodes[i]; 80349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Irecv(ptr_idxs, olengths_idxs[i], MPIU_INT, source_dest, tag_idxs, comm, &recv_req_idxs[i])); 80359566063dSJacob Faibussowitsch PetscCallMPI(MPI_Irecv(ptr_vals, olengths_vals[i], MPIU_SCALAR, source_dest, tag_vals, comm, &recv_req_vals[i])); 8036e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 8037e7931f94SStefano Zampini ptr_vals += olengths_vals[i]; 803828143c3dSStefano Zampini if (nis) { 803957de7509SStefano Zampini source_dest = onodes_is[i]; 80409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Irecv(ptr_idxs_is, olengths_idxs_is[i], MPIU_INT, source_dest, tag_idxs_is, comm, &recv_req_idxs_is[i])); 804128143c3dSStefano Zampini ptr_idxs_is += olengths_idxs_is[i]; 804228143c3dSStefano Zampini } 80431ae86dd6SStefano Zampini if (nvecs) { 80441ae86dd6SStefano Zampini source_dest = onodes[i]; 80459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Irecv(ptr_vecs, olengths_idxs[i] - 2, MPIU_SCALAR, source_dest, tag_vecs, comm, &recv_req_vecs[i])); 80461ae86dd6SStefano Zampini ptr_vecs += olengths_idxs[i] - 2; 80471ae86dd6SStefano Zampini } 8048e7931f94SStefano Zampini } 8049e7931f94SStefano Zampini for (i = 0; i < n_sends; i++) { 80509566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(is_indices[i], &source_dest)); 80519566063dSJacob Faibussowitsch PetscCallMPI(MPI_Isend(send_buffer_idxs, ilengths_idxs[source_dest], MPIU_INT, source_dest, tag_idxs, comm, &send_req_idxs[i])); 80529566063dSJacob Faibussowitsch PetscCallMPI(MPI_Isend((PetscScalar *)send_buffer_vals, ilengths_vals[source_dest], MPIU_SCALAR, source_dest, tag_vals, comm, &send_req_vals[i])); 805348a46eb9SPierre 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])); 80541ae86dd6SStefano Zampini if (nvecs) { 80559566063dSJacob Faibussowitsch PetscCall(VecGetArray(nnsp_vec[0], &send_buffer_vecs)); 80569566063dSJacob Faibussowitsch PetscCallMPI(MPI_Isend(send_buffer_vecs, ilengths_idxs[source_dest] - 2, MPIU_SCALAR, source_dest, tag_vecs, comm, &send_req_vecs[i])); 80571ae86dd6SStefano Zampini } 8058e7931f94SStefano Zampini } 80599566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is_sends_internal, &is_indices)); 80609566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_sends_internal)); 8061e7931f94SStefano Zampini 8062e7931f94SStefano Zampini /* assemble new l2g map */ 80639566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_recvs, recv_req_idxs, MPI_STATUSES_IGNORE)); 8064e7931f94SStefano Zampini ptr_idxs = recv_buffer_idxs; 80659d30be91SStefano Zampini new_local_rows = 0; 8066e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 80679d30be91SStefano Zampini new_local_rows += *(ptr_idxs + 1); /* second element is the local size of the l2gmap */ 8068e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 8069e7931f94SStefano Zampini } 80709566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(new_local_rows, &l2gmap_indices)); 8071e7931f94SStefano Zampini ptr_idxs = recv_buffer_idxs; 80729d30be91SStefano Zampini new_local_rows = 0; 8073e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 80749566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&l2gmap_indices[new_local_rows], ptr_idxs + 2, *(ptr_idxs + 1))); 80759d30be91SStefano Zampini new_local_rows += *(ptr_idxs + 1); /* second element is the local size of the l2gmap */ 8076e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 8077e7931f94SStefano Zampini } 80789566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&new_local_rows, l2gmap_indices)); 80799566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(comm_n, 1, new_local_rows, l2gmap_indices, PETSC_COPY_VALUES, &l2gmap)); 80809566063dSJacob Faibussowitsch PetscCall(PetscFree(l2gmap_indices)); 8081e7931f94SStefano Zampini 8082e7931f94SStefano Zampini /* infer new local matrix type from received local matrices type */ 8083e7931f94SStefano Zampini /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */ 8084e7931f94SStefano 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) */ 8085e7931f94SStefano Zampini if (n_recvs) { 808628143c3dSStefano Zampini MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0]; 8087e7931f94SStefano Zampini ptr_idxs = recv_buffer_idxs; 8088e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 8089e7931f94SStefano Zampini if ((PetscInt)new_local_type_private != *ptr_idxs) { 8090e7931f94SStefano Zampini new_local_type_private = MATAIJ_PRIVATE; 8091e7931f94SStefano Zampini break; 8092e7931f94SStefano Zampini } 8093e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 8094e7931f94SStefano Zampini } 8095e7931f94SStefano Zampini switch (new_local_type_private) { 809628143c3dSStefano Zampini case MATDENSE_PRIVATE: 8097e7931f94SStefano Zampini new_local_type = MATSEQAIJ; 8098e7931f94SStefano Zampini bs = 1; 8099e7931f94SStefano Zampini break; 8100e7931f94SStefano Zampini case MATAIJ_PRIVATE: 8101e7931f94SStefano Zampini new_local_type = MATSEQAIJ; 8102e7931f94SStefano Zampini bs = 1; 8103e7931f94SStefano Zampini break; 8104d71ae5a4SJacob Faibussowitsch case MATBAIJ_PRIVATE: 8105d71ae5a4SJacob Faibussowitsch new_local_type = MATSEQBAIJ; 8106d71ae5a4SJacob Faibussowitsch break; 8107d71ae5a4SJacob Faibussowitsch case MATSBAIJ_PRIVATE: 8108d71ae5a4SJacob Faibussowitsch new_local_type = MATSEQSBAIJ; 8109d71ae5a4SJacob Faibussowitsch break; 8110d71ae5a4SJacob Faibussowitsch default: 8111d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_SUP, "Unsupported private type %d in %s", new_local_type_private, PETSC_FUNCTION_NAME); 8112e7931f94SStefano Zampini } 8113ed8ed4edSstefano_zampini } else { /* by default, new_local_type is seqaij */ 8114ed8ed4edSstefano_zampini new_local_type = MATSEQAIJ; 811528143c3dSStefano Zampini bs = 1; 8116e7931f94SStefano Zampini } 8117e7931f94SStefano Zampini 811870cf5478SStefano Zampini /* create MATIS object if needed */ 811957de7509SStefano Zampini if (!reuse) { 81209566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &rows, &cols)); 81219566063dSJacob Faibussowitsch PetscCall(MatCreateIS(comm_n, bs, PETSC_DECIDE, PETSC_DECIDE, rows, cols, l2gmap, l2gmap, mat_n)); 812270cf5478SStefano Zampini } else { 812370cf5478SStefano Zampini /* it also destroys the local matrices */ 812457de7509SStefano Zampini if (*mat_n) { 81259566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*mat_n, l2gmap, l2gmap)); 812657de7509SStefano Zampini } else { /* this is a fake object */ 81279566063dSJacob Faibussowitsch PetscCall(MatCreateIS(comm_n, bs, PETSC_DECIDE, PETSC_DECIDE, rows, cols, l2gmap, l2gmap, mat_n)); 812857de7509SStefano Zampini } 812970cf5478SStefano Zampini } 81309566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*mat_n, &local_mat)); 81319566063dSJacob Faibussowitsch PetscCall(MatSetType(local_mat, new_local_type)); 81329d30be91SStefano Zampini 81339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_recvs, recv_req_vals, MPI_STATUSES_IGNORE)); 81349d30be91SStefano Zampini 81359d30be91SStefano Zampini /* Global to local map of received indices */ 81369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(buf_size_idxs, &recv_buffer_idxs_local)); /* needed for values insertion */ 81379566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(l2gmap, IS_GTOLM_MASK, buf_size_idxs, recv_buffer_idxs, &i, recv_buffer_idxs_local)); 81389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&l2gmap)); 81399d30be91SStefano Zampini 81409d30be91SStefano Zampini /* restore attributes -> type of incoming data and its size */ 81419d30be91SStefano Zampini buf_size_idxs = 0; 81429d30be91SStefano Zampini for (i = 0; i < n_recvs; i++) { 81439d30be91SStefano Zampini recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs]; 81449d30be91SStefano Zampini recv_buffer_idxs_local[buf_size_idxs + 1] = recv_buffer_idxs[buf_size_idxs + 1]; 81459d30be91SStefano Zampini buf_size_idxs += (PetscInt)olengths_idxs[i]; 81469d30be91SStefano Zampini } 81479566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_buffer_idxs)); 81489d30be91SStefano Zampini 81499d30be91SStefano Zampini /* set preallocation */ 81509566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)local_mat, MATSEQDENSE, &newisdense)); 81519d30be91SStefano Zampini if (!newisdense) { 81520a545947SLisandro Dalcin PetscInt *new_local_nnz = NULL; 81539d30be91SStefano Zampini 81549d30be91SStefano Zampini ptr_idxs = recv_buffer_idxs_local; 815548a46eb9SPierre Jolivet if (n_recvs) PetscCall(PetscCalloc1(new_local_rows, &new_local_nnz)); 81569d30be91SStefano Zampini for (i = 0; i < n_recvs; i++) { 81579d30be91SStefano Zampini PetscInt j; 81589d30be91SStefano Zampini if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */ 8159ad540459SPierre Jolivet for (j = 0; j < *(ptr_idxs + 1); j++) new_local_nnz[*(ptr_idxs + 2 + j)] += *(ptr_idxs + 1); 81609d30be91SStefano Zampini } else { 81619d30be91SStefano Zampini /* TODO */ 81629d30be91SStefano Zampini } 81639d30be91SStefano Zampini ptr_idxs += olengths_idxs[i]; 81649d30be91SStefano Zampini } 81659d30be91SStefano Zampini if (new_local_nnz) { 81669d30be91SStefano Zampini for (i = 0; i < new_local_rows; i++) new_local_nnz[i] = PetscMin(new_local_nnz[i], new_local_rows); 81679566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(local_mat, 0, new_local_nnz)); 81689d30be91SStefano Zampini for (i = 0; i < new_local_rows; i++) new_local_nnz[i] /= bs; 81699566063dSJacob Faibussowitsch PetscCall(MatSeqBAIJSetPreallocation(local_mat, bs, 0, new_local_nnz)); 81709d30be91SStefano Zampini for (i = 0; i < new_local_rows; i++) new_local_nnz[i] = PetscMax(new_local_nnz[i] - i, 0); 81719566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(local_mat, bs, 0, new_local_nnz)); 81729d30be91SStefano Zampini } else { 81739566063dSJacob Faibussowitsch PetscCall(MatSetUp(local_mat)); 81749d30be91SStefano Zampini } 81759566063dSJacob Faibussowitsch PetscCall(PetscFree(new_local_nnz)); 81769d30be91SStefano Zampini } else { 81779566063dSJacob Faibussowitsch PetscCall(MatSetUp(local_mat)); 81789d30be91SStefano Zampini } 8179e7931f94SStefano Zampini 8180e7931f94SStefano Zampini /* set values */ 8181e7931f94SStefano Zampini ptr_vals = recv_buffer_vals; 81829d30be91SStefano Zampini ptr_idxs = recv_buffer_idxs_local; 8183e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 8184e7931f94SStefano Zampini if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */ 81859566063dSJacob Faibussowitsch PetscCall(MatSetOption(local_mat, MAT_ROW_ORIENTED, PETSC_FALSE)); 81869566063dSJacob Faibussowitsch PetscCall(MatSetValues(local_mat, *(ptr_idxs + 1), ptr_idxs + 2, *(ptr_idxs + 1), ptr_idxs + 2, ptr_vals, ADD_VALUES)); 81879566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(local_mat, MAT_FLUSH_ASSEMBLY)); 81889566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(local_mat, MAT_FLUSH_ASSEMBLY)); 81899566063dSJacob Faibussowitsch PetscCall(MatSetOption(local_mat, MAT_ROW_ORIENTED, PETSC_TRUE)); 819028143c3dSStefano Zampini } else { 819128143c3dSStefano Zampini /* TODO */ 8192e7931f94SStefano Zampini } 8193e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 8194e7931f94SStefano Zampini ptr_vals += olengths_vals[i]; 8195e7931f94SStefano Zampini } 81969566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(local_mat, MAT_FINAL_ASSEMBLY)); 81979566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(local_mat, MAT_FINAL_ASSEMBLY)); 81989566063dSJacob Faibussowitsch PetscCall(MatISRestoreLocalMat(*mat_n, &local_mat)); 81999566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat_n, MAT_FINAL_ASSEMBLY)); 82009566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat_n, MAT_FINAL_ASSEMBLY)); 82019566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_buffer_vals)); 8202e7931f94SStefano Zampini 8203dfd14d43SStefano Zampini #if 0 820428143c3dSStefano Zampini if (!restrict_comm) { /* check */ 8205e7931f94SStefano Zampini Vec lvec,rvec; 8206e7931f94SStefano Zampini PetscReal infty_error; 8207e7931f94SStefano Zampini 82089566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(mat,&rvec,&lvec)); 82099566063dSJacob Faibussowitsch PetscCall(VecSetRandom(rvec,NULL)); 82109566063dSJacob Faibussowitsch PetscCall(MatMult(mat,rvec,lvec)); 82119566063dSJacob Faibussowitsch PetscCall(VecScale(lvec,-1.0)); 82129566063dSJacob Faibussowitsch PetscCall(MatMultAdd(*mat_n,rvec,lvec,lvec)); 82139566063dSJacob Faibussowitsch PetscCall(VecNorm(lvec,NORM_INFINITY,&infty_error)); 82149566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error)); 82159566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rvec)); 82169566063dSJacob Faibussowitsch PetscCall(VecDestroy(&lvec)); 8217e7931f94SStefano Zampini } 821828143c3dSStefano Zampini #endif 8219e7931f94SStefano Zampini 822028143c3dSStefano Zampini /* assemble new additional is (if any) */ 822128143c3dSStefano Zampini if (nis) { 822228143c3dSStefano Zampini PetscInt **temp_idxs, *count_is, j, psum; 822328143c3dSStefano Zampini 82249566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_recvs, recv_req_idxs_is, MPI_STATUSES_IGNORE)); 82259566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nis, &count_is)); 822628143c3dSStefano Zampini ptr_idxs = recv_buffer_idxs_is; 822728143c3dSStefano Zampini psum = 0; 822828143c3dSStefano Zampini for (i = 0; i < n_recvs; i++) { 822928143c3dSStefano Zampini for (j = 0; j < nis; j++) { 823028143c3dSStefano Zampini PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */ 823128143c3dSStefano Zampini count_is[j] += plen; /* increment counting of buffer for j-th IS */ 823228143c3dSStefano Zampini psum += plen; 823328143c3dSStefano Zampini ptr_idxs += plen + 1; /* shift pointer to received data */ 823428143c3dSStefano Zampini } 823528143c3dSStefano Zampini } 82369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nis, &temp_idxs)); 82379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(psum, &temp_idxs[0])); 82388e3a54c0SPierre Jolivet for (i = 1; i < nis; i++) temp_idxs[i] = PetscSafePointerPlusOffset(temp_idxs[i - 1], count_is[i - 1]); 82399566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(count_is, nis)); 824028143c3dSStefano Zampini ptr_idxs = recv_buffer_idxs_is; 824128143c3dSStefano Zampini for (i = 0; i < n_recvs; i++) { 824228143c3dSStefano Zampini for (j = 0; j < nis; j++) { 824328143c3dSStefano Zampini PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */ 82449566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&temp_idxs[j][count_is[j]], ptr_idxs + 1, plen)); 824528143c3dSStefano Zampini count_is[j] += plen; /* increment starting point of buffer for j-th IS */ 824628143c3dSStefano Zampini ptr_idxs += plen + 1; /* shift pointer to received data */ 824728143c3dSStefano Zampini } 824828143c3dSStefano Zampini } 824928143c3dSStefano Zampini for (i = 0; i < nis; i++) { 82509566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isarray[i])); 82519566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&count_is[i], temp_idxs[i])); 82529566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm_n, count_is[i], temp_idxs[i], PETSC_COPY_VALUES, &isarray[i])); 825328143c3dSStefano Zampini } 82549566063dSJacob Faibussowitsch PetscCall(PetscFree(count_is)); 82559566063dSJacob Faibussowitsch PetscCall(PetscFree(temp_idxs[0])); 82569566063dSJacob Faibussowitsch PetscCall(PetscFree(temp_idxs)); 825728143c3dSStefano Zampini } 8258e7931f94SStefano Zampini /* free workspace */ 82599566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_buffer_idxs_is)); 82609566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_sends, send_req_idxs, MPI_STATUSES_IGNORE)); 82619566063dSJacob Faibussowitsch PetscCall(PetscFree(send_buffer_idxs)); 82629566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_sends, send_req_vals, MPI_STATUSES_IGNORE)); 8263e7931f94SStefano Zampini if (isdense) { 82649566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(mat, &local_mat)); 82659566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(local_mat, &send_buffer_vals)); 82669566063dSJacob Faibussowitsch PetscCall(MatISRestoreLocalMat(mat, &local_mat)); 8267e7931f94SStefano Zampini } else { 82689566063dSJacob Faibussowitsch /* PetscCall(PetscFree(send_buffer_vals)); */ 8269e7931f94SStefano Zampini } 827028143c3dSStefano Zampini if (nis) { 82719566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_sends, send_req_idxs_is, MPI_STATUSES_IGNORE)); 82729566063dSJacob Faibussowitsch PetscCall(PetscFree(send_buffer_idxs_is)); 827328143c3dSStefano Zampini } 82741ae86dd6SStefano Zampini 82751ae86dd6SStefano Zampini if (nvecs) { 82769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_recvs, recv_req_vecs, MPI_STATUSES_IGNORE)); 82779566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_sends, send_req_vecs, MPI_STATUSES_IGNORE)); 82789566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(nnsp_vec[0], &send_buffer_vecs)); 82799566063dSJacob Faibussowitsch PetscCall(VecDestroy(&nnsp_vec[0])); 82809566063dSJacob Faibussowitsch PetscCall(VecCreate(comm_n, &nnsp_vec[0])); 82819566063dSJacob Faibussowitsch PetscCall(VecSetSizes(nnsp_vec[0], new_local_rows, PETSC_DECIDE)); 82829566063dSJacob Faibussowitsch PetscCall(VecSetType(nnsp_vec[0], VECSTANDARD)); 82831ae86dd6SStefano Zampini /* set values */ 82841ae86dd6SStefano Zampini ptr_vals = recv_buffer_vecs; 82851ae86dd6SStefano Zampini ptr_idxs = recv_buffer_idxs_local; 82869566063dSJacob Faibussowitsch PetscCall(VecGetArray(nnsp_vec[0], &send_buffer_vecs)); 82871ae86dd6SStefano Zampini for (i = 0; i < n_recvs; i++) { 82881ae86dd6SStefano Zampini PetscInt j; 8289ad540459SPierre Jolivet for (j = 0; j < *(ptr_idxs + 1); j++) send_buffer_vecs[*(ptr_idxs + 2 + j)] += *(ptr_vals + j); 82901ae86dd6SStefano Zampini ptr_idxs += olengths_idxs[i]; 82911ae86dd6SStefano Zampini ptr_vals += olengths_idxs[i] - 2; 82921ae86dd6SStefano Zampini } 82939566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(nnsp_vec[0], &send_buffer_vecs)); 82949566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(nnsp_vec[0])); 82959566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(nnsp_vec[0])); 82961ae86dd6SStefano Zampini } 82971ae86dd6SStefano Zampini 82989566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_buffer_vecs)); 82999566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_buffer_idxs_local)); 83009566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_req_idxs)); 83019566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_req_vals)); 83029566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_req_vecs)); 83039566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_req_idxs_is)); 83049566063dSJacob Faibussowitsch PetscCall(PetscFree(send_req_idxs)); 83059566063dSJacob Faibussowitsch PetscCall(PetscFree(send_req_vals)); 83069566063dSJacob Faibussowitsch PetscCall(PetscFree(send_req_vecs)); 83079566063dSJacob Faibussowitsch PetscCall(PetscFree(send_req_idxs_is)); 83089566063dSJacob Faibussowitsch PetscCall(PetscFree(ilengths_vals)); 83099566063dSJacob Faibussowitsch PetscCall(PetscFree(ilengths_idxs)); 83109566063dSJacob Faibussowitsch PetscCall(PetscFree(olengths_vals)); 83119566063dSJacob Faibussowitsch PetscCall(PetscFree(olengths_idxs)); 83129566063dSJacob Faibussowitsch PetscCall(PetscFree(onodes)); 831328143c3dSStefano Zampini if (nis) { 83149566063dSJacob Faibussowitsch PetscCall(PetscFree(ilengths_idxs_is)); 83159566063dSJacob Faibussowitsch PetscCall(PetscFree(olengths_idxs_is)); 83169566063dSJacob Faibussowitsch PetscCall(PetscFree(onodes_is)); 831728143c3dSStefano Zampini } 83189566063dSJacob Faibussowitsch PetscCall(PetscSubcommDestroy(&subcomm)); 83196aad120cSJose E. Roman if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not participate */ 83209566063dSJacob Faibussowitsch PetscCall(MatDestroy(mat_n)); 832148a46eb9SPierre Jolivet for (i = 0; i < nis; i++) PetscCall(ISDestroy(&isarray[i])); 83221ae86dd6SStefano Zampini if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */ 83239566063dSJacob Faibussowitsch PetscCall(VecDestroy(&nnsp_vec[0])); 83241ae86dd6SStefano Zampini } 832553a05cb3SStefano Zampini *mat_n = NULL; 832628143c3dSStefano Zampini } 83273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8328e7931f94SStefano Zampini } 8329a57a6d2fSStefano Zampini 833012edc857SStefano Zampini /* temporary hack into ksp private data structure */ 8331af0996ceSBarry Smith #include <petsc/private/kspimpl.h> 833212edc857SStefano Zampini 83339de2952eSStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc, Mat coarse_submat) 8334d71ae5a4SJacob Faibussowitsch { 8335c8587f34SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 8336c8587f34SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 83379de2952eSStefano Zampini PCBDDCGraph graph = pcbddc->mat_graph; 83389de2952eSStefano Zampini Mat coarse_mat, coarse_mat_is; 83391ae86dd6SStefano Zampini Mat coarsedivudotp = NULL; 83401e0482f5SStefano Zampini Mat coarseG, t_coarse_mat_is; 83419881197aSStefano Zampini MatNullSpace CoarseNullSpace = NULL; 834220a2ab83SStefano Zampini ISLocalToGlobalMapping coarse_islg; 83434f819b78SStefano Zampini IS coarse_is, *isarray, corners; 83446e683305SStefano Zampini PetscInt i, im_active = -1, active_procs = -1; 834530368db7SStefano Zampini PetscInt nis, nisdofs, nisneu, nisvert; 83469de2952eSStefano Zampini PetscInt coarse_eqs_per_proc, coarsening_ratio; 8347f9eb5b7dSStefano Zampini PC pc_temp; 8348c8587f34SStefano Zampini PCType coarse_pc_type; 8349c8587f34SStefano Zampini KSPType coarse_ksp_type; 8350f9eb5b7dSStefano Zampini PetscBool multilevel_requested, multilevel_allowed; 83519de2952eSStefano Zampini PetscBool coarse_reuse, multi_element = graph->multi_element; 83521e0482f5SStefano Zampini PetscInt ncoarse, nedcfield; 835368457ee5SStefano Zampini PetscBool compute_vecs = PETSC_FALSE; 835422bc73bbSStefano Zampini PetscScalar *array; 835557de7509SStefano Zampini MatReuse coarse_mat_reuse; 835657de7509SStefano Zampini PetscBool restr, full_restr, have_void; 8357e569e4e1SStefano Zampini PetscMPIInt size; 8358fdc09c96SStefano Zampini 8359c8587f34SStefano Zampini PetscFunctionBegin; 83609566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_CoarseSetUp[pcbddc->current_level], pc, 0, 0, 0)); 8361c8587f34SStefano Zampini /* Assign global numbering to coarse dofs */ 836268457ee5SStefano 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 */ 8363fa7f1dd8SStefano Zampini PetscInt ocoarse_size; 83645a75c04eSSatish Balay compute_vecs = PETSC_TRUE; 83657de4f681Sstefano_zampini 83667de4f681Sstefano_zampini pcbddc->new_primal_space = PETSC_TRUE; 8367fa7f1dd8SStefano Zampini ocoarse_size = pcbddc->coarse_size; 83689566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->global_primal_indices)); 83699566063dSJacob Faibussowitsch PetscCall(PCBDDCComputePrimalNumbering(pc, &pcbddc->coarse_size, &pcbddc->global_primal_indices)); 8370f4ddd8eeSStefano Zampini /* see if we can avoid some work */ 8371fa7f1dd8SStefano Zampini if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */ 837251bea450SStefano Zampini /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */ 837351bea450SStefano Zampini if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) { 83749566063dSJacob Faibussowitsch PetscCall(KSPReset(pcbddc->coarse_ksp)); 8375fa7f1dd8SStefano Zampini coarse_reuse = PETSC_FALSE; 8376fa7f1dd8SStefano Zampini } else { /* we can safely reuse already computed coarse matrix */ 8377fa7f1dd8SStefano Zampini coarse_reuse = PETSC_TRUE; 8378f4ddd8eeSStefano Zampini } 8379fa7f1dd8SStefano Zampini } else { /* there's no coarse ksp, so we need to create the coarse matrix too */ 8380fa7f1dd8SStefano Zampini coarse_reuse = PETSC_FALSE; 8381f4ddd8eeSStefano Zampini } 838270cf5478SStefano Zampini /* reset any subassembling information */ 838348a46eb9SPierre Jolivet if (!coarse_reuse || pcbddc->recompute_topography) PetscCall(ISDestroy(&pcbddc->coarse_subassembling)); 83846e683305SStefano Zampini } else { /* primal space is unchanged, so we can reuse coarse matrix */ 8385fa7f1dd8SStefano Zampini coarse_reuse = PETSC_TRUE; 8386f4ddd8eeSStefano Zampini } 838757de7509SStefano Zampini if (coarse_reuse && pcbddc->coarse_ksp) { 83889566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(pcbddc->coarse_ksp, &coarse_mat, NULL)); 83899566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coarse_mat)); 839057de7509SStefano Zampini coarse_mat_reuse = MAT_REUSE_MATRIX; 839118a45a71SStefano Zampini } else { 839257de7509SStefano Zampini coarse_mat = NULL; 839357de7509SStefano Zampini coarse_mat_reuse = MAT_INITIAL_MATRIX; 83946e683305SStefano Zampini } 8395e7931f94SStefano Zampini 8396abbbba34SStefano Zampini /* creates temporary l2gmap and IS for coarse indexes */ 83979566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), pcbddc->local_primal_size, pcbddc->global_primal_indices, PETSC_COPY_VALUES, &coarse_is)); 83989566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(coarse_is, &coarse_islg)); 8399abbbba34SStefano Zampini 8400abbbba34SStefano Zampini /* creates temporary MATIS object for coarse matrix */ 84019de2952eSStefano Zampini PetscCall(MatCreate(PetscObjectComm((PetscObject)pc), &t_coarse_mat_is)); 84029de2952eSStefano Zampini PetscCall(MatSetType(t_coarse_mat_is, MATIS)); 84039de2952eSStefano Zampini PetscCall(MatSetSizes(t_coarse_mat_is, PETSC_DECIDE, PETSC_DECIDE, pcbddc->coarse_size, pcbddc->coarse_size)); 84049de2952eSStefano Zampini PetscCall(MatISSetAllowRepeated(t_coarse_mat_is, PETSC_TRUE)); 84059de2952eSStefano Zampini PetscCall(MatSetLocalToGlobalMapping(t_coarse_mat_is, coarse_islg, coarse_islg)); 84069de2952eSStefano Zampini PetscCall(MatISSetLocalMat(t_coarse_mat_is, coarse_submat)); 84079566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(t_coarse_mat_is, MAT_FINAL_ASSEMBLY)); 84089566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(t_coarse_mat_is, MAT_FINAL_ASSEMBLY)); 84099de2952eSStefano Zampini PetscCall(MatViewFromOptions(t_coarse_mat_is, (PetscObject)pc, "-pc_bddc_coarse_mat_is_view")); 8410abbbba34SStefano Zampini 841157de7509SStefano Zampini /* count "active" (i.e. with positive local size) and "void" processes */ 8412f4f49eeaSPierre Jolivet im_active = !!pcis->n; 84131c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&im_active, &active_procs, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)pc))); 841457de7509SStefano Zampini 841514f0bfb9SStefano Zampini /* determine number of processes partecipating to coarse solver and compute subassembling pattern */ 841628d58a37SPierre Jolivet /* restr : whether we want to exclude senders (which are not receivers) from the subassembling pattern */ 841757de7509SStefano Zampini /* full_restr : just use the receivers from the subassembling pattern */ 84189566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size)); 841957de7509SStefano Zampini coarse_mat_is = NULL; 842057de7509SStefano Zampini multilevel_allowed = PETSC_FALSE; 842157de7509SStefano Zampini multilevel_requested = PETSC_FALSE; 8422e569e4e1SStefano Zampini coarse_eqs_per_proc = PetscMin(PetscMax(pcbddc->coarse_size, 1), pcbddc->coarse_eqs_per_proc); 84239de2952eSStefano Zampini if (coarse_eqs_per_proc < 0 || size == 1) coarse_eqs_per_proc = PetscMax(pcbddc->coarse_size, 1); 842457de7509SStefano Zampini if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE; 8425e569e4e1SStefano Zampini if (pcbddc->coarse_size <= pcbddc->coarse_eqs_limit) multilevel_requested = PETSC_FALSE; 84269de2952eSStefano Zampini coarsening_ratio = multi_element ? 1 : pcbddc->coarsening_ratio; 842757de7509SStefano Zampini if (multilevel_requested) { 84289de2952eSStefano Zampini ncoarse = active_procs / coarsening_ratio; 842957de7509SStefano Zampini restr = PETSC_FALSE; 843057de7509SStefano Zampini full_restr = PETSC_FALSE; 843157de7509SStefano Zampini } else { 8432e569e4e1SStefano Zampini ncoarse = pcbddc->coarse_size / coarse_eqs_per_proc + !!(pcbddc->coarse_size % coarse_eqs_per_proc); 843357de7509SStefano Zampini restr = PETSC_TRUE; 843457de7509SStefano Zampini full_restr = PETSC_TRUE; 843557de7509SStefano Zampini } 8436e569e4e1SStefano Zampini if (!pcbddc->coarse_size || size == 1) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE; 843757de7509SStefano Zampini ncoarse = PetscMax(1, ncoarse); 843857de7509SStefano Zampini if (!pcbddc->coarse_subassembling) { 84399de2952eSStefano Zampini if (coarsening_ratio > 1) { 8440bb360cb4SStefano Zampini if (multilevel_requested) { 84419566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISGetSubassemblingPattern(pc->pmat, &ncoarse, pcbddc->coarse_adj_red, &pcbddc->coarse_subassembling, &have_void)); 8442bb360cb4SStefano Zampini } else { 84439566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISGetSubassemblingPattern(t_coarse_mat_is, &ncoarse, pcbddc->coarse_adj_red, &pcbddc->coarse_subassembling, &have_void)); 8444bb360cb4SStefano Zampini } 8445a198735bSStefano Zampini } else { 84467de4f681Sstefano_zampini PetscMPIInt rank; 844728d58a37SPierre Jolivet 84489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc), &rank)); 8449e569e4e1SStefano Zampini have_void = (active_procs == (PetscInt)size) ? PETSC_FALSE : PETSC_TRUE; 84509566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)pc), 1, rank, 1, &pcbddc->coarse_subassembling)); 8451a198735bSStefano Zampini } 845257de7509SStefano Zampini } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */ 845357de7509SStefano Zampini PetscInt psum; 845457de7509SStefano Zampini if (pcbddc->coarse_ksp) psum = 1; 845557de7509SStefano Zampini else psum = 0; 84561c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&psum, &ncoarse, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)pc))); 8457075e25bcSStefano Zampini have_void = ncoarse < size ? PETSC_TRUE : PETSC_FALSE; 845857de7509SStefano Zampini } 845957de7509SStefano Zampini /* determine if we can go multilevel */ 846057de7509SStefano Zampini if (multilevel_requested) { 846157de7509SStefano Zampini if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */ 846257de7509SStefano Zampini else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */ 846357de7509SStefano Zampini } 846457de7509SStefano Zampini if (multilevel_allowed && have_void) restr = PETSC_TRUE; 846557de7509SStefano Zampini 8466e4d548c7SStefano Zampini /* dump subassembling pattern */ 846748a46eb9SPierre Jolivet if (pcbddc->dbg_flag && multilevel_allowed) PetscCall(ISView(pcbddc->coarse_subassembling, pcbddc->dbg_viewer)); 84686e683305SStefano Zampini /* compute dofs splitting and neumann boundaries for coarse dofs */ 84691e0482f5SStefano Zampini nedcfield = -1; 84704f819b78SStefano Zampini corners = NULL; 84718966356dSPierre Jolivet if (multilevel_allowed && !coarse_reuse && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal || pcbddc->nedclocal || pcbddc->corner_selected)) { /* protects from unneeded computations */ 84726e683305SStefano Zampini PetscInt *tidxs, *tidxs2, nout, tsize, i; 84736e683305SStefano Zampini const PetscInt *idxs; 84746e683305SStefano Zampini ISLocalToGlobalMapping tmap; 84756e683305SStefano Zampini 84766e683305SStefano Zampini /* create map between primal indices (in local representative ordering) and local primal numbering */ 84779566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PETSC_COMM_SELF, 1, pcbddc->local_primal_size, pcbddc->primal_indices_local_idxs, PETSC_COPY_VALUES, &tmap)); 84786e683305SStefano Zampini /* allocate space for temporary storage */ 84799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->local_primal_size, &tidxs)); 84809566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->local_primal_size, &tidxs2)); 84816e683305SStefano Zampini /* allocate for IS array */ 84826e683305SStefano Zampini nisdofs = pcbddc->n_ISForDofsLocal; 84831e0482f5SStefano Zampini if (pcbddc->nedclocal) { 84841e0482f5SStefano Zampini if (pcbddc->nedfield > -1) { 84851e0482f5SStefano Zampini nedcfield = pcbddc->nedfield; 84861e0482f5SStefano Zampini } else { 84871e0482f5SStefano Zampini nedcfield = 0; 848863a3b9bcSJacob Faibussowitsch PetscCheck(!nisdofs, PetscObjectComm((PetscObject)pc), PETSC_ERR_PLIB, "This should not happen (%" PetscInt_FMT ")", nisdofs); 84891e0482f5SStefano Zampini nisdofs = 1; 84901e0482f5SStefano Zampini } 84911e0482f5SStefano Zampini } 84926e683305SStefano Zampini nisneu = !!pcbddc->NeumannBoundariesLocal; 849327b6a85dSStefano Zampini nisvert = 0; /* nisvert is not used */ 849430368db7SStefano Zampini nis = nisdofs + nisneu + nisvert; 84959566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nis, &isarray)); 84966e683305SStefano Zampini /* dofs splitting */ 84976e683305SStefano Zampini for (i = 0; i < nisdofs; i++) { 84989566063dSJacob Faibussowitsch /* PetscCall(ISView(pcbddc->ISForDofsLocal[i],0)); */ 84991e0482f5SStefano Zampini if (nedcfield != i) { 85009566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->ISForDofsLocal[i], &tsize)); 85019566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->ISForDofsLocal[i], &idxs)); 85029566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(tmap, IS_GTOLM_DROP, tsize, idxs, &nout, tidxs)); 85039566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->ISForDofsLocal[i], &idxs)); 85041e0482f5SStefano Zampini } else { 85059566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->nedclocal, &tsize)); 85069566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->nedclocal, &idxs)); 85079566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(tmap, IS_GTOLM_DROP, tsize, idxs, &nout, tidxs)); 850863a3b9bcSJacob Faibussowitsch PetscCheck(tsize == nout, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Failed when mapping coarse nedelec field! %" PetscInt_FMT " != %" PetscInt_FMT, tsize, nout); 85099566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->nedclocal, &idxs)); 85101e0482f5SStefano Zampini } 85119566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(coarse_islg, nout, tidxs, tidxs2)); 85129566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), nout, tidxs2, PETSC_COPY_VALUES, &isarray[i])); 85139566063dSJacob Faibussowitsch /* PetscCall(ISView(isarray[i],0)); */ 85146e683305SStefano Zampini } 85156e683305SStefano Zampini /* neumann boundaries */ 85166e683305SStefano Zampini if (pcbddc->NeumannBoundariesLocal) { 85179566063dSJacob Faibussowitsch /* PetscCall(ISView(pcbddc->NeumannBoundariesLocal,0)); */ 85189566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->NeumannBoundariesLocal, &tsize)); 85199566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->NeumannBoundariesLocal, &idxs)); 85209566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(tmap, IS_GTOLM_DROP, tsize, idxs, &nout, tidxs)); 85219566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->NeumannBoundariesLocal, &idxs)); 85229566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(coarse_islg, nout, tidxs, tidxs2)); 85239566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), nout, tidxs2, PETSC_COPY_VALUES, &isarray[nisdofs])); 85249566063dSJacob Faibussowitsch /* PetscCall(ISView(isarray[nisdofs],0)); */ 85256e683305SStefano Zampini } 85264f819b78SStefano Zampini /* coordinates */ 85274f819b78SStefano Zampini if (pcbddc->corner_selected) { 85289566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &corners)); 85299566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(corners, &tsize)); 85309566063dSJacob Faibussowitsch PetscCall(ISGetIndices(corners, &idxs)); 85319566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(tmap, IS_GTOLM_DROP, tsize, idxs, &nout, tidxs)); 853263a3b9bcSJacob Faibussowitsch PetscCheck(tsize == nout, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Failed when mapping corners! %" PetscInt_FMT " != %" PetscInt_FMT, tsize, nout); 85339566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(corners, &idxs)); 85349566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &corners)); 85359566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(coarse_islg, nout, tidxs, tidxs2)); 85369566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), nout, tidxs2, PETSC_COPY_VALUES, &corners)); 85374f819b78SStefano Zampini } 85389566063dSJacob Faibussowitsch PetscCall(PetscFree(tidxs)); 85399566063dSJacob Faibussowitsch PetscCall(PetscFree(tidxs2)); 85409566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&tmap)); 85416e683305SStefano Zampini } else { 85426e683305SStefano Zampini nis = 0; 85436e683305SStefano Zampini nisdofs = 0; 85446e683305SStefano Zampini nisneu = 0; 854530368db7SStefano Zampini nisvert = 0; 85466e683305SStefano Zampini isarray = NULL; 85476e683305SStefano Zampini } 85486e683305SStefano Zampini /* destroy no longer needed map */ 85499566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&coarse_islg)); 85506e683305SStefano Zampini 855157de7509SStefano Zampini /* subassemble */ 855257de7509SStefano Zampini if (multilevel_allowed) { 85531ae86dd6SStefano Zampini Vec vp[1]; 85541ae86dd6SStefano Zampini PetscInt nvecs = 0; 85559de2952eSStefano Zampini PetscBool reuse; 85561ae86dd6SStefano Zampini 85571ae86dd6SStefano Zampini vp[0] = NULL; 85589de2952eSStefano Zampini /* XXX HDIV also */ 85591ae86dd6SStefano Zampini if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */ 85609566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pc), &vp[0])); 85619566063dSJacob Faibussowitsch PetscCall(VecSetSizes(vp[0], pcbddc->local_primal_size, PETSC_DECIDE)); 85629566063dSJacob Faibussowitsch PetscCall(VecSetType(vp[0], VECSTANDARD)); 85631ae86dd6SStefano Zampini nvecs = 1; 85641ae86dd6SStefano Zampini 85651ae86dd6SStefano Zampini if (pcbddc->divudotp) { 8566a198735bSStefano Zampini Mat B, loc_divudotp; 85671ae86dd6SStefano Zampini Vec v, p; 85681ae86dd6SStefano Zampini IS dummy; 85691ae86dd6SStefano Zampini PetscInt np; 85701ae86dd6SStefano Zampini 85719566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pcbddc->divudotp, &loc_divudotp)); 85729566063dSJacob Faibussowitsch PetscCall(MatGetSize(loc_divudotp, &np, NULL)); 85739566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, np, 0, 1, &dummy)); 85749566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(loc_divudotp, dummy, pcis->is_B_local, MAT_INITIAL_MATRIX, &B)); 85759566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(B, &v, &p)); 85769566063dSJacob Faibussowitsch PetscCall(VecSet(p, 1.)); 85779566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(B, p, v)); 85789566063dSJacob Faibussowitsch PetscCall(VecDestroy(&p)); 85799566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 85809566063dSJacob Faibussowitsch PetscCall(VecGetArray(vp[0], &array)); 85819566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_P, array)); 85829566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->coarse_phi_B, v, pcbddc->vec1_P)); 85839566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_P)); 85849566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(vp[0], &array)); 85859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&dummy)); 85869566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 858774e2c79eSStefano Zampini } 85881ae86dd6SStefano Zampini } 85899de2952eSStefano Zampini if (coarse_mat) reuse = PETSC_TRUE; 85909de2952eSStefano Zampini else reuse = PETSC_FALSE; 85919de2952eSStefano Zampini if (multi_element) { 85929de2952eSStefano Zampini /* XXX divudotp */ 85939de2952eSStefano Zampini PetscCall(MatISSetAllowRepeated(t_coarse_mat_is, PETSC_FALSE)); 85949de2952eSStefano Zampini PetscCall(PetscObjectReference((PetscObject)t_coarse_mat_is)); 85959de2952eSStefano Zampini coarse_mat_is = t_coarse_mat_is; 85969de2952eSStefano Zampini } else { 85979de2952eSStefano Zampini PetscCall(MPIU_Allreduce(MPI_IN_PLACE, &reuse, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 85989de2952eSStefano Zampini if (reuse) { 85999566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISSubassemble(t_coarse_mat_is, pcbddc->coarse_subassembling, 0, restr, full_restr, PETSC_TRUE, &coarse_mat, nis, isarray, nvecs, vp)); 860074e2c79eSStefano Zampini } else { 86019566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISSubassemble(t_coarse_mat_is, pcbddc->coarse_subassembling, 0, restr, full_restr, PETSC_FALSE, &coarse_mat_is, nis, isarray, nvecs, vp)); 86021ae86dd6SStefano Zampini } 86031ae86dd6SStefano Zampini if (vp[0]) { /* vp[0] could have been placed on a different set of processes */ 86041683a169SBarry Smith PetscScalar *arraym; 86051683a169SBarry Smith const PetscScalar *arrayv; 86061ae86dd6SStefano Zampini PetscInt nl; 86079566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vp[0], &nl)); 86089566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, 1, nl, NULL, &coarsedivudotp)); 86099566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(coarsedivudotp, &arraym)); 86109566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vp[0], &arrayv)); 86119566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(arraym, arrayv, nl)); 86129566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vp[0], &arrayv)); 86139566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(coarsedivudotp, &arraym)); 86149566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vp[0])); 8615a198735bSStefano Zampini } else { 86169566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, 0, 0, 1, NULL, &coarsedivudotp)); 86171ae86dd6SStefano Zampini } 86189de2952eSStefano Zampini } 86191ae86dd6SStefano Zampini } else { 86209de2952eSStefano Zampini if (ncoarse != size) PetscCall(PCBDDCMatISSubassemble(t_coarse_mat_is, pcbddc->coarse_subassembling, 0, restr, full_restr, PETSC_FALSE, &coarse_mat_is, 0, NULL, 0, NULL)); 86219de2952eSStefano Zampini else { 86229de2952eSStefano Zampini PetscCall(PetscObjectReference((PetscObject)t_coarse_mat_is)); 86239de2952eSStefano Zampini coarse_mat_is = t_coarse_mat_is; 86249de2952eSStefano Zampini } 86256e683305SStefano Zampini } 862657de7509SStefano Zampini if (coarse_mat_is || coarse_mat) { 862757de7509SStefano Zampini if (!multilevel_allowed) { 86289566063dSJacob Faibussowitsch PetscCall(MatConvert(coarse_mat_is, MATAIJ, coarse_mat_reuse, &coarse_mat)); 86296e683305SStefano Zampini } else { 863057de7509SStefano Zampini /* if this matrix is present, it means we are not reusing the coarse matrix */ 863157de7509SStefano Zampini if (coarse_mat_is) { 863228b400f6SJacob Faibussowitsch PetscCheck(!coarse_mat, PetscObjectComm((PetscObject)coarse_mat_is), PETSC_ERR_PLIB, "This should not happen"); 86339566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coarse_mat_is)); 863457de7509SStefano Zampini coarse_mat = coarse_mat_is; 863557de7509SStefano Zampini } 8636779c1cceSStefano Zampini } 8637779c1cceSStefano Zampini } 86389566063dSJacob Faibussowitsch PetscCall(MatDestroy(&t_coarse_mat_is)); 86399566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_mat_is)); 86406e683305SStefano Zampini 86416e683305SStefano Zampini /* create local to global scatters for coarse problem */ 864268457ee5SStefano Zampini if (compute_vecs) { 86436e683305SStefano Zampini PetscInt lrows; 86449566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->coarse_vec)); 864557de7509SStefano Zampini if (coarse_mat) { 86469566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(coarse_mat, &lrows, NULL)); 86476e683305SStefano Zampini } else { 86486e683305SStefano Zampini lrows = 0; 86496e683305SStefano Zampini } 86509566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pc), &pcbddc->coarse_vec)); 86519566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pcbddc->coarse_vec, lrows, PETSC_DECIDE)); 86529566063dSJacob Faibussowitsch PetscCall(VecSetType(pcbddc->coarse_vec, coarse_mat ? coarse_mat->defaultvectype : VECSTANDARD)); 86539566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->coarse_loc_to_glob)); 86549566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(pcbddc->vec1_P, NULL, pcbddc->coarse_vec, coarse_is, &pcbddc->coarse_loc_to_glob)); 86556e683305SStefano Zampini } 86569566063dSJacob Faibussowitsch PetscCall(ISDestroy(&coarse_is)); 8657c8587f34SStefano Zampini 8658f9eb5b7dSStefano Zampini /* set defaults for coarse KSP and PC */ 8659f9eb5b7dSStefano Zampini if (multilevel_allowed) { 8660f9eb5b7dSStefano Zampini coarse_ksp_type = KSPRICHARDSON; 8661f9eb5b7dSStefano Zampini coarse_pc_type = PCBDDC; 8662f9eb5b7dSStefano Zampini } else { 8663f9eb5b7dSStefano Zampini coarse_ksp_type = KSPPREONLY; 8664f9eb5b7dSStefano Zampini coarse_pc_type = PCREDUNDANT; 8665c8587f34SStefano Zampini } 8666c8587f34SStefano Zampini 86676e683305SStefano Zampini /* print some info if requested */ 86686e683305SStefano Zampini if (pcbddc->dbg_flag) { 86696e683305SStefano Zampini if (!multilevel_allowed) { 86709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 86716e683305SStefano Zampini if (multilevel_requested) { 86729de2952eSStefano Zampini 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, coarsening_ratio)); 86736e683305SStefano Zampini } else if (pcbddc->max_levels) { 867463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Maximum number of requested levels reached (%" PetscInt_FMT ")\n", pcbddc->max_levels)); 86756e683305SStefano Zampini } 86769566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 86776e683305SStefano Zampini } 86786e683305SStefano Zampini } 86796e683305SStefano Zampini 86801e0482f5SStefano Zampini /* communicate coarse discrete gradient */ 86811e0482f5SStefano Zampini coarseG = NULL; 86821e0482f5SStefano Zampini if (pcbddc->nedcG && multilevel_allowed) { 86831e0482f5SStefano Zampini MPI_Comm ccomm; 86841e0482f5SStefano Zampini if (coarse_mat) { 86851e0482f5SStefano Zampini ccomm = PetscObjectComm((PetscObject)coarse_mat); 86861e0482f5SStefano Zampini } else { 86871e0482f5SStefano Zampini ccomm = MPI_COMM_NULL; 86881e0482f5SStefano Zampini } 86899566063dSJacob Faibussowitsch PetscCall(MatMPIAIJRestrict(pcbddc->nedcG, ccomm, &coarseG)); 86901e0482f5SStefano Zampini } 86911e0482f5SStefano Zampini 8692f9eb5b7dSStefano Zampini /* create the coarse KSP object only once with defaults */ 869357de7509SStefano Zampini if (coarse_mat) { 869428d58a37SPierre Jolivet PetscBool isredundant, isbddc, force, valid; 86956a1308c2SStefano Zampini PetscViewer dbg_viewer = NULL; 8696b94d7dedSBarry Smith PetscBool isset, issym, isher, isspd; 86977274672aSStefano Zampini 86986e683305SStefano Zampini if (pcbddc->dbg_flag) { 869957de7509SStefano Zampini dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat)); 87009566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIAddTab(dbg_viewer, 2 * pcbddc->current_level)); 87016e683305SStefano Zampini } 8702f9eb5b7dSStefano Zampini if (!pcbddc->coarse_ksp) { 8703312be037SStefano Zampini char prefix[256], str_level[16]; 8704e604994aSStefano Zampini size_t len; 87051e0482f5SStefano Zampini 87069566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)coarse_mat), &pcbddc->coarse_ksp)); 87073821be0aSBarry Smith PetscCall(KSPSetNestLevel(pcbddc->coarse_ksp, pc->kspnestlevel)); 87089566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(pcbddc->coarse_ksp, pc->erroriffailure)); 87099566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp, (PetscObject)pc, 1)); 87109566063dSJacob Faibussowitsch PetscCall(KSPSetTolerances(pcbddc->coarse_ksp, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, 1)); 87119566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(pcbddc->coarse_ksp, coarse_mat, coarse_mat)); 87129566063dSJacob Faibussowitsch PetscCall(KSPSetType(pcbddc->coarse_ksp, coarse_ksp_type)); 87139566063dSJacob Faibussowitsch PetscCall(KSPSetNormType(pcbddc->coarse_ksp, KSP_NORM_NONE)); 87149566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &pc_temp)); 87151e0482f5SStefano Zampini /* TODO is this logic correct? should check for coarse_mat type */ 87169566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, coarse_pc_type)); 8717e604994aSStefano Zampini /* prefix */ 8718c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(prefix, "", sizeof(prefix))); 8719c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(str_level, "", sizeof(str_level))); 8720e604994aSStefano Zampini if (!pcbddc->current_level) { 87219566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(prefix, ((PetscObject)pc)->prefix, sizeof(prefix))); 87229566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, "pc_bddc_coarse_", sizeof(prefix))); 8723c8587f34SStefano Zampini } else { 87249566063dSJacob Faibussowitsch PetscCall(PetscStrlen(((PetscObject)pc)->prefix, &len)); 8725312be037SStefano Zampini if (pcbddc->current_level > 1) len -= 3; /* remove "lX_" with X level number */ 8726312be037SStefano Zampini if (pcbddc->current_level > 10) len -= 1; /* remove another char from level number */ 8727a126751eSBarry Smith /* Nonstandard use of PetscStrncpy() to copy only a portion of the string */ 87289566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(prefix, ((PetscObject)pc)->prefix, len + 1)); 8729f4f49eeaSPierre Jolivet PetscCall(PetscSNPrintf(str_level, sizeof(str_level), "l%d_", (int)pcbddc->current_level)); 87309566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, str_level, sizeof(prefix))); 8731e604994aSStefano Zampini } 87329566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(pcbddc->coarse_ksp, prefix)); 87333e3c6dadSStefano Zampini /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */ 87349566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLevel(pc_temp, pcbddc->current_level + 1)); 87359566063dSJacob Faibussowitsch PetscCall(PCBDDCSetCoarseningRatio(pc_temp, pcbddc->coarsening_ratio)); 87369566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLevels(pc_temp, pcbddc->max_levels)); 8737f9eb5b7dSStefano Zampini /* allow user customization */ 87389566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(pcbddc->coarse_ksp)); 8739e569e4e1SStefano Zampini /* get some info after set from options */ 87409566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &pc_temp)); 874128d58a37SPierre Jolivet /* multilevel cannot be done with coarse PC different from BDDC, NN, HPDDM, unless forced to */ 874228d58a37SPierre Jolivet force = PETSC_FALSE; 87439566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)pc_temp)->prefix, "-pc_type_forced", &force, NULL)); 87449566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)pc_temp, &valid, PCBDDC, PCNN, PCHPDDM, "")); 87459566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp, PCBDDC, &isbddc)); 874628d58a37SPierre Jolivet if (multilevel_allowed && !force && !valid) { 8747e569e4e1SStefano Zampini isbddc = PETSC_TRUE; 87489566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCBDDC)); 87499566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLevel(pc_temp, pcbddc->current_level + 1)); 87509566063dSJacob Faibussowitsch PetscCall(PCBDDCSetCoarseningRatio(pc_temp, pcbddc->coarsening_ratio)); 87519566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLevels(pc_temp, pcbddc->max_levels)); 87524f819b78SStefano Zampini if (pc_temp->ops->setfromoptions) { /* need to setfromoptions again, skipping the pc_type */ 8753d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)pc_temp); 8754dbbe0bcdSBarry Smith PetscCall((*pc_temp->ops->setfromoptions)(pc_temp, PetscOptionsObject)); 8755dbbe0bcdSBarry Smith PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)pc_temp, PetscOptionsObject)); 8756d0609cedSBarry Smith PetscOptionsEnd(); 87574f819b78SStefano Zampini pc_temp->setfromoptionscalled++; 87584f819b78SStefano Zampini } 8759e569e4e1SStefano Zampini } 87603e3c6dadSStefano Zampini } 87613e3c6dadSStefano Zampini /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */ 87629566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &pc_temp)); 87633e3c6dadSStefano Zampini if (nisdofs) { 87649566063dSJacob Faibussowitsch PetscCall(PCBDDCSetDofsSplitting(pc_temp, nisdofs, isarray)); 876548a46eb9SPierre Jolivet for (i = 0; i < nisdofs; i++) PetscCall(ISDestroy(&isarray[i])); 87663e3c6dadSStefano Zampini } 87673e3c6dadSStefano Zampini if (nisneu) { 87689566063dSJacob Faibussowitsch PetscCall(PCBDDCSetNeumannBoundaries(pc_temp, isarray[nisdofs])); 87699566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isarray[nisdofs])); 8770312be037SStefano Zampini } 877130368db7SStefano Zampini if (nisvert) { 87729566063dSJacob Faibussowitsch PetscCall(PCBDDCSetPrimalVerticesIS(pc_temp, isarray[nis - 1])); 87739566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isarray[nis - 1])); 877430368db7SStefano Zampini } 87751baa6e33SBarry Smith if (coarseG) PetscCall(PCBDDCSetDiscreteGradient(pc_temp, coarseG, 1, nedcfield, PETSC_FALSE, PETSC_TRUE)); 8776f9eb5b7dSStefano Zampini 8777f9eb5b7dSStefano Zampini /* get some info after set from options */ 87789566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp, PCBDDC, &isbddc)); 87794f819b78SStefano Zampini 8780b76f3995Sstefano_zampini /* multilevel can only be requested via -pc_bddc_levels or PCBDDCSetLevels */ 878148a46eb9SPierre Jolivet if (isbddc && !multilevel_allowed) PetscCall(PCSetType(pc_temp, coarse_pc_type)); 878228d58a37SPierre Jolivet /* multilevel cannot be done with coarse PC different from BDDC, NN, HPDDM, unless forced to */ 878328d58a37SPierre Jolivet force = PETSC_FALSE; 87849566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)pc_temp)->prefix, "-pc_type_forced", &force, NULL)); 87859566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)pc_temp, &valid, PCBDDC, PCNN, PCHPDDM, "")); 878648a46eb9SPierre Jolivet if (multilevel_requested && multilevel_allowed && !valid && !force) PetscCall(PCSetType(pc_temp, PCBDDC)); 87879566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp, PCREDUNDANT, &isredundant)); 87884f3a063dSStefano Zampini if (isredundant) { 87894f3a063dSStefano Zampini KSP inner_ksp; 87904f3a063dSStefano Zampini PC inner_pc; 87919326c5c6Sstefano_zampini 87929566063dSJacob Faibussowitsch PetscCall(PCRedundantGetKSP(pc_temp, &inner_ksp)); 87939566063dSJacob Faibussowitsch PetscCall(KSPGetPC(inner_ksp, &inner_pc)); 87944f3a063dSStefano Zampini } 8795f9eb5b7dSStefano Zampini 879657de7509SStefano Zampini /* parameters which miss an API */ 87979566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp, PCBDDC, &isbddc)); 879857de7509SStefano Zampini if (isbddc) { 8799720d30f9SStefano Zampini PC_BDDC *pcbddc_coarse = (PC_BDDC *)pc_temp->data; 88007274672aSStefano Zampini 8801720d30f9SStefano Zampini pcbddc_coarse->detect_disconnected = PETSC_TRUE; 880257de7509SStefano Zampini pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc; 8803e569e4e1SStefano Zampini pcbddc_coarse->coarse_eqs_limit = pcbddc->coarse_eqs_limit; 880427b6a85dSStefano Zampini pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null; 880527b6a85dSStefano Zampini if (pcbddc_coarse->benign_saddle_point) { 8806a198735bSStefano Zampini Mat coarsedivudotp_is; 8807a198735bSStefano Zampini ISLocalToGlobalMapping l2gmap, rl2g, cl2g; 8808a198735bSStefano Zampini IS row, col; 8809a198735bSStefano Zampini const PetscInt *gidxs; 8810a198735bSStefano Zampini PetscInt n, st, M, N; 8811a198735bSStefano Zampini 88129566063dSJacob Faibussowitsch PetscCall(MatGetSize(coarsedivudotp, &n, NULL)); 88139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Scan(&n, &st, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)coarse_mat))); 8814a198735bSStefano Zampini st = st - n; 88159566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)coarse_mat), 1, st, 1, &row)); 88169566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(coarse_mat, &l2gmap, NULL)); 88179566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(l2gmap, &n)); 88189566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(l2gmap, &gidxs)); 88199566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat), n, gidxs, PETSC_COPY_VALUES, &col)); 88209566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(l2gmap, &gidxs)); 88219566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(row, &rl2g)); 88229566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(col, &cl2g)); 88239566063dSJacob Faibussowitsch PetscCall(ISGetSize(row, &M)); 88249566063dSJacob Faibussowitsch PetscCall(MatGetSize(coarse_mat, &N, NULL)); 88259566063dSJacob Faibussowitsch PetscCall(ISDestroy(&row)); 88269566063dSJacob Faibussowitsch PetscCall(ISDestroy(&col)); 88279566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)coarse_mat), &coarsedivudotp_is)); 88289566063dSJacob Faibussowitsch PetscCall(MatSetType(coarsedivudotp_is, MATIS)); 88299566063dSJacob Faibussowitsch PetscCall(MatSetSizes(coarsedivudotp_is, PETSC_DECIDE, PETSC_DECIDE, M, N)); 88309566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(coarsedivudotp_is, rl2g, cl2g)); 88319566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 88329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 88339566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(coarsedivudotp_is, coarsedivudotp)); 88349566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarsedivudotp)); 88359566063dSJacob Faibussowitsch PetscCall(PCBDDCSetDivergenceMat(pc_temp, coarsedivudotp_is, PETSC_FALSE, NULL)); 88369566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarsedivudotp_is)); 8837720d30f9SStefano Zampini pcbddc_coarse->adaptive_userdefined = PETSC_TRUE; 8838bd2a564bSStefano Zampini if (pcbddc->adaptive_threshold[0] == 0.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE; 8839720d30f9SStefano Zampini } 8840d4d8cf7bSStefano Zampini } 88419881197aSStefano Zampini 88423301b35fSStefano Zampini /* propagate symmetry info of coarse matrix */ 88439566063dSJacob Faibussowitsch PetscCall(MatSetOption(coarse_mat, MAT_STRUCTURALLY_SYMMETRIC, PETSC_TRUE)); 8844b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(pc->pmat, &isset, &issym)); 8845b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(coarse_mat, MAT_SYMMETRIC, issym)); 8846b94d7dedSBarry Smith PetscCall(MatIsHermitianKnown(pc->pmat, &isset, &isher)); 8847b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(coarse_mat, MAT_HERMITIAN, isher)); 8848b94d7dedSBarry Smith PetscCall(MatIsSPDKnown(pc->pmat, &isset, &isspd)); 8849b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(coarse_mat, MAT_SPD, isspd)); 8850b94d7dedSBarry Smith 885148a46eb9SPierre Jolivet if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) PetscCall(MatSetOption(coarse_mat, MAT_SPD, PETSC_TRUE)); 88526e683305SStefano Zampini /* set operators */ 88539566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(coarse_mat, (PetscObject)pc, "-pc_bddc_coarse_mat_view")); 88549566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(coarse_mat, ((PetscObject)pcbddc->coarse_ksp)->prefix)); 88559566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(pcbddc->coarse_ksp, coarse_mat, coarse_mat)); 88561baa6e33SBarry Smith if (pcbddc->dbg_flag) PetscCall(PetscViewerASCIISubtractTab(dbg_viewer, 2 * pcbddc->current_level)); 88576e683305SStefano Zampini } 88589566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarseG)); 88599566063dSJacob Faibussowitsch PetscCall(PetscFree(isarray)); 8860b1ecc7b1SStefano Zampini #if 0 8861b9b85e73SStefano Zampini { 8862b9b85e73SStefano Zampini PetscViewer viewer; 8863b9b85e73SStefano Zampini char filename[256]; 8864a364092eSJacob Faibussowitsch PetscCall(PetscSNPrintf(filename, PETSC_STATIC_ARRAY_LENGTH(filename), "coarse_mat_level%d.m",pcbddc->current_level)); 88659566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer)); 88669566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB)); 88679566063dSJacob Faibussowitsch PetscCall(MatView(coarse_mat,viewer)); 88689566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 88699566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 8870b9b85e73SStefano Zampini } 8871b9b85e73SStefano Zampini #endif 8872f9eb5b7dSStefano Zampini 88734f819b78SStefano Zampini if (corners) { 88744f819b78SStefano Zampini Vec gv; 88754f819b78SStefano Zampini IS is; 88764f819b78SStefano Zampini const PetscInt *idxs; 88774f819b78SStefano Zampini PetscInt i, d, N, n, cdim = pcbddc->mat_graph->cdim; 88784f819b78SStefano Zampini PetscScalar *coords; 88794f819b78SStefano Zampini 888028b400f6SJacob Faibussowitsch PetscCheck(pcbddc->mat_graph->cloc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing local coordinates"); 88819566063dSJacob Faibussowitsch PetscCall(VecGetSize(pcbddc->coarse_vec, &N)); 88829566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(pcbddc->coarse_vec, &n)); 88839566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pcbddc->coarse_vec), &gv)); 88849566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(gv, cdim)); 88859566063dSJacob Faibussowitsch PetscCall(VecSetSizes(gv, n * cdim, N * cdim)); 88869566063dSJacob Faibussowitsch PetscCall(VecSetType(gv, VECSTANDARD)); 88879566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(gv)); 88889566063dSJacob Faibussowitsch PetscCall(VecSet(gv, PETSC_MAX_REAL)); /* we only propagate coordinates from vertices constraints */ 88894f819b78SStefano Zampini 88909566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &is)); 88919566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &n)); 88929566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, &idxs)); 88939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n * cdim, &coords)); 88944f819b78SStefano Zampini for (i = 0; i < n; i++) { 8895ad540459SPierre Jolivet for (d = 0; d < cdim; d++) coords[cdim * i + d] = pcbddc->mat_graph->coords[cdim * idxs[i] + d]; 88964f819b78SStefano Zampini } 88979566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, &idxs)); 88989566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &is)); 88994f819b78SStefano Zampini 89009566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(corners, &n)); 89019566063dSJacob Faibussowitsch PetscCall(ISGetIndices(corners, &idxs)); 89029566063dSJacob Faibussowitsch PetscCall(VecSetValuesBlocked(gv, n, idxs, coords, INSERT_VALUES)); 89039566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(corners, &idxs)); 89049566063dSJacob Faibussowitsch PetscCall(PetscFree(coords)); 89059566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(gv)); 89069566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(gv)); 89079566063dSJacob Faibussowitsch PetscCall(VecGetArray(gv, &coords)); 89084f819b78SStefano Zampini if (pcbddc->coarse_ksp) { 89094f819b78SStefano Zampini PC coarse_pc; 89104f819b78SStefano Zampini PetscBool isbddc; 89114f819b78SStefano Zampini 89129566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &coarse_pc)); 89139566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)coarse_pc, PCBDDC, &isbddc)); 89144f819b78SStefano Zampini if (isbddc) { /* coarse coordinates have PETSC_MAX_REAL, specific for BDDC */ 89154f819b78SStefano Zampini PetscReal *realcoords; 89164f819b78SStefano Zampini 89179566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(gv, &n)); 89184f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX) 89199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &realcoords)); 89204f819b78SStefano Zampini for (i = 0; i < n; i++) realcoords[i] = PetscRealPart(coords[i]); 89214f819b78SStefano Zampini #else 89224f819b78SStefano Zampini realcoords = coords; 89234f819b78SStefano Zampini #endif 89249566063dSJacob Faibussowitsch PetscCall(PCSetCoordinates(coarse_pc, cdim, n / cdim, realcoords)); 89254f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX) 89269566063dSJacob Faibussowitsch PetscCall(PetscFree(realcoords)); 89274f819b78SStefano Zampini #endif 89284f819b78SStefano Zampini } 89294f819b78SStefano Zampini } 89309566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(gv, &coords)); 89319566063dSJacob Faibussowitsch PetscCall(VecDestroy(&gv)); 89324f819b78SStefano Zampini } 89339566063dSJacob Faibussowitsch PetscCall(ISDestroy(&corners)); 89344f819b78SStefano Zampini 893598a51de6SStefano Zampini if (pcbddc->coarse_ksp) { 893698a51de6SStefano Zampini Vec crhs, csol; 893704708bb6SStefano Zampini 89389566063dSJacob Faibussowitsch PetscCall(KSPGetSolution(pcbddc->coarse_ksp, &csol)); 89399566063dSJacob Faibussowitsch PetscCall(KSPGetRhs(pcbddc->coarse_ksp, &crhs)); 8940f4f49eeaSPierre Jolivet if (!csol) PetscCall(MatCreateVecs(coarse_mat, &pcbddc->coarse_ksp->vec_sol, NULL)); 8941f4f49eeaSPierre Jolivet if (!crhs) PetscCall(MatCreateVecs(coarse_mat, NULL, &pcbddc->coarse_ksp->vec_rhs)); 8942b0f5fe93SStefano Zampini } 89439566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarsedivudotp)); 8944b0f5fe93SStefano Zampini 8945b0f5fe93SStefano Zampini /* compute null space for coarse solver if the benign trick has been requested */ 8946b0f5fe93SStefano Zampini if (pcbddc->benign_null) { 89479566063dSJacob Faibussowitsch PetscCall(VecSet(pcbddc->vec1_P, 0.)); 894848a46eb9SPierre 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)); 89499566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(pcbddc->vec1_P)); 89509566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(pcbddc->vec1_P)); 89519566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob, pcbddc->vec1_P, pcbddc->coarse_vec, INSERT_VALUES, SCATTER_FORWARD)); 89529566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob, pcbddc->vec1_P, pcbddc->coarse_vec, INSERT_VALUES, SCATTER_FORWARD)); 8953b0f5fe93SStefano Zampini if (coarse_mat) { 8954b0f5fe93SStefano Zampini Vec nullv; 8955b0f5fe93SStefano Zampini PetscScalar *array, *array2; 8956b0f5fe93SStefano Zampini PetscInt nl; 8957b0f5fe93SStefano Zampini 89589566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(coarse_mat, &nullv, NULL)); 89599566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(nullv, &nl)); 89609566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(pcbddc->coarse_vec, (const PetscScalar **)&array)); 89619566063dSJacob Faibussowitsch PetscCall(VecGetArray(nullv, &array2)); 89629566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(array2, array, nl)); 89639566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(nullv, &array2)); 89649566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(pcbddc->coarse_vec, (const PetscScalar **)&array)); 89659566063dSJacob Faibussowitsch PetscCall(VecNormalize(nullv, NULL)); 89669566063dSJacob Faibussowitsch PetscCall(MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat), PETSC_FALSE, 1, &nullv, &CoarseNullSpace)); 89679566063dSJacob Faibussowitsch PetscCall(VecDestroy(&nullv)); 8968b0f5fe93SStefano Zampini } 8969b0f5fe93SStefano Zampini } 89709566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_CoarseSetUp[pcbddc->current_level], pc, 0, 0, 0)); 8971b0f5fe93SStefano Zampini 89729566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_CoarseSolver[pcbddc->current_level], pc, 0, 0, 0)); 8973b0f5fe93SStefano Zampini if (pcbddc->coarse_ksp) { 8974b0f5fe93SStefano Zampini PetscBool ispreonly; 8975b0f5fe93SStefano Zampini 8976b0f5fe93SStefano Zampini if (CoarseNullSpace) { 8977b0f5fe93SStefano Zampini PetscBool isnull; 89787c625d9fSStefano Zampini 89799566063dSJacob Faibussowitsch PetscCall(MatNullSpaceTest(CoarseNullSpace, coarse_mat, &isnull)); 89801baa6e33SBarry Smith if (isnull) PetscCall(MatSetNullSpace(coarse_mat, CoarseNullSpace)); 8981bef83e63SStefano Zampini /* TODO: add local nullspaces (if any) */ 8982b0f5fe93SStefano Zampini } 8983b0f5fe93SStefano Zampini /* setup coarse ksp */ 89849566063dSJacob Faibussowitsch PetscCall(KSPSetUp(pcbddc->coarse_ksp)); 8985cbcc2c2aSStefano Zampini /* Check coarse problem if in debug mode or if solving with an iterative method */ 89869566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp, KSPPREONLY, &ispreonly)); 89876e683305SStefano Zampini if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates)) { 8988c8587f34SStefano Zampini KSP check_ksp; 89892b510759SStefano Zampini KSPType check_ksp_type; 8990c8587f34SStefano Zampini PC check_pc; 89916e683305SStefano Zampini Vec check_vec, coarse_vec; 89926a1308c2SStefano Zampini PetscReal abs_infty_error, infty_error, lambda_min = 1.0, lambda_max = 1.0; 89932b510759SStefano Zampini PetscInt its; 89946e683305SStefano Zampini PetscBool compute_eigs; 89956e683305SStefano Zampini PetscReal *eigs_r, *eigs_c; 89966e683305SStefano Zampini PetscInt neigs; 89978e185a42SStefano Zampini const char *prefix; 8998c8587f34SStefano Zampini 89992b510759SStefano Zampini /* Create ksp object suitable for estimation of extreme eigenvalues */ 90009566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp), &check_ksp)); 90013821be0aSBarry Smith PetscCall(KSPSetNestLevel(check_ksp, pc->kspnestlevel)); 90029566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)check_ksp, (PetscObject)pcbddc->coarse_ksp, 0)); 90039566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(pcbddc->coarse_ksp, PETSC_FALSE)); 90049566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(check_ksp, coarse_mat, coarse_mat)); 90059566063dSJacob Faibussowitsch PetscCall(KSPSetTolerances(check_ksp, 1.e-12, 1.e-12, PETSC_DEFAULT, pcbddc->coarse_size)); 9006e4d548c7SStefano Zampini /* prevent from setup unneeded object */ 90079566063dSJacob Faibussowitsch PetscCall(KSPGetPC(check_ksp, &check_pc)); 90089566063dSJacob Faibussowitsch PetscCall(PCSetType(check_pc, PCNONE)); 90092b510759SStefano Zampini if (ispreonly) { 90102b510759SStefano Zampini check_ksp_type = KSPPREONLY; 90116e683305SStefano Zampini compute_eigs = PETSC_FALSE; 90122b510759SStefano Zampini } else { 9013cbcc2c2aSStefano Zampini check_ksp_type = KSPGMRES; 90146e683305SStefano Zampini compute_eigs = PETSC_TRUE; 9015c8587f34SStefano Zampini } 90169566063dSJacob Faibussowitsch PetscCall(KSPSetType(check_ksp, check_ksp_type)); 90179566063dSJacob Faibussowitsch PetscCall(KSPSetComputeSingularValues(check_ksp, compute_eigs)); 90189566063dSJacob Faibussowitsch PetscCall(KSPSetComputeEigenvalues(check_ksp, compute_eigs)); 90199566063dSJacob Faibussowitsch PetscCall(KSPGMRESSetRestart(check_ksp, pcbddc->coarse_size + 1)); 90209566063dSJacob Faibussowitsch PetscCall(KSPGetOptionsPrefix(pcbddc->coarse_ksp, &prefix)); 90219566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(check_ksp, prefix)); 90229566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(check_ksp, "check_")); 90239566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(check_ksp)); 90249566063dSJacob Faibussowitsch PetscCall(KSPSetUp(check_ksp)); 90259566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &check_pc)); 90269566063dSJacob Faibussowitsch PetscCall(KSPSetPC(check_ksp, check_pc)); 9027c8587f34SStefano Zampini /* create random vec */ 90289566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(coarse_mat, &coarse_vec, &check_vec)); 90299566063dSJacob Faibussowitsch PetscCall(VecSetRandom(check_vec, NULL)); 90309566063dSJacob Faibussowitsch PetscCall(MatMult(coarse_mat, check_vec, coarse_vec)); 9031c8587f34SStefano Zampini /* solve coarse problem */ 90329566063dSJacob Faibussowitsch PetscCall(KSPSolve(check_ksp, coarse_vec, coarse_vec)); 90339566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(check_ksp, pc, coarse_vec)); 9034cbcc2c2aSStefano Zampini /* set eigenvalue estimation if preonly has not been requested */ 90356e683305SStefano Zampini if (compute_eigs) { 90369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->coarse_size + 1, &eigs_r)); 90379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->coarse_size + 1, &eigs_c)); 90389566063dSJacob Faibussowitsch PetscCall(KSPComputeEigenvalues(check_ksp, pcbddc->coarse_size + 1, eigs_r, eigs_c, &neigs)); 90391ae86dd6SStefano Zampini if (neigs) { 90406e683305SStefano Zampini lambda_max = eigs_r[neigs - 1]; 90416e683305SStefano Zampini lambda_min = eigs_r[0]; 90426e683305SStefano Zampini if (pcbddc->use_coarse_estimates) { 90432701bc32SStefano Zampini if (lambda_max >= lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */ 90449566063dSJacob Faibussowitsch PetscCall(KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp, lambda_max + PETSC_SMALL, lambda_min)); 90459566063dSJacob Faibussowitsch PetscCall(KSPRichardsonSetScale(pcbddc->coarse_ksp, 2.0 / (lambda_max + lambda_min))); 9046cbcc2c2aSStefano Zampini } 9047c8587f34SStefano Zampini } 9048c8587f34SStefano Zampini } 90491ae86dd6SStefano Zampini } 9050cbcc2c2aSStefano Zampini 9051c8587f34SStefano Zampini /* check coarse problem residual error */ 90526e683305SStefano Zampini if (pcbddc->dbg_flag) { 90536e683305SStefano Zampini PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp)); 90549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIAddTab(dbg_viewer, 2 * (pcbddc->current_level + 1))); 90559566063dSJacob Faibussowitsch PetscCall(VecAXPY(check_vec, -1.0, coarse_vec)); 90569566063dSJacob Faibussowitsch PetscCall(VecNorm(check_vec, NORM_INFINITY, &infty_error)); 90579566063dSJacob Faibussowitsch PetscCall(MatMult(coarse_mat, check_vec, coarse_vec)); 90589566063dSJacob Faibussowitsch PetscCall(VecNorm(coarse_vec, NORM_INFINITY, &abs_infty_error)); 90599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(dbg_viewer, "Coarse problem details (use estimates %d)\n", pcbddc->use_coarse_estimates)); 9060f4f49eeaSPierre Jolivet PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)pcbddc->coarse_ksp, dbg_viewer)); 90619566063dSJacob Faibussowitsch PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc), dbg_viewer)); 906263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(dbg_viewer, "Coarse problem exact infty_error : %1.6e\n", (double)infty_error)); 906363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(dbg_viewer, "Coarse problem residual infty_error: %1.6e\n", (double)abs_infty_error)); 906448a46eb9SPierre Jolivet if (CoarseNullSpace) PetscCall(PetscViewerASCIIPrintf(dbg_viewer, "Coarse problem is singular\n")); 90656e683305SStefano Zampini if (compute_eigs) { 90666e683305SStefano Zampini PetscReal lambda_max_s, lambda_min_s; 9067b03ebc13SStefano Zampini KSPConvergedReason reason; 90689566063dSJacob Faibussowitsch PetscCall(KSPGetType(check_ksp, &check_ksp_type)); 90699566063dSJacob Faibussowitsch PetscCall(KSPGetIterationNumber(check_ksp, &its)); 90709566063dSJacob Faibussowitsch PetscCall(KSPGetConvergedReason(check_ksp, &reason)); 90719566063dSJacob Faibussowitsch PetscCall(KSPComputeExtremeSingularValues(check_ksp, &lambda_max_s, &lambda_min_s)); 907263a3b9bcSJacob 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)); 907348a46eb9SPierre Jolivet for (i = 0; i < neigs; i++) PetscCall(PetscViewerASCIIPrintf(dbg_viewer, "%1.6e %1.6ei\n", (double)eigs_r[i], (double)eigs_c[i])); 90746e683305SStefano Zampini } 90759566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(dbg_viewer)); 90769566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISubtractTab(dbg_viewer, 2 * (pcbddc->current_level + 1))); 90776e683305SStefano Zampini } 90789566063dSJacob Faibussowitsch PetscCall(VecDestroy(&check_vec)); 90799566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coarse_vec)); 90809566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&check_ksp)); 90816e683305SStefano Zampini if (compute_eigs) { 90829566063dSJacob Faibussowitsch PetscCall(PetscFree(eigs_r)); 90839566063dSJacob Faibussowitsch PetscCall(PetscFree(eigs_c)); 9084c8587f34SStefano Zampini } 90856e683305SStefano Zampini } 90866e683305SStefano Zampini } 90879566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&CoarseNullSpace)); 9088cbcc2c2aSStefano Zampini /* print additional info */ 9089cbcc2c2aSStefano Zampini if (pcbddc->dbg_flag) { 90906e683305SStefano Zampini /* waits until all processes reaches this point */ 90919566063dSJacob Faibussowitsch PetscCall(PetscBarrier((PetscObject)pc)); 909263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Coarse solver setup completed at level %" PetscInt_FMT "\n", pcbddc->current_level)); 90939566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 9094cbcc2c2aSStefano Zampini } 9095cbcc2c2aSStefano Zampini 90962b510759SStefano Zampini /* free memory */ 90979566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_mat)); 90989566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_CoarseSolver[pcbddc->current_level], pc, 0, 0, 0)); 90993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9100c8587f34SStefano Zampini } 9101674ae819SStefano Zampini 9102d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCComputePrimalNumbering(PC pc, PetscInt *coarse_size_n, PetscInt **local_primal_indices_n) 9103d71ae5a4SJacob Faibussowitsch { 9104f34684f1SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 9105f34684f1SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 9106dc456d91SStefano Zampini IS subset, subset_mult, subset_n; 9107dc456d91SStefano Zampini PetscInt local_size, coarse_size = 0; 910873be2a3aSStefano Zampini PetscInt *local_primal_indices = NULL; 9109dc456d91SStefano Zampini const PetscInt *t_local_primal_indices; 9110f34684f1SStefano Zampini 9111f34684f1SStefano Zampini PetscFunctionBegin; 9112f34684f1SStefano Zampini /* Compute global number of coarse dofs */ 911308401ef6SPierre Jolivet PetscCheck(!pcbddc->local_primal_size || pcbddc->local_primal_ref_node, PETSC_COMM_SELF, PETSC_ERR_PLIB, "BDDC ConstraintsSetUp should be called first"); 9114f4f49eeaSPierre Jolivet PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc->pmat), pcbddc->local_primal_size_cc, pcbddc->local_primal_ref_node, PETSC_COPY_VALUES, &subset_n)); 91159566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(pcis->mapping, subset_n, &subset)); 91169566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subset_n)); 9117f4f49eeaSPierre Jolivet PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc->pmat), pcbddc->local_primal_size_cc, pcbddc->local_primal_ref_mult, PETSC_COPY_VALUES, &subset_mult)); 91189566063dSJacob Faibussowitsch PetscCall(ISRenumber(subset, subset_mult, &coarse_size, &subset_n)); 91199566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subset)); 91209566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subset_mult)); 91219566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(subset_n, &local_size)); 912263a3b9bcSJacob 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); 91239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(local_size, &local_primal_indices)); 91249566063dSJacob Faibussowitsch PetscCall(ISGetIndices(subset_n, &t_local_primal_indices)); 91259566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(local_primal_indices, t_local_primal_indices, local_size)); 91269566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(subset_n, &t_local_primal_indices)); 91279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subset_n)); 9128f34684f1SStefano Zampini 9129f34684f1SStefano Zampini if (pcbddc->dbg_flag) { 91309566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 91319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 91329de2952eSStefano Zampini PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Size of coarse problem is %" PetscInt_FMT "\n", coarse_size)); 91339566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 9134f34684f1SStefano Zampini } 91356080607fSStefano Zampini 9136f34684f1SStefano Zampini /* get back data */ 9137f34684f1SStefano Zampini *coarse_size_n = coarse_size; 9138f34684f1SStefano Zampini *local_primal_indices_n = local_primal_indices; 91393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9140674ae819SStefano Zampini } 9141674ae819SStefano Zampini 9142d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx, Vec gwork, Vec lwork, IS globalis, IS *localis) 9143d71ae5a4SJacob Faibussowitsch { 9144e456f2a8SStefano Zampini IS localis_t; 9145a7dc3881SStefano Zampini PetscInt i, lsize, *idxs, n; 9146e456f2a8SStefano Zampini PetscScalar *vals; 9147e456f2a8SStefano Zampini 9148e456f2a8SStefano Zampini PetscFunctionBegin; 9149a7dc3881SStefano Zampini /* get indices in local ordering exploiting local to global map */ 91509566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(globalis, &lsize)); 91519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(lsize, &vals)); 9152e456f2a8SStefano Zampini for (i = 0; i < lsize; i++) vals[i] = 1.0; 91539566063dSJacob Faibussowitsch PetscCall(ISGetIndices(globalis, (const PetscInt **)&idxs)); 91549566063dSJacob Faibussowitsch PetscCall(VecSet(gwork, 0.0)); 91559566063dSJacob Faibussowitsch PetscCall(VecSet(lwork, 0.0)); 91561035eff8SStefano Zampini if (idxs) { /* multilevel guard */ 91579566063dSJacob Faibussowitsch PetscCall(VecSetOption(gwork, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE)); 91589566063dSJacob Faibussowitsch PetscCall(VecSetValues(gwork, lsize, idxs, vals, INSERT_VALUES)); 91591035eff8SStefano Zampini } 91609566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(gwork)); 91619566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(globalis, (const PetscInt **)&idxs)); 91629566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 91639566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(gwork)); 9164a7dc3881SStefano Zampini /* now compute set in local ordering */ 91659566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(g2l_ctx, gwork, lwork, INSERT_VALUES, SCATTER_FORWARD)); 91669566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(g2l_ctx, gwork, lwork, INSERT_VALUES, SCATTER_FORWARD)); 91679566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(lwork, (const PetscScalar **)&vals)); 91689566063dSJacob Faibussowitsch PetscCall(VecGetSize(lwork, &n)); 9169a7dc3881SStefano Zampini for (i = 0, lsize = 0; i < n; i++) { 9170ad540459SPierre Jolivet if (PetscRealPart(vals[i]) > 0.5) lsize++; 9171e456f2a8SStefano Zampini } 91729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(lsize, &idxs)); 9173a7dc3881SStefano Zampini for (i = 0, lsize = 0; i < n; i++) { 9174ad540459SPierre Jolivet if (PetscRealPart(vals[i]) > 0.5) idxs[lsize++] = i; 9175e456f2a8SStefano Zampini } 91769566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(lwork, (const PetscScalar **)&vals)); 91779566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)gwork), lsize, idxs, PETSC_OWN_POINTER, &localis_t)); 9178e456f2a8SStefano Zampini *localis = localis_t; 91793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9180e456f2a8SStefano Zampini } 9181906d46d4SStefano Zampini 9182d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCComputeFakeChange(PC pc, PetscBool constraints, PCBDDCGraph graph, PCBDDCSubSchurs schurs, Mat *change, IS *change_primal, IS *change_primal_mult, PetscBool *change_with_qr) 9183d71ae5a4SJacob Faibussowitsch { 91847c625d9fSStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 91857c625d9fSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 91867c625d9fSStefano Zampini PC_IS *pcisf; 91877c625d9fSStefano Zampini PC_BDDC *pcbddcf; 91887c625d9fSStefano Zampini PC pcf; 91897c625d9fSStefano Zampini 91907c625d9fSStefano Zampini PetscFunctionBegin; 91917c625d9fSStefano Zampini PetscCall(PCCreate(PetscObjectComm((PetscObject)pc), &pcf)); 91927c625d9fSStefano Zampini PetscCall(PCSetOperators(pcf, pc->mat, pc->pmat)); 91937c625d9fSStefano Zampini PetscCall(PCSetType(pcf, PCBDDC)); 91947c625d9fSStefano Zampini 91957c625d9fSStefano Zampini pcisf = (PC_IS *)pcf->data; 919632fe681dSStefano Zampini pcbddcf = (PC_BDDC *)pcf->data; 919732fe681dSStefano Zampini 91987c625d9fSStefano Zampini pcisf->is_B_local = pcis->is_B_local; 91997c625d9fSStefano Zampini pcisf->vec1_N = pcis->vec1_N; 92007c625d9fSStefano Zampini pcisf->BtoNmap = pcis->BtoNmap; 92017c625d9fSStefano Zampini pcisf->n = pcis->n; 92027c625d9fSStefano Zampini pcisf->n_B = pcis->n_B; 92037c625d9fSStefano Zampini 92047c625d9fSStefano Zampini PetscCall(PetscFree(pcbddcf->mat_graph)); 920532fe681dSStefano Zampini PetscCall(PetscFree(pcbddcf->sub_schurs)); 92067c625d9fSStefano Zampini pcbddcf->mat_graph = graph ? graph : pcbddc->mat_graph; 920732fe681dSStefano Zampini pcbddcf->sub_schurs = schurs; 920832fe681dSStefano Zampini pcbddcf->adaptive_selection = schurs ? PETSC_TRUE : PETSC_FALSE; 920932fe681dSStefano Zampini pcbddcf->adaptive_threshold[0] = pcbddc->adaptive_threshold[0]; 921032fe681dSStefano Zampini pcbddcf->adaptive_threshold[1] = pcbddc->adaptive_threshold[1]; 921132fe681dSStefano Zampini pcbddcf->adaptive_nmin = pcbddc->adaptive_nmin; 921232fe681dSStefano Zampini pcbddcf->adaptive_nmax = pcbddc->adaptive_nmax; 92137c625d9fSStefano Zampini pcbddcf->use_faces = PETSC_TRUE; 921432fe681dSStefano Zampini pcbddcf->use_change_of_basis = (PetscBool)!constraints; 921532fe681dSStefano Zampini pcbddcf->use_change_on_faces = (PetscBool)!constraints; 921632fe681dSStefano Zampini pcbddcf->use_qr_single = (PetscBool)!constraints; 92177c625d9fSStefano Zampini pcbddcf->fake_change = PETSC_TRUE; 921832fe681dSStefano Zampini pcbddcf->dbg_flag = pcbddc->dbg_flag; 921932fe681dSStefano Zampini 922032fe681dSStefano Zampini PetscCall(PCBDDCAdaptiveSelection(pcf)); 92217c625d9fSStefano Zampini PetscCall(PCBDDCConstraintsSetUp(pcf)); 92227c625d9fSStefano Zampini 92237c625d9fSStefano Zampini *change = pcbddcf->ConstraintMatrix; 92247c625d9fSStefano 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)); 92257c625d9fSStefano 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)); 92267c625d9fSStefano Zampini if (change_with_qr) *change_with_qr = pcbddcf->use_qr_single; 92277c625d9fSStefano Zampini 922832fe681dSStefano Zampini if (schurs) pcbddcf->sub_schurs = NULL; 92297c625d9fSStefano Zampini pcbddcf->ConstraintMatrix = NULL; 923032fe681dSStefano Zampini pcbddcf->mat_graph = NULL; 923132fe681dSStefano Zampini pcisf->is_B_local = NULL; 923232fe681dSStefano Zampini pcisf->vec1_N = NULL; 923332fe681dSStefano Zampini pcisf->BtoNmap = NULL; 92347c625d9fSStefano Zampini PetscCall(PCDestroy(&pcf)); 92353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 92367c625d9fSStefano Zampini } 92377c625d9fSStefano Zampini 9238d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpSubSchurs(PC pc) 9239d71ae5a4SJacob Faibussowitsch { 9240a64f4aa4SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 9241b96c3477SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 9242b96c3477SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 9243a64f4aa4SStefano Zampini Mat S_j; 9244b96c3477SStefano Zampini PetscInt *used_xadj, *used_adjncy; 9245b96c3477SStefano Zampini PetscBool free_used_adj; 9246b96c3477SStefano Zampini 9247b96c3477SStefano Zampini PetscFunctionBegin; 92489566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Schurs[pcbddc->current_level], pc, 0, 0, 0)); 9249b96c3477SStefano Zampini /* decide the adjacency to be used for determining internal problems for local schur on subsets */ 9250b96c3477SStefano Zampini free_used_adj = PETSC_FALSE; 925108122e43SStefano Zampini if (pcbddc->sub_schurs_layers == -1) { 9252b96c3477SStefano Zampini used_xadj = NULL; 9253b96c3477SStefano Zampini used_adjncy = NULL; 9254b96c3477SStefano Zampini } else { 925508122e43SStefano Zampini if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) { 925608122e43SStefano Zampini used_xadj = pcbddc->mat_graph->xadj; 925708122e43SStefano Zampini used_adjncy = pcbddc->mat_graph->adjncy; 925808122e43SStefano Zampini } else if (pcbddc->computed_rowadj) { 9259b96c3477SStefano Zampini used_xadj = pcbddc->mat_graph->xadj; 9260b96c3477SStefano Zampini used_adjncy = pcbddc->mat_graph->adjncy; 9261b96c3477SStefano Zampini } else { 92622fffb893SStefano Zampini PetscBool flg_row = PETSC_FALSE; 9263b96c3477SStefano Zampini const PetscInt *xadj, *adjncy; 9264b96c3477SStefano Zampini PetscInt nvtxs; 9265b96c3477SStefano Zampini 92669566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(pcbddc->local_mat, 0, PETSC_TRUE, PETSC_FALSE, &nvtxs, &xadj, &adjncy, &flg_row)); 92672fffb893SStefano Zampini if (flg_row) { 92689566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nvtxs + 1, &used_xadj, xadj[nvtxs], &used_adjncy)); 92699566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(used_xadj, xadj, nvtxs + 1)); 92709566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(used_adjncy, adjncy, xadj[nvtxs])); 9271b96c3477SStefano Zampini free_used_adj = PETSC_TRUE; 92722fffb893SStefano Zampini } else { 92732fffb893SStefano Zampini pcbddc->sub_schurs_layers = -1; 92742fffb893SStefano Zampini used_xadj = NULL; 92752fffb893SStefano Zampini used_adjncy = NULL; 92762fffb893SStefano Zampini } 92779566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(pcbddc->local_mat, 0, PETSC_TRUE, PETSC_FALSE, &nvtxs, &xadj, &adjncy, &flg_row)); 9278b96c3477SStefano Zampini } 9279b96c3477SStefano Zampini } 9280d5574798SStefano Zampini 9281d5574798SStefano Zampini /* setup sub_schurs data */ 92829566063dSJacob Faibussowitsch PetscCall(MatCreateSchurComplement(pcis->A_II, pcis->pA_II, pcis->A_IB, pcis->A_BI, pcis->A_BB, &S_j)); 9283df4d28bfSStefano Zampini if (!sub_schurs->schur_explicit) { 9284df4d28bfSStefano Zampini /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */ 92859566063dSJacob Faibussowitsch PetscCall(MatSchurComplementSetKSP(S_j, pcbddc->ksp_D)); 92869566063dSJacob 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)); 9287a64f4aa4SStefano Zampini } else { 928872b8c272SStefano Zampini Mat change = NULL; 92899d54b7f4SStefano Zampini Vec scaling = NULL; 9290111315fdSstefano_zampini IS change_primal = NULL, iP; 9291111315fdSstefano_zampini PetscInt benign_n; 9292111315fdSstefano_zampini PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis; 92937ebab0bbSStefano Zampini PetscBool need_change = PETSC_FALSE; 9294111315fdSstefano_zampini PetscBool discrete_harmonic = PETSC_FALSE; 9295a3df083aSStefano Zampini 92965feab87aSStefano Zampini if (!pcbddc->use_vertices && reuse_solvers) { 92975feab87aSStefano Zampini PetscInt n_vertices; 92985feab87aSStefano Zampini 92999566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->is_vertices, &n_vertices)); 93002034aafcSStefano Zampini reuse_solvers = (PetscBool)!n_vertices; 93015feab87aSStefano Zampini } 9302a3df083aSStefano Zampini if (!pcbddc->benign_change_explicit) { 9303a3df083aSStefano Zampini benign_n = pcbddc->benign_n; 9304ca92afb2SStefano Zampini } else { 9305a3df083aSStefano Zampini benign_n = 0; 9306ca92afb2SStefano Zampini } 9307b7ab4a40SStefano Zampini /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc. 9308b7ab4a40SStefano Zampini We need a global reduction to avoid possible deadlocks. 9309b7ab4a40SStefano Zampini We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */ 931072b8c272SStefano Zampini if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) { 931122db5ddcSStefano Zampini PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change); 93121c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&have_loc_change, &need_change, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 931322db5ddcSStefano Zampini need_change = (PetscBool)(!need_change); 9314b7ab4a40SStefano Zampini } 93157c625d9fSStefano Zampini /* If the user defines additional constraints, we import them here */ 9316b7ab4a40SStefano Zampini if (need_change) { 931728b400f6SJacob Faibussowitsch PetscCheck(!pcbddc->sub_schurs_rebuild, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot compute change of basis with a different graph"); 931832fe681dSStefano Zampini PetscCall(PCBDDCComputeFakeChange(pc, PETSC_FALSE, NULL, NULL, &change, &change_primal, NULL, &sub_schurs->change_with_qr)); 931988c03ad3SStefano Zampini } 93209d54b7f4SStefano Zampini if (!pcbddc->use_deluxe_scaling) scaling = pcis->D; 9321111315fdSstefano_zampini 93229566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_iP", (PetscObject *)&iP)); 9323111315fdSstefano_zampini if (iP) { 9324d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)iP), sub_schurs->prefix, "BDDC sub_schurs options", "PC"); 93259566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-sub_schurs_discrete_harmonic", NULL, NULL, discrete_harmonic, &discrete_harmonic, NULL)); 9326d0609cedSBarry Smith PetscOptionsEnd(); 9327111315fdSstefano_zampini } 9328111315fdSstefano_zampini if (discrete_harmonic) { 9329111315fdSstefano_zampini Mat A; 93309566063dSJacob Faibussowitsch PetscCall(MatDuplicate(pcbddc->local_mat, MAT_COPY_VALUES, &A)); 93319566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumnsIS(A, iP, 1.0, NULL, NULL)); 93329566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A, "__KSPFETIDP_iP", (PetscObject)iP)); 93339371c9d4SSatish 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, 93349371c9d4SSatish Balay pcbddc->benign_zerodiag_subs, change, change_primal)); 93359566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 9336111315fdSstefano_zampini } else { 93379371c9d4SSatish 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, 93389371c9d4SSatish Balay pcbddc->benign_p0_lidx, pcbddc->benign_zerodiag_subs, change, change_primal)); 9339111315fdSstefano_zampini } 93409566063dSJacob Faibussowitsch PetscCall(MatDestroy(&change)); 93419566063dSJacob Faibussowitsch PetscCall(ISDestroy(&change_primal)); 9342ca92afb2SStefano Zampini } 93439566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_j)); 9344b96c3477SStefano Zampini 9345b96c3477SStefano Zampini /* free adjacency */ 93461baa6e33SBarry Smith if (free_used_adj) PetscCall(PetscFree2(used_xadj, used_adjncy)); 93479566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Schurs[pcbddc->current_level], pc, 0, 0, 0)); 93483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9349b96c3477SStefano Zampini } 9350b96c3477SStefano Zampini 9351d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCInitSubSchurs(PC pc) 9352d71ae5a4SJacob Faibussowitsch { 9353b96c3477SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 9354b96c3477SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 9355b96c3477SStefano Zampini PCBDDCGraph graph; 9356b96c3477SStefano Zampini 9357b96c3477SStefano Zampini PetscFunctionBegin; 9358b96c3477SStefano Zampini /* attach interface graph for determining subsets */ 935908122e43SStefano Zampini if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */ 93603301b35fSStefano Zampini IS verticesIS, verticescomm; 93613301b35fSStefano Zampini PetscInt vsize, *idxs; 9362b96c3477SStefano Zampini 93639566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &verticesIS)); 93649566063dSJacob Faibussowitsch PetscCall(ISGetSize(verticesIS, &vsize)); 93659566063dSJacob Faibussowitsch PetscCall(ISGetIndices(verticesIS, (const PetscInt **)&idxs)); 93669566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), vsize, idxs, PETSC_COPY_VALUES, &verticescomm)); 93679566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(verticesIS, (const PetscInt **)&idxs)); 93689566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &verticesIS)); 93699566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphCreate(&graph)); 93709566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphInit(graph, pcbddc->mat_graph->l2gmap, pcbddc->mat_graph->nvtxs_global, pcbddc->graphmaxcount)); 93719566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphSetUp(graph, pcbddc->mat_graph->custom_minimal_size, NULL, pcbddc->DirichletBoundariesLocal, 0, NULL, verticescomm)); 93729566063dSJacob Faibussowitsch PetscCall(ISDestroy(&verticescomm)); 93739566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphComputeConnectedComponents(graph)); 9374b96c3477SStefano Zampini } else { 9375b96c3477SStefano Zampini graph = pcbddc->mat_graph; 9376b96c3477SStefano Zampini } 9377e4d548c7SStefano Zampini /* print some info */ 93785c643e28SStefano Zampini if (pcbddc->dbg_flag && !pcbddc->sub_schurs_rebuild) { 9379e4d548c7SStefano Zampini IS vertices; 9380e4d548c7SStefano Zampini PetscInt nv, nedges, nfaces; 93819566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphASCIIView(graph, pcbddc->dbg_flag, pcbddc->dbg_viewer)); 93829566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(graph, &nfaces, NULL, &nedges, NULL, &vertices)); 93839566063dSJacob Faibussowitsch PetscCall(ISGetSize(vertices, &nv)); 93849566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 93859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "--------------------------------------------------------------\n")); 938663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate vertices (%d)\n", PetscGlobalRank, nv, pcbddc->use_vertices)); 938763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate edges (%d)\n", PetscGlobalRank, nedges, pcbddc->use_edges)); 938863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate faces (%d)\n", PetscGlobalRank, nfaces, pcbddc->use_faces)); 93899566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 93909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer)); 93919566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(graph, &nfaces, NULL, &nedges, NULL, &vertices)); 9392e4d548c7SStefano Zampini } 9393b96c3477SStefano Zampini 9394b96c3477SStefano Zampini /* sub_schurs init */ 939548a46eb9SPierre Jolivet if (!pcbddc->sub_schurs) PetscCall(PCBDDCSubSchursCreate(&pcbddc->sub_schurs)); 939632fe681dSStefano 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)); 9397a64f4aa4SStefano Zampini 9398b96c3477SStefano Zampini /* free graph struct */ 939948a46eb9SPierre Jolivet if (pcbddc->sub_schurs_rebuild) PetscCall(PCBDDCGraphDestroy(&graph)); 94003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9401b96c3477SStefano Zampini } 9402fa34dd3eSStefano Zampini 94039de2952eSStefano Zampini static PetscErrorCode PCBDDCViewGlobalIS(PC pc, IS is, PetscViewer viewer) 94049de2952eSStefano Zampini { 94059de2952eSStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 94069de2952eSStefano Zampini PetscInt n = pc->pmat->rmap->n, ln, ni, st; 94079de2952eSStefano Zampini const PetscInt *idxs; 94089de2952eSStefano Zampini IS gis; 94099de2952eSStefano Zampini 94109de2952eSStefano Zampini PetscFunctionBegin; 94119de2952eSStefano Zampini if (!is) PetscFunctionReturn(PETSC_SUCCESS); 94129de2952eSStefano Zampini PetscCall(MatGetOwnershipRange(pc->pmat, &st, NULL)); 94139de2952eSStefano Zampini PetscCall(MatGetLocalSize(matis->A, NULL, &ln)); 94149de2952eSStefano Zampini PetscCall(PetscArrayzero(matis->sf_leafdata, ln)); 94159de2952eSStefano Zampini PetscCall(PetscArrayzero(matis->sf_rootdata, n)); 94169de2952eSStefano Zampini PetscCall(ISGetLocalSize(is, &ni)); 94179de2952eSStefano Zampini PetscCall(ISGetIndices(is, &idxs)); 94189de2952eSStefano Zampini for (PetscInt i = 0; i < ni; i++) { 94199de2952eSStefano Zampini if (idxs[i] < 0 || idxs[i] >= ln) continue; 94209de2952eSStefano Zampini matis->sf_leafdata[idxs[i]] = 1; 94219de2952eSStefano Zampini } 94229de2952eSStefano Zampini PetscCall(ISRestoreIndices(is, &idxs)); 94239de2952eSStefano Zampini PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, matis->sf_leafdata, matis->sf_rootdata, MPI_SUM)); 94249de2952eSStefano Zampini PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, matis->sf_leafdata, matis->sf_rootdata, MPI_SUM)); 94259de2952eSStefano Zampini ln = 0; 94269de2952eSStefano Zampini for (PetscInt i = 0; i < n; i++) { 94279de2952eSStefano Zampini if (matis->sf_rootdata[i]) matis->sf_rootdata[ln++] = i + st; 94289de2952eSStefano Zampini } 94299de2952eSStefano Zampini PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), ln, matis->sf_rootdata, PETSC_USE_POINTER, &gis)); 94309de2952eSStefano Zampini PetscCall(ISView(gis, viewer)); 94319de2952eSStefano Zampini PetscCall(ISDestroy(&gis)); 94329de2952eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 94339de2952eSStefano Zampini } 94349de2952eSStefano Zampini 94359de2952eSStefano Zampini PetscErrorCode PCBDDCLoadOrViewCustomization(PC pc, PetscBool load, const char *outfile) 94369de2952eSStefano Zampini { 94379de2952eSStefano Zampini PetscInt header[11]; 94389de2952eSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 94399de2952eSStefano Zampini PetscViewer viewer; 94409de2952eSStefano Zampini MPI_Comm comm = PetscObjectComm((PetscObject)pc); 94419de2952eSStefano Zampini 94429de2952eSStefano Zampini PetscFunctionBegin; 94439de2952eSStefano Zampini PetscCall(PetscViewerBinaryOpen(comm, outfile ? outfile : "bddc_dump.dat", load ? FILE_MODE_READ : FILE_MODE_WRITE, &viewer)); 94449de2952eSStefano Zampini if (load) { 94459de2952eSStefano Zampini IS is; 94469de2952eSStefano Zampini Mat A; 94479de2952eSStefano Zampini 94489de2952eSStefano Zampini PetscCall(PetscViewerBinaryRead(viewer, header, PETSC_STATIC_ARRAY_LENGTH(header), NULL, PETSC_INT)); 94499de2952eSStefano Zampini PetscCheck(header[0] == 0 || header[0] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 94509de2952eSStefano Zampini PetscCheck(header[1] == 0 || header[1] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 94519de2952eSStefano Zampini PetscCheck(header[2] >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 94529de2952eSStefano Zampini PetscCheck(header[3] == 0 || header[3] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 94539de2952eSStefano Zampini PetscCheck(header[4] == 0 || header[4] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 94549de2952eSStefano Zampini PetscCheck(header[5] >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 94559de2952eSStefano Zampini PetscCheck(header[7] == 0 || header[7] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 94569de2952eSStefano Zampini PetscCheck(header[8] == 0 || header[8] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 94579de2952eSStefano Zampini PetscCheck(header[9] == 0 || header[9] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 94589de2952eSStefano Zampini PetscCheck(header[10] == 0 || header[10] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 94599de2952eSStefano Zampini if (header[0]) { 94609de2952eSStefano Zampini PetscCall(ISCreate(comm, &is)); 94619de2952eSStefano Zampini PetscCall(ISLoad(is, viewer)); 94629de2952eSStefano Zampini PetscCall(PCBDDCSetDirichletBoundaries(pc, is)); 94639de2952eSStefano Zampini PetscCall(ISDestroy(&is)); 94649de2952eSStefano Zampini } 94659de2952eSStefano Zampini if (header[1]) { 94669de2952eSStefano Zampini PetscCall(ISCreate(comm, &is)); 94679de2952eSStefano Zampini PetscCall(ISLoad(is, viewer)); 94689de2952eSStefano Zampini PetscCall(PCBDDCSetNeumannBoundaries(pc, is)); 94699de2952eSStefano Zampini PetscCall(ISDestroy(&is)); 94709de2952eSStefano Zampini } 94719de2952eSStefano Zampini if (header[2]) { 94729de2952eSStefano Zampini IS *isarray; 94739de2952eSStefano Zampini 94749de2952eSStefano Zampini PetscCall(PetscMalloc1(header[2], &isarray)); 94759de2952eSStefano Zampini for (PetscInt i = 0; i < header[2]; i++) { 94769de2952eSStefano Zampini PetscCall(ISCreate(comm, &isarray[i])); 94779de2952eSStefano Zampini PetscCall(ISLoad(isarray[i], viewer)); 94789de2952eSStefano Zampini } 94799de2952eSStefano Zampini PetscCall(PCBDDCSetDofsSplitting(pc, header[2], isarray)); 94809de2952eSStefano Zampini for (PetscInt i = 0; i < header[2]; i++) PetscCall(ISDestroy(&isarray[i])); 94819de2952eSStefano Zampini PetscCall(PetscFree(isarray)); 94829de2952eSStefano Zampini } 94839de2952eSStefano Zampini if (header[3]) { 94849de2952eSStefano Zampini PetscCall(ISCreate(comm, &is)); 94859de2952eSStefano Zampini PetscCall(ISLoad(is, viewer)); 94869de2952eSStefano Zampini PetscCall(PCBDDCSetPrimalVerticesIS(pc, is)); 94879de2952eSStefano Zampini PetscCall(ISDestroy(&is)); 94889de2952eSStefano Zampini } 94899de2952eSStefano Zampini if (header[4]) { 94909de2952eSStefano Zampini PetscCall(MatCreate(comm, &A)); 94919de2952eSStefano Zampini PetscCall(MatSetType(A, MATAIJ)); 94929de2952eSStefano Zampini PetscCall(MatLoad(A, viewer)); 94939de2952eSStefano Zampini PetscCall(PCBDDCSetDiscreteGradient(pc, A, header[5], header[6], (PetscBool)header[7], (PetscBool)header[8])); 94949de2952eSStefano Zampini PetscCall(MatDestroy(&A)); 94959de2952eSStefano Zampini } 94969de2952eSStefano Zampini if (header[9]) { 94979de2952eSStefano Zampini PetscCall(MatCreate(comm, &A)); 94989de2952eSStefano Zampini PetscCall(MatSetType(A, MATIS)); 94999de2952eSStefano Zampini PetscCall(MatLoad(A, viewer)); 95009de2952eSStefano Zampini PetscCall(PCBDDCSetDivergenceMat(pc, A, (PetscBool)header[10], NULL)); 95019de2952eSStefano Zampini PetscCall(MatDestroy(&A)); 95029de2952eSStefano Zampini } 95039de2952eSStefano Zampini } else { 95049de2952eSStefano Zampini header[0] = (PetscInt) !!pcbddc->DirichletBoundariesLocal; 95059de2952eSStefano Zampini header[1] = (PetscInt) !!pcbddc->NeumannBoundariesLocal; 95069de2952eSStefano Zampini header[2] = pcbddc->n_ISForDofsLocal; 95079de2952eSStefano Zampini header[3] = (PetscInt) !!pcbddc->user_primal_vertices_local; 95089de2952eSStefano Zampini header[4] = (PetscInt) !!pcbddc->discretegradient; 95099de2952eSStefano Zampini header[5] = pcbddc->nedorder; 95109de2952eSStefano Zampini header[6] = pcbddc->nedfield; 95119de2952eSStefano Zampini header[7] = (PetscInt)pcbddc->nedglobal; 95129de2952eSStefano Zampini header[8] = (PetscInt)pcbddc->conforming; 95139de2952eSStefano Zampini header[9] = (PetscInt) !!pcbddc->divudotp; 95149de2952eSStefano Zampini header[10] = (PetscInt)pcbddc->divudotp_trans; 95159de2952eSStefano Zampini if (header[4]) header[3] = 0; 95169de2952eSStefano Zampini 95179de2952eSStefano Zampini PetscCall(PetscViewerBinaryWrite(viewer, header, PETSC_STATIC_ARRAY_LENGTH(header), PETSC_INT)); 95189de2952eSStefano Zampini PetscCall(PCBDDCViewGlobalIS(pc, pcbddc->DirichletBoundariesLocal, viewer)); 95199de2952eSStefano Zampini PetscCall(PCBDDCViewGlobalIS(pc, pcbddc->NeumannBoundariesLocal, viewer)); 95209de2952eSStefano Zampini for (PetscInt i = 0; i < header[2]; i++) PetscCall(PCBDDCViewGlobalIS(pc, pcbddc->ISForDofsLocal[i], viewer)); 95219de2952eSStefano Zampini if (header[3]) PetscCall(PCBDDCViewGlobalIS(pc, pcbddc->user_primal_vertices_local, viewer)); 95229de2952eSStefano Zampini if (header[4]) PetscCall(MatView(pcbddc->discretegradient, viewer)); 95239de2952eSStefano Zampini if (header[9]) PetscCall(MatView(pcbddc->divudotp, viewer)); 95249de2952eSStefano Zampini } 95259de2952eSStefano Zampini PetscCall(PetscViewerDestroy(&viewer)); 95269de2952eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 95279de2952eSStefano Zampini } 95289de2952eSStefano Zampini 95291e0482f5SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h> 9530ba38deedSJacob Faibussowitsch static PetscErrorCode MatMPIAIJRestrict(Mat A, MPI_Comm ccomm, Mat *B) 9531d71ae5a4SJacob Faibussowitsch { 95321e0482f5SStefano Zampini Mat At; 95331e0482f5SStefano Zampini IS rows; 95341e0482f5SStefano Zampini PetscInt rst, ren; 95351e0482f5SStefano Zampini PetscLayout rmap; 95361e0482f5SStefano Zampini 95371e0482f5SStefano Zampini PetscFunctionBegin; 95381e0482f5SStefano Zampini rst = ren = 0; 95391e0482f5SStefano Zampini if (ccomm != MPI_COMM_NULL) { 95409566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(ccomm, &rmap)); 95419566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetSize(rmap, A->rmap->N)); 95429566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(rmap, 1)); 95439566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rmap)); 95449566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rmap, &rst, &ren)); 95451e0482f5SStefano Zampini } 95469566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), ren - rst, rst, 1, &rows)); 95479566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, rows, NULL, MAT_INITIAL_MATRIX, &At)); 95489566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rows)); 95491e0482f5SStefano Zampini 95501e0482f5SStefano Zampini if (ccomm != MPI_COMM_NULL) { 95511e0482f5SStefano Zampini Mat_MPIAIJ *a, *b; 95521e0482f5SStefano Zampini IS from, to; 95531e0482f5SStefano Zampini Vec gvec; 95541e0482f5SStefano Zampini PetscInt lsize; 95551e0482f5SStefano Zampini 95569566063dSJacob Faibussowitsch PetscCall(MatCreate(ccomm, B)); 95579566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B, ren - rst, PETSC_DECIDE, PETSC_DECIDE, At->cmap->N)); 95589566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, MATAIJ)); 95599566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&((*B)->rmap))); 95609566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp((*B)->cmap)); 95611e0482f5SStefano Zampini a = (Mat_MPIAIJ *)At->data; 95621e0482f5SStefano Zampini b = (Mat_MPIAIJ *)(*B)->data; 95639566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(ccomm, &b->size)); 95649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(ccomm, &b->rank)); 95659566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)a->A)); 95669566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)a->B)); 95671e0482f5SStefano Zampini b->A = a->A; 95681e0482f5SStefano Zampini b->B = a->B; 95691e0482f5SStefano Zampini 95701e0482f5SStefano Zampini b->donotstash = a->donotstash; 95711e0482f5SStefano Zampini b->roworiented = a->roworiented; 95720a545947SLisandro Dalcin b->rowindices = NULL; 95730a545947SLisandro Dalcin b->rowvalues = NULL; 95741e0482f5SStefano Zampini b->getrowactive = PETSC_FALSE; 95751e0482f5SStefano Zampini 95761e0482f5SStefano Zampini (*B)->rmap = rmap; 95771e0482f5SStefano Zampini (*B)->factortype = A->factortype; 95781e0482f5SStefano Zampini (*B)->assembled = PETSC_TRUE; 95791e0482f5SStefano Zampini (*B)->insertmode = NOT_SET_VALUES; 95801e0482f5SStefano Zampini (*B)->preallocated = PETSC_TRUE; 95811e0482f5SStefano Zampini 95821e0482f5SStefano Zampini if (a->colmap) { 95831e0482f5SStefano Zampini #if defined(PETSC_USE_CTABLE) 9584eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIDuplicate(a->colmap, &b->colmap)); 95851e0482f5SStefano Zampini #else 95869566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(At->cmap->N, &b->colmap)); 95879566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(b->colmap, a->colmap, At->cmap->N)); 95881e0482f5SStefano Zampini #endif 95890a545947SLisandro Dalcin } else b->colmap = NULL; 95901e0482f5SStefano Zampini if (a->garray) { 95911e0482f5SStefano Zampini PetscInt len; 95921e0482f5SStefano Zampini len = a->B->cmap->n; 95939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(len + 1, &b->garray)); 95949566063dSJacob Faibussowitsch if (len) PetscCall(PetscArraycpy(b->garray, a->garray, len)); 95950a545947SLisandro Dalcin } else b->garray = NULL; 95961e0482f5SStefano Zampini 95979566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)a->lvec)); 95981e0482f5SStefano Zampini b->lvec = a->lvec; 95991e0482f5SStefano Zampini 96001e0482f5SStefano Zampini /* cannot use VecScatterCopy */ 96019566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(b->lvec, &lsize)); 96029566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(ccomm, lsize, b->garray, PETSC_USE_POINTER, &from)); 96039566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, lsize, 0, 1, &to)); 96049566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(*B, &gvec, NULL)); 96059566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(gvec, from, b->lvec, to, &b->Mvctx)); 96069566063dSJacob Faibussowitsch PetscCall(ISDestroy(&from)); 96079566063dSJacob Faibussowitsch PetscCall(ISDestroy(&to)); 96089566063dSJacob Faibussowitsch PetscCall(VecDestroy(&gvec)); 96091e0482f5SStefano Zampini } 96109566063dSJacob Faibussowitsch PetscCall(MatDestroy(&At)); 96113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 96121e0482f5SStefano Zampini } 96139de2952eSStefano Zampini 96149de2952eSStefano Zampini /* same as MatCreateSubMatrix(A, rows, NULL,...) but allows repeated rows */ 96159de2952eSStefano Zampini static PetscErrorCode MatAIJExtractRows(Mat A, IS rows, Mat *sA) 96169de2952eSStefano Zampini { 96179de2952eSStefano Zampini PetscBool isaij; 96189de2952eSStefano Zampini MPI_Comm comm; 96199de2952eSStefano Zampini 96209de2952eSStefano Zampini PetscFunctionBegin; 96219de2952eSStefano Zampini PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 96229de2952eSStefano Zampini PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)A, &isaij, MATSEQAIJ, MATMPIAIJ, "")); 96239de2952eSStefano Zampini PetscCheck(isaij, comm, PETSC_ERR_SUP, "Not implemented"); 96249de2952eSStefano Zampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isaij)); 96259de2952eSStefano Zampini if (isaij) { /* SeqAIJ supports repeated rows */ 96269de2952eSStefano Zampini PetscCall(MatCreateSubMatrix(A, rows, NULL, MAT_INITIAL_MATRIX, sA)); 96279de2952eSStefano Zampini } else { 96289de2952eSStefano Zampini Mat A_loc; 96299de2952eSStefano Zampini Mat_SeqAIJ *da; 96309de2952eSStefano Zampini PetscSF sf; 96319de2952eSStefano Zampini PetscInt ni, *di, *dj, m = A->rmap->n, c, *ldata, *rdata; 96329de2952eSStefano Zampini PetscScalar *daa; 96339de2952eSStefano Zampini const PetscInt *idxs; 96349de2952eSStefano Zampini const PetscSFNode *iremotes; 96359de2952eSStefano Zampini PetscSFNode *remotes; 96369de2952eSStefano Zampini 96379de2952eSStefano Zampini /* SF for incoming rows */ 96389de2952eSStefano Zampini PetscCall(PetscSFCreate(comm, &sf)); 96399de2952eSStefano Zampini PetscCall(ISGetLocalSize(rows, &ni)); 96409de2952eSStefano Zampini PetscCall(ISGetIndices(rows, &idxs)); 96419de2952eSStefano Zampini PetscCall(PetscSFSetGraphLayout(sf, A->rmap, ni, NULL, PETSC_USE_POINTER, idxs)); 96429de2952eSStefano Zampini PetscCall(ISRestoreIndices(rows, &idxs)); 96439de2952eSStefano Zampini 96449de2952eSStefano Zampini PetscCall(MatMPIAIJGetLocalMat(A, MAT_INITIAL_MATRIX, &A_loc)); 96459de2952eSStefano Zampini da = (Mat_SeqAIJ *)A_loc->data; 96469de2952eSStefano Zampini PetscCall(PetscMalloc2(2 * ni, &ldata, 2 * m, &rdata)); 96479de2952eSStefano Zampini for (PetscInt i = 0; i < m; i++) { 96489de2952eSStefano Zampini rdata[2 * i + 0] = da->i[i + 1] - da->i[i]; 96499de2952eSStefano Zampini rdata[2 * i + 1] = da->i[i]; 96509de2952eSStefano Zampini } 96519de2952eSStefano Zampini PetscCall(PetscSFBcastBegin(sf, MPIU_2INT, rdata, ldata, MPI_REPLACE)); 96529de2952eSStefano Zampini PetscCall(PetscSFBcastEnd(sf, MPIU_2INT, rdata, ldata, MPI_REPLACE)); 96539de2952eSStefano Zampini PetscCall(PetscMalloc1(ni + 1, &di)); 96549de2952eSStefano Zampini di[0] = 0; 96559de2952eSStefano Zampini for (PetscInt i = 0; i < ni; i++) di[i + 1] = di[i] + ldata[2 * i + 0]; 96569de2952eSStefano Zampini PetscCall(PetscMalloc1(di[ni], &dj)); 96579de2952eSStefano Zampini PetscCall(PetscMalloc1(di[ni], &daa)); 96589de2952eSStefano Zampini PetscCall(PetscMalloc1(di[ni], &remotes)); 96599de2952eSStefano Zampini 96609de2952eSStefano Zampini PetscCall(PetscSFGetGraph(sf, NULL, NULL, NULL, &iremotes)); 96619de2952eSStefano Zampini 96629de2952eSStefano Zampini /* SF graph for nonzeros */ 96639de2952eSStefano Zampini c = 0; 96649de2952eSStefano Zampini for (PetscInt i = 0; i < ni; i++) { 96659de2952eSStefano Zampini const PetscInt rank = iremotes[i].rank; 96669de2952eSStefano Zampini const PetscInt rsize = ldata[2 * i]; 96679de2952eSStefano Zampini for (PetscInt j = 0; j < rsize; j++) { 96689de2952eSStefano Zampini remotes[c].rank = rank; 96699de2952eSStefano Zampini remotes[c].index = ldata[2 * i + 1] + j; 96709de2952eSStefano Zampini c++; 96719de2952eSStefano Zampini } 96729de2952eSStefano Zampini } 96739de2952eSStefano Zampini PetscCheck(c == di[ni], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of local nonzeros %" PetscInt_FMT " != %" PetscInt_FMT, c, di[ni]); 96749de2952eSStefano Zampini PetscCall(PetscSFSetGraph(sf, da->i[m], di[ni], NULL, PETSC_USE_POINTER, remotes, PETSC_USE_POINTER)); 96759de2952eSStefano Zampini PetscCall(PetscSFBcastBegin(sf, MPIU_INT, da->j, dj, MPI_REPLACE)); 96769de2952eSStefano Zampini PetscCall(PetscSFBcastEnd(sf, MPIU_INT, da->j, dj, MPI_REPLACE)); 96779de2952eSStefano Zampini PetscCall(PetscSFBcastBegin(sf, MPIU_SCALAR, da->a, daa, MPI_REPLACE)); 96789de2952eSStefano Zampini PetscCall(PetscSFBcastEnd(sf, MPIU_SCALAR, da->a, daa, MPI_REPLACE)); 96799de2952eSStefano Zampini 96809de2952eSStefano Zampini PetscCall(MatCreateMPIAIJWithArrays(comm, ni, A->cmap->n, PETSC_DECIDE, A->cmap->N, di, dj, daa, sA)); 96819de2952eSStefano Zampini PetscCall(MatDestroy(&A_loc)); 96829de2952eSStefano Zampini PetscCall(PetscSFDestroy(&sf)); 96839de2952eSStefano Zampini PetscCall(PetscFree(di)); 96849de2952eSStefano Zampini PetscCall(PetscFree(dj)); 96859de2952eSStefano Zampini PetscCall(PetscFree(daa)); 96869de2952eSStefano Zampini PetscCall(PetscFree(remotes)); 96879de2952eSStefano Zampini PetscCall(PetscFree2(ldata, rdata)); 96889de2952eSStefano Zampini } 96899de2952eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 96909de2952eSStefano Zampini } 9691