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()); 60835f2295SStefano Zampini PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in GESVD Lapack routine %" PetscBLASInt_FMT, 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; 1610b61a303SStefano Zampini IS lned, primals, allprimals, nedfieldlocal, elements_corners = NULL; 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; 1740b61a303SStefano Zampini PetscBool print, eerr, done, lrc[2], conforming, global, 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; 186a13144ffSStefano Zampini 187213b8bfaSStefano Zampini /* Command line customization */ 188d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)pc), ((PetscObject)pc)->prefix, "BDDC Nedelec options", "PC"); 1899566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_nedelec_field_primal", "All edge dofs set as primals: Toselli's algorithm C", NULL, setprimal, &setprimal, NULL)); 1900b61a303SStefano Zampini /* print debug info and adaptive order TODO: to be removed */ 1919566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_nedelec_order", "Test variable order code (to be removed)", NULL, order, &order, NULL)); 1929566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_nedelec_print", "Print debug info", NULL, print, &print, NULL)); 193d0609cedSBarry Smith PetscOptionsEnd(); 194213b8bfaSStefano Zampini 1950b61a303SStefano Zampini /* Return if there are no edges in the decomposition */ 1969566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(pc->pmat, &al2g, NULL)); 1979566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(al2g, &n)); 1989566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)pc, &comm)); 1999566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(matis->counter, (const PetscScalar **)&vals)); 200a13144ffSStefano Zampini lrc[0] = PETSC_FALSE; 201c2151214SStefano Zampini for (i = 0; i < n; i++) { 202a13144ffSStefano Zampini if (PetscRealPart(vals[i]) > 2.) { 203a13144ffSStefano Zampini lrc[0] = PETSC_TRUE; 204a13144ffSStefano Zampini break; 205a13144ffSStefano Zampini } 206a13144ffSStefano Zampini } 2079566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(matis->counter, (const PetscScalar **)&vals)); 208462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&lrc[0], &lrc[1], 1, MPIU_BOOL, MPI_LOR, comm)); 2093ba16761SJacob Faibussowitsch if (!lrc[1]) PetscFunctionReturn(PETSC_SUCCESS); 210a13144ffSStefano Zampini 211213b8bfaSStefano Zampini /* Get Nedelec field */ 21263a3b9bcSJacob 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); 213213b8bfaSStefano Zampini if (pcbddc->n_ISForDofsLocal && field >= 0) { 2149566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->ISForDofsLocal[field])); 215c2151214SStefano Zampini nedfieldlocal = pcbddc->ISForDofsLocal[field]; 2169566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(nedfieldlocal, &ne)); 217213b8bfaSStefano Zampini } else if (!pcbddc->n_ISForDofsLocal && field != PETSC_DECIDE) { 218213b8bfaSStefano Zampini ne = n; 219213b8bfaSStefano Zampini nedfieldlocal = NULL; 220213b8bfaSStefano Zampini global = PETSC_TRUE; 221213b8bfaSStefano Zampini } else if (field == PETSC_DECIDE) { 222213b8bfaSStefano Zampini PetscInt rst, ren, *idx; 223213b8bfaSStefano Zampini 2249566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_leafdata, n)); 2259566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_rootdata, pc->pmat->rmap->n)); 2269566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(pcbddc->discretegradient, &rst, &ren)); 227213b8bfaSStefano Zampini for (i = rst; i < ren; i++) { 228213b8bfaSStefano Zampini PetscInt nc; 229213b8bfaSStefano Zampini 2309566063dSJacob Faibussowitsch PetscCall(MatGetRow(pcbddc->discretegradient, i, &nc, NULL, NULL)); 231213b8bfaSStefano Zampini if (nc > 1) matis->sf_rootdata[i - rst] = 1; 2329566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(pcbddc->discretegradient, i, &nc, NULL, NULL)); 233213b8bfaSStefano Zampini } 2349566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 2359566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 2369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &idx)); 2379371c9d4SSatish Balay for (i = 0, ne = 0; i < n; i++) 2389371c9d4SSatish Balay if (matis->sf_leafdata[i]) idx[ne++] = i; 2399566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, ne, idx, PETSC_OWN_POINTER, &nedfieldlocal)); 240213b8bfaSStefano Zampini } else { 241213b8bfaSStefano Zampini SETERRQ(comm, PETSC_ERR_USER, "When multiple fields are present, the Nedelec field has to be specified"); 242213b8bfaSStefano Zampini } 243213b8bfaSStefano Zampini 244213b8bfaSStefano Zampini /* Sanity checks */ 2457827d75bSBarry Smith PetscCheck(order || conforming, comm, PETSC_ERR_SUP, "Variable order and non-conforming spaces are not supported at the same time"); 24628b400f6SJacob Faibussowitsch PetscCheck(!pcbddc->user_ChangeOfBasisMatrix, comm, PETSC_ERR_SUP, "Cannot generate Nedelec support with user defined change of basis"); 24763a3b9bcSJacob 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); 248213b8bfaSStefano Zampini 249213b8bfaSStefano Zampini /* Just set primal dofs and return */ 2501e0482f5SStefano Zampini if (setprimal) { 251eee23b56SStefano Zampini IS enedfieldlocal; 252eee23b56SStefano Zampini PetscInt *eidxs; 253eee23b56SStefano Zampini 2549566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ne, &eidxs)); 2559566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(matis->counter, (const PetscScalar **)&vals)); 256213b8bfaSStefano Zampini if (nedfieldlocal) { 2579566063dSJacob Faibussowitsch PetscCall(ISGetIndices(nedfieldlocal, &idxs)); 258eee23b56SStefano Zampini for (i = 0, cum = 0; i < ne; i++) { 259ad540459SPierre Jolivet if (PetscRealPart(vals[idxs[i]]) > 2.) eidxs[cum++] = idxs[i]; 260eee23b56SStefano Zampini } 2619566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(nedfieldlocal, &idxs)); 262213b8bfaSStefano Zampini } else { 263213b8bfaSStefano Zampini for (i = 0, cum = 0; i < ne; i++) { 264ad540459SPierre Jolivet if (PetscRealPart(vals[i]) > 2.) eidxs[cum++] = i; 265213b8bfaSStefano Zampini } 266213b8bfaSStefano Zampini } 2679566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(matis->counter, (const PetscScalar **)&vals)); 2689566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, cum, eidxs, PETSC_COPY_VALUES, &enedfieldlocal)); 2699566063dSJacob Faibussowitsch PetscCall(PCBDDCSetPrimalVerticesLocalIS(pc, enedfieldlocal)); 2709566063dSJacob Faibussowitsch PetscCall(PetscFree(eidxs)); 2719566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nedfieldlocal)); 2729566063dSJacob Faibussowitsch PetscCall(ISDestroy(&enedfieldlocal)); 2733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2741e0482f5SStefano Zampini } 275a13144ffSStefano Zampini 276213b8bfaSStefano Zampini /* Compute some l2g maps */ 277213b8bfaSStefano Zampini if (nedfieldlocal) { 278c2151214SStefano Zampini IS is; 279c2151214SStefano Zampini 280c2151214SStefano Zampini /* need to map from the local Nedelec field to local numbering */ 2819566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(nedfieldlocal, &fl2g)); 2821e0482f5SStefano Zampini /* need to map from the local Nedelec field to global numbering for the whole dofs*/ 2839566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(al2g, nedfieldlocal, &is)); 2849566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &al2g)); 2851e0482f5SStefano Zampini /* need to map from the local Nedelec field to global numbering (for Nedelec only) */ 2861e0482f5SStefano Zampini if (global) { 2879566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)al2g)); 2881e0482f5SStefano Zampini el2g = al2g; 2891e0482f5SStefano Zampini } else { 2901e0482f5SStefano Zampini IS gis; 2911e0482f5SStefano Zampini 2929566063dSJacob Faibussowitsch PetscCall(ISRenumber(is, NULL, NULL, &gis)); 2939566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(gis, &el2g)); 2949566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gis)); 2951e0482f5SStefano Zampini } 2969566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 297c2151214SStefano Zampini } else { 2981e0482f5SStefano Zampini /* one ref for the destruction of al2g, one for el2g */ 2999566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)al2g)); 3009566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)al2g)); 3011e0482f5SStefano Zampini el2g = al2g; 302c2151214SStefano Zampini fl2g = NULL; 303c2151214SStefano Zampini } 304a13144ffSStefano Zampini 305213b8bfaSStefano Zampini /* Start communication to drop connections for interior edges (for cc analysis only) */ 3069566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_leafdata, n)); 3079566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_rootdata, pc->pmat->rmap->n)); 308c2151214SStefano Zampini if (nedfieldlocal) { 3099566063dSJacob Faibussowitsch PetscCall(ISGetIndices(nedfieldlocal, &idxs)); 310c2151214SStefano Zampini for (i = 0; i < ne; i++) matis->sf_leafdata[idxs[i]] = 1; 3119566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(nedfieldlocal, &idxs)); 312c2151214SStefano Zampini } else { 313c2151214SStefano Zampini for (i = 0; i < ne; i++) matis->sf_leafdata[i] = 1; 314c2151214SStefano Zampini } 3159566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, matis->sf_leafdata, matis->sf_rootdata, MPI_SUM)); 3169566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, matis->sf_leafdata, matis->sf_rootdata, MPI_SUM)); 317213b8bfaSStefano Zampini 3180b61a303SStefano Zampini /* There's no way to detect all possible corner candidates in a element-by-element case in a pure algebraic setting 3190b61a303SStefano Zampini Firedrake attaches a index set to identify them upfront. If it is present, we assume we are in such a case */ 3200b61a303SStefano Zampini if (matis->allow_repeated) PetscCall(PetscObjectQuery((PetscObject)pcbddc->discretegradient, "_elements_corners", (PetscObject *)&elements_corners)); 3210b61a303SStefano Zampini 3220b61a303SStefano Zampini /* drop connections with interior edges to avoid unneeded communications and memory movements */ 3230b61a303SStefano Zampini PetscCall(MatViewFromOptions(pcbddc->discretegradient, (PetscObject)pc, "-pc_bddc_discrete_gradient_view")); 3249566063dSJacob Faibussowitsch PetscCall(MatDuplicate(pcbddc->discretegradient, MAT_COPY_VALUES, &G)); 3259566063dSJacob Faibussowitsch PetscCall(MatSetOption(G, MAT_KEEP_NONZERO_PATTERN, PETSC_FALSE)); 3261e0482f5SStefano Zampini if (global) { 3271e0482f5SStefano Zampini PetscInt rst; 3281e0482f5SStefano Zampini 3299566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(G, &rst, NULL)); 330c2151214SStefano Zampini for (i = 0, cum = 0; i < pc->pmat->rmap->n; i++) { 331ad540459SPierre Jolivet if (matis->sf_rootdata[i] < 2) matis->sf_rootdata[cum++] = i + rst; 332c2151214SStefano Zampini } 3339566063dSJacob Faibussowitsch PetscCall(MatSetOption(G, MAT_NO_OFF_PROC_ZERO_ROWS, PETSC_TRUE)); 3349566063dSJacob Faibussowitsch PetscCall(MatZeroRows(G, cum, matis->sf_rootdata, 0., NULL, NULL)); 3351e0482f5SStefano Zampini } else { 3361e0482f5SStefano Zampini PetscInt *tbz; 3371e0482f5SStefano Zampini 3389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ne, &tbz)); 3399566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 3409566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 3419566063dSJacob Faibussowitsch PetscCall(ISGetIndices(nedfieldlocal, &idxs)); 3421e0482f5SStefano Zampini for (i = 0, cum = 0; i < ne; i++) 3439371c9d4SSatish Balay if (matis->sf_leafdata[idxs[i]] == 1) tbz[cum++] = i; 3449566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(nedfieldlocal, &idxs)); 3459566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(el2g, cum, tbz, tbz)); 3469566063dSJacob Faibussowitsch PetscCall(MatZeroRows(G, cum, tbz, 0., NULL, NULL)); 3479566063dSJacob Faibussowitsch PetscCall(PetscFree(tbz)); 3481e0482f5SStefano Zampini } 349a13144ffSStefano Zampini 350a13144ffSStefano Zampini /* Extract subdomain relevant rows of G */ 3519566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(el2g, &idxs)); 3529566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, ne, idxs, PETSC_USE_POINTER, &lned)); 3539de2952eSStefano Zampini PetscCall(MatAIJExtractRows(G, lned, &lGall)); 3549de2952eSStefano Zampini /* PetscCall(MatCreateSubMatrix(G, lned, NULL, MAT_INITIAL_MATRIX, &lGall)); */ 3559566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(el2g, &idxs)); 3569566063dSJacob Faibussowitsch PetscCall(ISDestroy(&lned)); 3579566063dSJacob Faibussowitsch PetscCall(MatConvert(lGall, MATIS, MAT_INITIAL_MATRIX, &lGis)); 3589566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGall)); 3599566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(lGis, &lG)); 3609de2952eSStefano Zampini if (matis->allow_repeated) { /* multi-element support */ 3619de2952eSStefano Zampini Mat *lGn, B; 3629de2952eSStefano Zampini IS *is_rows, *tcols, tmap, nmap; 3639de2952eSStefano Zampini PetscInt subnv; 3649de2952eSStefano Zampini const PetscInt *subvidxs; 3659de2952eSStefano Zampini ISLocalToGlobalMapping mapn; 3669de2952eSStefano Zampini 3679de2952eSStefano Zampini PetscCall(PetscCalloc1(pcbddc->n_local_subs * pcbddc->n_local_subs, &lGn)); 3689de2952eSStefano Zampini PetscCall(PetscMalloc1(pcbddc->n_local_subs, &is_rows)); 3699de2952eSStefano Zampini PetscCall(PetscMalloc1(pcbddc->n_local_subs, &tcols)); 3709de2952eSStefano Zampini for (PetscInt i = 0; i < pcbddc->n_local_subs; i++) { 3719de2952eSStefano Zampini if (fl2g) { 3729de2952eSStefano Zampini PetscCall(ISGlobalToLocalMappingApplyIS(fl2g, IS_GTOLM_MASK, pcbddc->local_subs[i], &is_rows[i])); 3739de2952eSStefano Zampini } else { 3749de2952eSStefano Zampini PetscCall(PetscObjectReference((PetscObject)pcbddc->local_subs[i])); 3759de2952eSStefano Zampini is_rows[i] = pcbddc->local_subs[i]; 3769de2952eSStefano Zampini } 3779de2952eSStefano Zampini PetscCall(MatCreateSubMatrix(lG, is_rows[i], NULL, MAT_INITIAL_MATRIX, &lGn[i * (1 + pcbddc->n_local_subs)])); 3789de2952eSStefano Zampini PetscCall(MatSeqAIJCompactOutExtraColumns_SeqAIJ(lGn[i * (1 + pcbddc->n_local_subs)], &mapn)); 3799de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingGetSize(mapn, &subnv)); 3809de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingGetIndices(mapn, &subvidxs)); 3819de2952eSStefano Zampini PetscCall(ISCreateGeneral(PETSC_COMM_SELF, subnv, subvidxs, PETSC_COPY_VALUES, &tcols[i])); 3829de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingRestoreIndices(mapn, &subvidxs)); 3839de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingDestroy(&mapn)); 3849de2952eSStefano Zampini } 3859de2952eSStefano Zampini 3869de2952eSStefano Zampini /* Create new MATIS with repeated vertices */ 3879de2952eSStefano Zampini PetscCall(MatCreate(comm, &B)); 3889de2952eSStefano Zampini PetscCall(MatSetSizes(B, lGis->rmap->n, lGis->cmap->n, lGis->rmap->N, lGis->cmap->N)); 3899de2952eSStefano Zampini PetscCall(MatSetType(B, MATIS)); 3909de2952eSStefano Zampini PetscCall(MatISSetAllowRepeated(B, PETSC_TRUE)); 3919de2952eSStefano Zampini PetscCall(ISConcatenate(PETSC_COMM_SELF, pcbddc->n_local_subs, tcols, &tmap)); 3929de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingApplyIS(lGis->cmap->mapping, tmap, &nmap)); 3939de2952eSStefano Zampini PetscCall(ISDestroy(&tmap)); 3949de2952eSStefano Zampini PetscCall(ISGetLocalSize(nmap, &subnv)); 3959de2952eSStefano Zampini PetscCall(ISGetIndices(nmap, &subvidxs)); 3969de2952eSStefano Zampini PetscCall(ISCreateGeneral(comm, subnv, subvidxs, PETSC_USE_POINTER, &tmap)); 3979de2952eSStefano Zampini PetscCall(ISRestoreIndices(nmap, &subvidxs)); 3989de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingCreateIS(tmap, &mapn)); 3999de2952eSStefano Zampini PetscCall(ISDestroy(&tmap)); 4009de2952eSStefano Zampini PetscCall(ISDestroy(&nmap)); 4019de2952eSStefano Zampini PetscCall(MatSetLocalToGlobalMapping(B, lGis->rmap->mapping, mapn)); 4029de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingDestroy(&mapn)); 4039de2952eSStefano Zampini PetscCall(MatCreateNest(PETSC_COMM_SELF, pcbddc->n_local_subs, is_rows, pcbddc->n_local_subs, NULL, lGn, &lG)); 4049de2952eSStefano Zampini for (PetscInt i = 0; i < pcbddc->n_local_subs; i++) { 4059de2952eSStefano Zampini PetscCall(MatDestroy(&lGn[i * (1 + pcbddc->n_local_subs)])); 4069de2952eSStefano Zampini PetscCall(ISDestroy(&is_rows[i])); 4079de2952eSStefano Zampini PetscCall(ISDestroy(&tcols[i])); 4089de2952eSStefano Zampini } 4099de2952eSStefano Zampini PetscCall(MatConvert(lG, MATSEQAIJ, MAT_INPLACE_MATRIX, &lG)); 4109de2952eSStefano Zampini PetscCall(PetscFree(lGn)); 4119de2952eSStefano Zampini PetscCall(PetscFree(is_rows)); 4129de2952eSStefano Zampini PetscCall(PetscFree(tcols)); 4139de2952eSStefano Zampini PetscCall(MatISSetLocalMat(B, lG)); 4149de2952eSStefano Zampini PetscCall(MatDestroy(&lG)); 4159de2952eSStefano Zampini 4169de2952eSStefano Zampini PetscCall(MatDestroy(&lGis)); 4179de2952eSStefano Zampini lGis = B; 4180b61a303SStefano Zampini 4190b61a303SStefano Zampini lGis->assembled = PETSC_TRUE; 4209de2952eSStefano Zampini } 4210b61a303SStefano Zampini PetscCall(MatViewFromOptions(lGis, (PetscObject)pc, "-pc_bddc_nedelec_init_G_view")); 4229de2952eSStefano Zampini 423213b8bfaSStefano Zampini /* SF for nodal dofs communications */ 4249566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(G, NULL, &Lv)); 4259566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(lGis, NULL, &vl2g)); 4269566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)vl2g)); 4279566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(vl2g, &nv)); 4289566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &sfv)); 4299566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(vl2g, &idxs)); 4309566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(sfv, lGis->cmap, nv, NULL, PETSC_OWN_POINTER, idxs)); 4319566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(vl2g, &idxs)); 432a13144ffSStefano Zampini 4330b61a303SStefano Zampini if (elements_corners) { 4340b61a303SStefano Zampini IS tmp; 4350b61a303SStefano Zampini Vec global, local; 4360b61a303SStefano Zampini Mat_IS *tGis = (Mat_IS *)lGis->data; 4370b61a303SStefano Zampini 4380b61a303SStefano Zampini PetscCall(MatCreateVecs(lGis, &global, NULL)); 4390b61a303SStefano Zampini PetscCall(MatCreateVecs(tGis->A, &local, NULL)); 4400b61a303SStefano Zampini PetscCall(PCBDDCGlobalToLocal(tGis->cctx, global, local, elements_corners, &tmp)); 4410b61a303SStefano Zampini PetscCall(VecDestroy(&global)); 4420b61a303SStefano Zampini PetscCall(VecDestroy(&local)); 4430b61a303SStefano Zampini elements_corners = tmp; 4440b61a303SStefano Zampini } 4450b61a303SStefano Zampini 4460b61a303SStefano Zampini /* Destroy temporary G */ 4479de2952eSStefano Zampini PetscCall(MatISGetLocalMat(lGis, &lG)); 4489566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)lG)); 4499566063dSJacob Faibussowitsch PetscCall(MatDestroy(&G)); 4500b61a303SStefano Zampini PetscCall(MatDestroy(&lGis)); 451a13144ffSStefano Zampini 452213b8bfaSStefano Zampini if (print) { 4539566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)lG, "initial_lG")); 4549566063dSJacob Faibussowitsch PetscCall(MatView(lG, NULL)); 455213b8bfaSStefano Zampini } 456213b8bfaSStefano Zampini 457213b8bfaSStefano Zampini /* Save lG for values insertion in change of basis */ 4589566063dSJacob Faibussowitsch PetscCall(MatDuplicate(lG, MAT_COPY_VALUES, &lGinit)); 4590569b399SStefano Zampini 460a13144ffSStefano Zampini /* Analyze the edge-nodes connections (duplicate lG) */ 4619566063dSJacob Faibussowitsch PetscCall(MatDuplicate(lG, MAT_COPY_VALUES, &lGe)); 4629566063dSJacob Faibussowitsch PetscCall(MatSetOption(lGe, MAT_KEEP_NONZERO_PATTERN, PETSC_FALSE)); 4639566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(nv, &btv)); 4649566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(ne, &bte)); 4659566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(ne, &btb)); 4669566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(ne, &btbd)); 467a13144ffSStefano Zampini /* need to import the boundary specification to ensure the 468a13144ffSStefano Zampini proper detection of coarse edges' endpoints */ 469a13144ffSStefano Zampini if (pcbddc->DirichletBoundariesLocal) { 470c2151214SStefano Zampini IS is; 471c2151214SStefano Zampini 472c2151214SStefano Zampini if (fl2g) { 4739566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(fl2g, IS_GTOLM_MASK, pcbddc->DirichletBoundariesLocal, &is)); 474c2151214SStefano Zampini } else { 475c2151214SStefano Zampini is = pcbddc->DirichletBoundariesLocal; 476c2151214SStefano Zampini } 4779566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &cum)); 4789566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, &idxs)); 479a13144ffSStefano Zampini for (i = 0; i < cum; i++) { 4809de2952eSStefano Zampini if (idxs[i] >= 0 && idxs[i] < ne) { 4819566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btb, idxs[i])); 4829566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btbd, idxs[i])); 483a13144ffSStefano Zampini } 484a13144ffSStefano Zampini } 4859566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, &idxs)); 48648a46eb9SPierre Jolivet if (fl2g) PetscCall(ISDestroy(&is)); 487a13144ffSStefano Zampini } 488a13144ffSStefano Zampini if (pcbddc->NeumannBoundariesLocal) { 489c2151214SStefano Zampini IS is; 490c2151214SStefano Zampini 491c2151214SStefano Zampini if (fl2g) { 4929566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(fl2g, IS_GTOLM_MASK, pcbddc->NeumannBoundariesLocal, &is)); 493c2151214SStefano Zampini } else { 494c2151214SStefano Zampini is = pcbddc->NeumannBoundariesLocal; 495c2151214SStefano Zampini } 4969566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &cum)); 4979566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, &idxs)); 498a13144ffSStefano Zampini for (i = 0; i < cum; i++) { 4999de2952eSStefano Zampini if (idxs[i] >= 0 && idxs[i] < ne) PetscCall(PetscBTSet(btb, idxs[i])); 500a13144ffSStefano Zampini } 5019566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, &idxs)); 50248a46eb9SPierre Jolivet if (fl2g) PetscCall(ISDestroy(&is)); 503c2151214SStefano Zampini } 504c2151214SStefano Zampini 505213b8bfaSStefano Zampini /* Count neighs per dof */ 5069de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingGetNodeInfo(el2g, NULL, &ecount, NULL)); 5079de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingGetNodeInfo(vl2g, NULL, &vcount, NULL)); 508637e8532SStefano Zampini 5097d871cd7SStefano Zampini /* need to remove coarse faces' dofs and coarse edges' dirichlet dofs 5107d871cd7SStefano Zampini for proper detection of coarse edges' endpoints */ 5119566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(ne, &btee)); 51262b0c6f7SStefano Zampini for (i = 0; i < ne; i++) { 51348a46eb9SPierre Jolivet if ((ecount[i] > 2 && !PetscBTLookup(btbd, i)) || (ecount[i] == 2 && PetscBTLookup(btb, i))) PetscCall(PetscBTSet(btee, i)); 51462b0c6f7SStefano Zampini } 5159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ne, &marks)); 51662b0c6f7SStefano Zampini if (!conforming) { 5179566063dSJacob Faibussowitsch PetscCall(MatTranspose(lGe, MAT_INITIAL_MATRIX, &lGt)); 5189566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 51962b0c6f7SStefano Zampini } 5209566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGe, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 5219566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(lGe, &vals)); 52262b0c6f7SStefano Zampini cum = 0; 523a13144ffSStefano Zampini for (i = 0; i < ne; i++) { 524dec27d64SStefano Zampini /* eliminate rows corresponding to edge dofs belonging to coarse faces */ 52562b0c6f7SStefano Zampini if (!PetscBTLookup(btee, i)) { 526a13144ffSStefano Zampini marks[cum++] = i; 527dec27d64SStefano Zampini continue; 528dec27d64SStefano Zampini } 529dec27d64SStefano Zampini /* set badly connected edge dofs as primal */ 53062b0c6f7SStefano Zampini if (!conforming) { 53162b0c6f7SStefano Zampini if (ii[i + 1] - ii[i] != order + 1) { /* every row of G on the coarse edge should list order+1 nodal dofs */ 532a13144ffSStefano Zampini marks[cum++] = i; 5339566063dSJacob Faibussowitsch PetscCall(PetscBTSet(bte, i)); 53448a46eb9SPierre Jolivet for (j = ii[i]; j < ii[i + 1]; j++) PetscCall(PetscBTSet(btv, jj[j])); 53562b0c6f7SStefano Zampini } else { 536aaa8cc7dSPierre Jolivet /* every edge dofs should be connected through a certain number of nodal dofs 53762b0c6f7SStefano Zampini to other edge dofs belonging to coarse edges 53862b0c6f7SStefano Zampini - at most 2 endpoints 53962b0c6f7SStefano Zampini - order-1 interior nodal dofs 54062b0c6f7SStefano Zampini - no undefined nodal dofs (nconn < order) 54162b0c6f7SStefano Zampini */ 54262b0c6f7SStefano Zampini PetscInt ends = 0, ints = 0, undef = 0; 54362b0c6f7SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 54462b0c6f7SStefano Zampini PetscInt v = jj[j], k; 54562b0c6f7SStefano Zampini PetscInt nconn = iit[v + 1] - iit[v]; 5469371c9d4SSatish Balay for (k = iit[v]; k < iit[v + 1]; k++) 5479371c9d4SSatish Balay if (!PetscBTLookup(btee, jjt[k])) nconn--; 54862b0c6f7SStefano Zampini if (nconn > order) ends++; 54962b0c6f7SStefano Zampini else if (nconn == order) ints++; 55062b0c6f7SStefano Zampini else undef++; 55162b0c6f7SStefano Zampini } 55262b0c6f7SStefano Zampini if (undef || ends > 2 || ints != order - 1) { 55362b0c6f7SStefano Zampini marks[cum++] = i; 5549566063dSJacob Faibussowitsch PetscCall(PetscBTSet(bte, i)); 55548a46eb9SPierre Jolivet for (j = ii[i]; j < ii[i + 1]; j++) PetscCall(PetscBTSet(btv, jj[j])); 55662b0c6f7SStefano Zampini } 55762b0c6f7SStefano Zampini } 558a13144ffSStefano Zampini } 559dec27d64SStefano Zampini /* We assume the order on the element edge is ii[i+1]-ii[i]-1 */ 560dec27d64SStefano Zampini if (!order && ii[i + 1] != ii[i]) { 561dec27d64SStefano Zampini PetscScalar val = 1. / (ii[i + 1] - ii[i] - 1); 562dec27d64SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) vals[j] = val; 563a13144ffSStefano Zampini } 564dec27d64SStefano Zampini } 5659566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btee)); 5669566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(lGe, &vals)); 5679566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGe, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 56862b0c6f7SStefano Zampini if (!conforming) { 5699566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 5709566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGt)); 57162b0c6f7SStefano Zampini } 5729566063dSJacob Faibussowitsch PetscCall(MatZeroRows(lGe, cum, marks, 0., NULL, NULL)); 573637e8532SStefano Zampini 5740b61a303SStefano Zampini /* identify splitpoints and corner candidates */ 5750b61a303SStefano Zampini PetscCall(PetscMalloc2(nv, &sfvleaves, Lv, &sfvroots)); 5760b61a303SStefano Zampini PetscCall(PetscBTCreate(nv, &btvcand)); 5770b61a303SStefano Zampini if (elements_corners) { 5780b61a303SStefano Zampini PetscCall(ISGetLocalSize(elements_corners, &cum)); 5790b61a303SStefano Zampini PetscCall(ISGetIndices(elements_corners, &idxs)); 5800b61a303SStefano Zampini for (i = 0; i < cum; i++) PetscCall(PetscBTSet(btvcand, idxs[i])); 5810b61a303SStefano Zampini PetscCall(ISRestoreIndices(elements_corners, &idxs)); 5820b61a303SStefano Zampini } 5830b61a303SStefano Zampini 5849de2952eSStefano Zampini if (matis->allow_repeated) { /* assign a uniq global id to edge local subsets and communicate it with nodal space */ 5859de2952eSStefano Zampini PetscSF emlsf, vmlsf; 5869de2952eSStefano Zampini PetscInt *eleaves, *vleaves, *meleaves, *mvleaves; 5879de2952eSStefano Zampini PetscInt cum_subs = 0, n_subs = pcbddc->n_local_subs, bs, emnr, emnl, vmnr, vmnl; 5889de2952eSStefano Zampini 5899de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockSize(el2g, &bs)); 5909de2952eSStefano Zampini PetscCheck(bs == 1, comm, PETSC_ERR_SUP, "Not coded"); 5919de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockSize(vl2g, &bs)); 5929de2952eSStefano Zampini PetscCheck(bs == 1, comm, PETSC_ERR_SUP, "Not coded"); 5939de2952eSStefano Zampini 5949de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockMultiLeavesSF(el2g, &emlsf)); 5959de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockMultiLeavesSF(vl2g, &vmlsf)); 5969de2952eSStefano Zampini 5979de2952eSStefano Zampini PetscCall(PetscSFGetGraph(emlsf, &emnr, &emnl, NULL, NULL)); 5989de2952eSStefano Zampini for (i = 0, j = 0; i < ne; i++) j += ecount[i]; 5999de2952eSStefano 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); 6009de2952eSStefano 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); 6019de2952eSStefano Zampini 6029de2952eSStefano Zampini PetscCall(PetscSFGetGraph(vmlsf, &vmnr, &vmnl, NULL, NULL)); 6039de2952eSStefano Zampini for (i = 0, j = 0; i < nv; i++) j += vcount[i]; 6049de2952eSStefano 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); 6059de2952eSStefano 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); 6069de2952eSStefano Zampini 6079de2952eSStefano Zampini PetscCall(PetscMalloc1(ne, &eleaves)); 6089de2952eSStefano Zampini PetscCall(PetscMalloc1(nv, &vleaves)); 6091690c2aeSBarry Smith for (i = 0; i < ne; i++) eleaves[i] = PETSC_INT_MAX; 6101690c2aeSBarry Smith for (i = 0; i < nv; i++) vleaves[i] = PETSC_INT_MAX; 6119de2952eSStefano Zampini PetscCall(PetscMalloc1(emnl, &meleaves)); 6129de2952eSStefano Zampini PetscCall(PetscMalloc1(vmnl, &mvleaves)); 6139de2952eSStefano Zampini 6149de2952eSStefano Zampini PetscCallMPI(MPI_Exscan(&n_subs, &cum_subs, 1, MPIU_INT, MPI_SUM, comm)); 6150b61a303SStefano Zampini PetscCall(MatGetRowIJ(lGinit, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 6169de2952eSStefano Zampini for (i = 0; i < n_subs; i++) { 6179de2952eSStefano Zampini const PetscInt *idxs; 6189de2952eSStefano Zampini const PetscInt subid = cum_subs + i; 6199de2952eSStefano Zampini PetscInt ns; 6209de2952eSStefano Zampini 6219de2952eSStefano Zampini PetscCall(ISGetLocalSize(pcbddc->local_subs[i], &ns)); 6229de2952eSStefano Zampini PetscCall(ISGetIndices(pcbddc->local_subs[i], &idxs)); 6239de2952eSStefano Zampini for (j = 0; j < ns; j++) { 6249de2952eSStefano Zampini const PetscInt e = idxs[j]; 6259de2952eSStefano Zampini 6269de2952eSStefano Zampini eleaves[e] = subid; 6279de2952eSStefano Zampini for (PetscInt k = ii[e]; k < ii[e + 1]; k++) vleaves[jj[k]] = subid; 6289de2952eSStefano Zampini } 6299de2952eSStefano Zampini PetscCall(ISRestoreIndices(pcbddc->local_subs[i], &idxs)); 6309de2952eSStefano Zampini } 6310b61a303SStefano Zampini PetscCall(MatRestoreRowIJ(lGinit, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 6329de2952eSStefano Zampini PetscCall(PetscSFBcastBegin(emlsf, MPIU_INT, eleaves, meleaves, MPI_REPLACE)); 6339de2952eSStefano Zampini PetscCall(PetscSFBcastEnd(emlsf, MPIU_INT, eleaves, meleaves, MPI_REPLACE)); 6349de2952eSStefano Zampini PetscCall(PetscSFBcastBegin(vmlsf, MPIU_INT, vleaves, mvleaves, MPI_REPLACE)); 6359de2952eSStefano Zampini PetscCall(PetscSFBcastEnd(vmlsf, MPIU_INT, vleaves, mvleaves, MPI_REPLACE)); 6369de2952eSStefano Zampini PetscCall(PetscFree(eleaves)); 6379de2952eSStefano Zampini PetscCall(PetscFree(vleaves)); 6389de2952eSStefano Zampini 6399de2952eSStefano Zampini PetscCall(PetscMalloc1(ne + 1, &eneighs)); 6409de2952eSStefano Zampini eneighs[0] = meleaves; 6410b61a303SStefano Zampini for (i = 0; i < ne; i++) { 6420b61a303SStefano Zampini PetscCall(PetscSortInt(ecount[i], eneighs[i])); 6430b61a303SStefano Zampini eneighs[i + 1] = eneighs[i] + ecount[i]; 6449de2952eSStefano Zampini } 6459de2952eSStefano Zampini PetscCall(PetscMalloc1(nv + 1, &vneighs)); 6469de2952eSStefano Zampini vneighs[0] = mvleaves; 6470b61a303SStefano Zampini for (i = 0; i < nv; i++) { 6480b61a303SStefano Zampini PetscCall(PetscSortInt(vcount[i], vneighs[i])); 6490b61a303SStefano Zampini vneighs[i + 1] = vneighs[i] + vcount[i]; 6509de2952eSStefano Zampini } 6519de2952eSStefano Zampini } else { 6529de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingGetNodeInfo(el2g, NULL, NULL, &eneighs)); 6539de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingGetNodeInfo(vl2g, NULL, NULL, &vneighs)); 6549de2952eSStefano Zampini } 6559de2952eSStefano Zampini 6569566063dSJacob Faibussowitsch PetscCall(MatTranspose(lGe, MAT_INITIAL_MATRIX, &lGt)); 657a13144ffSStefano Zampini if (print) { 6589566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)lGe, "edgerestr_lG")); 6599566063dSJacob Faibussowitsch PetscCall(MatView(lGe, NULL)); 6609566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)lGt, "edgerestr_lGt")); 6619566063dSJacob Faibussowitsch PetscCall(MatView(lGt, NULL)); 662a13144ffSStefano Zampini } 6639566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 6649566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(lGt, &vals)); 665a13144ffSStefano Zampini for (i = 0; i < nv; i++) { 666637e8532SStefano Zampini PetscInt ord = order, test = ii[i + 1] - ii[i], vc = vcount[i]; 6677d871cd7SStefano Zampini PetscBool sneighs = PETSC_TRUE, bdir = PETSC_FALSE; 668b03ebc13SStefano Zampini if (!order) { /* variable order */ 669dec27d64SStefano Zampini PetscReal vorder = 0.; 670dec27d64SStefano Zampini 671dec27d64SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) vorder += PetscRealPart(vals[j]); 672dec27d64SStefano Zampini test = PetscFloorReal(vorder + 10. * PETSC_SQRT_MACHINE_EPSILON); 67363a3b9bcSJacob Faibussowitsch PetscCheck(vorder - test <= PETSC_SQRT_MACHINE_EPSILON, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected value for vorder: %g (%" PetscInt_FMT ")", (double)vorder, test); 674dec27d64SStefano Zampini ord = 1; 675dec27d64SStefano Zampini } 676637e8532SStefano Zampini for (j = ii[i]; j < ii[i + 1] && sneighs; j++) { 6779de2952eSStefano Zampini const PetscInt e = jj[j]; 6789de2952eSStefano Zampini 6799de2952eSStefano Zampini if (PetscBTLookup(btbd, e)) { 6807d871cd7SStefano Zampini bdir = PETSC_TRUE; 6817d871cd7SStefano Zampini break; 6827d871cd7SStefano Zampini } 6839de2952eSStefano Zampini if (vc != ecount[e]) { 684637e8532SStefano Zampini sneighs = PETSC_FALSE; 685637e8532SStefano Zampini } else { 6869de2952eSStefano Zampini const PetscInt *vn = vneighs[i], *en = eneighs[e]; 6879de2952eSStefano Zampini 6889de2952eSStefano Zampini for (PetscInt k = 0; k < vc; k++) { 689637e8532SStefano Zampini if (vn[k] != en[k]) { 690637e8532SStefano Zampini sneighs = PETSC_FALSE; 691637e8532SStefano Zampini break; 692637e8532SStefano Zampini } 693637e8532SStefano Zampini } 694637e8532SStefano Zampini } 695637e8532SStefano Zampini } 6960b61a303SStefano Zampini if (elements_corners) test = 0; 6977d871cd7SStefano Zampini if (!sneighs || test >= 3 * ord || bdir) { /* splitpoints */ 6983ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, "SPLITPOINT %" PetscInt_FMT " (%s %s %s)\n", i, PetscBools[!sneighs], PetscBools[test >= 3 * ord], PetscBools[bdir])); 6999566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, i)); 700dec27d64SStefano Zampini } else if (test == ord) { 701b03ebc13SStefano Zampini if (order == 1 || (!order && ii[i + 1] - ii[i] == 1)) { 7023ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, "ENDPOINT %" PetscInt_FMT "\n", i)); 7039566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, i)); 7040b61a303SStefano Zampini } else if (!elements_corners) { 7053ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, "CORNER CANDIDATE %" PetscInt_FMT "\n", i)); 7069566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btvcand, i)); 707a13144ffSStefano Zampini } 708a13144ffSStefano Zampini } 709a13144ffSStefano Zampini } 7109566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btbd)); 711b03ebc13SStefano Zampini 712b03ebc13SStefano Zampini /* a candidate is valid if it is connected to another candidate via a non-primal edge dof */ 713b03ebc13SStefano Zampini if (order != 1) { 7143ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, "INSPECTING CANDIDATES\n")); 7159566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGe, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 716b03ebc13SStefano Zampini for (i = 0; i < nv; i++) { 717b03ebc13SStefano Zampini if (PetscBTLookup(btvcand, i)) { 718b03ebc13SStefano Zampini PetscBool found = PETSC_FALSE; 719b03ebc13SStefano Zampini for (j = ii[i]; j < ii[i + 1] && !found; j++) { 720b03ebc13SStefano Zampini PetscInt k, e = jj[j]; 721b03ebc13SStefano Zampini if (PetscBTLookup(bte, e)) continue; 722b03ebc13SStefano Zampini for (k = iit[e]; k < iit[e + 1]; k++) { 723b03ebc13SStefano Zampini PetscInt v = jjt[k]; 724b03ebc13SStefano Zampini if (v != i && PetscBTLookup(btvcand, v)) { 725b03ebc13SStefano Zampini found = PETSC_TRUE; 726b03ebc13SStefano Zampini break; 727b03ebc13SStefano Zampini } 728b03ebc13SStefano Zampini } 729b03ebc13SStefano Zampini } 730b03ebc13SStefano Zampini if (!found) { 7313ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " CANDIDATE %" PetscInt_FMT " CLEARED\n", i)); 7329566063dSJacob Faibussowitsch PetscCall(PetscBTClear(btvcand, i)); 733b03ebc13SStefano Zampini } else { 7343ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " CANDIDATE %" PetscInt_FMT " ACCEPTED\n", i)); 735b03ebc13SStefano Zampini } 736b03ebc13SStefano Zampini } 737b03ebc13SStefano Zampini } 7389566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGe, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 739b03ebc13SStefano Zampini } 7409566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(lGt, &vals)); 7419566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 7429566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGe)); 743a13144ffSStefano Zampini 744a13144ffSStefano Zampini /* Get the local G^T explicitly */ 7459566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGt)); 7469566063dSJacob Faibussowitsch PetscCall(MatTranspose(lG, MAT_INITIAL_MATRIX, &lGt)); 7479566063dSJacob Faibussowitsch PetscCall(MatSetOption(lGt, MAT_KEEP_NONZERO_PATTERN, PETSC_FALSE)); 748a13144ffSStefano Zampini 7499de2952eSStefano Zampini /* Mark shared nodal dofs */ 7509566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(nv, &btvi)); 7519de2952eSStefano Zampini for (i = 0; i < nv; i++) { 7529de2952eSStefano Zampini if (vcount[i] > 1) PetscCall(PetscBTSet(btvi, i)); 753a13144ffSStefano Zampini } 7549de2952eSStefano Zampini 7559de2952eSStefano Zampini if (matis->allow_repeated) { 7569de2952eSStefano Zampini PetscCall(PetscFree(eneighs[0])); 7579de2952eSStefano Zampini PetscCall(PetscFree(vneighs[0])); 7589de2952eSStefano Zampini PetscCall(PetscFree(eneighs)); 7599de2952eSStefano Zampini PetscCall(PetscFree(vneighs)); 7609de2952eSStefano Zampini } 7619de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(el2g, NULL, &ecount, &eneighs)); 7629de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(vl2g, NULL, &vcount, &vneighs)); 763a13144ffSStefano Zampini 764a13144ffSStefano Zampini /* communicate corners and splitpoints */ 7659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nv, &vmarks)); 7669566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(sfvleaves, nv)); 7679566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(sfvroots, Lv)); 7689371c9d4SSatish Balay for (i = 0; i < nv; i++) 7699371c9d4SSatish Balay if (PetscUnlikely(PetscBTLookup(btv, i))) sfvleaves[i] = 1; 770a13144ffSStefano Zampini 771a13144ffSStefano Zampini if (print) { 772a13144ffSStefano Zampini IS tbz; 773a13144ffSStefano Zampini 774a13144ffSStefano Zampini cum = 0; 775a13144ffSStefano Zampini for (i = 0; i < nv; i++) 7769371c9d4SSatish Balay if (sfvleaves[i]) vmarks[cum++] = i; 777a13144ffSStefano Zampini 7789566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cum, vmarks, PETSC_COPY_VALUES, &tbz)); 7799566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)tbz, "corners_to_be_zeroed_local")); 7809566063dSJacob Faibussowitsch PetscCall(ISView(tbz, NULL)); 7819566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tbz)); 782a13144ffSStefano Zampini } 783a13144ffSStefano Zampini 7849566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(sfv, MPIU_INT, sfvleaves, sfvroots, MPI_SUM)); 7859566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(sfv, MPIU_INT, sfvleaves, sfvroots, MPI_SUM)); 7869566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfv, MPIU_INT, sfvroots, sfvleaves, MPI_REPLACE)); 7879566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfv, MPIU_INT, sfvroots, sfvleaves, MPI_REPLACE)); 788a13144ffSStefano Zampini 7894e64d54eSstefano_zampini /* Zero rows of lGt corresponding to identified corners 7904e64d54eSstefano_zampini and interior nodal dofs */ 791a13144ffSStefano Zampini cum = 0; 792a13144ffSStefano Zampini for (i = 0; i < nv; i++) { 793a13144ffSStefano Zampini if (sfvleaves[i]) { 794a13144ffSStefano Zampini vmarks[cum++] = i; 7959566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, i)); 7969de2952eSStefano Zampini } else if (!PetscBTLookup(btvi, i)) vmarks[cum++] = i; 797a13144ffSStefano Zampini } 7989566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btvi)); 799a13144ffSStefano Zampini if (print) { 800a13144ffSStefano Zampini IS tbz; 801a13144ffSStefano Zampini 8029566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cum, vmarks, PETSC_COPY_VALUES, &tbz)); 8039566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)tbz, "corners_to_be_zeroed_with_interior")); 8049566063dSJacob Faibussowitsch PetscCall(ISView(tbz, NULL)); 8059566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tbz)); 806a13144ffSStefano Zampini } 8079566063dSJacob Faibussowitsch PetscCall(MatZeroRows(lGt, cum, vmarks, 0., NULL, NULL)); 8089566063dSJacob Faibussowitsch PetscCall(PetscFree(vmarks)); 8099566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfv)); 8109566063dSJacob Faibussowitsch PetscCall(PetscFree2(sfvleaves, sfvroots)); 811a13144ffSStefano Zampini 812a13144ffSStefano Zampini /* Recompute G */ 8139566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lG)); 8149566063dSJacob Faibussowitsch PetscCall(MatTranspose(lGt, MAT_INITIAL_MATRIX, &lG)); 815a13144ffSStefano Zampini if (print) { 8169566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)lG, "used_lG")); 8179566063dSJacob Faibussowitsch PetscCall(MatView(lG, NULL)); 8189566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)lGt, "used_lGt")); 8199566063dSJacob Faibussowitsch PetscCall(MatView(lGt, NULL)); 820a13144ffSStefano Zampini } 821a13144ffSStefano Zampini 822a13144ffSStefano Zampini /* Get primal dofs (if any) */ 823a13144ffSStefano Zampini cum = 0; 824a13144ffSStefano Zampini for (i = 0; i < ne; i++) { 825a13144ffSStefano Zampini if (PetscUnlikely(PetscBTLookup(bte, i))) marks[cum++] = i; 826a13144ffSStefano Zampini } 8271baa6e33SBarry Smith if (fl2g) PetscCall(ISLocalToGlobalMappingApply(fl2g, cum, marks, marks)); 8289566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, cum, marks, PETSC_COPY_VALUES, &primals)); 829a13144ffSStefano Zampini if (print) { 8309566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)primals, "prescribed_primal_dofs")); 8319566063dSJacob Faibussowitsch PetscCall(ISView(primals, NULL)); 832a13144ffSStefano Zampini } 8339566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&bte)); 834c2151214SStefano Zampini /* TODO: what if the user passed in some of them ? */ 8359566063dSJacob Faibussowitsch PetscCall(PCBDDCSetPrimalVerticesLocalIS(pc, primals)); 8369566063dSJacob Faibussowitsch PetscCall(ISDestroy(&primals)); 837a13144ffSStefano Zampini 838a13144ffSStefano Zampini /* Compute edge connectivity */ 8399566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)lG, "econn_")); 8404222ddf1SHong Zhang 8414222ddf1SHong Zhang /* Symbolic conn = lG*lGt */ 8420b61a303SStefano Zampini if (!elements_corners) { /* if present, we assume we are in the element-by-element case and the CSR graph is not needed */ 8439566063dSJacob Faibussowitsch PetscCall(MatProductCreate(lG, lGt, NULL, &conn)); 8449566063dSJacob Faibussowitsch PetscCall(MatProductSetType(conn, MATPRODUCT_AB)); 8459566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(conn, "default")); 8469566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(conn, PETSC_DEFAULT)); 8479566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)conn, "econn_")); 8489566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(conn)); 8499566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(conn)); 8509566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 851c2151214SStefano Zampini if (fl2g) { 852c2151214SStefano Zampini PetscBT btf; 853c2151214SStefano Zampini PetscInt *iia, *jja, *iiu, *jju; 854c2151214SStefano Zampini PetscBool rest = PETSC_FALSE, free = PETSC_FALSE; 855c2151214SStefano Zampini 856c2151214SStefano Zampini /* create CSR for all local dofs */ 8579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n + 1, &iia)); 858c2151214SStefano Zampini if (pcbddc->mat_graph->nvtxs_csr) { /* the user has passed in a CSR graph */ 85963a3b9bcSJacob 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); 860c2151214SStefano Zampini iiu = pcbddc->mat_graph->xadj; 861c2151214SStefano Zampini jju = pcbddc->mat_graph->adjncy; 862c2151214SStefano Zampini } else if (pcbddc->use_local_adj) { 863c2151214SStefano Zampini rest = PETSC_TRUE; 8649566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(matis->A, 0, PETSC_TRUE, PETSC_FALSE, &i, (const PetscInt **)&iiu, (const PetscInt **)&jju, &done)); 865c2151214SStefano Zampini } else { 866c2151214SStefano Zampini free = PETSC_TRUE; 8679566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n + 1, &iiu, n, &jju)); 868c2151214SStefano Zampini iiu[0] = 0; 869c2151214SStefano Zampini for (i = 0; i < n; i++) { 870c2151214SStefano Zampini iiu[i + 1] = i + 1; 871c2151214SStefano Zampini jju[i] = -1; 872d904f53bSStefano Zampini } 873c2151214SStefano Zampini } 874c2151214SStefano Zampini 875c2151214SStefano Zampini /* import sizes of CSR */ 876c2151214SStefano Zampini iia[0] = 0; 877c2151214SStefano Zampini for (i = 0; i < n; i++) iia[i + 1] = iiu[i + 1] - iiu[i]; 878c2151214SStefano Zampini 879c2151214SStefano Zampini /* overwrite entries corresponding to the Nedelec field */ 8809566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(n, &btf)); 8819566063dSJacob Faibussowitsch PetscCall(ISGetIndices(nedfieldlocal, &idxs)); 882c2151214SStefano Zampini for (i = 0; i < ne; i++) { 8839566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btf, idxs[i])); 884c2151214SStefano Zampini iia[idxs[i] + 1] = ii[i + 1] - ii[i]; 885c2151214SStefano Zampini } 886c2151214SStefano Zampini 887c2151214SStefano Zampini /* iia in CSR */ 888c2151214SStefano Zampini for (i = 0; i < n; i++) iia[i + 1] += iia[i]; 889c2151214SStefano Zampini 890c2151214SStefano Zampini /* jja in CSR */ 8919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(iia[n], &jja)); 892c2151214SStefano Zampini for (i = 0; i < n; i++) 893c2151214SStefano Zampini if (!PetscBTLookup(btf, i)) 8949371c9d4SSatish Balay for (j = 0; j < iiu[i + 1] - iiu[i]; j++) jja[iia[i] + j] = jju[iiu[i] + j]; 895c2151214SStefano Zampini 896c2151214SStefano Zampini /* map edge dofs connectivity */ 8971e0482f5SStefano Zampini if (jj) { 8989566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(fl2g, ii[ne], jj, (PetscInt *)jj)); 899c2151214SStefano Zampini for (i = 0; i < ne; i++) { 900c2151214SStefano Zampini PetscInt e = idxs[i]; 901c2151214SStefano Zampini for (j = 0; j < ii[i + 1] - ii[i]; j++) jja[iia[e] + j] = jj[ii[i] + j]; 902c2151214SStefano Zampini } 9031e0482f5SStefano Zampini } 9049566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(nedfieldlocal, &idxs)); 9050b61a303SStefano Zampini PetscCall(PCBDDCSetLocalAdjacencyGraph(pc, n, iia, jja, PETSC_COPY_VALUES)); 90648a46eb9SPierre Jolivet if (rest) PetscCall(MatRestoreRowIJ(matis->A, 0, PETSC_TRUE, PETSC_FALSE, &i, (const PetscInt **)&iiu, (const PetscInt **)&jju, &done)); 9071baa6e33SBarry Smith if (free) PetscCall(PetscFree2(iiu, jju)); 9089566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btf)); 909c2151214SStefano Zampini } else { 9100b61a303SStefano Zampini PetscCall(PCBDDCSetLocalAdjacencyGraph(pc, n, ii, jj, PETSC_COPY_VALUES)); 9110b61a303SStefano Zampini } 9120b61a303SStefano Zampini PetscCall(MatRestoreRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 9130b61a303SStefano Zampini PetscCall(MatDestroy(&conn)); 914c2151214SStefano Zampini } 915c2151214SStefano Zampini 916a13144ffSStefano Zampini /* Analyze interface for edge dofs */ 9179566063dSJacob Faibussowitsch PetscCall(PCBDDCAnalyzeInterface(pc)); 918213b8bfaSStefano Zampini pcbddc->mat_graph->twodim = PETSC_FALSE; 919a13144ffSStefano Zampini 920a13144ffSStefano Zampini /* Get coarse edges in the edge space */ 9219566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, NULL, NULL, &nee, &alleedges, &allprimals)); 922a13144ffSStefano Zampini 923c2151214SStefano Zampini if (fl2g) { 9249566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(fl2g, IS_GTOLM_DROP, allprimals, &primals)); 9259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nee, &eedges)); 92648a46eb9SPierre Jolivet for (i = 0; i < nee; i++) PetscCall(ISGlobalToLocalMappingApplyIS(fl2g, IS_GTOLM_DROP, alleedges[i], &eedges[i])); 927c2151214SStefano Zampini } else { 928c2151214SStefano Zampini eedges = alleedges; 929c2151214SStefano Zampini primals = allprimals; 930c2151214SStefano Zampini } 931c2151214SStefano Zampini 932a13144ffSStefano Zampini /* Mark fine edge dofs with their coarse edge id */ 9339566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(marks, ne)); 9349566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(primals, &cum)); 9359566063dSJacob Faibussowitsch PetscCall(ISGetIndices(primals, &idxs)); 936c2151214SStefano Zampini for (i = 0; i < cum; i++) marks[idxs[i]] = nee + 1; 9379566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(primals, &idxs)); 938c2151214SStefano Zampini if (print) { 9399566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)primals, "obtained_primal_dofs")); 9409566063dSJacob Faibussowitsch PetscCall(ISView(primals, NULL)); 941c2151214SStefano Zampini } 942c2151214SStefano Zampini 943c2151214SStefano Zampini maxsize = 0; 944a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 945a13144ffSStefano Zampini PetscInt size, mark = i + 1; 946a13144ffSStefano Zampini 9479566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 9489566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 949a13144ffSStefano Zampini for (j = 0; j < size; j++) marks[idxs[j]] = mark; 9509566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 951a13144ffSStefano Zampini maxsize = PetscMax(maxsize, size); 952a13144ffSStefano Zampini } 953a13144ffSStefano Zampini 954a13144ffSStefano Zampini /* Find coarse edge endpoints */ 9559566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lG, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 9569566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 957a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 958a13144ffSStefano Zampini PetscInt mark = i + 1, size; 959a13144ffSStefano Zampini 9609566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 9611e0482f5SStefano Zampini if (!size && nedfieldlocal) continue; 96263a3b9bcSJacob Faibussowitsch PetscCheck(size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected zero sized edge %" PetscInt_FMT, i); 9639566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 964a13144ffSStefano Zampini if (print) { 96563a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "ENDPOINTS ANALYSIS EDGE %" PetscInt_FMT "\n", i)); 9669566063dSJacob Faibussowitsch PetscCall(ISView(eedges[i], NULL)); 967a13144ffSStefano Zampini } 968a13144ffSStefano Zampini for (j = 0; j < size; j++) { 969a13144ffSStefano Zampini PetscInt k, ee = idxs[j]; 9703ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " idx %" PetscInt_FMT "\n", ee)); 971a13144ffSStefano Zampini for (k = ii[ee]; k < ii[ee + 1]; k++) { 9723ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " inspect %" PetscInt_FMT "\n", jj[k])); 973a13144ffSStefano Zampini if (PetscBTLookup(btv, jj[k])) { 9743ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " corner found (already set) %" PetscInt_FMT "\n", jj[k])); 975a13144ffSStefano Zampini } else if (PetscBTLookup(btvcand, jj[k])) { /* is it ok? */ 976a13144ffSStefano Zampini PetscInt k2; 977a13144ffSStefano Zampini PetscBool corner = PETSC_FALSE; 978a13144ffSStefano Zampini for (k2 = iit[jj[k]]; k2 < iit[jj[k] + 1]; k2++) { 9793ba16761SJacob 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]))); 980c2151214SStefano Zampini /* it's a corner if either is connected with an edge dof belonging to a different cc or 981c2151214SStefano Zampini if the edge dof lie on the natural part of the boundary */ 982c2151214SStefano Zampini if ((marks[jjt[k2]] && marks[jjt[k2]] != mark) || (!marks[jjt[k2]] && PetscBTLookup(btb, jjt[k2]))) { 983a13144ffSStefano Zampini corner = PETSC_TRUE; 984a13144ffSStefano Zampini break; 985a13144ffSStefano Zampini } 986a13144ffSStefano Zampini } 987a13144ffSStefano Zampini if (corner) { /* found the nodal dof corresponding to the endpoint of the edge */ 9883ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " corner found %" PetscInt_FMT "\n", jj[k])); 9899566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, jj[k])); 990a13144ffSStefano Zampini } else { 9913ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " no corners found\n")); 992a13144ffSStefano Zampini } 993a13144ffSStefano Zampini } 994a13144ffSStefano Zampini } 995a13144ffSStefano Zampini } 9969566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 997a13144ffSStefano Zampini } 9989566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 9999566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lG, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 10009566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btb)); 1001a13144ffSStefano Zampini 1002a13144ffSStefano Zampini /* Reset marked primal dofs */ 10039566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(primals, &cum)); 10049566063dSJacob Faibussowitsch PetscCall(ISGetIndices(primals, &idxs)); 1005a13144ffSStefano Zampini for (i = 0; i < cum; i++) marks[idxs[i]] = 0; 10069566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(primals, &idxs)); 1007a13144ffSStefano Zampini 10080569b399SStefano Zampini /* Now use the initial lG */ 10099566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lG)); 10109566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGt)); 10110569b399SStefano Zampini lG = lGinit; 10129566063dSJacob Faibussowitsch PetscCall(MatTranspose(lG, MAT_INITIAL_MATRIX, &lGt)); 10130569b399SStefano Zampini 1014a13144ffSStefano Zampini /* Compute extended cols indices */ 10159566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(nv, &btvc)); 10169566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(nee, &bter)); 10179566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lG, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 10189566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetMaxRowNonzeros(lG, &i)); 1019a13144ffSStefano Zampini i *= maxsize; 10209566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nee, &extcols)); 10219566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(i, &extrow, i, &gidxs)); 1022a13144ffSStefano Zampini eerr = PETSC_FALSE; 1023a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 1024b03ebc13SStefano Zampini PetscInt size, found = 0; 1025a13144ffSStefano Zampini 1026a13144ffSStefano Zampini cum = 0; 10279566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 10281e0482f5SStefano Zampini if (!size && nedfieldlocal) continue; 102963a3b9bcSJacob Faibussowitsch PetscCheck(size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected zero sized edge %" PetscInt_FMT, i); 10309566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 10319566063dSJacob Faibussowitsch PetscCall(PetscBTMemzero(nv, btvc)); 1032a13144ffSStefano Zampini for (j = 0; j < size; j++) { 1033a13144ffSStefano Zampini PetscInt k, ee = idxs[j]; 1034b03ebc13SStefano Zampini for (k = ii[ee]; k < ii[ee + 1]; k++) { 1035b03ebc13SStefano Zampini PetscInt vv = jj[k]; 1036b03ebc13SStefano Zampini if (!PetscBTLookup(btv, vv)) extrow[cum++] = vv; 1037b03ebc13SStefano Zampini else if (!PetscBTLookupSet(btvc, vv)) found++; 1038b03ebc13SStefano Zampini } 1039a13144ffSStefano Zampini } 10409566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 10419566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&cum, extrow)); 10429566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(vl2g, cum, extrow, gidxs)); 10439566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(cum, gidxs, extrow)); 10449566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cum, extrow, PETSC_COPY_VALUES, &extcols[i])); 1045a13144ffSStefano Zampini /* it may happen that endpoints are not defined at this point 1046a13144ffSStefano Zampini if it is the case, mark this edge for a second pass */ 1047b03ebc13SStefano Zampini if (cum != size - 1 || found != 2) { 10489566063dSJacob Faibussowitsch PetscCall(PetscBTSet(bter, i)); 1049a13144ffSStefano Zampini if (print) { 10509566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)eedges[i], "error_edge")); 10519566063dSJacob Faibussowitsch PetscCall(ISView(eedges[i], NULL)); 10529566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)extcols[i], "error_extcol")); 10539566063dSJacob Faibussowitsch PetscCall(ISView(extcols[i], NULL)); 1054a13144ffSStefano Zampini } 1055a13144ffSStefano Zampini eerr = PETSC_TRUE; 1056a13144ffSStefano Zampini } 1057a13144ffSStefano Zampini } 105828b400f6SJacob Faibussowitsch /* PetscCheck(!eerr,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL FIRST PASS"); */ 1059462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&eerr, &done, 1, MPIU_BOOL, MPI_LOR, comm)); 1060a13144ffSStefano Zampini if (done) { 1061a13144ffSStefano Zampini PetscInt *newprimals; 1062a13144ffSStefano Zampini 10639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ne, &newprimals)); 10649566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(primals, &cum)); 10659566063dSJacob Faibussowitsch PetscCall(ISGetIndices(primals, &idxs)); 10669566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(newprimals, idxs, cum)); 10679566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(primals, &idxs)); 10689566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 10693ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, "DOING SECOND PASS (eerr %s)\n", PetscBools[eerr])); 1070a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 1071b03ebc13SStefano Zampini PetscBool has_candidates = PETSC_FALSE; 1072b03ebc13SStefano Zampini if (PetscBTLookup(bter, i)) { 1073a13144ffSStefano Zampini PetscInt size, mark = i + 1; 1074a13144ffSStefano Zampini 10759566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 10769566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 1077c2151214SStefano Zampini /* for (j=0;j<size;j++) newprimals[cum++] = idxs[j]; */ 1078a13144ffSStefano Zampini for (j = 0; j < size; j++) { 1079a13144ffSStefano Zampini PetscInt k, ee = idxs[j]; 10803ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, "Inspecting edge dof %" PetscInt_FMT " [%" PetscInt_FMT " %" PetscInt_FMT ")\n", ee, ii[ee], ii[ee + 1])); 1081a13144ffSStefano Zampini for (k = ii[ee]; k < ii[ee + 1]; k++) { 1082a13144ffSStefano Zampini /* set all candidates located on the edge as corners */ 1083a13144ffSStefano Zampini if (PetscBTLookup(btvcand, jj[k])) { 1084a13144ffSStefano Zampini PetscInt k2, vv = jj[k]; 1085b03ebc13SStefano Zampini has_candidates = PETSC_TRUE; 10863ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Candidate set to vertex %" PetscInt_FMT "\n", vv)); 10879566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, vv)); 1088a13144ffSStefano Zampini /* set all edge dofs connected to candidate as primals */ 1089a13144ffSStefano Zampini for (k2 = iit[vv]; k2 < iit[vv + 1]; k2++) { 1090a13144ffSStefano Zampini if (marks[jjt[k2]] == mark) { 1091a13144ffSStefano Zampini PetscInt k3, ee2 = jjt[k2]; 10923ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Connected edge dof set to primal %" PetscInt_FMT "\n", ee2)); 1093a13144ffSStefano Zampini newprimals[cum++] = ee2; 1094a13144ffSStefano Zampini /* finally set the new corners */ 1095a13144ffSStefano Zampini for (k3 = ii[ee2]; k3 < ii[ee2 + 1]; k3++) { 10963ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Connected nodal dof set to vertex %" PetscInt_FMT "\n", jj[k3])); 10979566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, jj[k3])); 1098a13144ffSStefano Zampini } 1099a13144ffSStefano Zampini } 1100a13144ffSStefano Zampini } 1101b03ebc13SStefano Zampini } else { 11023ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Not a candidate vertex %" PetscInt_FMT "\n", jj[k])); 1103a13144ffSStefano Zampini } 1104a13144ffSStefano Zampini } 1105a13144ffSStefano Zampini } 1106b03ebc13SStefano Zampini if (!has_candidates) { /* circular edge */ 1107b03ebc13SStefano Zampini PetscInt k, ee = idxs[0], *tmarks; 1108b03ebc13SStefano Zampini 11099566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(ne, &tmarks)); 11103ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Circular edge %" PetscInt_FMT "\n", i)); 1111b03ebc13SStefano Zampini for (k = ii[ee]; k < ii[ee + 1]; k++) { 1112b03ebc13SStefano Zampini PetscInt k2; 11133ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Set to corner %" PetscInt_FMT "\n", jj[k])); 11149566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, jj[k])); 1115b03ebc13SStefano Zampini for (k2 = iit[jj[k]]; k2 < iit[jj[k] + 1]; k2++) tmarks[jjt[k2]]++; 1116b03ebc13SStefano Zampini } 1117b03ebc13SStefano Zampini for (j = 0; j < size; j++) { 1118b03ebc13SStefano Zampini if (tmarks[idxs[j]] > 1) { 11193ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Edge dof set to primal %" PetscInt_FMT "\n", idxs[j])); 1120b03ebc13SStefano Zampini newprimals[cum++] = idxs[j]; 1121b03ebc13SStefano Zampini } 1122b03ebc13SStefano Zampini } 11239566063dSJacob Faibussowitsch PetscCall(PetscFree(tmarks)); 1124b03ebc13SStefano Zampini } 11259566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 1126a13144ffSStefano Zampini } 11279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&extcols[i])); 1128a13144ffSStefano Zampini } 11299566063dSJacob Faibussowitsch PetscCall(PetscFree(extcols)); 11309566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 11319566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&cum, newprimals)); 1132c2151214SStefano Zampini if (fl2g) { 11339566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(fl2g, cum, newprimals, newprimals)); 11349566063dSJacob Faibussowitsch PetscCall(ISDestroy(&primals)); 113548a46eb9SPierre Jolivet for (i = 0; i < nee; i++) PetscCall(ISDestroy(&eedges[i])); 11369566063dSJacob Faibussowitsch PetscCall(PetscFree(eedges)); 1137c2151214SStefano Zampini } 11389566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, NULL, NULL, &nee, &alleedges, &allprimals)); 11399566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, cum, newprimals, PETSC_COPY_VALUES, &primals)); 11409566063dSJacob Faibussowitsch PetscCall(PetscFree(newprimals)); 11419566063dSJacob Faibussowitsch PetscCall(PCBDDCSetPrimalVerticesLocalIS(pc, primals)); 11429566063dSJacob Faibussowitsch PetscCall(ISDestroy(&primals)); 11439566063dSJacob Faibussowitsch PetscCall(PCBDDCAnalyzeInterface(pc)); 1144213b8bfaSStefano Zampini pcbddc->mat_graph->twodim = PETSC_FALSE; 11459566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, NULL, NULL, &nee, &alleedges, &allprimals)); 1146c2151214SStefano Zampini if (fl2g) { 11479566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(fl2g, IS_GTOLM_DROP, allprimals, &primals)); 11489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nee, &eedges)); 114948a46eb9SPierre Jolivet for (i = 0; i < nee; i++) PetscCall(ISGlobalToLocalMappingApplyIS(fl2g, IS_GTOLM_DROP, alleedges[i], &eedges[i])); 1150c2151214SStefano Zampini } else { 1151c2151214SStefano Zampini eedges = alleedges; 1152c2151214SStefano Zampini primals = allprimals; 1153c2151214SStefano Zampini } 11549566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nee, &extcols)); 1155a13144ffSStefano Zampini 1156a13144ffSStefano Zampini /* Mark again */ 11579566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(marks, ne)); 1158a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 1159a13144ffSStefano Zampini PetscInt size, mark = i + 1; 1160a13144ffSStefano Zampini 11619566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 11629566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 1163a13144ffSStefano Zampini for (j = 0; j < size; j++) marks[idxs[j]] = mark; 11649566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 1165a13144ffSStefano Zampini } 1166a13144ffSStefano Zampini if (print) { 11679566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)primals, "obtained_primal_dofs_secondpass")); 11689566063dSJacob Faibussowitsch PetscCall(ISView(primals, NULL)); 1169a13144ffSStefano Zampini } 1170a13144ffSStefano Zampini 1171a13144ffSStefano Zampini /* Recompute extended cols */ 1172a13144ffSStefano Zampini eerr = PETSC_FALSE; 1173a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 1174a13144ffSStefano Zampini PetscInt size; 1175a13144ffSStefano Zampini 1176a13144ffSStefano Zampini cum = 0; 11779566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 11781e0482f5SStefano Zampini if (!size && nedfieldlocal) continue; 117963a3b9bcSJacob Faibussowitsch PetscCheck(size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected zero sized edge %" PetscInt_FMT, i); 11809566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 1181a13144ffSStefano Zampini for (j = 0; j < size; j++) { 1182a13144ffSStefano Zampini PetscInt k, ee = idxs[j]; 11839371c9d4SSatish Balay for (k = ii[ee]; k < ii[ee + 1]; k++) 11849371c9d4SSatish Balay if (!PetscBTLookup(btv, jj[k])) extrow[cum++] = jj[k]; 1185a13144ffSStefano Zampini } 11869566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 11879566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&cum, extrow)); 11889566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(vl2g, cum, extrow, gidxs)); 11899566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(cum, gidxs, extrow)); 11909566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cum, extrow, PETSC_COPY_VALUES, &extcols[i])); 1191a13144ffSStefano Zampini if (cum != size - 1) { 1192a13144ffSStefano Zampini if (print) { 11939566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)eedges[i], "error_edge_secondpass")); 11949566063dSJacob Faibussowitsch PetscCall(ISView(eedges[i], NULL)); 11959566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)extcols[i], "error_extcol_secondpass")); 11969566063dSJacob Faibussowitsch PetscCall(ISView(extcols[i], NULL)); 1197a13144ffSStefano Zampini } 1198a13144ffSStefano Zampini eerr = PETSC_TRUE; 1199a13144ffSStefano Zampini } 1200a13144ffSStefano Zampini } 1201a13144ffSStefano Zampini } 12029566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lG, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 12039566063dSJacob Faibussowitsch PetscCall(PetscFree2(extrow, gidxs)); 12049566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&bter)); 12059566063dSJacob Faibussowitsch if (print) PetscCall(PCBDDCGraphASCIIView(pcbddc->mat_graph, 5, PETSC_VIEWER_STDOUT_SELF)); 1206a13144ffSStefano Zampini /* an error should not occur at this point */ 120728b400f6SJacob Faibussowitsch PetscCheck(!eerr, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected SIZE OF EDGE > EXTCOL SECOND PASS"); 1208a13144ffSStefano Zampini 12094e64d54eSstefano_zampini /* Check the number of endpoints */ 12109566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lG, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 12119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2 * nee, &corners)); 12129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nee, &cedges)); 12134e64d54eSstefano_zampini for (i = 0; i < nee; i++) { 1214b03ebc13SStefano Zampini PetscInt size, found = 0, gc[2]; 12154e64d54eSstefano_zampini 1216b03ebc13SStefano Zampini /* init with defaults */ 1217b03ebc13SStefano Zampini cedges[i] = corners[i * 2] = corners[i * 2 + 1] = -1; 12189566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 12191e0482f5SStefano Zampini if (!size && nedfieldlocal) continue; 122063a3b9bcSJacob Faibussowitsch PetscCheck(size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected zero sized edge %" PetscInt_FMT, i); 12219566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 12229566063dSJacob Faibussowitsch PetscCall(PetscBTMemzero(nv, btvc)); 12234e64d54eSstefano_zampini for (j = 0; j < size; j++) { 12244e64d54eSstefano_zampini PetscInt k, ee = idxs[j]; 12254e64d54eSstefano_zampini for (k = ii[ee]; k < ii[ee + 1]; k++) { 12264e64d54eSstefano_zampini PetscInt vv = jj[k]; 12274e64d54eSstefano_zampini if (PetscBTLookup(btv, vv) && !PetscBTLookupSet(btvc, vv)) { 1228467446fbSPierre Jolivet PetscCheck(found != 2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Found more than two corners for edge %" PetscInt_FMT, i); 1229b03ebc13SStefano Zampini corners[i * 2 + found++] = vv; 12304e64d54eSstefano_zampini } 12314e64d54eSstefano_zampini } 12324e64d54eSstefano_zampini } 1233b03ebc13SStefano Zampini if (found != 2) { 1234b03ebc13SStefano Zampini PetscInt e; 1235b03ebc13SStefano Zampini if (fl2g) { 12369566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(fl2g, 1, idxs, &e)); 1237b03ebc13SStefano Zampini } else { 1238b03ebc13SStefano Zampini e = idxs[0]; 1239b03ebc13SStefano Zampini } 124063a3b9bcSJacob 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]); 1241b03ebc13SStefano Zampini } 1242eee23b56SStefano Zampini 1243eee23b56SStefano Zampini /* get primal dof index on this coarse edge */ 12449566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(vl2g, 2, corners + 2 * i, gc)); 1245b03ebc13SStefano Zampini if (gc[0] > gc[1]) { 1246b03ebc13SStefano Zampini PetscInt swap = corners[2 * i]; 1247b03ebc13SStefano Zampini corners[2 * i] = corners[2 * i + 1]; 1248b03ebc13SStefano Zampini corners[2 * i + 1] = swap; 1249b03ebc13SStefano Zampini } 1250eee23b56SStefano Zampini cedges[i] = idxs[size - 1]; 12519566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 12523ba16761SJacob 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])); 12534e64d54eSstefano_zampini } 12549566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lG, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 12559566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btvc)); 12564e64d54eSstefano_zampini 125776bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 1258a13144ffSStefano Zampini /* Inspects columns of lG (rows of lGt) and make sure the change of basis will 1259a13144ffSStefano Zampini not interfere with neighbouring coarse edges */ 12609566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nee + 1, &emarks)); 12619566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 1262a13144ffSStefano Zampini for (i = 0; i < nv; i++) { 1263a13144ffSStefano Zampini PetscInt emax = 0, eemax = 0; 1264a13144ffSStefano Zampini 1265a13144ffSStefano Zampini if (ii[i + 1] == ii[i] || PetscBTLookup(btv, i)) continue; 12669566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(emarks, nee + 1)); 1267a13144ffSStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) emarks[marks[jj[j]]]++; 1268a13144ffSStefano Zampini for (j = 1; j < nee + 1; j++) { 1269a13144ffSStefano Zampini if (emax < emarks[j]) { 1270a13144ffSStefano Zampini emax = emarks[j]; 1271a13144ffSStefano Zampini eemax = j; 1272a13144ffSStefano Zampini } 1273a13144ffSStefano Zampini } 1274a13144ffSStefano Zampini /* not relevant for edges */ 1275a13144ffSStefano Zampini if (!eemax) continue; 1276a13144ffSStefano Zampini 1277a13144ffSStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 12787a46b595SBarry 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]); 1279a13144ffSStefano Zampini } 1280a13144ffSStefano Zampini } 12819566063dSJacob Faibussowitsch PetscCall(PetscFree(emarks)); 12829566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 128376bd3646SJed Brown } 1284a13144ffSStefano Zampini 1285a13144ffSStefano Zampini /* Compute extended rows indices for edge blocks of the change of basis */ 12869566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 12879566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetMaxRowNonzeros(lGt, &extmem)); 1288a13144ffSStefano Zampini extmem *= maxsize; 12899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(extmem * nee, &extrow)); 12909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nee, &extrows)); 12919566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nee, &extrowcum)); 1292a13144ffSStefano Zampini for (i = 0; i < nv; i++) { 1293a13144ffSStefano Zampini PetscInt mark = 0, size, start; 1294213b8bfaSStefano Zampini 1295a13144ffSStefano Zampini if (ii[i + 1] == ii[i] || PetscBTLookup(btv, i)) continue; 1296a13144ffSStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) 12979371c9d4SSatish Balay if (marks[jj[j]] && !mark) mark = marks[jj[j]]; 1298a13144ffSStefano Zampini 1299a13144ffSStefano Zampini /* not relevant */ 1300a13144ffSStefano Zampini if (!mark) continue; 1301a13144ffSStefano Zampini 1302a13144ffSStefano Zampini /* import extended row */ 1303a13144ffSStefano Zampini mark--; 1304a13144ffSStefano Zampini start = mark * extmem + extrowcum[mark]; 1305a13144ffSStefano Zampini size = ii[i + 1] - ii[i]; 130663a3b9bcSJacob Faibussowitsch PetscCheck(extrowcum[mark] + size <= extmem, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Not enough memory allocated %" PetscInt_FMT " > %" PetscInt_FMT, extrowcum[mark] + size, extmem); 13079566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(extrow + start, jj + ii[i], size)); 1308a13144ffSStefano Zampini extrowcum[mark] += size; 1309a13144ffSStefano Zampini } 13109566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 13119566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGt)); 13129566063dSJacob Faibussowitsch PetscCall(PetscFree(marks)); 1313213b8bfaSStefano Zampini 1314213b8bfaSStefano Zampini /* Compress extrows */ 1315a13144ffSStefano Zampini cum = 0; 1316a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 1317a13144ffSStefano Zampini PetscInt size = extrowcum[i], *start = extrow + i * extmem; 13189566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&size, start)); 13199566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, size, start, PETSC_USE_POINTER, &extrows[i])); 1320a13144ffSStefano Zampini cum = PetscMax(cum, size); 1321a13144ffSStefano Zampini } 13229566063dSJacob Faibussowitsch PetscCall(PetscFree(extrowcum)); 13239566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btv)); 13249566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btvcand)); 1325a13144ffSStefano Zampini 1326a13144ffSStefano Zampini /* Workspace for lapack inner calls and VecSetValues */ 13279566063dSJacob Faibussowitsch PetscCall(PetscMalloc2((5 + cum + maxsize) * maxsize, &work, maxsize, &rwork)); 1328a13144ffSStefano Zampini 1329a13144ffSStefano Zampini /* Create change of basis matrix (preallocation can be improved) */ 13309566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &T)); 13319de2952eSStefano Zampini PetscCall(MatSetLayouts(T, pc->mat->rmap, pc->mat->cmap)); 13329566063dSJacob Faibussowitsch PetscCall(MatSetType(T, MATAIJ)); 13339de2952eSStefano Zampini PetscCall(MatSeqAIJSetPreallocation(T, maxsize, NULL)); 13349de2952eSStefano Zampini PetscCall(MatMPIAIJSetPreallocation(T, maxsize, NULL, maxsize, NULL)); 13359566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(T, al2g, al2g)); 13369566063dSJacob Faibussowitsch PetscCall(MatSetOption(T, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 13379566063dSJacob Faibussowitsch PetscCall(MatSetOption(T, MAT_ROW_ORIENTED, PETSC_FALSE)); 13389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&al2g)); 1339a13144ffSStefano Zampini 1340a13144ffSStefano Zampini /* Defaults to identity */ 13419de2952eSStefano Zampini for (i = pc->mat->rmap->rstart; i < pc->mat->rmap->rend; i++) PetscCall(MatSetValue(T, i, i, 1.0, INSERT_VALUES)); 1342a13144ffSStefano Zampini 13431e0482f5SStefano Zampini /* Create discrete gradient for the coarser level if needed */ 13449566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->nedcG)); 13459566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->nedclocal)); 13461e0482f5SStefano Zampini if (pcbddc->current_level < pcbddc->max_levels) { 13471e0482f5SStefano Zampini ISLocalToGlobalMapping cel2g, cvl2g; 13481e0482f5SStefano Zampini IS wis, gwis; 13491e0482f5SStefano Zampini PetscInt cnv, cne; 13501e0482f5SStefano Zampini 13519566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, nee, cedges, PETSC_COPY_VALUES, &wis)); 13521e0482f5SStefano Zampini if (fl2g) { 13539566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(fl2g, wis, &pcbddc->nedclocal)); 13541e0482f5SStefano Zampini } else { 13559566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)wis)); 13561e0482f5SStefano Zampini pcbddc->nedclocal = wis; 13571e0482f5SStefano Zampini } 13589566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(el2g, wis, &gwis)); 13599566063dSJacob Faibussowitsch PetscCall(ISDestroy(&wis)); 13609566063dSJacob Faibussowitsch PetscCall(ISRenumber(gwis, NULL, &cne, &wis)); 13619566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(wis, &cel2g)); 13629566063dSJacob Faibussowitsch PetscCall(ISDestroy(&wis)); 13639566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gwis)); 13641e0482f5SStefano Zampini 13659566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, 2 * nee, corners, PETSC_USE_POINTER, &wis)); 13669566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(vl2g, wis, &gwis)); 13679566063dSJacob Faibussowitsch PetscCall(ISDestroy(&wis)); 13689566063dSJacob Faibussowitsch PetscCall(ISRenumber(gwis, NULL, &cnv, &wis)); 13699566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(wis, &cvl2g)); 13709566063dSJacob Faibussowitsch PetscCall(ISDestroy(&wis)); 13719566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gwis)); 13721e0482f5SStefano Zampini 13739566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &pcbddc->nedcG)); 13749566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->nedcG, PETSC_DECIDE, PETSC_DECIDE, cne, cnv)); 13759566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->nedcG, MATAIJ)); 13769566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(pcbddc->nedcG, 2, NULL)); 13779566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(pcbddc->nedcG, 2, NULL, 2, NULL)); 13789566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(pcbddc->nedcG, cel2g, cvl2g)); 13799566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cel2g)); 13809566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cvl2g)); 13811e0482f5SStefano Zampini } 13829566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&vl2g)); 13831e0482f5SStefano Zampini 13841e0482f5SStefano Zampini #if defined(PRINT_GDET) 13851e0482f5SStefano Zampini inc = 0; 13861e0482f5SStefano Zampini lev = pcbddc->current_level; 13871e0482f5SStefano Zampini #endif 1388213b8bfaSStefano Zampini 1389213b8bfaSStefano Zampini /* Insert values in the change of basis matrix */ 1390a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 1391a13144ffSStefano Zampini Mat Gins = NULL, GKins = NULL; 13921e0482f5SStefano Zampini IS cornersis = NULL; 13931e0482f5SStefano Zampini PetscScalar cvals[2]; 1394a13144ffSStefano Zampini 139548a46eb9SPierre Jolivet if (pcbddc->nedcG) PetscCall(ISCreateGeneral(PETSC_COMM_SELF, 2, corners + 2 * i, PETSC_USE_POINTER, &cornersis)); 13969566063dSJacob Faibussowitsch PetscCall(PCBDDCComputeNedelecChangeEdge(lG, eedges[i], extrows[i], extcols[i], cornersis, &Gins, &GKins, cvals, work, rwork)); 1397a13144ffSStefano Zampini if (Gins && GKins) { 13981683a169SBarry Smith const PetscScalar *data; 1399a13144ffSStefano Zampini const PetscInt *rows, *cols; 1400a13144ffSStefano Zampini PetscInt nrh, nch, nrc, ncc; 1401a13144ffSStefano Zampini 14029566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &cols)); 1403a13144ffSStefano Zampini /* H1 */ 14049566063dSJacob Faibussowitsch PetscCall(ISGetIndices(extrows[i], &rows)); 14059566063dSJacob Faibussowitsch PetscCall(MatGetSize(Gins, &nrh, &nch)); 14069566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(Gins, &data)); 14079566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(T, nrh, rows, nch, cols, data, INSERT_VALUES)); 14089566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(Gins, &data)); 14099566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(extrows[i], &rows)); 1410a13144ffSStefano Zampini /* complement */ 14119566063dSJacob Faibussowitsch PetscCall(MatGetSize(GKins, &nrc, &ncc)); 141263a3b9bcSJacob Faibussowitsch PetscCheck(ncc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Constant function has not been generated for coarse edge %" PetscInt_FMT, i); 141363a3b9bcSJacob 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); 141463a3b9bcSJacob 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); 14159566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(GKins, &data)); 14169566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(T, nrc, cols, ncc, cols + nch, data, INSERT_VALUES)); 14179566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(GKins, &data)); 14181e0482f5SStefano Zampini 14191e0482f5SStefano Zampini /* coarse discrete gradient */ 14201e0482f5SStefano Zampini if (pcbddc->nedcG) { 14211e0482f5SStefano Zampini PetscInt cols[2]; 14221e0482f5SStefano Zampini 14231e0482f5SStefano Zampini cols[0] = 2 * i; 14241e0482f5SStefano Zampini cols[1] = 2 * i + 1; 14259566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(pcbddc->nedcG, 1, &i, 2, cols, cvals, INSERT_VALUES)); 14261e0482f5SStefano Zampini } 14279566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &cols)); 1428a13144ffSStefano Zampini } 14299566063dSJacob Faibussowitsch PetscCall(ISDestroy(&extrows[i])); 14309566063dSJacob Faibussowitsch PetscCall(ISDestroy(&extcols[i])); 14319566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cornersis)); 14329566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Gins)); 14339566063dSJacob Faibussowitsch PetscCall(MatDestroy(&GKins)); 1434a13144ffSStefano Zampini } 14350b61a303SStefano Zampini 14360b61a303SStefano Zampini /* for FDM element-by-element: first dof on the edge only constraint. Why? */ 14370b61a303SStefano Zampini if (elements_corners && pcbddc->mat_graph->multi_element) { 14380b61a303SStefano Zampini ISLocalToGlobalMapping map; 14390b61a303SStefano Zampini MatNullSpace nnsp; 14400b61a303SStefano Zampini Vec quad_vec; 14410b61a303SStefano Zampini 14420b61a303SStefano Zampini PetscCall(MatCreateVecs(pc->pmat, &quad_vec, NULL)); 14430b61a303SStefano Zampini PetscCall(PCBDDCNullSpaceCreate(PetscObjectComm((PetscObject)pc), PETSC_FALSE, 1, &quad_vec, &nnsp)); 14440b61a303SStefano Zampini PetscCall(VecLockReadPop(quad_vec)); 14450b61a303SStefano Zampini PetscCall(MatISGetLocalToGlobalMapping(pc->pmat, &map, NULL)); 14460b61a303SStefano Zampini PetscCall(VecSetLocalToGlobalMapping(quad_vec, map)); 14470b61a303SStefano Zampini for (i = 0; i < nee; i++) { 14480b61a303SStefano Zampini const PetscInt *idxs; 14490b61a303SStefano Zampini PetscScalar one = 1.0; 14500b61a303SStefano Zampini 14510b61a303SStefano Zampini PetscCall(ISGetLocalSize(alleedges[i], &cum)); 14520b61a303SStefano Zampini if (!cum) continue; 14530b61a303SStefano Zampini PetscCall(ISGetIndices(alleedges[i], &idxs)); 14540b61a303SStefano Zampini PetscCall(VecSetValuesLocal(quad_vec, 1, idxs, &one, INSERT_VALUES)); 14550b61a303SStefano Zampini PetscCall(ISRestoreIndices(alleedges[i], &idxs)); 14560b61a303SStefano Zampini } 14570b61a303SStefano Zampini PetscCall(VecLockReadPush(quad_vec)); 14580b61a303SStefano Zampini PetscCall(VecDestroy(&quad_vec)); 14590b61a303SStefano Zampini PetscCall(MatSetNearNullSpace(pc->pmat, nnsp)); 14600b61a303SStefano Zampini PetscCall(MatNullSpaceDestroy(&nnsp)); 14610b61a303SStefano Zampini } 14629566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&el2g)); 1463a13144ffSStefano Zampini 1464a13144ffSStefano Zampini /* Start assembling */ 14659566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(T, MAT_FINAL_ASSEMBLY)); 14661baa6e33SBarry Smith if (pcbddc->nedcG) PetscCall(MatAssemblyBegin(pcbddc->nedcG, MAT_FINAL_ASSEMBLY)); 1467a13144ffSStefano Zampini 1468a13144ffSStefano Zampini /* Free */ 1469c2151214SStefano Zampini if (fl2g) { 14709566063dSJacob Faibussowitsch PetscCall(ISDestroy(&primals)); 147148a46eb9SPierre Jolivet for (i = 0; i < nee; i++) PetscCall(ISDestroy(&eedges[i])); 14729566063dSJacob Faibussowitsch PetscCall(PetscFree(eedges)); 1473c2151214SStefano Zampini } 1474eee23b56SStefano Zampini 1475eee23b56SStefano Zampini /* hack mat_graph with primal dofs on the coarse edges */ 1476eee23b56SStefano Zampini { 1477eee23b56SStefano Zampini PCBDDCGraph graph = pcbddc->mat_graph; 1478eee23b56SStefano Zampini PetscInt *oqueue = graph->queue; 1479eee23b56SStefano Zampini PetscInt *ocptr = graph->cptr; 1480eee23b56SStefano Zampini PetscInt ncc, *idxs; 1481eee23b56SStefano Zampini 1482eee23b56SStefano Zampini /* find first primal edge */ 1483eee23b56SStefano Zampini if (pcbddc->nedclocal) { 14849566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->nedclocal, (const PetscInt **)&idxs)); 1485eee23b56SStefano Zampini } else { 14861baa6e33SBarry Smith if (fl2g) PetscCall(ISLocalToGlobalMappingApply(fl2g, nee, cedges, cedges)); 1487eee23b56SStefano Zampini idxs = cedges; 1488eee23b56SStefano Zampini } 1489eee23b56SStefano Zampini cum = 0; 1490eee23b56SStefano Zampini while (cum < nee && cedges[cum] < 0) cum++; 1491eee23b56SStefano Zampini 1492eee23b56SStefano Zampini /* adapt connected components */ 14939566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(graph->nvtxs + 1, &graph->cptr, ocptr[graph->ncc], &graph->queue)); 1494eee23b56SStefano Zampini graph->cptr[0] = 0; 1495eee23b56SStefano Zampini for (i = 0, ncc = 0; i < graph->ncc; i++) { 1496eee23b56SStefano Zampini PetscInt lc = ocptr[i + 1] - ocptr[i]; 1497eee23b56SStefano Zampini if (cum != nee && oqueue[ocptr[i + 1] - 1] == cedges[cum]) { /* this cc has a primal dof */ 1498eee23b56SStefano Zampini graph->cptr[ncc + 1] = graph->cptr[ncc] + 1; 1499eee23b56SStefano Zampini graph->queue[graph->cptr[ncc]] = cedges[cum]; 1500eee23b56SStefano Zampini ncc++; 1501eee23b56SStefano Zampini lc--; 1502eee23b56SStefano Zampini cum++; 1503eee23b56SStefano Zampini while (cum < nee && cedges[cum] < 0) cum++; 1504eee23b56SStefano Zampini } 1505eee23b56SStefano Zampini graph->cptr[ncc + 1] = graph->cptr[ncc] + lc; 1506eee23b56SStefano Zampini for (j = 0; j < lc; j++) graph->queue[graph->cptr[ncc] + j] = oqueue[ocptr[i] + j]; 1507eee23b56SStefano Zampini ncc++; 1508eee23b56SStefano Zampini } 1509eee23b56SStefano Zampini graph->ncc = ncc; 151048a46eb9SPierre Jolivet if (pcbddc->nedclocal) PetscCall(ISRestoreIndices(pcbddc->nedclocal, (const PetscInt **)&idxs)); 15119566063dSJacob Faibussowitsch PetscCall(PetscFree2(ocptr, oqueue)); 1512eee23b56SStefano Zampini } 15139566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&fl2g)); 15149566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, NULL, NULL, &nee, &alleedges, &allprimals)); 15159566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphResetCSR(pcbddc->mat_graph)); 1516eee23b56SStefano Zampini 15179566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nedfieldlocal)); 15189566063dSJacob Faibussowitsch PetscCall(PetscFree(extrow)); 15199566063dSJacob Faibussowitsch PetscCall(PetscFree2(work, rwork)); 15209566063dSJacob Faibussowitsch PetscCall(PetscFree(corners)); 15219566063dSJacob Faibussowitsch PetscCall(PetscFree(cedges)); 15229566063dSJacob Faibussowitsch PetscCall(PetscFree(extrows)); 15239566063dSJacob Faibussowitsch PetscCall(PetscFree(extcols)); 15249566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lG)); 1525a13144ffSStefano Zampini 1526a13144ffSStefano Zampini /* Complete assembling */ 15279566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(T, MAT_FINAL_ASSEMBLY)); 15289de2952eSStefano Zampini PetscCall(MatViewFromOptions(T, (PetscObject)pc, "-pc_bddc_nedelec_change_view")); 15291e0482f5SStefano Zampini if (pcbddc->nedcG) { 15309566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->nedcG, MAT_FINAL_ASSEMBLY)); 1531a4cdd7efSStefano Zampini PetscCall(MatViewFromOptions(pcbddc->nedcG, (PetscObject)pc, "-pc_bddc_nedelec_coarse_change_view")); 15321e0482f5SStefano Zampini } 1533a13144ffSStefano Zampini 15340b61a303SStefano Zampini PetscCall(ISDestroy(&elements_corners)); 15350b61a303SStefano Zampini 1536a13144ffSStefano Zampini /* set change of basis */ 15370b61a303SStefano Zampini PetscCall(PCBDDCSetChangeOfBasisMat(pc, T, PETSC_FALSE)); 15389566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 15393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1540a13144ffSStefano Zampini } 1541a13144ffSStefano Zampini 1542d8203eabSStefano Zampini /* the near-null space of BDDC carries information on quadrature weights, 1543d8203eabSStefano Zampini and these can be collinear -> so cheat with MatNullSpaceCreate 1544d8203eabSStefano Zampini and create a suitable set of basis vectors first */ 1545d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCNullSpaceCreate(MPI_Comm comm, PetscBool has_const, PetscInt nvecs, Vec quad_vecs[], MatNullSpace *nnsp) 1546d71ae5a4SJacob Faibussowitsch { 1547d8203eabSStefano Zampini PetscInt i; 1548d8203eabSStefano Zampini 1549d8203eabSStefano Zampini PetscFunctionBegin; 1550d8203eabSStefano Zampini for (i = 0; i < nvecs; i++) { 1551d8203eabSStefano Zampini PetscInt first, last; 1552d8203eabSStefano Zampini 15539566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(quad_vecs[i], &first, &last)); 15547827d75bSBarry Smith PetscCheck(last - first >= 2 * nvecs || !has_const, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented"); 1555d8203eabSStefano Zampini if (i >= first && i < last) { 1556d8203eabSStefano Zampini PetscScalar *data; 15579566063dSJacob Faibussowitsch PetscCall(VecGetArray(quad_vecs[i], &data)); 1558d8203eabSStefano Zampini if (!has_const) { 1559d8203eabSStefano Zampini data[i - first] = 1.; 1560d8203eabSStefano Zampini } else { 156186fa73c5SStefano Zampini data[2 * i - first] = 1. / PetscSqrtReal(2.); 156286fa73c5SStefano Zampini data[2 * i - first + 1] = -1. / PetscSqrtReal(2.); 1563d8203eabSStefano Zampini } 15649566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(quad_vecs[i], &data)); 1565d8203eabSStefano Zampini } 15669566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)quad_vecs[i])); 1567d8203eabSStefano Zampini } 15689566063dSJacob Faibussowitsch PetscCall(MatNullSpaceCreate(comm, has_const, nvecs, quad_vecs, nnsp)); 1569d8203eabSStefano Zampini for (i = 0; i < nvecs; i++) { /* reset vectors */ 1570d8203eabSStefano Zampini PetscInt first, last; 15719566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(quad_vecs[i])); 15729566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(quad_vecs[i], &first, &last)); 1573d8203eabSStefano Zampini if (i >= first && i < last) { 1574d8203eabSStefano Zampini PetscScalar *data; 15759566063dSJacob Faibussowitsch PetscCall(VecGetArray(quad_vecs[i], &data)); 1576d8203eabSStefano Zampini if (!has_const) { 1577d8203eabSStefano Zampini data[i - first] = 0.; 1578d8203eabSStefano Zampini } else { 157986fa73c5SStefano Zampini data[2 * i - first] = 0.; 158086fa73c5SStefano Zampini data[2 * i - first + 1] = 0.; 1581d8203eabSStefano Zampini } 15829566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(quad_vecs[i], &data)); 1583d8203eabSStefano Zampini } 15849566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)quad_vecs[i])); 15859566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(quad_vecs[i])); 1586d8203eabSStefano Zampini } 15873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1588d8203eabSStefano Zampini } 1589d8203eabSStefano Zampini 1590d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, PetscBool transpose, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp) 1591d71ae5a4SJacob Faibussowitsch { 1592a198735bSStefano Zampini Mat loc_divudotp; 15939de2952eSStefano Zampini Vec p, v, quad_vec; 15948ae0ca82SStefano Zampini ISLocalToGlobalMapping map; 15959de2952eSStefano Zampini PetscScalar *array; 1596669cc0f4SStefano Zampini 1597669cc0f4SStefano Zampini PetscFunctionBegin; 15989566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, &quad_vec, NULL)); 15998ae0ca82SStefano Zampini if (!transpose) { 16009566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(A, &map, NULL)); 16018ae0ca82SStefano Zampini } else { 16029566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(A, NULL, &map)); 16038ae0ca82SStefano Zampini } 16049de2952eSStefano Zampini PetscCall(PCBDDCNullSpaceCreate(PetscObjectComm((PetscObject)A), PETSC_FALSE, 1, &quad_vec, nnsp)); 16059de2952eSStefano Zampini PetscCall(VecLockReadPop(quad_vec)); 16069de2952eSStefano Zampini PetscCall(VecSetLocalToGlobalMapping(quad_vec, map)); 1607d8203eabSStefano Zampini 1608669cc0f4SStefano Zampini /* compute local quad vec */ 16099566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(divudotp, &loc_divudotp)); 16108ae0ca82SStefano Zampini if (!transpose) { 16119566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(loc_divudotp, &v, &p)); 16128ae0ca82SStefano Zampini } else { 16139566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(loc_divudotp, &p, &v)); 16148ae0ca82SStefano Zampini } 16159de2952eSStefano Zampini /* the assumption here is that the constant vector interpolates the constant on the L2 conforming space */ 16169566063dSJacob Faibussowitsch PetscCall(VecSet(p, 1.)); 16178ae0ca82SStefano Zampini if (!transpose) { 16189566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(loc_divudotp, p, v)); 16198ae0ca82SStefano Zampini } else { 16209566063dSJacob Faibussowitsch PetscCall(MatMult(loc_divudotp, p, v)); 16218ae0ca82SStefano Zampini } 16229de2952eSStefano Zampini PetscCall(VecDestroy(&p)); 1623fa23a32eSStefano Zampini if (vl2l) { 1624187c917aSStefano Zampini Mat lA; 1625187c917aSStefano Zampini VecScatter sc; 16269de2952eSStefano Zampini Vec vins; 1627187c917aSStefano Zampini 16289566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A, &lA)); 16299566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(lA, &vins, NULL)); 16309566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(v, NULL, vins, vl2l, &sc)); 16319566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sc, v, vins, INSERT_VALUES, SCATTER_FORWARD)); 16329566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sc, v, vins, INSERT_VALUES, SCATTER_FORWARD)); 16339566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sc)); 16349566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 16359de2952eSStefano Zampini v = vins; 1636669cc0f4SStefano Zampini } 16379de2952eSStefano Zampini 16389de2952eSStefano Zampini /* mask summation of interface values */ 16399de2952eSStefano Zampini PetscInt n, *mmask, *mask, *idxs, nmr, nr; 16409de2952eSStefano Zampini const PetscInt *degree; 16419de2952eSStefano Zampini PetscSF msf; 16429de2952eSStefano Zampini 16439de2952eSStefano Zampini PetscCall(VecGetLocalSize(v, &n)); 16449de2952eSStefano Zampini PetscCall(PetscSFGetGraph(graph->interface_subset_sf, &nr, NULL, NULL, NULL)); 16459de2952eSStefano Zampini PetscCall(PetscSFGetMultiSF(graph->interface_subset_sf, &msf)); 16469de2952eSStefano Zampini PetscCall(PetscSFGetGraph(msf, &nmr, NULL, NULL, NULL)); 16479de2952eSStefano Zampini PetscCall(PetscCalloc3(nmr, &mmask, n, &mask, n, &idxs)); 16489de2952eSStefano Zampini PetscCall(PetscSFComputeDegreeBegin(graph->interface_subset_sf, °ree)); 16499de2952eSStefano Zampini PetscCall(PetscSFComputeDegreeEnd(graph->interface_subset_sf, °ree)); 16509de2952eSStefano Zampini for (PetscInt i = 0, c = 0; i < nr; i++) { 16519de2952eSStefano Zampini mmask[c] = 1; 16529de2952eSStefano Zampini c += degree[i]; 16539de2952eSStefano Zampini } 16549de2952eSStefano Zampini PetscCall(PetscSFScatterBegin(graph->interface_subset_sf, MPIU_INT, mmask, mask)); 16559de2952eSStefano Zampini PetscCall(PetscSFScatterEnd(graph->interface_subset_sf, MPIU_INT, mmask, mask)); 16569de2952eSStefano Zampini PetscCall(VecGetArray(v, &array)); 16579de2952eSStefano Zampini for (PetscInt i = 0; i < n; i++) { 16589de2952eSStefano Zampini array[i] *= mask[i]; 16599de2952eSStefano Zampini idxs[i] = i; 16609de2952eSStefano Zampini } 16619de2952eSStefano Zampini PetscCall(VecSetValuesLocal(quad_vec, n, idxs, array, ADD_VALUES)); 16629de2952eSStefano Zampini PetscCall(VecRestoreArray(v, &array)); 16639de2952eSStefano Zampini PetscCall(PetscFree3(mmask, mask, idxs)); 16649de2952eSStefano Zampini PetscCall(VecDestroy(&v)); 16659de2952eSStefano Zampini PetscCall(VecAssemblyBegin(quad_vec)); 16669de2952eSStefano Zampini PetscCall(VecAssemblyEnd(quad_vec)); 16679de2952eSStefano Zampini PetscCall(VecViewFromOptions(quad_vec, NULL, "-pc_bddc_quad_vec_view")); 16689de2952eSStefano Zampini PetscCall(VecLockReadPush(quad_vec)); 16699de2952eSStefano Zampini PetscCall(VecDestroy(&quad_vec)); 16703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1671669cc0f4SStefano Zampini } 1672669cc0f4SStefano Zampini 1673d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCAddPrimalVerticesLocalIS(PC pc, IS primalv) 1674d71ae5a4SJacob Faibussowitsch { 16757620a527SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 16767620a527SStefano Zampini 16777620a527SStefano Zampini PetscFunctionBegin; 16787620a527SStefano Zampini if (primalv) { 16797620a527SStefano Zampini if (pcbddc->user_primal_vertices_local) { 16807620a527SStefano Zampini IS list[2], newp; 16817620a527SStefano Zampini 16827620a527SStefano Zampini list[0] = primalv; 16837620a527SStefano Zampini list[1] = pcbddc->user_primal_vertices_local; 16849566063dSJacob Faibussowitsch PetscCall(ISConcatenate(PetscObjectComm((PetscObject)pc), 2, list, &newp)); 16859566063dSJacob Faibussowitsch PetscCall(ISSortRemoveDups(newp)); 16869566063dSJacob Faibussowitsch PetscCall(ISDestroy(&list[1])); 16877620a527SStefano Zampini pcbddc->user_primal_vertices_local = newp; 16887620a527SStefano Zampini } else { 16899566063dSJacob Faibussowitsch PetscCall(PCBDDCSetPrimalVerticesLocalIS(pc, primalv)); 16907620a527SStefano Zampini } 16917620a527SStefano Zampini } 16923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16937620a527SStefano Zampini } 1694669cc0f4SStefano Zampini 1695d71ae5a4SJacob Faibussowitsch static PetscErrorCode func_coords_private(PetscInt dim, PetscReal t, const PetscReal X[], PetscInt Nf, PetscScalar *out, void *ctx) 1696d71ae5a4SJacob Faibussowitsch { 16971c7a958bSStefano Zampini PetscInt f, *comp = (PetscInt *)ctx; 16981c7a958bSStefano Zampini 16991c7a958bSStefano Zampini PetscFunctionBegin; 17001c7a958bSStefano Zampini for (f = 0; f < Nf; f++) out[f] = X[*comp]; 17013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17021c7a958bSStefano Zampini } 1703674ae819SStefano Zampini 1704d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc) 1705d71ae5a4SJacob Faibussowitsch { 17061f4df5f7SStefano Zampini Vec local, global; 17071f4df5f7SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 17081f4df5f7SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 17095c5e10d6SStefano Zampini PetscBool monolithic = PETSC_FALSE; 17101f4df5f7SStefano Zampini 17111f4df5f7SStefano Zampini PetscFunctionBegin; 1712d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)pc), ((PetscObject)pc)->prefix, "BDDC topology options", "PC"); 17139566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_monolithic", "Discard any information on dofs splitting", NULL, monolithic, &monolithic, NULL)); 1714d0609cedSBarry Smith PetscOptionsEnd(); 17151f4df5f7SStefano Zampini /* need to convert from global to local topology information and remove references to information in global ordering */ 17169566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(pc->pmat, &global, NULL)); 17179566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(matis->A, &local, NULL)); 17189566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(global, PETSC_TRUE)); 17199566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(local, PETSC_TRUE)); 17206a8fc67bSStefano Zampini if (monolithic) { /* just get block size to properly compute vertices */ 172148a46eb9SPierre Jolivet if (pcbddc->vertex_size == 1) PetscCall(MatGetBlockSize(pc->pmat, &pcbddc->vertex_size)); 17226a8fc67bSStefano Zampini goto boundary; 17236a8fc67bSStefano Zampini } 17245c5e10d6SStefano Zampini 17251f4df5f7SStefano Zampini if (pcbddc->user_provided_isfordofs) { 17261f4df5f7SStefano Zampini if (pcbddc->n_ISForDofs) { 17271f4df5f7SStefano Zampini PetscInt i; 17280c85b387SStefano Zampini 17299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->n_ISForDofs, &pcbddc->ISForDofsLocal)); 17301f4df5f7SStefano Zampini for (i = 0; i < pcbddc->n_ISForDofs; i++) { 17310c85b387SStefano Zampini PetscInt bs; 17320c85b387SStefano Zampini 17339566063dSJacob Faibussowitsch PetscCall(PCBDDCGlobalToLocal(matis->rctx, global, local, pcbddc->ISForDofs[i], &pcbddc->ISForDofsLocal[i])); 17349566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(pcbddc->ISForDofs[i], &bs)); 17359566063dSJacob Faibussowitsch PetscCall(ISSetBlockSize(pcbddc->ISForDofsLocal[i], bs)); 17369566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->ISForDofs[i])); 17371f4df5f7SStefano Zampini } 17381f4df5f7SStefano Zampini pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs; 17391f4df5f7SStefano Zampini pcbddc->n_ISForDofs = 0; 17409566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->ISForDofs)); 17411f4df5f7SStefano Zampini } 17421f4df5f7SStefano Zampini } else { 174321ef3d20SStefano Zampini if (!pcbddc->n_ISForDofsLocal) { /* field split not present */ 174421ef3d20SStefano Zampini DM dm; 174521ef3d20SStefano Zampini 17469566063dSJacob Faibussowitsch PetscCall(MatGetDM(pc->pmat, &dm)); 174748a46eb9SPierre Jolivet if (!dm) PetscCall(PCGetDM(pc, &dm)); 174821ef3d20SStefano Zampini if (dm) { 174921ef3d20SStefano Zampini IS *fields; 175021ef3d20SStefano Zampini PetscInt nf, i; 17510c85b387SStefano Zampini 17529566063dSJacob Faibussowitsch PetscCall(DMCreateFieldDecomposition(dm, &nf, NULL, &fields, NULL)); 17539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nf, &pcbddc->ISForDofsLocal)); 175421ef3d20SStefano Zampini for (i = 0; i < nf; i++) { 17550c85b387SStefano Zampini PetscInt bs; 17560c85b387SStefano Zampini 17579566063dSJacob Faibussowitsch PetscCall(PCBDDCGlobalToLocal(matis->rctx, global, local, fields[i], &pcbddc->ISForDofsLocal[i])); 17589566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(fields[i], &bs)); 17599566063dSJacob Faibussowitsch PetscCall(ISSetBlockSize(pcbddc->ISForDofsLocal[i], bs)); 17609566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fields[i])); 176121ef3d20SStefano Zampini } 17629566063dSJacob Faibussowitsch PetscCall(PetscFree(fields)); 176321ef3d20SStefano Zampini pcbddc->n_ISForDofsLocal = nf; 176421ef3d20SStefano Zampini } else { /* See if MATIS has fields attached by the conversion from MatNest */ 176521ef3d20SStefano Zampini PetscContainer c; 176621ef3d20SStefano Zampini 17679566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc->pmat, "_convert_nest_lfields", (PetscObject *)&c)); 176821ef3d20SStefano Zampini if (c) { 176921ef3d20SStefano Zampini MatISLocalFields lf; 17709566063dSJacob Faibussowitsch PetscCall(PetscContainerGetPointer(c, (void **)&lf)); 17719566063dSJacob Faibussowitsch PetscCall(PCBDDCSetDofsSplittingLocal(pc, lf->nr, lf->rf)); 177221ef3d20SStefano Zampini } else { /* fallback, create the default fields if bs > 1 */ 17731f4df5f7SStefano Zampini PetscInt i, n = matis->A->rmap->n; 17749566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(pc->pmat, &i)); 177521ef3d20SStefano Zampini if (i > 1) { 1776986cdee1SStefano Zampini pcbddc->n_ISForDofsLocal = i; 17779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->n_ISForDofsLocal, &pcbddc->ISForDofsLocal)); 177848a46eb9SPierre 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])); 17791f4df5f7SStefano Zampini } 178021ef3d20SStefano Zampini } 178121ef3d20SStefano Zampini } 17827a0e7b2cSstefano_zampini } else { 17837a0e7b2cSstefano_zampini PetscInt i; 178448a46eb9SPierre Jolivet for (i = 0; i < pcbddc->n_ISForDofsLocal; i++) PetscCall(PCBDDCConsistencyCheckIS(pc, MPI_LAND, &pcbddc->ISForDofsLocal[i])); 17851f4df5f7SStefano Zampini } 1786986cdee1SStefano Zampini } 17871f4df5f7SStefano Zampini 17885c5e10d6SStefano Zampini boundary: 17891f4df5f7SStefano Zampini if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) { 17909566063dSJacob Faibussowitsch PetscCall(PCBDDCGlobalToLocal(matis->rctx, global, local, pcbddc->DirichletBoundaries, &pcbddc->DirichletBoundariesLocal)); 17917a0e7b2cSstefano_zampini } else if (pcbddc->DirichletBoundariesLocal) { 17929566063dSJacob Faibussowitsch PetscCall(PCBDDCConsistencyCheckIS(pc, MPI_LAND, &pcbddc->DirichletBoundariesLocal)); 17931f4df5f7SStefano Zampini } 17941f4df5f7SStefano Zampini if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) { 17959566063dSJacob Faibussowitsch PetscCall(PCBDDCGlobalToLocal(matis->rctx, global, local, pcbddc->NeumannBoundaries, &pcbddc->NeumannBoundariesLocal)); 17967a0e7b2cSstefano_zampini } else if (pcbddc->NeumannBoundariesLocal) { 17979566063dSJacob Faibussowitsch PetscCall(PCBDDCConsistencyCheckIS(pc, MPI_LOR, &pcbddc->NeumannBoundariesLocal)); 17981f4df5f7SStefano Zampini } 179948a46eb9SPierre 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)); 18009566063dSJacob Faibussowitsch PetscCall(VecDestroy(&global)); 18019566063dSJacob Faibussowitsch PetscCall(VecDestroy(&local)); 18029de2952eSStefano Zampini /* detect local disconnected subdomains if requested or needed */ 18039de2952eSStefano Zampini if (pcbddc->detect_disconnected || matis->allow_repeated) { 18047620a527SStefano Zampini IS primalv = NULL; 18050b61a303SStefano Zampini PetscInt nel; 18068361f951SStefano Zampini PetscBool filter = pcbddc->detect_disconnected_filter; 18077a0e7b2cSstefano_zampini 18080b61a303SStefano Zampini for (PetscInt i = 0; i < pcbddc->n_local_subs; i++) PetscCall(ISDestroy(&pcbddc->local_subs[i])); 18099566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->local_subs)); 18100b61a303SStefano Zampini PetscCall(MatGetVariableBlockSizes(matis->A, &nel, NULL)); 18110b61a303SStefano Zampini if (matis->allow_repeated && nel) { 18120b61a303SStefano Zampini const PetscInt *elsizes; 18130b61a303SStefano Zampini 18140b61a303SStefano Zampini pcbddc->n_local_subs = nel; 18150b61a303SStefano Zampini PetscCall(MatGetVariableBlockSizes(matis->A, NULL, &elsizes)); 18160b61a303SStefano Zampini PetscCall(PetscMalloc1(nel, &pcbddc->local_subs)); 18170b61a303SStefano Zampini for (PetscInt i = 0, c = 0; i < nel; i++) { 18180b61a303SStefano Zampini PetscCall(ISCreateStride(PETSC_COMM_SELF, elsizes[i], c, 1, &pcbddc->local_subs[i])); 18190b61a303SStefano Zampini c += elsizes[i]; 18200b61a303SStefano Zampini } 18210b61a303SStefano Zampini } else { 18229566063dSJacob Faibussowitsch PetscCall(PCBDDCDetectDisconnectedComponents(pc, filter, &pcbddc->n_local_subs, &pcbddc->local_subs, &primalv)); 18230b61a303SStefano Zampini } 18249566063dSJacob Faibussowitsch PetscCall(PCBDDCAddPrimalVerticesLocalIS(pc, primalv)); 18259566063dSJacob Faibussowitsch PetscCall(ISDestroy(&primalv)); 18267620a527SStefano Zampini } 18277620a527SStefano Zampini /* early stage corner detection */ 18287620a527SStefano Zampini { 18297620a527SStefano Zampini DM dm; 18307620a527SStefano Zampini 18319566063dSJacob Faibussowitsch PetscCall(MatGetDM(pc->pmat, &dm)); 183248a46eb9SPierre Jolivet if (!dm) PetscCall(PCGetDM(pc, &dm)); 18337620a527SStefano Zampini if (dm) { 18347620a527SStefano Zampini PetscBool isda; 18357620a527SStefano Zampini 18369566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMDA, &isda)); 18377620a527SStefano Zampini if (isda) { 18387620a527SStefano Zampini ISLocalToGlobalMapping l2l; 18397620a527SStefano Zampini IS corners; 18407620a527SStefano Zampini Mat lA; 18414f819b78SStefano Zampini PetscBool gl, lo; 18427620a527SStefano Zampini 18434f819b78SStefano Zampini { 18444f819b78SStefano Zampini Vec cvec; 18454f819b78SStefano Zampini const PetscScalar *coords; 18464f819b78SStefano Zampini PetscInt dof, n, cdim; 18474f819b78SStefano Zampini PetscBool memc = PETSC_TRUE; 18484f819b78SStefano Zampini 18499566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL)); 18509566063dSJacob Faibussowitsch PetscCall(DMGetCoordinates(dm, &cvec)); 18519566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(cvec, &n)); 18529566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(cvec, &cdim)); 18534f819b78SStefano Zampini n /= cdim; 18549566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->mat_graph->coords)); 18559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dof * n * cdim, &pcbddc->mat_graph->coords)); 18569566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cvec, &coords)); 18574f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX) 18584f819b78SStefano Zampini memc = PETSC_FALSE; 18594f819b78SStefano Zampini #endif 18604f819b78SStefano Zampini if (dof != 1) memc = PETSC_FALSE; 18614f819b78SStefano Zampini if (memc) { 18629566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pcbddc->mat_graph->coords, coords, cdim * n * dof)); 18634f819b78SStefano Zampini } else { /* BDDC graph does not use any blocked information, we need to replicate the data */ 18644f819b78SStefano Zampini PetscReal *bcoords = pcbddc->mat_graph->coords; 18654f819b78SStefano Zampini PetscInt i, b, d; 18664f819b78SStefano Zampini 18674f819b78SStefano Zampini for (i = 0; i < n; i++) { 18684f819b78SStefano Zampini for (b = 0; b < dof; b++) { 1869ad540459SPierre Jolivet for (d = 0; d < cdim; d++) bcoords[i * dof * cdim + b * cdim + d] = PetscRealPart(coords[i * cdim + d]); 18704f819b78SStefano Zampini } 18714f819b78SStefano Zampini } 18724f819b78SStefano Zampini } 18739566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(cvec, &coords)); 18744f819b78SStefano Zampini pcbddc->mat_graph->cdim = cdim; 18754f819b78SStefano Zampini pcbddc->mat_graph->cnloc = dof * n; 18764f819b78SStefano Zampini pcbddc->mat_graph->cloc = PETSC_FALSE; 18774f819b78SStefano Zampini } 18789566063dSJacob Faibussowitsch PetscCall(DMDAGetSubdomainCornersIS(dm, &corners)); 18799566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->pmat, &lA)); 18809566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(lA, &l2l, NULL)); 18819566063dSJacob Faibussowitsch PetscCall(MatISRestoreLocalMat(pc->pmat, &lA)); 18824f819b78SStefano Zampini lo = (PetscBool)(l2l && corners); 1883462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&lo, &gl, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)pc))); 18844f819b78SStefano Zampini if (gl) { /* From PETSc's DMDA */ 18857620a527SStefano Zampini const PetscInt *idx; 188672ed36d8SStefano Zampini PetscInt dof, bs, *idxout, n; 18877620a527SStefano Zampini 18889566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL)); 18899566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(l2l, &bs)); 18909566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(corners, &n)); 18919566063dSJacob Faibussowitsch PetscCall(ISGetIndices(corners, &idx)); 189272ed36d8SStefano Zampini if (bs == dof) { 18939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &idxout)); 18949566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(l2l, n, idx, idxout)); 189572ed36d8SStefano Zampini } else { /* the original DMDA local-to-local map have been modified */ 189672ed36d8SStefano Zampini PetscInt i, d; 189772ed36d8SStefano Zampini 18989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dof * n, &idxout)); 18999371c9d4SSatish Balay for (i = 0; i < n; i++) 19009371c9d4SSatish Balay for (d = 0; d < dof; d++) idxout[dof * i + d] = dof * idx[i] + d; 19019566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(l2l, dof * n, idxout, idxout)); 190272ed36d8SStefano Zampini 190372ed36d8SStefano Zampini bs = 1; 190472ed36d8SStefano Zampini n *= dof; 190572ed36d8SStefano Zampini } 19069566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(corners, &idx)); 19079566063dSJacob Faibussowitsch PetscCall(DMDARestoreSubdomainCornersIS(dm, &corners)); 19089566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)pc), bs, n, idxout, PETSC_OWN_POINTER, &corners)); 19099566063dSJacob Faibussowitsch PetscCall(PCBDDCAddPrimalVerticesLocalIS(pc, corners)); 19109566063dSJacob Faibussowitsch PetscCall(ISDestroy(&corners)); 19111c7a958bSStefano Zampini pcbddc->corner_selected = PETSC_TRUE; 19124f819b78SStefano Zampini pcbddc->corner_selection = PETSC_TRUE; 19134f819b78SStefano Zampini } 191448a46eb9SPierre Jolivet if (corners) PetscCall(DMDARestoreSubdomainCornersIS(dm, &corners)); 19157620a527SStefano Zampini } 19167620a527SStefano Zampini } 19177620a527SStefano Zampini } 19181c7a958bSStefano Zampini if (pcbddc->corner_selection && !pcbddc->mat_graph->cdim) { 19191c7a958bSStefano Zampini DM dm; 19201c7a958bSStefano Zampini 19219566063dSJacob Faibussowitsch PetscCall(MatGetDM(pc->pmat, &dm)); 192248a46eb9SPierre Jolivet if (!dm) PetscCall(PCGetDM(pc, &dm)); 19234f819b78SStefano Zampini if (dm) { /* this can get very expensive, I need to find a faster alternative */ 19241c7a958bSStefano Zampini Vec vcoords; 19251c7a958bSStefano Zampini PetscSection section; 19261c7a958bSStefano Zampini PetscReal *coords; 19271c7a958bSStefano Zampini PetscInt d, cdim, nl, nf, **ctxs; 19281c7a958bSStefano Zampini PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal *, PetscInt, PetscScalar *, void *); 192951ab8ad6SStefano Zampini /* debug coordinates */ 193051ab8ad6SStefano Zampini PetscViewer viewer; 193151ab8ad6SStefano Zampini PetscBool flg; 193251ab8ad6SStefano Zampini PetscViewerFormat format; 193351ab8ad6SStefano Zampini const char *prefix; 19341c7a958bSStefano Zampini 19359566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 19369566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 19379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &nf)); 19389566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dm, &vcoords)); 19399566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vcoords, &nl)); 19409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl * cdim, &coords)); 19419566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nf, &funcs, nf, &ctxs)); 19429566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nf, &ctxs[0])); 19431c7a958bSStefano Zampini for (d = 0; d < nf; d++) funcs[d] = func_coords_private; 19441c7a958bSStefano Zampini for (d = 1; d < nf; d++) ctxs[d] = ctxs[d - 1] + 1; 194551ab8ad6SStefano Zampini 194651ab8ad6SStefano Zampini /* debug coordinates */ 194751ab8ad6SStefano Zampini PetscCall(PCGetOptionsPrefix(pc, &prefix)); 1948648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)vcoords), ((PetscObject)vcoords)->options, prefix, "-pc_bddc_coords_vec_view", &viewer, &format, &flg)); 194951ab8ad6SStefano Zampini if (flg) PetscCall(PetscViewerPushFormat(viewer, format)); 19501c7a958bSStefano Zampini for (d = 0; d < cdim; d++) { 19511c7a958bSStefano Zampini PetscInt i; 19521c7a958bSStefano Zampini const PetscScalar *v; 195351ab8ad6SStefano Zampini char name[16]; 19541c7a958bSStefano Zampini 19551c7a958bSStefano Zampini for (i = 0; i < nf; i++) ctxs[i][0] = d; 1956835f2295SStefano Zampini PetscCall(PetscSNPrintf(name, sizeof(name), "bddc_coords_%" PetscInt_FMT, d)); 195751ab8ad6SStefano Zampini PetscCall(PetscObjectSetName((PetscObject)vcoords, name)); 19589566063dSJacob Faibussowitsch PetscCall(DMProjectFunction(dm, 0.0, funcs, (void **)ctxs, INSERT_VALUES, vcoords)); 195951ab8ad6SStefano Zampini if (flg) PetscCall(VecView(vcoords, viewer)); 19609566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vcoords, &v)); 19611c7a958bSStefano Zampini for (i = 0; i < nl; i++) coords[i * cdim + d] = PetscRealPart(v[i]); 19629566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vcoords, &v)); 19631c7a958bSStefano Zampini } 19649566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vcoords)); 19659566063dSJacob Faibussowitsch PetscCall(PCSetCoordinates(pc, cdim, nl, coords)); 19669566063dSJacob Faibussowitsch PetscCall(PetscFree(coords)); 19679566063dSJacob Faibussowitsch PetscCall(PetscFree(ctxs[0])); 19689566063dSJacob Faibussowitsch PetscCall(PetscFree2(funcs, ctxs)); 196951ab8ad6SStefano Zampini if (flg) { 197051ab8ad6SStefano Zampini PetscCall(PetscViewerPopFormat(viewer)); 1971648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&viewer)); 197251ab8ad6SStefano Zampini } 19731c7a958bSStefano Zampini } 19741c7a958bSStefano Zampini } 19753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19767a0e7b2cSstefano_zampini } 19777a0e7b2cSstefano_zampini 1978d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCConsistencyCheckIS(PC pc, MPI_Op mop, IS *is) 1979d71ae5a4SJacob Faibussowitsch { 1980f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)pc->pmat->data; 19817a0e7b2cSstefano_zampini IS nis; 19827a0e7b2cSstefano_zampini const PetscInt *idxs; 19837a0e7b2cSstefano_zampini PetscInt i, nd, n = matis->A->rmap->n, *nidxs, nnd; 19847a0e7b2cSstefano_zampini 19857a0e7b2cSstefano_zampini PetscFunctionBegin; 198657508eceSPierre Jolivet PetscCheck(mop == MPI_LAND || mop == MPI_LOR, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Supported are MPI_LAND and MPI_LOR"); 19877a0e7b2cSstefano_zampini if (mop == MPI_LAND) { 19887a0e7b2cSstefano_zampini /* init rootdata with true */ 19891bd50df1SStefano Zampini for (i = 0; i < pc->pmat->rmap->n; i++) matis->sf_rootdata[i] = 1; 19907a0e7b2cSstefano_zampini } else { 19919566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_rootdata, pc->pmat->rmap->n)); 19927a0e7b2cSstefano_zampini } 19939566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_leafdata, n)); 19949566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(*is, &nd)); 19959566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*is, &idxs)); 19967a0e7b2cSstefano_zampini for (i = 0; i < nd; i++) 19979371c9d4SSatish Balay if (-1 < idxs[i] && idxs[i] < n) matis->sf_leafdata[idxs[i]] = 1; 19989566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*is, &idxs)); 19999566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, matis->sf_leafdata, matis->sf_rootdata, mop)); 20009566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, matis->sf_leafdata, matis->sf_rootdata, mop)); 20019566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 20029566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 20037a0e7b2cSstefano_zampini if (mop == MPI_LAND) { 20049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nd, &nidxs)); 20057a0e7b2cSstefano_zampini } else { 20069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &nidxs)); 20077a0e7b2cSstefano_zampini } 20087a0e7b2cSstefano_zampini for (i = 0, nnd = 0; i < n; i++) 20099371c9d4SSatish Balay if (matis->sf_leafdata[i]) nidxs[nnd++] = i; 2010f4f49eeaSPierre Jolivet PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)*is), nnd, nidxs, PETSC_OWN_POINTER, &nis)); 20119566063dSJacob Faibussowitsch PetscCall(ISDestroy(is)); 20127a0e7b2cSstefano_zampini *is = nis; 20133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20141f4df5f7SStefano Zampini } 20151f4df5f7SStefano Zampini 2016d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignRemoveInterior(PC pc, Vec r, Vec z) 2017d71ae5a4SJacob Faibussowitsch { 2018f4f49eeaSPierre Jolivet PC_IS *pcis = (PC_IS *)pc->data; 2019f4f49eeaSPierre Jolivet PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 20203e589ea0SStefano Zampini 20213e589ea0SStefano Zampini PetscFunctionBegin; 20223ba16761SJacob Faibussowitsch if (!pcbddc->benign_have_null) PetscFunctionReturn(PETSC_SUCCESS); 20233e589ea0SStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 20243e589ea0SStefano Zampini Vec swap; 20253e589ea0SStefano Zampini 20269566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, r, pcbddc->work_change)); 20273e589ea0SStefano Zampini swap = pcbddc->work_change; 20283e589ea0SStefano Zampini pcbddc->work_change = r; 20293e589ea0SStefano Zampini r = swap; 20303e589ea0SStefano Zampini } 20319566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 20329566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 20339566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 20349566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D)); 20359566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 20369566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D)); 20379566063dSJacob Faibussowitsch PetscCall(VecSet(z, 0.)); 20389566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE)); 20399566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE)); 20403e589ea0SStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 2041f913dca9SStefano Zampini pcbddc->work_change = r; 20429566063dSJacob Faibussowitsch PetscCall(VecCopy(z, pcbddc->work_change)); 20439566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcbddc->work_change, z)); 20443e589ea0SStefano Zampini } 20453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20463e589ea0SStefano Zampini } 20473e589ea0SStefano Zampini 2048ba38deedSJacob Faibussowitsch static PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose) 2049d71ae5a4SJacob Faibussowitsch { 2050a3df083aSStefano Zampini PCBDDCBenignMatMult_ctx ctx; 2051a3df083aSStefano Zampini PetscBool apply_right, apply_left, reset_x; 2052a3df083aSStefano Zampini 2053a3df083aSStefano Zampini PetscFunctionBegin; 20549566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(A, &ctx)); 2055a3df083aSStefano Zampini if (transpose) { 2056a3df083aSStefano Zampini apply_right = ctx->apply_left; 2057a3df083aSStefano Zampini apply_left = ctx->apply_right; 2058a3df083aSStefano Zampini } else { 2059a3df083aSStefano Zampini apply_right = ctx->apply_right; 2060a3df083aSStefano Zampini apply_left = ctx->apply_left; 2061a3df083aSStefano Zampini } 2062a3df083aSStefano Zampini reset_x = PETSC_FALSE; 2063a3df083aSStefano Zampini if (apply_right) { 2064a3df083aSStefano Zampini const PetscScalar *ax; 2065a3df083aSStefano Zampini PetscInt nl, i; 2066a3df083aSStefano Zampini 20679566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(x, &nl)); 20689566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &ax)); 20699566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(ctx->work, ax, nl)); 20709566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &ax)); 2071a3df083aSStefano Zampini for (i = 0; i < ctx->benign_n; i++) { 2072a3df083aSStefano Zampini PetscScalar sum, val; 2073a3df083aSStefano Zampini const PetscInt *idxs; 2074a3df083aSStefano Zampini PetscInt nz, j; 20759566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(ctx->benign_zerodiag_subs[i], &nz)); 20769566063dSJacob Faibussowitsch PetscCall(ISGetIndices(ctx->benign_zerodiag_subs[i], &idxs)); 2077a3df083aSStefano Zampini sum = 0.; 2078a3df083aSStefano Zampini if (ctx->apply_p0) { 2079a3df083aSStefano Zampini val = ctx->work[idxs[nz - 1]]; 2080a3df083aSStefano Zampini for (j = 0; j < nz - 1; j++) { 2081a3df083aSStefano Zampini sum += ctx->work[idxs[j]]; 2082a3df083aSStefano Zampini ctx->work[idxs[j]] += val; 2083a3df083aSStefano Zampini } 2084a3df083aSStefano Zampini } else { 2085ad540459SPierre Jolivet for (j = 0; j < nz - 1; j++) sum += ctx->work[idxs[j]]; 2086a3df083aSStefano Zampini } 2087a3df083aSStefano Zampini ctx->work[idxs[nz - 1]] -= sum; 20889566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(ctx->benign_zerodiag_subs[i], &idxs)); 2089a3df083aSStefano Zampini } 20909566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(x, ctx->work)); 2091a3df083aSStefano Zampini reset_x = PETSC_TRUE; 2092a3df083aSStefano Zampini } 2093a3df083aSStefano Zampini if (transpose) { 20949566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(ctx->A, x, y)); 2095a3df083aSStefano Zampini } else { 20969566063dSJacob Faibussowitsch PetscCall(MatMult(ctx->A, x, y)); 2097a3df083aSStefano Zampini } 20981baa6e33SBarry Smith if (reset_x) PetscCall(VecResetArray(x)); 2099a3df083aSStefano Zampini if (apply_left) { 2100a3df083aSStefano Zampini PetscScalar *ay; 2101a3df083aSStefano Zampini PetscInt i; 2102a3df083aSStefano Zampini 21039566063dSJacob Faibussowitsch PetscCall(VecGetArray(y, &ay)); 2104a3df083aSStefano Zampini for (i = 0; i < ctx->benign_n; i++) { 2105a3df083aSStefano Zampini PetscScalar sum, val; 2106a3df083aSStefano Zampini const PetscInt *idxs; 2107a3df083aSStefano Zampini PetscInt nz, j; 21089566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(ctx->benign_zerodiag_subs[i], &nz)); 21099566063dSJacob Faibussowitsch PetscCall(ISGetIndices(ctx->benign_zerodiag_subs[i], &idxs)); 2110a3df083aSStefano Zampini val = -ay[idxs[nz - 1]]; 2111a3df083aSStefano Zampini if (ctx->apply_p0) { 2112a3df083aSStefano Zampini sum = 0.; 2113a3df083aSStefano Zampini for (j = 0; j < nz - 1; j++) { 2114a3df083aSStefano Zampini sum += ay[idxs[j]]; 2115a3df083aSStefano Zampini ay[idxs[j]] += val; 2116a3df083aSStefano Zampini } 2117a3df083aSStefano Zampini ay[idxs[nz - 1]] += sum; 2118a3df083aSStefano Zampini } else { 2119ad540459SPierre Jolivet for (j = 0; j < nz - 1; j++) ay[idxs[j]] += val; 2120a3df083aSStefano Zampini ay[idxs[nz - 1]] = 0.; 2121a3df083aSStefano Zampini } 21229566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(ctx->benign_zerodiag_subs[i], &idxs)); 2123a3df083aSStefano Zampini } 21249566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(y, &ay)); 2125a3df083aSStefano Zampini } 21263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2127a3df083aSStefano Zampini } 2128a3df083aSStefano Zampini 2129ba38deedSJacob Faibussowitsch static PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y) 2130d71ae5a4SJacob Faibussowitsch { 2131a3df083aSStefano Zampini PetscFunctionBegin; 21329566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignMatMult_Private_Private(A, x, y, PETSC_TRUE)); 21333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2134a3df083aSStefano Zampini } 2135a3df083aSStefano Zampini 2136ba38deedSJacob Faibussowitsch static PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y) 2137d71ae5a4SJacob Faibussowitsch { 2138a3df083aSStefano Zampini PetscFunctionBegin; 21399566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignMatMult_Private_Private(A, x, y, PETSC_FALSE)); 21403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2141a3df083aSStefano Zampini } 2142a3df083aSStefano Zampini 2143d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore) 2144d71ae5a4SJacob Faibussowitsch { 2145a3df083aSStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 2146a3df083aSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 2147a3df083aSStefano Zampini PCBDDCBenignMatMult_ctx ctx; 2148a3df083aSStefano Zampini 2149a3df083aSStefano Zampini PetscFunctionBegin; 2150a3df083aSStefano Zampini if (!restore) { 21511dd7afcfSStefano Zampini Mat A_IB, A_BI; 2152a3df083aSStefano Zampini PetscScalar *work; 2153b334f244SStefano Zampini PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL; 2154a3df083aSStefano Zampini 215528b400f6SJacob Faibussowitsch PetscCheck(!pcbddc->benign_original_mat, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Benign original mat has not been restored"); 21563ba16761SJacob Faibussowitsch if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(PETSC_SUCCESS); 21579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n, &work)); 21589566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &A_IB)); 21599566063dSJacob Faibussowitsch PetscCall(MatSetSizes(A_IB, pcis->n - pcis->n_B, pcis->n_B, PETSC_DECIDE, PETSC_DECIDE)); 21609566063dSJacob Faibussowitsch PetscCall(MatSetType(A_IB, MATSHELL)); 21619566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(A_IB, MATOP_MULT, (void (*)(void))PCBDDCBenignMatMult_Private)); 21629566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(A_IB, MATOP_MULT_TRANSPOSE, (void (*)(void))PCBDDCBenignMatMultTranspose_Private)); 21639566063dSJacob Faibussowitsch PetscCall(PetscNew(&ctx)); 21649566063dSJacob Faibussowitsch PetscCall(MatShellSetContext(A_IB, ctx)); 2165a3df083aSStefano Zampini ctx->apply_left = PETSC_TRUE; 2166a3df083aSStefano Zampini ctx->apply_right = PETSC_FALSE; 2167a3df083aSStefano Zampini ctx->apply_p0 = PETSC_FALSE; 2168a3df083aSStefano Zampini ctx->benign_n = pcbddc->benign_n; 2169059032f7SStefano Zampini if (reuse) { 2170a3df083aSStefano Zampini ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs; 21711dd7afcfSStefano Zampini ctx->free = PETSC_FALSE; 2172059032f7SStefano Zampini } else { /* TODO: could be optimized for successive solves */ 2173059032f7SStefano Zampini ISLocalToGlobalMapping N_to_D; 2174059032f7SStefano Zampini PetscInt i; 2175059032f7SStefano Zampini 21769566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(pcis->is_I_local, &N_to_D)); 21779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->benign_n, &ctx->benign_zerodiag_subs)); 217848a46eb9SPierre 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])); 21799566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&N_to_D)); 21801dd7afcfSStefano Zampini ctx->free = PETSC_TRUE; 2181059032f7SStefano Zampini } 2182a3df083aSStefano Zampini ctx->A = pcis->A_IB; 2183a3df083aSStefano Zampini ctx->work = work; 21849566063dSJacob Faibussowitsch PetscCall(MatSetUp(A_IB)); 21859566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A_IB, MAT_FINAL_ASSEMBLY)); 21869566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A_IB, MAT_FINAL_ASSEMBLY)); 2187a3df083aSStefano Zampini pcis->A_IB = A_IB; 2188a3df083aSStefano Zampini 2189a3df083aSStefano Zampini /* A_BI as A_IB^T */ 21909566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(A_IB, &A_BI)); 2191a3df083aSStefano Zampini pcbddc->benign_original_mat = pcis->A_BI; 2192a3df083aSStefano Zampini pcis->A_BI = A_BI; 2193a3df083aSStefano Zampini } else { 21943ba16761SJacob Faibussowitsch if (!pcbddc->benign_original_mat) PetscFunctionReturn(PETSC_SUCCESS); 21959566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(pcis->A_IB, &ctx)); 21969566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_IB)); 2197a3df083aSStefano Zampini pcis->A_IB = ctx->A; 21981dd7afcfSStefano Zampini ctx->A = NULL; 21999566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_BI)); 22001dd7afcfSStefano Zampini pcis->A_BI = pcbddc->benign_original_mat; 22011dd7afcfSStefano Zampini pcbddc->benign_original_mat = NULL; 22021dd7afcfSStefano Zampini if (ctx->free) { 2203059032f7SStefano Zampini PetscInt i; 220448a46eb9SPierre Jolivet for (i = 0; i < ctx->benign_n; i++) PetscCall(ISDestroy(&ctx->benign_zerodiag_subs[i])); 22059566063dSJacob Faibussowitsch PetscCall(PetscFree(ctx->benign_zerodiag_subs)); 2206059032f7SStefano Zampini } 22079566063dSJacob Faibussowitsch PetscCall(PetscFree(ctx->work)); 22089566063dSJacob Faibussowitsch PetscCall(PetscFree(ctx)); 2209a3df083aSStefano Zampini } 22103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2211a3df083aSStefano Zampini } 2212a3df083aSStefano Zampini 2213a3df083aSStefano Zampini /* used just in bddc debug mode */ 2214ba38deedSJacob Faibussowitsch static PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B) 2215d71ae5a4SJacob Faibussowitsch { 2216a3df083aSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 2217a3df083aSStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 2218a3df083aSStefano Zampini Mat An; 2219a3df083aSStefano Zampini 2220a3df083aSStefano Zampini PetscFunctionBegin; 22219566063dSJacob Faibussowitsch PetscCall(MatPtAP(matis->A, pcbddc->benign_change, MAT_INITIAL_MATRIX, 2.0, &An)); 22229566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns(An, pcbddc->benign_n, pcbddc->benign_p0_lidx, 1.0, NULL, NULL)); 2223a3df083aSStefano Zampini if (is1) { 22249566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(An, is1, is2, MAT_INITIAL_MATRIX, B)); 22259566063dSJacob Faibussowitsch PetscCall(MatDestroy(&An)); 2226a3df083aSStefano Zampini } else { 2227a3df083aSStefano Zampini *B = An; 2228a3df083aSStefano Zampini } 22293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2230a3df083aSStefano Zampini } 2231a3df083aSStefano Zampini 22321cf9b237SStefano Zampini /* TODO: add reuse flag */ 2233d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B) 2234d71ae5a4SJacob Faibussowitsch { 22351cf9b237SStefano Zampini Mat Bt; 22361cf9b237SStefano Zampini PetscScalar *a, *bdata; 22371cf9b237SStefano Zampini const PetscInt *ii, *ij; 22381cf9b237SStefano Zampini PetscInt m, n, i, nnz, *bii, *bij; 22391cf9b237SStefano Zampini PetscBool flg_row; 22401cf9b237SStefano Zampini 22411cf9b237SStefano Zampini PetscFunctionBegin; 22429566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &n, &m)); 22439566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &ij, &flg_row)); 22449566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &a)); 22451cf9b237SStefano Zampini nnz = n; 22461cf9b237SStefano Zampini for (i = 0; i < ii[n]; i++) { 22471cf9b237SStefano Zampini if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++; 22481cf9b237SStefano Zampini } 22499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n + 1, &bii)); 22509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &bij)); 22519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &bdata)); 22521cf9b237SStefano Zampini nnz = 0; 22531cf9b237SStefano Zampini bii[0] = 0; 22541cf9b237SStefano Zampini for (i = 0; i < n; i++) { 22551cf9b237SStefano Zampini PetscInt j; 22561cf9b237SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 22571cf9b237SStefano Zampini PetscScalar entry = a[j]; 22583272d46bSStefano Zampini if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || (n == m && ij[j] == i)) { 22591cf9b237SStefano Zampini bij[nnz] = ij[j]; 22601cf9b237SStefano Zampini bdata[nnz] = entry; 22611cf9b237SStefano Zampini nnz++; 22621cf9b237SStefano Zampini } 22631cf9b237SStefano Zampini } 22641cf9b237SStefano Zampini bii[i + 1] = nnz; 22651cf9b237SStefano Zampini } 22669566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &a)); 22679566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A), n, m, bii, bij, bdata, &Bt)); 22689566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &ij, &flg_row)); 22691cf9b237SStefano Zampini { 2270f4f49eeaSPierre Jolivet Mat_SeqAIJ *b = (Mat_SeqAIJ *)Bt->data; 22711cf9b237SStefano Zampini b->free_a = PETSC_TRUE; 22721cf9b237SStefano Zampini b->free_ij = PETSC_TRUE; 22731cf9b237SStefano Zampini } 227448a46eb9SPierre Jolivet if (*B == A) PetscCall(MatDestroy(&A)); 22751cf9b237SStefano Zampini *B = Bt; 22763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22771cf9b237SStefano Zampini } 22781cf9b237SStefano Zampini 2279d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCDetectDisconnectedComponents(PC pc, PetscBool filter, PetscInt *ncc, IS *cc[], IS *primalv) 2280d71ae5a4SJacob Faibussowitsch { 2281c80a6c00SStefano Zampini Mat B = NULL; 2282c80a6c00SStefano Zampini DM dm; 22834f1b2e48SStefano Zampini IS is_dummy, *cc_n; 22844f1b2e48SStefano Zampini ISLocalToGlobalMapping l2gmap_dummy; 22854f1b2e48SStefano Zampini PCBDDCGraph graph; 2286c80a6c00SStefano Zampini PetscInt *xadj_filtered = NULL, *adjncy_filtered = NULL; 22874f1b2e48SStefano Zampini PetscInt i, n; 22884f1b2e48SStefano Zampini PetscInt *xadj, *adjncy; 2289c80a6c00SStefano Zampini PetscBool isplex = PETSC_FALSE; 22904f1b2e48SStefano Zampini 22914f1b2e48SStefano Zampini PetscFunctionBegin; 2292a2eca866SStefano Zampini if (ncc) *ncc = 0; 2293a2eca866SStefano Zampini if (cc) *cc = NULL; 2294a2eca866SStefano Zampini if (primalv) *primalv = NULL; 22959566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphCreate(&graph)); 22969566063dSJacob Faibussowitsch PetscCall(MatGetDM(pc->pmat, &dm)); 229748a46eb9SPierre Jolivet if (!dm) PetscCall(PCGetDM(pc, &dm)); 2298f9635d15SStefano Zampini if (dm) PetscCall(PetscObjectTypeCompareAny((PetscObject)dm, &isplex, DMPLEX, DMP4EST, DMP8EST, "")); 22998361f951SStefano Zampini if (filter) isplex = PETSC_FALSE; 23008361f951SStefano Zampini 2301c80a6c00SStefano Zampini if (isplex) { /* this code has been modified from plexpartition.c */ 2302c80a6c00SStefano Zampini PetscInt p, pStart, pEnd, a, adjSize, idx, size, nroots; 2303c80a6c00SStefano Zampini PetscInt *adj = NULL; 2304c80a6c00SStefano Zampini IS cellNumbering; 2305c80a6c00SStefano Zampini const PetscInt *cellNum; 2306c80a6c00SStefano Zampini PetscBool useCone, useClosure; 2307c80a6c00SStefano Zampini PetscSection section; 2308c80a6c00SStefano Zampini PetscSegBuffer adjBuffer; 2309c80a6c00SStefano Zampini PetscSF sfPoint; 2310c80a6c00SStefano Zampini 2311f9635d15SStefano Zampini PetscCall(DMConvert(dm, DMPLEX, &dm)); 23129566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd)); 23139566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 23149566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL)); 2315c80a6c00SStefano Zampini /* Build adjacency graph via a section/segbuffer */ 23169566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 23179566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 23189566063dSJacob Faibussowitsch PetscCall(PetscSegBufferCreate(sizeof(PetscInt), 1000, &adjBuffer)); 2319c80a6c00SStefano Zampini /* Always use FVM adjacency to create partitioner graph */ 23209566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 23219566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE)); 23229566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellNumbering(dm, &cellNumbering)); 23239566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cellNumbering, &cellNum)); 2324c80a6c00SStefano Zampini for (n = 0, p = pStart; p < pEnd; p++) { 2325c80a6c00SStefano Zampini /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 23269371c9d4SSatish Balay if (nroots > 0) { 23279371c9d4SSatish Balay if (cellNum[p] < 0) continue; 23289371c9d4SSatish Balay } 2329c80a6c00SStefano Zampini adjSize = PETSC_DETERMINE; 23309566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj)); 2331c80a6c00SStefano Zampini for (a = 0; a < adjSize; ++a) { 2332c80a6c00SStefano Zampini const PetscInt point = adj[a]; 23335cef3d0dSStefano Zampini if (pStart <= point && point < pEnd) { 2334c80a6c00SStefano Zampini PetscInt *PETSC_RESTRICT pBuf; 23359566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(section, p, 1)); 23369566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGetInts(adjBuffer, 1, &pBuf)); 2337c80a6c00SStefano Zampini *pBuf = point; 2338c80a6c00SStefano Zampini } 2339c80a6c00SStefano Zampini } 2340c80a6c00SStefano Zampini n++; 2341c80a6c00SStefano Zampini } 23429566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dm, useCone, useClosure)); 2343c80a6c00SStefano Zampini /* Derive CSR graph from section/segbuffer */ 23449566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 23459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &size)); 23469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n + 1, &xadj)); 2347c80a6c00SStefano Zampini for (idx = 0, p = pStart; p < pEnd; p++) { 23489371c9d4SSatish Balay if (nroots > 0) { 23499371c9d4SSatish Balay if (cellNum[p] < 0) continue; 23509371c9d4SSatish Balay } 2351f4f49eeaSPierre Jolivet PetscCall(PetscSectionGetOffset(section, p, &xadj[idx++])); 2352c80a6c00SStefano Zampini } 2353c80a6c00SStefano Zampini xadj[n] = size; 23549566063dSJacob Faibussowitsch PetscCall(PetscSegBufferExtractAlloc(adjBuffer, &adjncy)); 2355c80a6c00SStefano Zampini /* Clean up */ 23569566063dSJacob Faibussowitsch PetscCall(PetscSegBufferDestroy(&adjBuffer)); 23579566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 23589566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 2359c80a6c00SStefano Zampini graph->xadj = xadj; 2360c80a6c00SStefano Zampini graph->adjncy = adjncy; 2361c80a6c00SStefano Zampini } else { 2362c80a6c00SStefano Zampini Mat A; 23638361f951SStefano Zampini PetscBool isseqaij, flg_row; 2364c80a6c00SStefano Zampini 23659566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->pmat, &A)); 236663c961adSStefano Zampini if (!A->rmap->N || !A->cmap->N) { 23679566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphDestroy(&graph)); 23683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 236963c961adSStefano Zampini } 23709566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isseqaij)); 23714f1b2e48SStefano Zampini if (!isseqaij && filter) { 23721cf9b237SStefano Zampini PetscBool isseqdense; 23731cf9b237SStefano Zampini 23749566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATSEQDENSE, &isseqdense)); 23751cf9b237SStefano Zampini if (!isseqdense) { 23769566063dSJacob Faibussowitsch PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &B)); 23771cf9b237SStefano Zampini } else { /* TODO: rectangular case and LDA */ 23781cf9b237SStefano Zampini PetscScalar *array; 23791cf9b237SStefano Zampini PetscReal chop = 1.e-6; 23801cf9b237SStefano Zampini 23819566063dSJacob Faibussowitsch PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &B)); 23829566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(B, &array)); 23839566063dSJacob Faibussowitsch PetscCall(MatGetSize(B, &n, NULL)); 23841cf9b237SStefano Zampini for (i = 0; i < n; i++) { 23851cf9b237SStefano Zampini PetscInt j; 23861cf9b237SStefano Zampini for (j = i + 1; j < n; j++) { 23871cf9b237SStefano Zampini PetscReal thresh = chop * (PetscAbsScalar(array[i * (n + 1)]) + PetscAbsScalar(array[j * (n + 1)])); 23881cf9b237SStefano Zampini if (PetscAbsScalar(array[i * n + j]) < thresh) array[i * n + j] = 0.; 23891cf9b237SStefano Zampini if (PetscAbsScalar(array[j * n + i]) < thresh) array[j * n + i] = 0.; 23901cf9b237SStefano Zampini } 23911cf9b237SStefano Zampini } 23929566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(B, &array)); 23939566063dSJacob Faibussowitsch PetscCall(MatConvert(B, MATSEQAIJ, MAT_INPLACE_MATRIX, &B)); 23941cf9b237SStefano Zampini } 23954f1b2e48SStefano Zampini } else { 23969566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 23974f1b2e48SStefano Zampini B = A; 23984f1b2e48SStefano Zampini } 23999566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(B, 0, PETSC_TRUE, PETSC_FALSE, &n, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &flg_row)); 24004f1b2e48SStefano Zampini 24014f1b2e48SStefano Zampini /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */ 24024f1b2e48SStefano Zampini if (filter) { 24034f1b2e48SStefano Zampini PetscScalar *data; 24044f1b2e48SStefano Zampini PetscInt j, cum; 24054f1b2e48SStefano Zampini 24069566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(n + 1, &xadj_filtered, xadj[n], &adjncy_filtered)); 24079566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(B, &data)); 24084f1b2e48SStefano Zampini cum = 0; 24094f1b2e48SStefano Zampini for (i = 0; i < n; i++) { 24104f1b2e48SStefano Zampini PetscInt t; 24114f1b2e48SStefano Zampini 24124f1b2e48SStefano Zampini for (j = xadj[i]; j < xadj[i + 1]; j++) { 2413ad540459SPierre Jolivet if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) continue; 24144f1b2e48SStefano Zampini adjncy_filtered[cum + xadj_filtered[i]++] = adjncy[j]; 24154f1b2e48SStefano Zampini } 24164f1b2e48SStefano Zampini t = xadj_filtered[i]; 24174f1b2e48SStefano Zampini xadj_filtered[i] = cum; 24184f1b2e48SStefano Zampini cum += t; 24194f1b2e48SStefano Zampini } 24209566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(B, &data)); 24214f1b2e48SStefano Zampini graph->xadj = xadj_filtered; 24224f1b2e48SStefano Zampini graph->adjncy = adjncy_filtered; 24234f1b2e48SStefano Zampini } else { 24244f1b2e48SStefano Zampini graph->xadj = xadj; 24254f1b2e48SStefano Zampini graph->adjncy = adjncy; 24264f1b2e48SStefano Zampini } 2427c80a6c00SStefano Zampini } 2428c80a6c00SStefano Zampini /* compute local connected components using PCBDDCGraph */ 24299de2952eSStefano Zampini graph->seq_graph = PETSC_TRUE; /* analyze local connected components (i.e. disconnected subdomains) irrespective of dofs count */ 24309566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, n, 0, 1, &is_dummy)); 24319566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is_dummy, &l2gmap_dummy)); 24329566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_dummy)); 24331690c2aeSBarry Smith PetscCall(PCBDDCGraphInit(graph, l2gmap_dummy, n, PETSC_INT_MAX)); 24349566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&l2gmap_dummy)); 24359566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphSetUp(graph, 1, NULL, NULL, 0, NULL, NULL)); 24369566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphComputeConnectedComponents(graph)); 2437c80a6c00SStefano Zampini 24384f1b2e48SStefano Zampini /* partial clean up */ 24399566063dSJacob Faibussowitsch PetscCall(PetscFree2(xadj_filtered, adjncy_filtered)); 2440c80a6c00SStefano Zampini if (B) { 2441c80a6c00SStefano Zampini PetscBool flg_row; 24429566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(B, 0, PETSC_TRUE, PETSC_FALSE, &n, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &flg_row)); 24439566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 24444f1b2e48SStefano Zampini } 2445c80a6c00SStefano Zampini if (isplex) { 24469566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 24479566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 2448c80a6c00SStefano Zampini } 24494f1b2e48SStefano Zampini 24504f1b2e48SStefano Zampini /* get back data */ 2451c80a6c00SStefano Zampini if (isplex) { 2452c80a6c00SStefano Zampini if (ncc) *ncc = graph->ncc; 2453c80a6c00SStefano Zampini if (cc || primalv) { 2454c80a6c00SStefano Zampini Mat A; 2455f9635d15SStefano Zampini PetscBT btv, btvt, btvc; 2456c80a6c00SStefano Zampini PetscSection subSection; 2457c80a6c00SStefano Zampini PetscInt *ids, cum, cump, *cids, *pids; 2458f9635d15SStefano Zampini PetscInt dim, cStart, cEnd, fStart, fEnd, vStart, vEnd, pStart, pEnd; 2459c80a6c00SStefano Zampini 2460f9635d15SStefano Zampini PetscCall(DMGetDimension(dm, &dim)); 24619566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubdomainSection(dm, &subSection)); 2462f9635d15SStefano Zampini PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 2463f9635d15SStefano Zampini PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 2464f9635d15SStefano Zampini PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 2465f9635d15SStefano Zampini PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 24669566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->pmat, &A)); 24679566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(A->rmap->n, &ids, graph->ncc + 1, &cids, A->rmap->n, &pids)); 24689566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(A->rmap->n, &btv)); 24699566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(A->rmap->n, &btvt)); 2470f9635d15SStefano Zampini PetscCall(PetscBTCreate(pEnd - pStart, &btvc)); 2471f9635d15SStefano Zampini 2472f9635d15SStefano Zampini /* First see if we find corners for the subdomains, i.e. a vertex 2473f9635d15SStefano Zampini shared by at least dim subdomain boundary faces. This does not 2474f9635d15SStefano Zampini cover all the possible cases with simplices but it is enough 2475f9635d15SStefano Zampini for tensor cells */ 2476f9635d15SStefano Zampini if (vStart != fStart && dim <= 3) { 2477f9635d15SStefano Zampini for (PetscInt c = cStart; c < cEnd; c++) { 2478f9635d15SStefano Zampini PetscInt nf, cnt = 0, mcnt = dim, *cfaces; 2479f9635d15SStefano Zampini const PetscInt *faces; 2480f9635d15SStefano Zampini 2481f9635d15SStefano Zampini PetscCall(DMPlexGetConeSize(dm, c, &nf)); 2482f9635d15SStefano Zampini PetscCall(DMGetWorkArray(dm, nf, MPIU_INT, &cfaces)); 2483f9635d15SStefano Zampini PetscCall(DMPlexGetCone(dm, c, &faces)); 2484f9635d15SStefano Zampini for (PetscInt f = 0; f < nf; f++) { 2485f9635d15SStefano Zampini PetscInt nc, ff; 2486f9635d15SStefano Zampini 2487f9635d15SStefano Zampini PetscCall(DMPlexGetSupportSize(dm, faces[f], &nc)); 2488f9635d15SStefano Zampini PetscCall(DMPlexGetTreeParent(dm, faces[f], &ff, NULL)); 2489f9635d15SStefano Zampini if (nc == 1 && faces[f] == ff) cfaces[cnt++] = faces[f]; 2490f9635d15SStefano Zampini } 2491f9635d15SStefano Zampini if (cnt >= mcnt) { 2492f9635d15SStefano Zampini PetscInt size, *closure = NULL; 2493f9635d15SStefano Zampini 2494f9635d15SStefano Zampini PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &size, &closure)); 2495f9635d15SStefano Zampini for (PetscInt k = 0; k < 2 * size; k += 2) { 2496f9635d15SStefano Zampini PetscInt v = closure[k]; 2497f9635d15SStefano Zampini if (v >= vStart && v < vEnd) { 2498f9635d15SStefano Zampini PetscInt vsize, *vclosure = NULL; 2499f9635d15SStefano Zampini 2500f9635d15SStefano Zampini cnt = 0; 2501f9635d15SStefano Zampini PetscCall(DMPlexGetTransitiveClosure(dm, v, PETSC_FALSE, &vsize, &vclosure)); 2502f9635d15SStefano Zampini for (PetscInt vk = 0; vk < 2 * vsize; vk += 2) { 2503f9635d15SStefano Zampini PetscInt f = vclosure[vk]; 2504f9635d15SStefano Zampini if (f >= fStart && f < fEnd) { 2505f9635d15SStefano Zampini PetscInt nc, ff; 2506f9635d15SStefano Zampini PetscBool valid = PETSC_FALSE; 2507f9635d15SStefano Zampini 2508f9635d15SStefano Zampini for (PetscInt fk = 0; fk < nf; fk++) 2509f9635d15SStefano Zampini if (f == cfaces[fk]) valid = PETSC_TRUE; 2510f9635d15SStefano Zampini if (!valid) continue; 2511f9635d15SStefano Zampini PetscCall(DMPlexGetSupportSize(dm, f, &nc)); 2512f9635d15SStefano Zampini PetscCall(DMPlexGetTreeParent(dm, f, &ff, NULL)); 2513f9635d15SStefano Zampini if (nc == 1 && f == ff) cnt++; 2514f9635d15SStefano Zampini } 2515f9635d15SStefano Zampini } 2516f9635d15SStefano Zampini if (cnt >= mcnt) PetscCall(PetscBTSet(btvc, v - pStart)); 2517f9635d15SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure(dm, v, PETSC_FALSE, &vsize, &vclosure)); 2518f9635d15SStefano Zampini } 2519f9635d15SStefano Zampini } 2520f9635d15SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &size, &closure)); 2521f9635d15SStefano Zampini } 2522f9635d15SStefano Zampini PetscCall(DMRestoreWorkArray(dm, nf, MPIU_INT, &cfaces)); 2523f9635d15SStefano Zampini } 2524f9635d15SStefano Zampini } 2525c80a6c00SStefano Zampini 2526c80a6c00SStefano Zampini cids[0] = 0; 2527c80a6c00SStefano Zampini for (i = 0, cump = 0, cum = 0; i < graph->ncc; i++) { 2528c80a6c00SStefano Zampini PetscInt j; 2529c80a6c00SStefano Zampini 25309566063dSJacob Faibussowitsch PetscCall(PetscBTMemzero(A->rmap->n, btvt)); 2531c80a6c00SStefano Zampini for (j = graph->cptr[i]; j < graph->cptr[i + 1]; j++) { 2532c80a6c00SStefano Zampini PetscInt k, size, *closure = NULL, cell = graph->queue[j]; 2533c80a6c00SStefano Zampini 25349566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &size, &closure)); 2535c80a6c00SStefano Zampini for (k = 0; k < 2 * size; k += 2) { 253620c3699dSStefano Zampini PetscInt s, pp, p = closure[k], off, dof, cdof; 2537c80a6c00SStefano Zampini 25389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(subSection, p, &cdof)); 25399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(subSection, p, &off)); 25409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subSection, p, &dof)); 2541c80a6c00SStefano Zampini for (s = 0; s < dof - cdof; s++) { 2542c80a6c00SStefano Zampini if (PetscBTLookupSet(btvt, off + s)) continue; 2543f9635d15SStefano Zampini if (PetscBTLookup(btvc, p - pStart)) pids[cump++] = off + s; /* subdomain corner */ 2544f9635d15SStefano Zampini else if (!PetscBTLookup(btv, off + s)) ids[cum++] = off + s; 2545e432b41dSStefano Zampini else pids[cump++] = off + s; /* cross-vertex */ 2546c80a6c00SStefano Zampini } 25479566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL)); 254820c3699dSStefano Zampini if (pp != p) { 25499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(subSection, pp, &cdof)); 25509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(subSection, pp, &off)); 25519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subSection, pp, &dof)); 255220c3699dSStefano Zampini for (s = 0; s < dof - cdof; s++) { 255320c3699dSStefano Zampini if (PetscBTLookupSet(btvt, off + s)) continue; 2554f9635d15SStefano Zampini if (PetscBTLookup(btvc, pp - pStart)) pids[cump++] = off + s; /* subdomain corner */ 2555f9635d15SStefano Zampini else if (!PetscBTLookup(btv, off + s)) ids[cum++] = off + s; 2556e432b41dSStefano Zampini else pids[cump++] = off + s; /* cross-vertex */ 255720c3699dSStefano Zampini } 255820c3699dSStefano Zampini } 2559c80a6c00SStefano Zampini } 25609566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &size, &closure)); 2561c80a6c00SStefano Zampini } 2562c80a6c00SStefano Zampini cids[i + 1] = cum; 2563c80a6c00SStefano Zampini /* mark dofs as already assigned */ 256448a46eb9SPierre Jolivet for (j = cids[i]; j < cids[i + 1]; j++) PetscCall(PetscBTSet(btv, ids[j])); 2565c80a6c00SStefano Zampini } 2566c80a6c00SStefano Zampini if (cc) { 25679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(graph->ncc, &cc_n)); 256848a46eb9SPierre 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])); 2569c80a6c00SStefano Zampini *cc = cc_n; 2570c80a6c00SStefano Zampini } 25711baa6e33SBarry Smith if (primalv) PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), cump, pids, PETSC_COPY_VALUES, primalv)); 25729566063dSJacob Faibussowitsch PetscCall(PetscFree3(ids, cids, pids)); 25739566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btv)); 25749566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btvt)); 2575f9635d15SStefano Zampini PetscCall(PetscBTDestroy(&btvc)); 2576f9635d15SStefano Zampini PetscCall(DMDestroy(&dm)); 2577c80a6c00SStefano Zampini } 2578c80a6c00SStefano Zampini } else { 25791cf9b237SStefano Zampini if (ncc) *ncc = graph->ncc; 25801cf9b237SStefano Zampini if (cc) { 25819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(graph->ncc, &cc_n)); 258248a46eb9SPierre 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])); 25834f1b2e48SStefano Zampini *cc = cc_n; 25841cf9b237SStefano Zampini } 2585c80a6c00SStefano Zampini } 25864f1b2e48SStefano Zampini /* clean up graph */ 25870a545947SLisandro Dalcin graph->xadj = NULL; 25880a545947SLisandro Dalcin graph->adjncy = NULL; 25899566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphDestroy(&graph)); 25903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25914f1b2e48SStefano Zampini } 25924f1b2e48SStefano Zampini 2593d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag) 2594d71ae5a4SJacob Faibussowitsch { 25955408967cSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 2596f4f49eeaSPierre Jolivet PC_IS *pcis = (PC_IS *)pc->data; 2597dee84bffSStefano Zampini IS dirIS = NULL; 25984f1b2e48SStefano Zampini PetscInt i; 25995408967cSStefano Zampini 26005408967cSStefano Zampini PetscFunctionBegin; 26019566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph, &dirIS)); 26025408967cSStefano Zampini if (zerodiag) { 26035408967cSStefano Zampini Mat A; 26045408967cSStefano Zampini Vec vec3_N; 26055408967cSStefano Zampini PetscScalar *vals; 26065408967cSStefano Zampini const PetscInt *idxs; 2607d12d3064SStefano Zampini PetscInt nz, *count; 26085408967cSStefano Zampini 26095408967cSStefano Zampini /* p0 */ 26109566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_N, 0.)); 26119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n, &vals)); 26129566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zerodiag, &nz)); 26139566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zerodiag, &idxs)); 26144f1b2e48SStefano Zampini for (i = 0; i < nz; i++) vals[i] = 1.; 26159566063dSJacob Faibussowitsch PetscCall(VecSetValues(pcis->vec1_N, nz, idxs, vals, INSERT_VALUES)); 26169566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(pcis->vec1_N)); 26179566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(pcis->vec1_N)); 26185408967cSStefano Zampini /* v_I */ 26199566063dSJacob Faibussowitsch PetscCall(VecSetRandom(pcis->vec2_N, NULL)); 26205408967cSStefano Zampini for (i = 0; i < nz; i++) vals[i] = 0.; 26219566063dSJacob Faibussowitsch PetscCall(VecSetValues(pcis->vec2_N, nz, idxs, vals, INSERT_VALUES)); 26229566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zerodiag, &idxs)); 26239566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_B_local, &idxs)); 26245408967cSStefano Zampini for (i = 0; i < pcis->n_B; i++) vals[i] = 0.; 26259566063dSJacob Faibussowitsch PetscCall(VecSetValues(pcis->vec2_N, pcis->n_B, idxs, vals, INSERT_VALUES)); 26269566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_B_local, &idxs)); 26275408967cSStefano Zampini if (dirIS) { 26285408967cSStefano Zampini PetscInt n; 26295408967cSStefano Zampini 26309566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(dirIS, &n)); 26319566063dSJacob Faibussowitsch PetscCall(ISGetIndices(dirIS, &idxs)); 26325408967cSStefano Zampini for (i = 0; i < n; i++) vals[i] = 0.; 26339566063dSJacob Faibussowitsch PetscCall(VecSetValues(pcis->vec2_N, n, idxs, vals, INSERT_VALUES)); 26349566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(dirIS, &idxs)); 26355408967cSStefano Zampini } 26369566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(pcis->vec2_N)); 26379566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(pcis->vec2_N)); 26389566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_N, &vec3_N)); 26399566063dSJacob Faibussowitsch PetscCall(VecSet(vec3_N, 0.)); 26409566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->pmat, &A)); 26419566063dSJacob Faibussowitsch PetscCall(MatMult(A, pcis->vec1_N, vec3_N)); 26429566063dSJacob Faibussowitsch PetscCall(VecDot(vec3_N, pcis->vec2_N, &vals[0])); 26437827d75bSBarry 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])); 26449566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 26459566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vec3_N)); 2646d12d3064SStefano Zampini 2647d12d3064SStefano Zampini /* there should not be any pressure dofs lying on the interface */ 26489566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pcis->n, &count)); 26499566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_B_local, &idxs)); 2650d12d3064SStefano Zampini for (i = 0; i < pcis->n_B; i++) count[idxs[i]]++; 26519566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_B_local, &idxs)); 26529566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zerodiag, &idxs)); 265363a3b9bcSJacob 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]); 26549566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zerodiag, &idxs)); 26559566063dSJacob Faibussowitsch PetscCall(PetscFree(count)); 26565408967cSStefano Zampini } 26579566063dSJacob Faibussowitsch PetscCall(ISDestroy(&dirIS)); 26585408967cSStefano Zampini 26595408967cSStefano Zampini /* check PCBDDCBenignGetOrSetP0 */ 26609566063dSJacob Faibussowitsch PetscCall(VecSetRandom(pcis->vec1_global, NULL)); 26614f1b2e48SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) pcbddc->benign_p0[i] = -PetscGlobalRank - i; 26629566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc, pcis->vec1_global, PETSC_FALSE)); 26634f1b2e48SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) pcbddc->benign_p0[i] = 1; 26649566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc, pcis->vec1_global, PETSC_TRUE)); 2665f2a566d8SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) { 2666f2a566d8SStefano Zampini PetscInt val = PetscRealPart(pcbddc->benign_p0[i]); 266763a3b9bcSJacob 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)); 2668f2a566d8SStefano Zampini } 26693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 26705408967cSStefano Zampini } 26715408967cSStefano Zampini 2672d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, PetscBool reuse, IS *zerodiaglocal) 2673d71ae5a4SJacob Faibussowitsch { 2674339f8db1SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 2675f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)pc->pmat->data; 26763b03f7bbSStefano Zampini IS pressures = NULL, zerodiag = NULL, *bzerodiag = NULL, zerodiag_save, *zerodiag_subs; 26773b03f7bbSStefano Zampini PetscInt nz, n, benign_n, bsp = 1; 26784edc6404Sstefano_zampini PetscInt *interior_dofs, n_interior_dofs, nneu; 26794edc6404Sstefano_zampini PetscBool sorted, have_null, has_null_pressures, recompute_zerodiag, checkb; 2680339f8db1SStefano Zampini 2681339f8db1SStefano Zampini PetscFunctionBegin; 26823b03f7bbSStefano Zampini if (reuse) goto project_b0; 26839566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pcbddc->benign_sf)); 26849566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->benign_B0)); 268548a46eb9SPierre Jolivet for (n = 0; n < pcbddc->benign_n; n++) PetscCall(ISDestroy(&pcbddc->benign_zerodiag_subs[n])); 26869566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->benign_zerodiag_subs)); 26873b03f7bbSStefano Zampini has_null_pressures = PETSC_TRUE; 26883b03f7bbSStefano Zampini have_null = PETSC_TRUE; 26893b03f7bbSStefano Zampini /* if a local information on dofs is present, gets pressure dofs from command line (uses the last field is not provided) 26903b03f7bbSStefano Zampini Without local information, it uses only the zerodiagonal dofs (ok if the pressure block is all zero and it is a scalar field) 26914f1b2e48SStefano Zampini Checks if all the pressure dofs in each subdomain have a zero diagonal 26924f1b2e48SStefano Zampini If not, a change of basis on pressures is not needed 26931ae86dd6SStefano Zampini since the local Schur complements are already SPD 26944f1b2e48SStefano Zampini */ 269540fa8d13SStefano Zampini if (pcbddc->n_ISForDofsLocal) { 26967fbe2174Sstefano_zampini IS iP = NULL; 26973b03f7bbSStefano Zampini PetscInt p, *pp; 269847c5ace7SStefano Zampini PetscBool flg, blocked = PETSC_FALSE; 26994f1b2e48SStefano Zampini 27009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->n_ISForDofsLocal, &pp)); 27013b03f7bbSStefano Zampini n = pcbddc->n_ISForDofsLocal; 2702d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)pc), ((PetscObject)pc)->prefix, "BDDC benign options", "PC"); 27039566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-pc_bddc_pressure_field", "Field id for pressures", NULL, pp, &n, &flg)); 270447c5ace7SStefano Zampini PetscCall(PetscOptionsBool("-pc_bddc_pressure_blocked", "Use blocked pressure fields", NULL, blocked, &blocked, NULL)); 2705d0609cedSBarry Smith PetscOptionsEnd(); 27063b03f7bbSStefano Zampini if (!flg) { 27073b03f7bbSStefano Zampini n = 1; 27083b03f7bbSStefano Zampini pp[0] = pcbddc->n_ISForDofsLocal - 1; 27093b03f7bbSStefano Zampini } 27103b03f7bbSStefano Zampini 27113b03f7bbSStefano Zampini bsp = 0; 27123b03f7bbSStefano Zampini for (p = 0; p < n; p++) { 271347c5ace7SStefano Zampini PetscInt bs = 1; 27143b03f7bbSStefano Zampini 271563a3b9bcSJacob 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]); 271647c5ace7SStefano Zampini if (blocked) PetscCall(ISGetBlockSize(pcbddc->ISForDofsLocal[pp[p]], &bs)); 27173b03f7bbSStefano Zampini bsp += bs; 27183b03f7bbSStefano Zampini } 27199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bsp, &bzerodiag)); 27203b03f7bbSStefano Zampini bsp = 0; 27213b03f7bbSStefano Zampini for (p = 0; p < n; p++) { 27223b03f7bbSStefano Zampini const PetscInt *idxs; 272347c5ace7SStefano Zampini PetscInt b, bs = 1, npl, *bidxs; 27243b03f7bbSStefano Zampini 272547c5ace7SStefano Zampini if (blocked) PetscCall(ISGetBlockSize(pcbddc->ISForDofsLocal[pp[p]], &bs)); 27269566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->ISForDofsLocal[pp[p]], &npl)); 27279566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->ISForDofsLocal[pp[p]], &idxs)); 27289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(npl / bs, &bidxs)); 27293b03f7bbSStefano Zampini for (b = 0; b < bs; b++) { 27303b03f7bbSStefano Zampini PetscInt i; 27313b03f7bbSStefano Zampini 27323b03f7bbSStefano Zampini for (i = 0; i < npl / bs; i++) bidxs[i] = idxs[bs * i + b]; 27339566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, npl / bs, bidxs, PETSC_COPY_VALUES, &bzerodiag[bsp])); 27343b03f7bbSStefano Zampini bsp++; 27353b03f7bbSStefano Zampini } 27369566063dSJacob Faibussowitsch PetscCall(PetscFree(bidxs)); 27379566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->ISForDofsLocal[pp[p]], &idxs)); 27383b03f7bbSStefano Zampini } 27399566063dSJacob Faibussowitsch PetscCall(ISConcatenate(PETSC_COMM_SELF, bsp, bzerodiag, &pressures)); 27403b03f7bbSStefano Zampini 27417fbe2174Sstefano_zampini /* remove zeroed out pressures if we are setting up a BDDC solver for a saddle-point FETI-DP */ 27429566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lP", (PetscObject *)&iP)); 27437fbe2174Sstefano_zampini if (iP) { 27447fbe2174Sstefano_zampini IS newpressures; 27457fbe2174Sstefano_zampini 27469566063dSJacob Faibussowitsch PetscCall(ISDifference(pressures, iP, &newpressures)); 27479566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pressures)); 27487fbe2174Sstefano_zampini pressures = newpressures; 27497fbe2174Sstefano_zampini } 27509566063dSJacob Faibussowitsch PetscCall(ISSorted(pressures, &sorted)); 275148a46eb9SPierre Jolivet if (!sorted) PetscCall(ISSort(pressures)); 27529566063dSJacob Faibussowitsch PetscCall(PetscFree(pp)); 275340fa8d13SStefano Zampini } 27543b03f7bbSStefano Zampini 275597d764eeSStefano Zampini /* pcis has not been setup yet, so get the local size from the subdomain matrix */ 27569566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pcbddc->local_mat, &n, NULL)); 275727b6a85dSStefano Zampini if (!n) pcbddc->benign_change_explicit = PETSC_TRUE; 27589566063dSJacob Faibussowitsch PetscCall(MatFindZeroDiagonals(pcbddc->local_mat, &zerodiag)); 27599566063dSJacob Faibussowitsch PetscCall(ISSorted(zerodiag, &sorted)); 276048a46eb9SPierre Jolivet if (!sorted) PetscCall(ISSort(zerodiag)); 27619566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)zerodiag)); 27624edc6404Sstefano_zampini zerodiag_save = zerodiag; 27639566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zerodiag, &nz)); 27644f1b2e48SStefano Zampini if (!nz) { 27654f1b2e48SStefano Zampini if (n) have_null = PETSC_FALSE; 27664f1b2e48SStefano Zampini has_null_pressures = PETSC_FALSE; 27679566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zerodiag)); 276840fa8d13SStefano Zampini } 27694f1b2e48SStefano Zampini recompute_zerodiag = PETSC_FALSE; 27703b03f7bbSStefano Zampini 27714f1b2e48SStefano Zampini /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */ 27724f1b2e48SStefano Zampini zerodiag_subs = NULL; 27733b03f7bbSStefano Zampini benign_n = 0; 27741f4df5f7SStefano Zampini n_interior_dofs = 0; 27751f4df5f7SStefano Zampini interior_dofs = NULL; 27764edc6404Sstefano_zampini nneu = 0; 277748a46eb9SPierre Jolivet if (pcbddc->NeumannBoundariesLocal) PetscCall(ISGetLocalSize(pcbddc->NeumannBoundariesLocal, &nneu)); 27783369cb78Sstefano_zampini checkb = (PetscBool)(!pcbddc->NeumannBoundariesLocal || pcbddc->current_level); 27794edc6404Sstefano_zampini if (checkb) { /* need to compute interior nodes */ 27809de2952eSStefano Zampini PetscInt n, i; 27819de2952eSStefano Zampini PetscInt *count; 27829de2952eSStefano Zampini ISLocalToGlobalMapping mapping; 27831f4df5f7SStefano Zampini 27849de2952eSStefano Zampini PetscCall(MatISGetLocalToGlobalMapping(pc->pmat, &mapping, NULL)); 27859de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingGetNodeInfo(mapping, &n, &count, NULL)); 27869566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &interior_dofs)); 27871f4df5f7SStefano Zampini for (i = 0; i < n; i++) 27889de2952eSStefano Zampini if (count[i] < 2) interior_dofs[n_interior_dofs++] = i; 27899de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(mapping, &n, &count, NULL)); 27901f4df5f7SStefano Zampini } 27914f1b2e48SStefano Zampini if (has_null_pressures) { 27924f1b2e48SStefano Zampini IS *subs; 27934edc6404Sstefano_zampini PetscInt nsubs, i, j, nl; 27941f4df5f7SStefano Zampini const PetscInt *idxs; 27951f4df5f7SStefano Zampini PetscScalar *array; 27961f4df5f7SStefano Zampini Vec *work; 27974f1b2e48SStefano Zampini 27984f1b2e48SStefano Zampini subs = pcbddc->local_subs; 27994f1b2e48SStefano Zampini nsubs = pcbddc->n_local_subs; 28001f4df5f7SStefano 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) */ 28014edc6404Sstefano_zampini if (checkb) { 28029566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(matis->y, 2, &work)); 28039566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zerodiag, &nl)); 28049566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zerodiag, &idxs)); 28051f4df5f7SStefano Zampini /* work[0] = 1_p */ 28069566063dSJacob Faibussowitsch PetscCall(VecSet(work[0], 0.)); 28079566063dSJacob Faibussowitsch PetscCall(VecGetArray(work[0], &array)); 28081f4df5f7SStefano Zampini for (j = 0; j < nl; j++) array[idxs[j]] = 1.; 28099566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(work[0], &array)); 28101f4df5f7SStefano Zampini /* work[0] = 1_v */ 28119566063dSJacob Faibussowitsch PetscCall(VecSet(work[1], 1.)); 28129566063dSJacob Faibussowitsch PetscCall(VecGetArray(work[1], &array)); 28131f4df5f7SStefano Zampini for (j = 0; j < nl; j++) array[idxs[j]] = 0.; 28149566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(work[1], &array)); 28159566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zerodiag, &idxs)); 28161f4df5f7SStefano Zampini } 28173b03f7bbSStefano Zampini 28183b03f7bbSStefano Zampini if (nsubs > 1 || bsp > 1) { 28193b03f7bbSStefano Zampini IS *is; 28203b03f7bbSStefano Zampini PetscInt b, totb; 28213b03f7bbSStefano Zampini 28223b03f7bbSStefano Zampini totb = bsp; 28233b03f7bbSStefano Zampini is = bsp > 1 ? bzerodiag : &zerodiag; 28243b03f7bbSStefano Zampini nsubs = PetscMax(nsubs, 1); 28259566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nsubs * totb, &zerodiag_subs)); 28263b03f7bbSStefano Zampini for (b = 0; b < totb; b++) { 28274f1b2e48SStefano Zampini for (i = 0; i < nsubs; i++) { 28284f1b2e48SStefano Zampini ISLocalToGlobalMapping l2g; 28294f1b2e48SStefano Zampini IS t_zerodiag_subs; 28304f1b2e48SStefano Zampini PetscInt nl; 28314f1b2e48SStefano Zampini 28323b03f7bbSStefano Zampini if (subs) { 28339566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(subs[i], &l2g)); 28343b03f7bbSStefano Zampini } else { 28353b03f7bbSStefano Zampini IS tis; 28363b03f7bbSStefano Zampini 28379566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pcbddc->local_mat, &nl, NULL)); 28389566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, nl, 0, 1, &tis)); 28399566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(tis, &l2g)); 28409566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tis)); 28413b03f7bbSStefano Zampini } 28429566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(l2g, IS_GTOLM_DROP, is[b], &t_zerodiag_subs)); 28439566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(t_zerodiag_subs, &nl)); 28444f1b2e48SStefano Zampini if (nl) { 28454f1b2e48SStefano Zampini PetscBool valid = PETSC_TRUE; 28464f1b2e48SStefano Zampini 28474edc6404Sstefano_zampini if (checkb) { 28489566063dSJacob Faibussowitsch PetscCall(VecSet(matis->x, 0)); 28499566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(subs[i], &nl)); 28509566063dSJacob Faibussowitsch PetscCall(ISGetIndices(subs[i], &idxs)); 28519566063dSJacob Faibussowitsch PetscCall(VecGetArray(matis->x, &array)); 28521f4df5f7SStefano Zampini for (j = 0; j < nl; j++) array[idxs[j]] = 1.; 28539566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(matis->x, &array)); 28549566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(subs[i], &idxs)); 28559566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(matis->x, work[0], matis->x)); 28569566063dSJacob Faibussowitsch PetscCall(MatMult(matis->A, matis->x, matis->y)); 28579566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(matis->y, work[1], matis->y)); 28589566063dSJacob Faibussowitsch PetscCall(VecGetArray(matis->y, &array)); 28591f4df5f7SStefano Zampini for (j = 0; j < n_interior_dofs; j++) { 28601f4df5f7SStefano Zampini if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) { 28611f4df5f7SStefano Zampini valid = PETSC_FALSE; 28621f4df5f7SStefano Zampini break; 28631f4df5f7SStefano Zampini } 28641f4df5f7SStefano Zampini } 28659566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(matis->y, &array)); 28661f4df5f7SStefano Zampini } 28676632bad2Sstefano_zampini if (valid && nneu) { 28686632bad2Sstefano_zampini const PetscInt *idxs; 28691f4df5f7SStefano Zampini PetscInt nzb; 28701f4df5f7SStefano Zampini 28719566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->NeumannBoundariesLocal, &idxs)); 28729566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(l2g, IS_GTOLM_DROP, nneu, idxs, &nzb, NULL)); 28739566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->NeumannBoundariesLocal, &idxs)); 28741f4df5f7SStefano Zampini if (nzb) valid = PETSC_FALSE; 28751f4df5f7SStefano Zampini } 28761f4df5f7SStefano Zampini if (valid && pressures) { 28773b03f7bbSStefano Zampini IS t_pressure_subs, tmp; 28783b03f7bbSStefano Zampini PetscInt i1, i2; 28793b03f7bbSStefano Zampini 28809566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(l2g, IS_GTOLM_DROP, pressures, &t_pressure_subs)); 28819566063dSJacob Faibussowitsch PetscCall(ISEmbed(t_zerodiag_subs, t_pressure_subs, PETSC_TRUE, &tmp)); 28829566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(tmp, &i1)); 28839566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(t_zerodiag_subs, &i2)); 28843b03f7bbSStefano Zampini if (i2 != i1) valid = PETSC_FALSE; 28859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&t_pressure_subs)); 28869566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tmp)); 28874f1b2e48SStefano Zampini } 28884f1b2e48SStefano Zampini if (valid) { 28899566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(l2g, t_zerodiag_subs, &zerodiag_subs[benign_n])); 28903b03f7bbSStefano Zampini benign_n++; 28913b03f7bbSStefano Zampini } else recompute_zerodiag = PETSC_TRUE; 28924f1b2e48SStefano Zampini } 28939566063dSJacob Faibussowitsch PetscCall(ISDestroy(&t_zerodiag_subs)); 28949566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&l2g)); 28954f1b2e48SStefano Zampini } 28963b03f7bbSStefano Zampini } 28974f1b2e48SStefano Zampini } else { /* there's just one subdomain (or zero if they have not been detected */ 28984f1b2e48SStefano Zampini PetscBool valid = PETSC_TRUE; 28991f4df5f7SStefano Zampini 29006632bad2Sstefano_zampini if (nneu) valid = PETSC_FALSE; 290148a46eb9SPierre Jolivet if (valid && pressures) PetscCall(ISEqual(pressures, zerodiag, &valid)); 29024edc6404Sstefano_zampini if (valid && checkb) { 29039566063dSJacob Faibussowitsch PetscCall(MatMult(matis->A, work[0], matis->x)); 29049566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(matis->x, work[1], matis->x)); 29059566063dSJacob Faibussowitsch PetscCall(VecGetArray(matis->x, &array)); 29061f4df5f7SStefano Zampini for (j = 0; j < n_interior_dofs; j++) { 29071f4df5f7SStefano Zampini if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) { 29081f4df5f7SStefano Zampini valid = PETSC_FALSE; 29091f4df5f7SStefano Zampini break; 29101f4df5f7SStefano Zampini } 29111f4df5f7SStefano Zampini } 29129566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(matis->x, &array)); 29131f4df5f7SStefano Zampini } 29144f1b2e48SStefano Zampini if (valid) { 29153b03f7bbSStefano Zampini benign_n = 1; 29169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(benign_n, &zerodiag_subs)); 29179566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)zerodiag)); 29184f1b2e48SStefano Zampini zerodiag_subs[0] = zerodiag; 29194f1b2e48SStefano Zampini } 29204f1b2e48SStefano Zampini } 292148a46eb9SPierre Jolivet if (checkb) PetscCall(VecDestroyVecs(2, &work)); 29221f4df5f7SStefano Zampini } 29239566063dSJacob Faibussowitsch PetscCall(PetscFree(interior_dofs)); 29244f1b2e48SStefano Zampini 29253b03f7bbSStefano Zampini if (!benign_n) { 2926b9b0e38cSStefano Zampini PetscInt n; 2927b9b0e38cSStefano Zampini 29289566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zerodiag)); 29294f1b2e48SStefano Zampini recompute_zerodiag = PETSC_FALSE; 29309566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pcbddc->local_mat, &n, NULL)); 293176a58201SStefano Zampini if (n) have_null = PETSC_FALSE; 2932b9b0e38cSStefano Zampini } 29334f1b2e48SStefano Zampini 29344f1b2e48SStefano Zampini /* final check for null pressures */ 293548a46eb9SPierre Jolivet if (zerodiag && pressures) PetscCall(ISEqual(pressures, zerodiag, &have_null)); 29364f1b2e48SStefano Zampini 29374f1b2e48SStefano Zampini if (recompute_zerodiag) { 29389566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zerodiag)); 29393b03f7bbSStefano Zampini if (benign_n == 1) { 29409566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)zerodiag_subs[0])); 29414f1b2e48SStefano Zampini zerodiag = zerodiag_subs[0]; 29424f1b2e48SStefano Zampini } else { 29434f1b2e48SStefano Zampini PetscInt i, nzn, *new_idxs; 29444f1b2e48SStefano Zampini 29454f1b2e48SStefano Zampini nzn = 0; 29463b03f7bbSStefano Zampini for (i = 0; i < benign_n; i++) { 29474f1b2e48SStefano Zampini PetscInt ns; 29489566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zerodiag_subs[i], &ns)); 29494f1b2e48SStefano Zampini nzn += ns; 29504f1b2e48SStefano Zampini } 29519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nzn, &new_idxs)); 29524f1b2e48SStefano Zampini nzn = 0; 29533b03f7bbSStefano Zampini for (i = 0; i < benign_n; i++) { 29544f1b2e48SStefano Zampini PetscInt ns, *idxs; 29559566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zerodiag_subs[i], &ns)); 29569566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zerodiag_subs[i], (const PetscInt **)&idxs)); 29579566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(new_idxs + nzn, idxs, ns)); 29589566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zerodiag_subs[i], (const PetscInt **)&idxs)); 29594f1b2e48SStefano Zampini nzn += ns; 29604f1b2e48SStefano Zampini } 29619566063dSJacob Faibussowitsch PetscCall(PetscSortInt(nzn, new_idxs)); 29629566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nzn, new_idxs, PETSC_OWN_POINTER, &zerodiag)); 29634f1b2e48SStefano Zampini } 29644f1b2e48SStefano Zampini have_null = PETSC_FALSE; 29654f1b2e48SStefano Zampini } 29664f1b2e48SStefano Zampini 29673b03f7bbSStefano Zampini /* determines if the coarse solver will be singular or not */ 2968462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&have_null, &pcbddc->benign_null, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)pc))); 29693b03f7bbSStefano Zampini 2970669cc0f4SStefano Zampini /* Prepare matrix to compute no-net-flux */ 2971a198735bSStefano Zampini if (pcbddc->compute_nonetflux && !pcbddc->divudotp) { 2972a198735bSStefano Zampini Mat A, loc_divudotp; 2973a198735bSStefano Zampini ISLocalToGlobalMapping rl2g, cl2g, l2gmap; 2974a198735bSStefano Zampini IS row, col, isused = NULL; 2975a198735bSStefano Zampini PetscInt M, N, n, st, n_isused; 2976a198735bSStefano Zampini 29771f4df5f7SStefano Zampini if (pressures) { 29781f4df5f7SStefano Zampini isused = pressures; 29791f4df5f7SStefano Zampini } else { 29804edc6404Sstefano_zampini isused = zerodiag_save; 29811f4df5f7SStefano Zampini } 29829566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(pc->pmat, &l2gmap, NULL)); 29839566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->pmat, &A)); 29849566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &n, NULL)); 29857827d75bSBarry 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"); 2986a198735bSStefano Zampini n_isused = 0; 298748a46eb9SPierre Jolivet if (isused) PetscCall(ISGetLocalSize(isused, &n_isused)); 29889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Scan(&n_isused, &st, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)pc))); 2989a198735bSStefano Zampini st = st - n_isused; 29901ae86dd6SStefano Zampini if (n) { 2991a198735bSStefano Zampini const PetscInt *gidxs; 2992a198735bSStefano Zampini 29939566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, isused, NULL, MAT_INITIAL_MATRIX, &loc_divudotp)); 29949566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(l2gmap, &gidxs)); 2995a198735bSStefano Zampini /* TODO: extend ISCreateStride with st = PETSC_DECIDE */ 29969566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)pc), n_isused, st, 1, &row)); 29979566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), n, gidxs, PETSC_COPY_VALUES, &col)); 29989566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(l2gmap, &gidxs)); 29991ae86dd6SStefano Zampini } else { 30009566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, 0, 0, 1, NULL, &loc_divudotp)); 30019566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)pc), n_isused, st, 1, &row)); 30029566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), 0, NULL, PETSC_COPY_VALUES, &col)); 3003a198735bSStefano Zampini } 30049566063dSJacob Faibussowitsch PetscCall(MatGetSize(pc->pmat, NULL, &N)); 30059566063dSJacob Faibussowitsch PetscCall(ISGetSize(row, &M)); 30069566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(row, &rl2g)); 30079566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(col, &cl2g)); 30089566063dSJacob Faibussowitsch PetscCall(ISDestroy(&row)); 30099566063dSJacob Faibussowitsch PetscCall(ISDestroy(&col)); 30109566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)pc), &pcbddc->divudotp)); 30119566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->divudotp, MATIS)); 30129566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->divudotp, PETSC_DECIDE, PETSC_DECIDE, M, N)); 30139566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(pcbddc->divudotp, rl2g, cl2g)); 30149566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 30159566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 30169566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(pcbddc->divudotp, loc_divudotp)); 30179566063dSJacob Faibussowitsch PetscCall(MatDestroy(&loc_divudotp)); 30189566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pcbddc->divudotp, MAT_FINAL_ASSEMBLY)); 30199566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->divudotp, MAT_FINAL_ASSEMBLY)); 30201ae86dd6SStefano Zampini } 30219566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zerodiag_save)); 30229566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pressures)); 30233b03f7bbSStefano Zampini if (bzerodiag) { 30243b03f7bbSStefano Zampini PetscInt i; 3025b3afcdbeSStefano Zampini 302648a46eb9SPierre Jolivet for (i = 0; i < bsp; i++) PetscCall(ISDestroy(&bzerodiag[i])); 30279566063dSJacob Faibussowitsch PetscCall(PetscFree(bzerodiag)); 30283b03f7bbSStefano Zampini } 30293b03f7bbSStefano Zampini pcbddc->benign_n = benign_n; 30303b03f7bbSStefano Zampini pcbddc->benign_zerodiag_subs = zerodiag_subs; 30313b03f7bbSStefano Zampini 30323b03f7bbSStefano Zampini /* determines if the problem has subdomains with 0 pressure block */ 30333b03f7bbSStefano Zampini have_null = (PetscBool)(!!pcbddc->benign_n); 3034462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&have_null, &pcbddc->benign_have_null, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 30353b03f7bbSStefano Zampini 30363b03f7bbSStefano Zampini project_b0: 30379566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pcbddc->local_mat, &n, NULL)); 3038b3afcdbeSStefano Zampini /* change of basis and p0 dofs */ 30393b03f7bbSStefano Zampini if (pcbddc->benign_n) { 30404f1b2e48SStefano Zampini PetscInt i, s, *nnz; 30414f1b2e48SStefano Zampini 3042339f8db1SStefano Zampini /* local change of basis for pressures */ 30439566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->benign_change)); 30449566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat), &pcbddc->benign_change)); 30459566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->benign_change, MATAIJ)); 30469566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->benign_change, n, n, PETSC_DECIDE, PETSC_DECIDE)); 30479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &nnz)); 3048aa0d93e9SStefano Zampini for (i = 0; i < n; i++) nnz[i] = 1; /* defaults to identity */ 30494f1b2e48SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) { 3050aa0d93e9SStefano Zampini const PetscInt *idxs; 30514f1b2e48SStefano Zampini PetscInt nzs, j; 30524f1b2e48SStefano Zampini 30539566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[i], &nzs)); 30549566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->benign_zerodiag_subs[i], &idxs)); 30554f1b2e48SStefano Zampini for (j = 0; j < nzs - 1; j++) nnz[idxs[j]] = 2; /* change on pressures */ 30564f1b2e48SStefano Zampini nnz[idxs[nzs - 1]] = nzs; /* last local pressure dof in subdomain */ 30579566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->benign_zerodiag_subs[i], &idxs)); 30584f1b2e48SStefano Zampini } 30599566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(pcbddc->benign_change, 0, nnz)); 30609566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->benign_change, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 30619566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 3062aa0d93e9SStefano Zampini /* set identity by default */ 306348a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall(MatSetValue(pcbddc->benign_change, i, i, 1., INSERT_VALUES)); 30649566063dSJacob Faibussowitsch PetscCall(PetscFree3(pcbddc->benign_p0_lidx, pcbddc->benign_p0_gidx, pcbddc->benign_p0)); 30659566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(pcbddc->benign_n, &pcbddc->benign_p0_lidx, pcbddc->benign_n, &pcbddc->benign_p0_gidx, pcbddc->benign_n, &pcbddc->benign_p0)); 3066339f8db1SStefano Zampini /* set change on pressures */ 30674f1b2e48SStefano Zampini for (s = 0; s < pcbddc->benign_n; s++) { 30684f1b2e48SStefano Zampini PetscScalar *array; 3069aa0d93e9SStefano Zampini const PetscInt *idxs; 30704f1b2e48SStefano Zampini PetscInt nzs; 30714f1b2e48SStefano Zampini 30729566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[s], &nzs)); 30739566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->benign_zerodiag_subs[s], &idxs)); 30744f1b2e48SStefano Zampini for (i = 0; i < nzs - 1; i++) { 3075339f8db1SStefano Zampini PetscScalar vals[2]; 3076339f8db1SStefano Zampini PetscInt cols[2]; 3077339f8db1SStefano Zampini 3078339f8db1SStefano Zampini cols[0] = idxs[i]; 30794f1b2e48SStefano Zampini cols[1] = idxs[nzs - 1]; 3080339f8db1SStefano Zampini vals[0] = 1.; 3081b0f5fe93SStefano Zampini vals[1] = 1.; 30829566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->benign_change, 1, cols, 2, cols, vals, INSERT_VALUES)); 3083339f8db1SStefano Zampini } 30849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nzs, &array)); 30854f1b2e48SStefano Zampini for (i = 0; i < nzs - 1; i++) array[i] = -1.; 30864f1b2e48SStefano Zampini array[nzs - 1] = 1.; 30879566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->benign_change, 1, idxs + nzs - 1, nzs, idxs, array, INSERT_VALUES)); 30884f1b2e48SStefano Zampini /* store local idxs for p0 */ 30894f1b2e48SStefano Zampini pcbddc->benign_p0_lidx[s] = idxs[nzs - 1]; 30909566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->benign_zerodiag_subs[s], &idxs)); 30919566063dSJacob Faibussowitsch PetscCall(PetscFree(array)); 30924f1b2e48SStefano Zampini } 30939566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pcbddc->benign_change, MAT_FINAL_ASSEMBLY)); 30949566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->benign_change, MAT_FINAL_ASSEMBLY)); 30953b03f7bbSStefano Zampini 3096a3df083aSStefano Zampini /* project if needed */ 3097a3df083aSStefano Zampini if (pcbddc->benign_change_explicit) { 30981dd7afcfSStefano Zampini Mat M; 30991dd7afcfSStefano Zampini 31009566063dSJacob Faibussowitsch PetscCall(MatPtAP(pcbddc->local_mat, pcbddc->benign_change, MAT_INITIAL_MATRIX, 2.0, &M)); 31019566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 31029566063dSJacob Faibussowitsch PetscCall(MatSeqAIJCompress(M, &pcbddc->local_mat)); 31039566063dSJacob Faibussowitsch PetscCall(MatDestroy(&M)); 3104a3df083aSStefano Zampini } 31054f1b2e48SStefano Zampini /* store global idxs for p0 */ 31069566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(matis->rmapping, pcbddc->benign_n, pcbddc->benign_p0_lidx, pcbddc->benign_p0_gidx)); 3107339f8db1SStefano Zampini } 3108339f8db1SStefano Zampini *zerodiaglocal = zerodiag; 31093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3110339f8db1SStefano Zampini } 3111339f8db1SStefano Zampini 3112d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get) 3113d71ae5a4SJacob Faibussowitsch { 3114efc2fbd9SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 3115de9d7bd0SStefano Zampini PetscScalar *array; 3116efc2fbd9SStefano Zampini 3117efc2fbd9SStefano Zampini PetscFunctionBegin; 3118efc2fbd9SStefano Zampini if (!pcbddc->benign_sf) { 31199566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)pc), &pcbddc->benign_sf)); 31209566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(pcbddc->benign_sf, pc->pmat->rmap, pcbddc->benign_n, NULL, PETSC_OWN_POINTER, pcbddc->benign_p0_gidx)); 3121efc2fbd9SStefano Zampini } 3122de9d7bd0SStefano Zampini if (get) { 31239566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, (const PetscScalar **)&array)); 31249566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pcbddc->benign_sf, MPIU_SCALAR, array, pcbddc->benign_p0, MPI_REPLACE)); 31259566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pcbddc->benign_sf, MPIU_SCALAR, array, pcbddc->benign_p0, MPI_REPLACE)); 31269566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, (const PetscScalar **)&array)); 3127de9d7bd0SStefano Zampini } else { 31289566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 31299566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(pcbddc->benign_sf, MPIU_SCALAR, pcbddc->benign_p0, array, MPI_REPLACE)); 31309566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(pcbddc->benign_sf, MPIU_SCALAR, pcbddc->benign_p0, array, MPI_REPLACE)); 31319566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 3132efc2fbd9SStefano Zampini } 31333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3134efc2fbd9SStefano Zampini } 3135efc2fbd9SStefano Zampini 3136d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop) 3137d71ae5a4SJacob Faibussowitsch { 3138c263805aSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 3139c263805aSStefano Zampini 3140c263805aSStefano Zampini PetscFunctionBegin; 3141c263805aSStefano Zampini /* TODO: add error checking 3142c263805aSStefano Zampini - avoid nested pop (or push) calls. 3143c263805aSStefano Zampini - cannot push before pop. 31441c604dc7SStefano Zampini - cannot call this if pcbddc->local_mat is NULL 3145c263805aSStefano Zampini */ 31463ba16761SJacob Faibussowitsch if (!pcbddc->benign_n) PetscFunctionReturn(PETSC_SUCCESS); 3147c263805aSStefano Zampini if (pop) { 3148a3df083aSStefano Zampini if (pcbddc->benign_change_explicit) { 31494f1b2e48SStefano Zampini IS is_p0; 31504f1b2e48SStefano Zampini MatReuse reuse; 3151c263805aSStefano Zampini 3152c263805aSStefano Zampini /* extract B_0 */ 31534f1b2e48SStefano Zampini reuse = MAT_INITIAL_MATRIX; 3154ad540459SPierre Jolivet if (pcbddc->benign_B0) reuse = MAT_REUSE_MATRIX; 31559566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, pcbddc->benign_n, pcbddc->benign_p0_lidx, PETSC_COPY_VALUES, &is_p0)); 31569566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, is_p0, NULL, reuse, &pcbddc->benign_B0)); 3157c263805aSStefano Zampini /* remove rows and cols from local problem */ 31589566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->local_mat, MAT_KEEP_NONZERO_PATTERN, PETSC_TRUE)); 31599566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->local_mat, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_FALSE)); 31609566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumnsIS(pcbddc->local_mat, is_p0, 1.0, NULL, NULL)); 31619566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_p0)); 3162a3df083aSStefano Zampini } else { 3163a3df083aSStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 3164a3df083aSStefano Zampini PetscScalar *vals; 3165a3df083aSStefano Zampini PetscInt i, n, *idxs_ins; 3166a3df083aSStefano Zampini 31679566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(matis->y, &n)); 31689566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n, &idxs_ins, n, &vals)); 3169a3df083aSStefano Zampini if (!pcbddc->benign_B0) { 31700b5adadeSStefano Zampini PetscInt *nnz; 31719566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat), &pcbddc->benign_B0)); 31729566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->benign_B0, MATAIJ)); 31739566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->benign_B0, pcbddc->benign_n, n, PETSC_DECIDE, PETSC_DECIDE)); 31749566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->benign_n, &nnz)); 3175331e053bSStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) { 31769566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[i], &nnz[i])); 3177331e053bSStefano Zampini nnz[i] = n - nnz[i]; 3178331e053bSStefano Zampini } 31799566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(pcbddc->benign_B0, 0, nnz)); 31809566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->benign_B0, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 31819566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 3182331e053bSStefano Zampini } 3183a3df083aSStefano Zampini 3184a3df083aSStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) { 3185a3df083aSStefano Zampini PetscScalar *array; 3186a3df083aSStefano Zampini PetscInt *idxs, j, nz, cum; 3187a3df083aSStefano Zampini 31889566063dSJacob Faibussowitsch PetscCall(VecSet(matis->x, 0.)); 31899566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[i], &nz)); 31909566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->benign_zerodiag_subs[i], (const PetscInt **)&idxs)); 3191a3df083aSStefano Zampini for (j = 0; j < nz; j++) vals[j] = 1.; 31929566063dSJacob Faibussowitsch PetscCall(VecSetValues(matis->x, nz, idxs, vals, INSERT_VALUES)); 31939566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(matis->x)); 31949566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(matis->x)); 31959566063dSJacob Faibussowitsch PetscCall(VecSet(matis->y, 0.)); 31969566063dSJacob Faibussowitsch PetscCall(MatMult(matis->A, matis->x, matis->y)); 31979566063dSJacob Faibussowitsch PetscCall(VecGetArray(matis->y, &array)); 3198a3df083aSStefano Zampini cum = 0; 3199a3df083aSStefano Zampini for (j = 0; j < n; j++) { 320022db5ddcSStefano Zampini if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) { 3201a3df083aSStefano Zampini vals[cum] = array[j]; 3202a3df083aSStefano Zampini idxs_ins[cum] = j; 3203a3df083aSStefano Zampini cum++; 3204a3df083aSStefano Zampini } 3205a3df083aSStefano Zampini } 32069566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->benign_B0, 1, &i, cum, idxs_ins, vals, INSERT_VALUES)); 32079566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(matis->y, &array)); 32089566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->benign_zerodiag_subs[i], (const PetscInt **)&idxs)); 3209a3df083aSStefano Zampini } 32109566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pcbddc->benign_B0, MAT_FINAL_ASSEMBLY)); 32119566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->benign_B0, MAT_FINAL_ASSEMBLY)); 32129566063dSJacob Faibussowitsch PetscCall(PetscFree2(idxs_ins, vals)); 3213a3df083aSStefano Zampini } 3214c263805aSStefano Zampini } else { /* push */ 32154f1b2e48SStefano Zampini 32160fdf79fbSJacob Faibussowitsch PetscCheck(pcbddc->benign_change_explicit, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Cannot push B0!"); 32170fdf79fbSJacob Faibussowitsch for (PetscInt i = 0; i < pcbddc->benign_n; i++) { 32184f1b2e48SStefano Zampini PetscScalar *B0_vals; 32194f1b2e48SStefano Zampini PetscInt *B0_cols, B0_ncol; 32204f1b2e48SStefano Zampini 32219566063dSJacob Faibussowitsch PetscCall(MatGetRow(pcbddc->benign_B0, i, &B0_ncol, (const PetscInt **)&B0_cols, (const PetscScalar **)&B0_vals)); 32229566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->local_mat, 1, pcbddc->benign_p0_lidx + i, B0_ncol, B0_cols, B0_vals, INSERT_VALUES)); 32239566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->local_mat, B0_ncol, B0_cols, 1, pcbddc->benign_p0_lidx + i, B0_vals, INSERT_VALUES)); 32249566063dSJacob Faibussowitsch PetscCall(MatSetValue(pcbddc->local_mat, pcbddc->benign_p0_lidx[i], pcbddc->benign_p0_lidx[i], 0.0, INSERT_VALUES)); 32259566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(pcbddc->benign_B0, i, &B0_ncol, (const PetscInt **)&B0_cols, (const PetscScalar **)&B0_vals)); 32264f1b2e48SStefano Zampini } 32279566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pcbddc->local_mat, MAT_FINAL_ASSEMBLY)); 32289566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->local_mat, MAT_FINAL_ASSEMBLY)); 3229c263805aSStefano Zampini } 32303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3231c263805aSStefano Zampini } 3232c263805aSStefano Zampini 3233d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCAdaptiveSelection(PC pc) 3234d71ae5a4SJacob Faibussowitsch { 3235b1b3d7a2SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 323608122e43SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 3237*97b17b2cSPierre Jolivet PetscBLASInt B_neigs, B_ierr, B_lwork; 323808122e43SStefano Zampini PetscBLASInt *B_iwork, *B_ifail; 323908122e43SStefano Zampini PetscScalar *work, lwork; 324008122e43SStefano Zampini PetscScalar *St, *S, *eigv; 324108122e43SStefano Zampini PetscScalar *Sarray, *Starray; 3242bd2a564bSStefano Zampini PetscReal *eigs, thresh, lthresh, uthresh; 32431b968477SStefano Zampini PetscInt i, nmax, nmin, nv, cum, mss, cum2, cumarray, maxneigs; 324432fe681dSStefano Zampini PetscBool allocated_S_St, upart; 324508122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 324608122e43SStefano Zampini PetscReal *rwork; 324708122e43SStefano Zampini #endif 3248b1b3d7a2SStefano Zampini 3249b1b3d7a2SStefano Zampini PetscFunctionBegin; 32503ba16761SJacob Faibussowitsch if (!pcbddc->adaptive_selection) PetscFunctionReturn(PETSC_SUCCESS); 325128b400f6SJacob Faibussowitsch PetscCheck(sub_schurs, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Adaptive selection of constraints requires SubSchurs data"); 325232fe681dSStefano 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"); 32539371c9d4SSatish 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, 32549371c9d4SSatish Balay sub_schurs->is_posdef); 32559566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_AdaptiveSetUp[pcbddc->current_level], pc, 0, 0, 0)); 325606a4e24aSStefano Zampini 3257fd14bc51SStefano Zampini if (pcbddc->dbg_flag) { 325832fe681dSStefano Zampini if (!pcbddc->dbg_viewer) pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc)); 32599566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 32609566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 32619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Check adaptive selection of constraints\n")); 32629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 3263fd14bc51SStefano Zampini } 3264fd14bc51SStefano Zampini 326548a46eb9SPierre 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)); 3266e496cd5dSStefano Zampini 326708122e43SStefano Zampini /* max size of subsets */ 326808122e43SStefano Zampini mss = 0; 326908122e43SStefano Zampini for (i = 0; i < sub_schurs->n_subs; i++) { 327008122e43SStefano Zampini PetscInt subset_size; 3271862806e4SStefano Zampini 32729566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->is_subs[i], &subset_size)); 327308122e43SStefano Zampini mss = PetscMax(mss, subset_size); 327408122e43SStefano Zampini } 327508122e43SStefano Zampini 327608122e43SStefano Zampini /* min/max and threshold */ 327708122e43SStefano Zampini nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss; 3278f6f667cfSStefano Zampini nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0; 327908122e43SStefano Zampini nmax = PetscMax(nmin, nmax); 3280f6f667cfSStefano Zampini allocated_S_St = PETSC_FALSE; 3281bd2a564bSStefano Zampini if (nmin || !sub_schurs->is_posdef) { /* XXX */ 3282f6f667cfSStefano Zampini allocated_S_St = PETSC_TRUE; 3283f6f667cfSStefano Zampini } 328408122e43SStefano Zampini 328508122e43SStefano Zampini /* allocate lapack workspace */ 328608122e43SStefano Zampini cum = cum2 = 0; 328708122e43SStefano Zampini maxneigs = 0; 328808122e43SStefano Zampini for (i = 0; i < sub_schurs->n_subs; i++) { 328908122e43SStefano Zampini PetscInt n, subset_size; 3290f6f667cfSStefano Zampini 32919566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->is_subs[i], &subset_size)); 329208122e43SStefano Zampini n = PetscMin(subset_size, nmax); 32939162d606SStefano Zampini cum += subset_size; 32949162d606SStefano Zampini cum2 += subset_size * n; 329508122e43SStefano Zampini maxneigs = PetscMax(maxneigs, n); 329608122e43SStefano Zampini } 32977ebab0bbSStefano Zampini lwork = 0; 329808122e43SStefano Zampini if (mss) { 32997ebab0bbSStefano Zampini PetscScalar sdummy = 0.; 330008122e43SStefano Zampini PetscBLASInt B_itype = 1; 33016497c311SBarry Smith PetscBLASInt B_N, idummy = 0; 33027ebab0bbSStefano Zampini PetscReal rdummy = 0., zero = 0.0; 33034c6709b3SStefano Zampini PetscReal eps = 0.0; /* dlamch? */ 330408122e43SStefano Zampini 33050fdf79fbSJacob Faibussowitsch PetscCheck(sub_schurs->is_symmetric, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not yet implemented"); 33066497c311SBarry Smith PetscCall(PetscBLASIntCast(mss, &B_N)); 330708122e43SStefano Zampini B_lwork = -1; 33087ebab0bbSStefano Zampini /* some implementations may complain about NULL pointers, even if we are querying */ 33097ebab0bbSStefano Zampini S = &sdummy; 33107ebab0bbSStefano Zampini St = &sdummy; 33117ebab0bbSStefano Zampini eigs = &rdummy; 33127ebab0bbSStefano Zampini eigv = &sdummy; 33137ebab0bbSStefano Zampini B_iwork = &idummy; 33147ebab0bbSStefano Zampini B_ifail = &idummy; 3315d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX) 33167ebab0bbSStefano Zampini rwork = &rdummy; 3317d1710679SStefano Zampini #endif 33188bec7fa6SStefano Zampini thresh = 1.0; 33199566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 332008122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 3321*97b17b2cSPierre Jolivet PetscCallBLAS("LAPACKsygvx", LAPACKsygvx_(&B_itype, "V", "V", "L", &B_N, St, &B_N, S, &B_N, &zero, &thresh, B_iwork, B_iwork, &eps, &B_neigs, eigs, eigv, &B_N, &lwork, &B_lwork, rwork, B_iwork, B_ifail, &B_ierr)); 332208122e43SStefano Zampini #else 3323*97b17b2cSPierre Jolivet PetscCallBLAS("LAPACKsygvx", LAPACKsygvx_(&B_itype, "V", "V", "L", &B_N, St, &B_N, S, &B_N, &zero, &thresh, B_iwork, B_iwork, &eps, &B_neigs, eigs, eigv, &B_N, &lwork, &B_lwork, B_iwork, B_ifail, &B_ierr)); 332408122e43SStefano Zampini #endif 3325835f2295SStefano Zampini PetscCheck(B_ierr == 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in query to SYGVX Lapack routine %" PetscBLASInt_FMT, B_ierr); 33269566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 332708122e43SStefano Zampini } 332808122e43SStefano Zampini 332908122e43SStefano Zampini nv = 0; 3330d62866d3SStefano 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) */ 33319566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->is_vertices, &nv)); 333208122e43SStefano Zampini } 33339566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(lwork), &B_lwork)); 333448a46eb9SPierre Jolivet if (allocated_S_St) PetscCall(PetscMalloc2(mss * mss, &S, mss * mss, &St)); 33359566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(mss * mss, &eigv, mss, &eigs, B_lwork, &work, 5 * mss, &B_iwork, mss, &B_ifail)); 333608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 33379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(7 * mss, &rwork)); 333808122e43SStefano Zampini #endif 33399371c9d4SSatish 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, 33409371c9d4SSatish Balay &pcbddc->adaptive_constraints_data)); 33419566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(pcbddc->adaptive_constraints_n, nv + sub_schurs->n_subs)); 334208122e43SStefano Zampini 334308122e43SStefano Zampini maxneigs = 0; 334472b8c272SStefano Zampini cum = cumarray = 0; 33459162d606SStefano Zampini pcbddc->adaptive_constraints_idxs_ptr[0] = 0; 33469162d606SStefano Zampini pcbddc->adaptive_constraints_data_ptr[0] = 0; 3347d62866d3SStefano Zampini if (sub_schurs->is_vertices && pcbddc->use_vertices) { 334808122e43SStefano Zampini const PetscInt *idxs; 334908122e43SStefano Zampini 33509566063dSJacob Faibussowitsch PetscCall(ISGetIndices(sub_schurs->is_vertices, &idxs)); 335108122e43SStefano Zampini for (cum = 0; cum < nv; cum++) { 335208122e43SStefano Zampini pcbddc->adaptive_constraints_n[cum] = 1; 335308122e43SStefano Zampini pcbddc->adaptive_constraints_idxs[cum] = idxs[cum]; 335408122e43SStefano Zampini pcbddc->adaptive_constraints_data[cum] = 1.0; 33559162d606SStefano Zampini pcbddc->adaptive_constraints_idxs_ptr[cum + 1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + 1; 33569162d606SStefano Zampini pcbddc->adaptive_constraints_data_ptr[cum + 1] = pcbddc->adaptive_constraints_data_ptr[cum] + 1; 335708122e43SStefano Zampini } 33589566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(sub_schurs->is_vertices, &idxs)); 335908122e43SStefano Zampini } 336008122e43SStefano Zampini 336108122e43SStefano Zampini if (mss) { /* multilevel */ 336232fe681dSStefano Zampini if (sub_schurs->gdsw) { 336332fe681dSStefano Zampini PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_all, &Sarray)); 336432fe681dSStefano Zampini PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all, &Starray)); 336532fe681dSStefano Zampini } else { 33669566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all, &Sarray)); 33679566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all, &Starray)); 336808122e43SStefano Zampini } 336932fe681dSStefano Zampini } 337008122e43SStefano Zampini 3371bd2a564bSStefano Zampini lthresh = pcbddc->adaptive_threshold[0]; 3372bd2a564bSStefano Zampini uthresh = pcbddc->adaptive_threshold[1]; 337332fe681dSStefano Zampini upart = pcbddc->use_deluxe_scaling; 337408122e43SStefano Zampini for (i = 0; i < sub_schurs->n_subs; i++) { 337508122e43SStefano Zampini const PetscInt *idxs; 33769d54b7f4SStefano Zampini PetscReal upper, lower; 3377862806e4SStefano Zampini PetscInt j, subset_size, eigs_start = 0; 337808122e43SStefano Zampini PetscBLASInt B_N; 3379aff50787SStefano Zampini PetscBool same_data = PETSC_FALSE; 3380bd2a564bSStefano Zampini PetscBool scal = PETSC_FALSE; 338108122e43SStefano Zampini 338232fe681dSStefano Zampini if (upart) { 33839d54b7f4SStefano Zampini upper = PETSC_MAX_REAL; 3384bd2a564bSStefano Zampini lower = uthresh; 33859d54b7f4SStefano Zampini } else { 338632fe681dSStefano Zampini if (sub_schurs->gdsw) { 338732fe681dSStefano Zampini upper = uthresh; 338832fe681dSStefano Zampini lower = PETSC_MIN_REAL; 338932fe681dSStefano Zampini } else { 339028b400f6SJacob Faibussowitsch PetscCheck(sub_schurs->is_posdef, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not yet implemented without deluxe scaling"); 3391bd2a564bSStefano Zampini upper = 1. / uthresh; 33929d54b7f4SStefano Zampini lower = 0.; 33939d54b7f4SStefano Zampini } 339432fe681dSStefano Zampini } 33959566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->is_subs[i], &subset_size)); 33969566063dSJacob Faibussowitsch PetscCall(ISGetIndices(sub_schurs->is_subs[i], &idxs)); 33979566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(subset_size, &B_N)); 3398bd2a564bSStefano Zampini /* this is experimental: we assume the dofs have been properly grouped to have 3399bd2a564bSStefano Zampini the diagonal blocks Schur complements either positive or negative definite (true for Stokes) */ 3400bd2a564bSStefano Zampini if (!sub_schurs->is_posdef) { 3401bd2a564bSStefano Zampini Mat T; 3402bd2a564bSStefano Zampini 3403bd2a564bSStefano Zampini for (j = 0; j < subset_size; j++) { 3404bd2a564bSStefano Zampini if (PetscRealPart(*(Sarray + cumarray + j * (subset_size + 1))) < 0.0) { 34059566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, subset_size, subset_size, Sarray + cumarray, &T)); 34069566063dSJacob Faibussowitsch PetscCall(MatScale(T, -1.0)); 34079566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 34089566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, subset_size, subset_size, Starray + cumarray, &T)); 34099566063dSJacob Faibussowitsch PetscCall(MatScale(T, -1.0)); 34109566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 3411bd2a564bSStefano Zampini if (sub_schurs->change_primal_sub) { 3412bd2a564bSStefano Zampini PetscInt nz, k; 3413bd2a564bSStefano Zampini const PetscInt *idxs; 3414bd2a564bSStefano Zampini 34159566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->change_primal_sub[i], &nz)); 34169566063dSJacob Faibussowitsch PetscCall(ISGetIndices(sub_schurs->change_primal_sub[i], &idxs)); 3417bd2a564bSStefano Zampini for (k = 0; k < nz; k++) { 3418bd2a564bSStefano Zampini *(Sarray + cumarray + idxs[k] * (subset_size + 1)) *= -1.0; 3419bd2a564bSStefano Zampini *(Starray + cumarray + idxs[k] * (subset_size + 1)) = 0.0; 3420bd2a564bSStefano Zampini } 34219566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(sub_schurs->change_primal_sub[i], &idxs)); 3422bd2a564bSStefano Zampini } 3423bd2a564bSStefano Zampini scal = PETSC_TRUE; 3424bd2a564bSStefano Zampini break; 3425bd2a564bSStefano Zampini } 3426bd2a564bSStefano Zampini } 3427bd2a564bSStefano Zampini } 3428bd2a564bSStefano Zampini 3429f6f667cfSStefano Zampini if (allocated_S_St) { /* S and S_t should be copied since we could need them later */ 3430bd2a564bSStefano Zampini if (sub_schurs->is_symmetric) { 3431aff50787SStefano Zampini PetscInt j, k; 3432580bdb30SBarry Smith if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscArraycmp() later */ 34339566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(S, subset_size * subset_size)); 34349566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(St, subset_size * subset_size)); 343508122e43SStefano Zampini } 343608122e43SStefano Zampini for (j = 0; j < subset_size; j++) { 3437aff50787SStefano Zampini for (k = j; k < subset_size; k++) { 3438aff50787SStefano Zampini S[j * subset_size + k] = Sarray[cumarray + j * subset_size + k]; 3439aff50787SStefano Zampini St[j * subset_size + k] = Starray[cumarray + j * subset_size + k]; 3440aff50787SStefano Zampini } 344108122e43SStefano Zampini } 344208122e43SStefano Zampini } else { 34439566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 34449566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 344508122e43SStefano Zampini } 34468bec7fa6SStefano Zampini } else { 3447f6f667cfSStefano Zampini S = Sarray + cumarray; 3448f6f667cfSStefano Zampini St = Starray + cumarray; 34498bec7fa6SStefano Zampini } 3450aff50787SStefano Zampini /* see if we can save some work */ 345148a46eb9SPierre Jolivet if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) PetscCall(PetscArraycmp(S, St, subset_size * subset_size, &same_data)); 3452aff50787SStefano Zampini 3453b7ab4a40SStefano Zampini if (same_data && !sub_schurs->change) { /* there's no need of constraints here */ 3454aff50787SStefano Zampini B_neigs = 0; 3455aff50787SStefano Zampini } else { 3456*97b17b2cSPierre Jolivet PetscBLASInt B_itype = 1, B_IL = 1, B_IU = 0; 34574c6709b3SStefano Zampini PetscReal eps = -1.0; /* dlamch? */ 34589552c7c7SStefano Zampini PetscInt nmin_s; 3459bd2a564bSStefano Zampini PetscBool compute_range; 3460bd2a564bSStefano Zampini 34610fdf79fbSJacob Faibussowitsch PetscCheck(sub_schurs->is_symmetric, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not yet implemented"); 34629036ceccSStefano Zampini B_neigs = 0; 3463bd2a564bSStefano Zampini compute_range = (PetscBool)!same_data; 3464bd2a564bSStefano Zampini if (nmin >= subset_size) compute_range = PETSC_FALSE; 346508122e43SStefano Zampini 3466fd14bc51SStefano Zampini if (pcbddc->dbg_flag) { 3467a4cdd7efSStefano Zampini PetscInt nc = 0, c = pcbddc->mat_graph->nodes[idxs[0]].count, w = pcbddc->mat_graph->nodes[idxs[0]].which_dof; 3468d16cbb6bSStefano Zampini 346948a46eb9SPierre Jolivet if (sub_schurs->change_primal_sub) PetscCall(ISGetLocalSize(sub_schurs->change_primal_sub[i], &nc)); 34709de2952eSStefano Zampini PetscCall( 34719de2952eSStefano 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)); 3472b7ab4a40SStefano Zampini } 3473b7ab4a40SStefano Zampini 34749566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 3475b7ab4a40SStefano Zampini if (compute_range) { 3476d16cbb6bSStefano Zampini /* ask for eigenvalues larger than thresh */ 3477bd2a564bSStefano Zampini if (sub_schurs->is_posdef) { 347808122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 3479792fecdfSBarry 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)); 348008122e43SStefano Zampini #else 3481792fecdfSBarry 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)); 348208122e43SStefano Zampini #endif 34839566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 3484bd2a564bSStefano Zampini } else { /* no theory so far, but it works nicely */ 34859036ceccSStefano Zampini PetscInt recipe = 0, recipe_m = 1; 3486bd2a564bSStefano Zampini PetscReal bb[2]; 3487bd2a564bSStefano Zampini 34889566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)pc)->prefix, "-pc_bddc_adaptive_recipe", &recipe, NULL)); 3489bd2a564bSStefano Zampini switch (recipe) { 3490bd2a564bSStefano Zampini case 0: 34919371c9d4SSatish Balay if (scal) { 34929371c9d4SSatish Balay bb[0] = PETSC_MIN_REAL; 34939371c9d4SSatish Balay bb[1] = lthresh; 34949371c9d4SSatish Balay } else { 34959371c9d4SSatish Balay bb[0] = uthresh; 34969371c9d4SSatish Balay bb[1] = PETSC_MAX_REAL; 34979371c9d4SSatish Balay } 3498bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3499792fecdfSBarry 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)); 3500bd2a564bSStefano Zampini #else 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_neigs, eigs, eigv, &B_N, work, &B_lwork, B_iwork, B_ifail, &B_ierr)); 3502bd2a564bSStefano Zampini #endif 35039566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 3504bd2a564bSStefano Zampini break; 3505d71ae5a4SJacob Faibussowitsch case 1: 3506d71ae5a4SJacob Faibussowitsch bb[0] = PETSC_MIN_REAL; 3507d71ae5a4SJacob Faibussowitsch bb[1] = lthresh * lthresh; 3508bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3509792fecdfSBarry 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)); 3510bd2a564bSStefano Zampini #else 3511792fecdfSBarry 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)); 3512bd2a564bSStefano Zampini #endif 35139566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 3514bd2a564bSStefano Zampini if (!scal) { 35159036ceccSStefano Zampini PetscBLASInt B_neigs2 = 0; 3516bd2a564bSStefano Zampini 35179371c9d4SSatish Balay bb[0] = PetscMax(lthresh * lthresh, uthresh); 35189371c9d4SSatish Balay bb[1] = PETSC_MAX_REAL; 35199566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 35209566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 3521bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3522792fecdfSBarry 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)); 3523bd2a564bSStefano Zampini #else 3524792fecdfSBarry 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)); 3525bd2a564bSStefano Zampini #endif 35269566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 3527bd2a564bSStefano Zampini B_neigs += B_neigs2; 3528bd2a564bSStefano Zampini } 3529bd2a564bSStefano Zampini break; 35309036ceccSStefano Zampini case 2: 35319036ceccSStefano Zampini if (scal) { 35329036ceccSStefano Zampini bb[0] = PETSC_MIN_REAL; 35339036ceccSStefano Zampini bb[1] = 0; 35349036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3535792fecdfSBarry 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)); 35369036ceccSStefano Zampini #else 3537792fecdfSBarry 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)); 35389036ceccSStefano Zampini #endif 35399566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 35409036ceccSStefano Zampini } else { 35419036ceccSStefano Zampini PetscBLASInt B_neigs2 = 0; 354213bcc0bdSJacob Faibussowitsch PetscBool do_copy = PETSC_FALSE; 35439036ceccSStefano Zampini 35449036ceccSStefano Zampini lthresh = PetscMax(lthresh, 0.0); 35459036ceccSStefano Zampini if (lthresh > 0.0) { 35469036ceccSStefano Zampini bb[0] = PETSC_MIN_REAL; 35479036ceccSStefano Zampini bb[1] = lthresh * lthresh; 35489036ceccSStefano Zampini 354913bcc0bdSJacob Faibussowitsch do_copy = PETSC_TRUE; 35509036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3551792fecdfSBarry 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)); 35529036ceccSStefano Zampini #else 3553792fecdfSBarry 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)); 35549036ceccSStefano Zampini #endif 35559566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 35569036ceccSStefano Zampini } 35579036ceccSStefano Zampini bb[0] = PetscMax(lthresh * lthresh, uthresh); 35589036ceccSStefano Zampini bb[1] = PETSC_MAX_REAL; 355913bcc0bdSJacob Faibussowitsch if (do_copy) { 35609566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 35619566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 35629036ceccSStefano Zampini } 35639036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3564792fecdfSBarry 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)); 35659036ceccSStefano Zampini #else 3566792fecdfSBarry 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)); 35679036ceccSStefano Zampini #endif 35689566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 35699036ceccSStefano Zampini B_neigs += B_neigs2; 35709036ceccSStefano Zampini } 35719036ceccSStefano Zampini break; 35729036ceccSStefano Zampini case 3: 35739036ceccSStefano Zampini if (scal) { 35749566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)pc)->prefix, "-pc_bddc_adaptive_recipe3_min_scal", &recipe_m, NULL)); 35759036ceccSStefano Zampini } else { 35769566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)pc)->prefix, "-pc_bddc_adaptive_recipe3_min", &recipe_m, NULL)); 35779036ceccSStefano Zampini } 35789036ceccSStefano Zampini if (!scal) { 35799036ceccSStefano Zampini bb[0] = uthresh; 35809036ceccSStefano Zampini bb[1] = PETSC_MAX_REAL; 35819036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3582792fecdfSBarry 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)); 35839036ceccSStefano Zampini #else 3584792fecdfSBarry 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)); 35859036ceccSStefano Zampini #endif 35869566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 35879036ceccSStefano Zampini } 35889036ceccSStefano Zampini if (recipe_m > 0 && B_N - B_neigs > 0) { 35899036ceccSStefano Zampini PetscBLASInt B_neigs2 = 0; 35909036ceccSStefano Zampini 35919566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(PetscMin(recipe_m, B_N - B_neigs), &B_IU)); 35929566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 35939566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 35949036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3595792fecdfSBarry 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)); 35969036ceccSStefano Zampini #else 3597792fecdfSBarry 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)); 35989036ceccSStefano Zampini #endif 35999566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 36009036ceccSStefano Zampini B_neigs += B_neigs2; 36019036ceccSStefano Zampini } 36029036ceccSStefano Zampini break; 3603d71ae5a4SJacob Faibussowitsch case 4: 3604d71ae5a4SJacob Faibussowitsch bb[0] = PETSC_MIN_REAL; 3605d71ae5a4SJacob Faibussowitsch bb[1] = lthresh; 360648cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX) 3607792fecdfSBarry 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)); 360848cebe81SStefano Zampini #else 3609792fecdfSBarry 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)); 361048cebe81SStefano Zampini #endif 36119566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 361248cebe81SStefano Zampini { 361348cebe81SStefano Zampini PetscBLASInt B_neigs2 = 0; 361448cebe81SStefano Zampini 36159371c9d4SSatish Balay bb[0] = PetscMax(lthresh + PETSC_SMALL, uthresh); 36169371c9d4SSatish Balay bb[1] = PETSC_MAX_REAL; 36179566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 36189566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 361948cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX) 3620792fecdfSBarry 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)); 362148cebe81SStefano Zampini #else 3622792fecdfSBarry 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)); 362348cebe81SStefano Zampini #endif 36249566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 362548cebe81SStefano Zampini B_neigs += B_neigs2; 362648cebe81SStefano Zampini } 362748cebe81SStefano Zampini break; 362880db8efeSStefano Zampini case 5: /* same as before: first compute all eigenvalues, then filter */ 362980db8efeSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3630792fecdfSBarry 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)); 363180db8efeSStefano Zampini #else 3632792fecdfSBarry 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)); 363380db8efeSStefano Zampini #endif 36349566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 363580db8efeSStefano Zampini { 363680db8efeSStefano Zampini PetscInt e, k, ne; 363780db8efeSStefano Zampini for (e = 0, ne = 0; e < B_neigs; e++) { 363880db8efeSStefano Zampini if (eigs[e] < lthresh || eigs[e] > uthresh) { 363980db8efeSStefano Zampini for (k = 0; k < B_N; k++) S[ne * B_N + k] = eigv[e * B_N + k]; 364080db8efeSStefano Zampini eigs[ne] = eigs[e]; 364180db8efeSStefano Zampini ne++; 364280db8efeSStefano Zampini } 364380db8efeSStefano Zampini } 36449566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(eigv, S, B_N * ne)); 36456497c311SBarry Smith PetscCall(PetscBLASIntCast(ne, &B_neigs)); 364680db8efeSStefano Zampini } 364780db8efeSStefano Zampini break; 3648d71ae5a4SJacob Faibussowitsch default: 3649d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Unknown recipe %" PetscInt_FMT, recipe); 3650bd2a564bSStefano Zampini } 3651bd2a564bSStefano Zampini } 3652bd2a564bSStefano Zampini } else if (!same_data) { /* this is just to see all the eigenvalues */ 36536497c311SBarry Smith PetscCall(PetscBLASIntCast(PetscMax(1, PetscMin(B_N, nmax)), &B_IU)); 3654d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3655792fecdfSBarry 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)); 3656d16cbb6bSStefano Zampini #else 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_neigs, eigs, eigv, &B_N, work, &B_lwork, B_iwork, B_ifail, &B_ierr)); 3658d16cbb6bSStefano Zampini #endif 36599566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 3660b03ebc13SStefano Zampini } else { /* same_data is true, so just get the adaptive functional requested by the user */ 3661b7ab4a40SStefano Zampini PetscInt k; 366228b400f6SJacob Faibussowitsch PetscCheck(sub_schurs->change_primal_sub, PETSC_COMM_SELF, PETSC_ERR_PLIB, "This should not happen"); 36639566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->change_primal_sub[i], &nmax)); 36649566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(nmax, &B_neigs)); 3665b7ab4a40SStefano Zampini nmin = nmax; 36669566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(eigv, subset_size * nmax)); 3667b7ab4a40SStefano Zampini for (k = 0; k < nmax; k++) { 3668b7ab4a40SStefano Zampini eigs[k] = 1. / PETSC_SMALL; 3669b7ab4a40SStefano Zampini eigv[k * (subset_size + 1)] = 1.0; 3670b7ab4a40SStefano Zampini } 3671d16cbb6bSStefano Zampini } 36729566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 367308122e43SStefano Zampini if (B_ierr) { 367463a3b9bcSJacob Faibussowitsch PetscCheck(B_ierr >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in SYGVX Lapack routine: illegal value for argument %" PetscBLASInt_FMT, -B_ierr); 367563a3b9bcSJacob 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); 367663a3b9bcSJacob 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); 367708122e43SStefano Zampini } 367808122e43SStefano Zampini 367908122e43SStefano Zampini if (B_neigs > nmax) { 368048a46eb9SPierre Jolivet if (pcbddc->dbg_flag) PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " found %" PetscBLASInt_FMT " eigs, more than maximum required %" PetscInt_FMT ".\n", B_neigs, nmax)); 368132fe681dSStefano Zampini if (upart) eigs_start = scal ? 0 : B_neigs - nmax; 36826497c311SBarry Smith PetscCall(PetscBLASIntCast(nmax, &B_neigs)); 368308122e43SStefano Zampini } 368408122e43SStefano Zampini 36859552c7c7SStefano Zampini nmin_s = PetscMin(nmin, B_N); 36869552c7c7SStefano Zampini if (B_neigs < nmin_s) { 36879036ceccSStefano Zampini PetscBLASInt B_neigs2 = 0; 368808122e43SStefano Zampini 368932fe681dSStefano Zampini if (upart) { 3690bd2a564bSStefano Zampini if (scal) { 36916497c311SBarry Smith PetscCall(PetscBLASIntCast(nmin_s, &B_IU)); 3692bd2a564bSStefano Zampini B_IL = B_neigs + 1; 3693bd2a564bSStefano Zampini } else { 36946497c311SBarry Smith PetscCall(PetscBLASIntCast(B_N - nmin_s + 1, &B_IL)); 36959d54b7f4SStefano Zampini B_IU = B_N - B_neigs; 3696bd2a564bSStefano Zampini } 36979d54b7f4SStefano Zampini } else { 36989d54b7f4SStefano Zampini B_IL = B_neigs + 1; 36996497c311SBarry Smith PetscCall(PetscBLASIntCast(nmin_s, &B_IU)); 37009d54b7f4SStefano Zampini } 3701fd14bc51SStefano Zampini if (pcbddc->dbg_flag) { 370263a3b9bcSJacob 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)); 3703fd14bc51SStefano Zampini } 3704bd2a564bSStefano Zampini if (sub_schurs->is_symmetric) { 37051ae86dd6SStefano Zampini PetscInt j, k; 370608122e43SStefano Zampini for (j = 0; j < subset_size; j++) { 37071ae86dd6SStefano Zampini for (k = j; k < subset_size; k++) { 37081ae86dd6SStefano Zampini S[j * subset_size + k] = Sarray[cumarray + j * subset_size + k]; 37091ae86dd6SStefano Zampini St[j * subset_size + k] = Starray[cumarray + j * subset_size + k]; 371008122e43SStefano Zampini } 371108122e43SStefano Zampini } 371208122e43SStefano Zampini } else { 37139566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 37149566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 371508122e43SStefano Zampini } 37169566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 371708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 3718792fecdfSBarry 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)); 371908122e43SStefano Zampini #else 3720792fecdfSBarry 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)); 372108122e43SStefano Zampini #endif 37229566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 37239566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 372408122e43SStefano Zampini B_neigs += B_neigs2; 372508122e43SStefano Zampini } 372608122e43SStefano Zampini if (B_ierr) { 372763a3b9bcSJacob Faibussowitsch PetscCheck(B_ierr >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in SYGVX Lapack routine: illegal value for argument %" PetscBLASInt_FMT, -B_ierr); 372863a3b9bcSJacob 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); 372963a3b9bcSJacob 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); 373008122e43SStefano Zampini } 3731fd14bc51SStefano Zampini if (pcbddc->dbg_flag) { 373263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " -> Got %" PetscBLASInt_FMT " eigs\n", B_neigs)); 373308122e43SStefano Zampini for (j = 0; j < B_neigs; j++) { 373432fe681dSStefano Zampini if (!sub_schurs->gdsw) { 373508122e43SStefano Zampini if (eigs[j] == 0.0) { 37369566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " Inf\n")); 373708122e43SStefano Zampini } else { 373832fe681dSStefano Zampini if (upart) { 373963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.6e\n", (double)eigs[j + eigs_start])); 37409d54b7f4SStefano Zampini } else { 3741835f2295SStefano Zampini PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.6e\n", (double)(1 / eigs[j + eigs_start]))); 37429d54b7f4SStefano Zampini } 3743fd14bc51SStefano Zampini } 374432fe681dSStefano Zampini } else { 374532fe681dSStefano Zampini double pg = (double)eigs[j + eigs_start]; 374632fe681dSStefano Zampini if (pg < 2 * PETSC_SMALL) pg = 0.0; 374732fe681dSStefano Zampini PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.6e\n", pg)); 374832fe681dSStefano Zampini } 374908122e43SStefano Zampini } 375008122e43SStefano Zampini } 3751aff50787SStefano Zampini } 37526c3e6151SStefano Zampini /* change the basis back to the original one */ 37536c3e6151SStefano Zampini if (sub_schurs->change) { 375472b8c272SStefano Zampini Mat change, phi, phit; 37556c3e6151SStefano Zampini 375603dfb2d7SStefano Zampini if (pcbddc->dbg_flag > 2) { 37576c3e6151SStefano Zampini PetscInt ii; 37586c3e6151SStefano Zampini for (ii = 0; ii < B_neigs; ii++) { 375963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " -> Eigenvector (old basis) %" PetscInt_FMT "/%" PetscBLASInt_FMT " (%" PetscBLASInt_FMT ")\n", ii, B_neigs, B_N)); 37606c3e6151SStefano Zampini for (j = 0; j < B_N; j++) { 3761684229deSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3762684229deSStefano Zampini PetscReal r = PetscRealPart(eigv[(ii + eigs_start) * subset_size + j]); 3763684229deSStefano Zampini PetscReal c = PetscImaginaryPart(eigv[(ii + eigs_start) * subset_size + j]); 376463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.4e + %1.4e i\n", (double)r, (double)c)); 3765684229deSStefano Zampini #else 376663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.4e\n", (double)(eigv[(ii + eigs_start) * subset_size + j]))); 3767684229deSStefano Zampini #endif 37686c3e6151SStefano Zampini } 37696c3e6151SStefano Zampini } 37706c3e6151SStefano Zampini } 37719566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(sub_schurs->change[i], &change, NULL)); 37729566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, subset_size, B_neigs, eigv + eigs_start * subset_size, &phit)); 3773fb842aefSJose E. Roman PetscCall(MatMatMult(change, phit, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &phi)); 37749566063dSJacob Faibussowitsch PetscCall(MatCopy(phi, phit, SAME_NONZERO_PATTERN)); 37759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&phit)); 37769566063dSJacob Faibussowitsch PetscCall(MatDestroy(&phi)); 37776c3e6151SStefano Zampini } 37788bec7fa6SStefano Zampini maxneigs = PetscMax(B_neigs, maxneigs); 37798bec7fa6SStefano Zampini pcbddc->adaptive_constraints_n[i + nv] = B_neigs; 37809162d606SStefano Zampini if (B_neigs) { 37819566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pcbddc->adaptive_constraints_data + pcbddc->adaptive_constraints_data_ptr[cum], eigv + eigs_start * subset_size, B_neigs * subset_size)); 3782fd14bc51SStefano Zampini 3783fd14bc51SStefano Zampini if (pcbddc->dbg_flag > 1) { 37849552c7c7SStefano Zampini PetscInt ii; 37859552c7c7SStefano Zampini for (ii = 0; ii < B_neigs; ii++) { 378663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " -> Eigenvector %" PetscInt_FMT "/%" PetscBLASInt_FMT " (%" PetscBLASInt_FMT ")\n", ii, B_neigs, B_N)); 37879552c7c7SStefano Zampini for (j = 0; j < B_N; j++) { 3788ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3789ac47001eSStefano Zampini PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii * subset_size + j + pcbddc->adaptive_constraints_data_ptr[cum]]); 3790ac47001eSStefano Zampini PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii * subset_size + j + pcbddc->adaptive_constraints_data_ptr[cum]]); 379163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.4e + %1.4e i\n", (double)r, (double)c)); 3792ac47001eSStefano Zampini #else 379363a3b9bcSJacob 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]]))); 3794ac47001eSStefano Zampini #endif 37959552c7c7SStefano Zampini } 37969552c7c7SStefano Zampini } 3797fd14bc51SStefano Zampini } 37989566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pcbddc->adaptive_constraints_idxs + pcbddc->adaptive_constraints_idxs_ptr[cum], idxs, subset_size)); 37999162d606SStefano Zampini pcbddc->adaptive_constraints_idxs_ptr[cum + 1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size; 38009162d606SStefano Zampini pcbddc->adaptive_constraints_data_ptr[cum + 1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size * B_neigs; 38019162d606SStefano Zampini cum++; 380208122e43SStefano Zampini } 38039566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(sub_schurs->is_subs[i], &idxs)); 380408122e43SStefano Zampini /* shift for next computation */ 380508122e43SStefano Zampini cumarray += subset_size * subset_size; 380608122e43SStefano Zampini } 38071baa6e33SBarry Smith if (pcbddc->dbg_flag) PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 380808122e43SStefano Zampini 380908122e43SStefano Zampini if (mss) { 381032fe681dSStefano Zampini if (sub_schurs->gdsw) { 381132fe681dSStefano Zampini PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_all, &Sarray)); 381232fe681dSStefano Zampini PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all, &Starray)); 381332fe681dSStefano Zampini } else { 38149566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all, &Sarray)); 38159566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all, &Starray)); 3816f6f667cfSStefano Zampini /* destroy matrices (junk) */ 38179566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sub_schurs->sum_S_Ej_inv_all)); 38189566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sub_schurs->sum_S_Ej_tilda_all)); 381908122e43SStefano Zampini } 382032fe681dSStefano Zampini } 38211baa6e33SBarry Smith if (allocated_S_St) PetscCall(PetscFree2(S, St)); 38229566063dSJacob Faibussowitsch PetscCall(PetscFree5(eigv, eigs, work, B_iwork, B_ifail)); 382308122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 38249566063dSJacob Faibussowitsch PetscCall(PetscFree(rwork)); 382508122e43SStefano Zampini #endif 382608122e43SStefano Zampini if (pcbddc->dbg_flag) { 38271b968477SStefano Zampini PetscInt maxneigs_r; 3828462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&maxneigs, &maxneigs_r, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)pc))); 382963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Maximum number of constraints per cc %" PetscInt_FMT "\n", maxneigs_r)); 383008122e43SStefano Zampini } 38319566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_AdaptiveSetUp[pcbddc->current_level], pc, 0, 0, 0)); 38323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 383308122e43SStefano Zampini } 3834b1b3d7a2SStefano Zampini 3835d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpSolvers(PC pc) 3836d71ae5a4SJacob Faibussowitsch { 38379de2952eSStefano Zampini Mat coarse_submat; 3838c8587f34SStefano Zampini 3839c8587f34SStefano Zampini PetscFunctionBegin; 3840f4ddd8eeSStefano Zampini /* Setup local scatters R_to_B and (optionally) R_to_D */ 38415e8657edSStefano Zampini /* PCBDDCSetUpLocalWorkVectors should be called first! */ 38429566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpLocalScatters(pc)); 3843c8587f34SStefano Zampini 3844684f6988SStefano Zampini /* Setup local neumann solver ksp_R */ 38450fccc4e9SStefano Zampini /* PCBDDCSetUpLocalScatters should be called first! */ 38469566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpLocalSolvers(pc, PETSC_FALSE, PETSC_TRUE)); 3847c8587f34SStefano Zampini 38488629588bSStefano Zampini /* 38498629588bSStefano Zampini Setup local correction and local part of coarse basis. 38508629588bSStefano Zampini Gives back the dense local part of the coarse matrix in column major ordering 38518629588bSStefano Zampini */ 38529de2952eSStefano Zampini PetscCall(PCBDDCSetUpCorrection(pc, &coarse_submat)); 38538629588bSStefano Zampini 38548629588bSStefano Zampini /* Compute total number of coarse nodes and setup coarse solver */ 38559de2952eSStefano Zampini PetscCall(PCBDDCSetUpCoarseSolver(pc, coarse_submat)); 38569de2952eSStefano Zampini PetscCall(MatDestroy(&coarse_submat)); 38573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3858c8587f34SStefano Zampini } 3859c8587f34SStefano Zampini 3860d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCResetCustomization(PC pc) 3861d71ae5a4SJacob Faibussowitsch { 3862674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 3863674ae819SStefano Zampini 3864674ae819SStefano Zampini PetscFunctionBegin; 38659566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices)); 38669566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local)); 38679566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundaries)); 38689566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal)); 38699566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundaries)); 38709566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&pcbddc->onearnullspace)); 38719566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->onearnullvecs_state)); 38729566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal)); 38739566063dSJacob Faibussowitsch PetscCall(PCBDDCSetDofsSplitting(pc, 0, NULL)); 38749566063dSJacob Faibussowitsch PetscCall(PCBDDCSetDofsSplittingLocal(pc, 0, NULL)); 38753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3876674ae819SStefano Zampini } 3877674ae819SStefano Zampini 3878d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCResetTopography(PC pc) 3879d71ae5a4SJacob Faibussowitsch { 3880674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 38814f1b2e48SStefano Zampini PetscInt i; 3882674ae819SStefano Zampini 3883674ae819SStefano Zampini PetscFunctionBegin; 38849566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->nedcG)); 38859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->nedclocal)); 38869566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->discretegradient)); 38879566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->user_ChangeOfBasisMatrix)); 38889566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->ChangeOfBasisMatrix)); 38899566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->switch_static_change)); 38909566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->work_change)); 38919566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->ConstraintMatrix)); 38929566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->divudotp)); 38939566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->divudotp_vl2l)); 38949566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphDestroy(&pcbddc->mat_graph)); 389548a46eb9SPierre Jolivet for (i = 0; i < pcbddc->n_local_subs; i++) PetscCall(ISDestroy(&pcbddc->local_subs[i])); 3896e68a0315Sstefano_zampini pcbddc->n_local_subs = 0; 38979566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->local_subs)); 38989566063dSJacob Faibussowitsch PetscCall(PCBDDCSubSchursDestroy(&pcbddc->sub_schurs)); 3899c703fcc7SStefano Zampini pcbddc->graphanalyzed = PETSC_FALSE; 39008af8fcf9SStefano Zampini pcbddc->recompute_topography = PETSC_TRUE; 39011c7a958bSStefano Zampini pcbddc->corner_selected = PETSC_FALSE; 39023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3903674ae819SStefano Zampini } 3904674ae819SStefano Zampini 3905d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCResetSolvers(PC pc) 3906d71ae5a4SJacob Faibussowitsch { 3907674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 3908674ae819SStefano Zampini 3909674ae819SStefano Zampini PetscFunctionBegin; 39109566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->coarse_vec)); 39119566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_phi_B)); 39129566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_phi_D)); 39139566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_psi_B)); 39149566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_psi_D)); 39159566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_P)); 39169566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_C)); 39179566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_auxmat2)); 39189566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_auxmat1)); 39199566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_R)); 39209566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec2_R)); 39219566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->is_R_local)); 39229566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->R_to_B)); 39239566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->R_to_D)); 39249566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->coarse_loc_to_glob)); 39259566063dSJacob Faibussowitsch PetscCall(KSPReset(pcbddc->ksp_D)); 39269566063dSJacob Faibussowitsch PetscCall(KSPReset(pcbddc->ksp_R)); 39279566063dSJacob Faibussowitsch PetscCall(KSPReset(pcbddc->coarse_ksp)); 39289566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 39299566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->primal_indices_local_idxs)); 39309566063dSJacob Faibussowitsch PetscCall(PetscFree2(pcbddc->local_primal_ref_node, pcbddc->local_primal_ref_mult)); 39319566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->global_primal_indices)); 39329566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->coarse_subassembling)); 39339566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->benign_change)); 39349566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->benign_vec)); 39359566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignShellMat(pc, PETSC_TRUE)); 39369566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->benign_B0)); 39379566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pcbddc->benign_sf)); 3938ca92afb2SStefano Zampini if (pcbddc->benign_zerodiag_subs) { 3939ca92afb2SStefano Zampini PetscInt i; 394048a46eb9SPierre Jolivet for (i = 0; i < pcbddc->benign_n; i++) PetscCall(ISDestroy(&pcbddc->benign_zerodiag_subs[i])); 39419566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->benign_zerodiag_subs)); 3942ca92afb2SStefano Zampini } 39439566063dSJacob Faibussowitsch PetscCall(PetscFree3(pcbddc->benign_p0_lidx, pcbddc->benign_p0_gidx, pcbddc->benign_p0)); 39443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3945674ae819SStefano Zampini } 3946674ae819SStefano Zampini 3947d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc) 3948d71ae5a4SJacob Faibussowitsch { 39496bfb1811SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 39506bfb1811SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 39516bfb1811SStefano Zampini VecType impVecType; 39524f1b2e48SStefano Zampini PetscInt n_constraints, n_R, old_size; 39536bfb1811SStefano Zampini 39546bfb1811SStefano Zampini PetscFunctionBegin; 39554f1b2e48SStefano Zampini n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices; 3956b371cd4fSStefano Zampini n_R = pcis->n - pcbddc->n_vertices; 39579566063dSJacob Faibussowitsch PetscCall(VecGetType(pcis->vec1_N, &impVecType)); 3958e7b262bdSStefano Zampini /* local work vectors (try to avoid unneeded work)*/ 3959e7b262bdSStefano Zampini /* R nodes */ 3960e7b262bdSStefano Zampini old_size = -1; 396148a46eb9SPierre Jolivet if (pcbddc->vec1_R) PetscCall(VecGetSize(pcbddc->vec1_R, &old_size)); 3962e7b262bdSStefano Zampini if (n_R != old_size) { 39639566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_R)); 39649566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec2_R)); 39659566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N), &pcbddc->vec1_R)); 39669566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pcbddc->vec1_R, PETSC_DECIDE, n_R)); 39679566063dSJacob Faibussowitsch PetscCall(VecSetType(pcbddc->vec1_R, impVecType)); 39689566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcbddc->vec1_R, &pcbddc->vec2_R)); 3969e7b262bdSStefano Zampini } 3970e7b262bdSStefano Zampini /* local primal dofs */ 3971e7b262bdSStefano Zampini old_size = -1; 397248a46eb9SPierre Jolivet if (pcbddc->vec1_P) PetscCall(VecGetSize(pcbddc->vec1_P, &old_size)); 3973e9189074SStefano Zampini if (pcbddc->local_primal_size != old_size) { 39749566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_P)); 39759566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N), &pcbddc->vec1_P)); 39769566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pcbddc->vec1_P, PETSC_DECIDE, pcbddc->local_primal_size)); 39779566063dSJacob Faibussowitsch PetscCall(VecSetType(pcbddc->vec1_P, impVecType)); 3978e7b262bdSStefano Zampini } 3979e7b262bdSStefano Zampini /* local explicit constraints */ 3980e7b262bdSStefano Zampini old_size = -1; 398148a46eb9SPierre Jolivet if (pcbddc->vec1_C) PetscCall(VecGetSize(pcbddc->vec1_C, &old_size)); 3982e7b262bdSStefano Zampini if (n_constraints && n_constraints != old_size) { 39839566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_C)); 39849566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N), &pcbddc->vec1_C)); 39859566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pcbddc->vec1_C, PETSC_DECIDE, n_constraints)); 39869566063dSJacob Faibussowitsch PetscCall(VecSetType(pcbddc->vec1_C, impVecType)); 398783b7ccabSStefano Zampini } 39883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 39896bfb1811SStefano Zampini } 39906bfb1811SStefano Zampini 39919de2952eSStefano Zampini static PetscErrorCode MatSetValuesSubMat(Mat A, Mat S, PetscInt nr, const PetscInt rows[], PetscInt nc, const PetscInt cols[], InsertMode imode) 3992d71ae5a4SJacob Faibussowitsch { 39939de2952eSStefano Zampini PetscBool flg; 39949de2952eSStefano Zampini const PetscScalar *a; 39959de2952eSStefano Zampini 39969de2952eSStefano Zampini PetscFunctionBegin; 39979de2952eSStefano Zampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)S, MATSEQDENSE, &flg)); 39989de2952eSStefano Zampini if (flg) { 39999de2952eSStefano Zampini PetscCall(MatDenseGetArrayRead(S, &a)); 40009de2952eSStefano Zampini PetscCall(MatSetOption(A, MAT_ROW_ORIENTED, PETSC_FALSE)); 40019de2952eSStefano Zampini PetscCall(MatSetValues(A, nr, rows, nc, cols, a, imode)); 40029de2952eSStefano Zampini PetscCall(MatSetOption(A, MAT_ROW_ORIENTED, PETSC_TRUE)); 40039de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayRead(S, &a)); 40049de2952eSStefano Zampini } else { 40059de2952eSStefano Zampini const PetscInt *ii, *jj; 40069de2952eSStefano Zampini PetscInt n; 40079de2952eSStefano Zampini PetscInt buf[8192], *bufc = NULL; 40089de2952eSStefano Zampini PetscBool freeb = PETSC_FALSE; 40099de2952eSStefano Zampini Mat Sm = S; 40109de2952eSStefano Zampini 40119de2952eSStefano Zampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)S, MATSEQAIJ, &flg)); 40129de2952eSStefano Zampini if (!flg) PetscCall(MatConvert(S, MATSEQAIJ, MAT_INITIAL_MATRIX, &Sm)); 40139de2952eSStefano Zampini else PetscCall(PetscObjectReference((PetscObject)S)); 40149de2952eSStefano Zampini PetscCall(MatSeqAIJGetArrayRead(Sm, &a)); 40159de2952eSStefano Zampini PetscCall(MatGetRowIJ(Sm, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &flg)); 40169de2952eSStefano Zampini PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Cannot get IJ structure"); 40179de2952eSStefano Zampini if (nc <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 40189de2952eSStefano Zampini bufc = buf; 40199de2952eSStefano Zampini } else { 40209de2952eSStefano Zampini PetscCall(PetscMalloc1(nc, &bufc)); 40219de2952eSStefano Zampini freeb = PETSC_TRUE; 40229de2952eSStefano Zampini } 40239de2952eSStefano Zampini 40249de2952eSStefano Zampini for (PetscInt i = 0; i < n; i++) { 40259de2952eSStefano Zampini const PetscInt nci = ii[i + 1] - ii[i]; 40269de2952eSStefano Zampini 40279de2952eSStefano Zampini for (PetscInt j = 0; j < nci; j++) bufc[j] = cols[jj[ii[i] + j]]; 40289de2952eSStefano Zampini PetscCall(MatSetValues(A, 1, rows + i, nci, bufc, a + ii[i], imode)); 40299de2952eSStefano Zampini } 40309de2952eSStefano Zampini PetscCall(MatRestoreRowIJ(Sm, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &flg)); 40319de2952eSStefano Zampini PetscCall(MatSeqAIJRestoreArrayRead(Sm, &a)); 40329de2952eSStefano Zampini PetscCall(MatDestroy(&Sm)); 40339de2952eSStefano Zampini if (freeb) PetscCall(PetscFree(bufc)); 40349de2952eSStefano Zampini } 40359de2952eSStefano Zampini PetscCall(MatAssemblyBegin(A, MAT_FLUSH_ASSEMBLY)); 40369de2952eSStefano Zampini PetscCall(MatAssemblyEnd(A, MAT_FLUSH_ASSEMBLY)); 40379de2952eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 40389de2952eSStefano Zampini } 40399de2952eSStefano Zampini 40409de2952eSStefano Zampini static PetscErrorCode MatCreateSeqAIJFromDenseExpand(Mat D, PetscInt n, const PetscInt j[], Mat *mat) 40419de2952eSStefano Zampini { 40429de2952eSStefano Zampini Mat_SeqAIJ *aij; 40439de2952eSStefano Zampini PetscInt *ii, *jj; 40449de2952eSStefano Zampini PetscScalar *aa; 40459de2952eSStefano Zampini PetscInt nnz = 0, m, nc; 40469de2952eSStefano Zampini const PetscScalar *a; 40479de2952eSStefano Zampini const PetscScalar zero = 0.0; 40489de2952eSStefano Zampini 40499de2952eSStefano Zampini PetscFunctionBegin; 40509de2952eSStefano Zampini PetscCall(MatGetLocalSize(D, &m, &nc)); 40519de2952eSStefano Zampini PetscCall(MatDenseGetArrayRead(D, &a)); 40529de2952eSStefano Zampini PetscCall(PetscMalloc1(m + 1, &ii)); 40539de2952eSStefano Zampini PetscCall(PetscMalloc1(m * nc, &jj)); 40549de2952eSStefano Zampini PetscCall(PetscMalloc1(m * nc, &aa)); 40559de2952eSStefano Zampini ii[0] = 0; 40569de2952eSStefano Zampini for (PetscInt k = 0; k < m; k++) { 40579de2952eSStefano Zampini for (PetscInt s = 0; s < nc; s++) { 40589de2952eSStefano Zampini const PetscInt c = s + k * nc; 40599de2952eSStefano Zampini const PetscScalar v = a[k + s * m]; 40609de2952eSStefano Zampini 40619de2952eSStefano Zampini if (PetscUnlikely(j[c] < 0 || v == zero)) continue; 40629de2952eSStefano Zampini jj[nnz] = j[c]; 40639de2952eSStefano Zampini aa[nnz] = a[k + s * m]; 40649de2952eSStefano Zampini nnz++; 40659de2952eSStefano Zampini } 40669de2952eSStefano Zampini ii[k + 1] = nnz; 40679de2952eSStefano Zampini } 40689de2952eSStefano Zampini 40699de2952eSStefano Zampini PetscCall(MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)D), m, n, ii, jj, aa, mat)); 40709de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayRead(D, &a)); 40719de2952eSStefano Zampini 40729de2952eSStefano Zampini aij = (Mat_SeqAIJ *)(*mat)->data; 40739de2952eSStefano Zampini aij->free_a = PETSC_TRUE; 40749de2952eSStefano Zampini aij->free_ij = PETSC_TRUE; 40759de2952eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 40769de2952eSStefano Zampini } 40779de2952eSStefano Zampini 40789de2952eSStefano Zampini /* adapted from MatInvertVariableBlockDiagonal_SeqAIJ */ 40799de2952eSStefano Zampini static PetscErrorCode MatSeqAIJInvertVariableBlockDiagonalMat(Mat A, PetscInt nblocks, const PetscInt *bsizes, Mat *B) 40809de2952eSStefano Zampini { 40819de2952eSStefano Zampini PetscInt n = A->rmap->n, ncnt = 0, ncnt2 = 0, bsizemax = 0, *v_pivots = NULL; 40829de2952eSStefano Zampini const PetscBool allowzeropivot = PETSC_FALSE; 40839de2952eSStefano Zampini PetscBool zeropivotdetected = PETSC_FALSE; 40849de2952eSStefano Zampini const PetscReal shift = 0.0; 40859de2952eSStefano Zampini PetscInt ipvt[5], *ii, *jj, *indi, *indj; 40869de2952eSStefano Zampini PetscScalar work[25], *v_work = NULL, *aa, *diag; 40879de2952eSStefano Zampini PetscLogDouble flops = 0.0; 40889de2952eSStefano Zampini 40899de2952eSStefano Zampini PetscFunctionBegin; 40909de2952eSStefano Zampini PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Not for rectangular matrices"); 40919de2952eSStefano Zampini for (PetscInt i = 0; i < nblocks; i++) { 40929de2952eSStefano Zampini ncnt += bsizes[i]; 40939de2952eSStefano Zampini ncnt2 += PetscSqr(bsizes[i]); 40949de2952eSStefano Zampini } 40959de2952eSStefano 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); 40969de2952eSStefano Zampini for (PetscInt i = 0; i < nblocks; i++) bsizemax = PetscMax(bsizemax, bsizes[i]); 40979de2952eSStefano Zampini if (bsizemax > 7) PetscCall(PetscMalloc2(bsizemax, &v_work, bsizemax, &v_pivots)); 40989de2952eSStefano Zampini 40999de2952eSStefano Zampini PetscCall(PetscMalloc1(n + 1, &ii)); 41009de2952eSStefano Zampini PetscCall(PetscMalloc1(ncnt2, &jj)); 41019de2952eSStefano Zampini PetscCall(PetscCalloc1(ncnt2, &aa)); 41029de2952eSStefano Zampini 41039de2952eSStefano Zampini ncnt = 0; 41049de2952eSStefano Zampini ii[0] = 0; 41059de2952eSStefano Zampini indi = ii; 41069de2952eSStefano Zampini indj = jj; 41079de2952eSStefano Zampini diag = aa; 41089de2952eSStefano Zampini for (PetscInt i = 0; i < nblocks; i++) { 41099de2952eSStefano Zampini const PetscInt bs = bsizes[i]; 41109de2952eSStefano Zampini 41119de2952eSStefano Zampini for (PetscInt k = 0; k < bs; k++) { 41129de2952eSStefano Zampini indi[k + 1] = indi[k] + bs; 41139de2952eSStefano Zampini for (PetscInt j = 0; j < bs; j++) indj[k * bs + j] = ncnt + j; 41149de2952eSStefano Zampini } 41159de2952eSStefano Zampini PetscCall(MatGetValues(A, bs, indj, bs, indj, diag)); 41169de2952eSStefano Zampini switch (bs) { 41179de2952eSStefano Zampini case 1: 41189de2952eSStefano Zampini *diag = 1.0 / (*diag); 41199de2952eSStefano Zampini break; 41209de2952eSStefano Zampini case 2: 41219de2952eSStefano Zampini PetscCall(PetscKernel_A_gets_inverse_A_2(diag, shift, allowzeropivot, &zeropivotdetected)); 41229de2952eSStefano Zampini break; 41239de2952eSStefano Zampini case 3: 41249de2952eSStefano Zampini PetscCall(PetscKernel_A_gets_inverse_A_3(diag, shift, allowzeropivot, &zeropivotdetected)); 41259de2952eSStefano Zampini break; 41269de2952eSStefano Zampini case 4: 41279de2952eSStefano Zampini PetscCall(PetscKernel_A_gets_inverse_A_4(diag, shift, allowzeropivot, &zeropivotdetected)); 41289de2952eSStefano Zampini break; 41299de2952eSStefano Zampini case 5: 41309de2952eSStefano Zampini PetscCall(PetscKernel_A_gets_inverse_A_5(diag, ipvt, work, shift, allowzeropivot, &zeropivotdetected)); 41319de2952eSStefano Zampini break; 41329de2952eSStefano Zampini case 6: 41339de2952eSStefano Zampini PetscCall(PetscKernel_A_gets_inverse_A_6(diag, shift, allowzeropivot, &zeropivotdetected)); 41349de2952eSStefano Zampini break; 41359de2952eSStefano Zampini case 7: 41369de2952eSStefano Zampini PetscCall(PetscKernel_A_gets_inverse_A_7(diag, shift, allowzeropivot, &zeropivotdetected)); 41379de2952eSStefano Zampini break; 41389de2952eSStefano Zampini default: 41399de2952eSStefano Zampini PetscCall(PetscKernel_A_gets_inverse_A(bs, diag, v_pivots, v_work, allowzeropivot, &zeropivotdetected)); 41409de2952eSStefano Zampini } 41419de2952eSStefano Zampini ncnt += bs; 41429de2952eSStefano Zampini flops += 2.0 * PetscPowInt(bs, 3) / 3.0; 41439de2952eSStefano Zampini diag += bs * bs; 41449de2952eSStefano Zampini indj += bs * bs; 41459de2952eSStefano Zampini indi += bs; 41469de2952eSStefano Zampini } 41479de2952eSStefano Zampini PetscCall(PetscLogFlops(flops)); 41489de2952eSStefano Zampini PetscCall(PetscFree2(v_work, v_pivots)); 41499de2952eSStefano Zampini PetscCall(MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A), n, n, ii, jj, aa, B)); 41509de2952eSStefano Zampini { 41519de2952eSStefano Zampini Mat_SeqAIJ *aij = (Mat_SeqAIJ *)(*B)->data; 41529de2952eSStefano Zampini aij->free_a = PETSC_TRUE; 41539de2952eSStefano Zampini aij->free_ij = PETSC_TRUE; 41549de2952eSStefano Zampini } 41559de2952eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 41569de2952eSStefano Zampini } 41579de2952eSStefano Zampini 41589de2952eSStefano Zampini static PetscErrorCode MatDenseScatter(Mat A, PetscSF sf, Mat B) 41599de2952eSStefano Zampini { 41609de2952eSStefano Zampini const PetscScalar *rarr; 41619de2952eSStefano Zampini PetscScalar *larr; 41629de2952eSStefano Zampini PetscSF vsf; 41639de2952eSStefano Zampini PetscInt n, rld, lld; 41649de2952eSStefano Zampini 41659de2952eSStefano Zampini PetscFunctionBegin; 41669de2952eSStefano Zampini PetscCall(MatGetSize(A, NULL, &n)); 41679de2952eSStefano Zampini PetscCall(MatDenseGetLDA(A, &rld)); 41689de2952eSStefano Zampini PetscCall(MatDenseGetLDA(B, &lld)); 41699de2952eSStefano Zampini PetscCall(MatDenseGetArrayRead(A, &rarr)); 41709de2952eSStefano Zampini PetscCall(MatDenseGetArrayWrite(B, &larr)); 41719de2952eSStefano Zampini PetscCall(PetscSFCreateStridedSF(sf, n, rld, lld, &vsf)); 41729de2952eSStefano Zampini PetscCall(PetscSFBcastBegin(vsf, MPIU_SCALAR, rarr, larr, MPI_REPLACE)); 41739de2952eSStefano Zampini PetscCall(PetscSFBcastEnd(vsf, MPIU_SCALAR, rarr, larr, MPI_REPLACE)); 41749de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayRead(A, &rarr)); 41759de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayWrite(B, &larr)); 41769de2952eSStefano Zampini PetscCall(PetscSFDestroy(&vsf)); 41779de2952eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 41789de2952eSStefano Zampini } 41799de2952eSStefano Zampini 41809de2952eSStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, Mat *coarse_submat) 41819de2952eSStefano Zampini { 418288ebb749SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 418388ebb749SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 41849de2952eSStefano Zampini PCBDDCGraph graph = pcbddc->mat_graph; 4185d62866d3SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 418625084f0cSStefano Zampini /* submatrices of local problem */ 41879de2952eSStefano Zampini Mat A_RV = NULL, A_VR, A_VV, local_auxmat2_R = NULL; 418806656605SStefano Zampini /* submatrices of local coarse problem */ 41899de2952eSStefano Zampini Mat S_CV = NULL, S_VC = NULL, S_CC = NULL; 419025084f0cSStefano Zampini /* working matrices */ 419106656605SStefano Zampini Mat C_CR; 41929de2952eSStefano Zampini 419325084f0cSStefano Zampini /* additional working stuff */ 419406656605SStefano Zampini PC pc_R; 41959de2952eSStefano Zampini IS is_R, is_V, is_C; 41969de2952eSStefano Zampini const PetscInt *idx_V, *idx_C; 4197c58f9fdbSStefano Zampini Mat F, Brhs = NULL; 41985cbda25cSStefano Zampini Vec dummy_vec; 41997ebab0bbSStefano Zampini PetscBool isLU, isCHOL, need_benign_correction, sparserhs; 420006656605SStefano Zampini PetscInt *idx_V_B; 42019de2952eSStefano Zampini PetscInt lda_rhs, n_vertices, n_constraints, *p0_lidx_I; 42029de2952eSStefano Zampini PetscInt n_eff_vertices, n_eff_constraints; 420306656605SStefano Zampini PetscInt i, n_R, n_D, n_B; 420406656605SStefano Zampini PetscScalar one = 1.0, m_one = -1.0; 420588ebb749SStefano Zampini 42069de2952eSStefano Zampini /* Multi-element support */ 42079de2952eSStefano Zampini PetscBool multi_element = graph->multi_element; 42089de2952eSStefano Zampini PetscInt *V_to_eff_V = NULL, *C_to_eff_C = NULL; 42099de2952eSStefano Zampini PetscInt *B_eff_V_J = NULL, *R_eff_V_J = NULL, *B_eff_C_J = NULL, *R_eff_C_J = NULL; 42109de2952eSStefano Zampini IS is_C_perm = NULL; 42119de2952eSStefano Zampini PetscInt n_C_bss = 0, *C_bss = NULL; 42129de2952eSStefano Zampini Mat coarse_phi_multi; 42139de2952eSStefano Zampini 421488ebb749SStefano Zampini PetscFunctionBegin; 42157827d75bSBarry 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"); 42169566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_CorrectionSetUp[pcbddc->current_level], pc, 0, 0, 0)); 4217ffd830a3SStefano Zampini 4218ffd830a3SStefano Zampini /* Set Non-overlapping dimensions */ 4219b371cd4fSStefano Zampini n_vertices = pcbddc->n_vertices; 42204f1b2e48SStefano Zampini n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices; 4221b371cd4fSStefano Zampini n_B = pcis->n_B; 4222b371cd4fSStefano Zampini n_D = pcis->n - n_B; 422388ebb749SStefano Zampini n_R = pcis->n - n_vertices; 422488ebb749SStefano Zampini 422588ebb749SStefano Zampini /* vertices in boundary numbering */ 42269566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_vertices, &idx_V_B)); 42279566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(pcis->BtoNmap, IS_GTOLM_DROP, n_vertices, pcbddc->local_primal_ref_node, &i, idx_V_B)); 422863a3b9bcSJacob 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); 422988ebb749SStefano Zampini 42309de2952eSStefano Zampini /* these two cases still need to be optimized */ 42319de2952eSStefano Zampini if (pcbddc->benign_saddle_point || !pcbddc->symmetric_primal) multi_element = PETSC_FALSE; 42329de2952eSStefano Zampini 423306656605SStefano Zampini /* Subdomain contribution (Non-overlapping) to coarse matrix */ 42349de2952eSStefano Zampini if (multi_element) { 42359de2952eSStefano Zampini PetscCheck(!pcbddc->benign_n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not yet implemented"); 42369de2952eSStefano Zampini 42379de2952eSStefano Zampini PetscCall(MatCreate(PETSC_COMM_SELF, coarse_submat)); 42389de2952eSStefano Zampini PetscCall(MatSetSizes(*coarse_submat, pcbddc->local_primal_size, pcbddc->local_primal_size, pcbddc->local_primal_size, pcbddc->local_primal_size)); 42399de2952eSStefano Zampini PetscCall(MatSetType(*coarse_submat, MATSEQAIJ)); 42409de2952eSStefano Zampini PetscCall(MatSetOption(*coarse_submat, MAT_IGNORE_ZERO_ENTRIES, PETSC_TRUE)); 42419de2952eSStefano Zampini PetscCall(MatSetOption(*coarse_submat, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 42429de2952eSStefano Zampini 42439de2952eSStefano Zampini /* group vertices and constraints by subdomain id */ 42449de2952eSStefano Zampini const PetscInt *vidxs = pcbddc->primal_indices_local_idxs; 42459de2952eSStefano Zampini const PetscInt *cidxs = pcbddc->primal_indices_local_idxs + n_vertices; 42469de2952eSStefano Zampini PetscInt *count_eff, *V_eff_to_V, *C_eff_to_C, *nnz; 42479de2952eSStefano Zampini PetscInt n_el = PetscMax(graph->n_local_subs, 1); 42489de2952eSStefano Zampini 42499de2952eSStefano Zampini PetscCall(PetscCalloc1(2 * n_el, &count_eff)); 42509de2952eSStefano Zampini PetscCall(PetscMalloc1(n_vertices, &V_to_eff_V)); 42519de2952eSStefano Zampini PetscCall(PetscMalloc1(n_constraints, &C_to_eff_C)); 42529de2952eSStefano Zampini for (PetscInt i = 0; i < n_vertices; i++) { 42539de2952eSStefano Zampini PetscInt s = 2 * graph->nodes[vidxs[i]].local_sub; 42549de2952eSStefano Zampini 42559de2952eSStefano Zampini V_to_eff_V[i] = count_eff[s]; 42569de2952eSStefano Zampini count_eff[s] += 1; 42579de2952eSStefano Zampini } 42589de2952eSStefano Zampini for (PetscInt i = 0; i < n_constraints; i++) { 42599de2952eSStefano Zampini PetscInt s = 2 * graph->nodes[cidxs[i]].local_sub + 1; 42609de2952eSStefano Zampini 42619de2952eSStefano Zampini C_to_eff_C[i] = count_eff[s]; 42629de2952eSStefano Zampini count_eff[s] += 1; 42639de2952eSStefano Zampini } 42649de2952eSStefano Zampini 42659de2952eSStefano Zampini /* preallocation */ 42669de2952eSStefano Zampini PetscCall(PetscMalloc1(n_vertices + n_constraints, &nnz)); 42679de2952eSStefano Zampini for (PetscInt i = 0; i < n_vertices; i++) { 42689de2952eSStefano Zampini PetscInt s = 2 * graph->nodes[vidxs[i]].local_sub; 42699de2952eSStefano Zampini 42709de2952eSStefano Zampini nnz[i] = count_eff[s] + count_eff[s + 1]; 42719de2952eSStefano Zampini } 42729de2952eSStefano Zampini for (PetscInt i = 0; i < n_constraints; i++) { 42739de2952eSStefano Zampini PetscInt s = 2 * graph->nodes[cidxs[i]].local_sub; 42749de2952eSStefano Zampini 42759de2952eSStefano Zampini nnz[i + n_vertices] = count_eff[s] + count_eff[s + 1]; 42769de2952eSStefano Zampini } 42779de2952eSStefano Zampini PetscCall(MatSeqAIJSetPreallocation(*coarse_submat, 0, nnz)); 42789de2952eSStefano Zampini PetscCall(PetscFree(nnz)); 42799de2952eSStefano Zampini 42809de2952eSStefano Zampini n_eff_vertices = 0; 42819de2952eSStefano Zampini n_eff_constraints = 0; 42829de2952eSStefano Zampini for (PetscInt i = 0; i < n_el; i++) { 42839de2952eSStefano Zampini n_eff_vertices = PetscMax(n_eff_vertices, count_eff[2 * i]); 42849de2952eSStefano Zampini n_eff_constraints = PetscMax(n_eff_constraints, count_eff[2 * i + 1]); 42859de2952eSStefano Zampini count_eff[2 * i] = 0; 42869de2952eSStefano Zampini count_eff[2 * i + 1] = 0; 42879de2952eSStefano Zampini } 42889de2952eSStefano Zampini 42899de2952eSStefano Zampini const PetscInt *idx; 42909de2952eSStefano Zampini PetscCall(PetscMalloc2(n_el * n_eff_vertices, &V_eff_to_V, n_el * n_eff_constraints, &C_eff_to_C)); 42919de2952eSStefano Zampini 42929de2952eSStefano Zampini for (PetscInt i = 0; i < n_vertices; i++) { 42939de2952eSStefano Zampini const PetscInt e = graph->nodes[vidxs[i]].local_sub; 42949de2952eSStefano Zampini const PetscInt s = 2 * e; 42959de2952eSStefano Zampini 42969de2952eSStefano Zampini V_eff_to_V[e * n_eff_vertices + count_eff[s]] = i; 42979de2952eSStefano Zampini count_eff[s] += 1; 42989de2952eSStefano Zampini } 42999de2952eSStefano Zampini for (PetscInt i = 0; i < n_constraints; i++) { 43009de2952eSStefano Zampini const PetscInt e = graph->nodes[cidxs[i]].local_sub; 43019de2952eSStefano Zampini const PetscInt s = 2 * e + 1; 43029de2952eSStefano Zampini 43039de2952eSStefano Zampini C_eff_to_C[e * n_eff_constraints + count_eff[s]] = i; 43049de2952eSStefano Zampini count_eff[s] += 1; 43059de2952eSStefano Zampini } 43069de2952eSStefano Zampini 43079de2952eSStefano Zampini PetscCall(PetscMalloc1(n_R * n_eff_vertices, &R_eff_V_J)); 43089de2952eSStefano Zampini PetscCall(PetscMalloc1(n_R * n_eff_constraints, &R_eff_C_J)); 43099de2952eSStefano Zampini PetscCall(PetscMalloc1(n_B * n_eff_vertices, &B_eff_V_J)); 43109de2952eSStefano Zampini PetscCall(PetscMalloc1(n_B * n_eff_constraints, &B_eff_C_J)); 43119de2952eSStefano Zampini for (PetscInt i = 0; i < n_R * n_eff_vertices; i++) R_eff_V_J[i] = -1; 43129de2952eSStefano Zampini for (PetscInt i = 0; i < n_R * n_eff_constraints; i++) R_eff_C_J[i] = -1; 43139de2952eSStefano Zampini for (PetscInt i = 0; i < n_B * n_eff_vertices; i++) B_eff_V_J[i] = -1; 43149de2952eSStefano Zampini for (PetscInt i = 0; i < n_B * n_eff_constraints; i++) B_eff_C_J[i] = -1; 43159de2952eSStefano Zampini 43169de2952eSStefano Zampini PetscCall(ISGetIndices(pcbddc->is_R_local, &idx)); 43179de2952eSStefano Zampini for (PetscInt i = 0; i < n_R; i++) { 43189de2952eSStefano Zampini const PetscInt e = graph->nodes[idx[i]].local_sub; 43199de2952eSStefano Zampini const PetscInt s = 2 * e; 43209de2952eSStefano Zampini PetscInt j; 43219de2952eSStefano Zampini 43229de2952eSStefano 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]; 43239de2952eSStefano 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]; 43249de2952eSStefano Zampini } 43259de2952eSStefano Zampini PetscCall(ISRestoreIndices(pcbddc->is_R_local, &idx)); 43269de2952eSStefano Zampini PetscCall(ISGetIndices(pcis->is_B_local, &idx)); 43279de2952eSStefano Zampini for (PetscInt i = 0; i < n_B; i++) { 43289de2952eSStefano Zampini const PetscInt e = graph->nodes[idx[i]].local_sub; 43299de2952eSStefano Zampini const PetscInt s = 2 * e; 43309de2952eSStefano Zampini PetscInt j; 43319de2952eSStefano Zampini 43329de2952eSStefano 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]; 43339de2952eSStefano 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]; 43349de2952eSStefano Zampini } 43359de2952eSStefano Zampini PetscCall(ISRestoreIndices(pcis->is_B_local, &idx)); 43369de2952eSStefano Zampini 43379de2952eSStefano Zampini /* permutation and blocksizes for block invert of S_CC */ 43389de2952eSStefano Zampini PetscInt *idxp; 43399de2952eSStefano Zampini 43409de2952eSStefano Zampini PetscCall(PetscMalloc1(n_constraints, &idxp)); 43419de2952eSStefano Zampini PetscCall(PetscMalloc1(n_el, &C_bss)); 43429de2952eSStefano Zampini n_C_bss = 0; 43439de2952eSStefano Zampini for (PetscInt e = 0, cnt = 0; e < n_el; e++) { 43449de2952eSStefano Zampini const PetscInt nc = count_eff[2 * e + 1]; 43459de2952eSStefano Zampini 43469de2952eSStefano Zampini if (nc) C_bss[n_C_bss++] = nc; 43479de2952eSStefano Zampini for (PetscInt c = 0; c < nc; c++) { idxp[cnt + c] = C_eff_to_C[e * n_eff_constraints + c]; } 43489de2952eSStefano Zampini cnt += nc; 43499de2952eSStefano Zampini } 43509de2952eSStefano Zampini 43519de2952eSStefano Zampini PetscCall(ISCreateGeneral(PETSC_COMM_SELF, n_constraints, idxp, PETSC_OWN_POINTER, &is_C_perm)); 43529de2952eSStefano Zampini 43539de2952eSStefano Zampini PetscCall(PetscFree2(V_eff_to_V, C_eff_to_C)); 43549de2952eSStefano Zampini PetscCall(PetscFree(count_eff)); 43559de2952eSStefano Zampini } else { 43569de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, pcbddc->local_primal_size, pcbddc->local_primal_size, NULL, coarse_submat)); 43579de2952eSStefano Zampini n_eff_constraints = n_constraints; 43589de2952eSStefano Zampini n_eff_vertices = n_vertices; 43599de2952eSStefano Zampini } 436006656605SStefano Zampini 436106656605SStefano Zampini /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */ 43629566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_R, &pc_R)); 43639566063dSJacob Faibussowitsch PetscCall(PCSetUp(pc_R)); 43649566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_R, PCLU, &isLU)); 43659566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_R, PCCHOLESKY, &isCHOL)); 4366ffd830a3SStefano Zampini lda_rhs = n_R; 4367a3df083aSStefano Zampini need_benign_correction = PETSC_FALSE; 43687ebab0bbSStefano Zampini if (isLU || isCHOL) { 43699566063dSJacob Faibussowitsch PetscCall(PCFactorGetMatrix(pc_R, &F)); 4370b334f244SStefano Zampini } else if (sub_schurs && sub_schurs->reuse_solver) { 4371df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 4372d62866d3SStefano Zampini MatFactorType type; 4373d62866d3SStefano Zampini 4374df4d28bfSStefano Zampini F = reuse_solver->F; 43759566063dSJacob Faibussowitsch PetscCall(MatGetFactorType(F, &type)); 4376d62866d3SStefano Zampini if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE; 43777ebab0bbSStefano Zampini if (type == MAT_FACTOR_LU) isLU = PETSC_TRUE; 43789566063dSJacob Faibussowitsch PetscCall(MatGetSize(F, &lda_rhs, NULL)); 437922db5ddcSStefano Zampini need_benign_correction = (PetscBool)(!!reuse_solver->benign_n); 43807ebab0bbSStefano Zampini } else F = NULL; 438106656605SStefano Zampini 4382c58f9fdbSStefano Zampini /* determine if we can use a sparse right-hand side */ 4383c58f9fdbSStefano Zampini sparserhs = PETSC_FALSE; 43849de2952eSStefano Zampini if (F && !multi_element) { 4385ea799195SBarry Smith MatSolverType solver; 4386c58f9fdbSStefano Zampini 43879566063dSJacob Faibussowitsch PetscCall(MatFactorGetSolverType(F, &solver)); 43889566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(solver, MATSOLVERMUMPS, &sparserhs)); 4389c58f9fdbSStefano Zampini } 4390c58f9fdbSStefano Zampini 43915cbda25cSStefano Zampini /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */ 43925cbda25cSStefano Zampini dummy_vec = NULL; 43935cbda25cSStefano Zampini if (need_benign_correction && lda_rhs != n_R && F) { 43949566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N), &dummy_vec)); 43959566063dSJacob Faibussowitsch PetscCall(VecSetSizes(dummy_vec, lda_rhs, PETSC_DECIDE)); 43969566063dSJacob Faibussowitsch PetscCall(VecSetType(dummy_vec, ((PetscObject)pcis->vec1_N)->type_name)); 43975cbda25cSStefano Zampini } 43985cbda25cSStefano Zampini 43999566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_auxmat1)); 44009566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_auxmat2)); 44017ebab0bbSStefano Zampini 44029de2952eSStefano Zampini PetscCall(ISCreateStride(PETSC_COMM_SELF, n_R, 0, 1, &is_R)); 44039de2952eSStefano Zampini PetscCall(ISCreateStride(PETSC_COMM_SELF, n_vertices, 0, 1, &is_V)); 44049de2952eSStefano Zampini PetscCall(ISCreateStride(PETSC_COMM_SELF, n_constraints, n_vertices, 1, &is_C)); 44059de2952eSStefano Zampini PetscCall(ISGetIndices(is_V, &idx_V)); 44069de2952eSStefano Zampini PetscCall(ISGetIndices(is_C, &idx_C)); 44079de2952eSStefano Zampini 440888ebb749SStefano Zampini /* Precompute stuffs needed for preprocessing and application of BDDC*/ 440988ebb749SStefano Zampini if (n_constraints) { 44109de2952eSStefano Zampini Mat C_B; 441106656605SStefano Zampini 441225084f0cSStefano Zampini /* Extract constraints on R nodes: C_{CR} */ 44139de2952eSStefano Zampini PetscCall(MatCreateSubMatrix(pcbddc->ConstraintMatrix, is_C, pcbddc->is_R_local, MAT_INITIAL_MATRIX, &C_CR)); 44149de2952eSStefano Zampini PetscCall(MatCreateSubMatrix(pcbddc->ConstraintMatrix, is_C, pcis->is_B_local, MAT_INITIAL_MATRIX, &C_B)); 441588ebb749SStefano Zampini 441680677318SStefano Zampini /* Assemble local_auxmat2_R = (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */ 441780677318SStefano Zampini /* Assemble pcbddc->local_auxmat2 = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */ 4418c58f9fdbSStefano Zampini if (!sparserhs) { 44199de2952eSStefano Zampini PetscScalar *marr; 44209de2952eSStefano Zampini 44219de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, lda_rhs, n_eff_constraints, NULL, &Brhs)); 44229de2952eSStefano Zampini PetscCall(MatDenseGetArrayWrite(Brhs, &marr)); 442388ebb749SStefano Zampini for (i = 0; i < n_constraints; i++) { 442406656605SStefano Zampini const PetscScalar *row_cmat_values; 442506656605SStefano Zampini const PetscInt *row_cmat_indices; 44269de2952eSStefano Zampini PetscInt size_of_constraint, j, col = C_to_eff_C ? C_to_eff_C[i] : i; 442788ebb749SStefano Zampini 44289566063dSJacob Faibussowitsch PetscCall(MatGetRow(C_CR, i, &size_of_constraint, &row_cmat_indices, &row_cmat_values)); 44299de2952eSStefano Zampini for (j = 0; j < size_of_constraint; j++) marr[row_cmat_indices[j] + col * lda_rhs] = -row_cmat_values[j]; 44309566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(C_CR, i, &size_of_constraint, &row_cmat_indices, &row_cmat_values)); 443106656605SStefano Zampini } 44329de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayWrite(Brhs, &marr)); 4433c58f9fdbSStefano Zampini } else { 4434c58f9fdbSStefano Zampini Mat tC_CR; 4435c58f9fdbSStefano Zampini 44369566063dSJacob Faibussowitsch PetscCall(MatScale(C_CR, -1.0)); 4437c58f9fdbSStefano Zampini if (lda_rhs != n_R) { 4438c58f9fdbSStefano Zampini PetscScalar *aa; 4439c58f9fdbSStefano Zampini PetscInt r, *ii, *jj; 4440c58f9fdbSStefano Zampini PetscBool done; 4441c58f9fdbSStefano Zampini 44429566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(C_CR, 0, PETSC_FALSE, PETSC_FALSE, &r, (const PetscInt **)&ii, (const PetscInt **)&jj, &done)); 444328b400f6SJacob Faibussowitsch PetscCheck(done, PETSC_COMM_SELF, PETSC_ERR_PLIB, "GetRowIJ failed"); 44449566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(C_CR, &aa)); 44459566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, n_constraints, lda_rhs, ii, jj, aa, &tC_CR)); 44469566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(C_CR, 0, PETSC_FALSE, PETSC_FALSE, &r, (const PetscInt **)&ii, (const PetscInt **)&jj, &done)); 444728b400f6SJacob Faibussowitsch PetscCheck(done, PETSC_COMM_SELF, PETSC_ERR_PLIB, "RestoreRowIJ failed"); 4448c58f9fdbSStefano Zampini } else { 44499566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)C_CR)); 4450c58f9fdbSStefano Zampini tC_CR = C_CR; 4451c58f9fdbSStefano Zampini } 44529566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(tC_CR, &Brhs)); 44539566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tC_CR)); 4454c58f9fdbSStefano Zampini } 44559de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, lda_rhs, n_eff_constraints, NULL, &local_auxmat2_R)); 445606656605SStefano Zampini if (F) { 4457a3df083aSStefano Zampini if (need_benign_correction) { 4458df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 4459a3df083aSStefano Zampini 446072b8c272SStefano Zampini /* rhs is already zero on interior dofs, no need to change the rhs */ 44619566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(reuse_solver->benign_save_vals, pcbddc->benign_n)); 4462a3df083aSStefano Zampini } 44639566063dSJacob Faibussowitsch PetscCall(MatMatSolve(F, Brhs, local_auxmat2_R)); 4464a3df083aSStefano Zampini if (need_benign_correction) { 4465a3df083aSStefano Zampini PetscScalar *marr; 4466df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 4467a3df083aSStefano Zampini 44689de2952eSStefano Zampini /* XXX multi_element? */ 44699566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(local_auxmat2_R, &marr)); 44705cbda25cSStefano Zampini if (lda_rhs != n_R) { 44719de2952eSStefano Zampini for (i = 0; i < n_eff_constraints; i++) { 44729566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dummy_vec, marr + i * lda_rhs)); 44739566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, dummy_vec, NULL, PETSC_TRUE, PETSC_TRUE)); 44749566063dSJacob Faibussowitsch PetscCall(VecResetArray(dummy_vec)); 44755cbda25cSStefano Zampini } 44765cbda25cSStefano Zampini } else { 44779de2952eSStefano Zampini for (i = 0; i < n_eff_constraints; i++) { 44789566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, marr + i * lda_rhs)); 44799566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, pcbddc->vec1_R, NULL, PETSC_TRUE, PETSC_TRUE)); 44809566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 4481a3df083aSStefano Zampini } 44825cbda25cSStefano Zampini } 44839566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(local_auxmat2_R, &marr)); 4484a3df083aSStefano Zampini } 448506656605SStefano Zampini } else { 44869de2952eSStefano Zampini const PetscScalar *barr; 448780677318SStefano Zampini PetscScalar *marr; 448880677318SStefano Zampini 44899de2952eSStefano Zampini PetscCall(MatDenseGetArrayRead(Brhs, &barr)); 44909566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(local_auxmat2_R, &marr)); 44919de2952eSStefano Zampini for (i = 0; i < n_eff_constraints; i++) { 44929de2952eSStefano Zampini PetscCall(VecPlaceArray(pcbddc->vec1_R, barr + i * lda_rhs)); 44939566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec2_R, marr + i * lda_rhs)); 44949566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec2_R)); 44959566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec2_R)); 44969566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 44979566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec2_R)); 449806656605SStefano Zampini } 44999de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayRead(Brhs, &barr)); 45009566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(local_auxmat2_R, &marr)); 450106656605SStefano Zampini } 45021baa6e33SBarry Smith if (sparserhs) PetscCall(MatScale(C_CR, -1.0)); 45039566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Brhs)); 45049de2952eSStefano Zampini /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR})^{-1} */ 450580677318SStefano Zampini if (!pcbddc->switch_static) { 45069de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_B, n_eff_constraints, NULL, &pcbddc->local_auxmat2)); 45079de2952eSStefano Zampini for (i = 0; i < n_eff_constraints; i++) { 4508ab2d12f3SJunchao Zhang Vec r, b; 45099566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVecRead(local_auxmat2_R, i, &r)); 45109566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVec(pcbddc->local_auxmat2, i, &b)); 45119566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, r, b, INSERT_VALUES, SCATTER_FORWARD)); 45129566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, r, b, INSERT_VALUES, SCATTER_FORWARD)); 45139566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVec(pcbddc->local_auxmat2, i, &b)); 45149566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVecRead(local_auxmat2_R, i, &r)); 451580677318SStefano Zampini } 45169de2952eSStefano Zampini if (multi_element) { 45179de2952eSStefano Zampini Mat T; 4518ffd830a3SStefano Zampini 45199de2952eSStefano Zampini PetscCall(MatCreateSeqAIJFromDenseExpand(local_auxmat2_R, n_constraints, R_eff_C_J, &T)); 45209de2952eSStefano Zampini PetscCall(MatDestroy(&local_auxmat2_R)); 45219de2952eSStefano Zampini local_auxmat2_R = T; 45229de2952eSStefano Zampini PetscCall(MatCreateSeqAIJFromDenseExpand(pcbddc->local_auxmat2, n_constraints, B_eff_C_J, &T)); 45239de2952eSStefano Zampini PetscCall(MatDestroy(&pcbddc->local_auxmat2)); 45249de2952eSStefano Zampini pcbddc->local_auxmat2 = T; 45259de2952eSStefano Zampini } 4526fb842aefSJose E. Roman PetscCall(MatMatMult(C_B, pcbddc->local_auxmat2, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &S_CC)); 45279de2952eSStefano Zampini } else { 45289de2952eSStefano Zampini if (multi_element) { 45299de2952eSStefano Zampini Mat T; 45309de2952eSStefano Zampini 45319de2952eSStefano Zampini PetscCall(MatCreateSeqAIJFromDenseExpand(local_auxmat2_R, n_constraints, R_eff_C_J, &T)); 45329de2952eSStefano Zampini PetscCall(MatDestroy(&local_auxmat2_R)); 45339de2952eSStefano Zampini local_auxmat2_R = T; 45349de2952eSStefano Zampini } 45359de2952eSStefano Zampini if (lda_rhs != n_R) { 45369de2952eSStefano Zampini PetscCall(MatCreateSubMatrix(local_auxmat2_R, is_R, NULL, MAT_INITIAL_MATRIX, &pcbddc->local_auxmat2)); 4537ffd830a3SStefano Zampini } else { 45389566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)local_auxmat2_R)); 453980677318SStefano Zampini pcbddc->local_auxmat2 = local_auxmat2_R; 4540ffd830a3SStefano Zampini } 4541fb842aefSJose E. Roman PetscCall(MatMatMult(C_CR, pcbddc->local_auxmat2, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &S_CC)); 454280677318SStefano Zampini } 45439de2952eSStefano Zampini PetscCall(MatScale(S_CC, m_one)); 45449de2952eSStefano Zampini if (multi_element) { 45459de2952eSStefano Zampini Mat T, T2; 45469de2952eSStefano Zampini IS isp, ispi; 45479de2952eSStefano Zampini 45489de2952eSStefano Zampini isp = is_C_perm; 45499de2952eSStefano Zampini 45509de2952eSStefano Zampini PetscCall(ISInvertPermutation(isp, PETSC_DECIDE, &ispi)); 45519de2952eSStefano Zampini PetscCall(MatPermute(S_CC, isp, isp, &T)); 45529de2952eSStefano Zampini PetscCall(MatSeqAIJInvertVariableBlockDiagonalMat(T, n_C_bss, C_bss, &T2)); 45539de2952eSStefano Zampini PetscCall(MatDestroy(&T)); 45549de2952eSStefano Zampini PetscCall(MatDestroy(&S_CC)); 45559de2952eSStefano Zampini PetscCall(MatPermute(T2, ispi, ispi, &S_CC)); 45569de2952eSStefano Zampini PetscCall(MatDestroy(&T2)); 45579de2952eSStefano Zampini PetscCall(ISDestroy(&ispi)); 455880677318SStefano Zampini } else { 45599de2952eSStefano Zampini if (isCHOL) { 45609de2952eSStefano Zampini PetscCall(MatCholeskyFactor(S_CC, NULL, NULL)); 45619de2952eSStefano Zampini } else { 45629de2952eSStefano Zampini PetscCall(MatLUFactor(S_CC, NULL, NULL, NULL)); 456380677318SStefano Zampini } 45649de2952eSStefano Zampini PetscCall(MatSeqDenseInvertFactors_Private(S_CC)); 45659de2952eSStefano Zampini } 456680677318SStefano Zampini /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */ 4567fb842aefSJose E. Roman PetscCall(MatMatMult(S_CC, C_B, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &pcbddc->local_auxmat1)); 45689566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C_B)); 45699de2952eSStefano Zampini PetscCall(MatSetValuesSubMat(*coarse_submat, S_CC, n_constraints, idx_C, n_constraints, idx_C, INSERT_VALUES)); 4570f4ddd8eeSStefano Zampini } 4571fc227af8SStefano Zampini 4572fc227af8SStefano Zampini /* Get submatrices from subdomain matrix */ 457388ebb749SStefano Zampini if (n_vertices) { 45747ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 45757ebab0bbSStefano Zampini PetscBool oldpin; 45767ebab0bbSStefano Zampini #endif 457706656605SStefano Zampini IS is_aux; 45783a50541eSStefano Zampini 4579b334f244SStefano Zampini if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */ 45806816873aSStefano Zampini IS tis; 45816816873aSStefano Zampini 45829566063dSJacob Faibussowitsch PetscCall(ISDuplicate(pcbddc->is_R_local, &tis)); 45839566063dSJacob Faibussowitsch PetscCall(ISSort(tis)); 45849566063dSJacob Faibussowitsch PetscCall(ISComplement(tis, 0, pcis->n, &is_aux)); 45859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tis)); 45866816873aSStefano Zampini } else { 45879566063dSJacob Faibussowitsch PetscCall(ISComplement(pcbddc->is_R_local, 0, pcis->n, &is_aux)); 45886816873aSStefano Zampini } 45897ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 4590b470e4b4SRichard Tran Mills oldpin = pcbddc->local_mat->boundtocpu; 45917ebab0bbSStefano Zampini #endif 45929566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(pcbddc->local_mat, PETSC_TRUE)); 45939566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcbddc->is_R_local, is_aux, MAT_INITIAL_MATRIX, &A_RV)); 45949566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, is_aux, pcbddc->is_R_local, MAT_INITIAL_MATRIX, &A_VR)); 45959de2952eSStefano Zampini /* TODO REMOVE: MatMatMult(A_VR,A_RRmA_RV) below may raise an error */ 45969566063dSJacob Faibussowitsch PetscCall(MatConvert(A_VR, MATSEQAIJ, MAT_INPLACE_MATRIX, &A_VR)); 45979566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, is_aux, is_aux, MAT_INITIAL_MATRIX, &A_VV)); 45987ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 45999566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(pcbddc->local_mat, oldpin)); 46007ebab0bbSStefano Zampini #endif 46019566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_aux)); 460288ebb749SStefano Zampini } 46039de2952eSStefano Zampini PetscCall(ISDestroy(&is_C_perm)); 46049de2952eSStefano Zampini PetscCall(PetscFree(C_bss)); 460588ebb749SStefano Zampini 46064f1b2e48SStefano Zampini p0_lidx_I = NULL; 46074f1b2e48SStefano Zampini if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) { 4608d12edf2fSStefano Zampini const PetscInt *idxs; 4609d12edf2fSStefano Zampini 46109566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_I_local, &idxs)); 46119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->benign_n, &p0_lidx_I)); 461248a46eb9SPierre 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])); 46139566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_I_local, &idxs)); 4614d12edf2fSStefano Zampini } 4615d16cbb6bSStefano Zampini 46169de2952eSStefano Zampini /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */ 46179de2952eSStefano Zampini 46189de2952eSStefano Zampini /* Matrices of coarse basis functions (local) */ 46199de2952eSStefano Zampini PetscCall(MatDestroy(&pcbddc->coarse_phi_B)); 46209de2952eSStefano Zampini PetscCall(MatDestroy(&pcbddc->coarse_psi_B)); 46219de2952eSStefano Zampini PetscCall(MatDestroy(&pcbddc->coarse_phi_D)); 46229de2952eSStefano Zampini PetscCall(MatDestroy(&pcbddc->coarse_psi_D)); 46239de2952eSStefano Zampini if (!multi_element) { 46249de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_B, pcbddc->local_primal_size, NULL, &pcbddc->coarse_phi_B)); 46259de2952eSStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_D, pcbddc->local_primal_size, NULL, &pcbddc->coarse_phi_D)); 46269de2952eSStefano Zampini coarse_phi_multi = NULL; 46279de2952eSStefano Zampini } else { /* Create temporary NEST matrix to hold coarse basis functions blocks */ 46289de2952eSStefano Zampini IS is_rows[2] = {pcbddc->is_R_local, NULL}; 46299de2952eSStefano Zampini IS is_cols[2] = {is_V, is_C}; 46309de2952eSStefano Zampini 46319de2952eSStefano Zampini PetscCall(ISCreateGeneral(PETSC_COMM_SELF, n_vertices, pcbddc->local_primal_ref_node, PETSC_USE_POINTER, &is_rows[1])); 46329de2952eSStefano Zampini PetscCall(MatCreateNest(PETSC_COMM_SELF, 2, is_rows, 2, is_cols, NULL, &coarse_phi_multi)); 46339de2952eSStefano Zampini PetscCall(ISDestroy(&is_rows[1])); 46349de2952eSStefano Zampini } 46359de2952eSStefano Zampini 463606656605SStefano Zampini /* vertices */ 463706656605SStefano Zampini if (n_vertices) { 4638c58f9fdbSStefano Zampini PetscBool restoreavr = PETSC_FALSE; 46399de2952eSStefano Zampini Mat A_RRmA_RV = NULL; 464016f15bc4SStefano Zampini 46419de2952eSStefano Zampini PetscCall(MatSetValuesSubMat(*coarse_submat, A_VV, n_vertices, idx_V, n_vertices, idx_V, ADD_VALUES)); 46429de2952eSStefano Zampini PetscCall(MatDestroy(&A_VV)); 464304708bb6SStefano Zampini 464416f15bc4SStefano Zampini if (n_R) { 46459de2952eSStefano Zampini Mat A_RV_bcorr = NULL, S_VV; 464606656605SStefano Zampini 46479566063dSJacob Faibussowitsch PetscCall(MatScale(A_RV, m_one)); 464814393ed6SStefano Zampini if (need_benign_correction) { 464914393ed6SStefano Zampini ISLocalToGlobalMapping RtoN; 465014393ed6SStefano Zampini IS is_p0; 465114393ed6SStefano Zampini PetscInt *idxs_p0, n; 465214393ed6SStefano Zampini 46539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->benign_n, &idxs_p0)); 46549566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local, &RtoN)); 46559566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(RtoN, IS_GTOLM_DROP, pcbddc->benign_n, pcbddc->benign_p0_lidx, &n, idxs_p0)); 465663a3b9bcSJacob 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); 46579566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&RtoN)); 46589566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, n, idxs_p0, PETSC_OWN_POINTER, &is_p0)); 46599566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A_RV, is_p0, NULL, MAT_INITIAL_MATRIX, &A_RV_bcorr)); 46609566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_p0)); 466114393ed6SStefano Zampini } 466214393ed6SStefano Zampini 46639de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, lda_rhs, n_eff_vertices, NULL, &A_RRmA_RV)); 4664c58f9fdbSStefano Zampini if (!sparserhs || need_benign_correction) { 46659de2952eSStefano Zampini if (lda_rhs == n_R && !multi_element) { 46669566063dSJacob Faibussowitsch PetscCall(MatConvert(A_RV, MATDENSE, MAT_INPLACE_MATRIX, &A_RV)); 4667ffd830a3SStefano Zampini } else { 46689de2952eSStefano Zampini Mat T; 4669ca92afb2SStefano Zampini PetscScalar *av, *array; 4670ca92afb2SStefano Zampini const PetscInt *xadj, *adjncy; 4671ca92afb2SStefano Zampini PetscInt n; 4672ca92afb2SStefano Zampini PetscBool flg_row; 4673ffd830a3SStefano Zampini 46749de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, lda_rhs, n_eff_vertices, NULL, &T)); 46759de2952eSStefano Zampini PetscCall(MatDenseGetArrayWrite(T, &array)); 46769566063dSJacob Faibussowitsch PetscCall(MatConvert(A_RV, MATSEQAIJ, MAT_INPLACE_MATRIX, &A_RV)); 46779566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A_RV, 0, PETSC_FALSE, PETSC_FALSE, &n, &xadj, &adjncy, &flg_row)); 46789566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A_RV, &av)); 4679ca92afb2SStefano Zampini for (i = 0; i < n; i++) { 4680ca92afb2SStefano Zampini PetscInt j; 46819de2952eSStefano 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]; 4682ffd830a3SStefano Zampini } 46839566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A_RV, 0, PETSC_FALSE, PETSC_FALSE, &n, &xadj, &adjncy, &flg_row)); 46849de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayWrite(T, &array)); 46859566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RV)); 46869de2952eSStefano Zampini A_RV = T; 4687ffd830a3SStefano Zampini } 4688a3df083aSStefano Zampini if (need_benign_correction) { 4689df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 4690a3df083aSStefano Zampini PetscScalar *marr; 4691a3df083aSStefano Zampini 46929de2952eSStefano Zampini /* XXX multi_element */ 46939566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(A_RV, &marr)); 469414393ed6SStefano Zampini /* need \Phi^T A_RV = (I+L)A_RV, L given by 469514393ed6SStefano Zampini 469614393ed6SStefano Zampini | 0 0 0 | (V) 469714393ed6SStefano Zampini L = | 0 0 -1 | (P-p0) 469814393ed6SStefano Zampini | 0 0 -1 | (p0) 469914393ed6SStefano Zampini 470014393ed6SStefano Zampini */ 4701df4d28bfSStefano Zampini for (i = 0; i < reuse_solver->benign_n; i++) { 470214393ed6SStefano Zampini const PetscScalar *vals; 470314393ed6SStefano Zampini const PetscInt *idxs, *idxs_zero; 470414393ed6SStefano Zampini PetscInt n, j, nz; 470514393ed6SStefano Zampini 47069566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i], &nz)); 47079566063dSJacob Faibussowitsch PetscCall(ISGetIndices(reuse_solver->benign_zerodiag_subs[i], &idxs_zero)); 47089566063dSJacob Faibussowitsch PetscCall(MatGetRow(A_RV_bcorr, i, &n, &idxs, &vals)); 470914393ed6SStefano Zampini for (j = 0; j < n; j++) { 471014393ed6SStefano Zampini PetscScalar val = vals[j]; 471114393ed6SStefano Zampini PetscInt k, col = idxs[j]; 471214393ed6SStefano Zampini for (k = 0; k < nz; k++) marr[idxs_zero[k] + lda_rhs * col] -= val; 471314393ed6SStefano Zampini } 47149566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(A_RV_bcorr, i, &n, &idxs, &vals)); 47159566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i], &idxs_zero)); 471614393ed6SStefano Zampini } 47179566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(A_RV, &marr)); 471872b8c272SStefano Zampini } 47199566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A_RV)); 4720c58f9fdbSStefano Zampini Brhs = A_RV; 4721c58f9fdbSStefano Zampini } else { 4722c58f9fdbSStefano Zampini Mat tA_RVT, A_RVT; 4723c58f9fdbSStefano Zampini 4724c58f9fdbSStefano Zampini if (!pcbddc->symmetric_primal) { 4725fb6280fbSStefano Zampini /* A_RV already scaled by -1 */ 47269566063dSJacob Faibussowitsch PetscCall(MatTranspose(A_RV, MAT_INITIAL_MATRIX, &A_RVT)); 4727c58f9fdbSStefano Zampini } else { 4728c58f9fdbSStefano Zampini restoreavr = PETSC_TRUE; 47299566063dSJacob Faibussowitsch PetscCall(MatScale(A_VR, -1.0)); 47309566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A_VR)); 4731c58f9fdbSStefano Zampini A_RVT = A_VR; 4732c58f9fdbSStefano Zampini } 4733c58f9fdbSStefano Zampini if (lda_rhs != n_R) { 4734c58f9fdbSStefano Zampini PetscScalar *aa; 4735c58f9fdbSStefano Zampini PetscInt r, *ii, *jj; 4736c58f9fdbSStefano Zampini PetscBool done; 4737c58f9fdbSStefano Zampini 47389566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A_RVT, 0, PETSC_FALSE, PETSC_FALSE, &r, (const PetscInt **)&ii, (const PetscInt **)&jj, &done)); 473928b400f6SJacob Faibussowitsch PetscCheck(done, PETSC_COMM_SELF, PETSC_ERR_PLIB, "GetRowIJ failed"); 47409566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A_RVT, &aa)); 47419566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, n_vertices, lda_rhs, ii, jj, aa, &tA_RVT)); 47429566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A_RVT, 0, PETSC_FALSE, PETSC_FALSE, &r, (const PetscInt **)&ii, (const PetscInt **)&jj, &done)); 474328b400f6SJacob Faibussowitsch PetscCheck(done, PETSC_COMM_SELF, PETSC_ERR_PLIB, "RestoreRowIJ failed"); 4744c58f9fdbSStefano Zampini } else { 47459566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A_RVT)); 4746c58f9fdbSStefano Zampini tA_RVT = A_RVT; 4747c58f9fdbSStefano Zampini } 47489566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(tA_RVT, &Brhs)); 47499566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tA_RVT)); 47509566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RVT)); 4751c58f9fdbSStefano Zampini } 475272b8c272SStefano Zampini if (F) { 475314393ed6SStefano Zampini /* need to correct the rhs */ 475472b8c272SStefano Zampini if (need_benign_correction) { 475572b8c272SStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 475672b8c272SStefano Zampini PetscScalar *marr; 475772b8c272SStefano Zampini 47589566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(Brhs, &marr)); 47595cbda25cSStefano Zampini if (lda_rhs != n_R) { 47609de2952eSStefano Zampini for (i = 0; i < n_eff_vertices; i++) { 47619566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dummy_vec, marr + i * lda_rhs)); 47629566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, dummy_vec, NULL, PETSC_FALSE, PETSC_TRUE)); 47639566063dSJacob Faibussowitsch PetscCall(VecResetArray(dummy_vec)); 47645cbda25cSStefano Zampini } 47655cbda25cSStefano Zampini } else { 47669de2952eSStefano Zampini for (i = 0; i < n_eff_vertices; i++) { 47679566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, marr + i * lda_rhs)); 47689566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, pcbddc->vec1_R, NULL, PETSC_FALSE, PETSC_TRUE)); 47699566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 4770a3df083aSStefano Zampini } 47715cbda25cSStefano Zampini } 47729566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(Brhs, &marr)); 4773a3df083aSStefano Zampini } 47749566063dSJacob Faibussowitsch PetscCall(MatMatSolve(F, Brhs, A_RRmA_RV)); 47751baa6e33SBarry Smith if (restoreavr) PetscCall(MatScale(A_VR, -1.0)); 477614393ed6SStefano Zampini /* need to correct the solution */ 4777a3df083aSStefano Zampini if (need_benign_correction) { 4778df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 4779a3df083aSStefano Zampini PetscScalar *marr; 4780a3df083aSStefano Zampini 47819566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(A_RRmA_RV, &marr)); 47825cbda25cSStefano Zampini if (lda_rhs != n_R) { 47839de2952eSStefano Zampini for (i = 0; i < n_eff_vertices; i++) { 47849566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dummy_vec, marr + i * lda_rhs)); 47859566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, dummy_vec, NULL, PETSC_TRUE, PETSC_TRUE)); 47869566063dSJacob Faibussowitsch PetscCall(VecResetArray(dummy_vec)); 47875cbda25cSStefano Zampini } 47885cbda25cSStefano Zampini } else { 47899de2952eSStefano Zampini for (i = 0; i < n_eff_vertices; i++) { 47909566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, marr + i * lda_rhs)); 47919566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, pcbddc->vec1_R, NULL, PETSC_TRUE, PETSC_TRUE)); 47929566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 4793a3df083aSStefano Zampini } 47945cbda25cSStefano Zampini } 47959566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(A_RRmA_RV, &marr)); 4796a3df083aSStefano Zampini } 479706656605SStefano Zampini } else { 47989de2952eSStefano Zampini const PetscScalar *barr; 47999de2952eSStefano Zampini PetscScalar *marr; 48009de2952eSStefano Zampini 48019de2952eSStefano Zampini PetscCall(MatDenseGetArrayRead(Brhs, &barr)); 48029de2952eSStefano Zampini PetscCall(MatDenseGetArray(A_RRmA_RV, &marr)); 48039de2952eSStefano Zampini for (i = 0; i < n_eff_vertices; i++) { 48049de2952eSStefano Zampini PetscCall(VecPlaceArray(pcbddc->vec1_R, barr + i * lda_rhs)); 48059de2952eSStefano Zampini PetscCall(VecPlaceArray(pcbddc->vec2_R, marr + i * lda_rhs)); 48069566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec2_R)); 48079566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec2_R)); 48089566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 48099566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec2_R)); 481006656605SStefano Zampini } 48119de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayRead(Brhs, &barr)); 48129de2952eSStefano Zampini PetscCall(MatDenseRestoreArray(A_RRmA_RV, &marr)); 481306656605SStefano Zampini } 48149566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RV)); 48159566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Brhs)); 4816ffd830a3SStefano Zampini /* S_VV and S_CV */ 481706656605SStefano Zampini if (n_constraints) { 481806656605SStefano Zampini Mat B; 481980677318SStefano Zampini 48209de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_B, n_eff_vertices, NULL, &B)); 48219de2952eSStefano Zampini PetscCall(MatDenseScatter(A_RRmA_RV, pcbddc->R_to_B, B)); 48229de2952eSStefano Zampini 48239de2952eSStefano Zampini /* S_CV = pcbddc->local_auxmat1 * B */ 48249de2952eSStefano Zampini if (multi_element) { 48259de2952eSStefano Zampini Mat T; 48269de2952eSStefano Zampini 48279de2952eSStefano Zampini PetscCall(MatCreateSeqAIJFromDenseExpand(B, n_vertices, B_eff_V_J, &T)); 48289de2952eSStefano Zampini PetscCall(MatDestroy(&B)); 48299de2952eSStefano Zampini B = T; 483080677318SStefano Zampini } 48319de2952eSStefano Zampini PetscCall(MatProductCreate(pcbddc->local_auxmat1, B, NULL, &S_CV)); 48329566063dSJacob Faibussowitsch PetscCall(MatProductSetType(S_CV, MATPRODUCT_AB)); 48339566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(S_CV)); 48349566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(S_CV)); 48359566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(S_CV)); 48369566063dSJacob Faibussowitsch PetscCall(MatProductClear(S_CV)); 48379566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 48389de2952eSStefano Zampini 48399de2952eSStefano Zampini /* B = local_auxmat2_R * S_CV */ 48409de2952eSStefano Zampini PetscCall(MatProductCreate(local_auxmat2_R, S_CV, NULL, &B)); 48419566063dSJacob Faibussowitsch PetscCall(MatProductSetType(B, MATPRODUCT_AB)); 48429566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(B)); 48439566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(B)); 48449566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(B)); 48454222ddf1SHong Zhang 48469566063dSJacob Faibussowitsch PetscCall(MatScale(S_CV, m_one)); 48479de2952eSStefano Zampini PetscCall(MatSetValuesSubMat(*coarse_submat, S_CV, n_constraints, idx_C, n_vertices, idx_V, INSERT_VALUES)); 484814393ed6SStefano Zampini 48499de2952eSStefano Zampini if (multi_element) { 48509de2952eSStefano Zampini Mat T; 48519de2952eSStefano Zampini 48529de2952eSStefano Zampini PetscCall(MatCreateSeqAIJFromDenseExpand(A_RRmA_RV, n_vertices, R_eff_V_J, &T)); 48539de2952eSStefano Zampini PetscCall(MatDestroy(&A_RRmA_RV)); 48549de2952eSStefano Zampini A_RRmA_RV = T; 48559de2952eSStefano Zampini } 48569de2952eSStefano Zampini PetscCall(MatAXPY(A_RRmA_RV, 1.0, B, UNKNOWN_NONZERO_PATTERN)); /* XXX ? */ 48579de2952eSStefano Zampini PetscCall(MatDestroy(&B)); 48589de2952eSStefano Zampini } else if (multi_element) { 48599de2952eSStefano Zampini Mat T; 48609de2952eSStefano Zampini 48619de2952eSStefano Zampini PetscCall(MatCreateSeqAIJFromDenseExpand(A_RRmA_RV, n_vertices, R_eff_V_J, &T)); 48629de2952eSStefano Zampini PetscCall(MatDestroy(&A_RRmA_RV)); 48639de2952eSStefano Zampini A_RRmA_RV = T; 48649de2952eSStefano Zampini } 48659de2952eSStefano Zampini 48669de2952eSStefano Zampini if (lda_rhs != n_R) { 48679de2952eSStefano Zampini Mat T; 48689de2952eSStefano Zampini 48699de2952eSStefano Zampini PetscCall(MatCreateSubMatrix(A_RRmA_RV, is_R, NULL, MAT_INITIAL_MATRIX, &T)); 48709de2952eSStefano Zampini PetscCall(MatDestroy(&A_RRmA_RV)); 48719de2952eSStefano Zampini A_RRmA_RV = T; 48729de2952eSStefano Zampini } 48739de2952eSStefano Zampini 48749de2952eSStefano Zampini /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */ 48759de2952eSStefano Zampini if (need_benign_correction) { /* XXX SPARSE */ 48769de2952eSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 48779de2952eSStefano Zampini PetscScalar *sums; 48789de2952eSStefano Zampini const PetscScalar *marr; 48799de2952eSStefano Zampini 48809de2952eSStefano Zampini PetscCall(MatDenseGetArrayRead(A_RRmA_RV, &marr)); 48819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_vertices, &sums)); 4882df4d28bfSStefano Zampini for (i = 0; i < reuse_solver->benign_n; i++) { 488314393ed6SStefano Zampini const PetscScalar *vals; 488414393ed6SStefano Zampini const PetscInt *idxs, *idxs_zero; 488514393ed6SStefano Zampini PetscInt n, j, nz; 488614393ed6SStefano Zampini 48879566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i], &nz)); 48889566063dSJacob Faibussowitsch PetscCall(ISGetIndices(reuse_solver->benign_zerodiag_subs[i], &idxs_zero)); 488914393ed6SStefano Zampini for (j = 0; j < n_vertices; j++) { 489014393ed6SStefano Zampini sums[j] = 0.; 48919de2952eSStefano Zampini for (PetscInt k = 0; k < nz; k++) sums[j] += marr[idxs_zero[k] + j * n_R]; 489214393ed6SStefano Zampini } 48939566063dSJacob Faibussowitsch PetscCall(MatGetRow(A_RV_bcorr, i, &n, &idxs, &vals)); 489414393ed6SStefano Zampini for (j = 0; j < n; j++) { 489514393ed6SStefano Zampini PetscScalar val = vals[j]; 48969de2952eSStefano 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)); 489714393ed6SStefano Zampini } 48989566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(A_RV_bcorr, i, &n, &idxs, &vals)); 48999566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i], &idxs_zero)); 490014393ed6SStefano Zampini } 49019566063dSJacob Faibussowitsch PetscCall(PetscFree(sums)); 49029566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RV_bcorr)); 49039de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayRead(A_RRmA_RV, &marr)); 490414393ed6SStefano Zampini } 49059de2952eSStefano Zampini 4906fb842aefSJose E. Roman PetscCall(MatMatMult(A_VR, A_RRmA_RV, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &S_VV)); 49079de2952eSStefano Zampini PetscCall(MatSetValuesSubMat(*coarse_submat, S_VV, n_vertices, idx_V, n_vertices, idx_V, ADD_VALUES)); 49089de2952eSStefano Zampini PetscCall(MatDestroy(&S_VV)); 4909d16cbb6bSStefano Zampini } 4910d16cbb6bSStefano Zampini 491106656605SStefano Zampini /* coarse basis functions */ 49129de2952eSStefano Zampini if (coarse_phi_multi) { 49139de2952eSStefano Zampini Mat Vid; 491416f15bc4SStefano Zampini 49159de2952eSStefano Zampini PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, n_vertices, n_vertices, 1, NULL, &Vid)); 49169de2952eSStefano Zampini PetscCall(MatShift_Basic(Vid, 1.0)); 49179de2952eSStefano Zampini PetscCall(MatNestSetSubMat(coarse_phi_multi, 0, 0, A_RRmA_RV)); 49189de2952eSStefano Zampini PetscCall(MatNestSetSubMat(coarse_phi_multi, 1, 0, Vid)); 49199de2952eSStefano Zampini PetscCall(MatDestroy(&Vid)); 49209de2952eSStefano Zampini } else { 49219de2952eSStefano Zampini if (A_RRmA_RV) { 49229de2952eSStefano Zampini PetscCall(MatDenseScatter(A_RRmA_RV, pcbddc->R_to_B, pcbddc->coarse_phi_B)); 492306656605SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 49249de2952eSStefano Zampini PetscCall(MatDenseScatter(A_RRmA_RV, pcbddc->R_to_D, pcbddc->coarse_phi_D)); 49259de2952eSStefano Zampini if (pcbddc->benign_n) { 49269de2952eSStefano 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)); } 49278a162dc6SStefano Zampini PetscCall(MatAssemblyBegin(pcbddc->coarse_phi_D, MAT_FINAL_ASSEMBLY)); 49288a162dc6SStefano Zampini PetscCall(MatAssemblyEnd(pcbddc->coarse_phi_D, MAT_FINAL_ASSEMBLY)); 4929ab2d12f3SJunchao Zhang } 493006656605SStefano Zampini } 493106656605SStefano Zampini } 49329de2952eSStefano Zampini for (i = 0; i < n_vertices; i++) PetscCall(MatSetValues(pcbddc->coarse_phi_B, 1, &idx_V_B[i], 1, &i, &one, INSERT_VALUES)); 49339de2952eSStefano Zampini PetscCall(MatAssemblyBegin(pcbddc->coarse_phi_B, MAT_FINAL_ASSEMBLY)); 49349de2952eSStefano Zampini PetscCall(MatAssemblyEnd(pcbddc->coarse_phi_B, MAT_FINAL_ASSEMBLY)); 49359de2952eSStefano Zampini } 49369de2952eSStefano Zampini PetscCall(MatDestroy(&A_RRmA_RV)); 49379de2952eSStefano Zampini } 49389566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RV)); 49399566063dSJacob Faibussowitsch PetscCall(VecDestroy(&dummy_vec)); 494006656605SStefano Zampini 494106656605SStefano Zampini if (n_constraints) { 49429de2952eSStefano Zampini Mat B, B2; 494306656605SStefano Zampini 49449566063dSJacob Faibussowitsch PetscCall(MatScale(S_CC, m_one)); 49459de2952eSStefano Zampini PetscCall(MatProductCreate(local_auxmat2_R, S_CC, NULL, &B)); 49469566063dSJacob Faibussowitsch PetscCall(MatProductSetType(B, MATPRODUCT_AB)); 49479566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(B)); 49489566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(B)); 49499566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(B)); 4950a961b312SStefano Zampini 495106656605SStefano Zampini if (n_vertices) { 495203dfb2d7SStefano Zampini if (isCHOL || need_benign_correction) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */ 49539de2952eSStefano Zampini PetscCall(MatTranspose(S_CV, MAT_INITIAL_MATRIX, &S_VC)); 495480677318SStefano Zampini } else { 4955ffd830a3SStefano Zampini if (lda_rhs != n_R) { 49569de2952eSStefano Zampini Mat tB; 495706656605SStefano Zampini 49589de2952eSStefano Zampini PetscCall(MatCreateSubMatrix(B, is_R, NULL, MAT_INITIAL_MATRIX, &tB)); 49599de2952eSStefano Zampini PetscCall(MatDestroy(&B)); 49609de2952eSStefano Zampini B = tB; 49619de2952eSStefano Zampini } 4962fb842aefSJose E. Roman PetscCall(MatMatMult(A_VR, B, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &S_VC)); 49639de2952eSStefano Zampini } 49649de2952eSStefano Zampini PetscCall(MatSetValuesSubMat(*coarse_submat, S_VC, n_vertices, idx_V, n_constraints, idx_C, INSERT_VALUES)); 49659de2952eSStefano Zampini } 49669de2952eSStefano Zampini 49679de2952eSStefano Zampini /* coarse basis functions */ 49689de2952eSStefano Zampini if (coarse_phi_multi) { 49699de2952eSStefano Zampini PetscCall(MatNestSetSubMat(coarse_phi_multi, 0, 1, B)); 49709de2952eSStefano Zampini } else { 49719de2952eSStefano Zampini PetscCall(MatDenseGetSubMatrix(pcbddc->coarse_phi_B, PETSC_DECIDE, PETSC_DECIDE, n_vertices, n_vertices + n_constraints, &B2)); 49729de2952eSStefano Zampini PetscCall(MatDenseScatter(B, pcbddc->R_to_B, B2)); 49739de2952eSStefano Zampini PetscCall(MatDenseRestoreSubMatrix(pcbddc->coarse_phi_B, &B2)); 497406656605SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 49759de2952eSStefano Zampini PetscCall(MatDenseGetSubMatrix(pcbddc->coarse_phi_D, PETSC_DECIDE, PETSC_DECIDE, n_vertices, n_vertices + n_constraints, &B2)); 49769de2952eSStefano Zampini PetscCall(MatDenseScatter(B, pcbddc->R_to_D, B2)); 49779de2952eSStefano Zampini if (pcbddc->benign_n) { 49789de2952eSStefano Zampini for (i = 0; i < n_constraints; i++) { PetscCall(MatSetValues(B2, pcbddc->benign_n, p0_lidx_I, 1, &i, NULL, INSERT_VALUES)); } 497906656605SStefano Zampini } 49809de2952eSStefano Zampini PetscCall(MatDenseRestoreSubMatrix(pcbddc->coarse_phi_D, &B2)); 498106656605SStefano Zampini } 498206656605SStefano Zampini } 49839de2952eSStefano Zampini PetscCall(MatDestroy(&B)); 49849de2952eSStefano Zampini } 49859de2952eSStefano Zampini 49869de2952eSStefano Zampini /* assemble sparse coarse basis functions */ 49879de2952eSStefano Zampini if (coarse_phi_multi) { 49889de2952eSStefano Zampini Mat T; 49899de2952eSStefano Zampini 49909de2952eSStefano Zampini PetscCall(MatConvert(coarse_phi_multi, MATSEQAIJ, MAT_INITIAL_MATRIX, &T)); 49919de2952eSStefano Zampini PetscCall(MatDestroy(&coarse_phi_multi)); 49929de2952eSStefano Zampini PetscCall(MatCreateSubMatrix(T, pcis->is_B_local, NULL, MAT_INITIAL_MATRIX, &pcbddc->coarse_phi_B)); 49939de2952eSStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { PetscCall(MatCreateSubMatrix(T, pcis->is_I_local, NULL, MAT_INITIAL_MATRIX, &pcbddc->coarse_phi_D)); } 49949de2952eSStefano Zampini PetscCall(MatDestroy(&T)); 49959de2952eSStefano Zampini } 49969de2952eSStefano Zampini PetscCall(MatDestroy(&local_auxmat2_R)); 49979566063dSJacob Faibussowitsch PetscCall(PetscFree(p0_lidx_I)); 499872b8c272SStefano Zampini 499972b8c272SStefano Zampini /* coarse matrix entries relative to B_0 */ 500072b8c272SStefano Zampini if (pcbddc->benign_n) { 500172b8c272SStefano Zampini Mat B0_B, B0_BPHI; 500272b8c272SStefano Zampini IS is_dummy; 50031683a169SBarry Smith const PetscScalar *data; 500472b8c272SStefano Zampini PetscInt j; 500572b8c272SStefano Zampini 50069566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pcbddc->benign_n, 0, 1, &is_dummy)); 50079566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->benign_B0, is_dummy, pcis->is_B_local, MAT_INITIAL_MATRIX, &B0_B)); 50089566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_dummy)); 50099566063dSJacob Faibussowitsch PetscCall(MatMatMult(B0_B, pcbddc->coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &B0_BPHI)); 50109566063dSJacob Faibussowitsch PetscCall(MatConvert(B0_BPHI, MATSEQDENSE, MAT_INPLACE_MATRIX, &B0_BPHI)); 50119566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(B0_BPHI, &data)); 501272b8c272SStefano Zampini for (j = 0; j < pcbddc->benign_n; j++) { 501372b8c272SStefano Zampini PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j; 501472b8c272SStefano Zampini for (i = 0; i < pcbddc->local_primal_size; i++) { 50159de2952eSStefano Zampini PetscCall(MatSetValue(*coarse_submat, primal_idx, i, data[i * pcbddc->benign_n + j], INSERT_VALUES)); 50169de2952eSStefano Zampini PetscCall(MatSetValue(*coarse_submat, i, primal_idx, data[i * pcbddc->benign_n + j], INSERT_VALUES)); 501772b8c272SStefano Zampini } 501872b8c272SStefano Zampini } 50199566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(B0_BPHI, &data)); 50209566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B0_B)); 50219566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B0_BPHI)); 502272b8c272SStefano Zampini } 5023019a44ceSStefano Zampini 502406656605SStefano Zampini /* compute other basis functions for non-symmetric problems */ 50253301b35fSStefano Zampini if (!pcbddc->symmetric_primal) { 5026ffd830a3SStefano Zampini Mat B_V = NULL, B_C = NULL; 50279de2952eSStefano Zampini PetscScalar *marray, *work; 502806656605SStefano Zampini 50299de2952eSStefano Zampini /* TODO multi_element MatDenseScatter */ 503006656605SStefano Zampini if (n_constraints) { 5031ffd830a3SStefano Zampini Mat S_CCT, C_CRT; 503206656605SStefano Zampini 50339de2952eSStefano Zampini PetscCall(MatScale(S_CC, m_one)); 50349566063dSJacob Faibussowitsch PetscCall(MatTranspose(C_CR, MAT_INITIAL_MATRIX, &C_CRT)); 50359566063dSJacob Faibussowitsch PetscCall(MatTranspose(S_CC, MAT_INITIAL_MATRIX, &S_CCT)); 5036fb842aefSJose E. Roman PetscCall(MatMatMult(C_CRT, S_CCT, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &B_C)); 50379de2952eSStefano Zampini PetscCall(MatConvert(B_C, MATDENSE, MAT_INPLACE_MATRIX, &B_C)); 50389566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_CCT)); 503906656605SStefano Zampini if (n_vertices) { 5040ffd830a3SStefano Zampini Mat S_VCT; 504106656605SStefano Zampini 50429566063dSJacob Faibussowitsch PetscCall(MatTranspose(S_VC, MAT_INITIAL_MATRIX, &S_VCT)); 5043fb842aefSJose E. Roman PetscCall(MatMatMult(C_CRT, S_VCT, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &B_V)); 50449566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_VCT)); 50459de2952eSStefano Zampini PetscCall(MatConvert(B_V, MATDENSE, MAT_INPLACE_MATRIX, &B_V)); 504606656605SStefano Zampini } 50479566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C_CRT)); 50485b782168SStefano Zampini } else { 50499566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_R, n_vertices, NULL, &B_V)); 505006656605SStefano Zampini } 505116f15bc4SStefano Zampini if (n_vertices && n_R) { 5052ffd830a3SStefano Zampini PetscScalar *av, *marray; 5053ffd830a3SStefano Zampini const PetscInt *xadj, *adjncy; 5054ffd830a3SStefano Zampini PetscInt n; 5055ffd830a3SStefano Zampini PetscBool flg_row; 505606656605SStefano Zampini 5057ffd830a3SStefano Zampini /* B_V = B_V - A_VR^T */ 50589566063dSJacob Faibussowitsch PetscCall(MatConvert(A_VR, MATSEQAIJ, MAT_INPLACE_MATRIX, &A_VR)); 50599566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A_VR, 0, PETSC_FALSE, PETSC_FALSE, &n, &xadj, &adjncy, &flg_row)); 50609566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A_VR, &av)); 50619566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(B_V, &marray)); 5062ffd830a3SStefano Zampini for (i = 0; i < n; i++) { 5063ffd830a3SStefano Zampini PetscInt j; 5064ffd830a3SStefano Zampini for (j = xadj[i]; j < xadj[i + 1]; j++) marray[i * n_R + adjncy[j]] -= av[j]; 5065ffd830a3SStefano Zampini } 50669566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(B_V, &marray)); 50679566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A_VR, 0, PETSC_FALSE, PETSC_FALSE, &n, &xadj, &adjncy, &flg_row)); 50689566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_VR)); 506906656605SStefano Zampini } 507006656605SStefano Zampini 5071ffd830a3SStefano Zampini /* currently there's no support for MatTransposeMatSolve(F,B,X) */ 50729de2952eSStefano Zampini PetscCall(PetscMalloc1(n_R * pcbddc->local_primal_size, &work)); 5073abc8f43dSstefano_zampini if (n_vertices) { 50749566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(B_V, &marray)); 5075ffd830a3SStefano Zampini for (i = 0; i < n_vertices; i++) { 50769566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, marray + i * n_R)); 50779566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec2_R, work + i * n_R)); 50789566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec2_R)); 50799566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec2_R)); 50809566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 50819566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec2_R)); 508206656605SStefano Zampini } 50839566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(B_V, &marray)); 5084abc8f43dSstefano_zampini } 50855b782168SStefano Zampini if (B_C) { 50869566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(B_C, &marray)); 5087ffd830a3SStefano Zampini for (i = n_vertices; i < n_constraints + n_vertices; i++) { 50889566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, marray + (i - n_vertices) * n_R)); 50899566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec2_R, work + i * n_R)); 50909566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec2_R)); 50919566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec2_R)); 50929566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 50939566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec2_R)); 509406656605SStefano Zampini } 50959566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(B_C, &marray)); 50965b782168SStefano Zampini } 509706656605SStefano Zampini /* coarse basis functions */ 50989de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_B, pcbddc->local_primal_size, NULL, &pcbddc->coarse_psi_B)); 50999de2952eSStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_D, pcbddc->local_primal_size, NULL, &pcbddc->coarse_psi_D)); 510006656605SStefano Zampini for (i = 0; i < pcbddc->local_primal_size; i++) { 5101ab2d12f3SJunchao Zhang Vec v; 510206656605SStefano Zampini 51039566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, work + i * n_R)); 51049566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVec(pcbddc->coarse_psi_B, i, &v)); 51059566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 51069566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 510706656605SStefano Zampini if (i < n_vertices) { 5108ab2d12f3SJunchao Zhang PetscScalar one = 1.0; 51099566063dSJacob Faibussowitsch PetscCall(VecSetValues(v, 1, &idx_V_B[i], &one, INSERT_VALUES)); 51109566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(v)); 51119566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(v)); 511206656605SStefano Zampini } 51139566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_psi_B, i, &v)); 511406656605SStefano Zampini 511506656605SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 51169566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVec(pcbddc->coarse_psi_D, i, &v)); 51179566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_D, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 51189566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_D, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 51199566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_psi_D, i, &v)); 512006656605SStefano Zampini } 51219566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 512206656605SStefano Zampini } 51239566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B_V)); 51249566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B_C)); 51259de2952eSStefano Zampini PetscCall(PetscFree(work)); 51269de2952eSStefano Zampini } else { 51279de2952eSStefano Zampini PetscCall(PetscObjectReference((PetscObject)pcbddc->coarse_phi_B)); 51289de2952eSStefano Zampini pcbddc->coarse_psi_B = pcbddc->coarse_phi_B; 51299de2952eSStefano Zampini PetscCall(PetscObjectReference((PetscObject)pcbddc->coarse_phi_D)); 51309de2952eSStefano Zampini pcbddc->coarse_psi_D = pcbddc->coarse_phi_D; 513106656605SStefano Zampini } 51329de2952eSStefano Zampini PetscCall(MatAssemblyBegin(*coarse_submat, MAT_FINAL_ASSEMBLY)); 51339de2952eSStefano Zampini PetscCall(MatAssemblyEnd(*coarse_submat, MAT_FINAL_ASSEMBLY)); 5134a6e023c1Sstefano_zampini 5135d62866d3SStefano Zampini /* free memory */ 51369de2952eSStefano Zampini PetscCall(PetscFree(V_to_eff_V)); 51379de2952eSStefano Zampini PetscCall(PetscFree(C_to_eff_C)); 51389de2952eSStefano Zampini PetscCall(PetscFree(R_eff_V_J)); 51399de2952eSStefano Zampini PetscCall(PetscFree(R_eff_C_J)); 51409de2952eSStefano Zampini PetscCall(PetscFree(B_eff_V_J)); 51419de2952eSStefano Zampini PetscCall(PetscFree(B_eff_C_J)); 51429de2952eSStefano Zampini PetscCall(ISDestroy(&is_R)); 51439de2952eSStefano Zampini PetscCall(ISRestoreIndices(is_V, &idx_V)); 51449de2952eSStefano Zampini PetscCall(ISRestoreIndices(is_C, &idx_C)); 51459de2952eSStefano Zampini PetscCall(ISDestroy(&is_V)); 51469de2952eSStefano Zampini PetscCall(ISDestroy(&is_C)); 51479566063dSJacob Faibussowitsch PetscCall(PetscFree(idx_V_B)); 51489566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_CV)); 51499566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_VC)); 51509566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_CC)); 515148a46eb9SPierre Jolivet if (n_vertices) PetscCall(MatDestroy(&A_VR)); 515248a46eb9SPierre Jolivet if (n_constraints) PetscCall(MatDestroy(&C_CR)); 51539566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_CorrectionSetUp[pcbddc->current_level], pc, 0, 0, 0)); 51548ead10e4SStefano Zampini 5155da81f932SPierre Jolivet /* Checking coarse_sub_mat and coarse basis functions */ 515688ebb749SStefano Zampini /* Symmetric case : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */ 515788ebb749SStefano Zampini /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */ 5158d12edf2fSStefano Zampini if (pcbddc->dbg_flag) { 515925084f0cSStefano Zampini Mat AUXMAT, TM1, TM2, TM3, TM4; 516088ebb749SStefano Zampini Mat coarse_phi_D, coarse_phi_B; 516188ebb749SStefano Zampini Mat coarse_psi_D, coarse_psi_B; 516288ebb749SStefano Zampini Mat A_II, A_BB, A_IB, A_BI; 51638bec7fa6SStefano Zampini Mat C_B, CPHI; 51648bec7fa6SStefano Zampini IS is_dummy; 51658bec7fa6SStefano Zampini Vec mones; 516688ebb749SStefano Zampini MatType checkmattype = MATSEQAIJ; 516788ebb749SStefano Zampini PetscReal real_value; 516888ebb749SStefano Zampini 5169a3df083aSStefano Zampini if (pcbddc->benign_n && !pcbddc->benign_change_explicit) { 5170a3df083aSStefano Zampini Mat A; 51719566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignProject(pc, NULL, NULL, &A)); 51729566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, pcis->is_I_local, pcis->is_I_local, MAT_INITIAL_MATRIX, &A_II)); 51739566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, pcis->is_I_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &A_IB)); 51749566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, pcis->is_B_local, pcis->is_I_local, MAT_INITIAL_MATRIX, &A_BI)); 51759566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, pcis->is_B_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &A_BB)); 51769566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 5177a3df083aSStefano Zampini } else { 51789566063dSJacob Faibussowitsch PetscCall(MatConvert(pcis->A_II, checkmattype, MAT_INITIAL_MATRIX, &A_II)); 51799566063dSJacob Faibussowitsch PetscCall(MatConvert(pcis->A_IB, checkmattype, MAT_INITIAL_MATRIX, &A_IB)); 51809566063dSJacob Faibussowitsch PetscCall(MatConvert(pcis->A_BI, checkmattype, MAT_INITIAL_MATRIX, &A_BI)); 51819566063dSJacob Faibussowitsch PetscCall(MatConvert(pcis->A_BB, checkmattype, MAT_INITIAL_MATRIX, &A_BB)); 5182a3df083aSStefano Zampini } 51839566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->coarse_phi_D, checkmattype, MAT_INITIAL_MATRIX, &coarse_phi_D)); 51849566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->coarse_phi_B, checkmattype, MAT_INITIAL_MATRIX, &coarse_phi_B)); 5185ffd830a3SStefano Zampini if (!pcbddc->symmetric_primal) { 51869566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->coarse_psi_D, checkmattype, MAT_INITIAL_MATRIX, &coarse_psi_D)); 51879566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->coarse_psi_B, checkmattype, MAT_INITIAL_MATRIX, &coarse_psi_B)); 518888ebb749SStefano Zampini } 51899566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 51909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Check coarse sub mat computation (symmetric %d)\n", pcbddc->symmetric_primal)); 51919566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 5192ffd830a3SStefano Zampini if (!pcbddc->symmetric_primal) { 51939566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_II, coarse_phi_D, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 51949566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_psi_D, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM1)); 51959566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 51969566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_BB, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 51979566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_psi_B, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM2)); 51989566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 51999566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_IB, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 52009566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_psi_D, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM3)); 52019566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 52029566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_BI, coarse_phi_D, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 52039566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_psi_B, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM4)); 52049566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 520588ebb749SStefano Zampini } else { 52069566063dSJacob Faibussowitsch PetscCall(MatPtAP(A_II, coarse_phi_D, MAT_INITIAL_MATRIX, 1.0, &TM1)); 52079566063dSJacob Faibussowitsch PetscCall(MatPtAP(A_BB, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &TM2)); 52089566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_IB, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 52099566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_phi_D, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM3)); 52109566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 52119566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_BI, coarse_phi_D, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 52129566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_phi_B, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM4)); 52139566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 521488ebb749SStefano Zampini } 52159566063dSJacob Faibussowitsch PetscCall(MatAXPY(TM1, one, TM2, DIFFERENT_NONZERO_PATTERN)); 52169566063dSJacob Faibussowitsch PetscCall(MatAXPY(TM1, one, TM3, DIFFERENT_NONZERO_PATTERN)); 52179566063dSJacob Faibussowitsch PetscCall(MatAXPY(TM1, one, TM4, DIFFERENT_NONZERO_PATTERN)); 52189566063dSJacob Faibussowitsch PetscCall(MatConvert(TM1, MATSEQDENSE, MAT_INPLACE_MATRIX, &TM1)); 52194f1b2e48SStefano Zampini if (pcbddc->benign_n) { 5220fc227af8SStefano Zampini Mat B0_B, B0_BPHI; 52211683a169SBarry Smith const PetscScalar *data2; 52221683a169SBarry Smith PetscScalar *data; 52234f1b2e48SStefano Zampini PetscInt j; 5224d12edf2fSStefano Zampini 52259566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pcbddc->benign_n, 0, 1, &is_dummy)); 52269566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->benign_B0, is_dummy, pcis->is_B_local, MAT_INITIAL_MATRIX, &B0_B)); 52279566063dSJacob Faibussowitsch PetscCall(MatMatMult(B0_B, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &B0_BPHI)); 52289566063dSJacob Faibussowitsch PetscCall(MatConvert(B0_BPHI, MATSEQDENSE, MAT_INPLACE_MATRIX, &B0_BPHI)); 52299566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(TM1, &data)); 52309566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(B0_BPHI, &data2)); 52314f1b2e48SStefano Zampini for (j = 0; j < pcbddc->benign_n; j++) { 52324f1b2e48SStefano Zampini PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j; 5233d12edf2fSStefano Zampini for (i = 0; i < pcbddc->local_primal_size; i++) { 52344f1b2e48SStefano Zampini data[primal_idx * pcbddc->local_primal_size + i] += data2[i * pcbddc->benign_n + j]; 52354f1b2e48SStefano Zampini data[i * pcbddc->local_primal_size + primal_idx] += data2[i * pcbddc->benign_n + j]; 52364f1b2e48SStefano Zampini } 5237d12edf2fSStefano Zampini } 52389566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(TM1, &data)); 52399566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(B0_BPHI, &data2)); 52409566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B0_B)); 52419566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_dummy)); 52429566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B0_BPHI)); 5243d12edf2fSStefano Zampini } 52449de2952eSStefano Zampini PetscCall(MatAXPY(TM1, m_one, *coarse_submat, DIFFERENT_NONZERO_PATTERN)); 52459566063dSJacob Faibussowitsch PetscCall(MatNorm(TM1, NORM_FROBENIUS, &real_value)); 52469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 524763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d matrix error % 1.14e\n", PetscGlobalRank, (double)real_value)); 52488bec7fa6SStefano Zampini 52498bec7fa6SStefano Zampini /* check constraints */ 52509566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pcbddc->local_primal_size - pcbddc->benign_n, 0, 1, &is_dummy)); 52519566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->ConstraintMatrix, is_dummy, pcis->is_B_local, MAT_INITIAL_MATRIX, &C_B)); 52524f1b2e48SStefano Zampini if (!pcbddc->benign_n) { /* TODO: add benign case */ 52539566063dSJacob Faibussowitsch PetscCall(MatMatMult(C_B, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &CPHI)); 5254a00504b5SStefano Zampini } else { 5255a00504b5SStefano Zampini PetscScalar *data; 5256a00504b5SStefano Zampini Mat tmat; 52579566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(pcbddc->coarse_phi_B, &data)); 52589566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, pcis->n_B, pcbddc->local_primal_size - pcbddc->benign_n, data, &tmat)); 52599566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(pcbddc->coarse_phi_B, &data)); 52609566063dSJacob Faibussowitsch PetscCall(MatMatMult(C_B, tmat, MAT_INITIAL_MATRIX, 1.0, &CPHI)); 52619566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tmat)); 5262a00504b5SStefano Zampini } 52639566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(CPHI, &mones, NULL)); 52649566063dSJacob Faibussowitsch PetscCall(VecSet(mones, -1.0)); 52659566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(CPHI, mones, ADD_VALUES)); 52669566063dSJacob Faibussowitsch PetscCall(MatNorm(CPHI, NORM_FROBENIUS, &real_value)); 526763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d phi constraints error % 1.14e\n", PetscGlobalRank, (double)real_value)); 5268ffd830a3SStefano Zampini if (!pcbddc->symmetric_primal) { 52699566063dSJacob Faibussowitsch PetscCall(MatMatMult(C_B, coarse_psi_B, MAT_REUSE_MATRIX, 1.0, &CPHI)); 52709566063dSJacob Faibussowitsch PetscCall(VecSet(mones, -1.0)); 52719566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(CPHI, mones, ADD_VALUES)); 52729566063dSJacob Faibussowitsch PetscCall(MatNorm(CPHI, NORM_FROBENIUS, &real_value)); 527363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d psi constraints error % 1.14e\n", PetscGlobalRank, (double)real_value)); 527488ebb749SStefano Zampini } 52759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C_B)); 52769566063dSJacob Faibussowitsch PetscCall(MatDestroy(&CPHI)); 52779566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_dummy)); 52789566063dSJacob Faibussowitsch PetscCall(VecDestroy(&mones)); 52799566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 52809566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_II)); 52819566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_BB)); 52829566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_IB)); 52839566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_BI)); 52849566063dSJacob Faibussowitsch PetscCall(MatDestroy(&TM1)); 52859566063dSJacob Faibussowitsch PetscCall(MatDestroy(&TM2)); 52869566063dSJacob Faibussowitsch PetscCall(MatDestroy(&TM3)); 52879566063dSJacob Faibussowitsch PetscCall(MatDestroy(&TM4)); 52889566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_phi_D)); 52899566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_phi_B)); 5290ffd830a3SStefano Zampini if (!pcbddc->symmetric_primal) { 52919566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_psi_D)); 52929566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_psi_B)); 529388ebb749SStefano Zampini } 529488ebb749SStefano Zampini } 52957ebab0bbSStefano Zampini 52969de2952eSStefano Zampini #if 0 52979de2952eSStefano Zampini { 52989de2952eSStefano Zampini PetscViewer viewer; 52999de2952eSStefano Zampini char filename[256]; 53009de2952eSStefano Zampini 53019de2952eSStefano Zampini PetscCall(PetscSNPrintf(filename, PETSC_STATIC_ARRAY_LENGTH(filename), "details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level)); 53029de2952eSStefano Zampini PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer)); 53039de2952eSStefano Zampini PetscCall(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB)); 53049de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)*coarse_submat,"coarse submat")); 53059de2952eSStefano Zampini PetscCall(MatView(*coarse_submat,viewer)); 53069de2952eSStefano Zampini if (pcbddc->coarse_phi_B) { 53079de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B")); 53089de2952eSStefano Zampini PetscCall(MatView(pcbddc->coarse_phi_B,viewer)); 53099de2952eSStefano Zampini } 53109de2952eSStefano Zampini if (pcbddc->coarse_phi_D) { 53119de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D")); 53129de2952eSStefano Zampini PetscCall(MatView(pcbddc->coarse_phi_D,viewer)); 53139de2952eSStefano Zampini } 53149de2952eSStefano Zampini if (pcbddc->coarse_psi_B) { 53159de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B")); 53169de2952eSStefano Zampini PetscCall(MatView(pcbddc->coarse_psi_B,viewer)); 53179de2952eSStefano Zampini } 53189de2952eSStefano Zampini if (pcbddc->coarse_psi_D) { 53199de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D")); 53209de2952eSStefano Zampini PetscCall(MatView(pcbddc->coarse_psi_D,viewer)); 53219de2952eSStefano Zampini } 53229de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcbddc->local_mat,"A")); 53239de2952eSStefano Zampini PetscCall(MatView(pcbddc->local_mat,viewer)); 53249de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcbddc->ConstraintMatrix,"C")); 53259de2952eSStefano Zampini PetscCall(MatView(pcbddc->ConstraintMatrix,viewer)); 53269de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcis->is_I_local,"I")); 53279de2952eSStefano Zampini PetscCall(ISView(pcis->is_I_local,viewer)); 53289de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcis->is_B_local,"B")); 53299de2952eSStefano Zampini PetscCall(ISView(pcis->is_B_local,viewer)); 53309de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcbddc->is_R_local,"R")); 53319de2952eSStefano Zampini PetscCall(ISView(pcbddc->is_R_local,viewer)); 5332648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&viewer)); 53339de2952eSStefano Zampini } 53349de2952eSStefano Zampini #endif 53359de2952eSStefano Zampini 53369de2952eSStefano Zampini /* device support */ 53379de2952eSStefano Zampini { 53389de2952eSStefano Zampini PetscBool iscuda, iship, iskokkos; 53399de2952eSStefano Zampini MatType mtype = NULL; 53409de2952eSStefano Zampini 53419de2952eSStefano Zampini PetscCall(PetscObjectTypeCompareAny((PetscObject)pcis->vec1_N, &iscuda, VECCUDA, VECMPICUDA, VECSEQCUDA, "")); 53429de2952eSStefano Zampini PetscCall(PetscObjectTypeCompareAny((PetscObject)pcis->vec1_N, &iship, VECHIP, VECMPIHIP, VECSEQHIP, "")); 53439de2952eSStefano Zampini PetscCall(PetscObjectTypeCompareAny((PetscObject)pcis->vec1_N, &iskokkos, VECKOKKOS, VECMPIKOKKOS, VECSEQKOKKOS, "")); 53449de2952eSStefano Zampini if (iskokkos) { 53459de2952eSStefano Zampini if (PetscDefined(HAVE_MACRO_KOKKOS_ENABLE_CUDA)) iscuda = PETSC_TRUE; 53469de2952eSStefano Zampini else if (PetscDefined(HAVE_MACRO_KOKKOS_ENABLE_HIP)) iship = PETSC_TRUE; 53479de2952eSStefano Zampini } 53489de2952eSStefano Zampini if (iskokkos) mtype = multi_element ? MATSEQAIJKOKKOS : (iscuda ? MATSEQDENSECUDA : MATSEQDENSEHIP); 53499de2952eSStefano Zampini else if (iship) mtype = multi_element ? MATSEQAIJHIPSPARSE : MATSEQDENSEHIP; 53509de2952eSStefano Zampini else if (iscuda) mtype = multi_element ? MATSEQAIJCUSPARSE : MATSEQDENSECUDA; 53519de2952eSStefano Zampini if (mtype) { 53529de2952eSStefano Zampini if (pcbddc->local_auxmat1) PetscCall(MatConvert(pcbddc->local_auxmat1, mtype, MAT_INPLACE_MATRIX, &pcbddc->local_auxmat1)); 53539de2952eSStefano Zampini if (pcbddc->local_auxmat2) PetscCall(MatConvert(pcbddc->local_auxmat2, mtype, MAT_INPLACE_MATRIX, &pcbddc->local_auxmat2)); 53549de2952eSStefano Zampini if (pcbddc->coarse_phi_B) PetscCall(MatConvert(pcbddc->coarse_phi_B, mtype, MAT_INPLACE_MATRIX, &pcbddc->coarse_phi_B)); 53559de2952eSStefano Zampini if (pcbddc->coarse_phi_D) PetscCall(MatConvert(pcbddc->coarse_phi_D, mtype, MAT_INPLACE_MATRIX, &pcbddc->coarse_phi_D)); 53569de2952eSStefano Zampini if (pcbddc->coarse_psi_B) PetscCall(MatConvert(pcbddc->coarse_psi_B, mtype, MAT_INPLACE_MATRIX, &pcbddc->coarse_psi_B)); 53579de2952eSStefano Zampini if (pcbddc->coarse_psi_D) PetscCall(MatConvert(pcbddc->coarse_psi_D, mtype, MAT_INPLACE_MATRIX, &pcbddc->coarse_psi_D)); 53587ebab0bbSStefano Zampini } 53597ebab0bbSStefano Zampini } 53603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 536188ebb749SStefano Zampini } 536288ebb749SStefano Zampini 5363d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat *B) 5364d71ae5a4SJacob Faibussowitsch { 5365d65f70fdSStefano Zampini Mat *work_mat; 5366d65f70fdSStefano Zampini IS isrow_s, iscol_s; 5367d65f70fdSStefano Zampini PetscBool rsorted, csorted; 5368c43ebad9SStefano Zampini PetscInt rsize, *idxs_perm_r = NULL, csize, *idxs_perm_c = NULL; 5369aa0d41d4SStefano Zampini 5370aa0d41d4SStefano Zampini PetscFunctionBegin; 53719566063dSJacob Faibussowitsch PetscCall(ISSorted(isrow, &rsorted)); 53729566063dSJacob Faibussowitsch PetscCall(ISSorted(iscol, &csorted)); 53739566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isrow, &rsize)); 53749566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(iscol, &csize)); 5375aa0d41d4SStefano Zampini 5376d65f70fdSStefano Zampini if (!rsorted) { 5377906d46d4SStefano Zampini const PetscInt *idxs; 5378906d46d4SStefano Zampini PetscInt *idxs_sorted, i; 5379aa0d41d4SStefano Zampini 53809566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rsize, &idxs_perm_r)); 53819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rsize, &idxs_sorted)); 5382ad540459SPierre Jolivet for (i = 0; i < rsize; i++) idxs_perm_r[i] = i; 53839566063dSJacob Faibussowitsch PetscCall(ISGetIndices(isrow, &idxs)); 53849566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithPermutation(rsize, idxs, idxs_perm_r)); 5385ad540459SPierre Jolivet for (i = 0; i < rsize; i++) idxs_sorted[i] = idxs[idxs_perm_r[i]]; 53869566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(isrow, &idxs)); 53879566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, rsize, idxs_sorted, PETSC_OWN_POINTER, &isrow_s)); 5388d65f70fdSStefano Zampini } else { 53899566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)isrow)); 5390d65f70fdSStefano Zampini isrow_s = isrow; 5391aa0d41d4SStefano Zampini } 5392906d46d4SStefano Zampini 5393d65f70fdSStefano Zampini if (!csorted) { 5394d65f70fdSStefano Zampini if (isrow == iscol) { 53959566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)isrow_s)); 5396d65f70fdSStefano Zampini iscol_s = isrow_s; 5397d65f70fdSStefano Zampini } else { 5398d65f70fdSStefano Zampini const PetscInt *idxs; 5399d65f70fdSStefano Zampini PetscInt *idxs_sorted, i; 5400906d46d4SStefano Zampini 54019566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(csize, &idxs_perm_c)); 54029566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(csize, &idxs_sorted)); 5403ad540459SPierre Jolivet for (i = 0; i < csize; i++) idxs_perm_c[i] = i; 54049566063dSJacob Faibussowitsch PetscCall(ISGetIndices(iscol, &idxs)); 54059566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithPermutation(csize, idxs, idxs_perm_c)); 5406ad540459SPierre Jolivet for (i = 0; i < csize; i++) idxs_sorted[i] = idxs[idxs_perm_c[i]]; 54079566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(iscol, &idxs)); 54089566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, csize, idxs_sorted, PETSC_OWN_POINTER, &iscol_s)); 5409d65f70fdSStefano Zampini } 5410d65f70fdSStefano Zampini } else { 54119566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)iscol)); 5412d65f70fdSStefano Zampini iscol_s = iscol; 5413d65f70fdSStefano Zampini } 5414d65f70fdSStefano Zampini 54159566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(A, 1, &isrow_s, &iscol_s, MAT_INITIAL_MATRIX, &work_mat)); 5416d65f70fdSStefano Zampini 5417d65f70fdSStefano Zampini if (!rsorted || !csorted) { 5418906d46d4SStefano Zampini Mat new_mat; 5419d65f70fdSStefano Zampini IS is_perm_r, is_perm_c; 5420906d46d4SStefano Zampini 5421d65f70fdSStefano Zampini if (!rsorted) { 5422d65f70fdSStefano Zampini PetscInt *idxs_r, i; 54239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rsize, &idxs_r)); 5424ad540459SPierre Jolivet for (i = 0; i < rsize; i++) idxs_r[idxs_perm_r[i]] = i; 54259566063dSJacob Faibussowitsch PetscCall(PetscFree(idxs_perm_r)); 54269566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, rsize, idxs_r, PETSC_OWN_POINTER, &is_perm_r)); 5427d65f70fdSStefano Zampini } else { 54289566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, rsize, 0, 1, &is_perm_r)); 5429906d46d4SStefano Zampini } 54309566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(is_perm_r)); 5431d65f70fdSStefano Zampini 5432d65f70fdSStefano Zampini if (!csorted) { 5433d65f70fdSStefano Zampini if (isrow_s == iscol_s) { 54349566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is_perm_r)); 5435d65f70fdSStefano Zampini is_perm_c = is_perm_r; 5436d65f70fdSStefano Zampini } else { 5437d65f70fdSStefano Zampini PetscInt *idxs_c, i; 543828b400f6SJacob Faibussowitsch PetscCheck(idxs_perm_c, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Permutation array not present"); 54399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(csize, &idxs_c)); 5440ad540459SPierre Jolivet for (i = 0; i < csize; i++) idxs_c[idxs_perm_c[i]] = i; 54419566063dSJacob Faibussowitsch PetscCall(PetscFree(idxs_perm_c)); 54429566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, csize, idxs_c, PETSC_OWN_POINTER, &is_perm_c)); 5443d65f70fdSStefano Zampini } 5444d65f70fdSStefano Zampini } else { 54459566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, csize, 0, 1, &is_perm_c)); 5446d65f70fdSStefano Zampini } 54479566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(is_perm_c)); 5448d65f70fdSStefano Zampini 54499566063dSJacob Faibussowitsch PetscCall(MatPermute(work_mat[0], is_perm_r, is_perm_c, &new_mat)); 54509566063dSJacob Faibussowitsch PetscCall(MatDestroy(&work_mat[0])); 5451d65f70fdSStefano Zampini work_mat[0] = new_mat; 54529566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_perm_r)); 54539566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_perm_c)); 5454d65f70fdSStefano Zampini } 5455d65f70fdSStefano Zampini 54569566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)work_mat[0])); 5457d65f70fdSStefano Zampini *B = work_mat[0]; 54589566063dSJacob Faibussowitsch PetscCall(MatDestroyMatrices(1, &work_mat)); 54599566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isrow_s)); 54609566063dSJacob Faibussowitsch PetscCall(ISDestroy(&iscol_s)); 54613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5462d65f70fdSStefano Zampini } 5463d65f70fdSStefano Zampini 5464d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix) 5465d71ae5a4SJacob Faibussowitsch { 5466aa0d41d4SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 54675e8657edSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 5468022d8d2bSstefano_zampini Mat new_mat, lA; 54695e8657edSStefano Zampini IS is_local, is_global; 5470d65f70fdSStefano Zampini PetscInt local_size; 5471b94d7dedSBarry Smith PetscBool isseqaij, issym, isset; 5472aa0d41d4SStefano Zampini 5473aa0d41d4SStefano Zampini PetscFunctionBegin; 54749566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 54759566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A, &local_size, NULL)); 54769de2952eSStefano Zampini if (pcbddc->mat_graph->multi_element) { 54779de2952eSStefano Zampini Mat *mats, *bdiags; 54789de2952eSStefano Zampini IS *gsubs; 54799de2952eSStefano Zampini PetscInt nsubs = pcbddc->n_local_subs; 54809de2952eSStefano Zampini 54819de2952eSStefano Zampini PetscCall(PetscCalloc1(nsubs * nsubs, &mats)); 54829de2952eSStefano Zampini PetscCall(PetscMalloc1(nsubs, &gsubs)); 54839de2952eSStefano Zampini for (PetscInt i = 0; i < nsubs; i++) PetscCall(ISLocalToGlobalMappingApplyIS(matis->rmapping, pcbddc->local_subs[i], &gsubs[i])); 54849de2952eSStefano Zampini PetscCall(MatCreateSubMatrices(ChangeOfBasisMatrix, nsubs, gsubs, gsubs, MAT_INITIAL_MATRIX, &bdiags)); 54859de2952eSStefano Zampini for (PetscInt i = 0; i < nsubs; i++) PetscCall(ISDestroy(&gsubs[i])); 54869de2952eSStefano Zampini PetscCall(PetscFree(gsubs)); 54879de2952eSStefano Zampini 54889de2952eSStefano Zampini for (PetscInt i = 0; i < nsubs; i++) mats[i * (1 + nsubs)] = bdiags[i]; 54899de2952eSStefano Zampini PetscCall(MatCreateNest(PETSC_COMM_SELF, nsubs, pcbddc->local_subs, nsubs, pcbddc->local_subs, mats, &new_mat)); 54909de2952eSStefano Zampini PetscCall(MatConvert(new_mat, MATSEQAIJ, MAT_INPLACE_MATRIX, &new_mat)); 54919de2952eSStefano Zampini PetscCall(MatDestroySubMatrices(nsubs, &bdiags)); 54929de2952eSStefano Zampini PetscCall(PetscFree(mats)); 54939de2952eSStefano Zampini } else { 54949566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)matis->A), local_size, 0, 1, &is_local)); 54959566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(matis->rmapping, is_local, &is_global)); 54969566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_local)); 54979566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrixUnsorted(ChangeOfBasisMatrix, is_global, is_global, &new_mat)); 54989566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_global)); 54999de2952eSStefano Zampini } 5500906d46d4SStefano Zampini if (pcbddc->dbg_flag) { 5501906d46d4SStefano Zampini Vec x, x_change; 5502906d46d4SStefano Zampini PetscReal error; 5503906d46d4SStefano Zampini 55049566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(ChangeOfBasisMatrix, &x, &x_change)); 55059566063dSJacob Faibussowitsch PetscCall(VecSetRandom(x, NULL)); 55069566063dSJacob Faibussowitsch PetscCall(MatMult(ChangeOfBasisMatrix, x, x_change)); 55079566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->cctx, x, matis->x, INSERT_VALUES, SCATTER_FORWARD)); 55089566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->cctx, x, matis->x, INSERT_VALUES, SCATTER_FORWARD)); 55099566063dSJacob Faibussowitsch PetscCall(MatMult(new_mat, matis->x, matis->y)); 551088428137SStefano Zampini if (!pcbddc->change_interior) { 551188428137SStefano Zampini const PetscScalar *x, *y, *v; 551288428137SStefano Zampini PetscReal lerror = 0.; 551388428137SStefano Zampini PetscInt i; 551488428137SStefano Zampini 55159566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(matis->x, &x)); 55169566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(matis->y, &y)); 55179566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(matis->counter, &v)); 551888428137SStefano Zampini for (i = 0; i < local_size; i++) 55199371c9d4SSatish Balay if (PetscRealPart(v[i]) < 1.5 && PetscAbsScalar(x[i] - y[i]) > lerror) lerror = PetscAbsScalar(x[i] - y[i]); 55209566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(matis->x, &x)); 55219566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(matis->y, &y)); 55229566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(matis->counter, &v)); 5523462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&lerror, &error, 1, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)pc))); 5524637e8532SStefano Zampini if (error > PETSC_SMALL) { 5525637e8532SStefano Zampini if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) { 552663a3b9bcSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_PLIB, "Error global vs local change on I: %1.6e", (double)error); 5527637e8532SStefano Zampini } else { 552863a3b9bcSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "Error global vs local change on I: %1.6e", (double)error); 5529637e8532SStefano Zampini } 5530637e8532SStefano Zampini } 553188428137SStefano Zampini } 55329566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, matis->y, x, INSERT_VALUES, SCATTER_REVERSE)); 55339566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, matis->y, x, INSERT_VALUES, SCATTER_REVERSE)); 55349566063dSJacob Faibussowitsch PetscCall(VecAXPY(x, -1.0, x_change)); 55359566063dSJacob Faibussowitsch PetscCall(VecNorm(x, NORM_INFINITY, &error)); 5536637e8532SStefano Zampini if (error > PETSC_SMALL) { 5537637e8532SStefano Zampini if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) { 553863a3b9bcSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_PLIB, "Error global vs local change on N: %1.6e", (double)error); 5539637e8532SStefano Zampini } else { 554063a3b9bcSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "Error global vs local change on N: %1.6e", (double)error); 5541637e8532SStefano Zampini } 5542637e8532SStefano Zampini } 55439566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 55449566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x_change)); 5545906d46d4SStefano Zampini } 5546906d46d4SStefano Zampini 5547022d8d2bSstefano_zampini /* lA is present if we are setting up an inner BDDC for a saddle point FETI-DP */ 55489566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lA", (PetscObject *)&lA)); 5549022d8d2bSstefano_zampini 555022d5777bSStefano Zampini /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */ 55519566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQAIJ, &isseqaij)); 555222d5777bSStefano Zampini if (isseqaij) { 55539566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 55549566063dSJacob Faibussowitsch PetscCall(MatPtAP(matis->A, new_mat, MAT_INITIAL_MATRIX, 2.0, &pcbddc->local_mat)); 5555022d8d2bSstefano_zampini if (lA) { 5556022d8d2bSstefano_zampini Mat work; 55579566063dSJacob Faibussowitsch PetscCall(MatPtAP(lA, new_mat, MAT_INITIAL_MATRIX, 2.0, &work)); 55589566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_lA", (PetscObject)work)); 55599566063dSJacob Faibussowitsch PetscCall(MatDestroy(&work)); 5560022d8d2bSstefano_zampini } 5561aa0d41d4SStefano Zampini } else { 5562a00504b5SStefano Zampini Mat work_mat; 55631cf9b237SStefano Zampini 55649566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 55659566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &work_mat)); 55669566063dSJacob Faibussowitsch PetscCall(MatPtAP(work_mat, new_mat, MAT_INITIAL_MATRIX, 2.0, &pcbddc->local_mat)); 55679566063dSJacob Faibussowitsch PetscCall(MatDestroy(&work_mat)); 5568022d8d2bSstefano_zampini if (lA) { 5569022d8d2bSstefano_zampini Mat work; 55709566063dSJacob Faibussowitsch PetscCall(MatConvert(lA, MATSEQAIJ, MAT_INITIAL_MATRIX, &work_mat)); 55719566063dSJacob Faibussowitsch PetscCall(MatPtAP(work_mat, new_mat, MAT_INITIAL_MATRIX, 2.0, &work)); 55729566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_lA", (PetscObject)work)); 55739566063dSJacob Faibussowitsch PetscCall(MatDestroy(&work)); 5574022d8d2bSstefano_zampini } 5575aa0d41d4SStefano Zampini } 5576b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(matis->A, &isset, &issym)); 5577b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(pcbddc->local_mat, MAT_SYMMETRIC, issym)); 55789566063dSJacob Faibussowitsch PetscCall(MatDestroy(&new_mat)); 55793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5580aa0d41d4SStefano Zampini } 5581aa0d41d4SStefano Zampini 5582d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpLocalScatters(PC pc) 5583d71ae5a4SJacob Faibussowitsch { 5584f4f49eeaSPierre Jolivet PC_IS *pcis = (PC_IS *)pc->data; 5585a64d13efSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 5586d62866d3SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 558753892102SStefano Zampini PetscInt *idx_R_local = NULL; 55883a50541eSStefano Zampini PetscInt n_vertices, i, j, n_R, n_D, n_B; 55893a50541eSStefano Zampini PetscInt vbs, bs; 55906816873aSStefano Zampini PetscBT bitmask = NULL; 5591a64d13efSStefano Zampini 5592a64d13efSStefano Zampini PetscFunctionBegin; 5593b23d619eSStefano Zampini /* 5594b23d619eSStefano Zampini No need to setup local scatters if 5595b23d619eSStefano Zampini - primal space is unchanged 5596b23d619eSStefano Zampini AND 5597b23d619eSStefano Zampini - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains) 5598b23d619eSStefano Zampini AND 5599b23d619eSStefano Zampini - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine 5600b23d619eSStefano Zampini */ 56013ba16761SJacob Faibussowitsch if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) PetscFunctionReturn(PETSC_SUCCESS); 5602f4ddd8eeSStefano Zampini /* destroy old objects */ 56039566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->is_R_local)); 56049566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->R_to_B)); 56059566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->R_to_D)); 5606a64d13efSStefano Zampini /* Set Non-overlapping dimensions */ 5607b371cd4fSStefano Zampini n_B = pcis->n_B; 5608b371cd4fSStefano Zampini n_D = pcis->n - n_B; 5609b371cd4fSStefano Zampini n_vertices = pcbddc->n_vertices; 56103a50541eSStefano Zampini 5611e602f447SPierre Jolivet /* Dohrmann's notation: dofs split in R (Remaining: all dofs but the vertices) and V (Vertices) */ 56126816873aSStefano Zampini 561353892102SStefano Zampini /* create auxiliary bitmask and allocate workspace */ 5614b334f244SStefano Zampini if (!sub_schurs || !sub_schurs->reuse_solver) { 56159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n - n_vertices, &idx_R_local)); 56169566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(pcis->n, &bitmask)); 561748a46eb9SPierre Jolivet for (i = 0; i < n_vertices; i++) PetscCall(PetscBTSet(bitmask, pcbddc->local_primal_ref_node[i])); 56184641a718SStefano Zampini 5619a64d13efSStefano Zampini for (i = 0, n_R = 0; i < pcis->n; i++) { 5620ad540459SPierre Jolivet if (!PetscBTLookup(bitmask, i)) idx_R_local[n_R++] = i; 5621a64d13efSStefano Zampini } 5622df4d28bfSStefano Zampini } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */ 5623df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 56246816873aSStefano Zampini 56259566063dSJacob Faibussowitsch PetscCall(ISGetIndices(reuse_solver->is_R, (const PetscInt **)&idx_R_local)); 56269566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(reuse_solver->is_R, &n_R)); 56276816873aSStefano Zampini } 56283a50541eSStefano Zampini 56293a50541eSStefano Zampini /* Block code */ 56303a50541eSStefano Zampini vbs = 1; 56319566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(pcbddc->local_mat, &bs)); 56323a50541eSStefano Zampini if (bs > 1 && !(n_vertices % bs)) { 56333a50541eSStefano Zampini PetscBool is_blocked = PETSC_TRUE; 56343a50541eSStefano Zampini PetscInt *vary; 5635b334f244SStefano Zampini if (!sub_schurs || !sub_schurs->reuse_solver) { 56369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n / bs, &vary)); 56379566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(vary, pcis->n / bs)); 5638d3df7717SStefano Zampini /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */ 5639d3df7717SStefano 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 */ 56400e6343abSStefano Zampini for (i = 0; i < n_vertices; i++) vary[pcbddc->local_primal_ref_node[i] / bs]++; 5641d3df7717SStefano Zampini for (i = 0; i < pcis->n / bs; i++) { 56423a50541eSStefano Zampini if (vary[i] != 0 && vary[i] != bs) { 56433a50541eSStefano Zampini is_blocked = PETSC_FALSE; 56443a50541eSStefano Zampini break; 56453a50541eSStefano Zampini } 56463a50541eSStefano Zampini } 56479566063dSJacob Faibussowitsch PetscCall(PetscFree(vary)); 5648d3df7717SStefano Zampini } else { 5649d3df7717SStefano Zampini /* Verify directly the R set */ 5650d3df7717SStefano Zampini for (i = 0; i < n_R / bs; i++) { 5651d3df7717SStefano Zampini PetscInt j, node = idx_R_local[bs * i]; 5652d3df7717SStefano Zampini for (j = 1; j < bs; j++) { 5653d3df7717SStefano Zampini if (node != idx_R_local[bs * i + j] - j) { 5654d3df7717SStefano Zampini is_blocked = PETSC_FALSE; 5655d3df7717SStefano Zampini break; 5656d3df7717SStefano Zampini } 5657d3df7717SStefano Zampini } 5658d3df7717SStefano Zampini } 5659d3df7717SStefano Zampini } 56603a50541eSStefano Zampini if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */ 56613a50541eSStefano Zampini vbs = bs; 5662ad540459SPierre Jolivet for (i = 0; i < n_R / vbs; i++) idx_R_local[i] = idx_R_local[vbs * i] / vbs; 56633a50541eSStefano Zampini } 56643a50541eSStefano Zampini } 56659566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF, vbs, n_R / vbs, idx_R_local, PETSC_COPY_VALUES, &pcbddc->is_R_local)); 5666b334f244SStefano Zampini if (sub_schurs && sub_schurs->reuse_solver) { 5667df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 566853892102SStefano Zampini 56699566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(reuse_solver->is_R, (const PetscInt **)&idx_R_local)); 56709566063dSJacob Faibussowitsch PetscCall(ISDestroy(&reuse_solver->is_R)); 56719566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->is_R_local)); 5672df4d28bfSStefano Zampini reuse_solver->is_R = pcbddc->is_R_local; 567353892102SStefano Zampini } else { 56749566063dSJacob Faibussowitsch PetscCall(PetscFree(idx_R_local)); 567553892102SStefano Zampini } 5676a64d13efSStefano Zampini 5677a64d13efSStefano Zampini /* print some info if requested */ 5678a64d13efSStefano Zampini if (pcbddc->dbg_flag) { 56799566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 56809566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 56819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 56829566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d local dimensions\n", PetscGlobalRank)); 568363a3b9bcSJacob 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)); 56849371c9d4SSatish 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, 56859371c9d4SSatish Balay pcbddc->local_primal_size - n_vertices - pcbddc->benign_n, pcbddc->local_primal_size)); 56869566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 5687a64d13efSStefano Zampini } 5688a64d13efSStefano Zampini 5689a64d13efSStefano Zampini /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */ 5690b334f244SStefano Zampini if (!sub_schurs || !sub_schurs->reuse_solver) { 56916816873aSStefano Zampini IS is_aux1, is_aux2; 56926816873aSStefano Zampini PetscInt *aux_array1, *aux_array2, *is_indices, *idx_R_local; 56936816873aSStefano Zampini 56949566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->is_R_local, (const PetscInt **)&idx_R_local)); 56959566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n_B - n_vertices, &aux_array1)); 56969566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n_B - n_vertices, &aux_array2)); 56979566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_I_local, (const PetscInt **)&is_indices)); 569848a46eb9SPierre Jolivet for (i = 0; i < n_D; i++) PetscCall(PetscBTSet(bitmask, is_indices[i])); 56999566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_I_local, (const PetscInt **)&is_indices)); 5700a64d13efSStefano Zampini for (i = 0, j = 0; i < n_R; i++) { 5701ad540459SPierre Jolivet if (!PetscBTLookup(bitmask, idx_R_local[i])) aux_array1[j++] = i; 5702a64d13efSStefano Zampini } 57039566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, aux_array1, PETSC_OWN_POINTER, &is_aux1)); 57049566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_B_local, (const PetscInt **)&is_indices)); 5705a64d13efSStefano Zampini for (i = 0, j = 0; i < n_B; i++) { 5706ad540459SPierre Jolivet if (!PetscBTLookup(bitmask, is_indices[i])) aux_array2[j++] = i; 5707a64d13efSStefano Zampini } 57089566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_B_local, (const PetscInt **)&is_indices)); 57099566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, aux_array2, PETSC_OWN_POINTER, &is_aux2)); 57109566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(pcbddc->vec1_R, is_aux1, pcis->vec1_B, is_aux2, &pcbddc->R_to_B)); 57119566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_aux1)); 57129566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_aux2)); 5713a64d13efSStefano Zampini 57148eeda7d8SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 57159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_D, &aux_array1)); 5716a64d13efSStefano Zampini for (i = 0, j = 0; i < n_R; i++) { 5717ad540459SPierre Jolivet if (PetscBTLookup(bitmask, idx_R_local[i])) aux_array1[j++] = i; 5718a64d13efSStefano Zampini } 57199566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, aux_array1, PETSC_OWN_POINTER, &is_aux1)); 57209566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(pcbddc->vec1_R, is_aux1, pcis->vec1_D, (IS)0, &pcbddc->R_to_D)); 57219566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_aux1)); 5722a64d13efSStefano Zampini } 57239566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&bitmask)); 57249566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->is_R_local, (const PetscInt **)&idx_R_local)); 5725d62866d3SStefano Zampini } else { 5726df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 57276816873aSStefano Zampini IS tis; 57286816873aSStefano Zampini PetscInt schur_size; 57296816873aSStefano Zampini 57309566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(reuse_solver->is_B, &schur_size)); 57319566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, schur_size, n_D, 1, &tis)); 57329566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(pcbddc->vec1_R, tis, pcis->vec1_B, reuse_solver->is_B, &pcbddc->R_to_B)); 57339566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tis)); 57346816873aSStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 57359566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, n_D, 0, 1, &tis)); 57369566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(pcbddc->vec1_R, tis, pcis->vec1_D, (IS)0, &pcbddc->R_to_D)); 57379566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tis)); 5738d62866d3SStefano Zampini } 5739d62866d3SStefano Zampini } 57403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5741a64d13efSStefano Zampini } 5742a64d13efSStefano Zampini 5743e1614d24SStefano Zampini PetscErrorCode MatNullSpacePropagateAny_Private(Mat A, IS is, Mat B) 5744d71ae5a4SJacob Faibussowitsch { 574592cccca0SStefano Zampini MatNullSpace NullSpace; 574692cccca0SStefano Zampini Mat dmat; 574792cccca0SStefano Zampini const Vec *nullvecs; 574892cccca0SStefano Zampini Vec v, v2, *nullvecs2; 57496d9e27e4SStefano Zampini VecScatter sct = NULL; 5750eb06acf8SStefano Zampini PetscScalar *ddata; 5751295df10fSStefano Zampini PetscInt k, nnsp_size, bsiz, bsiz2, n, N, bs; 575292cccca0SStefano Zampini PetscBool nnsp_has_cnst; 575392cccca0SStefano Zampini 575492cccca0SStefano Zampini PetscFunctionBegin; 57556d9e27e4SStefano Zampini if (!is && !B) { /* MATIS */ 57566d9e27e4SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 57576d9e27e4SStefano Zampini 575848a46eb9SPierre Jolivet if (!B) PetscCall(MatISGetLocalMat(A, &B)); 57596d9e27e4SStefano Zampini sct = matis->cctx; 57609566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)sct)); 57616d9e27e4SStefano Zampini } else { 57629566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(B, &NullSpace)); 576348a46eb9SPierre Jolivet if (!NullSpace) PetscCall(MatGetNearNullSpace(B, &NullSpace)); 57643ba16761SJacob Faibussowitsch if (NullSpace) PetscFunctionReturn(PETSC_SUCCESS); 57656d9e27e4SStefano Zampini } 57669566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(A, &NullSpace)); 576748a46eb9SPierre Jolivet if (!NullSpace) PetscCall(MatGetNearNullSpace(A, &NullSpace)); 57683ba16761SJacob Faibussowitsch if (!NullSpace) PetscFunctionReturn(PETSC_SUCCESS); 57696d9e27e4SStefano Zampini 57709566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, &v, NULL)); 57719566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(B, &v2, NULL)); 577248a46eb9SPierre Jolivet if (!sct) PetscCall(VecScatterCreate(v, is, v2, NULL, &sct)); 5773835f2295SStefano Zampini PetscCall(MatNullSpaceGetVecs(NullSpace, &nnsp_has_cnst, &nnsp_size, &nullvecs)); 5774295df10fSStefano Zampini bsiz = bsiz2 = nnsp_size + !!nnsp_has_cnst; 57759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bsiz, &nullvecs2)); 57769566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(v2, &bs)); 57779566063dSJacob Faibussowitsch PetscCall(VecGetSize(v2, &N)); 57789566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v2, &n)); 57799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n * bsiz, &ddata)); 578092cccca0SStefano Zampini for (k = 0; k < nnsp_size; k++) { 57819566063dSJacob Faibussowitsch PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)B), bs, n, N, ddata + n * k, &nullvecs2[k])); 57829566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sct, nullvecs[k], nullvecs2[k], INSERT_VALUES, SCATTER_FORWARD)); 57839566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sct, nullvecs[k], nullvecs2[k], INSERT_VALUES, SCATTER_FORWARD)); 578492cccca0SStefano Zampini } 578592cccca0SStefano Zampini if (nnsp_has_cnst) { 57869566063dSJacob Faibussowitsch PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)B), bs, n, N, ddata + n * nnsp_size, &nullvecs2[nnsp_size])); 57879566063dSJacob Faibussowitsch PetscCall(VecSet(nullvecs2[nnsp_size], 1.0)); 578892cccca0SStefano Zampini } 57899566063dSJacob Faibussowitsch PetscCall(PCBDDCOrthonormalizeVecs(&bsiz2, nullvecs2)); 57909566063dSJacob Faibussowitsch PetscCall(MatNullSpaceCreate(PetscObjectComm((PetscObject)B), PETSC_FALSE, bsiz2, nullvecs2, &NullSpace)); 5791295df10fSStefano Zampini 57929566063dSJacob Faibussowitsch PetscCall(MatCreateDense(PetscObjectComm((PetscObject)B), n, PETSC_DECIDE, N, bsiz2, ddata, &dmat)); 579349abdd8aSBarry Smith PetscCall(PetscObjectContainerCompose((PetscObject)dmat, "_PBDDC_Null_dmat_arr", ddata, PetscCtxDestroyDefault)); 57949566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)NullSpace, "_PBDDC_Null_dmat", (PetscObject)dmat)); 57959566063dSJacob Faibussowitsch PetscCall(MatDestroy(&dmat)); 5796eb06acf8SStefano Zampini 579748a46eb9SPierre Jolivet for (k = 0; k < bsiz; k++) PetscCall(VecDestroy(&nullvecs2[k])); 57989566063dSJacob Faibussowitsch PetscCall(PetscFree(nullvecs2)); 57999566063dSJacob Faibussowitsch PetscCall(MatSetNearNullSpace(B, NullSpace)); 58009566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&NullSpace)); 58019566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 58029566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v2)); 58039566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sct)); 58043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 580592cccca0SStefano Zampini } 5806304d26faSStefano Zampini 5807d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann) 5808d71ae5a4SJacob Faibussowitsch { 5809304d26faSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 5810304d26faSStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 5811304d26faSStefano Zampini PC pc_temp; 5812304d26faSStefano Zampini Mat A_RR; 581392cccca0SStefano Zampini MatNullSpace nnsp; 5814f4ddd8eeSStefano Zampini MatReuse reuse; 5815304d26faSStefano Zampini PetscScalar m_one = -1.0; 5816304d26faSStefano Zampini PetscReal value; 581704708bb6SStefano Zampini PetscInt n_D, n_R; 5818b94d7dedSBarry Smith PetscBool issbaij, opts, isset, issym; 58190cd8b6e2SStefano Zampini PetscBool f = PETSC_FALSE; 5820312be037SStefano Zampini char dir_prefix[256], neu_prefix[256], str_level[16]; 5821e604994aSStefano Zampini size_t len; 5822304d26faSStefano Zampini 5823304d26faSStefano Zampini PetscFunctionBegin; 58249566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_LocalSolvers[pcbddc->current_level], pc, 0, 0, 0)); 58256d9e27e4SStefano Zampini /* approximate solver, propagate NearNullSpace if needed */ 58266d9e27e4SStefano Zampini if (!pc->setupcalled && (pcbddc->NullSpace_corr[0] || pcbddc->NullSpace_corr[2])) { 58276d9e27e4SStefano Zampini MatNullSpace gnnsp1, gnnsp2; 58286d9e27e4SStefano Zampini PetscBool lhas, ghas; 58296d9e27e4SStefano Zampini 58309566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pcbddc->local_mat, &nnsp)); 58319566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pc->pmat, &gnnsp1)); 58329566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(pc->pmat, &gnnsp2)); 58336d9e27e4SStefano Zampini lhas = nnsp ? PETSC_TRUE : PETSC_FALSE; 5834462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&lhas, &ghas, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 583548a46eb9SPierre Jolivet if (!ghas && (gnnsp1 || gnnsp2)) PetscCall(MatNullSpacePropagateAny_Private(pc->pmat, NULL, NULL)); 58366d9e27e4SStefano Zampini } 58376d9e27e4SStefano Zampini 5838e604994aSStefano Zampini /* compute prefixes */ 5839c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(dir_prefix, "", sizeof(dir_prefix))); 5840c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(neu_prefix, "", sizeof(neu_prefix))); 5841e604994aSStefano Zampini if (!pcbddc->current_level) { 58429566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(dir_prefix, ((PetscObject)pc)->prefix, sizeof(dir_prefix))); 58439566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(neu_prefix, ((PetscObject)pc)->prefix, sizeof(neu_prefix))); 58449566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(dir_prefix, "pc_bddc_dirichlet_", sizeof(dir_prefix))); 58459566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(neu_prefix, "pc_bddc_neumann_", sizeof(neu_prefix))); 5846e604994aSStefano Zampini } else { 5847835f2295SStefano Zampini PetscCall(PetscSNPrintf(str_level, sizeof(str_level), "l%" PetscInt_FMT "_", pcbddc->current_level)); 58489566063dSJacob Faibussowitsch PetscCall(PetscStrlen(((PetscObject)pc)->prefix, &len)); 5849e604994aSStefano Zampini len -= 15; /* remove "pc_bddc_coarse_" */ 5850312be037SStefano Zampini if (pcbddc->current_level > 1) len -= 3; /* remove "lX_" with X level number */ 5851312be037SStefano Zampini if (pcbddc->current_level > 10) len -= 1; /* remove another char from level number */ 5852a126751eSBarry Smith /* Nonstandard use of PetscStrncpy() to only copy a portion of the input string */ 58539566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(dir_prefix, ((PetscObject)pc)->prefix, len + 1)); 58549566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(neu_prefix, ((PetscObject)pc)->prefix, len + 1)); 58559566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(dir_prefix, "pc_bddc_dirichlet_", sizeof(dir_prefix))); 58569566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(neu_prefix, "pc_bddc_neumann_", sizeof(neu_prefix))); 58579566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(dir_prefix, str_level, sizeof(dir_prefix))); 58589566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(neu_prefix, str_level, sizeof(neu_prefix))); 5859e604994aSStefano Zampini } 5860e604994aSStefano Zampini 5861304d26faSStefano Zampini /* DIRICHLET PROBLEM */ 5862684f6988SStefano Zampini if (dirichlet) { 5863d5574798SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 5864450f8f5eSStefano Zampini if (pcbddc->benign_n && !pcbddc->benign_change_explicit) { 58657827d75bSBarry Smith PetscCheck(sub_schurs && sub_schurs->reuse_solver, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not yet implemented"); 5866450f8f5eSStefano Zampini if (pcbddc->dbg_flag) { 5867a3df083aSStefano Zampini Mat A_IIn; 5868a3df083aSStefano Zampini 58699566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignProject(pc, pcis->is_I_local, pcis->is_I_local, &A_IIn)); 58709566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_II)); 5871a3df083aSStefano Zampini pcis->A_II = A_IIn; 5872a3df083aSStefano Zampini } 5873450f8f5eSStefano Zampini } 5874b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(pcbddc->local_mat, &isset, &issym)); 5875b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(pcis->A_II, MAT_SYMMETRIC, issym)); 5876b94d7dedSBarry Smith 5877ac78edfcSStefano Zampini /* Matrix for Dirichlet problem is pcis->A_II */ 5878964fefecSStefano Zampini n_D = pcis->n - pcis->n_B; 587992cccca0SStefano Zampini opts = PETSC_FALSE; 5880304d26faSStefano Zampini if (!pcbddc->ksp_D) { /* create object if not yet build */ 588192cccca0SStefano Zampini opts = PETSC_TRUE; 58829566063dSJacob Faibussowitsch PetscCall(KSPCreate(PETSC_COMM_SELF, &pcbddc->ksp_D)); 58833821be0aSBarry Smith PetscCall(KSPSetNestLevel(pcbddc->ksp_D, pc->kspnestlevel)); 58849566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D, (PetscObject)pc, 1)); 5885304d26faSStefano Zampini /* default */ 58869566063dSJacob Faibussowitsch PetscCall(KSPSetType(pcbddc->ksp_D, KSPPREONLY)); 58879566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(pcbddc->ksp_D, dir_prefix)); 58889566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pcis->pA_II, MATSEQSBAIJ, &issbaij)); 58899566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_D, &pc_temp)); 58909577ea80SStefano Zampini if (issbaij) { 58919566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCCHOLESKY)); 58929577ea80SStefano Zampini } else { 58939566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCLU)); 58949577ea80SStefano Zampini } 58959566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(pcbddc->ksp_D, pc->erroriffailure)); 589692cccca0SStefano Zampini } 58979566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(pcis->pA_II, ((PetscObject)pcbddc->ksp_D)->prefix)); 58989de2952eSStefano Zampini PetscCall(MatViewFromOptions(pcis->pA_II, NULL, "-mat_view")); 58999566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(pcbddc->ksp_D, pcis->A_II, pcis->pA_II)); 5900304d26faSStefano Zampini /* Allow user's customization */ 59011baa6e33SBarry Smith if (opts) PetscCall(KSPSetFromOptions(pcbddc->ksp_D)); 59029566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pcis->pA_II, &nnsp)); 59036d9e27e4SStefano Zampini if (pcbddc->NullSpace_corr[0] && !nnsp) { /* approximate solver, propagate NearNullSpace */ 59049566063dSJacob Faibussowitsch PetscCall(MatNullSpacePropagateAny_Private(pcbddc->local_mat, pcis->is_I_local, pcis->pA_II)); 590592cccca0SStefano Zampini } 59069566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pcis->pA_II, &nnsp)); 59079566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_D, &pc_temp)); 59080cd8b6e2SStefano Zampini PetscCall(PetscObjectHasFunction((PetscObject)pc_temp, "PCSetCoordinates_C", &f)); 590992cccca0SStefano Zampini if (f && pcbddc->mat_graph->cloc && !nnsp) { 5910cd18cfedSStefano Zampini PetscReal *coords = pcbddc->mat_graph->coords, *scoords; 5911cd18cfedSStefano Zampini const PetscInt *idxs; 5912cd18cfedSStefano Zampini PetscInt cdim = pcbddc->mat_graph->cdim, nl, i, d; 5913cd18cfedSStefano Zampini 59149566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcis->is_I_local, &nl)); 59159566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_I_local, &idxs)); 59169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl * cdim, &scoords)); 5917cd18cfedSStefano Zampini for (i = 0; i < nl; i++) { 5918ad540459SPierre Jolivet for (d = 0; d < cdim; d++) scoords[i * cdim + d] = coords[idxs[i] * cdim + d]; 5919cd18cfedSStefano Zampini } 59209566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_I_local, &idxs)); 59219566063dSJacob Faibussowitsch PetscCall(PCSetCoordinates(pc_temp, cdim, nl, scoords)); 59229566063dSJacob Faibussowitsch PetscCall(PetscFree(scoords)); 5923cd18cfedSStefano Zampini } 5924b334f244SStefano Zampini if (sub_schurs && sub_schurs->reuse_solver) { 5925df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 5926d62866d3SStefano Zampini 59279566063dSJacob Faibussowitsch PetscCall(KSPSetPC(pcbddc->ksp_D, reuse_solver->interior_solver)); 5928d5574798SStefano Zampini } 592992cccca0SStefano Zampini 5930304d26faSStefano Zampini /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */ 5931304d26faSStefano Zampini if (!n_D) { 59329566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_D, &pc_temp)); 59339566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCNONE)); 5934304d26faSStefano Zampini } 59359566063dSJacob Faibussowitsch PetscCall(KSPSetUp(pcbddc->ksp_D)); 5936304d26faSStefano Zampini /* set ksp_D into pcis data */ 59379566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->ksp_D)); 59389566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&pcis->ksp_D)); 5939304d26faSStefano Zampini pcis->ksp_D = pcbddc->ksp_D; 5940684f6988SStefano Zampini } 5941304d26faSStefano Zampini 5942304d26faSStefano Zampini /* NEUMANN PROBLEM */ 59430a545947SLisandro Dalcin A_RR = NULL; 5944684f6988SStefano Zampini if (neumann) { 5945d62866d3SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 594604708bb6SStefano Zampini PetscInt ibs, mbs; 5947b94d7dedSBarry Smith PetscBool issbaij, reuse_neumann_solver, isset, issym; 594804708bb6SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 59490aa714b2SStefano Zampini 59500aa714b2SStefano Zampini reuse_neumann_solver = PETSC_FALSE; 59510aa714b2SStefano Zampini if (sub_schurs && sub_schurs->reuse_solver) { 59520aa714b2SStefano Zampini IS iP; 59530aa714b2SStefano Zampini 59540aa714b2SStefano Zampini reuse_neumann_solver = PETSC_TRUE; 59559566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)sub_schurs->A, "__KSPFETIDP_iP", (PetscObject *)&iP)); 59560aa714b2SStefano Zampini if (iP) reuse_neumann_solver = PETSC_FALSE; 59570aa714b2SStefano Zampini } 5958f4ddd8eeSStefano Zampini /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */ 59599566063dSJacob Faibussowitsch PetscCall(ISGetSize(pcbddc->is_R_local, &n_R)); 5960f4ddd8eeSStefano Zampini if (pcbddc->ksp_R) { /* already created ksp */ 5961f4ddd8eeSStefano Zampini PetscInt nn_R; 59629566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(pcbddc->ksp_R, NULL, &A_RR)); 59639566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A_RR)); 59649566063dSJacob Faibussowitsch PetscCall(MatGetSize(A_RR, &nn_R, NULL)); 5965f4ddd8eeSStefano Zampini if (nn_R != n_R) { /* old ksp is not reusable, so reset it */ 59669566063dSJacob Faibussowitsch PetscCall(KSPReset(pcbddc->ksp_R)); 59679566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 5968f4ddd8eeSStefano Zampini reuse = MAT_INITIAL_MATRIX; 5969f4ddd8eeSStefano Zampini } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */ 5970727cdba6SStefano Zampini if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */ 59719566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 5972f4ddd8eeSStefano Zampini reuse = MAT_INITIAL_MATRIX; 5973f4ddd8eeSStefano Zampini } else { /* safe to reuse the matrix */ 5974f4ddd8eeSStefano Zampini reuse = MAT_REUSE_MATRIX; 5975f4ddd8eeSStefano Zampini } 5976f4ddd8eeSStefano Zampini } 5977f4ddd8eeSStefano Zampini /* last check */ 5978d1e9a80fSBarry Smith if (pc->flag == DIFFERENT_NONZERO_PATTERN) { 59799566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 5980f4ddd8eeSStefano Zampini reuse = MAT_INITIAL_MATRIX; 5981f4ddd8eeSStefano Zampini } 5982f4ddd8eeSStefano Zampini } else { /* first time, so we need to create the matrix */ 5983f4ddd8eeSStefano Zampini reuse = MAT_INITIAL_MATRIX; 5984f4ddd8eeSStefano Zampini } 5985365a3a41SStefano Zampini /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection 5986365a3a41SStefano Zampini TODO: Get Rid of these conversions */ 59879566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(pcbddc->local_mat, &mbs)); 59889566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(pcbddc->is_R_local, &ibs)); 59899566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pcbddc->local_mat, MATSEQSBAIJ, &issbaij)); 599004708bb6SStefano Zampini if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */ 599104708bb6SStefano Zampini if (matis->A == pcbddc->local_mat) { 59929566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 59939566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &pcbddc->local_mat)); 5994af732b37SStefano Zampini } else { 59959566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->local_mat, MATSEQAIJ, MAT_INPLACE_MATRIX, &pcbddc->local_mat)); 59966816873aSStefano Zampini } 59974cf0e950SBarry Smith } else if (issbaij) { /* need to convert to BAIJ to get off-diagonal blocks */ 599804708bb6SStefano Zampini if (matis->A == pcbddc->local_mat) { 59999566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 60009566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, mbs > 1 ? MATSEQBAIJ : MATSEQAIJ, MAT_INITIAL_MATRIX, &pcbddc->local_mat)); 600104708bb6SStefano Zampini } else { 60029566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->local_mat, mbs > 1 ? MATSEQBAIJ : MATSEQAIJ, MAT_INPLACE_MATRIX, &pcbddc->local_mat)); 600304708bb6SStefano Zampini } 600404708bb6SStefano Zampini } 6005a00504b5SStefano Zampini /* extract A_RR */ 60060aa714b2SStefano Zampini if (reuse_neumann_solver) { 6007a00504b5SStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 6008a00504b5SStefano Zampini 6009a00504b5SStefano Zampini if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */ 60109566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 6011a00504b5SStefano Zampini if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */ 60129566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignProject(pc, pcbddc->is_R_local, pcbddc->is_R_local, &A_RR)); 601316e386b8SStefano Zampini } else { 60149566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcbddc->is_R_local, pcbddc->is_R_local, MAT_INITIAL_MATRIX, &A_RR)); 6015a00504b5SStefano Zampini } 6016a00504b5SStefano Zampini } else { 60179566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 60189566063dSJacob Faibussowitsch PetscCall(PCGetOperators(reuse_solver->correction_solver, &A_RR, NULL)); 60199566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A_RR)); 6020a00504b5SStefano Zampini } 6021a00504b5SStefano Zampini } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */ 60229566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcbddc->is_R_local, pcbddc->is_R_local, reuse, &A_RR)); 602316e386b8SStefano Zampini } 6024b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(pcbddc->local_mat, &isset, &issym)); 6025b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(A_RR, MAT_SYMMETRIC, issym)); 602692cccca0SStefano Zampini opts = PETSC_FALSE; 6027f4ddd8eeSStefano Zampini if (!pcbddc->ksp_R) { /* create object if not present */ 602892cccca0SStefano Zampini opts = PETSC_TRUE; 60299566063dSJacob Faibussowitsch PetscCall(KSPCreate(PETSC_COMM_SELF, &pcbddc->ksp_R)); 60303821be0aSBarry Smith PetscCall(KSPSetNestLevel(pcbddc->ksp_R, pc->kspnestlevel)); 60319566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R, (PetscObject)pc, 1)); 6032304d26faSStefano Zampini /* default */ 60339566063dSJacob Faibussowitsch PetscCall(KSPSetType(pcbddc->ksp_R, KSPPREONLY)); 60349566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(pcbddc->ksp_R, neu_prefix)); 60359566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_R, &pc_temp)); 60369566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A_RR, MATSEQSBAIJ, &issbaij)); 60379577ea80SStefano Zampini if (issbaij) { 60389566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCCHOLESKY)); 60399577ea80SStefano Zampini } else { 60409566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCLU)); 60419577ea80SStefano Zampini } 60429566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(pcbddc->ksp_R, pc->erroriffailure)); 604392cccca0SStefano Zampini } 60449566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(A_RR, ((PetscObject)pcbddc->ksp_R)->prefix)); 60459de2952eSStefano Zampini PetscCall(MatViewFromOptions(A_RR, NULL, "-mat_view")); 60469de2952eSStefano Zampini PetscCall(KSPSetOperators(pcbddc->ksp_R, A_RR, A_RR)); 604792cccca0SStefano Zampini if (opts) { /* Allow user's customization once */ 60489566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(pcbddc->ksp_R)); 604992cccca0SStefano Zampini } 60509566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(A_RR, &nnsp)); 60516d9e27e4SStefano Zampini if (pcbddc->NullSpace_corr[2] && !nnsp) { /* approximate solver, propagate NearNullSpace */ 60529566063dSJacob Faibussowitsch PetscCall(MatNullSpacePropagateAny_Private(pcbddc->local_mat, pcbddc->is_R_local, A_RR)); 605392cccca0SStefano Zampini } 60549566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(A_RR, &nnsp)); 60559566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_R, &pc_temp)); 60560cd8b6e2SStefano Zampini PetscCall(PetscObjectHasFunction((PetscObject)pc_temp, "PCSetCoordinates_C", &f)); 605792cccca0SStefano Zampini if (f && pcbddc->mat_graph->cloc && !nnsp) { 6058cd18cfedSStefano Zampini PetscReal *coords = pcbddc->mat_graph->coords, *scoords; 6059cd18cfedSStefano Zampini const PetscInt *idxs; 6060cd18cfedSStefano Zampini PetscInt cdim = pcbddc->mat_graph->cdim, nl, i, d; 6061cd18cfedSStefano Zampini 60629566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->is_R_local, &nl)); 60639566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->is_R_local, &idxs)); 60649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl * cdim, &scoords)); 6065cd18cfedSStefano Zampini for (i = 0; i < nl; i++) { 6066ad540459SPierre Jolivet for (d = 0; d < cdim; d++) scoords[i * cdim + d] = coords[idxs[i] * cdim + d]; 6067cd18cfedSStefano Zampini } 60689566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->is_R_local, &idxs)); 60699566063dSJacob Faibussowitsch PetscCall(PCSetCoordinates(pc_temp, cdim, nl, scoords)); 60709566063dSJacob Faibussowitsch PetscCall(PetscFree(scoords)); 6071cd18cfedSStefano Zampini } 607292cccca0SStefano Zampini 6073304d26faSStefano Zampini /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */ 6074304d26faSStefano Zampini if (!n_R) { 60759566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_R, &pc_temp)); 60769566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCNONE)); 6077304d26faSStefano Zampini } 6078df4d28bfSStefano Zampini /* Reuse solver if it is present */ 60790aa714b2SStefano Zampini if (reuse_neumann_solver) { 6080df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 6081d62866d3SStefano Zampini 60829566063dSJacob Faibussowitsch PetscCall(KSPSetPC(pcbddc->ksp_R, reuse_solver->correction_solver)); 6083d62866d3SStefano Zampini } 60849566063dSJacob Faibussowitsch PetscCall(KSPSetUp(pcbddc->ksp_R)); 6085684f6988SStefano Zampini } 6086304d26faSStefano Zampini 6087684f6988SStefano Zampini if (pcbddc->dbg_flag) { 60889566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 60899566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 60909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 6091684f6988SStefano Zampini } 60929566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_LocalSolvers[pcbddc->current_level], pc, 0, 0, 0)); 6093c7017625SStefano Zampini 6094c7017625SStefano Zampini /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */ 609548a46eb9SPierre Jolivet if (pcbddc->NullSpace_corr[0]) PetscCall(PCBDDCSetUseExactDirichlet(pc, PETSC_FALSE)); 609648a46eb9SPierre Jolivet if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) PetscCall(PCBDDCNullSpaceAssembleCorrection(pc, PETSC_TRUE, pcbddc->NullSpace_corr[1])); 609748a46eb9SPierre Jolivet if (neumann && pcbddc->NullSpace_corr[2]) PetscCall(PCBDDCNullSpaceAssembleCorrection(pc, PETSC_FALSE, pcbddc->NullSpace_corr[3])); 6098c7017625SStefano Zampini /* check Dirichlet and Neumann solvers */ 6099c7017625SStefano Zampini if (pcbddc->dbg_flag) { 6100684f6988SStefano Zampini if (dirichlet) { /* Dirichlet */ 61019566063dSJacob Faibussowitsch PetscCall(VecSetRandom(pcis->vec1_D, NULL)); 61029566063dSJacob Faibussowitsch PetscCall(MatMult(pcis->A_II, pcis->vec1_D, pcis->vec2_D)); 61039566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec2_D, pcis->vec2_D)); 61049566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D)); 61059566063dSJacob Faibussowitsch PetscCall(VecAXPY(pcis->vec1_D, m_one, pcis->vec2_D)); 61069566063dSJacob Faibussowitsch PetscCall(VecNorm(pcis->vec1_D, NORM_INFINITY, &value)); 6107f4f49eeaSPierre 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)); 61089566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 6109304d26faSStefano Zampini } 6110684f6988SStefano Zampini if (neumann) { /* Neumann */ 61119566063dSJacob Faibussowitsch PetscCall(VecSetRandom(pcbddc->vec1_R, NULL)); 61129566063dSJacob Faibussowitsch PetscCall(MatMult(A_RR, pcbddc->vec1_R, pcbddc->vec2_R)); 61139566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_R, pcbddc->vec2_R, pcbddc->vec2_R)); 61149566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec2_R)); 61159566063dSJacob Faibussowitsch PetscCall(VecAXPY(pcbddc->vec1_R, m_one, pcbddc->vec2_R)); 61169566063dSJacob Faibussowitsch PetscCall(VecNorm(pcbddc->vec1_R, NORM_INFINITY, &value)); 6117f4f49eeaSPierre 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)); 61189566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 6119304d26faSStefano Zampini } 6120684f6988SStefano Zampini } 61215cbda25cSStefano Zampini /* free Neumann problem's matrix */ 61229566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 61233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6124304d26faSStefano Zampini } 6125304d26faSStefano Zampini 6126d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose) 6127d71ae5a4SJacob Faibussowitsch { 6128f4f49eeaSPierre Jolivet PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 6129be83ff47SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 6130b334f244SStefano Zampini PetscBool reuse_solver = sub_schurs ? (sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE) : PETSC_FALSE; 6131674ae819SStefano Zampini 6132674ae819SStefano Zampini PetscFunctionBegin; 613348a46eb9SPierre Jolivet if (!reuse_solver) PetscCall(VecSet(pcbddc->vec1_R, 0.)); 613480677318SStefano Zampini if (!pcbddc->switch_static) { 613580677318SStefano Zampini if (applytranspose && pcbddc->local_auxmat1) { 61369566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->local_auxmat2, inout_B, pcbddc->vec1_C)); 61379566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(pcbddc->local_auxmat1, pcbddc->vec1_C, inout_B, inout_B)); 613820c7b377SStefano Zampini } 6139b334f244SStefano Zampini if (!reuse_solver) { 61409566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 61419566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 614220c7b377SStefano Zampini } else { 6143df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 6144be83ff47SStefano Zampini 61459566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(reuse_solver->correction_scatter_B, inout_B, reuse_solver->rhs_B, INSERT_VALUES, SCATTER_FORWARD)); 61469566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(reuse_solver->correction_scatter_B, inout_B, reuse_solver->rhs_B, INSERT_VALUES, SCATTER_FORWARD)); 614720c7b377SStefano Zampini } 6148be83ff47SStefano Zampini } else { 61499566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 61509566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 61519566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_D, inout_D, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 61529566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_D, inout_D, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 615380677318SStefano Zampini if (applytranspose && pcbddc->local_auxmat1) { 61549566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->local_auxmat2, pcbddc->vec1_R, pcbddc->vec1_C)); 61559566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(pcbddc->local_auxmat1, pcbddc->vec1_C, inout_B, inout_B)); 61569566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 61579566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 6158674ae819SStefano Zampini } 6159674ae819SStefano Zampini } 61609566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][1], pc, 0, 0, 0)); 6161b334f244SStefano Zampini if (!reuse_solver || pcbddc->switch_static) { 616280677318SStefano Zampini if (applytranspose) { 61639566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec1_R)); 616480677318SStefano Zampini } else { 61659566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec1_R)); 616680677318SStefano Zampini } 61679566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec1_R)); 6168be83ff47SStefano Zampini } else { 6169df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 6170be83ff47SStefano Zampini 6171be83ff47SStefano Zampini if (applytranspose) { 61729566063dSJacob Faibussowitsch PetscCall(MatFactorSolveSchurComplementTranspose(reuse_solver->F, reuse_solver->rhs_B, reuse_solver->sol_B)); 6173be83ff47SStefano Zampini } else { 61749566063dSJacob Faibussowitsch PetscCall(MatFactorSolveSchurComplement(reuse_solver->F, reuse_solver->rhs_B, reuse_solver->sol_B)); 6175be83ff47SStefano Zampini } 6176be83ff47SStefano Zampini } 61779566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][1], pc, 0, 0, 0)); 61789566063dSJacob Faibussowitsch PetscCall(VecSet(inout_B, 0.)); 617980677318SStefano Zampini if (!pcbddc->switch_static) { 6180b334f244SStefano Zampini if (!reuse_solver) { 61819566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 61829566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 6183be83ff47SStefano Zampini } else { 6184df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 6185be83ff47SStefano Zampini 61869566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(reuse_solver->correction_scatter_B, reuse_solver->sol_B, inout_B, INSERT_VALUES, SCATTER_REVERSE)); 61879566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(reuse_solver->correction_scatter_B, reuse_solver->sol_B, inout_B, INSERT_VALUES, SCATTER_REVERSE)); 6188be83ff47SStefano Zampini } 618980677318SStefano Zampini if (!applytranspose && pcbddc->local_auxmat1) { 61909566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->local_auxmat1, inout_B, pcbddc->vec1_C)); 61919566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pcbddc->local_auxmat2, pcbddc->vec1_C, inout_B, inout_B)); 619280677318SStefano Zampini } 619380677318SStefano Zampini } else { 61949566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 61959566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 61969566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_D, pcbddc->vec1_R, inout_D, INSERT_VALUES, SCATTER_FORWARD)); 61979566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_D, pcbddc->vec1_R, inout_D, INSERT_VALUES, SCATTER_FORWARD)); 619880677318SStefano Zampini if (!applytranspose && pcbddc->local_auxmat1) { 61999566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->local_auxmat1, inout_B, pcbddc->vec1_C)); 62009566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pcbddc->local_auxmat2, pcbddc->vec1_C, pcbddc->vec1_R, pcbddc->vec1_R)); 620180677318SStefano Zampini } 62029566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 62039566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 62049566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_D, pcbddc->vec1_R, inout_D, INSERT_VALUES, SCATTER_FORWARD)); 62059566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_D, pcbddc->vec1_R, inout_D, INSERT_VALUES, SCATTER_FORWARD)); 6206674ae819SStefano Zampini } 62073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6208674ae819SStefano Zampini } 6209674ae819SStefano Zampini 6210dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */ 6211d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose) 6212d71ae5a4SJacob Faibussowitsch { 6213f4f49eeaSPierre Jolivet PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 6214f4f49eeaSPierre Jolivet PC_IS *pcis = (PC_IS *)pc->data; 6215674ae819SStefano Zampini const PetscScalar zero = 0.0; 6216674ae819SStefano Zampini 6217674ae819SStefano Zampini PetscFunctionBegin; 6218dc359a40SStefano Zampini /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */ 62194fee134fSStefano Zampini if (!pcbddc->benign_apply_coarse_only) { 6220dc359a40SStefano Zampini if (applytranspose) { 62219566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->coarse_phi_B, pcis->vec1_B, pcbddc->vec1_P)); 62229566063dSJacob Faibussowitsch if (pcbddc->switch_static) PetscCall(MatMultTransposeAdd(pcbddc->coarse_phi_D, pcis->vec1_D, pcbddc->vec1_P, pcbddc->vec1_P)); 6223dc359a40SStefano Zampini } else { 62249566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->coarse_psi_B, pcis->vec1_B, pcbddc->vec1_P)); 62259566063dSJacob Faibussowitsch if (pcbddc->switch_static) PetscCall(MatMultTransposeAdd(pcbddc->coarse_psi_D, pcis->vec1_D, pcbddc->vec1_P, pcbddc->vec1_P)); 622615aaf578SStefano Zampini } 62274fee134fSStefano Zampini } else { 62289566063dSJacob Faibussowitsch PetscCall(VecSet(pcbddc->vec1_P, zero)); 62294fee134fSStefano Zampini } 6230efc2fbd9SStefano Zampini 6231efc2fbd9SStefano Zampini /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */ 62324f1b2e48SStefano Zampini if (pcbddc->benign_n) { 6233efc2fbd9SStefano Zampini PetscScalar *array; 62344f1b2e48SStefano Zampini PetscInt j; 6235efc2fbd9SStefano Zampini 62369566063dSJacob Faibussowitsch PetscCall(VecGetArray(pcbddc->vec1_P, &array)); 62374f1b2e48SStefano Zampini for (j = 0; j < pcbddc->benign_n; j++) array[pcbddc->local_primal_size - pcbddc->benign_n + j] += pcbddc->benign_p0[j]; 62389566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pcbddc->vec1_P, &array)); 6239efc2fbd9SStefano Zampini } 6240efc2fbd9SStefano Zampini 624112edc857SStefano Zampini /* start communications from local primal nodes to rhs of coarse solver */ 62429566063dSJacob Faibussowitsch PetscCall(VecSet(pcbddc->coarse_vec, zero)); 62439566063dSJacob Faibussowitsch PetscCall(PCBDDCScatterCoarseDataBegin(pc, ADD_VALUES, SCATTER_FORWARD)); 62449566063dSJacob Faibussowitsch PetscCall(PCBDDCScatterCoarseDataEnd(pc, ADD_VALUES, SCATTER_FORWARD)); 624512edc857SStefano Zampini 62469f00e9b4SStefano Zampini /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */ 6247a1cb837bSStefano Zampini PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][2], pc, 0, 0, 0)); 624812edc857SStefano Zampini if (pcbddc->coarse_ksp) { 624951694757SStefano Zampini Mat coarse_mat; 6250964fefecSStefano Zampini Vec rhs, sol; 625151694757SStefano Zampini MatNullSpace nullsp; 625227b6a85dSStefano Zampini PetscBool isbddc = PETSC_FALSE; 6253964fefecSStefano Zampini 625427b6a85dSStefano Zampini if (pcbddc->benign_have_null) { 625527b6a85dSStefano Zampini PC coarse_pc; 625627b6a85dSStefano Zampini 62579566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &coarse_pc)); 62589566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)coarse_pc, PCBDDC, &isbddc)); 625927b6a85dSStefano Zampini /* we need to propagate to coarser levels the need for a possible benign correction */ 626027b6a85dSStefano Zampini if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) { 6261f4f49eeaSPierre Jolivet PC_BDDC *coarsepcbddc = (PC_BDDC *)coarse_pc->data; 626227b6a85dSStefano Zampini coarsepcbddc->benign_skip_correction = PETSC_FALSE; 62633bca92a6SStefano Zampini coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE; 626427b6a85dSStefano Zampini } 626527b6a85dSStefano Zampini } 62669566063dSJacob Faibussowitsch PetscCall(KSPGetRhs(pcbddc->coarse_ksp, &rhs)); 62679566063dSJacob Faibussowitsch PetscCall(KSPGetSolution(pcbddc->coarse_ksp, &sol)); 62689566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(pcbddc->coarse_ksp, &coarse_mat, NULL)); 626912edc857SStefano Zampini if (applytranspose) { 627028b400f6SJacob Faibussowitsch PetscCheck(!pcbddc->benign_apply_coarse_only, PetscObjectComm((PetscObject)pcbddc->coarse_ksp), PETSC_ERR_SUP, "Not yet implemented"); 62719566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->coarse_ksp, rhs, sol)); 62729566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->coarse_ksp, pc, sol)); 62739566063dSJacob Faibussowitsch PetscCall(MatGetTransposeNullSpace(coarse_mat, &nullsp)); 62741baa6e33SBarry Smith if (nullsp) PetscCall(MatNullSpaceRemove(nullsp, sol)); 62752701bc32SStefano Zampini } else { 62769566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(coarse_mat, &nullsp)); 62771f4df5f7SStefano Zampini if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */ 62782701bc32SStefano Zampini PC coarse_pc; 62792701bc32SStefano Zampini 62801baa6e33SBarry Smith if (nullsp) PetscCall(MatNullSpaceRemove(nullsp, rhs)); 62819566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &coarse_pc)); 62829566063dSJacob Faibussowitsch PetscCall(PCPreSolve(coarse_pc, pcbddc->coarse_ksp)); 62839566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignRemoveInterior(coarse_pc, rhs, sol)); 62849566063dSJacob Faibussowitsch PetscCall(PCPostSolve(coarse_pc, pcbddc->coarse_ksp)); 628512edc857SStefano Zampini } else { 62869566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->coarse_ksp, rhs, sol)); 62879566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->coarse_ksp, pc, sol)); 62881baa6e33SBarry Smith if (nullsp) PetscCall(MatNullSpaceRemove(nullsp, sol)); 628912edc857SStefano Zampini } 62902701bc32SStefano Zampini } 62911d82a3b6SStefano Zampini /* we don't need the benign correction at coarser levels anymore */ 629227b6a85dSStefano Zampini if (pcbddc->benign_have_null && isbddc) { 629327b6a85dSStefano Zampini PC coarse_pc; 629427b6a85dSStefano Zampini PC_BDDC *coarsepcbddc; 629527b6a85dSStefano Zampini 62969566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &coarse_pc)); 6297f4f49eeaSPierre Jolivet coarsepcbddc = (PC_BDDC *)coarse_pc->data; 629827b6a85dSStefano Zampini coarsepcbddc->benign_skip_correction = PETSC_TRUE; 62993bca92a6SStefano Zampini coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE; 630027b6a85dSStefano Zampini } 630112edc857SStefano Zampini } 6302a1cb837bSStefano Zampini PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][2], pc, 0, 0, 0)); 6303674ae819SStefano Zampini 6304674ae819SStefano Zampini /* Local solution on R nodes */ 6305a1cb837bSStefano Zampini if (!pcbddc->benign_apply_coarse_only) PetscCall(PCBDDCSolveSubstructureCorrection(pc, pcis->vec1_B, pcis->vec1_D, applytranspose)); 63069f00e9b4SStefano Zampini /* communications from coarse sol to local primal nodes */ 63079566063dSJacob Faibussowitsch PetscCall(PCBDDCScatterCoarseDataBegin(pc, INSERT_VALUES, SCATTER_REVERSE)); 63089566063dSJacob Faibussowitsch PetscCall(PCBDDCScatterCoarseDataEnd(pc, INSERT_VALUES, SCATTER_REVERSE)); 6309674ae819SStefano Zampini 63104fee134fSStefano Zampini /* Sum contributions from the two levels */ 63114fee134fSStefano Zampini if (!pcbddc->benign_apply_coarse_only) { 6312dc359a40SStefano Zampini if (applytranspose) { 63139566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pcbddc->coarse_psi_B, pcbddc->vec1_P, pcis->vec1_B, pcis->vec1_B)); 63149566063dSJacob Faibussowitsch if (pcbddc->switch_static) PetscCall(MatMultAdd(pcbddc->coarse_psi_D, pcbddc->vec1_P, pcis->vec1_D, pcis->vec1_D)); 6315dc359a40SStefano Zampini } else { 63169566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pcbddc->coarse_phi_B, pcbddc->vec1_P, pcis->vec1_B, pcis->vec1_B)); 63179566063dSJacob Faibussowitsch if (pcbddc->switch_static) PetscCall(MatMultAdd(pcbddc->coarse_phi_D, pcbddc->vec1_P, pcis->vec1_D, pcis->vec1_D)); 6318dc359a40SStefano Zampini } 6319efc2fbd9SStefano Zampini /* store p0 */ 63204f1b2e48SStefano Zampini if (pcbddc->benign_n) { 6321efc2fbd9SStefano Zampini PetscScalar *array; 63224f1b2e48SStefano Zampini PetscInt j; 6323efc2fbd9SStefano Zampini 63249566063dSJacob Faibussowitsch PetscCall(VecGetArray(pcbddc->vec1_P, &array)); 63254f1b2e48SStefano Zampini for (j = 0; j < pcbddc->benign_n; j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size - pcbddc->benign_n + j]; 63269566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pcbddc->vec1_P, &array)); 6327efc2fbd9SStefano Zampini } 63284fee134fSStefano Zampini } else { /* expand the coarse solution */ 63294fee134fSStefano Zampini if (applytranspose) { 63309566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->coarse_psi_B, pcbddc->vec1_P, pcis->vec1_B)); 63314fee134fSStefano Zampini } else { 63329566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->coarse_phi_B, pcbddc->vec1_P, pcis->vec1_B)); 63334fee134fSStefano Zampini } 63344fee134fSStefano Zampini } 63353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6336674ae819SStefano Zampini } 6337674ae819SStefano Zampini 6338d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc, InsertMode imode, ScatterMode smode) 6339d71ae5a4SJacob Faibussowitsch { 6340f4f49eeaSPierre Jolivet PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 634112edc857SStefano Zampini Vec from, to; 63427ebab0bbSStefano Zampini const PetscScalar *array; 6343674ae819SStefano Zampini 6344674ae819SStefano Zampini PetscFunctionBegin; 634512edc857SStefano Zampini if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */ 634612edc857SStefano Zampini from = pcbddc->coarse_vec; 634712edc857SStefano Zampini to = pcbddc->vec1_P; 634812edc857SStefano Zampini if (pcbddc->coarse_ksp) { /* get array from coarse processes */ 634912edc857SStefano Zampini Vec tvec; 635058da7f69SStefano Zampini 63519566063dSJacob Faibussowitsch PetscCall(KSPGetRhs(pcbddc->coarse_ksp, &tvec)); 63529566063dSJacob Faibussowitsch PetscCall(VecResetArray(tvec)); 63539566063dSJacob Faibussowitsch PetscCall(KSPGetSolution(pcbddc->coarse_ksp, &tvec)); 63549566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(tvec, &array)); 63559566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(from, array)); 63569566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(tvec, &array)); 635712edc857SStefano Zampini } 6358dd8e379bSPierre Jolivet } else { /* from local to global -> put data in coarse right-hand side */ 635912edc857SStefano Zampini from = pcbddc->vec1_P; 636012edc857SStefano Zampini to = pcbddc->coarse_vec; 636112edc857SStefano Zampini } 63629566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob, from, to, imode, smode)); 63633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6364674ae819SStefano Zampini } 6365674ae819SStefano Zampini 6366d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode) 6367d71ae5a4SJacob Faibussowitsch { 6368f4f49eeaSPierre Jolivet PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 636912edc857SStefano Zampini Vec from, to; 63707ebab0bbSStefano Zampini const PetscScalar *array; 6371674ae819SStefano Zampini 6372674ae819SStefano Zampini PetscFunctionBegin; 637312edc857SStefano Zampini if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */ 637412edc857SStefano Zampini from = pcbddc->coarse_vec; 637512edc857SStefano Zampini to = pcbddc->vec1_P; 6376dd8e379bSPierre Jolivet } else { /* from local to global -> put data in coarse right-hand side */ 637712edc857SStefano Zampini from = pcbddc->vec1_P; 637812edc857SStefano Zampini to = pcbddc->coarse_vec; 637912edc857SStefano Zampini } 63809566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob, from, to, imode, smode)); 638112edc857SStefano Zampini if (smode == SCATTER_FORWARD) { 638212edc857SStefano Zampini if (pcbddc->coarse_ksp) { /* get array from coarse processes */ 638312edc857SStefano Zampini Vec tvec; 638458da7f69SStefano Zampini 63859566063dSJacob Faibussowitsch PetscCall(KSPGetRhs(pcbddc->coarse_ksp, &tvec)); 63869566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(to, &array)); 63879566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(tvec, array)); 63889566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(to, &array)); 638958da7f69SStefano Zampini } 639058da7f69SStefano Zampini } else { 639158da7f69SStefano Zampini if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */ 63929566063dSJacob Faibussowitsch PetscCall(VecResetArray(from)); 639312edc857SStefano Zampini } 639412edc857SStefano Zampini } 63953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6396674ae819SStefano Zampini } 6397674ae819SStefano Zampini 6398d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCConstraintsSetUp(PC pc) 6399d71ae5a4SJacob Faibussowitsch { 6400f4f49eeaSPierre Jolivet PC_IS *pcis = (PC_IS *)pc->data; 6401674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 6402674ae819SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 6403984c4197SStefano Zampini /* one and zero */ 6404984c4197SStefano Zampini PetscScalar one = 1.0, zero = 0.0; 6405984c4197SStefano Zampini /* space to store constraints and their local indices */ 64069162d606SStefano Zampini PetscScalar *constraints_data; 64079162d606SStefano Zampini PetscInt *constraints_idxs, *constraints_idxs_B; 64089162d606SStefano Zampini PetscInt *constraints_idxs_ptr, *constraints_data_ptr; 64099162d606SStefano Zampini PetscInt *constraints_n; 6410984c4197SStefano Zampini /* iterators */ 6411b3d85658SStefano Zampini PetscInt i, j, k, total_counts, total_counts_cc, cum; 6412984c4197SStefano Zampini /* BLAS integers */ 6413e310c8b4SStefano Zampini PetscBLASInt lwork, lierr; 6414e310c8b4SStefano Zampini PetscBLASInt Blas_N, Blas_M, Blas_K, Blas_one = 1; 6415c4303822SStefano Zampini PetscBLASInt Blas_LDA, Blas_LDB, Blas_LDC; 6416727cdba6SStefano Zampini /* reuse */ 64170e6343abSStefano Zampini PetscInt olocal_primal_size, olocal_primal_size_cc; 64180e6343abSStefano Zampini PetscInt *olocal_primal_ref_node, *olocal_primal_ref_mult; 6419984c4197SStefano Zampini /* change of basis */ 6420b3d85658SStefano Zampini PetscBool qr_needed; 64219162d606SStefano Zampini PetscBT change_basis, qr_needed_idx; 6422984c4197SStefano Zampini /* auxiliary stuff */ 642364efe560SStefano Zampini PetscInt *nnz, *is_indices; 64248a0068c3SStefano Zampini PetscInt ncc; 6425984c4197SStefano Zampini /* some quantities */ 642645a1bb75SStefano Zampini PetscInt n_vertices, total_primal_vertices, valid_constraints; 6427a58a30b4SStefano Zampini PetscInt size_of_constraint, max_size_of_constraint = 0, max_constraints, temp_constraints; 642857715f18SStefano Zampini PetscReal tol; /* tolerance for retaining eigenmodes */ 6429984c4197SStefano Zampini 6430674ae819SStefano Zampini PetscFunctionBegin; 643157715f18SStefano Zampini tol = PetscSqrtReal(PETSC_SMALL); 64328e61c736SStefano Zampini /* Destroy Mat objects computed previously */ 64339566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->ChangeOfBasisMatrix)); 64349566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->ConstraintMatrix)); 64359566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->switch_static_change)); 6436088faed8SStefano Zampini /* save info on constraints from previous setup (if any) */ 6437088faed8SStefano Zampini olocal_primal_size = pcbddc->local_primal_size; 64380e6343abSStefano Zampini olocal_primal_size_cc = pcbddc->local_primal_size_cc; 64399566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(olocal_primal_size_cc, &olocal_primal_ref_node, olocal_primal_size_cc, &olocal_primal_ref_mult)); 64409566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(olocal_primal_ref_node, pcbddc->local_primal_ref_node, olocal_primal_size_cc)); 64419566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(olocal_primal_ref_mult, pcbddc->local_primal_ref_mult, olocal_primal_size_cc)); 64429566063dSJacob Faibussowitsch PetscCall(PetscFree2(pcbddc->local_primal_ref_node, pcbddc->local_primal_ref_mult)); 64439566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->primal_indices_local_idxs)); 6444cf5a6209SStefano Zampini 6445cf5a6209SStefano Zampini if (!pcbddc->adaptive_selection) { 64469162d606SStefano Zampini IS ISForVertices, *ISForFaces, *ISForEdges; 6447cf5a6209SStefano Zampini MatNullSpace nearnullsp; 6448cf5a6209SStefano Zampini const Vec *nearnullvecs; 6449cf5a6209SStefano Zampini Vec *localnearnullsp; 6450cf5a6209SStefano Zampini PetscScalar *array; 645132fe681dSStefano Zampini PetscInt n_ISForFaces, n_ISForEdges, nnsp_size, o_nf, o_ne; 6452cf5a6209SStefano Zampini PetscBool nnsp_has_cnst; 6453674ae819SStefano Zampini /* LAPACK working arrays for SVD or POD */ 6454b3d85658SStefano Zampini PetscBool skip_lapack, boolforchange; 6455674ae819SStefano Zampini PetscScalar *work; 6456674ae819SStefano Zampini PetscReal *singular_vals; 6457674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX) 6458674ae819SStefano Zampini PetscReal *rwork; 6459674ae819SStefano Zampini #endif 646055080a34SStefano Zampini PetscScalar *temp_basis = NULL, *correlation_mat = NULL; 6461964fefecSStefano Zampini PetscBLASInt dummy_int = 1; 6462964fefecSStefano Zampini PetscScalar dummy_scalar = 1.; 646355080a34SStefano Zampini PetscBool use_pod = PETSC_FALSE; 6464674ae819SStefano Zampini 646555080a34SStefano Zampini /* MKL SVD with same input gives different results on different processes! */ 6466b88df2e7SBarry Smith #if defined(PETSC_MISSING_LAPACK_GESVD) || defined(PETSC_HAVE_MKL_LIBS) 646755080a34SStefano Zampini use_pod = PETSC_TRUE; 646855080a34SStefano Zampini #endif 6469674ae819SStefano Zampini /* Get index sets for faces, edges and vertices from graph */ 64709566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, &n_ISForFaces, &ISForFaces, &n_ISForEdges, &ISForEdges, &ISForVertices)); 647132fe681dSStefano Zampini o_nf = n_ISForFaces; 647232fe681dSStefano Zampini o_ne = n_ISForEdges; 647332fe681dSStefano Zampini n_vertices = 0; 647432fe681dSStefano Zampini if (ISForVertices) PetscCall(ISGetSize(ISForVertices, &n_vertices)); 6475e4d548c7SStefano Zampini /* print some info */ 64765c643e28SStefano Zampini if (pcbddc->dbg_flag && (!pcbddc->sub_schurs || pcbddc->sub_schurs_rebuild)) { 647732fe681dSStefano Zampini if (!pcbddc->dbg_viewer) pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc)); 64789566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphASCIIView(pcbddc->mat_graph, pcbddc->dbg_flag, pcbddc->dbg_viewer)); 64799566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 64809566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "--------------------------------------------------------------\n")); 648132fe681dSStefano Zampini PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate vertices (%d)\n", PetscGlobalRank, n_vertices, pcbddc->use_vertices)); 648263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate edges (%d)\n", PetscGlobalRank, n_ISForEdges, pcbddc->use_edges)); 648363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate faces (%d)\n", PetscGlobalRank, n_ISForFaces, pcbddc->use_faces)); 64849566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 64859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer)); 6486e4d548c7SStefano Zampini } 6487e4d548c7SStefano Zampini 648832fe681dSStefano Zampini if (!pcbddc->use_vertices) n_vertices = 0; 648932fe681dSStefano Zampini if (!pcbddc->use_edges) n_ISForEdges = 0; 649032fe681dSStefano Zampini if (!pcbddc->use_faces) n_ISForFaces = 0; 649170022509SStefano Zampini 6492674ae819SStefano Zampini /* check if near null space is attached to global mat */ 64936d9e27e4SStefano Zampini if (pcbddc->use_nnsp) { 64949566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pc->pmat, &nearnullsp)); 64956d9e27e4SStefano Zampini } else nearnullsp = NULL; 64966d9e27e4SStefano Zampini 6497674ae819SStefano Zampini if (nearnullsp) { 64989566063dSJacob Faibussowitsch PetscCall(MatNullSpaceGetVecs(nearnullsp, &nnsp_has_cnst, &nnsp_size, &nearnullvecs)); 6499f4ddd8eeSStefano Zampini /* remove any stored info */ 65009566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&pcbddc->onearnullspace)); 65019566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->onearnullvecs_state)); 6502f4ddd8eeSStefano Zampini /* store information for BDDC solver reuse */ 65039566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)nearnullsp)); 6504f4ddd8eeSStefano Zampini pcbddc->onearnullspace = nearnullsp; 65059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnsp_size, &pcbddc->onearnullvecs_state)); 650648a46eb9SPierre Jolivet for (i = 0; i < nnsp_size; i++) PetscCall(PetscObjectStateGet((PetscObject)nearnullvecs[i], &pcbddc->onearnullvecs_state[i])); 6507984c4197SStefano Zampini } else { /* if near null space is not provided BDDC uses constants by default */ 6508984c4197SStefano Zampini nnsp_size = 0; 6509674ae819SStefano Zampini nnsp_has_cnst = PETSC_TRUE; 6510674ae819SStefano Zampini } 6511984c4197SStefano Zampini /* get max number of constraints on a single cc */ 6512984c4197SStefano Zampini max_constraints = nnsp_size; 6513984c4197SStefano Zampini if (nnsp_has_cnst) max_constraints++; 6514984c4197SStefano Zampini 6515674ae819SStefano Zampini /* 6516674ae819SStefano Zampini Evaluate maximum storage size needed by the procedure 65179162d606SStefano Zampini - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]" 65189162d606SStefano Zampini - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]" 65199162d606SStefano Zampini There can be multiple constraints per connected component 6520674ae819SStefano Zampini */ 65219162d606SStefano Zampini ncc = n_vertices + n_ISForFaces + n_ISForEdges; 65229566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(ncc + 1, &constraints_idxs_ptr, ncc + 1, &constraints_data_ptr, ncc, &constraints_n)); 65239162d606SStefano Zampini 65249162d606SStefano Zampini total_counts = n_ISForFaces + n_ISForEdges; 65259162d606SStefano Zampini total_counts *= max_constraints; 6526674ae819SStefano Zampini total_counts += n_vertices; 65279566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(total_counts, &change_basis)); 65289162d606SStefano Zampini 6529674ae819SStefano Zampini total_counts = 0; 6530674ae819SStefano Zampini max_size_of_constraint = 0; 6531674ae819SStefano Zampini for (i = 0; i < n_ISForEdges + n_ISForFaces; i++) { 65329162d606SStefano Zampini IS used_is; 6533674ae819SStefano Zampini if (i < n_ISForEdges) { 65349162d606SStefano Zampini used_is = ISForEdges[i]; 6535674ae819SStefano Zampini } else { 65369162d606SStefano Zampini used_is = ISForFaces[i - n_ISForEdges]; 6537674ae819SStefano Zampini } 65389566063dSJacob Faibussowitsch PetscCall(ISGetSize(used_is, &j)); 6539674ae819SStefano Zampini total_counts += j; 6540674ae819SStefano Zampini max_size_of_constraint = PetscMax(j, max_size_of_constraint); 6541674ae819SStefano Zampini } 65429566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(total_counts * max_constraints + n_vertices, &constraints_data, total_counts + n_vertices, &constraints_idxs, total_counts + n_vertices, &constraints_idxs_B)); 65439162d606SStefano Zampini 6544984c4197SStefano Zampini /* get local part of global near null space vectors */ 65459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnsp_size, &localnearnullsp)); 6546984c4197SStefano Zampini for (k = 0; k < nnsp_size; k++) { 65479566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_N, &localnearnullsp[k])); 65489566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, nearnullvecs[k], localnearnullsp[k], INSERT_VALUES, SCATTER_FORWARD)); 65499566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, nearnullvecs[k], localnearnullsp[k], INSERT_VALUES, SCATTER_FORWARD)); 6550984c4197SStefano Zampini } 6551674ae819SStefano Zampini 6552242a89d7SStefano Zampini /* whether or not to skip lapack calls */ 6553242a89d7SStefano Zampini skip_lapack = PETSC_TRUE; 6554a773dcb8SStefano Zampini if (n_ISForFaces + n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE; 6555242a89d7SStefano Zampini 6556984c4197SStefano Zampini /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */ 6557a773dcb8SStefano Zampini if (!skip_lapack) { 6558674ae819SStefano Zampini PetscScalar temp_work; 6559911cabfeSStefano Zampini 656055080a34SStefano Zampini if (use_pod) { 6561984c4197SStefano Zampini /* Proper Orthogonal Decomposition (POD) using the snapshot method */ 65629566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_constraints * max_constraints, &correlation_mat)); 65639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_constraints, &singular_vals)); 65649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_size_of_constraint * max_constraints, &temp_basis)); 6565674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX) 65669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(3 * max_constraints, &rwork)); 6567674ae819SStefano Zampini #endif 6568674ae819SStefano Zampini /* now we evaluate the optimal workspace using query with lwork=-1 */ 65699566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_constraints, &Blas_N)); 65709566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_constraints, &Blas_LDA)); 6571674ae819SStefano Zampini lwork = -1; 65729566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6573674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX) 6574792fecdfSBarry Smith PetscCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &Blas_N, correlation_mat, &Blas_LDA, singular_vals, &temp_work, &lwork, &lierr)); 6575674ae819SStefano Zampini #else 6576792fecdfSBarry Smith PetscCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &Blas_N, correlation_mat, &Blas_LDA, singular_vals, &temp_work, &lwork, rwork, &lierr)); 6577674ae819SStefano Zampini #endif 65789566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 6579835f2295SStefano Zampini PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in query to SYEV Lapack routine %" PetscBLASInt_FMT, lierr); 658055080a34SStefano Zampini } else { 658155080a34SStefano Zampini #if !defined(PETSC_MISSING_LAPACK_GESVD) 6582674ae819SStefano Zampini /* SVD */ 6583674ae819SStefano Zampini PetscInt max_n, min_n; 6584674ae819SStefano Zampini max_n = max_size_of_constraint; 6585984c4197SStefano Zampini min_n = max_constraints; 6586984c4197SStefano Zampini if (max_size_of_constraint < max_constraints) { 6587674ae819SStefano Zampini min_n = max_size_of_constraint; 6588984c4197SStefano Zampini max_n = max_constraints; 6589674ae819SStefano Zampini } 65909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(min_n, &singular_vals)); 6591674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX) 65929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(5 * min_n, &rwork)); 6593674ae819SStefano Zampini #endif 6594674ae819SStefano Zampini /* now we evaluate the optimal workspace using query with lwork=-1 */ 6595674ae819SStefano Zampini lwork = -1; 65969566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_n, &Blas_M)); 65979566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(min_n, &Blas_N)); 65989566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_n, &Blas_LDA)); 65999566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6600674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX) 6601792fecdfSBarry 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)); 6602674ae819SStefano Zampini #else 6603792fecdfSBarry 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)); 6604674ae819SStefano Zampini #endif 66059566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 6606835f2295SStefano Zampini PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in query to GESVD Lapack routine %" PetscBLASInt_FMT, lierr); 660755080a34SStefano Zampini #else 660855080a34SStefano Zampini SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "This should not happen"); 6609984c4197SStefano Zampini #endif /* on missing GESVD */ 661055080a34SStefano Zampini } 6611674ae819SStefano Zampini /* Allocate optimal workspace */ 66129566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(temp_work), &lwork)); 66139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(lwork, &work)); 6614674ae819SStefano Zampini } 6615674ae819SStefano Zampini /* Now we can loop on constraining sets */ 6616674ae819SStefano Zampini total_counts = 0; 66179162d606SStefano Zampini constraints_idxs_ptr[0] = 0; 66189162d606SStefano Zampini constraints_data_ptr[0] = 0; 6619674ae819SStefano Zampini /* vertices */ 66209162d606SStefano Zampini if (n_vertices) { 66219566063dSJacob Faibussowitsch PetscCall(ISGetIndices(ISForVertices, (const PetscInt **)&is_indices)); 66229566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(constraints_idxs, is_indices, n_vertices)); 6623674ae819SStefano Zampini for (i = 0; i < n_vertices; i++) { 66249162d606SStefano Zampini constraints_n[total_counts] = 1; 66259162d606SStefano Zampini constraints_data[total_counts] = 1.0; 66269162d606SStefano Zampini constraints_idxs_ptr[total_counts + 1] = constraints_idxs_ptr[total_counts] + 1; 66279162d606SStefano Zampini constraints_data_ptr[total_counts + 1] = constraints_data_ptr[total_counts] + 1; 6628674ae819SStefano Zampini total_counts++; 6629674ae819SStefano Zampini } 66309566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(ISForVertices, (const PetscInt **)&is_indices)); 6631674ae819SStefano Zampini } 6632984c4197SStefano Zampini 6633674ae819SStefano Zampini /* edges and faces */ 66349162d606SStefano Zampini total_counts_cc = total_counts; 6635911cabfeSStefano Zampini for (ncc = 0; ncc < n_ISForEdges + n_ISForFaces; ncc++) { 66369162d606SStefano Zampini IS used_is; 66379162d606SStefano Zampini PetscBool idxs_copied = PETSC_FALSE; 66389162d606SStefano Zampini 6639911cabfeSStefano Zampini if (ncc < n_ISForEdges) { 66409162d606SStefano Zampini used_is = ISForEdges[ncc]; 6641984c4197SStefano Zampini boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */ 6642674ae819SStefano Zampini } else { 66439162d606SStefano Zampini used_is = ISForFaces[ncc - n_ISForEdges]; 6644984c4197SStefano Zampini boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */ 6645674ae819SStefano Zampini } 6646674ae819SStefano Zampini temp_constraints = 0; /* zero the number of constraints I have on this conn comp */ 66479162d606SStefano Zampini 66489566063dSJacob Faibussowitsch PetscCall(ISGetSize(used_is, &size_of_constraint)); 664932fe681dSStefano Zampini if (!size_of_constraint) continue; 66509566063dSJacob Faibussowitsch PetscCall(ISGetIndices(used_is, (const PetscInt **)&is_indices)); 6651674ae819SStefano Zampini if (nnsp_has_cnst) { 66525b08dc53SStefano Zampini PetscScalar quad_value; 66539162d606SStefano Zampini 66549566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc], is_indices, size_of_constraint)); 66559162d606SStefano Zampini idxs_copied = PETSC_TRUE; 66569162d606SStefano Zampini 6657a773dcb8SStefano Zampini if (!pcbddc->use_nnsp_true) { 6658674ae819SStefano Zampini quad_value = (PetscScalar)(1.0 / PetscSqrtReal((PetscReal)size_of_constraint)); 6659a773dcb8SStefano Zampini } else { 6660a773dcb8SStefano Zampini quad_value = 1.0; 6661a773dcb8SStefano Zampini } 6662ad540459SPierre Jolivet for (j = 0; j < size_of_constraint; j++) constraints_data[constraints_data_ptr[total_counts_cc] + j] = quad_value; 66639162d606SStefano Zampini temp_constraints++; 6664674ae819SStefano Zampini total_counts++; 6665674ae819SStefano Zampini } 6666674ae819SStefano Zampini for (k = 0; k < nnsp_size; k++) { 6667984c4197SStefano Zampini PetscReal real_value; 66689162d606SStefano Zampini PetscScalar *ptr_to_data; 66699162d606SStefano Zampini 66709566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(localnearnullsp[k], (const PetscScalar **)&array)); 66719162d606SStefano Zampini ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc] + temp_constraints * size_of_constraint]; 6672ad540459SPierre Jolivet for (j = 0; j < size_of_constraint; j++) ptr_to_data[j] = array[is_indices[j]]; 66739566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(localnearnullsp[k], (const PetscScalar **)&array)); 6674984c4197SStefano Zampini /* check if array is null on the connected component */ 66759566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 6676792fecdfSBarry Smith PetscCallBLAS("BLASasum", real_value = BLASasum_(&Blas_N, ptr_to_data, &Blas_one)); 667757715f18SStefano Zampini if (real_value > tol * size_of_constraint) { /* keep indices and values */ 6678674ae819SStefano Zampini temp_constraints++; 6679674ae819SStefano Zampini total_counts++; 66809162d606SStefano Zampini if (!idxs_copied) { 66819566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc], is_indices, size_of_constraint)); 66829162d606SStefano Zampini idxs_copied = PETSC_TRUE; 6683674ae819SStefano Zampini } 6684674ae819SStefano Zampini } 66859162d606SStefano Zampini } 66869566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(used_is, (const PetscInt **)&is_indices)); 668745a1bb75SStefano Zampini valid_constraints = temp_constraints; 6688eb97c9d2SStefano Zampini if (!pcbddc->use_nnsp_true && temp_constraints) { 6689a773dcb8SStefano Zampini if (temp_constraints == 1) { /* just normalize the constraint */ 66909162d606SStefano Zampini PetscScalar norm, *ptr_to_data; 66919162d606SStefano Zampini 66929162d606SStefano Zampini ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]]; 66939566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 6694792fecdfSBarry Smith PetscCallBLAS("BLASdot", norm = BLASdot_(&Blas_N, ptr_to_data, &Blas_one, ptr_to_data, &Blas_one)); 6695a773dcb8SStefano Zampini norm = 1.0 / PetscSqrtReal(PetscRealPart(norm)); 6696792fecdfSBarry Smith PetscCallBLAS("BLASscal", BLASscal_(&Blas_N, &norm, ptr_to_data, &Blas_one)); 6697a773dcb8SStefano Zampini } else { /* perform SVD */ 66989162d606SStefano Zampini PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]]; 6699674ae819SStefano Zampini 670055080a34SStefano Zampini if (use_pod) { 6701984c4197SStefano Zampini /* SVD: Y = U*S*V^H -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag 6702984c4197SStefano Zampini POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2) 6703984c4197SStefano Zampini -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined 6704984c4197SStefano Zampini the constraints basis will differ (by a complex factor with absolute value equal to 1) 6705984c4197SStefano Zampini from that computed using LAPACKgesvd 6706984c4197SStefano Zampini -> This is due to a different computation of eigenvectors in LAPACKheev 6707984c4197SStefano Zampini -> The quality of the POD-computed basis will be the same */ 67089566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(correlation_mat, temp_constraints * temp_constraints)); 6709674ae819SStefano Zampini /* Store upper triangular part of correlation matrix */ 67109566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 67119566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6712674ae819SStefano Zampini for (j = 0; j < temp_constraints; j++) { 671348a46eb9SPierre 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)); 6714674ae819SStefano Zampini } 6715e310c8b4SStefano Zampini /* compute eigenvalues and eigenvectors of correlation matrix */ 67169566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_N)); 67179566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_LDA)); 6718674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX) 6719792fecdfSBarry Smith PetscCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &Blas_N, correlation_mat, &Blas_LDA, singular_vals, work, &lwork, &lierr)); 6720674ae819SStefano Zampini #else 6721792fecdfSBarry Smith PetscCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &Blas_N, correlation_mat, &Blas_LDA, singular_vals, work, &lwork, rwork, &lierr)); 6722674ae819SStefano Zampini #endif 67239566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 6724835f2295SStefano Zampini PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in SYEV Lapack routine %" PetscBLASInt_FMT, lierr); 6725984c4197SStefano Zampini /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */ 6726674ae819SStefano Zampini j = 0; 672787b3baaaSStefano Zampini while (j < temp_constraints && singular_vals[j] / singular_vals[temp_constraints - 1] < tol) j++; 6728674ae819SStefano Zampini total_counts = total_counts - j; 672945a1bb75SStefano Zampini valid_constraints = temp_constraints - j; 6730e310c8b4SStefano Zampini /* scale and copy POD basis into used quadrature memory */ 67319566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_M)); 67329566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_N)); 67339566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_K)); 67349566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 67359566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_LDB)); 67369566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDC)); 6737674ae819SStefano Zampini if (j < temp_constraints) { 6738984c4197SStefano Zampini PetscInt ii; 6739984c4197SStefano Zampini for (k = j; k < temp_constraints; k++) singular_vals[k] = 1.0 / PetscSqrtReal(singular_vals[k]); 67409566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6741792fecdfSBarry 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)); 67429566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 6743984c4197SStefano Zampini for (k = 0; k < temp_constraints - j; k++) { 6744ad540459SPierre 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]; 6745674ae819SStefano Zampini } 6746674ae819SStefano Zampini } 674755080a34SStefano Zampini } else { 674855080a34SStefano Zampini #if !defined(PETSC_MISSING_LAPACK_GESVD) 67499566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_M)); 67509566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_N)); 67519566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 67529566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6753674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX) 6754792fecdfSBarry 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)); 6755674ae819SStefano Zampini #else 6756792fecdfSBarry 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)); 6757674ae819SStefano Zampini #endif 6758835f2295SStefano Zampini PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in GESVD Lapack routine %" PetscBLASInt_FMT, lierr); 67599566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 6760984c4197SStefano Zampini /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */ 6761e310c8b4SStefano Zampini k = temp_constraints; 6762e310c8b4SStefano Zampini if (k > size_of_constraint) k = size_of_constraint; 6763674ae819SStefano Zampini j = 0; 676487b3baaaSStefano Zampini while (j < k && singular_vals[k - j - 1] / singular_vals[0] < tol) j++; 676545a1bb75SStefano Zampini valid_constraints = k - j; 6766911cabfeSStefano Zampini total_counts = total_counts - temp_constraints + valid_constraints; 676755080a34SStefano Zampini #else 676855080a34SStefano Zampini SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "This should not happen"); 6769984c4197SStefano Zampini #endif /* on missing GESVD */ 6770674ae819SStefano Zampini } 6771a773dcb8SStefano Zampini } 677255080a34SStefano Zampini } 67739162d606SStefano Zampini /* update pointers information */ 67749162d606SStefano Zampini if (valid_constraints) { 67759162d606SStefano Zampini constraints_n[total_counts_cc] = valid_constraints; 67769162d606SStefano Zampini constraints_idxs_ptr[total_counts_cc + 1] = constraints_idxs_ptr[total_counts_cc] + size_of_constraint; 67779162d606SStefano Zampini constraints_data_ptr[total_counts_cc + 1] = constraints_data_ptr[total_counts_cc] + size_of_constraint * valid_constraints; 67789162d606SStefano Zampini /* set change_of_basis flag */ 67793ba16761SJacob Faibussowitsch if (boolforchange) PetscCall(PetscBTSet(change_basis, total_counts_cc)); 6780b3d85658SStefano Zampini total_counts_cc++; 678145a1bb75SStefano Zampini } 678245a1bb75SStefano Zampini } 6783984c4197SStefano Zampini /* free workspace */ 67848f1c130eSStefano Zampini if (!skip_lapack) { 67859566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 6786984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX) 67879566063dSJacob Faibussowitsch PetscCall(PetscFree(rwork)); 6788984c4197SStefano Zampini #endif 67899566063dSJacob Faibussowitsch PetscCall(PetscFree(singular_vals)); 67909566063dSJacob Faibussowitsch PetscCall(PetscFree(correlation_mat)); 67919566063dSJacob Faibussowitsch PetscCall(PetscFree(temp_basis)); 6792984c4197SStefano Zampini } 679348a46eb9SPierre Jolivet for (k = 0; k < nnsp_size; k++) PetscCall(VecDestroy(&localnearnullsp[k])); 67949566063dSJacob Faibussowitsch PetscCall(PetscFree(localnearnullsp)); 6795cf5a6209SStefano Zampini /* free index sets of faces, edges and vertices */ 679632fe681dSStefano Zampini PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, &o_nf, &ISForFaces, &o_ne, &ISForEdges, &ISForVertices)); 679708122e43SStefano Zampini } else { 679808122e43SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 6799984c4197SStefano Zampini 680008122e43SStefano Zampini total_counts = 0; 680108122e43SStefano Zampini n_vertices = 0; 680248a46eb9SPierre Jolivet if (sub_schurs->is_vertices && pcbddc->use_vertices) PetscCall(ISGetLocalSize(sub_schurs->is_vertices, &n_vertices)); 680308122e43SStefano Zampini max_constraints = 0; 68049162d606SStefano Zampini total_counts_cc = 0; 680508122e43SStefano Zampini for (i = 0; i < sub_schurs->n_subs + n_vertices; i++) { 680608122e43SStefano Zampini total_counts += pcbddc->adaptive_constraints_n[i]; 68079162d606SStefano Zampini if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++; 680808122e43SStefano Zampini max_constraints = PetscMax(max_constraints, pcbddc->adaptive_constraints_n[i]); 680908122e43SStefano Zampini } 68109162d606SStefano Zampini constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr; 68119162d606SStefano Zampini constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr; 68129162d606SStefano Zampini constraints_idxs = pcbddc->adaptive_constraints_idxs; 68139162d606SStefano Zampini constraints_data = pcbddc->adaptive_constraints_data; 681474d5cdf7SStefano Zampini /* constraints_n differs from pcbddc->adaptive_constraints_n */ 68159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(total_counts_cc, &constraints_n)); 68169162d606SStefano Zampini total_counts_cc = 0; 68179162d606SStefano Zampini for (i = 0; i < sub_schurs->n_subs + n_vertices; i++) { 6818ad540459SPierre Jolivet if (pcbddc->adaptive_constraints_n[i]) constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i]; 681908122e43SStefano Zampini } 682008122e43SStefano Zampini 68218bec7fa6SStefano Zampini max_size_of_constraint = 0; 68229162d606SStefano 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]); 68239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(constraints_idxs_ptr[total_counts_cc], &constraints_idxs_B)); 682408122e43SStefano Zampini /* Change of basis */ 68259566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(total_counts_cc, &change_basis)); 682608122e43SStefano Zampini if (pcbddc->use_change_of_basis) { 682708122e43SStefano Zampini for (i = 0; i < sub_schurs->n_subs; i++) { 682848a46eb9SPierre Jolivet if (PetscBTLookup(sub_schurs->is_edge, i) || pcbddc->use_change_on_faces) PetscCall(PetscBTSet(change_basis, i + n_vertices)); 682908122e43SStefano Zampini } 683008122e43SStefano Zampini } 683108122e43SStefano Zampini } 6832984c4197SStefano Zampini pcbddc->local_primal_size = total_counts; 68339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->local_primal_size + pcbddc->benign_n, &pcbddc->primal_indices_local_idxs)); 683408122e43SStefano Zampini 68359162d606SStefano Zampini /* map constraints_idxs in boundary numbering */ 683632fe681dSStefano Zampini if (pcbddc->use_change_of_basis) { 68379566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(pcis->BtoNmap, IS_GTOLM_DROP, constraints_idxs_ptr[total_counts_cc], constraints_idxs, &i, constraints_idxs_B)); 683863a3b9bcSJacob 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); 683932fe681dSStefano Zampini } 6840674ae819SStefano Zampini 6841674ae819SStefano Zampini /* Create constraint matrix */ 68429566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &pcbddc->ConstraintMatrix)); 68439566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->ConstraintMatrix, MATAIJ)); 68449566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->ConstraintMatrix, pcbddc->local_primal_size, pcis->n, pcbddc->local_primal_size, pcis->n)); 6845984c4197SStefano Zampini 6846984c4197SStefano Zampini /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */ 6847a717540cSStefano Zampini /* determine if a QR strategy is needed for change of basis */ 68485a52fde0SStefano Zampini qr_needed = pcbddc->use_qr_single; 68499566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(total_counts_cc, &qr_needed_idx)); 6850984c4197SStefano Zampini total_primal_vertices = 0; 6851b3d85658SStefano Zampini pcbddc->local_primal_size_cc = 0; 68529162d606SStefano Zampini for (i = 0; i < total_counts_cc; i++) { 68539162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[i + 1] - constraints_idxs_ptr[i]; 685472b8c272SStefano Zampini if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) { 68559162d606SStefano Zampini pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]]; 6856b3d85658SStefano Zampini pcbddc->local_primal_size_cc += 1; 685764efe560SStefano Zampini } else if (PetscBTLookup(change_basis, i)) { 6858ad540459SPierre Jolivet for (k = 0; k < constraints_n[i]; k++) pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i] + k]; 6859b3d85658SStefano Zampini pcbddc->local_primal_size_cc += constraints_n[i]; 686091af6908SStefano Zampini if (constraints_n[i] > 1 || pcbddc->use_qr_single) { 68613ba16761SJacob Faibussowitsch PetscCall(PetscBTSet(qr_needed_idx, i)); 6862a717540cSStefano Zampini qr_needed = PETSC_TRUE; 6863a717540cSStefano Zampini } 6864fa434743SStefano Zampini } else { 6865b3d85658SStefano Zampini pcbddc->local_primal_size_cc += 1; 6866fa434743SStefano Zampini } 6867a717540cSStefano Zampini } 6868b371cd4fSStefano Zampini /* note that the local variable n_vertices used below stores the number of pointwise constraints */ 6869b371cd4fSStefano Zampini pcbddc->n_vertices = total_primal_vertices; 6870674ae819SStefano Zampini /* permute indices in order to have a sorted set of vertices */ 68719566063dSJacob Faibussowitsch PetscCall(PetscSortInt(total_primal_vertices, pcbddc->primal_indices_local_idxs)); 68729566063dSJacob 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)); 68739566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pcbddc->local_primal_ref_node, pcbddc->primal_indices_local_idxs, total_primal_vertices)); 68740e6343abSStefano Zampini for (i = 0; i < total_primal_vertices; i++) pcbddc->local_primal_ref_mult[i] = 1; 6875984c4197SStefano Zampini 6876984c4197SStefano Zampini /* nonzero structure of constraint matrix */ 687774d5cdf7SStefano Zampini /* and get reference dof for local constraints */ 68789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->local_primal_size, &nnz)); 6879984c4197SStefano Zampini for (i = 0; i < total_primal_vertices; i++) nnz[i] = 1; 688074d5cdf7SStefano Zampini 6881984c4197SStefano Zampini j = total_primal_vertices; 688274d5cdf7SStefano Zampini total_counts = total_primal_vertices; 6883b3d85658SStefano Zampini cum = total_primal_vertices; 68849162d606SStefano Zampini for (i = n_vertices; i < total_counts_cc; i++) { 68854641a718SStefano Zampini if (!PetscBTLookup(change_basis, i)) { 6886b3d85658SStefano Zampini pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]]; 6887b3d85658SStefano Zampini pcbddc->local_primal_ref_mult[cum] = constraints_n[i]; 6888b3d85658SStefano Zampini cum++; 68899162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[i + 1] - constraints_idxs_ptr[i]; 689074d5cdf7SStefano Zampini for (k = 0; k < constraints_n[i]; k++) { 689174d5cdf7SStefano Zampini pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i] + k]; 689274d5cdf7SStefano Zampini nnz[j + k] = size_of_constraint; 689374d5cdf7SStefano Zampini } 68949162d606SStefano Zampini j += constraints_n[i]; 6895674ae819SStefano Zampini } 6896674ae819SStefano Zampini } 68979566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix, 0, nnz)); 68989566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->ConstraintMatrix, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 68999566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 6900088faed8SStefano Zampini 6901674ae819SStefano Zampini /* set values in constraint matrix */ 690248a46eb9SPierre Jolivet for (i = 0; i < total_primal_vertices; i++) PetscCall(MatSetValue(pcbddc->ConstraintMatrix, i, pcbddc->local_primal_ref_node[i], 1.0, INSERT_VALUES)); 6903984c4197SStefano Zampini total_counts = total_primal_vertices; 69049162d606SStefano Zampini for (i = n_vertices; i < total_counts_cc; i++) { 69054641a718SStefano Zampini if (!PetscBTLookup(change_basis, i)) { 69069162d606SStefano Zampini PetscInt *cols; 69079162d606SStefano Zampini 69089162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[i + 1] - constraints_idxs_ptr[i]; 69099162d606SStefano Zampini cols = constraints_idxs + constraints_idxs_ptr[i]; 69109162d606SStefano Zampini for (k = 0; k < constraints_n[i]; k++) { 69119162d606SStefano Zampini PetscInt row = total_counts + k; 69129162d606SStefano Zampini PetscScalar *vals; 69139162d606SStefano Zampini 69149162d606SStefano Zampini vals = constraints_data + constraints_data_ptr[i] + k * size_of_constraint; 69159566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->ConstraintMatrix, 1, &row, size_of_constraint, cols, vals, INSERT_VALUES)); 69169162d606SStefano Zampini } 69179162d606SStefano Zampini total_counts += constraints_n[i]; 6918674ae819SStefano Zampini } 6919674ae819SStefano Zampini } 6920674ae819SStefano Zampini /* assembling */ 69219566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pcbddc->ConstraintMatrix, MAT_FINAL_ASSEMBLY)); 69229566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->ConstraintMatrix, MAT_FINAL_ASSEMBLY)); 69239566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(pcbddc->ConstraintMatrix, (PetscObject)pc, "-pc_bddc_constraint_mat_view")); 6924088faed8SStefano Zampini 6925674ae819SStefano Zampini /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */ 6926674ae819SStefano Zampini if (pcbddc->use_change_of_basis) { 6927026de310SStefano Zampini /* dual and primal dofs on a single cc */ 6928984c4197SStefano Zampini PetscInt dual_dofs, primal_dofs; 6929984c4197SStefano Zampini /* working stuff for GEQRF */ 69305a52fde0SStefano Zampini PetscScalar *qr_basis = NULL, *qr_tau = NULL, *qr_work = NULL, lqr_work_t; 6931984c4197SStefano Zampini PetscBLASInt lqr_work; 6932984c4197SStefano Zampini /* working stuff for UNGQR */ 69333c377650SSatish Balay PetscScalar *gqr_work = NULL, lgqr_work_t = 0.0; 6934984c4197SStefano Zampini PetscBLASInt lgqr_work; 6935984c4197SStefano Zampini /* working stuff for TRTRS */ 69365a52fde0SStefano Zampini PetscScalar *trs_rhs = NULL; 69373f08241aSStefano Zampini PetscBLASInt Blas_NRHS; 6938984c4197SStefano Zampini /* pointers for values insertion into change of basis matrix */ 6939984c4197SStefano Zampini PetscInt *start_rows, *start_cols; 6940984c4197SStefano Zampini PetscScalar *start_vals; 6941984c4197SStefano Zampini /* working stuff for values insertion */ 69424641a718SStefano Zampini PetscBT is_primal; 694364efe560SStefano Zampini PetscInt *aux_primal_numbering_B; 6944906d46d4SStefano Zampini /* matrix sizes */ 6945906d46d4SStefano Zampini PetscInt global_size, local_size; 6946906d46d4SStefano Zampini /* temporary change of basis */ 6947906d46d4SStefano Zampini Mat localChangeOfBasisMatrix; 6948cf5a6209SStefano Zampini /* extra space for debugging */ 69495a52fde0SStefano Zampini PetscScalar *dbg_work = NULL; 6950984c4197SStefano Zampini 69519566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &localChangeOfBasisMatrix)); 69529566063dSJacob Faibussowitsch PetscCall(MatSetType(localChangeOfBasisMatrix, MATAIJ)); 69539566063dSJacob Faibussowitsch PetscCall(MatSetSizes(localChangeOfBasisMatrix, pcis->n, pcis->n, pcis->n, pcis->n)); 6954906d46d4SStefano Zampini /* nonzeros for local mat */ 69559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n, &nnz)); 69561dd7afcfSStefano Zampini if (!pcbddc->benign_change || pcbddc->fake_change) { 6957bbb9e6c6SStefano Zampini for (i = 0; i < pcis->n; i++) nnz[i] = 1; 69581dd7afcfSStefano Zampini } else { 69591dd7afcfSStefano Zampini const PetscInt *ii; 69601dd7afcfSStefano Zampini PetscInt n; 69611dd7afcfSStefano Zampini PetscBool flg_row; 69629566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(pcbddc->benign_change, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, NULL, &flg_row)); 69631dd7afcfSStefano Zampini for (i = 0; i < n; i++) nnz[i] = ii[i + 1] - ii[i]; 69649566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(pcbddc->benign_change, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, NULL, &flg_row)); 69651dd7afcfSStefano Zampini } 69669162d606SStefano Zampini for (i = n_vertices; i < total_counts_cc; i++) { 6967a717540cSStefano Zampini if (PetscBTLookup(change_basis, i)) { 69689162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[i + 1] - constraints_idxs_ptr[i]; 6969a717540cSStefano Zampini if (PetscBTLookup(qr_needed_idx, i)) { 69709162d606SStefano Zampini for (j = 0; j < size_of_constraint; j++) nnz[constraints_idxs[constraints_idxs_ptr[i] + j]] = size_of_constraint; 6971a717540cSStefano Zampini } else { 69729162d606SStefano Zampini nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint; 69739162d606SStefano Zampini for (j = 1; j < size_of_constraint; j++) nnz[constraints_idxs[constraints_idxs_ptr[i] + j]] = 2; 6974a717540cSStefano Zampini } 6975a717540cSStefano Zampini } 6976a717540cSStefano Zampini } 69779566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(localChangeOfBasisMatrix, 0, nnz)); 69789566063dSJacob Faibussowitsch PetscCall(MatSetOption(localChangeOfBasisMatrix, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 69799566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 69801dd7afcfSStefano Zampini /* Set interior change in the matrix */ 69811dd7afcfSStefano Zampini if (!pcbddc->benign_change || pcbddc->fake_change) { 698248a46eb9SPierre Jolivet for (i = 0; i < pcis->n; i++) PetscCall(MatSetValue(localChangeOfBasisMatrix, i, i, 1.0, INSERT_VALUES)); 69831dd7afcfSStefano Zampini } else { 69841dd7afcfSStefano Zampini const PetscInt *ii, *jj; 69851dd7afcfSStefano Zampini PetscScalar *aa; 69861dd7afcfSStefano Zampini PetscInt n; 69871dd7afcfSStefano Zampini PetscBool flg_row; 69889566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(pcbddc->benign_change, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &flg_row)); 69899566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(pcbddc->benign_change, &aa)); 699048a46eb9SPierre 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)); 69919566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(pcbddc->benign_change, &aa)); 69929566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(pcbddc->benign_change, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &flg_row)); 69931dd7afcfSStefano Zampini } 6994a717540cSStefano Zampini 6995a717540cSStefano Zampini if (pcbddc->dbg_flag) { 69969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "--------------------------------------------------------------\n")); 69979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Checking change of basis computation for subdomain %04d\n", PetscGlobalRank)); 6998a717540cSStefano Zampini } 6999a717540cSStefano Zampini 7000a717540cSStefano Zampini /* Now we loop on the constraints which need a change of basis */ 7001a717540cSStefano Zampini /* 7002a717540cSStefano Zampini Change of basis matrix is evaluated similarly to the FIRST APPROACH in 7003a717540cSStefano Zampini Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1) 7004a717540cSStefano Zampini 70057c625d9fSStefano Zampini Basic blocks of change of basis matrix T computed: 7006a717540cSStefano Zampini 70077c625d9fSStefano 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) 7008a6b551f4SStefano Zampini 7009a6b551f4SStefano Zampini | 1 0 ... 0 s_1/S | 7010a6b551f4SStefano Zampini | 0 1 ... 0 s_2/S | 7011a717540cSStefano Zampini | ... | 7012a6b551f4SStefano Zampini | 0 ... 1 s_{n-1}/S | 7013a6b551f4SStefano Zampini | -s_1/s_n ... -s_{n-1}/s_n s_n/S | 7014a717540cSStefano Zampini 7015a6b551f4SStefano Zampini with S = \sum_{i=1}^n s_i^2 7016a6b551f4SStefano Zampini NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering 7017a6b551f4SStefano Zampini in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering 7018a6b551f4SStefano Zampini 7019a6b551f4SStefano Zampini - QR decomposition of constraints otherwise 7020a717540cSStefano Zampini */ 70215a52fde0SStefano Zampini if (qr_needed && max_size_of_constraint) { 7022984c4197SStefano Zampini /* space to store Q */ 70239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_size_of_constraint * max_size_of_constraint, &qr_basis)); 70244e64d54eSstefano_zampini /* array to store scaling factors for reflectors */ 70259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_constraints, &qr_tau)); 7026984c4197SStefano Zampini /* first we issue queries for optimal work */ 70279566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_size_of_constraint, &Blas_M)); 70289566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_constraints, &Blas_N)); 70299566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_size_of_constraint, &Blas_LDA)); 7030984c4197SStefano Zampini lqr_work = -1; 7031792fecdfSBarry Smith PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&Blas_M, &Blas_N, qr_basis, &Blas_LDA, qr_tau, &lqr_work_t, &lqr_work, &lierr)); 7032835f2295SStefano Zampini PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in query to GEQRF Lapack routine %" PetscBLASInt_FMT, lierr); 70339566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t), &lqr_work)); 703459b05608SBarry Smith PetscCall(PetscMalloc1(lqr_work, &qr_work)); 7035984c4197SStefano Zampini lgqr_work = -1; 70369566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_size_of_constraint, &Blas_M)); 70379566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_size_of_constraint, &Blas_N)); 70389566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_constraints, &Blas_K)); 70399566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_size_of_constraint, &Blas_LDA)); 70403f08241aSStefano Zampini if (Blas_K > Blas_M) Blas_K = Blas_M; /* adjust just for computing optimal work */ 7041792fecdfSBarry Smith PetscCallBLAS("LAPACKorgqr", LAPACKorgqr_(&Blas_M, &Blas_N, &Blas_K, qr_basis, &Blas_LDA, qr_tau, &lgqr_work_t, &lgqr_work, &lierr)); 7042835f2295SStefano Zampini PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in query to ORGQR/UNGQR Lapack routine %" PetscBLASInt_FMT, lierr); 70439566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t), &lgqr_work)); 704459b05608SBarry Smith PetscCall(PetscMalloc1(lgqr_work, &gqr_work)); 7045984c4197SStefano Zampini /* array to store rhs and solution of triangular solver */ 70469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_constraints * max_constraints, &trs_rhs)); 7047a717540cSStefano Zampini /* allocating workspace for check */ 704848a46eb9SPierre Jolivet if (pcbddc->dbg_flag) PetscCall(PetscMalloc1(max_size_of_constraint * (max_constraints + max_size_of_constraint), &dbg_work)); 7049a717540cSStefano Zampini } 7050984c4197SStefano Zampini /* array to store whether a node is primal or not */ 70519566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(pcis->n_B, &is_primal)); 70529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(total_primal_vertices, &aux_primal_numbering_B)); 70539566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(pcis->BtoNmap, IS_GTOLM_DROP, total_primal_vertices, pcbddc->local_primal_ref_node, &i, aux_primal_numbering_B)); 705463a3b9bcSJacob 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); 705548a46eb9SPierre Jolivet for (i = 0; i < total_primal_vertices; i++) PetscCall(PetscBTSet(is_primal, aux_primal_numbering_B[i])); 70569566063dSJacob Faibussowitsch PetscCall(PetscFree(aux_primal_numbering_B)); 7057984c4197SStefano Zampini 7058a717540cSStefano Zampini /* loop on constraints and see whether or not they need a change of basis and compute it */ 70599162d606SStefano Zampini for (total_counts = n_vertices; total_counts < total_counts_cc; total_counts++) { 70609162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[total_counts + 1] - constraints_idxs_ptr[total_counts]; 70614641a718SStefano Zampini if (PetscBTLookup(change_basis, total_counts)) { 7062984c4197SStefano Zampini /* get constraint info */ 70639162d606SStefano Zampini primal_dofs = constraints_n[total_counts]; 7064984c4197SStefano Zampini dual_dofs = size_of_constraint - primal_dofs; 7065984c4197SStefano Zampini 706648a46eb9SPierre 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)); 7067984c4197SStefano Zampini 7068fa434743SStefano Zampini if (PetscBTLookup(qr_needed_idx, total_counts)) { /* QR */ 7069a717540cSStefano Zampini 7070a717540cSStefano Zampini /* copy quadrature constraints for change of basis check */ 707148a46eb9SPierre Jolivet if (pcbddc->dbg_flag) PetscCall(PetscArraycpy(dbg_work, &constraints_data[constraints_data_ptr[total_counts]], size_of_constraint * primal_dofs)); 7072984c4197SStefano Zampini /* copy temporary constraints into larger work vector (in order to store all columns of Q) */ 70739566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(qr_basis, &constraints_data[constraints_data_ptr[total_counts]], size_of_constraint * primal_dofs)); 7074984c4197SStefano Zampini 7075984c4197SStefano Zampini /* compute QR decomposition of constraints */ 70769566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_M)); 70779566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_N)); 70789566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 70799566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 7080792fecdfSBarry Smith PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&Blas_M, &Blas_N, qr_basis, &Blas_LDA, qr_tau, qr_work, &lqr_work, &lierr)); 7081835f2295SStefano Zampini PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in GEQRF Lapack routine %" PetscBLASInt_FMT, lierr); 70829566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 7083984c4197SStefano Zampini 7084a5b23f4aSJose E. Roman /* explicitly compute R^-T */ 70859566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(trs_rhs, primal_dofs * primal_dofs)); 7086984c4197SStefano Zampini for (j = 0; j < primal_dofs; j++) trs_rhs[j * (primal_dofs + 1)] = 1.0; 70879566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_N)); 70889566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_NRHS)); 70899566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 70909566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_LDB)); 70919566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 7092792fecdfSBarry Smith PetscCallBLAS("LAPACKtrtrs", LAPACKtrtrs_("U", "T", "N", &Blas_N, &Blas_NRHS, qr_basis, &Blas_LDA, trs_rhs, &Blas_LDB, &lierr)); 7093835f2295SStefano Zampini PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in TRTRS Lapack routine %" PetscBLASInt_FMT, lierr); 70949566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 7095984c4197SStefano Zampini 7096a717540cSStefano Zampini /* explicitly compute all columns of Q (Q = [Q1 | Q2]) overwriting QR factorization in qr_basis */ 70979566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_M)); 70989566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 70999566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_K)); 71009566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 71019566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 7102792fecdfSBarry Smith PetscCallBLAS("LAPACKorgqr", LAPACKorgqr_(&Blas_M, &Blas_N, &Blas_K, qr_basis, &Blas_LDA, qr_tau, gqr_work, &lgqr_work, &lierr)); 7103835f2295SStefano Zampini PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ORGQR/UNGQR Lapack routine %" PetscBLASInt_FMT, lierr); 71049566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 7105984c4197SStefano Zampini 7106984c4197SStefano Zampini /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints 7107984c4197SStefano Zampini i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below) 7108984c4197SStefano Zampini where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */ 71099566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_M)); 71109566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_N)); 71119566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_K)); 71129566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 71139566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_LDB)); 71149566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDC)); 71159566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 7116792fecdfSBarry 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)); 71179566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 71189566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(qr_basis, &constraints_data[constraints_data_ptr[total_counts]], size_of_constraint * primal_dofs)); 7119984c4197SStefano Zampini 7120984c4197SStefano Zampini /* insert values in change of basis matrix respecting global ordering of new primal dofs */ 71219162d606SStefano Zampini start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]]; 7122984c4197SStefano Zampini /* insert cols for primal dofs */ 7123984c4197SStefano Zampini for (j = 0; j < primal_dofs; j++) { 7124984c4197SStefano Zampini start_vals = &qr_basis[j * size_of_constraint]; 71259162d606SStefano Zampini start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts] + j]; 71269566063dSJacob Faibussowitsch PetscCall(MatSetValues(localChangeOfBasisMatrix, size_of_constraint, start_rows, 1, start_cols, start_vals, INSERT_VALUES)); 7127984c4197SStefano Zampini } 7128984c4197SStefano Zampini /* insert cols for dual dofs */ 7129984c4197SStefano Zampini for (j = 0, k = 0; j < dual_dofs; k++) { 71309162d606SStefano Zampini if (!PetscBTLookup(is_primal, constraints_idxs_B[constraints_idxs_ptr[total_counts] + k])) { 7131984c4197SStefano Zampini start_vals = &qr_basis[(primal_dofs + j) * size_of_constraint]; 71329162d606SStefano Zampini start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts] + k]; 71339566063dSJacob Faibussowitsch PetscCall(MatSetValues(localChangeOfBasisMatrix, size_of_constraint, start_rows, 1, start_cols, start_vals, INSERT_VALUES)); 7134984c4197SStefano Zampini j++; 7135674ae819SStefano Zampini } 7136674ae819SStefano Zampini } 7137984c4197SStefano Zampini 7138984c4197SStefano Zampini /* check change of basis */ 7139984c4197SStefano Zampini if (pcbddc->dbg_flag) { 7140984c4197SStefano Zampini PetscInt ii, jj; 7141984c4197SStefano Zampini PetscBool valid_qr = PETSC_TRUE; 71429566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_M)); 71439566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 71449566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_K)); 71459566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 71469566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDB)); 71479566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_LDC)); 71489566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 7149792fecdfSBarry 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)); 71509566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 7151984c4197SStefano Zampini for (jj = 0; jj < size_of_constraint; jj++) { 7152984c4197SStefano Zampini for (ii = 0; ii < primal_dofs; ii++) { 7153cf5a6209SStefano Zampini if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint * primal_dofs + jj * primal_dofs + ii]) > 1.e-12) valid_qr = PETSC_FALSE; 7154c068d9bbSLisandro 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; 7155674ae819SStefano Zampini } 7156674ae819SStefano Zampini } 7157984c4197SStefano Zampini if (!valid_qr) { 71589566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "\t-> wrong change of basis!\n")); 7159984c4197SStefano Zampini for (jj = 0; jj < size_of_constraint; jj++) { 7160984c4197SStefano Zampini for (ii = 0; ii < primal_dofs; ii++) { 7161cf5a6209SStefano Zampini if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint * primal_dofs + jj * primal_dofs + ii]) > 1.e-12) { 716263a3b9bcSJacob 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]))); 7163674ae819SStefano Zampini } 7164c068d9bbSLisandro Dalcin if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint * primal_dofs + jj * primal_dofs + ii] - (PetscReal)1) > 1.e-12) { 716563a3b9bcSJacob 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]))); 7166984c4197SStefano Zampini } 7167984c4197SStefano Zampini } 7168984c4197SStefano Zampini } 7169674ae819SStefano Zampini } else { 71709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "\t-> right change of basis!\n")); 7171674ae819SStefano Zampini } 7172674ae819SStefano Zampini } 7173a717540cSStefano Zampini } else { /* simple transformation block */ 7174a717540cSStefano Zampini PetscInt row, col; 7175a6b551f4SStefano Zampini PetscScalar val, norm; 7176a6b551f4SStefano Zampini 71779566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 7178792fecdfSBarry 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)); 7179a717540cSStefano Zampini for (j = 0; j < size_of_constraint; j++) { 71809162d606SStefano Zampini PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts] + j]; 71819162d606SStefano Zampini row = constraints_idxs[constraints_idxs_ptr[total_counts] + j]; 7182bbb9e6c6SStefano Zampini if (!PetscBTLookup(is_primal, row_B)) { 71839162d606SStefano Zampini col = constraints_idxs[constraints_idxs_ptr[total_counts]]; 71849566063dSJacob Faibussowitsch PetscCall(MatSetValue(localChangeOfBasisMatrix, row, row, 1.0, INSERT_VALUES)); 71859566063dSJacob Faibussowitsch PetscCall(MatSetValue(localChangeOfBasisMatrix, row, col, constraints_data[constraints_data_ptr[total_counts] + j] / norm, INSERT_VALUES)); 7186a717540cSStefano Zampini } else { 7187a717540cSStefano Zampini for (k = 0; k < size_of_constraint; k++) { 71889162d606SStefano Zampini col = constraints_idxs[constraints_idxs_ptr[total_counts] + k]; 7189a717540cSStefano Zampini if (row != col) { 71909162d606SStefano Zampini val = -constraints_data[constraints_data_ptr[total_counts] + k] / constraints_data[constraints_data_ptr[total_counts]]; 7191a717540cSStefano Zampini } else { 71929162d606SStefano Zampini val = constraints_data[constraints_data_ptr[total_counts]] / norm; 7193a717540cSStefano Zampini } 71949566063dSJacob Faibussowitsch PetscCall(MatSetValue(localChangeOfBasisMatrix, row, col, val, INSERT_VALUES)); 7195a717540cSStefano Zampini } 7196a717540cSStefano Zampini } 7197a717540cSStefano Zampini } 719848a46eb9SPierre Jolivet if (pcbddc->dbg_flag) PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "\t-> using standard change of basis\n")); 7199a717540cSStefano Zampini } 7200984c4197SStefano Zampini } else { 720148a46eb9SPierre 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)); 7202674ae819SStefano Zampini } 7203674ae819SStefano Zampini } 7204a717540cSStefano Zampini 7205a717540cSStefano Zampini /* free workspace */ 7206a717540cSStefano Zampini if (qr_needed) { 72071baa6e33SBarry Smith if (pcbddc->dbg_flag) PetscCall(PetscFree(dbg_work)); 72089566063dSJacob Faibussowitsch PetscCall(PetscFree(trs_rhs)); 72099566063dSJacob Faibussowitsch PetscCall(PetscFree(qr_tau)); 72109566063dSJacob Faibussowitsch PetscCall(PetscFree(qr_work)); 72119566063dSJacob Faibussowitsch PetscCall(PetscFree(gqr_work)); 72129566063dSJacob Faibussowitsch PetscCall(PetscFree(qr_basis)); 7213674ae819SStefano Zampini } 72149566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&is_primal)); 72159566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(localChangeOfBasisMatrix, MAT_FINAL_ASSEMBLY)); 72169566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(localChangeOfBasisMatrix, MAT_FINAL_ASSEMBLY)); 7217906d46d4SStefano Zampini 7218906d46d4SStefano Zampini /* assembling of global change of variable */ 721988c03ad3SStefano Zampini if (!pcbddc->fake_change) { 7220bbb9e6c6SStefano Zampini Mat tmat; 722116f15bc4SStefano Zampini PetscInt bs; 722216f15bc4SStefano Zampini 72239566063dSJacob Faibussowitsch PetscCall(VecGetSize(pcis->vec1_global, &global_size)); 72249566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(pcis->vec1_global, &local_size)); 72259566063dSJacob Faibussowitsch PetscCall(MatDuplicate(pc->pmat, MAT_DO_NOT_COPY_VALUES, &tmat)); 72269566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(tmat, localChangeOfBasisMatrix)); 72279566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(tmat, MAT_FINAL_ASSEMBLY)); 72289566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(tmat, MAT_FINAL_ASSEMBLY)); 72299566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)pc), &pcbddc->ChangeOfBasisMatrix)); 72309566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->ChangeOfBasisMatrix, MATAIJ)); 72319566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(pc->pmat, &bs)); 72329566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(pcbddc->ChangeOfBasisMatrix, bs)); 72339566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->ChangeOfBasisMatrix, local_size, local_size, global_size, global_size)); 72349566063dSJacob Faibussowitsch PetscCall(MatISSetMPIXAIJPreallocation_Private(tmat, pcbddc->ChangeOfBasisMatrix, PETSC_TRUE)); 72359566063dSJacob Faibussowitsch PetscCall(MatConvert(tmat, MATAIJ, MAT_REUSE_MATRIX, &pcbddc->ChangeOfBasisMatrix)); 72369566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tmat)); 72379566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_global, 0.0)); 72389566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_N, 1.0)); 72399566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_N, pcis->vec1_global, ADD_VALUES, SCATTER_REVERSE)); 72409566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_N, pcis->vec1_global, ADD_VALUES, SCATTER_REVERSE)); 72419566063dSJacob Faibussowitsch PetscCall(VecReciprocal(pcis->vec1_global)); 72429566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(pcbddc->ChangeOfBasisMatrix, pcis->vec1_global, NULL)); 724388c03ad3SStefano Zampini 7244906d46d4SStefano Zampini /* check */ 7245906d46d4SStefano Zampini if (pcbddc->dbg_flag) { 7246906d46d4SStefano Zampini PetscReal error; 7247906d46d4SStefano Zampini Vec x, x_change; 7248906d46d4SStefano Zampini 72499566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_global, &x)); 72509566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_global, &x_change)); 72519566063dSJacob Faibussowitsch PetscCall(VecSetRandom(x, NULL)); 72529566063dSJacob Faibussowitsch PetscCall(VecCopy(x, pcis->vec1_global)); 72539566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, x, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD)); 72549566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, x, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD)); 72559566063dSJacob Faibussowitsch PetscCall(MatMult(localChangeOfBasisMatrix, pcis->vec1_N, pcis->vec2_N)); 72569566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, pcis->vec2_N, x, INSERT_VALUES, SCATTER_REVERSE)); 72579566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, pcis->vec2_N, x, INSERT_VALUES, SCATTER_REVERSE)); 72589566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcis->vec1_global, x_change)); 72599566063dSJacob Faibussowitsch PetscCall(VecAXPY(x, -1.0, x_change)); 72609566063dSJacob Faibussowitsch PetscCall(VecNorm(x, NORM_INFINITY, &error)); 7261049d1499SBarry Smith PetscCheck(error <= PETSC_SMALL, PetscObjectComm((PetscObject)pc), PETSC_ERR_PLIB, "Error global vs local change on N: %1.6e", (double)error); 72629566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 72639566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x_change)); 7264906d46d4SStefano Zampini } 7265b96c3477SStefano Zampini /* adapt sub_schurs computed (if any) */ 7266b96c3477SStefano Zampini if (pcbddc->use_deluxe_scaling) { 7267b96c3477SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 7268bf3a8328SStefano Zampini 726908401ef6SPierre 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"); 7270b334f244SStefano Zampini if (sub_schurs && sub_schurs->S_Ej_all) { 7271ac632422SStefano Zampini Mat S_new, tmat; 7272bf3a8328SStefano Zampini IS is_all_N, is_V_Sall = NULL; 7273bbb9e6c6SStefano Zampini 72749566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(pcis->BtoNmap, sub_schurs->is_Ej_all, &is_all_N)); 72759566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(localChangeOfBasisMatrix, is_all_N, is_all_N, MAT_INITIAL_MATRIX, &tmat)); 7276bf3a8328SStefano Zampini if (pcbddc->deluxe_zerorows) { 7277bf3a8328SStefano Zampini ISLocalToGlobalMapping NtoSall; 7278bf3a8328SStefano Zampini IS is_V; 72799566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, pcbddc->n_vertices, pcbddc->local_primal_ref_node, PETSC_COPY_VALUES, &is_V)); 72809566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is_all_N, &NtoSall)); 72819566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(NtoSall, IS_GTOLM_DROP, is_V, &is_V_Sall)); 72829566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&NtoSall)); 72839566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_V)); 7284bf3a8328SStefano Zampini } 72859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_all_N)); 72869566063dSJacob Faibussowitsch PetscCall(MatPtAP(sub_schurs->S_Ej_all, tmat, MAT_INITIAL_MATRIX, 1.0, &S_new)); 72879566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sub_schurs->S_Ej_all)); 72889566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)S_new)); 7289bf3a8328SStefano Zampini if (pcbddc->deluxe_zerorows) { 7290bf3a8328SStefano Zampini const PetscScalar *array; 7291bf3a8328SStefano Zampini const PetscInt *idxs_V, *idxs_all; 7292bf3a8328SStefano Zampini PetscInt i, n_V; 7293bf3a8328SStefano Zampini 72949566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumnsIS(S_new, is_V_Sall, 1., NULL, NULL)); 72959566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is_V_Sall, &n_V)); 72969566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is_V_Sall, &idxs_V)); 72979566063dSJacob Faibussowitsch PetscCall(ISGetIndices(sub_schurs->is_Ej_all, &idxs_all)); 72989566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(pcis->D, &array)); 7299b087196eSStefano Zampini for (i = 0; i < n_V; i++) { 7300b087196eSStefano Zampini PetscScalar val; 7301b087196eSStefano Zampini PetscInt idx; 7302b087196eSStefano Zampini 7303b087196eSStefano Zampini idx = idxs_V[i]; 7304b087196eSStefano Zampini val = array[idxs_all[idxs_V[i]]]; 73059566063dSJacob Faibussowitsch PetscCall(MatSetValue(S_new, idx, idx, val, INSERT_VALUES)); 7306b087196eSStefano Zampini } 73079566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(S_new, MAT_FINAL_ASSEMBLY)); 73089566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(S_new, MAT_FINAL_ASSEMBLY)); 73099566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(pcis->D, &array)); 73109566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(sub_schurs->is_Ej_all, &idxs_all)); 73119566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is_V_Sall, &idxs_V)); 7312bf3a8328SStefano Zampini } 7313ac632422SStefano Zampini sub_schurs->S_Ej_all = S_new; 73149566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_new)); 7315ac632422SStefano Zampini if (sub_schurs->sum_S_Ej_all) { 73169566063dSJacob Faibussowitsch PetscCall(MatPtAP(sub_schurs->sum_S_Ej_all, tmat, MAT_INITIAL_MATRIX, 1.0, &S_new)); 73179566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sub_schurs->sum_S_Ej_all)); 73189566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)S_new)); 73191baa6e33SBarry Smith if (pcbddc->deluxe_zerorows) PetscCall(MatZeroRowsColumnsIS(S_new, is_V_Sall, 1., NULL, NULL)); 7320ac632422SStefano Zampini sub_schurs->sum_S_Ej_all = S_new; 73219566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_new)); 7322ac632422SStefano Zampini } 73239566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_V_Sall)); 73249566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tmat)); 7325b96c3477SStefano Zampini } 7326c9db6a07SStefano Zampini /* destroy any change of basis context in sub_schurs */ 7327b334f244SStefano Zampini if (sub_schurs && sub_schurs->change) { 7328c9db6a07SStefano Zampini PetscInt i; 7329c9db6a07SStefano Zampini 733048a46eb9SPierre Jolivet for (i = 0; i < sub_schurs->n_subs; i++) PetscCall(KSPDestroy(&sub_schurs->change[i])); 73319566063dSJacob Faibussowitsch PetscCall(PetscFree(sub_schurs->change)); 7332c9db6a07SStefano Zampini } 7333b96c3477SStefano Zampini } 733416909a7fSStefano Zampini if (pcbddc->switch_static) { /* need to save the local change */ 733516909a7fSStefano Zampini pcbddc->switch_static_change = localChangeOfBasisMatrix; 733616909a7fSStefano Zampini } else { 73379566063dSJacob Faibussowitsch PetscCall(MatDestroy(&localChangeOfBasisMatrix)); 733816909a7fSStefano Zampini } 73391dd7afcfSStefano Zampini /* determine if any process has changed the pressures locally */ 734027b6a85dSStefano Zampini pcbddc->change_interior = pcbddc->benign_have_null; 734172b8c272SStefano Zampini } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */ 73429566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->ConstraintMatrix)); 734372b8c272SStefano Zampini pcbddc->ConstraintMatrix = localChangeOfBasisMatrix; 734472b8c272SStefano Zampini pcbddc->use_qr_single = qr_needed; 734572b8c272SStefano Zampini } 73461dd7afcfSStefano Zampini } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) { 734727b6a85dSStefano Zampini if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) { 73489566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix)); 7349b9b85e73SStefano Zampini pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix; 7350906d46d4SStefano Zampini } else { 73511dd7afcfSStefano Zampini Mat benign_global = NULL; 735227b6a85dSStefano Zampini if (pcbddc->benign_have_null) { 73531dd7afcfSStefano Zampini Mat M; 73541dd7afcfSStefano Zampini 73559e9b7b1fSStefano Zampini pcbddc->change_interior = PETSC_TRUE; 73569566063dSJacob Faibussowitsch PetscCall(VecCopy(matis->counter, pcis->vec1_N)); 73579566063dSJacob Faibussowitsch PetscCall(VecReciprocal(pcis->vec1_N)); 73589566063dSJacob Faibussowitsch PetscCall(MatDuplicate(pc->pmat, MAT_DO_NOT_COPY_VALUES, &benign_global)); 73599e9b7b1fSStefano Zampini if (pcbddc->benign_change) { 73609566063dSJacob Faibussowitsch PetscCall(MatDuplicate(pcbddc->benign_change, MAT_COPY_VALUES, &M)); 73619566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(M, pcis->vec1_N, NULL)); 7362906d46d4SStefano Zampini } else { 73639566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, pcis->n, pcis->n, 1, NULL, &M)); 73649566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(M, pcis->vec1_N, INSERT_VALUES)); 7365906d46d4SStefano Zampini } 73669566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(benign_global, M)); 73679566063dSJacob Faibussowitsch PetscCall(MatDestroy(&M)); 73689566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(benign_global, MAT_FINAL_ASSEMBLY)); 73699566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(benign_global, MAT_FINAL_ASSEMBLY)); 73701dd7afcfSStefano Zampini } 73711dd7afcfSStefano Zampini if (pcbddc->user_ChangeOfBasisMatrix) { 7372fb842aefSJose E. Roman PetscCall(MatMatMult(pcbddc->user_ChangeOfBasisMatrix, benign_global, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &pcbddc->ChangeOfBasisMatrix)); 73739566063dSJacob Faibussowitsch PetscCall(MatDestroy(&benign_global)); 737427b6a85dSStefano Zampini } else if (pcbddc->benign_have_null) { 73751dd7afcfSStefano Zampini pcbddc->ChangeOfBasisMatrix = benign_global; 73761dd7afcfSStefano Zampini } 73771dd7afcfSStefano Zampini } 737816909a7fSStefano Zampini if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */ 737916909a7fSStefano Zampini IS is_global; 738016909a7fSStefano Zampini const PetscInt *gidxs; 738116909a7fSStefano Zampini 73829566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->rmapping, &gidxs)); 73839566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), pcis->n, gidxs, PETSC_COPY_VALUES, &is_global)); 73849566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->rmapping, &gidxs)); 73859566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix, is_global, is_global, &pcbddc->switch_static_change)); 73869566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_global)); 738716909a7fSStefano Zampini } 73881dd7afcfSStefano Zampini } 738948a46eb9SPierre Jolivet if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->work_change)); 7390a717540cSStefano Zampini 739172b8c272SStefano Zampini if (!pcbddc->fake_change) { 73924f1b2e48SStefano Zampini /* add pressure dofs to set of primal nodes for numbering purposes */ 73934f1b2e48SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) { 73944f1b2e48SStefano Zampini pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i]; 73954f1b2e48SStefano Zampini pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i]; 7396019a44ceSStefano Zampini pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1; 7397019a44ceSStefano Zampini pcbddc->local_primal_size_cc++; 7398019a44ceSStefano Zampini pcbddc->local_primal_size++; 7399019a44ceSStefano Zampini } 7400019a44ceSStefano Zampini 7401019a44ceSStefano Zampini /* check if a new primal space has been introduced (also take into account benign trick) */ 7402727cdba6SStefano Zampini pcbddc->new_primal_space_local = PETSC_TRUE; 7403727cdba6SStefano Zampini if (olocal_primal_size == pcbddc->local_primal_size) { 74049566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(pcbddc->local_primal_ref_node, olocal_primal_ref_node, olocal_primal_size_cc, &pcbddc->new_primal_space_local)); 7405c1c8e736SStefano Zampini pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local); 74060e6343abSStefano Zampini if (!pcbddc->new_primal_space_local) { 74079566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(pcbddc->local_primal_ref_mult, olocal_primal_ref_mult, olocal_primal_size_cc, &pcbddc->new_primal_space_local)); 7408727cdba6SStefano Zampini pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local); 7409727cdba6SStefano Zampini } 74100e6343abSStefano Zampini } 7411727cdba6SStefano Zampini /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */ 7412462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&pcbddc->new_primal_space_local, &pcbddc->new_primal_space, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 741372b8c272SStefano Zampini } 74149566063dSJacob Faibussowitsch PetscCall(PetscFree2(olocal_primal_ref_node, olocal_primal_ref_mult)); 7415727cdba6SStefano Zampini 7416a717540cSStefano Zampini /* flush dbg viewer */ 74171baa6e33SBarry Smith if (pcbddc->dbg_flag) PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 7418a717540cSStefano Zampini 7419e310c8b4SStefano Zampini /* free workspace */ 74209566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&qr_needed_idx)); 74219566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&change_basis)); 742208122e43SStefano Zampini if (!pcbddc->adaptive_selection) { 74239566063dSJacob Faibussowitsch PetscCall(PetscFree3(constraints_idxs_ptr, constraints_data_ptr, constraints_n)); 74249566063dSJacob Faibussowitsch PetscCall(PetscFree3(constraints_data, constraints_idxs, constraints_idxs_B)); 742508122e43SStefano Zampini } else { 7426d0609cedSBarry 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)); 74279566063dSJacob Faibussowitsch PetscCall(PetscFree(constraints_n)); 74289566063dSJacob Faibussowitsch PetscCall(PetscFree(constraints_idxs_B)); 742908122e43SStefano Zampini } 74303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7431674ae819SStefano Zampini } 7432674ae819SStefano Zampini 7433d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCAnalyzeInterface(PC pc) 7434d71ae5a4SJacob Faibussowitsch { 743571582508SStefano Zampini ISLocalToGlobalMapping map; 7436674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 7437674ae819SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 743866da6bd7Sstefano_zampini PetscInt i, N; 743966da6bd7Sstefano_zampini PetscBool rcsr = PETSC_FALSE; 7440674ae819SStefano Zampini 7441674ae819SStefano Zampini PetscFunctionBegin; 74428af8fcf9SStefano Zampini if (pcbddc->recompute_topography) { 7443b03ebc13SStefano Zampini pcbddc->graphanalyzed = PETSC_FALSE; 74448e61c736SStefano Zampini /* Reset previously computed graph */ 74459566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphReset(pcbddc->mat_graph)); 7446674ae819SStefano Zampini /* Init local Graph struct */ 74479566063dSJacob Faibussowitsch PetscCall(MatGetSize(pc->pmat, &N, NULL)); 74489566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(pc->pmat, &map, NULL)); 74499566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphInit(pcbddc->mat_graph, map, N, pcbddc->graphmaxcount)); 7450674ae819SStefano Zampini 745148a46eb9SPierre Jolivet if (pcbddc->user_primal_vertices_local && !pcbddc->user_primal_vertices) PetscCall(PCBDDCConsistencyCheckIS(pc, MPI_LOR, &pcbddc->user_primal_vertices_local)); 7452575ad6abSStefano Zampini /* Check validity of the csr graph passed in by the user */ 74539371c9d4SSatish 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, 74549371c9d4SSatish Balay pcbddc->mat_graph->nvtxs); 74559577ea80SStefano Zampini 7456674ae819SStefano Zampini /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */ 745766da6bd7Sstefano_zampini if (!pcbddc->mat_graph->xadj && pcbddc->use_local_adj) { 74584d379d7bSStefano Zampini PetscInt *xadj, *adjncy; 74594d379d7bSStefano Zampini PetscInt nvtxs; 74609de2952eSStefano Zampini PetscBool flg_row; 74619de2952eSStefano Zampini Mat A; 7462674ae819SStefano Zampini 74639de2952eSStefano Zampini PetscCall(PetscObjectReference((PetscObject)matis->A)); 74649de2952eSStefano Zampini A = matis->A; 74659de2952eSStefano Zampini for (PetscInt i = 0; i < pcbddc->local_adj_square; i++) { 74669de2952eSStefano Zampini Mat AtA; 74679de2952eSStefano Zampini 74689de2952eSStefano Zampini PetscCall(MatProductCreate(A, A, NULL, &AtA)); 74699de2952eSStefano Zampini PetscCall(MatSetOptionsPrefix(AtA, "pc_bddc_graph_")); 74709de2952eSStefano Zampini PetscCall(MatProductSetType(AtA, MATPRODUCT_AtB)); 74719de2952eSStefano Zampini PetscCall(MatProductSetFromOptions(AtA)); 74729de2952eSStefano Zampini PetscCall(MatProductSymbolic(AtA)); 74739de2952eSStefano Zampini PetscCall(MatProductClear(AtA)); 74749de2952eSStefano Zampini /* we only need the sparsity, cheat and tell PETSc the matrix has been assembled */ 74759de2952eSStefano Zampini AtA->assembled = PETSC_TRUE; 74769de2952eSStefano Zampini PetscCall(MatDestroy(&A)); 74779de2952eSStefano Zampini A = AtA; 74789de2952eSStefano Zampini } 74799de2952eSStefano Zampini PetscCall(MatGetRowIJ(A, 0, PETSC_TRUE, PETSC_FALSE, &nvtxs, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &flg_row)); 74802fffb893SStefano Zampini if (flg_row) { 74819566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLocalAdjacencyGraph(pc, nvtxs, xadj, adjncy, PETSC_COPY_VALUES)); 7482b96c3477SStefano Zampini pcbddc->computed_rowadj = PETSC_TRUE; 74839de2952eSStefano Zampini PetscCall(MatRestoreRowIJ(A, 0, PETSC_TRUE, PETSC_FALSE, &nvtxs, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &flg_row)); 748466da6bd7Sstefano_zampini rcsr = PETSC_TRUE; 7485674ae819SStefano Zampini } 74869de2952eSStefano Zampini PetscCall(MatDestroy(&A)); 74879de2952eSStefano Zampini } 74881baa6e33SBarry Smith if (pcbddc->dbg_flag) PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 7489674ae819SStefano Zampini 7490ab8c8b98SStefano Zampini if (pcbddc->mat_graph->cdim && !pcbddc->mat_graph->cloc) { 7491ab8c8b98SStefano Zampini PetscReal *lcoords; 7492ab8c8b98SStefano Zampini PetscInt n; 7493ab8c8b98SStefano Zampini MPI_Datatype dimrealtype; 7494835f2295SStefano Zampini PetscMPIInt cdimi; 7495ab8c8b98SStefano Zampini 74964f819b78SStefano Zampini /* TODO: support for blocked */ 749763a3b9bcSJacob 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); 74989566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(matis->A, &n, NULL)); 74999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->mat_graph->cdim * n, &lcoords)); 7500835f2295SStefano Zampini PetscCall(PetscMPIIntCast(pcbddc->mat_graph->cdim, &cdimi)); 7501835f2295SStefano Zampini PetscCallMPI(MPI_Type_contiguous(cdimi, MPIU_REAL, &dimrealtype)); 75029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&dimrealtype)); 75039566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, dimrealtype, pcbddc->mat_graph->coords, lcoords, MPI_REPLACE)); 75049566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, dimrealtype, pcbddc->mat_graph->coords, lcoords, MPI_REPLACE)); 75059566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&dimrealtype)); 75069566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->mat_graph->coords)); 7507ab8c8b98SStefano Zampini 7508ab8c8b98SStefano Zampini pcbddc->mat_graph->coords = lcoords; 7509ab8c8b98SStefano Zampini pcbddc->mat_graph->cloc = PETSC_TRUE; 7510ab8c8b98SStefano Zampini pcbddc->mat_graph->cnloc = n; 7511ab8c8b98SStefano Zampini } 75129371c9d4SSatish 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, 75139371c9d4SSatish Balay pcbddc->mat_graph->nvtxs); 7514625961bdSStefano Zampini pcbddc->mat_graph->active_coords = (PetscBool)(pcbddc->corner_selection && pcbddc->mat_graph->cdim && !pcbddc->corner_selected); 7515ab8c8b98SStefano Zampini 75164f1b2e48SStefano Zampini /* attach info on disconnected subdomains if present */ 75174f1b2e48SStefano Zampini if (pcbddc->n_local_subs) { 751820c3699dSStefano Zampini PetscInt *local_subs, n, totn; 75194f1b2e48SStefano Zampini 75209566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(matis->A, &n, NULL)); 75219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &local_subs)); 752220c3699dSStefano Zampini for (i = 0; i < n; i++) local_subs[i] = pcbddc->n_local_subs; 75234f1b2e48SStefano Zampini for (i = 0; i < pcbddc->n_local_subs; i++) { 75244f1b2e48SStefano Zampini const PetscInt *idxs; 75254f1b2e48SStefano Zampini PetscInt nl, j; 75264f1b2e48SStefano Zampini 75279566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->local_subs[i], &nl)); 75289566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->local_subs[i], &idxs)); 752971582508SStefano Zampini for (j = 0; j < nl; j++) local_subs[idxs[j]] = i; 75309566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->local_subs[i], &idxs)); 75314f1b2e48SStefano Zampini } 753220c3699dSStefano Zampini for (i = 0, totn = 0; i < n; i++) totn = PetscMax(totn, local_subs[i]); 753320c3699dSStefano Zampini pcbddc->mat_graph->n_local_subs = totn + 1; 75344f1b2e48SStefano Zampini pcbddc->mat_graph->local_subs = local_subs; 75354f1b2e48SStefano Zampini } 75369de2952eSStefano Zampini 75379de2952eSStefano Zampini /* Setup of Graph */ 75389de2952eSStefano Zampini PetscCall(PCBDDCGraphSetUp(pcbddc->mat_graph, pcbddc->vertex_size, pcbddc->NeumannBoundariesLocal, pcbddc->DirichletBoundariesLocal, pcbddc->n_ISForDofsLocal, pcbddc->ISForDofsLocal, pcbddc->user_primal_vertices_local)); 75398af8fcf9SStefano Zampini } 75404f1b2e48SStefano Zampini 7541cac5312eSStefano Zampini if (!pcbddc->graphanalyzed) { 7542674ae819SStefano Zampini /* Graph's connected components analysis */ 75439566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph)); 754471582508SStefano Zampini pcbddc->graphanalyzed = PETSC_TRUE; 75454f819b78SStefano Zampini pcbddc->corner_selected = pcbddc->corner_selection; 75468af8fcf9SStefano Zampini } 754766da6bd7Sstefano_zampini if (rcsr) pcbddc->mat_graph->nvtxs_csr = 0; 75483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7549674ae819SStefano Zampini } 7550674ae819SStefano Zampini 7551d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt *nio, Vec vecs[]) 7552d71ae5a4SJacob Faibussowitsch { 7553295df10fSStefano Zampini PetscInt i, j, n; 75549a7d3425SStefano Zampini PetscScalar *alphas; 7555295df10fSStefano Zampini PetscReal norm, *onorms; 75569a7d3425SStefano Zampini 75579a7d3425SStefano Zampini PetscFunctionBegin; 7558295df10fSStefano Zampini n = *nio; 75593ba16761SJacob Faibussowitsch if (!n) PetscFunctionReturn(PETSC_SUCCESS); 75609566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n, &alphas, n, &onorms)); 75619566063dSJacob Faibussowitsch PetscCall(VecNormalize(vecs[0], &norm)); 756292cccca0SStefano Zampini if (norm < PETSC_SMALL) { 7563295df10fSStefano Zampini onorms[0] = 0.0; 75649566063dSJacob Faibussowitsch PetscCall(VecSet(vecs[0], 0.0)); 7565295df10fSStefano Zampini } else { 7566295df10fSStefano Zampini onorms[0] = norm; 756792cccca0SStefano Zampini } 7568295df10fSStefano Zampini 75698c0031efSStefano Zampini for (i = 1; i < n; i++) { 75709566063dSJacob Faibussowitsch PetscCall(VecMDot(vecs[i], i, vecs, alphas)); 75718c0031efSStefano Zampini for (j = 0; j < i; j++) alphas[j] = PetscConj(-alphas[j]); 75729566063dSJacob Faibussowitsch PetscCall(VecMAXPY(vecs[i], i, alphas, vecs)); 75739566063dSJacob Faibussowitsch PetscCall(VecNormalize(vecs[i], &norm)); 757492cccca0SStefano Zampini if (norm < PETSC_SMALL) { 7575295df10fSStefano Zampini onorms[i] = 0.0; 75769566063dSJacob Faibussowitsch PetscCall(VecSet(vecs[i], 0.0)); 7577295df10fSStefano Zampini } else { 7578295df10fSStefano Zampini onorms[i] = norm; 757992cccca0SStefano Zampini } 75809a7d3425SStefano Zampini } 7581295df10fSStefano Zampini /* push nonzero vectors at the beginning */ 7582295df10fSStefano Zampini for (i = 0; i < n; i++) { 7583295df10fSStefano Zampini if (onorms[i] == 0.0) { 7584295df10fSStefano Zampini for (j = i + 1; j < n; j++) { 7585295df10fSStefano Zampini if (onorms[j] != 0.0) { 75869566063dSJacob Faibussowitsch PetscCall(VecCopy(vecs[j], vecs[i])); 7587e1614d24SStefano Zampini onorms[i] = onorms[j]; 7588295df10fSStefano Zampini onorms[j] = 0.0; 7589e1614d24SStefano Zampini break; 7590295df10fSStefano Zampini } 7591295df10fSStefano Zampini } 7592295df10fSStefano Zampini } 7593295df10fSStefano Zampini } 7594295df10fSStefano Zampini for (i = 0, *nio = 0; i < n; i++) *nio += onorms[i] != 0.0 ? 1 : 0; 75959566063dSJacob Faibussowitsch PetscCall(PetscFree2(alphas, onorms)); 75963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 75979a7d3425SStefano Zampini } 75989a7d3425SStefano Zampini 7599ba38deedSJacob Faibussowitsch static PetscErrorCode PCBDDCMatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS *is_sends, PetscBool *have_void) 7600d71ae5a4SJacob Faibussowitsch { 7601e432b41dSStefano Zampini ISLocalToGlobalMapping mapping; 760257de7509SStefano Zampini Mat A; 7603e7931f94SStefano Zampini PetscInt n_neighs, *neighs, *n_shared, **shared; 7604e7931f94SStefano Zampini PetscMPIInt size, rank, color; 760552e5ac9dSStefano Zampini PetscInt *xadj, *adjncy; 760652e5ac9dSStefano Zampini PetscInt *adjncy_wgt, *v_wgt, *ranks_send_to_idx; 7607bb360cb4SStefano Zampini PetscInt im_active, active_procs, N, n, i, j, threshold = 2; 760857de7509SStefano Zampini PetscInt void_procs, *procs_candidates = NULL; 760927b6a85dSStefano Zampini PetscInt xadj_count, *count; 761027b6a85dSStefano Zampini PetscBool ismatis, use_vwgt = PETSC_FALSE; 761127b6a85dSStefano Zampini PetscSubcomm psubcomm; 761227b6a85dSStefano Zampini MPI_Comm subcomm; 7613a57a6d2fSStefano Zampini 7614e7931f94SStefano Zampini PetscFunctionBegin; 761557de7509SStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 76169566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)mat, MATIS, &ismatis)); 761728b400f6SJacob 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); 761857de7509SStefano Zampini PetscValidLogicalCollectiveInt(mat, *n_subdomains, 2); 761957de7509SStefano Zampini PetscValidLogicalCollectiveInt(mat, redprocs, 3); 762063a3b9bcSJacob Faibussowitsch PetscCheck(*n_subdomains > 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Invalid number of subdomains requested %" PetscInt_FMT, *n_subdomains); 762157de7509SStefano Zampini 762257de7509SStefano Zampini if (have_void) *have_void = PETSC_FALSE; 76239566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 76249566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)mat), &rank)); 76259566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(mat, &A)); 76269566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &n, NULL)); 7627bb360cb4SStefano Zampini im_active = !!n; 7628462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&im_active, &active_procs, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 762957de7509SStefano Zampini void_procs = size - active_procs; 763015229ffcSPierre Jolivet /* get ranks of non-active processes in mat communicator */ 763157de7509SStefano Zampini if (void_procs) { 763257de7509SStefano Zampini PetscInt ncand; 763357de7509SStefano Zampini 763457de7509SStefano Zampini if (have_void) *have_void = PETSC_TRUE; 76359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &procs_candidates)); 76369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allgather(&im_active, 1, MPIU_INT, procs_candidates, 1, MPIU_INT, PetscObjectComm((PetscObject)mat))); 763757de7509SStefano Zampini for (i = 0, ncand = 0; i < size; i++) { 7638ad540459SPierre Jolivet if (!procs_candidates[i]) procs_candidates[ncand++] = i; 763957de7509SStefano Zampini } 764057de7509SStefano Zampini /* force n_subdomains to be not greater that the number of non-active processes */ 764157de7509SStefano Zampini *n_subdomains = PetscMin(void_procs, *n_subdomains); 764257de7509SStefano Zampini } 764357de7509SStefano Zampini 7644bb360cb4SStefano Zampini /* number of subdomains requested greater than active processes or matrix size -> just shift the matrix 76459dddd249SSatish Balay number of subdomains requested 1 -> send to rank-0 or first candidate in voids */ 76469566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &N, NULL)); 7647bb360cb4SStefano Zampini if (active_procs < *n_subdomains || *n_subdomains == 1 || N <= *n_subdomains) { 764814f0bfb9SStefano Zampini PetscInt issize, isidx, dest; 764914f0bfb9SStefano Zampini if (*n_subdomains == 1) dest = 0; 765014f0bfb9SStefano Zampini else dest = rank; 765157de7509SStefano Zampini if (im_active) { 765257de7509SStefano Zampini issize = 1; 765357de7509SStefano Zampini if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */ 765414f0bfb9SStefano Zampini isidx = procs_candidates[dest]; 765557de7509SStefano Zampini } else { 765614f0bfb9SStefano Zampini isidx = dest; 765757de7509SStefano Zampini } 765857de7509SStefano Zampini } else { 765957de7509SStefano Zampini issize = 0; 766057de7509SStefano Zampini isidx = -1; 766157de7509SStefano Zampini } 7662bb360cb4SStefano Zampini if (*n_subdomains != 1) *n_subdomains = active_procs; 76639566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), issize, &isidx, PETSC_COPY_VALUES, is_sends)); 76649566063dSJacob Faibussowitsch PetscCall(PetscFree(procs_candidates)); 76653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 766657de7509SStefano Zampini } 76679de2952eSStefano Zampini PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)A)->prefix, "-mat_is_partitioning_use_vwgt", &use_vwgt, NULL)); 76689de2952eSStefano Zampini PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)A)->prefix, "-mat_is_partitioning_threshold", &threshold, NULL)); 766927b6a85dSStefano Zampini threshold = PetscMax(threshold, 2); 7670e7931f94SStefano Zampini 7671e7931f94SStefano Zampini /* Get info on mapping */ 76729566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(mat, &mapping, NULL)); 76739566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetInfo(mapping, &n_neighs, &neighs, &n_shared, &shared)); 7674e7931f94SStefano Zampini 7675e7931f94SStefano Zampini /* build local CSR graph of subdomains' connectivity */ 76769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2, &xadj)); 7677e7931f94SStefano Zampini xadj[0] = 0; 7678e7931f94SStefano Zampini xadj[1] = PetscMax(n_neighs - 1, 0); 76799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(xadj[1], &adjncy)); 76809566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(xadj[1], &adjncy_wgt)); 76819566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(n, &count)); 768227b6a85dSStefano Zampini for (i = 1; i < n_neighs; i++) 76839371c9d4SSatish Balay for (j = 0; j < n_shared[i]; j++) count[shared[i][j]] += 1; 7684e7931f94SStefano Zampini 768527b6a85dSStefano Zampini xadj_count = 0; 76862b510759SStefano Zampini for (i = 1; i < n_neighs; i++) { 768727b6a85dSStefano Zampini for (j = 0; j < n_shared[i]; j++) { 768827b6a85dSStefano Zampini if (count[shared[i][j]] < threshold) { 7689d023bfaeSStefano Zampini adjncy[xadj_count] = neighs[i]; 7690d023bfaeSStefano Zampini adjncy_wgt[xadj_count] = n_shared[i]; 7691d023bfaeSStefano Zampini xadj_count++; 769227b6a85dSStefano Zampini break; 769327b6a85dSStefano Zampini } 7694e7931f94SStefano Zampini } 7695e7931f94SStefano Zampini } 7696d023bfaeSStefano Zampini xadj[1] = xadj_count; 76979566063dSJacob Faibussowitsch PetscCall(PetscFree(count)); 76989566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreInfo(mapping, &n_neighs, &neighs, &n_shared, &shared)); 76999566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(xadj[1], adjncy, adjncy_wgt)); 7700e7931f94SStefano Zampini 77019566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &ranks_send_to_idx)); 7702e7931f94SStefano Zampini 770327b6a85dSStefano Zampini /* Restrict work on active processes only */ 77049566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(im_active, &color)); 770527b6a85dSStefano Zampini if (void_procs) { 77069566063dSJacob Faibussowitsch PetscCall(PetscSubcommCreate(PetscObjectComm((PetscObject)mat), &psubcomm)); 77079566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetNumber(psubcomm, 2)); /* 2 groups, active process and not active processes */ 77089566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetTypeGeneral(psubcomm, color, rank)); 770927b6a85dSStefano Zampini subcomm = PetscSubcommChild(psubcomm); 771027b6a85dSStefano Zampini } else { 771127b6a85dSStefano Zampini psubcomm = NULL; 771227b6a85dSStefano Zampini subcomm = PetscObjectComm((PetscObject)mat); 771327b6a85dSStefano Zampini } 771427b6a85dSStefano Zampini 771527b6a85dSStefano Zampini v_wgt = NULL; 771627b6a85dSStefano Zampini if (!color) { 77179566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 77189566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 77199566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy_wgt)); 7720c8587f34SStefano Zampini } else { 772152e5ac9dSStefano Zampini Mat subdomain_adj; 772252e5ac9dSStefano Zampini IS new_ranks, new_ranks_contig; 772352e5ac9dSStefano Zampini MatPartitioning partitioner; 77246497c311SBarry Smith PetscInt rstart, rend; 77256497c311SBarry Smith PetscMPIInt irstart = 0, irend = 0; 772652e5ac9dSStefano Zampini PetscInt *is_indices, *oldranks; 772757de7509SStefano Zampini PetscMPIInt size; 7728b0c7d250SStefano Zampini PetscBool aggregate; 7729b0c7d250SStefano Zampini 77309566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(subcomm, &size)); 773127b6a85dSStefano Zampini if (void_procs) { 773227b6a85dSStefano Zampini PetscInt prank = rank; 77339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &oldranks)); 77349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allgather(&prank, 1, MPIU_INT, oldranks, 1, MPIU_INT, subcomm)); 773548a46eb9SPierre Jolivet for (i = 0; i < xadj[1]; i++) PetscCall(PetscFindInt(adjncy[i], size, oldranks, &adjncy[i])); 77369566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(xadj[1], adjncy, adjncy_wgt)); 773727b6a85dSStefano Zampini } else { 773827b6a85dSStefano Zampini oldranks = NULL; 773927b6a85dSStefano Zampini } 7740b0c7d250SStefano Zampini aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE); 774127b6a85dSStefano Zampini if (aggregate) { /* TODO: all this part could be made more efficient */ 7742b0c7d250SStefano Zampini PetscInt lrows, row, ncols, *cols; 7743b0c7d250SStefano Zampini PetscMPIInt nrank; 7744b0c7d250SStefano Zampini PetscScalar *vals; 7745b0c7d250SStefano Zampini 77469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(subcomm, &nrank)); 7747b0c7d250SStefano Zampini lrows = 0; 7748b0c7d250SStefano Zampini if (nrank < redprocs) { 7749b0c7d250SStefano Zampini lrows = size / redprocs; 7750b0c7d250SStefano Zampini if (nrank < size % redprocs) lrows++; 7751b0c7d250SStefano Zampini } 77529566063dSJacob Faibussowitsch PetscCall(MatCreateAIJ(subcomm, lrows, lrows, size, size, 50, NULL, 50, NULL, &subdomain_adj)); 77539566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(subdomain_adj, &rstart, &rend)); 7754835f2295SStefano Zampini PetscCall(PetscMPIIntCast(rstart, &irstart)); 7755835f2295SStefano Zampini PetscCall(PetscMPIIntCast(rend, &irend)); 77569566063dSJacob Faibussowitsch PetscCall(MatSetOption(subdomain_adj, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_FALSE)); 77579566063dSJacob Faibussowitsch PetscCall(MatSetOption(subdomain_adj, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 7758b0c7d250SStefano Zampini row = nrank; 7759b0c7d250SStefano Zampini ncols = xadj[1] - xadj[0]; 7760b0c7d250SStefano Zampini cols = adjncy; 77619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncols, &vals)); 7762b0c7d250SStefano Zampini for (i = 0; i < ncols; i++) vals[i] = adjncy_wgt[i]; 77639566063dSJacob Faibussowitsch PetscCall(MatSetValues(subdomain_adj, 1, &row, ncols, cols, vals, INSERT_VALUES)); 77649566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(subdomain_adj, MAT_FINAL_ASSEMBLY)); 77659566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(subdomain_adj, MAT_FINAL_ASSEMBLY)); 77669566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 77679566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 77689566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy_wgt)); 77699566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 777027b6a85dSStefano Zampini if (use_vwgt) { 777127b6a85dSStefano Zampini Vec v; 777227b6a85dSStefano Zampini const PetscScalar *array; 777327b6a85dSStefano Zampini PetscInt nl; 777427b6a85dSStefano Zampini 77759566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(subdomain_adj, &v, NULL)); 77769566063dSJacob Faibussowitsch PetscCall(VecSetValue(v, row, (PetscScalar)n, INSERT_VALUES)); 77779566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(v)); 77789566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(v)); 77799566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &nl)); 77809566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &array)); 77819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl, &v_wgt)); 778222db5ddcSStefano Zampini for (i = 0; i < nl; i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]); 77839566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &array)); 77849566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 778527b6a85dSStefano Zampini } 7786b0c7d250SStefano Zampini } else { 7787835f2295SStefano Zampini PetscCall(MatCreateMPIAdj(subcomm, 1, size, xadj, adjncy, adjncy_wgt, &subdomain_adj)); 778827b6a85dSStefano Zampini if (use_vwgt) { 77899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &v_wgt)); 7790bb360cb4SStefano Zampini v_wgt[0] = n; 779127b6a85dSStefano Zampini } 7792b0c7d250SStefano Zampini } 77939566063dSJacob Faibussowitsch /* PetscCall(MatView(subdomain_adj,0)); */ 7794e7931f94SStefano Zampini 7795e7931f94SStefano Zampini /* Partition */ 77969566063dSJacob Faibussowitsch PetscCall(MatPartitioningCreate(subcomm, &partitioner)); 7797ce64c636SStefano Zampini #if defined(PETSC_HAVE_PTSCOTCH) 77989566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetType(partitioner, MATPARTITIONINGPTSCOTCH)); 7799ce64c636SStefano Zampini #elif defined(PETSC_HAVE_PARMETIS) 78009566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetType(partitioner, MATPARTITIONINGPARMETIS)); 7801ce64c636SStefano Zampini #else 78029566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetType(partitioner, MATPARTITIONINGAVERAGE)); 7803ce64c636SStefano Zampini #endif 78049566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetAdjacency(partitioner, subdomain_adj)); 78051baa6e33SBarry Smith if (v_wgt) PetscCall(MatPartitioningSetVertexWeights(partitioner, v_wgt)); 7806835f2295SStefano Zampini *n_subdomains = PetscMin(size, *n_subdomains); 78079566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetNParts(partitioner, *n_subdomains)); 78089566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetFromOptions(partitioner)); 78099566063dSJacob Faibussowitsch PetscCall(MatPartitioningApply(partitioner, &new_ranks)); 78109566063dSJacob Faibussowitsch /* PetscCall(MatPartitioningView(partitioner,0)); */ 7811e7931f94SStefano Zampini 781252e5ac9dSStefano Zampini /* renumber new_ranks to avoid "holes" in new set of processors */ 78139566063dSJacob Faibussowitsch PetscCall(ISRenumber(new_ranks, NULL, NULL, &new_ranks_contig)); 78149566063dSJacob Faibussowitsch PetscCall(ISDestroy(&new_ranks)); 78159566063dSJacob Faibussowitsch PetscCall(ISGetIndices(new_ranks_contig, (const PetscInt **)&is_indices)); 781657de7509SStefano Zampini if (!aggregate) { 781757de7509SStefano Zampini if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */ 78186bdcaf15SBarry Smith PetscAssert(oldranks, PETSC_COMM_SELF, PETSC_ERR_PLIB, "This should not happen"); 781957de7509SStefano Zampini ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]]; 782027b6a85dSStefano Zampini } else if (oldranks) { 7821b0c7d250SStefano Zampini ranks_send_to_idx[0] = oldranks[is_indices[0]]; 782227b6a85dSStefano Zampini } else { 782327b6a85dSStefano Zampini ranks_send_to_idx[0] = is_indices[0]; 782457de7509SStefano Zampini } 782528143c3dSStefano Zampini } else { 78267fb8a5e4SKarl Rupp PetscInt idx = 0; 7827b0c7d250SStefano Zampini PetscMPIInt tag; 7828b0c7d250SStefano Zampini MPI_Request *reqs; 7829b0c7d250SStefano Zampini 78309566063dSJacob Faibussowitsch PetscCall(PetscObjectGetNewTag((PetscObject)subdomain_adj, &tag)); 78319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rend - rstart, &reqs)); 78326497c311SBarry Smith for (PetscMPIInt i = irstart; i < irend; i++) PetscCallMPI(MPIU_Isend(is_indices + i - rstart, 1, MPIU_INT, i, tag, subcomm, &reqs[i - rstart])); 78336497c311SBarry Smith PetscCallMPI(MPIU_Recv(&idx, 1, MPIU_INT, MPI_ANY_SOURCE, tag, subcomm, MPI_STATUS_IGNORE)); 78346497c311SBarry Smith PetscCallMPI(MPI_Waitall(irend - irstart, reqs, MPI_STATUSES_IGNORE)); 78359566063dSJacob Faibussowitsch PetscCall(PetscFree(reqs)); 783657de7509SStefano Zampini if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */ 78376bdcaf15SBarry Smith PetscAssert(oldranks, PETSC_COMM_SELF, PETSC_ERR_PLIB, "This should not happen"); 78387fb8a5e4SKarl Rupp ranks_send_to_idx[0] = procs_candidates[oldranks[idx]]; 783927b6a85dSStefano Zampini } else if (oldranks) { 78407fb8a5e4SKarl Rupp ranks_send_to_idx[0] = oldranks[idx]; 784127b6a85dSStefano Zampini } else { 78427fb8a5e4SKarl Rupp ranks_send_to_idx[0] = idx; 784328143c3dSStefano Zampini } 784457de7509SStefano Zampini } 78459566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(new_ranks_contig, (const PetscInt **)&is_indices)); 7846e7931f94SStefano Zampini /* clean up */ 78479566063dSJacob Faibussowitsch PetscCall(PetscFree(oldranks)); 78489566063dSJacob Faibussowitsch PetscCall(ISDestroy(&new_ranks_contig)); 78499566063dSJacob Faibussowitsch PetscCall(MatDestroy(&subdomain_adj)); 78509566063dSJacob Faibussowitsch PetscCall(MatPartitioningDestroy(&partitioner)); 7851e7931f94SStefano Zampini } 78529566063dSJacob Faibussowitsch PetscCall(PetscSubcommDestroy(&psubcomm)); 78539566063dSJacob Faibussowitsch PetscCall(PetscFree(procs_candidates)); 7854e7931f94SStefano Zampini 7855e7931f94SStefano Zampini /* assemble parallel IS for sends */ 7856e7931f94SStefano Zampini i = 1; 785727b6a85dSStefano Zampini if (!color) i = 0; 78589566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), i, ranks_send_to_idx, PETSC_OWN_POINTER, is_sends)); 78593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7860e7931f94SStefano Zampini } 7861e7931f94SStefano Zampini 78629371c9d4SSatish Balay typedef enum { 78639371c9d4SSatish Balay MATDENSE_PRIVATE = 0, 78649371c9d4SSatish Balay MATAIJ_PRIVATE, 78659371c9d4SSatish Balay MATBAIJ_PRIVATE, 78669371c9d4SSatish Balay MATSBAIJ_PRIVATE 78679371c9d4SSatish Balay } MatTypePrivate; 7868e7931f94SStefano Zampini 7869ba38deedSJacob 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[]) 7870d71ae5a4SJacob Faibussowitsch { 787170cf5478SStefano Zampini Mat local_mat; 7872e7931f94SStefano Zampini IS is_sends_internal; 78739d30be91SStefano Zampini PetscInt rows, cols, new_local_rows; 78741ae86dd6SStefano Zampini PetscInt i, bs, buf_size_idxs, buf_size_idxs_is, buf_size_vals, buf_size_vecs; 78759d30be91SStefano Zampini PetscBool ismatis, isdense, newisdense, destroy_mat; 7876e7931f94SStefano Zampini ISLocalToGlobalMapping l2gmap; 7877e7931f94SStefano Zampini PetscInt *l2gmap_indices; 7878e7931f94SStefano Zampini const PetscInt *is_indices; 7879e7931f94SStefano Zampini MatType new_local_type; 7880e7931f94SStefano Zampini /* buffers */ 7881e7931f94SStefano Zampini PetscInt *ptr_idxs, *send_buffer_idxs, *recv_buffer_idxs; 788228143c3dSStefano Zampini PetscInt *ptr_idxs_is, *send_buffer_idxs_is, *recv_buffer_idxs_is; 78839d30be91SStefano Zampini PetscInt *recv_buffer_idxs_local; 78841683a169SBarry Smith PetscScalar *ptr_vals, *recv_buffer_vals; 78851683a169SBarry Smith const PetscScalar *send_buffer_vals; 78861ae86dd6SStefano Zampini PetscScalar *ptr_vecs, *send_buffer_vecs, *recv_buffer_vecs; 7887e7931f94SStefano Zampini /* MPI */ 788828143c3dSStefano Zampini MPI_Comm comm, comm_n; 788928143c3dSStefano Zampini PetscSubcomm subcomm; 7890e569e4e1SStefano Zampini PetscMPIInt n_sends, n_recvs, size; 789128143c3dSStefano Zampini PetscMPIInt *iflags, *ilengths_idxs, *ilengths_vals, *ilengths_idxs_is; 789228143c3dSStefano Zampini PetscMPIInt *onodes, *onodes_is, *olengths_idxs, *olengths_idxs_is, *olengths_vals; 789360b1fa21SPierre Jolivet PetscMPIInt len, tag_idxs, tag_idxs_is, tag_vals, tag_vecs, source_dest; 78941ae86dd6SStefano Zampini MPI_Request *send_req_idxs, *send_req_idxs_is, *send_req_vals, *send_req_vecs; 78951ae86dd6SStefano Zampini MPI_Request *recv_req_idxs, *recv_req_idxs_is, *recv_req_vals, *recv_req_vecs; 7896e7931f94SStefano Zampini 7897e7931f94SStefano Zampini PetscFunctionBegin; 789857de7509SStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 78999566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)mat, MATIS, &ismatis)); 79005f80ce2aSJacob 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); 790157de7509SStefano Zampini PetscValidLogicalCollectiveInt(mat, n_subdomains, 3); 790257de7509SStefano Zampini PetscValidLogicalCollectiveBool(mat, restrict_comm, 4); 790357de7509SStefano Zampini PetscValidLogicalCollectiveBool(mat, restrict_full, 5); 790457de7509SStefano Zampini PetscValidLogicalCollectiveBool(mat, reuse, 6); 790557de7509SStefano Zampini PetscValidLogicalCollectiveInt(mat, nis, 8); 79061ae86dd6SStefano Zampini PetscValidLogicalCollectiveInt(mat, nvecs, 10); 79071ae86dd6SStefano Zampini if (nvecs) { 790808401ef6SPierre Jolivet PetscCheck(nvecs <= 1, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Just 1 vector supported"); 79091ae86dd6SStefano Zampini PetscValidHeaderSpecific(nnsp_vec[0], VEC_CLASSID, 11); 79101ae86dd6SStefano Zampini } 791157de7509SStefano Zampini /* further checks */ 79129566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(mat, &local_mat)); 79139566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)local_mat, MATSEQDENSE, &isdense)); 79149de2952eSStefano Zampini /* XXX hack for multi_element */ 79159de2952eSStefano Zampini if (!isdense) PetscCall(MatConvert(local_mat, MATDENSE, MAT_INPLACE_MATRIX, &local_mat)); 79169de2952eSStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)local_mat, MATSEQDENSE, &isdense)); 79175f80ce2aSJacob Faibussowitsch PetscCheck(isdense, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE"); 79189de2952eSStefano Zampini 79199566063dSJacob Faibussowitsch PetscCall(MatGetSize(local_mat, &rows, &cols)); 79205f80ce2aSJacob Faibussowitsch PetscCheck(rows == cols, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Local MATIS matrices should be square"); 792157de7509SStefano Zampini if (reuse && *mat_n) { 792270cf5478SStefano Zampini PetscInt mrows, mcols, mnrows, mncols; 792357de7509SStefano Zampini PetscValidHeaderSpecific(*mat_n, MAT_CLASSID, 7); 79249566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)*mat_n, MATIS, &ismatis)); 79255f80ce2aSJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)*mat_n), PETSC_ERR_SUP, "Cannot reuse a matrix which is not of type MATIS"); 79269566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &mrows, &mcols)); 79279566063dSJacob Faibussowitsch PetscCall(MatGetSize(*mat_n, &mnrows, &mncols)); 792863a3b9bcSJacob Faibussowitsch PetscCheck(mrows == mnrows, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix! Wrong number of rows %" PetscInt_FMT " != %" PetscInt_FMT, mrows, mnrows); 792963a3b9bcSJacob Faibussowitsch PetscCheck(mcols == mncols, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix! Wrong number of cols %" PetscInt_FMT " != %" PetscInt_FMT, mcols, mncols); 793070cf5478SStefano Zampini } 79319566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(local_mat, &bs)); 7932064a246eSJacob Faibussowitsch PetscValidLogicalCollectiveInt(mat, bs, 1); 793357de7509SStefano Zampini 7934e7931f94SStefano Zampini /* prepare IS for sending if not provided */ 7935e7931f94SStefano Zampini if (!is_sends) { 79365f80ce2aSJacob Faibussowitsch PetscCheck(n_subdomains, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "You should specify either an IS or a target number of subdomains"); 79379566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISGetSubassemblingPattern(mat, &n_subdomains, 0, &is_sends_internal, NULL)); 7938c8587f34SStefano Zampini } else { 79399566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is_sends)); 7940e7931f94SStefano Zampini is_sends_internal = is_sends; 7941c8587f34SStefano Zampini } 7942e7931f94SStefano Zampini 7943e7931f94SStefano Zampini /* get comm */ 79449566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7945e7931f94SStefano Zampini 7946e7931f94SStefano Zampini /* compute number of sends */ 79479566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is_sends_internal, &i)); 79489566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(i, &n_sends)); 7949e7931f94SStefano Zampini 7950e7931f94SStefano Zampini /* compute number of receives */ 79519566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 79529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &iflags)); 79539566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(iflags, size)); 79549566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is_sends_internal, &is_indices)); 7955e7931f94SStefano Zampini for (i = 0; i < n_sends; i++) iflags[is_indices[i]] = 1; 79569566063dSJacob Faibussowitsch PetscCall(PetscGatherNumberOfMessages(comm, iflags, NULL, &n_recvs)); 79579566063dSJacob Faibussowitsch PetscCall(PetscFree(iflags)); 7958e7931f94SStefano Zampini 795928143c3dSStefano Zampini /* restrict comm if requested */ 79600a545947SLisandro Dalcin subcomm = NULL; 796128143c3dSStefano Zampini destroy_mat = PETSC_FALSE; 796228143c3dSStefano Zampini if (restrict_comm) { 7963779c1cceSStefano Zampini PetscMPIInt color, subcommsize; 7964779c1cceSStefano Zampini 796528143c3dSStefano Zampini color = 0; 796653a05cb3SStefano Zampini if (restrict_full) { 79676aad120cSJose E. Roman if (!n_recvs) color = 1; /* processes not receiving anything will not participate in new comm (full restriction) */ 796853a05cb3SStefano Zampini } else { 79696aad120cSJose 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 */ 797053a05cb3SStefano Zampini } 7971462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&color, &subcommsize, 1, MPI_INT, MPI_SUM, comm)); 7972e569e4e1SStefano Zampini subcommsize = size - subcommsize; 797328143c3dSStefano Zampini /* check if reuse has been requested */ 797457de7509SStefano Zampini if (reuse) { 797528143c3dSStefano Zampini if (*mat_n) { 797628143c3dSStefano Zampini PetscMPIInt subcommsize2; 79779566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n), &subcommsize2)); 79785f80ce2aSJacob Faibussowitsch PetscCheck(subcommsize == subcommsize2, PetscObjectComm((PetscObject)*mat_n), PETSC_ERR_PLIB, "Cannot reuse matrix! wrong subcomm size %d != %d", subcommsize, subcommsize2); 797928143c3dSStefano Zampini comm_n = PetscObjectComm((PetscObject)*mat_n); 798028143c3dSStefano Zampini } else { 798128143c3dSStefano Zampini comm_n = PETSC_COMM_SELF; 798228143c3dSStefano Zampini } 798328143c3dSStefano Zampini } else { /* MAT_INITIAL_MATRIX */ 7984779c1cceSStefano Zampini PetscMPIInt rank; 7985779c1cceSStefano Zampini 79869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 79879566063dSJacob Faibussowitsch PetscCall(PetscSubcommCreate(comm, &subcomm)); 79889566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetNumber(subcomm, 2)); 79899566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetTypeGeneral(subcomm, color, rank)); 7990306c2d5bSBarry Smith comm_n = PetscSubcommChild(subcomm); 799128143c3dSStefano Zampini } 799228143c3dSStefano Zampini /* flag to destroy *mat_n if not significative */ 799328143c3dSStefano Zampini if (color) destroy_mat = PETSC_TRUE; 799428143c3dSStefano Zampini } else { 799528143c3dSStefano Zampini comm_n = comm; 799628143c3dSStefano Zampini } 799728143c3dSStefano Zampini 7998e7931f94SStefano Zampini /* prepare send/receive buffers */ 79999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &ilengths_idxs)); 80009566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(ilengths_idxs, size)); 80019566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &ilengths_vals)); 80029566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(ilengths_vals, size)); 800348a46eb9SPierre Jolivet if (nis) PetscCall(PetscCalloc1(size, &ilengths_idxs_is)); 8004e7931f94SStefano Zampini 800528143c3dSStefano Zampini /* Get data from local matrices */ 8006e432b41dSStefano Zampini PetscCheck(isdense, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Subassembling of AIJ local matrices not yet implemented"); 8007e7931f94SStefano Zampini /* TODO: See below some guidelines on how to prepare the local buffers */ 8008e7931f94SStefano Zampini /* 8009e7931f94SStefano Zampini send_buffer_vals should contain the raw values of the local matrix 8010e7931f94SStefano Zampini send_buffer_idxs should contain: 8011e7931f94SStefano Zampini - MatType_PRIVATE type 8012e7931f94SStefano Zampini - PetscInt size_of_l2gmap 8013e7931f94SStefano Zampini - PetscInt global_row_indices[size_of_l2gmap] 8014e7931f94SStefano Zampini - PetscInt all_other_info_which_is_needed_to_compute_preallocation_and_set_values 8015e7931f94SStefano Zampini */ 8016e432b41dSStefano Zampini { 8017e432b41dSStefano Zampini ISLocalToGlobalMapping mapping; 8018e432b41dSStefano Zampini 80199566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(mat, &mapping, NULL)); 80209566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(local_mat, &send_buffer_vals)); 80219566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(mapping, &i)); 80229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(i + 2, &send_buffer_idxs)); 8023e7931f94SStefano Zampini send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE; 8024e7931f94SStefano Zampini send_buffer_idxs[1] = i; 80259566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(mapping, (const PetscInt **)&ptr_idxs)); 80269566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&send_buffer_idxs[2], ptr_idxs, i)); 80279566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(mapping, (const PetscInt **)&ptr_idxs)); 80289566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(i, &len)); 8029e7931f94SStefano Zampini for (i = 0; i < n_sends; i++) { 8030e7931f94SStefano Zampini ilengths_vals[is_indices[i]] = len * len; 8031e7931f94SStefano Zampini ilengths_idxs[is_indices[i]] = len + 2; 8032c8587f34SStefano Zampini } 8033c8587f34SStefano Zampini } 80349566063dSJacob Faibussowitsch PetscCall(PetscGatherMessageLengths2(comm, n_sends, n_recvs, ilengths_idxs, ilengths_vals, &onodes, &olengths_idxs, &olengths_vals)); 803528143c3dSStefano Zampini /* additional is (if any) */ 803628143c3dSStefano Zampini if (nis) { 803728143c3dSStefano Zampini PetscMPIInt psum; 803828143c3dSStefano Zampini PetscInt j; 803928143c3dSStefano Zampini for (j = 0, psum = 0; j < nis; j++) { 804028143c3dSStefano Zampini PetscInt plen; 80419566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isarray[j], &plen)); 80429566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(plen, &len)); 80436aad120cSJose E. Roman psum += len + 1; /* indices + length */ 804428143c3dSStefano Zampini } 80459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(psum, &send_buffer_idxs_is)); 804628143c3dSStefano Zampini for (j = 0, psum = 0; j < nis; j++) { 804728143c3dSStefano Zampini PetscInt plen; 804828143c3dSStefano Zampini const PetscInt *is_array_idxs; 80499566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isarray[j], &plen)); 805028143c3dSStefano Zampini send_buffer_idxs_is[psum] = plen; 80519566063dSJacob Faibussowitsch PetscCall(ISGetIndices(isarray[j], &is_array_idxs)); 80529566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&send_buffer_idxs_is[psum + 1], is_array_idxs, plen)); 80539566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(isarray[j], &is_array_idxs)); 80546aad120cSJose E. Roman psum += plen + 1; /* indices + length */ 805528143c3dSStefano Zampini } 8056ad540459SPierre Jolivet for (i = 0; i < n_sends; i++) ilengths_idxs_is[is_indices[i]] = psum; 80579566063dSJacob Faibussowitsch PetscCall(PetscGatherMessageLengths(comm, n_sends, n_recvs, ilengths_idxs_is, &onodes_is, &olengths_idxs_is)); 805828143c3dSStefano Zampini } 80599566063dSJacob Faibussowitsch PetscCall(MatISRestoreLocalMat(mat, &local_mat)); 806028143c3dSStefano Zampini 8061e7931f94SStefano Zampini buf_size_idxs = 0; 8062e7931f94SStefano Zampini buf_size_vals = 0; 806328143c3dSStefano Zampini buf_size_idxs_is = 0; 80641ae86dd6SStefano Zampini buf_size_vecs = 0; 8065e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 8066835f2295SStefano Zampini buf_size_idxs += olengths_idxs[i]; 8067835f2295SStefano Zampini buf_size_vals += olengths_vals[i]; 8068835f2295SStefano Zampini if (nis) buf_size_idxs_is += olengths_idxs_is[i]; 8069835f2295SStefano Zampini if (nvecs) buf_size_vecs += olengths_idxs[i]; 8070e7931f94SStefano Zampini } 80719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(buf_size_idxs, &recv_buffer_idxs)); 80729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(buf_size_vals, &recv_buffer_vals)); 80739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(buf_size_idxs_is, &recv_buffer_idxs_is)); 80749566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(buf_size_vecs, &recv_buffer_vecs)); 8075e7931f94SStefano Zampini 8076e7931f94SStefano Zampini /* get new tags for clean communications */ 80779566063dSJacob Faibussowitsch PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag_idxs)); 80789566063dSJacob Faibussowitsch PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag_vals)); 80799566063dSJacob Faibussowitsch PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag_idxs_is)); 80809566063dSJacob Faibussowitsch PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag_vecs)); 8081e7931f94SStefano Zampini 8082e7931f94SStefano Zampini /* allocate for requests */ 80839566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_sends, &send_req_idxs)); 80849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_sends, &send_req_vals)); 80859566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_sends, &send_req_idxs_is)); 80869566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_sends, &send_req_vecs)); 80879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_recvs, &recv_req_idxs)); 80889566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_recvs, &recv_req_vals)); 80899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_recvs, &recv_req_idxs_is)); 80909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_recvs, &recv_req_vecs)); 8091e7931f94SStefano Zampini 8092e7931f94SStefano Zampini /* communications */ 8093e7931f94SStefano Zampini ptr_idxs = recv_buffer_idxs; 8094e7931f94SStefano Zampini ptr_vals = recv_buffer_vals; 809528143c3dSStefano Zampini ptr_idxs_is = recv_buffer_idxs_is; 80961ae86dd6SStefano Zampini ptr_vecs = recv_buffer_vecs; 8097e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 8098e91c04dfSPierre Jolivet PetscCallMPI(MPIU_Irecv(ptr_idxs, olengths_idxs[i], MPIU_INT, onodes[i], tag_idxs, comm, &recv_req_idxs[i])); 8099e91c04dfSPierre Jolivet PetscCallMPI(MPIU_Irecv(ptr_vals, olengths_vals[i], MPIU_SCALAR, onodes[i], tag_vals, comm, &recv_req_vals[i])); 8100e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 8101e7931f94SStefano Zampini ptr_vals += olengths_vals[i]; 810228143c3dSStefano Zampini if (nis) { 8103e91c04dfSPierre Jolivet PetscCallMPI(MPIU_Irecv(ptr_idxs_is, olengths_idxs_is[i], MPIU_INT, onodes_is[i], tag_idxs_is, comm, &recv_req_idxs_is[i])); 810428143c3dSStefano Zampini ptr_idxs_is += olengths_idxs_is[i]; 810528143c3dSStefano Zampini } 81061ae86dd6SStefano Zampini if (nvecs) { 8107e91c04dfSPierre Jolivet PetscCallMPI(MPIU_Irecv(ptr_vecs, olengths_idxs[i] - 2, MPIU_SCALAR, onodes[i], tag_vecs, comm, &recv_req_vecs[i])); 81081ae86dd6SStefano Zampini ptr_vecs += olengths_idxs[i] - 2; 81091ae86dd6SStefano Zampini } 8110e7931f94SStefano Zampini } 8111e7931f94SStefano Zampini for (i = 0; i < n_sends; i++) { 811260b1fa21SPierre Jolivet PetscCall(PetscMPIIntCast(is_indices[i], &source_dest)); 811360b1fa21SPierre Jolivet PetscCallMPI(MPIU_Isend(send_buffer_idxs, ilengths_idxs[source_dest], MPIU_INT, source_dest, tag_idxs, comm, &send_req_idxs[i])); 811460b1fa21SPierre Jolivet PetscCallMPI(MPIU_Isend(send_buffer_vals, ilengths_vals[source_dest], MPIU_SCALAR, source_dest, tag_vals, comm, &send_req_vals[i])); 811560b1fa21SPierre Jolivet if (nis) PetscCallMPI(MPIU_Isend(send_buffer_idxs_is, ilengths_idxs_is[source_dest], MPIU_INT, source_dest, tag_idxs_is, comm, &send_req_idxs_is[i])); 81161ae86dd6SStefano Zampini if (nvecs) { 81179566063dSJacob Faibussowitsch PetscCall(VecGetArray(nnsp_vec[0], &send_buffer_vecs)); 811860b1fa21SPierre Jolivet PetscCallMPI(MPIU_Isend(send_buffer_vecs, ilengths_idxs[source_dest] - 2, MPIU_SCALAR, source_dest, tag_vecs, comm, &send_req_vecs[i])); 81191ae86dd6SStefano Zampini } 8120e7931f94SStefano Zampini } 81219566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is_sends_internal, &is_indices)); 81229566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_sends_internal)); 8123e7931f94SStefano Zampini 8124e7931f94SStefano Zampini /* assemble new l2g map */ 81259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_recvs, recv_req_idxs, MPI_STATUSES_IGNORE)); 8126e7931f94SStefano Zampini ptr_idxs = recv_buffer_idxs; 81279d30be91SStefano Zampini new_local_rows = 0; 8128e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 81299d30be91SStefano Zampini new_local_rows += *(ptr_idxs + 1); /* second element is the local size of the l2gmap */ 8130e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 8131e7931f94SStefano Zampini } 81329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(new_local_rows, &l2gmap_indices)); 8133e7931f94SStefano Zampini ptr_idxs = recv_buffer_idxs; 81349d30be91SStefano Zampini new_local_rows = 0; 8135e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 81369566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&l2gmap_indices[new_local_rows], ptr_idxs + 2, *(ptr_idxs + 1))); 81379d30be91SStefano Zampini new_local_rows += *(ptr_idxs + 1); /* second element is the local size of the l2gmap */ 8138e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 8139e7931f94SStefano Zampini } 81409566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&new_local_rows, l2gmap_indices)); 81419566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(comm_n, 1, new_local_rows, l2gmap_indices, PETSC_COPY_VALUES, &l2gmap)); 81429566063dSJacob Faibussowitsch PetscCall(PetscFree(l2gmap_indices)); 8143e7931f94SStefano Zampini 8144e7931f94SStefano Zampini /* infer new local matrix type from received local matrices type */ 8145e7931f94SStefano Zampini /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */ 8146e7931f94SStefano 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) */ 8147e7931f94SStefano Zampini if (n_recvs) { 814828143c3dSStefano Zampini MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0]; 8149e7931f94SStefano Zampini ptr_idxs = recv_buffer_idxs; 8150e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 8151e7931f94SStefano Zampini if ((PetscInt)new_local_type_private != *ptr_idxs) { 8152e7931f94SStefano Zampini new_local_type_private = MATAIJ_PRIVATE; 8153e7931f94SStefano Zampini break; 8154e7931f94SStefano Zampini } 8155e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 8156e7931f94SStefano Zampini } 8157e7931f94SStefano Zampini switch (new_local_type_private) { 815828143c3dSStefano Zampini case MATDENSE_PRIVATE: 8159e7931f94SStefano Zampini new_local_type = MATSEQAIJ; 8160e7931f94SStefano Zampini bs = 1; 8161e7931f94SStefano Zampini break; 8162e7931f94SStefano Zampini case MATAIJ_PRIVATE: 8163e7931f94SStefano Zampini new_local_type = MATSEQAIJ; 8164e7931f94SStefano Zampini bs = 1; 8165e7931f94SStefano Zampini break; 8166d71ae5a4SJacob Faibussowitsch case MATBAIJ_PRIVATE: 8167d71ae5a4SJacob Faibussowitsch new_local_type = MATSEQBAIJ; 8168d71ae5a4SJacob Faibussowitsch break; 8169d71ae5a4SJacob Faibussowitsch case MATSBAIJ_PRIVATE: 8170d71ae5a4SJacob Faibussowitsch new_local_type = MATSEQSBAIJ; 8171d71ae5a4SJacob Faibussowitsch break; 8172d71ae5a4SJacob Faibussowitsch default: 8173d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_SUP, "Unsupported private type %d in %s", new_local_type_private, PETSC_FUNCTION_NAME); 8174e7931f94SStefano Zampini } 8175ed8ed4edSstefano_zampini } else { /* by default, new_local_type is seqaij */ 8176ed8ed4edSstefano_zampini new_local_type = MATSEQAIJ; 817728143c3dSStefano Zampini bs = 1; 8178e7931f94SStefano Zampini } 8179e7931f94SStefano Zampini 818070cf5478SStefano Zampini /* create MATIS object if needed */ 818157de7509SStefano Zampini if (!reuse) { 81829566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &rows, &cols)); 81839566063dSJacob Faibussowitsch PetscCall(MatCreateIS(comm_n, bs, PETSC_DECIDE, PETSC_DECIDE, rows, cols, l2gmap, l2gmap, mat_n)); 818470cf5478SStefano Zampini } else { 818570cf5478SStefano Zampini /* it also destroys the local matrices */ 818657de7509SStefano Zampini if (*mat_n) { 81879566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*mat_n, l2gmap, l2gmap)); 818857de7509SStefano Zampini } else { /* this is a fake object */ 81899566063dSJacob Faibussowitsch PetscCall(MatCreateIS(comm_n, bs, PETSC_DECIDE, PETSC_DECIDE, rows, cols, l2gmap, l2gmap, mat_n)); 819057de7509SStefano Zampini } 819170cf5478SStefano Zampini } 81929566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*mat_n, &local_mat)); 81939566063dSJacob Faibussowitsch PetscCall(MatSetType(local_mat, new_local_type)); 81949d30be91SStefano Zampini 81959566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_recvs, recv_req_vals, MPI_STATUSES_IGNORE)); 81969d30be91SStefano Zampini 81979d30be91SStefano Zampini /* Global to local map of received indices */ 81989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(buf_size_idxs, &recv_buffer_idxs_local)); /* needed for values insertion */ 81999566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(l2gmap, IS_GTOLM_MASK, buf_size_idxs, recv_buffer_idxs, &i, recv_buffer_idxs_local)); 82009566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&l2gmap)); 82019d30be91SStefano Zampini 82029d30be91SStefano Zampini /* restore attributes -> type of incoming data and its size */ 82039d30be91SStefano Zampini buf_size_idxs = 0; 82049d30be91SStefano Zampini for (i = 0; i < n_recvs; i++) { 82059d30be91SStefano Zampini recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs]; 82069d30be91SStefano Zampini recv_buffer_idxs_local[buf_size_idxs + 1] = recv_buffer_idxs[buf_size_idxs + 1]; 8207835f2295SStefano Zampini buf_size_idxs += olengths_idxs[i]; 82089d30be91SStefano Zampini } 82099566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_buffer_idxs)); 82109d30be91SStefano Zampini 82119d30be91SStefano Zampini /* set preallocation */ 82129566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)local_mat, MATSEQDENSE, &newisdense)); 82139d30be91SStefano Zampini if (!newisdense) { 82140a545947SLisandro Dalcin PetscInt *new_local_nnz = NULL; 82159d30be91SStefano Zampini 82169d30be91SStefano Zampini ptr_idxs = recv_buffer_idxs_local; 821748a46eb9SPierre Jolivet if (n_recvs) PetscCall(PetscCalloc1(new_local_rows, &new_local_nnz)); 82189d30be91SStefano Zampini for (i = 0; i < n_recvs; i++) { 82199d30be91SStefano Zampini PetscInt j; 82209d30be91SStefano Zampini if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */ 8221ad540459SPierre Jolivet for (j = 0; j < *(ptr_idxs + 1); j++) new_local_nnz[*(ptr_idxs + 2 + j)] += *(ptr_idxs + 1); 82229d30be91SStefano Zampini } else { 82239d30be91SStefano Zampini /* TODO */ 82249d30be91SStefano Zampini } 82259d30be91SStefano Zampini ptr_idxs += olengths_idxs[i]; 82269d30be91SStefano Zampini } 82279d30be91SStefano Zampini if (new_local_nnz) { 82289d30be91SStefano Zampini for (i = 0; i < new_local_rows; i++) new_local_nnz[i] = PetscMin(new_local_nnz[i], new_local_rows); 82299566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(local_mat, 0, new_local_nnz)); 82309d30be91SStefano Zampini for (i = 0; i < new_local_rows; i++) new_local_nnz[i] /= bs; 82319566063dSJacob Faibussowitsch PetscCall(MatSeqBAIJSetPreallocation(local_mat, bs, 0, new_local_nnz)); 82329d30be91SStefano Zampini for (i = 0; i < new_local_rows; i++) new_local_nnz[i] = PetscMax(new_local_nnz[i] - i, 0); 82339566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(local_mat, bs, 0, new_local_nnz)); 82349d30be91SStefano Zampini } else { 82359566063dSJacob Faibussowitsch PetscCall(MatSetUp(local_mat)); 82369d30be91SStefano Zampini } 82379566063dSJacob Faibussowitsch PetscCall(PetscFree(new_local_nnz)); 82389d30be91SStefano Zampini } else { 82399566063dSJacob Faibussowitsch PetscCall(MatSetUp(local_mat)); 82409d30be91SStefano Zampini } 8241e7931f94SStefano Zampini 8242e7931f94SStefano Zampini /* set values */ 8243e7931f94SStefano Zampini ptr_vals = recv_buffer_vals; 82449d30be91SStefano Zampini ptr_idxs = recv_buffer_idxs_local; 8245e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 8246e7931f94SStefano Zampini if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */ 82479566063dSJacob Faibussowitsch PetscCall(MatSetOption(local_mat, MAT_ROW_ORIENTED, PETSC_FALSE)); 82489566063dSJacob Faibussowitsch PetscCall(MatSetValues(local_mat, *(ptr_idxs + 1), ptr_idxs + 2, *(ptr_idxs + 1), ptr_idxs + 2, ptr_vals, ADD_VALUES)); 82499566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(local_mat, MAT_FLUSH_ASSEMBLY)); 82509566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(local_mat, MAT_FLUSH_ASSEMBLY)); 82519566063dSJacob Faibussowitsch PetscCall(MatSetOption(local_mat, MAT_ROW_ORIENTED, PETSC_TRUE)); 825228143c3dSStefano Zampini } else { 825328143c3dSStefano Zampini /* TODO */ 8254e7931f94SStefano Zampini } 8255e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 8256e7931f94SStefano Zampini ptr_vals += olengths_vals[i]; 8257e7931f94SStefano Zampini } 82589566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(local_mat, MAT_FINAL_ASSEMBLY)); 82599566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(local_mat, MAT_FINAL_ASSEMBLY)); 82609566063dSJacob Faibussowitsch PetscCall(MatISRestoreLocalMat(*mat_n, &local_mat)); 82619566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat_n, MAT_FINAL_ASSEMBLY)); 82629566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat_n, MAT_FINAL_ASSEMBLY)); 82639566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_buffer_vals)); 8264e7931f94SStefano Zampini 8265dfd14d43SStefano Zampini #if 0 826628143c3dSStefano Zampini if (!restrict_comm) { /* check */ 8267e7931f94SStefano Zampini Vec lvec,rvec; 8268e7931f94SStefano Zampini PetscReal infty_error; 8269e7931f94SStefano Zampini 82709566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(mat,&rvec,&lvec)); 82719566063dSJacob Faibussowitsch PetscCall(VecSetRandom(rvec,NULL)); 82729566063dSJacob Faibussowitsch PetscCall(MatMult(mat,rvec,lvec)); 82739566063dSJacob Faibussowitsch PetscCall(VecScale(lvec,-1.0)); 82749566063dSJacob Faibussowitsch PetscCall(MatMultAdd(*mat_n,rvec,lvec,lvec)); 82759566063dSJacob Faibussowitsch PetscCall(VecNorm(lvec,NORM_INFINITY,&infty_error)); 82769566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error)); 82779566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rvec)); 82789566063dSJacob Faibussowitsch PetscCall(VecDestroy(&lvec)); 8279e7931f94SStefano Zampini } 828028143c3dSStefano Zampini #endif 8281e7931f94SStefano Zampini 828228143c3dSStefano Zampini /* assemble new additional is (if any) */ 828328143c3dSStefano Zampini if (nis) { 828428143c3dSStefano Zampini PetscInt **temp_idxs, *count_is, j, psum; 828528143c3dSStefano Zampini 82869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_recvs, recv_req_idxs_is, MPI_STATUSES_IGNORE)); 82879566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nis, &count_is)); 828828143c3dSStefano Zampini ptr_idxs = recv_buffer_idxs_is; 828928143c3dSStefano Zampini psum = 0; 829028143c3dSStefano Zampini for (i = 0; i < n_recvs; i++) { 829128143c3dSStefano Zampini for (j = 0; j < nis; j++) { 829228143c3dSStefano Zampini PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */ 829328143c3dSStefano Zampini count_is[j] += plen; /* increment counting of buffer for j-th IS */ 829428143c3dSStefano Zampini psum += plen; 829528143c3dSStefano Zampini ptr_idxs += plen + 1; /* shift pointer to received data */ 829628143c3dSStefano Zampini } 829728143c3dSStefano Zampini } 82989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nis, &temp_idxs)); 82999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(psum, &temp_idxs[0])); 83008e3a54c0SPierre Jolivet for (i = 1; i < nis; i++) temp_idxs[i] = PetscSafePointerPlusOffset(temp_idxs[i - 1], count_is[i - 1]); 83019566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(count_is, nis)); 830228143c3dSStefano Zampini ptr_idxs = recv_buffer_idxs_is; 830328143c3dSStefano Zampini for (i = 0; i < n_recvs; i++) { 830428143c3dSStefano Zampini for (j = 0; j < nis; j++) { 830528143c3dSStefano Zampini PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */ 83069566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&temp_idxs[j][count_is[j]], ptr_idxs + 1, plen)); 830728143c3dSStefano Zampini count_is[j] += plen; /* increment starting point of buffer for j-th IS */ 830828143c3dSStefano Zampini ptr_idxs += plen + 1; /* shift pointer to received data */ 830928143c3dSStefano Zampini } 831028143c3dSStefano Zampini } 831128143c3dSStefano Zampini for (i = 0; i < nis; i++) { 83129566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isarray[i])); 83139566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&count_is[i], temp_idxs[i])); 83149566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm_n, count_is[i], temp_idxs[i], PETSC_COPY_VALUES, &isarray[i])); 831528143c3dSStefano Zampini } 83169566063dSJacob Faibussowitsch PetscCall(PetscFree(count_is)); 83179566063dSJacob Faibussowitsch PetscCall(PetscFree(temp_idxs[0])); 83189566063dSJacob Faibussowitsch PetscCall(PetscFree(temp_idxs)); 831928143c3dSStefano Zampini } 8320e7931f94SStefano Zampini /* free workspace */ 83219566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_buffer_idxs_is)); 83229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_sends, send_req_idxs, MPI_STATUSES_IGNORE)); 83239566063dSJacob Faibussowitsch PetscCall(PetscFree(send_buffer_idxs)); 83249566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_sends, send_req_vals, MPI_STATUSES_IGNORE)); 8325e7931f94SStefano Zampini if (isdense) { 83269566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(mat, &local_mat)); 83279566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(local_mat, &send_buffer_vals)); 83289566063dSJacob Faibussowitsch PetscCall(MatISRestoreLocalMat(mat, &local_mat)); 8329e7931f94SStefano Zampini } else { 83309566063dSJacob Faibussowitsch /* PetscCall(PetscFree(send_buffer_vals)); */ 8331e7931f94SStefano Zampini } 833228143c3dSStefano Zampini if (nis) { 83339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_sends, send_req_idxs_is, MPI_STATUSES_IGNORE)); 83349566063dSJacob Faibussowitsch PetscCall(PetscFree(send_buffer_idxs_is)); 833528143c3dSStefano Zampini } 83361ae86dd6SStefano Zampini 83371ae86dd6SStefano Zampini if (nvecs) { 83389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_recvs, recv_req_vecs, MPI_STATUSES_IGNORE)); 83399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_sends, send_req_vecs, MPI_STATUSES_IGNORE)); 83409566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(nnsp_vec[0], &send_buffer_vecs)); 83419566063dSJacob Faibussowitsch PetscCall(VecDestroy(&nnsp_vec[0])); 83429566063dSJacob Faibussowitsch PetscCall(VecCreate(comm_n, &nnsp_vec[0])); 83439566063dSJacob Faibussowitsch PetscCall(VecSetSizes(nnsp_vec[0], new_local_rows, PETSC_DECIDE)); 83449566063dSJacob Faibussowitsch PetscCall(VecSetType(nnsp_vec[0], VECSTANDARD)); 83451ae86dd6SStefano Zampini /* set values */ 83461ae86dd6SStefano Zampini ptr_vals = recv_buffer_vecs; 83471ae86dd6SStefano Zampini ptr_idxs = recv_buffer_idxs_local; 83489566063dSJacob Faibussowitsch PetscCall(VecGetArray(nnsp_vec[0], &send_buffer_vecs)); 83491ae86dd6SStefano Zampini for (i = 0; i < n_recvs; i++) { 83501ae86dd6SStefano Zampini PetscInt j; 8351ad540459SPierre Jolivet for (j = 0; j < *(ptr_idxs + 1); j++) send_buffer_vecs[*(ptr_idxs + 2 + j)] += *(ptr_vals + j); 83521ae86dd6SStefano Zampini ptr_idxs += olengths_idxs[i]; 83531ae86dd6SStefano Zampini ptr_vals += olengths_idxs[i] - 2; 83541ae86dd6SStefano Zampini } 83559566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(nnsp_vec[0], &send_buffer_vecs)); 83569566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(nnsp_vec[0])); 83579566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(nnsp_vec[0])); 83581ae86dd6SStefano Zampini } 83591ae86dd6SStefano Zampini 83609566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_buffer_vecs)); 83619566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_buffer_idxs_local)); 83629566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_req_idxs)); 83639566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_req_vals)); 83649566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_req_vecs)); 83659566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_req_idxs_is)); 83669566063dSJacob Faibussowitsch PetscCall(PetscFree(send_req_idxs)); 83679566063dSJacob Faibussowitsch PetscCall(PetscFree(send_req_vals)); 83689566063dSJacob Faibussowitsch PetscCall(PetscFree(send_req_vecs)); 83699566063dSJacob Faibussowitsch PetscCall(PetscFree(send_req_idxs_is)); 83709566063dSJacob Faibussowitsch PetscCall(PetscFree(ilengths_vals)); 83719566063dSJacob Faibussowitsch PetscCall(PetscFree(ilengths_idxs)); 83729566063dSJacob Faibussowitsch PetscCall(PetscFree(olengths_vals)); 83739566063dSJacob Faibussowitsch PetscCall(PetscFree(olengths_idxs)); 83749566063dSJacob Faibussowitsch PetscCall(PetscFree(onodes)); 837528143c3dSStefano Zampini if (nis) { 83769566063dSJacob Faibussowitsch PetscCall(PetscFree(ilengths_idxs_is)); 83779566063dSJacob Faibussowitsch PetscCall(PetscFree(olengths_idxs_is)); 83789566063dSJacob Faibussowitsch PetscCall(PetscFree(onodes_is)); 837928143c3dSStefano Zampini } 83809566063dSJacob Faibussowitsch PetscCall(PetscSubcommDestroy(&subcomm)); 83816aad120cSJose E. Roman if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not participate */ 83829566063dSJacob Faibussowitsch PetscCall(MatDestroy(mat_n)); 838348a46eb9SPierre Jolivet for (i = 0; i < nis; i++) PetscCall(ISDestroy(&isarray[i])); 83841ae86dd6SStefano Zampini if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */ 83859566063dSJacob Faibussowitsch PetscCall(VecDestroy(&nnsp_vec[0])); 83861ae86dd6SStefano Zampini } 838753a05cb3SStefano Zampini *mat_n = NULL; 838828143c3dSStefano Zampini } 83893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8390e7931f94SStefano Zampini } 8391a57a6d2fSStefano Zampini 839212edc857SStefano Zampini /* temporary hack into ksp private data structure */ 8393af0996ceSBarry Smith #include <petsc/private/kspimpl.h> 839412edc857SStefano Zampini 83959de2952eSStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc, Mat coarse_submat) 8396d71ae5a4SJacob Faibussowitsch { 8397c8587f34SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 8398c8587f34SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 83999de2952eSStefano Zampini PCBDDCGraph graph = pcbddc->mat_graph; 84009de2952eSStefano Zampini Mat coarse_mat, coarse_mat_is; 84011ae86dd6SStefano Zampini Mat coarsedivudotp = NULL; 84021e0482f5SStefano Zampini Mat coarseG, t_coarse_mat_is; 84039881197aSStefano Zampini MatNullSpace CoarseNullSpace = NULL; 840420a2ab83SStefano Zampini ISLocalToGlobalMapping coarse_islg; 84054f819b78SStefano Zampini IS coarse_is, *isarray, corners; 84066e683305SStefano Zampini PetscInt i, im_active = -1, active_procs = -1; 840730368db7SStefano Zampini PetscInt nis, nisdofs, nisneu, nisvert; 84089de2952eSStefano Zampini PetscInt coarse_eqs_per_proc, coarsening_ratio; 8409f9eb5b7dSStefano Zampini PC pc_temp; 8410c8587f34SStefano Zampini PCType coarse_pc_type; 8411c8587f34SStefano Zampini KSPType coarse_ksp_type; 8412f9eb5b7dSStefano Zampini PetscBool multilevel_requested, multilevel_allowed; 84139de2952eSStefano Zampini PetscBool coarse_reuse, multi_element = graph->multi_element; 84141e0482f5SStefano Zampini PetscInt ncoarse, nedcfield; 841568457ee5SStefano Zampini PetscBool compute_vecs = PETSC_FALSE; 841622bc73bbSStefano Zampini PetscScalar *array; 841757de7509SStefano Zampini MatReuse coarse_mat_reuse; 841857de7509SStefano Zampini PetscBool restr, full_restr, have_void; 8419e569e4e1SStefano Zampini PetscMPIInt size; 8420fdc09c96SStefano Zampini 8421c8587f34SStefano Zampini PetscFunctionBegin; 84229566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_CoarseSetUp[pcbddc->current_level], pc, 0, 0, 0)); 8423c8587f34SStefano Zampini /* Assign global numbering to coarse dofs */ 842468457ee5SStefano 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 */ 8425fa7f1dd8SStefano Zampini PetscInt ocoarse_size; 84265a75c04eSSatish Balay compute_vecs = PETSC_TRUE; 84277de4f681Sstefano_zampini 84287de4f681Sstefano_zampini pcbddc->new_primal_space = PETSC_TRUE; 8429fa7f1dd8SStefano Zampini ocoarse_size = pcbddc->coarse_size; 84309566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->global_primal_indices)); 84319566063dSJacob Faibussowitsch PetscCall(PCBDDCComputePrimalNumbering(pc, &pcbddc->coarse_size, &pcbddc->global_primal_indices)); 8432f4ddd8eeSStefano Zampini /* see if we can avoid some work */ 8433fa7f1dd8SStefano Zampini if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */ 843451bea450SStefano Zampini /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */ 843551bea450SStefano Zampini if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) { 84369566063dSJacob Faibussowitsch PetscCall(KSPReset(pcbddc->coarse_ksp)); 8437fa7f1dd8SStefano Zampini coarse_reuse = PETSC_FALSE; 8438fa7f1dd8SStefano Zampini } else { /* we can safely reuse already computed coarse matrix */ 8439fa7f1dd8SStefano Zampini coarse_reuse = PETSC_TRUE; 8440f4ddd8eeSStefano Zampini } 8441fa7f1dd8SStefano Zampini } else { /* there's no coarse ksp, so we need to create the coarse matrix too */ 8442fa7f1dd8SStefano Zampini coarse_reuse = PETSC_FALSE; 8443f4ddd8eeSStefano Zampini } 844470cf5478SStefano Zampini /* reset any subassembling information */ 844548a46eb9SPierre Jolivet if (!coarse_reuse || pcbddc->recompute_topography) PetscCall(ISDestroy(&pcbddc->coarse_subassembling)); 84466e683305SStefano Zampini } else { /* primal space is unchanged, so we can reuse coarse matrix */ 8447fa7f1dd8SStefano Zampini coarse_reuse = PETSC_TRUE; 8448f4ddd8eeSStefano Zampini } 844957de7509SStefano Zampini if (coarse_reuse && pcbddc->coarse_ksp) { 84509566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(pcbddc->coarse_ksp, &coarse_mat, NULL)); 84519566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coarse_mat)); 845257de7509SStefano Zampini coarse_mat_reuse = MAT_REUSE_MATRIX; 845318a45a71SStefano Zampini } else { 845457de7509SStefano Zampini coarse_mat = NULL; 845557de7509SStefano Zampini coarse_mat_reuse = MAT_INITIAL_MATRIX; 84566e683305SStefano Zampini } 8457e7931f94SStefano Zampini 8458abbbba34SStefano Zampini /* creates temporary l2gmap and IS for coarse indexes */ 84599566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), pcbddc->local_primal_size, pcbddc->global_primal_indices, PETSC_COPY_VALUES, &coarse_is)); 84609566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(coarse_is, &coarse_islg)); 8461abbbba34SStefano Zampini 8462abbbba34SStefano Zampini /* creates temporary MATIS object for coarse matrix */ 84639de2952eSStefano Zampini PetscCall(MatCreate(PetscObjectComm((PetscObject)pc), &t_coarse_mat_is)); 84649de2952eSStefano Zampini PetscCall(MatSetType(t_coarse_mat_is, MATIS)); 84659de2952eSStefano Zampini PetscCall(MatSetSizes(t_coarse_mat_is, PETSC_DECIDE, PETSC_DECIDE, pcbddc->coarse_size, pcbddc->coarse_size)); 84669de2952eSStefano Zampini PetscCall(MatISSetAllowRepeated(t_coarse_mat_is, PETSC_TRUE)); 84679de2952eSStefano Zampini PetscCall(MatSetLocalToGlobalMapping(t_coarse_mat_is, coarse_islg, coarse_islg)); 84689de2952eSStefano Zampini PetscCall(MatISSetLocalMat(t_coarse_mat_is, coarse_submat)); 84699566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(t_coarse_mat_is, MAT_FINAL_ASSEMBLY)); 84709566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(t_coarse_mat_is, MAT_FINAL_ASSEMBLY)); 84719de2952eSStefano Zampini PetscCall(MatViewFromOptions(t_coarse_mat_is, (PetscObject)pc, "-pc_bddc_coarse_mat_is_view")); 8472abbbba34SStefano Zampini 847357de7509SStefano Zampini /* count "active" (i.e. with positive local size) and "void" processes */ 8474f4f49eeaSPierre Jolivet im_active = !!pcis->n; 8475462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&im_active, &active_procs, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)pc))); 847657de7509SStefano Zampini 847714f0bfb9SStefano Zampini /* determine number of processes partecipating to coarse solver and compute subassembling pattern */ 847828d58a37SPierre Jolivet /* restr : whether we want to exclude senders (which are not receivers) from the subassembling pattern */ 847957de7509SStefano Zampini /* full_restr : just use the receivers from the subassembling pattern */ 84809566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size)); 848157de7509SStefano Zampini coarse_mat_is = NULL; 848257de7509SStefano Zampini multilevel_allowed = PETSC_FALSE; 848357de7509SStefano Zampini multilevel_requested = PETSC_FALSE; 8484e569e4e1SStefano Zampini coarse_eqs_per_proc = PetscMin(PetscMax(pcbddc->coarse_size, 1), pcbddc->coarse_eqs_per_proc); 84859de2952eSStefano Zampini if (coarse_eqs_per_proc < 0 || size == 1) coarse_eqs_per_proc = PetscMax(pcbddc->coarse_size, 1); 848657de7509SStefano Zampini if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE; 8487e569e4e1SStefano Zampini if (pcbddc->coarse_size <= pcbddc->coarse_eqs_limit) multilevel_requested = PETSC_FALSE; 84889de2952eSStefano Zampini coarsening_ratio = multi_element ? 1 : pcbddc->coarsening_ratio; 848957de7509SStefano Zampini if (multilevel_requested) { 84909de2952eSStefano Zampini ncoarse = active_procs / coarsening_ratio; 849157de7509SStefano Zampini restr = PETSC_FALSE; 849257de7509SStefano Zampini full_restr = PETSC_FALSE; 849357de7509SStefano Zampini } else { 8494e569e4e1SStefano Zampini ncoarse = pcbddc->coarse_size / coarse_eqs_per_proc + !!(pcbddc->coarse_size % coarse_eqs_per_proc); 849557de7509SStefano Zampini restr = PETSC_TRUE; 849657de7509SStefano Zampini full_restr = PETSC_TRUE; 849757de7509SStefano Zampini } 8498e569e4e1SStefano Zampini if (!pcbddc->coarse_size || size == 1) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE; 849957de7509SStefano Zampini ncoarse = PetscMax(1, ncoarse); 850057de7509SStefano Zampini if (!pcbddc->coarse_subassembling) { 85019de2952eSStefano Zampini if (coarsening_ratio > 1) { 8502bb360cb4SStefano Zampini if (multilevel_requested) { 85039566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISGetSubassemblingPattern(pc->pmat, &ncoarse, pcbddc->coarse_adj_red, &pcbddc->coarse_subassembling, &have_void)); 8504bb360cb4SStefano Zampini } else { 85059566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISGetSubassemblingPattern(t_coarse_mat_is, &ncoarse, pcbddc->coarse_adj_red, &pcbddc->coarse_subassembling, &have_void)); 8506bb360cb4SStefano Zampini } 8507a198735bSStefano Zampini } else { 85087de4f681Sstefano_zampini PetscMPIInt rank; 850928d58a37SPierre Jolivet 85109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc), &rank)); 8511835f2295SStefano Zampini have_void = (active_procs == size) ? PETSC_FALSE : PETSC_TRUE; 85129566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)pc), 1, rank, 1, &pcbddc->coarse_subassembling)); 8513a198735bSStefano Zampini } 851457de7509SStefano Zampini } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */ 851557de7509SStefano Zampini PetscInt psum; 851657de7509SStefano Zampini if (pcbddc->coarse_ksp) psum = 1; 851757de7509SStefano Zampini else psum = 0; 8518462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&psum, &ncoarse, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)pc))); 8519075e25bcSStefano Zampini have_void = ncoarse < size ? PETSC_TRUE : PETSC_FALSE; 852057de7509SStefano Zampini } 852157de7509SStefano Zampini /* determine if we can go multilevel */ 852257de7509SStefano Zampini if (multilevel_requested) { 852357de7509SStefano Zampini if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */ 852457de7509SStefano Zampini else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */ 852557de7509SStefano Zampini } 852657de7509SStefano Zampini if (multilevel_allowed && have_void) restr = PETSC_TRUE; 852757de7509SStefano Zampini 8528e4d548c7SStefano Zampini /* dump subassembling pattern */ 852948a46eb9SPierre Jolivet if (pcbddc->dbg_flag && multilevel_allowed) PetscCall(ISView(pcbddc->coarse_subassembling, pcbddc->dbg_viewer)); 85306e683305SStefano Zampini /* compute dofs splitting and neumann boundaries for coarse dofs */ 85311e0482f5SStefano Zampini nedcfield = -1; 85324f819b78SStefano Zampini corners = NULL; 85338966356dSPierre Jolivet if (multilevel_allowed && !coarse_reuse && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal || pcbddc->nedclocal || pcbddc->corner_selected)) { /* protects from unneeded computations */ 85346e683305SStefano Zampini PetscInt *tidxs, *tidxs2, nout, tsize, i; 85356e683305SStefano Zampini const PetscInt *idxs; 85366e683305SStefano Zampini ISLocalToGlobalMapping tmap; 85376e683305SStefano Zampini 85386e683305SStefano Zampini /* create map between primal indices (in local representative ordering) and local primal numbering */ 85399566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PETSC_COMM_SELF, 1, pcbddc->local_primal_size, pcbddc->primal_indices_local_idxs, PETSC_COPY_VALUES, &tmap)); 85406e683305SStefano Zampini /* allocate space for temporary storage */ 85419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->local_primal_size, &tidxs)); 85429566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->local_primal_size, &tidxs2)); 85436e683305SStefano Zampini /* allocate for IS array */ 85446e683305SStefano Zampini nisdofs = pcbddc->n_ISForDofsLocal; 85451e0482f5SStefano Zampini if (pcbddc->nedclocal) { 85461e0482f5SStefano Zampini if (pcbddc->nedfield > -1) { 85471e0482f5SStefano Zampini nedcfield = pcbddc->nedfield; 85481e0482f5SStefano Zampini } else { 85491e0482f5SStefano Zampini nedcfield = 0; 855063a3b9bcSJacob Faibussowitsch PetscCheck(!nisdofs, PetscObjectComm((PetscObject)pc), PETSC_ERR_PLIB, "This should not happen (%" PetscInt_FMT ")", nisdofs); 85511e0482f5SStefano Zampini nisdofs = 1; 85521e0482f5SStefano Zampini } 85531e0482f5SStefano Zampini } 85546e683305SStefano Zampini nisneu = !!pcbddc->NeumannBoundariesLocal; 855527b6a85dSStefano Zampini nisvert = 0; /* nisvert is not used */ 855630368db7SStefano Zampini nis = nisdofs + nisneu + nisvert; 85579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nis, &isarray)); 85586e683305SStefano Zampini /* dofs splitting */ 85596e683305SStefano Zampini for (i = 0; i < nisdofs; i++) { 85609566063dSJacob Faibussowitsch /* PetscCall(ISView(pcbddc->ISForDofsLocal[i],0)); */ 85611e0482f5SStefano Zampini if (nedcfield != i) { 85629566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->ISForDofsLocal[i], &tsize)); 85639566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->ISForDofsLocal[i], &idxs)); 85649566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(tmap, IS_GTOLM_DROP, tsize, idxs, &nout, tidxs)); 85659566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->ISForDofsLocal[i], &idxs)); 85661e0482f5SStefano Zampini } else { 85679566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->nedclocal, &tsize)); 85689566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->nedclocal, &idxs)); 85699566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(tmap, IS_GTOLM_DROP, tsize, idxs, &nout, tidxs)); 857063a3b9bcSJacob Faibussowitsch PetscCheck(tsize == nout, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Failed when mapping coarse nedelec field! %" PetscInt_FMT " != %" PetscInt_FMT, tsize, nout); 85719566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->nedclocal, &idxs)); 85721e0482f5SStefano Zampini } 85739566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(coarse_islg, nout, tidxs, tidxs2)); 85749566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), nout, tidxs2, PETSC_COPY_VALUES, &isarray[i])); 85759566063dSJacob Faibussowitsch /* PetscCall(ISView(isarray[i],0)); */ 85766e683305SStefano Zampini } 85776e683305SStefano Zampini /* neumann boundaries */ 85786e683305SStefano Zampini if (pcbddc->NeumannBoundariesLocal) { 85799566063dSJacob Faibussowitsch /* PetscCall(ISView(pcbddc->NeumannBoundariesLocal,0)); */ 85809566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->NeumannBoundariesLocal, &tsize)); 85819566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->NeumannBoundariesLocal, &idxs)); 85829566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(tmap, IS_GTOLM_DROP, tsize, idxs, &nout, tidxs)); 85839566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->NeumannBoundariesLocal, &idxs)); 85849566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(coarse_islg, nout, tidxs, tidxs2)); 85859566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), nout, tidxs2, PETSC_COPY_VALUES, &isarray[nisdofs])); 85869566063dSJacob Faibussowitsch /* PetscCall(ISView(isarray[nisdofs],0)); */ 85876e683305SStefano Zampini } 85884f819b78SStefano Zampini /* coordinates */ 85894f819b78SStefano Zampini if (pcbddc->corner_selected) { 85909566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &corners)); 85919566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(corners, &tsize)); 85929566063dSJacob Faibussowitsch PetscCall(ISGetIndices(corners, &idxs)); 85939566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(tmap, IS_GTOLM_DROP, tsize, idxs, &nout, tidxs)); 859463a3b9bcSJacob Faibussowitsch PetscCheck(tsize == nout, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Failed when mapping corners! %" PetscInt_FMT " != %" PetscInt_FMT, tsize, nout); 85959566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(corners, &idxs)); 85969566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &corners)); 85979566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(coarse_islg, nout, tidxs, tidxs2)); 85989566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), nout, tidxs2, PETSC_COPY_VALUES, &corners)); 85994f819b78SStefano Zampini } 86009566063dSJacob Faibussowitsch PetscCall(PetscFree(tidxs)); 86019566063dSJacob Faibussowitsch PetscCall(PetscFree(tidxs2)); 86029566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&tmap)); 86036e683305SStefano Zampini } else { 86046e683305SStefano Zampini nis = 0; 86056e683305SStefano Zampini nisdofs = 0; 86066e683305SStefano Zampini nisneu = 0; 860730368db7SStefano Zampini nisvert = 0; 86086e683305SStefano Zampini isarray = NULL; 86096e683305SStefano Zampini } 86106e683305SStefano Zampini /* destroy no longer needed map */ 86119566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&coarse_islg)); 86126e683305SStefano Zampini 861357de7509SStefano Zampini /* subassemble */ 861457de7509SStefano Zampini if (multilevel_allowed) { 86151ae86dd6SStefano Zampini Vec vp[1]; 86161ae86dd6SStefano Zampini PetscInt nvecs = 0; 86179de2952eSStefano Zampini PetscBool reuse; 86181ae86dd6SStefano Zampini 86191ae86dd6SStefano Zampini vp[0] = NULL; 86209de2952eSStefano Zampini /* XXX HDIV also */ 86211ae86dd6SStefano Zampini if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */ 86229566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pc), &vp[0])); 86239566063dSJacob Faibussowitsch PetscCall(VecSetSizes(vp[0], pcbddc->local_primal_size, PETSC_DECIDE)); 86249566063dSJacob Faibussowitsch PetscCall(VecSetType(vp[0], VECSTANDARD)); 86251ae86dd6SStefano Zampini nvecs = 1; 86261ae86dd6SStefano Zampini 86271ae86dd6SStefano Zampini if (pcbddc->divudotp) { 8628a198735bSStefano Zampini Mat B, loc_divudotp; 86291ae86dd6SStefano Zampini Vec v, p; 86301ae86dd6SStefano Zampini IS dummy; 86311ae86dd6SStefano Zampini PetscInt np; 86321ae86dd6SStefano Zampini 86339566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pcbddc->divudotp, &loc_divudotp)); 86349566063dSJacob Faibussowitsch PetscCall(MatGetSize(loc_divudotp, &np, NULL)); 86359566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, np, 0, 1, &dummy)); 86369566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(loc_divudotp, dummy, pcis->is_B_local, MAT_INITIAL_MATRIX, &B)); 86379566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(B, &v, &p)); 86389566063dSJacob Faibussowitsch PetscCall(VecSet(p, 1.)); 86399566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(B, p, v)); 86409566063dSJacob Faibussowitsch PetscCall(VecDestroy(&p)); 86419566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 86429566063dSJacob Faibussowitsch PetscCall(VecGetArray(vp[0], &array)); 86439566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_P, array)); 86449566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->coarse_phi_B, v, pcbddc->vec1_P)); 86459566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_P)); 86469566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(vp[0], &array)); 86479566063dSJacob Faibussowitsch PetscCall(ISDestroy(&dummy)); 86489566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 864974e2c79eSStefano Zampini } 86501ae86dd6SStefano Zampini } 86519de2952eSStefano Zampini if (coarse_mat) reuse = PETSC_TRUE; 86529de2952eSStefano Zampini else reuse = PETSC_FALSE; 86539de2952eSStefano Zampini if (multi_element) { 86549de2952eSStefano Zampini /* XXX divudotp */ 86559de2952eSStefano Zampini PetscCall(MatISSetAllowRepeated(t_coarse_mat_is, PETSC_FALSE)); 86569de2952eSStefano Zampini PetscCall(PetscObjectReference((PetscObject)t_coarse_mat_is)); 86579de2952eSStefano Zampini coarse_mat_is = t_coarse_mat_is; 86589de2952eSStefano Zampini } else { 8659462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &reuse, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 86609de2952eSStefano Zampini if (reuse) { 86619566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISSubassemble(t_coarse_mat_is, pcbddc->coarse_subassembling, 0, restr, full_restr, PETSC_TRUE, &coarse_mat, nis, isarray, nvecs, vp)); 866274e2c79eSStefano Zampini } else { 86639566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISSubassemble(t_coarse_mat_is, pcbddc->coarse_subassembling, 0, restr, full_restr, PETSC_FALSE, &coarse_mat_is, nis, isarray, nvecs, vp)); 86641ae86dd6SStefano Zampini } 86651ae86dd6SStefano Zampini if (vp[0]) { /* vp[0] could have been placed on a different set of processes */ 86661683a169SBarry Smith PetscScalar *arraym; 86671683a169SBarry Smith const PetscScalar *arrayv; 86681ae86dd6SStefano Zampini PetscInt nl; 86699566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vp[0], &nl)); 86709566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, 1, nl, NULL, &coarsedivudotp)); 86719566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(coarsedivudotp, &arraym)); 86729566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vp[0], &arrayv)); 86739566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(arraym, arrayv, nl)); 86749566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vp[0], &arrayv)); 86759566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(coarsedivudotp, &arraym)); 86769566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vp[0])); 8677a198735bSStefano Zampini } else { 86789566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, 0, 0, 1, NULL, &coarsedivudotp)); 86791ae86dd6SStefano Zampini } 86809de2952eSStefano Zampini } 86811ae86dd6SStefano Zampini } else { 86829de2952eSStefano 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)); 86839de2952eSStefano Zampini else { 86849de2952eSStefano Zampini PetscCall(PetscObjectReference((PetscObject)t_coarse_mat_is)); 86859de2952eSStefano Zampini coarse_mat_is = t_coarse_mat_is; 86869de2952eSStefano Zampini } 86876e683305SStefano Zampini } 868857de7509SStefano Zampini if (coarse_mat_is || coarse_mat) { 868957de7509SStefano Zampini if (!multilevel_allowed) { 86909566063dSJacob Faibussowitsch PetscCall(MatConvert(coarse_mat_is, MATAIJ, coarse_mat_reuse, &coarse_mat)); 86916e683305SStefano Zampini } else { 869257de7509SStefano Zampini /* if this matrix is present, it means we are not reusing the coarse matrix */ 869357de7509SStefano Zampini if (coarse_mat_is) { 869428b400f6SJacob Faibussowitsch PetscCheck(!coarse_mat, PetscObjectComm((PetscObject)coarse_mat_is), PETSC_ERR_PLIB, "This should not happen"); 86959566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coarse_mat_is)); 869657de7509SStefano Zampini coarse_mat = coarse_mat_is; 869757de7509SStefano Zampini } 8698779c1cceSStefano Zampini } 8699779c1cceSStefano Zampini } 87009566063dSJacob Faibussowitsch PetscCall(MatDestroy(&t_coarse_mat_is)); 87019566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_mat_is)); 87026e683305SStefano Zampini 87036e683305SStefano Zampini /* create local to global scatters for coarse problem */ 870468457ee5SStefano Zampini if (compute_vecs) { 87056e683305SStefano Zampini PetscInt lrows; 87069566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->coarse_vec)); 870757de7509SStefano Zampini if (coarse_mat) { 87089566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(coarse_mat, &lrows, NULL)); 87096e683305SStefano Zampini } else { 87106e683305SStefano Zampini lrows = 0; 87116e683305SStefano Zampini } 87129566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pc), &pcbddc->coarse_vec)); 87139566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pcbddc->coarse_vec, lrows, PETSC_DECIDE)); 87149566063dSJacob Faibussowitsch PetscCall(VecSetType(pcbddc->coarse_vec, coarse_mat ? coarse_mat->defaultvectype : VECSTANDARD)); 87159566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->coarse_loc_to_glob)); 87169566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(pcbddc->vec1_P, NULL, pcbddc->coarse_vec, coarse_is, &pcbddc->coarse_loc_to_glob)); 87176e683305SStefano Zampini } 87189566063dSJacob Faibussowitsch PetscCall(ISDestroy(&coarse_is)); 8719c8587f34SStefano Zampini 8720f9eb5b7dSStefano Zampini /* set defaults for coarse KSP and PC */ 8721f9eb5b7dSStefano Zampini if (multilevel_allowed) { 8722f9eb5b7dSStefano Zampini coarse_ksp_type = KSPRICHARDSON; 8723f9eb5b7dSStefano Zampini coarse_pc_type = PCBDDC; 8724f9eb5b7dSStefano Zampini } else { 8725f9eb5b7dSStefano Zampini coarse_ksp_type = KSPPREONLY; 8726f9eb5b7dSStefano Zampini coarse_pc_type = PCREDUNDANT; 8727c8587f34SStefano Zampini } 8728c8587f34SStefano Zampini 87296e683305SStefano Zampini /* print some info if requested */ 87306e683305SStefano Zampini if (pcbddc->dbg_flag) { 87316e683305SStefano Zampini if (!multilevel_allowed) { 87329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 87336e683305SStefano Zampini if (multilevel_requested) { 87349de2952eSStefano 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)); 87356e683305SStefano Zampini } else if (pcbddc->max_levels) { 873663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Maximum number of requested levels reached (%" PetscInt_FMT ")\n", pcbddc->max_levels)); 87376e683305SStefano Zampini } 87389566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 87396e683305SStefano Zampini } 87406e683305SStefano Zampini } 87416e683305SStefano Zampini 87421e0482f5SStefano Zampini /* communicate coarse discrete gradient */ 87431e0482f5SStefano Zampini coarseG = NULL; 87441e0482f5SStefano Zampini if (pcbddc->nedcG && multilevel_allowed) { 87451e0482f5SStefano Zampini MPI_Comm ccomm; 87461e0482f5SStefano Zampini if (coarse_mat) { 87471e0482f5SStefano Zampini ccomm = PetscObjectComm((PetscObject)coarse_mat); 87481e0482f5SStefano Zampini } else { 87491e0482f5SStefano Zampini ccomm = MPI_COMM_NULL; 87501e0482f5SStefano Zampini } 87519566063dSJacob Faibussowitsch PetscCall(MatMPIAIJRestrict(pcbddc->nedcG, ccomm, &coarseG)); 87521e0482f5SStefano Zampini } 87531e0482f5SStefano Zampini 8754f9eb5b7dSStefano Zampini /* create the coarse KSP object only once with defaults */ 875557de7509SStefano Zampini if (coarse_mat) { 875628d58a37SPierre Jolivet PetscBool isredundant, isbddc, force, valid; 87576a1308c2SStefano Zampini PetscViewer dbg_viewer = NULL; 8758b94d7dedSBarry Smith PetscBool isset, issym, isher, isspd; 87597274672aSStefano Zampini 87606e683305SStefano Zampini if (pcbddc->dbg_flag) { 876157de7509SStefano Zampini dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat)); 87629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIAddTab(dbg_viewer, 2 * pcbddc->current_level)); 87636e683305SStefano Zampini } 8764f9eb5b7dSStefano Zampini if (!pcbddc->coarse_ksp) { 8765312be037SStefano Zampini char prefix[256], str_level[16]; 8766e604994aSStefano Zampini size_t len; 87671e0482f5SStefano Zampini 87689566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)coarse_mat), &pcbddc->coarse_ksp)); 87693821be0aSBarry Smith PetscCall(KSPSetNestLevel(pcbddc->coarse_ksp, pc->kspnestlevel)); 87709566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(pcbddc->coarse_ksp, pc->erroriffailure)); 87719566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp, (PetscObject)pc, 1)); 8772fb842aefSJose E. Roman PetscCall(KSPSetTolerances(pcbddc->coarse_ksp, PETSC_CURRENT, PETSC_CURRENT, PETSC_CURRENT, 1)); 87739566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(pcbddc->coarse_ksp, coarse_mat, coarse_mat)); 87749566063dSJacob Faibussowitsch PetscCall(KSPSetType(pcbddc->coarse_ksp, coarse_ksp_type)); 87759566063dSJacob Faibussowitsch PetscCall(KSPSetNormType(pcbddc->coarse_ksp, KSP_NORM_NONE)); 87769566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &pc_temp)); 87771e0482f5SStefano Zampini /* TODO is this logic correct? should check for coarse_mat type */ 87789566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, coarse_pc_type)); 8779e604994aSStefano Zampini /* prefix */ 8780c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(prefix, "", sizeof(prefix))); 8781c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(str_level, "", sizeof(str_level))); 8782e604994aSStefano Zampini if (!pcbddc->current_level) { 87839566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(prefix, ((PetscObject)pc)->prefix, sizeof(prefix))); 87849566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, "pc_bddc_coarse_", sizeof(prefix))); 8785c8587f34SStefano Zampini } else { 87869566063dSJacob Faibussowitsch PetscCall(PetscStrlen(((PetscObject)pc)->prefix, &len)); 8787312be037SStefano Zampini if (pcbddc->current_level > 1) len -= 3; /* remove "lX_" with X level number */ 8788312be037SStefano Zampini if (pcbddc->current_level > 10) len -= 1; /* remove another char from level number */ 8789a126751eSBarry Smith /* Nonstandard use of PetscStrncpy() to copy only a portion of the string */ 87909566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(prefix, ((PetscObject)pc)->prefix, len + 1)); 8791835f2295SStefano Zampini PetscCall(PetscSNPrintf(str_level, sizeof(str_level), "l%" PetscInt_FMT "_", pcbddc->current_level)); 87929566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, str_level, sizeof(prefix))); 8793e604994aSStefano Zampini } 87949566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(pcbddc->coarse_ksp, prefix)); 87953e3c6dadSStefano Zampini /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */ 87969566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLevel(pc_temp, pcbddc->current_level + 1)); 87979566063dSJacob Faibussowitsch PetscCall(PCBDDCSetCoarseningRatio(pc_temp, pcbddc->coarsening_ratio)); 87989566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLevels(pc_temp, pcbddc->max_levels)); 8799f9eb5b7dSStefano Zampini /* allow user customization */ 88009566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(pcbddc->coarse_ksp)); 8801e569e4e1SStefano Zampini /* get some info after set from options */ 88029566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &pc_temp)); 880328d58a37SPierre Jolivet /* multilevel cannot be done with coarse PC different from BDDC, NN, HPDDM, unless forced to */ 880428d58a37SPierre Jolivet force = PETSC_FALSE; 88059566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)pc_temp)->prefix, "-pc_type_forced", &force, NULL)); 88069566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)pc_temp, &valid, PCBDDC, PCNN, PCHPDDM, "")); 88079566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp, PCBDDC, &isbddc)); 880828d58a37SPierre Jolivet if (multilevel_allowed && !force && !valid) { 8809e569e4e1SStefano Zampini isbddc = PETSC_TRUE; 88109566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCBDDC)); 88119566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLevel(pc_temp, pcbddc->current_level + 1)); 88129566063dSJacob Faibussowitsch PetscCall(PCBDDCSetCoarseningRatio(pc_temp, pcbddc->coarsening_ratio)); 88139566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLevels(pc_temp, pcbddc->max_levels)); 88144f819b78SStefano Zampini if (pc_temp->ops->setfromoptions) { /* need to setfromoptions again, skipping the pc_type */ 8815d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)pc_temp); 8816dbbe0bcdSBarry Smith PetscCall((*pc_temp->ops->setfromoptions)(pc_temp, PetscOptionsObject)); 8817dbbe0bcdSBarry Smith PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)pc_temp, PetscOptionsObject)); 8818d0609cedSBarry Smith PetscOptionsEnd(); 88194f819b78SStefano Zampini pc_temp->setfromoptionscalled++; 88204f819b78SStefano Zampini } 8821e569e4e1SStefano Zampini } 88223e3c6dadSStefano Zampini } 88233e3c6dadSStefano Zampini /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */ 88249566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &pc_temp)); 88253e3c6dadSStefano Zampini if (nisdofs) { 88269566063dSJacob Faibussowitsch PetscCall(PCBDDCSetDofsSplitting(pc_temp, nisdofs, isarray)); 882748a46eb9SPierre Jolivet for (i = 0; i < nisdofs; i++) PetscCall(ISDestroy(&isarray[i])); 88283e3c6dadSStefano Zampini } 88293e3c6dadSStefano Zampini if (nisneu) { 88309566063dSJacob Faibussowitsch PetscCall(PCBDDCSetNeumannBoundaries(pc_temp, isarray[nisdofs])); 88319566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isarray[nisdofs])); 8832312be037SStefano Zampini } 883330368db7SStefano Zampini if (nisvert) { 88349566063dSJacob Faibussowitsch PetscCall(PCBDDCSetPrimalVerticesIS(pc_temp, isarray[nis - 1])); 88359566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isarray[nis - 1])); 883630368db7SStefano Zampini } 88371baa6e33SBarry Smith if (coarseG) PetscCall(PCBDDCSetDiscreteGradient(pc_temp, coarseG, 1, nedcfield, PETSC_FALSE, PETSC_TRUE)); 8838f9eb5b7dSStefano Zampini 8839f9eb5b7dSStefano Zampini /* get some info after set from options */ 88409566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp, PCBDDC, &isbddc)); 88414f819b78SStefano Zampini 8842b76f3995Sstefano_zampini /* multilevel can only be requested via -pc_bddc_levels or PCBDDCSetLevels */ 884348a46eb9SPierre Jolivet if (isbddc && !multilevel_allowed) PetscCall(PCSetType(pc_temp, coarse_pc_type)); 884428d58a37SPierre Jolivet /* multilevel cannot be done with coarse PC different from BDDC, NN, HPDDM, unless forced to */ 884528d58a37SPierre Jolivet force = PETSC_FALSE; 88469566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)pc_temp)->prefix, "-pc_type_forced", &force, NULL)); 88479566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)pc_temp, &valid, PCBDDC, PCNN, PCHPDDM, "")); 884848a46eb9SPierre Jolivet if (multilevel_requested && multilevel_allowed && !valid && !force) PetscCall(PCSetType(pc_temp, PCBDDC)); 88499566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp, PCREDUNDANT, &isredundant)); 88504f3a063dSStefano Zampini if (isredundant) { 88514f3a063dSStefano Zampini KSP inner_ksp; 88524f3a063dSStefano Zampini PC inner_pc; 88539326c5c6Sstefano_zampini 88549566063dSJacob Faibussowitsch PetscCall(PCRedundantGetKSP(pc_temp, &inner_ksp)); 88559566063dSJacob Faibussowitsch PetscCall(KSPGetPC(inner_ksp, &inner_pc)); 88564f3a063dSStefano Zampini } 8857f9eb5b7dSStefano Zampini 885857de7509SStefano Zampini /* parameters which miss an API */ 88599566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp, PCBDDC, &isbddc)); 886057de7509SStefano Zampini if (isbddc) { 8861720d30f9SStefano Zampini PC_BDDC *pcbddc_coarse = (PC_BDDC *)pc_temp->data; 88627274672aSStefano Zampini 8863720d30f9SStefano Zampini pcbddc_coarse->detect_disconnected = PETSC_TRUE; 886457de7509SStefano Zampini pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc; 8865e569e4e1SStefano Zampini pcbddc_coarse->coarse_eqs_limit = pcbddc->coarse_eqs_limit; 886627b6a85dSStefano Zampini pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null; 886727b6a85dSStefano Zampini if (pcbddc_coarse->benign_saddle_point) { 8868a198735bSStefano Zampini Mat coarsedivudotp_is; 8869a198735bSStefano Zampini ISLocalToGlobalMapping l2gmap, rl2g, cl2g; 8870a198735bSStefano Zampini IS row, col; 8871a198735bSStefano Zampini const PetscInt *gidxs; 8872a198735bSStefano Zampini PetscInt n, st, M, N; 8873a198735bSStefano Zampini 88749566063dSJacob Faibussowitsch PetscCall(MatGetSize(coarsedivudotp, &n, NULL)); 88759566063dSJacob Faibussowitsch PetscCallMPI(MPI_Scan(&n, &st, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)coarse_mat))); 8876a198735bSStefano Zampini st = st - n; 88779566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)coarse_mat), 1, st, 1, &row)); 88789566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(coarse_mat, &l2gmap, NULL)); 88799566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(l2gmap, &n)); 88809566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(l2gmap, &gidxs)); 88819566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat), n, gidxs, PETSC_COPY_VALUES, &col)); 88829566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(l2gmap, &gidxs)); 88839566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(row, &rl2g)); 88849566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(col, &cl2g)); 88859566063dSJacob Faibussowitsch PetscCall(ISGetSize(row, &M)); 88869566063dSJacob Faibussowitsch PetscCall(MatGetSize(coarse_mat, &N, NULL)); 88879566063dSJacob Faibussowitsch PetscCall(ISDestroy(&row)); 88889566063dSJacob Faibussowitsch PetscCall(ISDestroy(&col)); 88899566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)coarse_mat), &coarsedivudotp_is)); 88909566063dSJacob Faibussowitsch PetscCall(MatSetType(coarsedivudotp_is, MATIS)); 88919566063dSJacob Faibussowitsch PetscCall(MatSetSizes(coarsedivudotp_is, PETSC_DECIDE, PETSC_DECIDE, M, N)); 88929566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(coarsedivudotp_is, rl2g, cl2g)); 88939566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 88949566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 88959566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(coarsedivudotp_is, coarsedivudotp)); 88969566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarsedivudotp)); 88979566063dSJacob Faibussowitsch PetscCall(PCBDDCSetDivergenceMat(pc_temp, coarsedivudotp_is, PETSC_FALSE, NULL)); 88989566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarsedivudotp_is)); 8899720d30f9SStefano Zampini pcbddc_coarse->adaptive_userdefined = PETSC_TRUE; 8900bd2a564bSStefano Zampini if (pcbddc->adaptive_threshold[0] == 0.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE; 8901720d30f9SStefano Zampini } 8902d4d8cf7bSStefano Zampini } 89039881197aSStefano Zampini 89043301b35fSStefano Zampini /* propagate symmetry info of coarse matrix */ 89059566063dSJacob Faibussowitsch PetscCall(MatSetOption(coarse_mat, MAT_STRUCTURALLY_SYMMETRIC, PETSC_TRUE)); 8906b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(pc->pmat, &isset, &issym)); 8907b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(coarse_mat, MAT_SYMMETRIC, issym)); 8908b94d7dedSBarry Smith PetscCall(MatIsHermitianKnown(pc->pmat, &isset, &isher)); 8909b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(coarse_mat, MAT_HERMITIAN, isher)); 8910b94d7dedSBarry Smith PetscCall(MatIsSPDKnown(pc->pmat, &isset, &isspd)); 8911b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(coarse_mat, MAT_SPD, isspd)); 8912b94d7dedSBarry Smith 891348a46eb9SPierre Jolivet if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) PetscCall(MatSetOption(coarse_mat, MAT_SPD, PETSC_TRUE)); 89146e683305SStefano Zampini /* set operators */ 89159566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(coarse_mat, (PetscObject)pc, "-pc_bddc_coarse_mat_view")); 89169566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(coarse_mat, ((PetscObject)pcbddc->coarse_ksp)->prefix)); 89179566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(pcbddc->coarse_ksp, coarse_mat, coarse_mat)); 89181baa6e33SBarry Smith if (pcbddc->dbg_flag) PetscCall(PetscViewerASCIISubtractTab(dbg_viewer, 2 * pcbddc->current_level)); 89196e683305SStefano Zampini } 89209566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarseG)); 89219566063dSJacob Faibussowitsch PetscCall(PetscFree(isarray)); 8922b1ecc7b1SStefano Zampini #if 0 8923b9b85e73SStefano Zampini { 8924b9b85e73SStefano Zampini PetscViewer viewer; 8925b9b85e73SStefano Zampini char filename[256]; 8926a364092eSJacob Faibussowitsch PetscCall(PetscSNPrintf(filename, PETSC_STATIC_ARRAY_LENGTH(filename), "coarse_mat_level%d.m",pcbddc->current_level)); 89279566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer)); 89289566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB)); 89299566063dSJacob Faibussowitsch PetscCall(MatView(coarse_mat,viewer)); 89309566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 89319566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 8932b9b85e73SStefano Zampini } 8933b9b85e73SStefano Zampini #endif 8934f9eb5b7dSStefano Zampini 89354f819b78SStefano Zampini if (corners) { 89364f819b78SStefano Zampini Vec gv; 89374f819b78SStefano Zampini IS is; 89384f819b78SStefano Zampini const PetscInt *idxs; 89394f819b78SStefano Zampini PetscInt i, d, N, n, cdim = pcbddc->mat_graph->cdim; 89404f819b78SStefano Zampini PetscScalar *coords; 89414f819b78SStefano Zampini 894228b400f6SJacob Faibussowitsch PetscCheck(pcbddc->mat_graph->cloc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing local coordinates"); 89439566063dSJacob Faibussowitsch PetscCall(VecGetSize(pcbddc->coarse_vec, &N)); 89449566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(pcbddc->coarse_vec, &n)); 89459566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pcbddc->coarse_vec), &gv)); 89469566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(gv, cdim)); 89479566063dSJacob Faibussowitsch PetscCall(VecSetSizes(gv, n * cdim, N * cdim)); 89489566063dSJacob Faibussowitsch PetscCall(VecSetType(gv, VECSTANDARD)); 89499566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(gv)); 89509566063dSJacob Faibussowitsch PetscCall(VecSet(gv, PETSC_MAX_REAL)); /* we only propagate coordinates from vertices constraints */ 89514f819b78SStefano Zampini 89529566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &is)); 89539566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &n)); 89549566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, &idxs)); 89559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n * cdim, &coords)); 89564f819b78SStefano Zampini for (i = 0; i < n; i++) { 8957ad540459SPierre Jolivet for (d = 0; d < cdim; d++) coords[cdim * i + d] = pcbddc->mat_graph->coords[cdim * idxs[i] + d]; 89584f819b78SStefano Zampini } 89599566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, &idxs)); 89609566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &is)); 89614f819b78SStefano Zampini 89629566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(corners, &n)); 89639566063dSJacob Faibussowitsch PetscCall(ISGetIndices(corners, &idxs)); 89649566063dSJacob Faibussowitsch PetscCall(VecSetValuesBlocked(gv, n, idxs, coords, INSERT_VALUES)); 89659566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(corners, &idxs)); 89669566063dSJacob Faibussowitsch PetscCall(PetscFree(coords)); 89679566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(gv)); 89689566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(gv)); 89699566063dSJacob Faibussowitsch PetscCall(VecGetArray(gv, &coords)); 89704f819b78SStefano Zampini if (pcbddc->coarse_ksp) { 89714f819b78SStefano Zampini PC coarse_pc; 89724f819b78SStefano Zampini PetscBool isbddc; 89734f819b78SStefano Zampini 89749566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &coarse_pc)); 89759566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)coarse_pc, PCBDDC, &isbddc)); 89764f819b78SStefano Zampini if (isbddc) { /* coarse coordinates have PETSC_MAX_REAL, specific for BDDC */ 89774f819b78SStefano Zampini PetscReal *realcoords; 89784f819b78SStefano Zampini 89799566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(gv, &n)); 89804f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX) 89819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &realcoords)); 89824f819b78SStefano Zampini for (i = 0; i < n; i++) realcoords[i] = PetscRealPart(coords[i]); 89834f819b78SStefano Zampini #else 89844f819b78SStefano Zampini realcoords = coords; 89854f819b78SStefano Zampini #endif 89869566063dSJacob Faibussowitsch PetscCall(PCSetCoordinates(coarse_pc, cdim, n / cdim, realcoords)); 89874f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX) 89889566063dSJacob Faibussowitsch PetscCall(PetscFree(realcoords)); 89894f819b78SStefano Zampini #endif 89904f819b78SStefano Zampini } 89914f819b78SStefano Zampini } 89929566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(gv, &coords)); 89939566063dSJacob Faibussowitsch PetscCall(VecDestroy(&gv)); 89944f819b78SStefano Zampini } 89959566063dSJacob Faibussowitsch PetscCall(ISDestroy(&corners)); 89964f819b78SStefano Zampini 899798a51de6SStefano Zampini if (pcbddc->coarse_ksp) { 899898a51de6SStefano Zampini Vec crhs, csol; 899904708bb6SStefano Zampini 90009566063dSJacob Faibussowitsch PetscCall(KSPGetSolution(pcbddc->coarse_ksp, &csol)); 90019566063dSJacob Faibussowitsch PetscCall(KSPGetRhs(pcbddc->coarse_ksp, &crhs)); 9002f4f49eeaSPierre Jolivet if (!csol) PetscCall(MatCreateVecs(coarse_mat, &pcbddc->coarse_ksp->vec_sol, NULL)); 9003f4f49eeaSPierre Jolivet if (!crhs) PetscCall(MatCreateVecs(coarse_mat, NULL, &pcbddc->coarse_ksp->vec_rhs)); 9004b0f5fe93SStefano Zampini } 90059566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarsedivudotp)); 9006b0f5fe93SStefano Zampini 9007b0f5fe93SStefano Zampini /* compute null space for coarse solver if the benign trick has been requested */ 9008b0f5fe93SStefano Zampini if (pcbddc->benign_null) { 90099566063dSJacob Faibussowitsch PetscCall(VecSet(pcbddc->vec1_P, 0.)); 901048a46eb9SPierre 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)); 90119566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(pcbddc->vec1_P)); 90129566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(pcbddc->vec1_P)); 90139566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob, pcbddc->vec1_P, pcbddc->coarse_vec, INSERT_VALUES, SCATTER_FORWARD)); 90149566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob, pcbddc->vec1_P, pcbddc->coarse_vec, INSERT_VALUES, SCATTER_FORWARD)); 9015b0f5fe93SStefano Zampini if (coarse_mat) { 9016b0f5fe93SStefano Zampini Vec nullv; 9017b0f5fe93SStefano Zampini PetscScalar *array, *array2; 9018b0f5fe93SStefano Zampini PetscInt nl; 9019b0f5fe93SStefano Zampini 90209566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(coarse_mat, &nullv, NULL)); 90219566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(nullv, &nl)); 90229566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(pcbddc->coarse_vec, (const PetscScalar **)&array)); 90239566063dSJacob Faibussowitsch PetscCall(VecGetArray(nullv, &array2)); 90249566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(array2, array, nl)); 90259566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(nullv, &array2)); 90269566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(pcbddc->coarse_vec, (const PetscScalar **)&array)); 90279566063dSJacob Faibussowitsch PetscCall(VecNormalize(nullv, NULL)); 90289566063dSJacob Faibussowitsch PetscCall(MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat), PETSC_FALSE, 1, &nullv, &CoarseNullSpace)); 90299566063dSJacob Faibussowitsch PetscCall(VecDestroy(&nullv)); 9030b0f5fe93SStefano Zampini } 9031b0f5fe93SStefano Zampini } 90329566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_CoarseSetUp[pcbddc->current_level], pc, 0, 0, 0)); 9033b0f5fe93SStefano Zampini 90349566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_CoarseSolver[pcbddc->current_level], pc, 0, 0, 0)); 9035b0f5fe93SStefano Zampini if (pcbddc->coarse_ksp) { 9036b0f5fe93SStefano Zampini PetscBool ispreonly; 9037b0f5fe93SStefano Zampini 9038b0f5fe93SStefano Zampini if (CoarseNullSpace) { 9039b0f5fe93SStefano Zampini PetscBool isnull; 90407c625d9fSStefano Zampini 90419566063dSJacob Faibussowitsch PetscCall(MatNullSpaceTest(CoarseNullSpace, coarse_mat, &isnull)); 90421baa6e33SBarry Smith if (isnull) PetscCall(MatSetNullSpace(coarse_mat, CoarseNullSpace)); 9043bef83e63SStefano Zampini /* TODO: add local nullspaces (if any) */ 9044b0f5fe93SStefano Zampini } 9045b0f5fe93SStefano Zampini /* setup coarse ksp */ 90469566063dSJacob Faibussowitsch PetscCall(KSPSetUp(pcbddc->coarse_ksp)); 9047cbcc2c2aSStefano Zampini /* Check coarse problem if in debug mode or if solving with an iterative method */ 90489566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp, KSPPREONLY, &ispreonly)); 90496e683305SStefano Zampini if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates)) { 9050c8587f34SStefano Zampini KSP check_ksp; 90512b510759SStefano Zampini KSPType check_ksp_type; 9052c8587f34SStefano Zampini PC check_pc; 90536e683305SStefano Zampini Vec check_vec, coarse_vec; 90546a1308c2SStefano Zampini PetscReal abs_infty_error, infty_error, lambda_min = 1.0, lambda_max = 1.0; 90552b510759SStefano Zampini PetscInt its; 90566e683305SStefano Zampini PetscBool compute_eigs; 90576e683305SStefano Zampini PetscReal *eigs_r, *eigs_c; 90586e683305SStefano Zampini PetscInt neigs; 90598e185a42SStefano Zampini const char *prefix; 9060c8587f34SStefano Zampini 90612b510759SStefano Zampini /* Create ksp object suitable for estimation of extreme eigenvalues */ 90629566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp), &check_ksp)); 90633821be0aSBarry Smith PetscCall(KSPSetNestLevel(check_ksp, pc->kspnestlevel)); 90649566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)check_ksp, (PetscObject)pcbddc->coarse_ksp, 0)); 90659566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(pcbddc->coarse_ksp, PETSC_FALSE)); 90669566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(check_ksp, coarse_mat, coarse_mat)); 9067fb842aefSJose E. Roman PetscCall(KSPSetTolerances(check_ksp, 1.e-12, 1.e-12, PETSC_CURRENT, pcbddc->coarse_size)); 9068e4d548c7SStefano Zampini /* prevent from setup unneeded object */ 90699566063dSJacob Faibussowitsch PetscCall(KSPGetPC(check_ksp, &check_pc)); 90709566063dSJacob Faibussowitsch PetscCall(PCSetType(check_pc, PCNONE)); 90712b510759SStefano Zampini if (ispreonly) { 90722b510759SStefano Zampini check_ksp_type = KSPPREONLY; 90736e683305SStefano Zampini compute_eigs = PETSC_FALSE; 90742b510759SStefano Zampini } else { 9075cbcc2c2aSStefano Zampini check_ksp_type = KSPGMRES; 90766e683305SStefano Zampini compute_eigs = PETSC_TRUE; 9077c8587f34SStefano Zampini } 90789566063dSJacob Faibussowitsch PetscCall(KSPSetType(check_ksp, check_ksp_type)); 90799566063dSJacob Faibussowitsch PetscCall(KSPSetComputeSingularValues(check_ksp, compute_eigs)); 90809566063dSJacob Faibussowitsch PetscCall(KSPSetComputeEigenvalues(check_ksp, compute_eigs)); 90819566063dSJacob Faibussowitsch PetscCall(KSPGMRESSetRestart(check_ksp, pcbddc->coarse_size + 1)); 90829566063dSJacob Faibussowitsch PetscCall(KSPGetOptionsPrefix(pcbddc->coarse_ksp, &prefix)); 90839566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(check_ksp, prefix)); 90849566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(check_ksp, "check_")); 90859566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(check_ksp)); 90869566063dSJacob Faibussowitsch PetscCall(KSPSetUp(check_ksp)); 90879566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &check_pc)); 90889566063dSJacob Faibussowitsch PetscCall(KSPSetPC(check_ksp, check_pc)); 9089c8587f34SStefano Zampini /* create random vec */ 90909566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(coarse_mat, &coarse_vec, &check_vec)); 90919566063dSJacob Faibussowitsch PetscCall(VecSetRandom(check_vec, NULL)); 90929566063dSJacob Faibussowitsch PetscCall(MatMult(coarse_mat, check_vec, coarse_vec)); 9093c8587f34SStefano Zampini /* solve coarse problem */ 90949566063dSJacob Faibussowitsch PetscCall(KSPSolve(check_ksp, coarse_vec, coarse_vec)); 90959566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(check_ksp, pc, coarse_vec)); 9096cbcc2c2aSStefano Zampini /* set eigenvalue estimation if preonly has not been requested */ 90976e683305SStefano Zampini if (compute_eigs) { 90989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->coarse_size + 1, &eigs_r)); 90999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->coarse_size + 1, &eigs_c)); 91009566063dSJacob Faibussowitsch PetscCall(KSPComputeEigenvalues(check_ksp, pcbddc->coarse_size + 1, eigs_r, eigs_c, &neigs)); 91011ae86dd6SStefano Zampini if (neigs) { 91026e683305SStefano Zampini lambda_max = eigs_r[neigs - 1]; 91036e683305SStefano Zampini lambda_min = eigs_r[0]; 91046e683305SStefano Zampini if (pcbddc->use_coarse_estimates) { 91052701bc32SStefano Zampini if (lambda_max >= lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */ 91069566063dSJacob Faibussowitsch PetscCall(KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp, lambda_max + PETSC_SMALL, lambda_min)); 91079566063dSJacob Faibussowitsch PetscCall(KSPRichardsonSetScale(pcbddc->coarse_ksp, 2.0 / (lambda_max + lambda_min))); 9108cbcc2c2aSStefano Zampini } 9109c8587f34SStefano Zampini } 9110c8587f34SStefano Zampini } 91111ae86dd6SStefano Zampini } 9112cbcc2c2aSStefano Zampini 9113c8587f34SStefano Zampini /* check coarse problem residual error */ 91146e683305SStefano Zampini if (pcbddc->dbg_flag) { 91156e683305SStefano Zampini PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp)); 91169566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIAddTab(dbg_viewer, 2 * (pcbddc->current_level + 1))); 91179566063dSJacob Faibussowitsch PetscCall(VecAXPY(check_vec, -1.0, coarse_vec)); 91189566063dSJacob Faibussowitsch PetscCall(VecNorm(check_vec, NORM_INFINITY, &infty_error)); 91199566063dSJacob Faibussowitsch PetscCall(MatMult(coarse_mat, check_vec, coarse_vec)); 91209566063dSJacob Faibussowitsch PetscCall(VecNorm(coarse_vec, NORM_INFINITY, &abs_infty_error)); 91219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(dbg_viewer, "Coarse problem details (use estimates %d)\n", pcbddc->use_coarse_estimates)); 9122f4f49eeaSPierre Jolivet PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)pcbddc->coarse_ksp, dbg_viewer)); 912357508eceSPierre Jolivet PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)check_pc, dbg_viewer)); 912463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(dbg_viewer, "Coarse problem exact infty_error : %1.6e\n", (double)infty_error)); 912563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(dbg_viewer, "Coarse problem residual infty_error: %1.6e\n", (double)abs_infty_error)); 912648a46eb9SPierre Jolivet if (CoarseNullSpace) PetscCall(PetscViewerASCIIPrintf(dbg_viewer, "Coarse problem is singular\n")); 91276e683305SStefano Zampini if (compute_eigs) { 91286e683305SStefano Zampini PetscReal lambda_max_s, lambda_min_s; 9129b03ebc13SStefano Zampini KSPConvergedReason reason; 91309566063dSJacob Faibussowitsch PetscCall(KSPGetType(check_ksp, &check_ksp_type)); 91319566063dSJacob Faibussowitsch PetscCall(KSPGetIterationNumber(check_ksp, &its)); 91329566063dSJacob Faibussowitsch PetscCall(KSPGetConvergedReason(check_ksp, &reason)); 91339566063dSJacob Faibussowitsch PetscCall(KSPComputeExtremeSingularValues(check_ksp, &lambda_max_s, &lambda_min_s)); 913463a3b9bcSJacob 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)); 913548a46eb9SPierre Jolivet for (i = 0; i < neigs; i++) PetscCall(PetscViewerASCIIPrintf(dbg_viewer, "%1.6e %1.6ei\n", (double)eigs_r[i], (double)eigs_c[i])); 91366e683305SStefano Zampini } 91379566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(dbg_viewer)); 91389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISubtractTab(dbg_viewer, 2 * (pcbddc->current_level + 1))); 91396e683305SStefano Zampini } 91409566063dSJacob Faibussowitsch PetscCall(VecDestroy(&check_vec)); 91419566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coarse_vec)); 91429566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&check_ksp)); 91436e683305SStefano Zampini if (compute_eigs) { 91449566063dSJacob Faibussowitsch PetscCall(PetscFree(eigs_r)); 91459566063dSJacob Faibussowitsch PetscCall(PetscFree(eigs_c)); 9146c8587f34SStefano Zampini } 91476e683305SStefano Zampini } 91486e683305SStefano Zampini } 91499566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&CoarseNullSpace)); 9150cbcc2c2aSStefano Zampini /* print additional info */ 9151cbcc2c2aSStefano Zampini if (pcbddc->dbg_flag) { 91526e683305SStefano Zampini /* waits until all processes reaches this point */ 91539566063dSJacob Faibussowitsch PetscCall(PetscBarrier((PetscObject)pc)); 915463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Coarse solver setup completed at level %" PetscInt_FMT "\n", pcbddc->current_level)); 91559566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 9156cbcc2c2aSStefano Zampini } 9157cbcc2c2aSStefano Zampini 91582b510759SStefano Zampini /* free memory */ 91599566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_mat)); 91609566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_CoarseSolver[pcbddc->current_level], pc, 0, 0, 0)); 91613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9162c8587f34SStefano Zampini } 9163674ae819SStefano Zampini 9164d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCComputePrimalNumbering(PC pc, PetscInt *coarse_size_n, PetscInt **local_primal_indices_n) 9165d71ae5a4SJacob Faibussowitsch { 9166f34684f1SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 9167f34684f1SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 9168dc456d91SStefano Zampini IS subset, subset_mult, subset_n; 9169dc456d91SStefano Zampini PetscInt local_size, coarse_size = 0; 917073be2a3aSStefano Zampini PetscInt *local_primal_indices = NULL; 9171dc456d91SStefano Zampini const PetscInt *t_local_primal_indices; 9172f34684f1SStefano Zampini 9173f34684f1SStefano Zampini PetscFunctionBegin; 9174f34684f1SStefano Zampini /* Compute global number of coarse dofs */ 917508401ef6SPierre Jolivet PetscCheck(!pcbddc->local_primal_size || pcbddc->local_primal_ref_node, PETSC_COMM_SELF, PETSC_ERR_PLIB, "BDDC ConstraintsSetUp should be called first"); 9176f4f49eeaSPierre Jolivet PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc->pmat), pcbddc->local_primal_size_cc, pcbddc->local_primal_ref_node, PETSC_COPY_VALUES, &subset_n)); 91779566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(pcis->mapping, subset_n, &subset)); 91789566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subset_n)); 9179f4f49eeaSPierre Jolivet PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc->pmat), pcbddc->local_primal_size_cc, pcbddc->local_primal_ref_mult, PETSC_COPY_VALUES, &subset_mult)); 91809566063dSJacob Faibussowitsch PetscCall(ISRenumber(subset, subset_mult, &coarse_size, &subset_n)); 91819566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subset)); 91829566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subset_mult)); 91839566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(subset_n, &local_size)); 918463a3b9bcSJacob 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); 91859566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(local_size, &local_primal_indices)); 91869566063dSJacob Faibussowitsch PetscCall(ISGetIndices(subset_n, &t_local_primal_indices)); 91879566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(local_primal_indices, t_local_primal_indices, local_size)); 91889566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(subset_n, &t_local_primal_indices)); 91899566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subset_n)); 9190f34684f1SStefano Zampini 9191f34684f1SStefano Zampini if (pcbddc->dbg_flag) { 91929566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 91939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 91949de2952eSStefano Zampini PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Size of coarse problem is %" PetscInt_FMT "\n", coarse_size)); 91959566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 9196f34684f1SStefano Zampini } 91976080607fSStefano Zampini 9198f34684f1SStefano Zampini /* get back data */ 9199f34684f1SStefano Zampini *coarse_size_n = coarse_size; 9200f34684f1SStefano Zampini *local_primal_indices_n = local_primal_indices; 92013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9202674ae819SStefano Zampini } 9203674ae819SStefano Zampini 9204d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx, Vec gwork, Vec lwork, IS globalis, IS *localis) 9205d71ae5a4SJacob Faibussowitsch { 9206e456f2a8SStefano Zampini IS localis_t; 9207a7dc3881SStefano Zampini PetscInt i, lsize, *idxs, n; 9208e456f2a8SStefano Zampini PetscScalar *vals; 9209e456f2a8SStefano Zampini 9210e456f2a8SStefano Zampini PetscFunctionBegin; 9211a7dc3881SStefano Zampini /* get indices in local ordering exploiting local to global map */ 92129566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(globalis, &lsize)); 92139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(lsize, &vals)); 9214e456f2a8SStefano Zampini for (i = 0; i < lsize; i++) vals[i] = 1.0; 92159566063dSJacob Faibussowitsch PetscCall(ISGetIndices(globalis, (const PetscInt **)&idxs)); 92169566063dSJacob Faibussowitsch PetscCall(VecSet(gwork, 0.0)); 92179566063dSJacob Faibussowitsch PetscCall(VecSet(lwork, 0.0)); 92181035eff8SStefano Zampini if (idxs) { /* multilevel guard */ 92199566063dSJacob Faibussowitsch PetscCall(VecSetOption(gwork, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE)); 92209566063dSJacob Faibussowitsch PetscCall(VecSetValues(gwork, lsize, idxs, vals, INSERT_VALUES)); 92211035eff8SStefano Zampini } 92229566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(gwork)); 92239566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(globalis, (const PetscInt **)&idxs)); 92249566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 92259566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(gwork)); 9226a7dc3881SStefano Zampini /* now compute set in local ordering */ 92279566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(g2l_ctx, gwork, lwork, INSERT_VALUES, SCATTER_FORWARD)); 92289566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(g2l_ctx, gwork, lwork, INSERT_VALUES, SCATTER_FORWARD)); 92299566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(lwork, (const PetscScalar **)&vals)); 92309566063dSJacob Faibussowitsch PetscCall(VecGetSize(lwork, &n)); 9231a7dc3881SStefano Zampini for (i = 0, lsize = 0; i < n; i++) { 9232ad540459SPierre Jolivet if (PetscRealPart(vals[i]) > 0.5) lsize++; 9233e456f2a8SStefano Zampini } 92349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(lsize, &idxs)); 9235a7dc3881SStefano Zampini for (i = 0, lsize = 0; i < n; i++) { 9236ad540459SPierre Jolivet if (PetscRealPart(vals[i]) > 0.5) idxs[lsize++] = i; 9237e456f2a8SStefano Zampini } 92389566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(lwork, (const PetscScalar **)&vals)); 92399566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)gwork), lsize, idxs, PETSC_OWN_POINTER, &localis_t)); 9240e456f2a8SStefano Zampini *localis = localis_t; 92413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9242e456f2a8SStefano Zampini } 9243906d46d4SStefano Zampini 9244d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCComputeFakeChange(PC pc, PetscBool constraints, PCBDDCGraph graph, PCBDDCSubSchurs schurs, Mat *change, IS *change_primal, IS *change_primal_mult, PetscBool *change_with_qr) 9245d71ae5a4SJacob Faibussowitsch { 92467c625d9fSStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 92477c625d9fSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 92487c625d9fSStefano Zampini PC_IS *pcisf; 92497c625d9fSStefano Zampini PC_BDDC *pcbddcf; 92507c625d9fSStefano Zampini PC pcf; 92517c625d9fSStefano Zampini 92527c625d9fSStefano Zampini PetscFunctionBegin; 92537c625d9fSStefano Zampini PetscCall(PCCreate(PetscObjectComm((PetscObject)pc), &pcf)); 92547c625d9fSStefano Zampini PetscCall(PCSetOperators(pcf, pc->mat, pc->pmat)); 92557c625d9fSStefano Zampini PetscCall(PCSetType(pcf, PCBDDC)); 92567c625d9fSStefano Zampini 92577c625d9fSStefano Zampini pcisf = (PC_IS *)pcf->data; 925832fe681dSStefano Zampini pcbddcf = (PC_BDDC *)pcf->data; 925932fe681dSStefano Zampini 92607c625d9fSStefano Zampini pcisf->is_B_local = pcis->is_B_local; 92617c625d9fSStefano Zampini pcisf->vec1_N = pcis->vec1_N; 92627c625d9fSStefano Zampini pcisf->BtoNmap = pcis->BtoNmap; 92637c625d9fSStefano Zampini pcisf->n = pcis->n; 92647c625d9fSStefano Zampini pcisf->n_B = pcis->n_B; 92657c625d9fSStefano Zampini 92667c625d9fSStefano Zampini PetscCall(PetscFree(pcbddcf->mat_graph)); 926732fe681dSStefano Zampini PetscCall(PetscFree(pcbddcf->sub_schurs)); 92687c625d9fSStefano Zampini pcbddcf->mat_graph = graph ? graph : pcbddc->mat_graph; 926932fe681dSStefano Zampini pcbddcf->sub_schurs = schurs; 927032fe681dSStefano Zampini pcbddcf->adaptive_selection = schurs ? PETSC_TRUE : PETSC_FALSE; 927132fe681dSStefano Zampini pcbddcf->adaptive_threshold[0] = pcbddc->adaptive_threshold[0]; 927232fe681dSStefano Zampini pcbddcf->adaptive_threshold[1] = pcbddc->adaptive_threshold[1]; 927332fe681dSStefano Zampini pcbddcf->adaptive_nmin = pcbddc->adaptive_nmin; 927432fe681dSStefano Zampini pcbddcf->adaptive_nmax = pcbddc->adaptive_nmax; 92757c625d9fSStefano Zampini pcbddcf->use_faces = PETSC_TRUE; 927632fe681dSStefano Zampini pcbddcf->use_change_of_basis = (PetscBool)!constraints; 927732fe681dSStefano Zampini pcbddcf->use_change_on_faces = (PetscBool)!constraints; 927832fe681dSStefano Zampini pcbddcf->use_qr_single = (PetscBool)!constraints; 92797c625d9fSStefano Zampini pcbddcf->fake_change = PETSC_TRUE; 928032fe681dSStefano Zampini pcbddcf->dbg_flag = pcbddc->dbg_flag; 928132fe681dSStefano Zampini 928232fe681dSStefano Zampini PetscCall(PCBDDCAdaptiveSelection(pcf)); 92837c625d9fSStefano Zampini PetscCall(PCBDDCConstraintsSetUp(pcf)); 92847c625d9fSStefano Zampini 92857c625d9fSStefano Zampini *change = pcbddcf->ConstraintMatrix; 92867c625d9fSStefano 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)); 92877c625d9fSStefano 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)); 92887c625d9fSStefano Zampini if (change_with_qr) *change_with_qr = pcbddcf->use_qr_single; 92897c625d9fSStefano Zampini 929032fe681dSStefano Zampini if (schurs) pcbddcf->sub_schurs = NULL; 92917c625d9fSStefano Zampini pcbddcf->ConstraintMatrix = NULL; 929232fe681dSStefano Zampini pcbddcf->mat_graph = NULL; 929332fe681dSStefano Zampini pcisf->is_B_local = NULL; 929432fe681dSStefano Zampini pcisf->vec1_N = NULL; 929532fe681dSStefano Zampini pcisf->BtoNmap = NULL; 92967c625d9fSStefano Zampini PetscCall(PCDestroy(&pcf)); 92973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 92987c625d9fSStefano Zampini } 92997c625d9fSStefano Zampini 9300d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpSubSchurs(PC pc) 9301d71ae5a4SJacob Faibussowitsch { 9302a64f4aa4SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 9303b96c3477SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 9304b96c3477SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 9305a64f4aa4SStefano Zampini Mat S_j; 9306b96c3477SStefano Zampini PetscInt *used_xadj, *used_adjncy; 9307b96c3477SStefano Zampini PetscBool free_used_adj; 9308b96c3477SStefano Zampini 9309b96c3477SStefano Zampini PetscFunctionBegin; 93109566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Schurs[pcbddc->current_level], pc, 0, 0, 0)); 9311b96c3477SStefano Zampini /* decide the adjacency to be used for determining internal problems for local schur on subsets */ 9312b96c3477SStefano Zampini free_used_adj = PETSC_FALSE; 931308122e43SStefano Zampini if (pcbddc->sub_schurs_layers == -1) { 9314b96c3477SStefano Zampini used_xadj = NULL; 9315b96c3477SStefano Zampini used_adjncy = NULL; 9316b96c3477SStefano Zampini } else { 931708122e43SStefano Zampini if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) { 931808122e43SStefano Zampini used_xadj = pcbddc->mat_graph->xadj; 931908122e43SStefano Zampini used_adjncy = pcbddc->mat_graph->adjncy; 932008122e43SStefano Zampini } else if (pcbddc->computed_rowadj) { 9321b96c3477SStefano Zampini used_xadj = pcbddc->mat_graph->xadj; 9322b96c3477SStefano Zampini used_adjncy = pcbddc->mat_graph->adjncy; 9323b96c3477SStefano Zampini } else { 93242fffb893SStefano Zampini PetscBool flg_row = PETSC_FALSE; 9325b96c3477SStefano Zampini const PetscInt *xadj, *adjncy; 9326b96c3477SStefano Zampini PetscInt nvtxs; 9327b96c3477SStefano Zampini 93289566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(pcbddc->local_mat, 0, PETSC_TRUE, PETSC_FALSE, &nvtxs, &xadj, &adjncy, &flg_row)); 93292fffb893SStefano Zampini if (flg_row) { 93309566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nvtxs + 1, &used_xadj, xadj[nvtxs], &used_adjncy)); 93319566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(used_xadj, xadj, nvtxs + 1)); 93329566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(used_adjncy, adjncy, xadj[nvtxs])); 9333b96c3477SStefano Zampini free_used_adj = PETSC_TRUE; 93342fffb893SStefano Zampini } else { 93352fffb893SStefano Zampini pcbddc->sub_schurs_layers = -1; 93362fffb893SStefano Zampini used_xadj = NULL; 93372fffb893SStefano Zampini used_adjncy = NULL; 93382fffb893SStefano Zampini } 93399566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(pcbddc->local_mat, 0, PETSC_TRUE, PETSC_FALSE, &nvtxs, &xadj, &adjncy, &flg_row)); 9340b96c3477SStefano Zampini } 9341b96c3477SStefano Zampini } 9342d5574798SStefano Zampini 9343d5574798SStefano Zampini /* setup sub_schurs data */ 93449566063dSJacob Faibussowitsch PetscCall(MatCreateSchurComplement(pcis->A_II, pcis->pA_II, pcis->A_IB, pcis->A_BI, pcis->A_BB, &S_j)); 9345df4d28bfSStefano Zampini if (!sub_schurs->schur_explicit) { 9346df4d28bfSStefano Zampini /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */ 93479566063dSJacob Faibussowitsch PetscCall(MatSchurComplementSetKSP(S_j, pcbddc->ksp_D)); 93489566063dSJacob 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)); 9349a64f4aa4SStefano Zampini } else { 935072b8c272SStefano Zampini Mat change = NULL; 93519d54b7f4SStefano Zampini Vec scaling = NULL; 9352111315fdSstefano_zampini IS change_primal = NULL, iP; 9353111315fdSstefano_zampini PetscInt benign_n; 9354111315fdSstefano_zampini PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis; 93557ebab0bbSStefano Zampini PetscBool need_change = PETSC_FALSE; 9356111315fdSstefano_zampini PetscBool discrete_harmonic = PETSC_FALSE; 9357a3df083aSStefano Zampini 93585feab87aSStefano Zampini if (!pcbddc->use_vertices && reuse_solvers) { 93595feab87aSStefano Zampini PetscInt n_vertices; 93605feab87aSStefano Zampini 93619566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->is_vertices, &n_vertices)); 93622034aafcSStefano Zampini reuse_solvers = (PetscBool)!n_vertices; 93635feab87aSStefano Zampini } 9364a3df083aSStefano Zampini if (!pcbddc->benign_change_explicit) { 9365a3df083aSStefano Zampini benign_n = pcbddc->benign_n; 9366ca92afb2SStefano Zampini } else { 9367a3df083aSStefano Zampini benign_n = 0; 9368ca92afb2SStefano Zampini } 9369b7ab4a40SStefano Zampini /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc. 9370b7ab4a40SStefano Zampini We need a global reduction to avoid possible deadlocks. 9371b7ab4a40SStefano Zampini We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */ 937272b8c272SStefano Zampini if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) { 937322db5ddcSStefano Zampini PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change); 9374462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&have_loc_change, &need_change, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 937522db5ddcSStefano Zampini need_change = (PetscBool)(!need_change); 9376b7ab4a40SStefano Zampini } 93777c625d9fSStefano Zampini /* If the user defines additional constraints, we import them here */ 9378b7ab4a40SStefano Zampini if (need_change) { 937928b400f6SJacob Faibussowitsch PetscCheck(!pcbddc->sub_schurs_rebuild, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot compute change of basis with a different graph"); 938032fe681dSStefano Zampini PetscCall(PCBDDCComputeFakeChange(pc, PETSC_FALSE, NULL, NULL, &change, &change_primal, NULL, &sub_schurs->change_with_qr)); 938188c03ad3SStefano Zampini } 93829d54b7f4SStefano Zampini if (!pcbddc->use_deluxe_scaling) scaling = pcis->D; 9383111315fdSstefano_zampini 93849566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_iP", (PetscObject *)&iP)); 9385111315fdSstefano_zampini if (iP) { 9386d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)iP), sub_schurs->prefix, "BDDC sub_schurs options", "PC"); 93879566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-sub_schurs_discrete_harmonic", NULL, NULL, discrete_harmonic, &discrete_harmonic, NULL)); 9388d0609cedSBarry Smith PetscOptionsEnd(); 9389111315fdSstefano_zampini } 9390111315fdSstefano_zampini if (discrete_harmonic) { 9391111315fdSstefano_zampini Mat A; 93929566063dSJacob Faibussowitsch PetscCall(MatDuplicate(pcbddc->local_mat, MAT_COPY_VALUES, &A)); 93939566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumnsIS(A, iP, 1.0, NULL, NULL)); 93949566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A, "__KSPFETIDP_iP", (PetscObject)iP)); 93959371c9d4SSatish 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, 93969371c9d4SSatish Balay pcbddc->benign_zerodiag_subs, change, change_primal)); 93979566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 9398111315fdSstefano_zampini } else { 93999371c9d4SSatish 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, 94009371c9d4SSatish Balay pcbddc->benign_p0_lidx, pcbddc->benign_zerodiag_subs, change, change_primal)); 9401111315fdSstefano_zampini } 94029566063dSJacob Faibussowitsch PetscCall(MatDestroy(&change)); 94039566063dSJacob Faibussowitsch PetscCall(ISDestroy(&change_primal)); 9404ca92afb2SStefano Zampini } 94059566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_j)); 9406b96c3477SStefano Zampini 9407b96c3477SStefano Zampini /* free adjacency */ 94081baa6e33SBarry Smith if (free_used_adj) PetscCall(PetscFree2(used_xadj, used_adjncy)); 94099566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Schurs[pcbddc->current_level], pc, 0, 0, 0)); 94103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9411b96c3477SStefano Zampini } 9412b96c3477SStefano Zampini 9413d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCInitSubSchurs(PC pc) 9414d71ae5a4SJacob Faibussowitsch { 9415b96c3477SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 9416b96c3477SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 9417b96c3477SStefano Zampini PCBDDCGraph graph; 9418b96c3477SStefano Zampini 9419b96c3477SStefano Zampini PetscFunctionBegin; 9420b96c3477SStefano Zampini /* attach interface graph for determining subsets */ 942108122e43SStefano Zampini if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */ 94223301b35fSStefano Zampini IS verticesIS, verticescomm; 94233301b35fSStefano Zampini PetscInt vsize, *idxs; 9424b96c3477SStefano Zampini 94259566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &verticesIS)); 94269566063dSJacob Faibussowitsch PetscCall(ISGetSize(verticesIS, &vsize)); 94279566063dSJacob Faibussowitsch PetscCall(ISGetIndices(verticesIS, (const PetscInt **)&idxs)); 94289566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), vsize, idxs, PETSC_COPY_VALUES, &verticescomm)); 94299566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(verticesIS, (const PetscInt **)&idxs)); 94309566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &verticesIS)); 94319566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphCreate(&graph)); 94329566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphInit(graph, pcbddc->mat_graph->l2gmap, pcbddc->mat_graph->nvtxs_global, pcbddc->graphmaxcount)); 94339566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphSetUp(graph, pcbddc->mat_graph->custom_minimal_size, NULL, pcbddc->DirichletBoundariesLocal, 0, NULL, verticescomm)); 94349566063dSJacob Faibussowitsch PetscCall(ISDestroy(&verticescomm)); 94359566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphComputeConnectedComponents(graph)); 9436b96c3477SStefano Zampini } else { 9437b96c3477SStefano Zampini graph = pcbddc->mat_graph; 9438b96c3477SStefano Zampini } 9439e4d548c7SStefano Zampini /* print some info */ 94405c643e28SStefano Zampini if (pcbddc->dbg_flag && !pcbddc->sub_schurs_rebuild) { 9441e4d548c7SStefano Zampini IS vertices; 9442e4d548c7SStefano Zampini PetscInt nv, nedges, nfaces; 94439566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphASCIIView(graph, pcbddc->dbg_flag, pcbddc->dbg_viewer)); 94449566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(graph, &nfaces, NULL, &nedges, NULL, &vertices)); 94459566063dSJacob Faibussowitsch PetscCall(ISGetSize(vertices, &nv)); 94469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 94479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "--------------------------------------------------------------\n")); 944863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate vertices (%d)\n", PetscGlobalRank, nv, pcbddc->use_vertices)); 944963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate edges (%d)\n", PetscGlobalRank, nedges, pcbddc->use_edges)); 945063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate faces (%d)\n", PetscGlobalRank, nfaces, pcbddc->use_faces)); 94519566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 94529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer)); 94539566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(graph, &nfaces, NULL, &nedges, NULL, &vertices)); 9454e4d548c7SStefano Zampini } 9455b96c3477SStefano Zampini 9456b96c3477SStefano Zampini /* sub_schurs init */ 945748a46eb9SPierre Jolivet if (!pcbddc->sub_schurs) PetscCall(PCBDDCSubSchursCreate(&pcbddc->sub_schurs)); 945832fe681dSStefano 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)); 9459a64f4aa4SStefano Zampini 9460b96c3477SStefano Zampini /* free graph struct */ 946148a46eb9SPierre Jolivet if (pcbddc->sub_schurs_rebuild) PetscCall(PCBDDCGraphDestroy(&graph)); 94623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9463b96c3477SStefano Zampini } 9464fa34dd3eSStefano Zampini 94659de2952eSStefano Zampini static PetscErrorCode PCBDDCViewGlobalIS(PC pc, IS is, PetscViewer viewer) 94669de2952eSStefano Zampini { 94679de2952eSStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 94689de2952eSStefano Zampini PetscInt n = pc->pmat->rmap->n, ln, ni, st; 94699de2952eSStefano Zampini const PetscInt *idxs; 94709de2952eSStefano Zampini IS gis; 94719de2952eSStefano Zampini 94729de2952eSStefano Zampini PetscFunctionBegin; 94739de2952eSStefano Zampini if (!is) PetscFunctionReturn(PETSC_SUCCESS); 94749de2952eSStefano Zampini PetscCall(MatGetOwnershipRange(pc->pmat, &st, NULL)); 94759de2952eSStefano Zampini PetscCall(MatGetLocalSize(matis->A, NULL, &ln)); 94769de2952eSStefano Zampini PetscCall(PetscArrayzero(matis->sf_leafdata, ln)); 94779de2952eSStefano Zampini PetscCall(PetscArrayzero(matis->sf_rootdata, n)); 94789de2952eSStefano Zampini PetscCall(ISGetLocalSize(is, &ni)); 94799de2952eSStefano Zampini PetscCall(ISGetIndices(is, &idxs)); 94809de2952eSStefano Zampini for (PetscInt i = 0; i < ni; i++) { 94819de2952eSStefano Zampini if (idxs[i] < 0 || idxs[i] >= ln) continue; 94829de2952eSStefano Zampini matis->sf_leafdata[idxs[i]] = 1; 94839de2952eSStefano Zampini } 94849de2952eSStefano Zampini PetscCall(ISRestoreIndices(is, &idxs)); 94859de2952eSStefano Zampini PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, matis->sf_leafdata, matis->sf_rootdata, MPI_SUM)); 94869de2952eSStefano Zampini PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, matis->sf_leafdata, matis->sf_rootdata, MPI_SUM)); 94879de2952eSStefano Zampini ln = 0; 94889de2952eSStefano Zampini for (PetscInt i = 0; i < n; i++) { 94899de2952eSStefano Zampini if (matis->sf_rootdata[i]) matis->sf_rootdata[ln++] = i + st; 94909de2952eSStefano Zampini } 94919de2952eSStefano Zampini PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), ln, matis->sf_rootdata, PETSC_USE_POINTER, &gis)); 94929de2952eSStefano Zampini PetscCall(ISView(gis, viewer)); 94939de2952eSStefano Zampini PetscCall(ISDestroy(&gis)); 94949de2952eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 94959de2952eSStefano Zampini } 94969de2952eSStefano Zampini 94979de2952eSStefano Zampini PetscErrorCode PCBDDCLoadOrViewCustomization(PC pc, PetscBool load, const char *outfile) 94989de2952eSStefano Zampini { 94999de2952eSStefano Zampini PetscInt header[11]; 95009de2952eSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 95019de2952eSStefano Zampini PetscViewer viewer; 95029de2952eSStefano Zampini MPI_Comm comm = PetscObjectComm((PetscObject)pc); 95039de2952eSStefano Zampini 95049de2952eSStefano Zampini PetscFunctionBegin; 95059de2952eSStefano Zampini PetscCall(PetscViewerBinaryOpen(comm, outfile ? outfile : "bddc_dump.dat", load ? FILE_MODE_READ : FILE_MODE_WRITE, &viewer)); 95069de2952eSStefano Zampini if (load) { 95079de2952eSStefano Zampini IS is; 95089de2952eSStefano Zampini Mat A; 95099de2952eSStefano Zampini 95109de2952eSStefano Zampini PetscCall(PetscViewerBinaryRead(viewer, header, PETSC_STATIC_ARRAY_LENGTH(header), NULL, PETSC_INT)); 95119de2952eSStefano Zampini PetscCheck(header[0] == 0 || header[0] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 95129de2952eSStefano Zampini PetscCheck(header[1] == 0 || header[1] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 95139de2952eSStefano Zampini PetscCheck(header[2] >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 95149de2952eSStefano Zampini PetscCheck(header[3] == 0 || header[3] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 95159de2952eSStefano Zampini PetscCheck(header[4] == 0 || header[4] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 95169de2952eSStefano Zampini PetscCheck(header[5] >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 95179de2952eSStefano Zampini PetscCheck(header[7] == 0 || header[7] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 95189de2952eSStefano Zampini PetscCheck(header[8] == 0 || header[8] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 95199de2952eSStefano Zampini PetscCheck(header[9] == 0 || header[9] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 95209de2952eSStefano Zampini PetscCheck(header[10] == 0 || header[10] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 95219de2952eSStefano Zampini if (header[0]) { 95229de2952eSStefano Zampini PetscCall(ISCreate(comm, &is)); 95239de2952eSStefano Zampini PetscCall(ISLoad(is, viewer)); 95249de2952eSStefano Zampini PetscCall(PCBDDCSetDirichletBoundaries(pc, is)); 95259de2952eSStefano Zampini PetscCall(ISDestroy(&is)); 95269de2952eSStefano Zampini } 95279de2952eSStefano Zampini if (header[1]) { 95289de2952eSStefano Zampini PetscCall(ISCreate(comm, &is)); 95299de2952eSStefano Zampini PetscCall(ISLoad(is, viewer)); 95309de2952eSStefano Zampini PetscCall(PCBDDCSetNeumannBoundaries(pc, is)); 95319de2952eSStefano Zampini PetscCall(ISDestroy(&is)); 95329de2952eSStefano Zampini } 95339de2952eSStefano Zampini if (header[2]) { 95349de2952eSStefano Zampini IS *isarray; 95359de2952eSStefano Zampini 95369de2952eSStefano Zampini PetscCall(PetscMalloc1(header[2], &isarray)); 95379de2952eSStefano Zampini for (PetscInt i = 0; i < header[2]; i++) { 95389de2952eSStefano Zampini PetscCall(ISCreate(comm, &isarray[i])); 95399de2952eSStefano Zampini PetscCall(ISLoad(isarray[i], viewer)); 95409de2952eSStefano Zampini } 95419de2952eSStefano Zampini PetscCall(PCBDDCSetDofsSplitting(pc, header[2], isarray)); 95429de2952eSStefano Zampini for (PetscInt i = 0; i < header[2]; i++) PetscCall(ISDestroy(&isarray[i])); 95439de2952eSStefano Zampini PetscCall(PetscFree(isarray)); 95449de2952eSStefano Zampini } 95459de2952eSStefano Zampini if (header[3]) { 95469de2952eSStefano Zampini PetscCall(ISCreate(comm, &is)); 95479de2952eSStefano Zampini PetscCall(ISLoad(is, viewer)); 95489de2952eSStefano Zampini PetscCall(PCBDDCSetPrimalVerticesIS(pc, is)); 95499de2952eSStefano Zampini PetscCall(ISDestroy(&is)); 95509de2952eSStefano Zampini } 95519de2952eSStefano Zampini if (header[4]) { 95529de2952eSStefano Zampini PetscCall(MatCreate(comm, &A)); 95539de2952eSStefano Zampini PetscCall(MatSetType(A, MATAIJ)); 95549de2952eSStefano Zampini PetscCall(MatLoad(A, viewer)); 95559de2952eSStefano Zampini PetscCall(PCBDDCSetDiscreteGradient(pc, A, header[5], header[6], (PetscBool)header[7], (PetscBool)header[8])); 95569de2952eSStefano Zampini PetscCall(MatDestroy(&A)); 95579de2952eSStefano Zampini } 95589de2952eSStefano Zampini if (header[9]) { 95599de2952eSStefano Zampini PetscCall(MatCreate(comm, &A)); 95609de2952eSStefano Zampini PetscCall(MatSetType(A, MATIS)); 95619de2952eSStefano Zampini PetscCall(MatLoad(A, viewer)); 95629de2952eSStefano Zampini PetscCall(PCBDDCSetDivergenceMat(pc, A, (PetscBool)header[10], NULL)); 95639de2952eSStefano Zampini PetscCall(MatDestroy(&A)); 95649de2952eSStefano Zampini } 95659de2952eSStefano Zampini } else { 95669de2952eSStefano Zampini header[0] = (PetscInt)!!pcbddc->DirichletBoundariesLocal; 95679de2952eSStefano Zampini header[1] = (PetscInt)!!pcbddc->NeumannBoundariesLocal; 95689de2952eSStefano Zampini header[2] = pcbddc->n_ISForDofsLocal; 95699de2952eSStefano Zampini header[3] = (PetscInt)!!pcbddc->user_primal_vertices_local; 95709de2952eSStefano Zampini header[4] = (PetscInt)!!pcbddc->discretegradient; 95719de2952eSStefano Zampini header[5] = pcbddc->nedorder; 95729de2952eSStefano Zampini header[6] = pcbddc->nedfield; 95739de2952eSStefano Zampini header[7] = (PetscInt)pcbddc->nedglobal; 95749de2952eSStefano Zampini header[8] = (PetscInt)pcbddc->conforming; 95759de2952eSStefano Zampini header[9] = (PetscInt)!!pcbddc->divudotp; 95769de2952eSStefano Zampini header[10] = (PetscInt)pcbddc->divudotp_trans; 95779de2952eSStefano Zampini if (header[4]) header[3] = 0; 95789de2952eSStefano Zampini 95799de2952eSStefano Zampini PetscCall(PetscViewerBinaryWrite(viewer, header, PETSC_STATIC_ARRAY_LENGTH(header), PETSC_INT)); 95809de2952eSStefano Zampini PetscCall(PCBDDCViewGlobalIS(pc, pcbddc->DirichletBoundariesLocal, viewer)); 95819de2952eSStefano Zampini PetscCall(PCBDDCViewGlobalIS(pc, pcbddc->NeumannBoundariesLocal, viewer)); 95829de2952eSStefano Zampini for (PetscInt i = 0; i < header[2]; i++) PetscCall(PCBDDCViewGlobalIS(pc, pcbddc->ISForDofsLocal[i], viewer)); 95839de2952eSStefano Zampini if (header[3]) PetscCall(PCBDDCViewGlobalIS(pc, pcbddc->user_primal_vertices_local, viewer)); 95849de2952eSStefano Zampini if (header[4]) PetscCall(MatView(pcbddc->discretegradient, viewer)); 95859de2952eSStefano Zampini if (header[9]) PetscCall(MatView(pcbddc->divudotp, viewer)); 95869de2952eSStefano Zampini } 95879de2952eSStefano Zampini PetscCall(PetscViewerDestroy(&viewer)); 95889de2952eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 95899de2952eSStefano Zampini } 95909de2952eSStefano Zampini 95911e0482f5SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h> 9592ba38deedSJacob Faibussowitsch static PetscErrorCode MatMPIAIJRestrict(Mat A, MPI_Comm ccomm, Mat *B) 9593d71ae5a4SJacob Faibussowitsch { 95941e0482f5SStefano Zampini Mat At; 95951e0482f5SStefano Zampini IS rows; 95961e0482f5SStefano Zampini PetscInt rst, ren; 95971e0482f5SStefano Zampini PetscLayout rmap; 95981e0482f5SStefano Zampini 95991e0482f5SStefano Zampini PetscFunctionBegin; 96001e0482f5SStefano Zampini rst = ren = 0; 96011e0482f5SStefano Zampini if (ccomm != MPI_COMM_NULL) { 96029566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(ccomm, &rmap)); 96039566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetSize(rmap, A->rmap->N)); 96049566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(rmap, 1)); 96059566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rmap)); 96069566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rmap, &rst, &ren)); 96071e0482f5SStefano Zampini } 96089566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), ren - rst, rst, 1, &rows)); 96099566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, rows, NULL, MAT_INITIAL_MATRIX, &At)); 96109566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rows)); 96111e0482f5SStefano Zampini 96121e0482f5SStefano Zampini if (ccomm != MPI_COMM_NULL) { 96131e0482f5SStefano Zampini Mat_MPIAIJ *a, *b; 96141e0482f5SStefano Zampini IS from, to; 96151e0482f5SStefano Zampini Vec gvec; 96161e0482f5SStefano Zampini PetscInt lsize; 96171e0482f5SStefano Zampini 96189566063dSJacob Faibussowitsch PetscCall(MatCreate(ccomm, B)); 96199566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B, ren - rst, PETSC_DECIDE, PETSC_DECIDE, At->cmap->N)); 96209566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, MATAIJ)); 962157508eceSPierre Jolivet PetscCall(PetscLayoutDestroy(&(*B)->rmap)); 96229566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp((*B)->cmap)); 96231e0482f5SStefano Zampini a = (Mat_MPIAIJ *)At->data; 96241e0482f5SStefano Zampini b = (Mat_MPIAIJ *)(*B)->data; 96259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(ccomm, &b->size)); 96269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(ccomm, &b->rank)); 96279566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)a->A)); 96289566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)a->B)); 96291e0482f5SStefano Zampini b->A = a->A; 96301e0482f5SStefano Zampini b->B = a->B; 96311e0482f5SStefano Zampini 96321e0482f5SStefano Zampini b->donotstash = a->donotstash; 96331e0482f5SStefano Zampini b->roworiented = a->roworiented; 96340a545947SLisandro Dalcin b->rowindices = NULL; 96350a545947SLisandro Dalcin b->rowvalues = NULL; 96361e0482f5SStefano Zampini b->getrowactive = PETSC_FALSE; 96371e0482f5SStefano Zampini 96381e0482f5SStefano Zampini (*B)->rmap = rmap; 96391e0482f5SStefano Zampini (*B)->factortype = A->factortype; 96401e0482f5SStefano Zampini (*B)->assembled = PETSC_TRUE; 96411e0482f5SStefano Zampini (*B)->insertmode = NOT_SET_VALUES; 96421e0482f5SStefano Zampini (*B)->preallocated = PETSC_TRUE; 96431e0482f5SStefano Zampini 96441e0482f5SStefano Zampini if (a->colmap) { 96451e0482f5SStefano Zampini #if defined(PETSC_USE_CTABLE) 9646eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIDuplicate(a->colmap, &b->colmap)); 96471e0482f5SStefano Zampini #else 96489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(At->cmap->N, &b->colmap)); 96499566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(b->colmap, a->colmap, At->cmap->N)); 96501e0482f5SStefano Zampini #endif 96510a545947SLisandro Dalcin } else b->colmap = NULL; 96521e0482f5SStefano Zampini if (a->garray) { 96531e0482f5SStefano Zampini PetscInt len; 96541e0482f5SStefano Zampini len = a->B->cmap->n; 96559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(len + 1, &b->garray)); 96569566063dSJacob Faibussowitsch if (len) PetscCall(PetscArraycpy(b->garray, a->garray, len)); 96570a545947SLisandro Dalcin } else b->garray = NULL; 96581e0482f5SStefano Zampini 96599566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)a->lvec)); 96601e0482f5SStefano Zampini b->lvec = a->lvec; 96611e0482f5SStefano Zampini 96621e0482f5SStefano Zampini /* cannot use VecScatterCopy */ 96639566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(b->lvec, &lsize)); 96649566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(ccomm, lsize, b->garray, PETSC_USE_POINTER, &from)); 96659566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, lsize, 0, 1, &to)); 96669566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(*B, &gvec, NULL)); 96679566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(gvec, from, b->lvec, to, &b->Mvctx)); 96689566063dSJacob Faibussowitsch PetscCall(ISDestroy(&from)); 96699566063dSJacob Faibussowitsch PetscCall(ISDestroy(&to)); 96709566063dSJacob Faibussowitsch PetscCall(VecDestroy(&gvec)); 96711e0482f5SStefano Zampini } 96729566063dSJacob Faibussowitsch PetscCall(MatDestroy(&At)); 96733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 96741e0482f5SStefano Zampini } 96759de2952eSStefano Zampini 96769de2952eSStefano Zampini /* same as MatCreateSubMatrix(A, rows, NULL,...) but allows repeated rows */ 96779de2952eSStefano Zampini static PetscErrorCode MatAIJExtractRows(Mat A, IS rows, Mat *sA) 96789de2952eSStefano Zampini { 96799de2952eSStefano Zampini PetscBool isaij; 96809de2952eSStefano Zampini MPI_Comm comm; 96819de2952eSStefano Zampini 96829de2952eSStefano Zampini PetscFunctionBegin; 96839de2952eSStefano Zampini PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 96849de2952eSStefano Zampini PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)A, &isaij, MATSEQAIJ, MATMPIAIJ, "")); 96859de2952eSStefano Zampini PetscCheck(isaij, comm, PETSC_ERR_SUP, "Not implemented"); 96869de2952eSStefano Zampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isaij)); 96879de2952eSStefano Zampini if (isaij) { /* SeqAIJ supports repeated rows */ 96889de2952eSStefano Zampini PetscCall(MatCreateSubMatrix(A, rows, NULL, MAT_INITIAL_MATRIX, sA)); 96899de2952eSStefano Zampini } else { 96909de2952eSStefano Zampini Mat A_loc; 96919de2952eSStefano Zampini Mat_SeqAIJ *da; 96929de2952eSStefano Zampini PetscSF sf; 96939de2952eSStefano Zampini PetscInt ni, *di, *dj, m = A->rmap->n, c, *ldata, *rdata; 96949de2952eSStefano Zampini PetscScalar *daa; 96959de2952eSStefano Zampini const PetscInt *idxs; 96969de2952eSStefano Zampini const PetscSFNode *iremotes; 96979de2952eSStefano Zampini PetscSFNode *remotes; 96989de2952eSStefano Zampini 96999de2952eSStefano Zampini /* SF for incoming rows */ 97009de2952eSStefano Zampini PetscCall(PetscSFCreate(comm, &sf)); 97019de2952eSStefano Zampini PetscCall(ISGetLocalSize(rows, &ni)); 97029de2952eSStefano Zampini PetscCall(ISGetIndices(rows, &idxs)); 97039de2952eSStefano Zampini PetscCall(PetscSFSetGraphLayout(sf, A->rmap, ni, NULL, PETSC_USE_POINTER, idxs)); 97049de2952eSStefano Zampini PetscCall(ISRestoreIndices(rows, &idxs)); 97059de2952eSStefano Zampini 97069de2952eSStefano Zampini PetscCall(MatMPIAIJGetLocalMat(A, MAT_INITIAL_MATRIX, &A_loc)); 97079de2952eSStefano Zampini da = (Mat_SeqAIJ *)A_loc->data; 97089de2952eSStefano Zampini PetscCall(PetscMalloc2(2 * ni, &ldata, 2 * m, &rdata)); 97099de2952eSStefano Zampini for (PetscInt i = 0; i < m; i++) { 97109de2952eSStefano Zampini rdata[2 * i + 0] = da->i[i + 1] - da->i[i]; 97119de2952eSStefano Zampini rdata[2 * i + 1] = da->i[i]; 97129de2952eSStefano Zampini } 97139de2952eSStefano Zampini PetscCall(PetscSFBcastBegin(sf, MPIU_2INT, rdata, ldata, MPI_REPLACE)); 97149de2952eSStefano Zampini PetscCall(PetscSFBcastEnd(sf, MPIU_2INT, rdata, ldata, MPI_REPLACE)); 97159de2952eSStefano Zampini PetscCall(PetscMalloc1(ni + 1, &di)); 97169de2952eSStefano Zampini di[0] = 0; 97179de2952eSStefano Zampini for (PetscInt i = 0; i < ni; i++) di[i + 1] = di[i] + ldata[2 * i + 0]; 97189de2952eSStefano Zampini PetscCall(PetscMalloc1(di[ni], &dj)); 97199de2952eSStefano Zampini PetscCall(PetscMalloc1(di[ni], &daa)); 97209de2952eSStefano Zampini PetscCall(PetscMalloc1(di[ni], &remotes)); 97219de2952eSStefano Zampini 97229de2952eSStefano Zampini PetscCall(PetscSFGetGraph(sf, NULL, NULL, NULL, &iremotes)); 97239de2952eSStefano Zampini 97249de2952eSStefano Zampini /* SF graph for nonzeros */ 97259de2952eSStefano Zampini c = 0; 97269de2952eSStefano Zampini for (PetscInt i = 0; i < ni; i++) { 9727835f2295SStefano Zampini const PetscInt rank = iremotes[i].rank; 97289de2952eSStefano Zampini const PetscInt rsize = ldata[2 * i]; 97299de2952eSStefano Zampini for (PetscInt j = 0; j < rsize; j++) { 97309de2952eSStefano Zampini remotes[c].rank = rank; 97319de2952eSStefano Zampini remotes[c].index = ldata[2 * i + 1] + j; 97329de2952eSStefano Zampini c++; 97339de2952eSStefano Zampini } 97349de2952eSStefano Zampini } 97359de2952eSStefano Zampini PetscCheck(c == di[ni], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of local nonzeros %" PetscInt_FMT " != %" PetscInt_FMT, c, di[ni]); 97369de2952eSStefano Zampini PetscCall(PetscSFSetGraph(sf, da->i[m], di[ni], NULL, PETSC_USE_POINTER, remotes, PETSC_USE_POINTER)); 97379de2952eSStefano Zampini PetscCall(PetscSFBcastBegin(sf, MPIU_INT, da->j, dj, MPI_REPLACE)); 97389de2952eSStefano Zampini PetscCall(PetscSFBcastEnd(sf, MPIU_INT, da->j, dj, MPI_REPLACE)); 97399de2952eSStefano Zampini PetscCall(PetscSFBcastBegin(sf, MPIU_SCALAR, da->a, daa, MPI_REPLACE)); 97409de2952eSStefano Zampini PetscCall(PetscSFBcastEnd(sf, MPIU_SCALAR, da->a, daa, MPI_REPLACE)); 97419de2952eSStefano Zampini 97429de2952eSStefano Zampini PetscCall(MatCreateMPIAIJWithArrays(comm, ni, A->cmap->n, PETSC_DECIDE, A->cmap->N, di, dj, daa, sA)); 97439de2952eSStefano Zampini PetscCall(MatDestroy(&A_loc)); 97449de2952eSStefano Zampini PetscCall(PetscSFDestroy(&sf)); 97459de2952eSStefano Zampini PetscCall(PetscFree(di)); 97469de2952eSStefano Zampini PetscCall(PetscFree(dj)); 97479de2952eSStefano Zampini PetscCall(PetscFree(daa)); 97489de2952eSStefano Zampini PetscCall(PetscFree(remotes)); 97499de2952eSStefano Zampini PetscCall(PetscFree2(ldata, rdata)); 97509de2952eSStefano Zampini } 97519de2952eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 97529de2952eSStefano Zampini } 9753