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)); 2085440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&lrc[0], &lrc[1], 1, MPI_C_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"); */ 10595440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&eerr, &done, 1, MPI_C_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 1329732a5147SStefano Zampini /* Create change of basis matrix (no preallocation) */ 13309566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &T)); 13319de2952eSStefano Zampini PetscCall(MatSetLayouts(T, pc->mat->rmap, pc->mat->cmap)); 13329566063dSJacob Faibussowitsch PetscCall(MatSetType(T, MATAIJ)); 13339566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(T, al2g, al2g)); 13349566063dSJacob Faibussowitsch PetscCall(MatSetOption(T, MAT_ROW_ORIENTED, PETSC_FALSE)); 1335732a5147SStefano Zampini PetscCall(MatSetOption(T, MAT_IGNORE_ZERO_ENTRIES, PETSC_TRUE)); 1336732a5147SStefano Zampini //PetscCall(MatSeqAIJSetPreallocation(T, maxsize, NULL)); 1337732a5147SStefano Zampini //PetscCall(MatMPIAIJSetPreallocation(T, maxsize, NULL, maxsize, NULL)); 1338732a5147SStefano Zampini //PetscCall(MatSetOption(T, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 1339a13144ffSStefano Zampini 1340a13144ffSStefano Zampini /* Defaults to identity */ 1341732a5147SStefano Zampini { 1342732a5147SStefano Zampini Vec w; 1343732a5147SStefano Zampini const PetscScalar *wa; 1344732a5147SStefano Zampini 1345732a5147SStefano Zampini PetscCall(MatCreateVecs(T, &w, NULL)); 1346732a5147SStefano Zampini PetscCall(VecSetLocalToGlobalMapping(w, al2g)); 1347732a5147SStefano Zampini PetscCall(VecSet(w, 1.0)); 1348732a5147SStefano Zampini for (i = 0; i < nee; i++) { 1349732a5147SStefano Zampini const PetscInt *idxs; 1350732a5147SStefano Zampini PetscInt nl; 1351732a5147SStefano Zampini 1352732a5147SStefano Zampini PetscCall(ISGetLocalSize(eedges[i], &nl)); 1353732a5147SStefano Zampini PetscCall(ISGetIndices(eedges[i], &idxs)); 1354732a5147SStefano Zampini PetscCall(VecSetValuesLocal(w, nl, idxs, NULL, INSERT_VALUES)); 1355732a5147SStefano Zampini PetscCall(ISRestoreIndices(eedges[i], &idxs)); 1356732a5147SStefano Zampini } 1357732a5147SStefano Zampini PetscCall(VecAssemblyBegin(w)); 1358732a5147SStefano Zampini PetscCall(VecAssemblyEnd(w)); 1359732a5147SStefano Zampini PetscCall(VecGetArrayRead(w, &wa)); 1360732a5147SStefano Zampini for (i = T->rmap->rstart; i < T->rmap->rend; i++) 1361732a5147SStefano Zampini if (PetscAbsScalar(wa[i - T->rmap->rstart])) PetscCall(MatSetValue(T, i, i, 1.0, INSERT_VALUES)); 1362732a5147SStefano Zampini PetscCall(VecRestoreArrayRead(w, &wa)); 1363732a5147SStefano Zampini PetscCall(VecDestroy(&w)); 1364732a5147SStefano Zampini } 1365a13144ffSStefano Zampini 13661e0482f5SStefano Zampini /* Create discrete gradient for the coarser level if needed */ 13679566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->nedcG)); 13689566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->nedclocal)); 13691e0482f5SStefano Zampini if (pcbddc->current_level < pcbddc->max_levels) { 13701e0482f5SStefano Zampini ISLocalToGlobalMapping cel2g, cvl2g; 13711e0482f5SStefano Zampini IS wis, gwis; 13721e0482f5SStefano Zampini PetscInt cnv, cne; 13731e0482f5SStefano Zampini 13749566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, nee, cedges, PETSC_COPY_VALUES, &wis)); 13751e0482f5SStefano Zampini if (fl2g) { 13769566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(fl2g, wis, &pcbddc->nedclocal)); 13771e0482f5SStefano Zampini } else { 13789566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)wis)); 13791e0482f5SStefano Zampini pcbddc->nedclocal = wis; 13801e0482f5SStefano Zampini } 13819566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(el2g, wis, &gwis)); 13829566063dSJacob Faibussowitsch PetscCall(ISDestroy(&wis)); 13839566063dSJacob Faibussowitsch PetscCall(ISRenumber(gwis, NULL, &cne, &wis)); 13849566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(wis, &cel2g)); 13859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&wis)); 13869566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gwis)); 13871e0482f5SStefano Zampini 13889566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, 2 * nee, corners, PETSC_USE_POINTER, &wis)); 13899566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(vl2g, wis, &gwis)); 13909566063dSJacob Faibussowitsch PetscCall(ISDestroy(&wis)); 13919566063dSJacob Faibussowitsch PetscCall(ISRenumber(gwis, NULL, &cnv, &wis)); 13929566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(wis, &cvl2g)); 13939566063dSJacob Faibussowitsch PetscCall(ISDestroy(&wis)); 13949566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gwis)); 13951e0482f5SStefano Zampini 13969566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &pcbddc->nedcG)); 13979566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->nedcG, PETSC_DECIDE, PETSC_DECIDE, cne, cnv)); 13989566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->nedcG, MATAIJ)); 13999566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(pcbddc->nedcG, 2, NULL)); 14009566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(pcbddc->nedcG, 2, NULL, 2, NULL)); 14019566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(pcbddc->nedcG, cel2g, cvl2g)); 14029566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cel2g)); 14039566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cvl2g)); 14041e0482f5SStefano Zampini } 14051e0482f5SStefano Zampini 1406a75bf7bfSStefano Zampini MatNullSpace nnsp; 1407a75bf7bfSStefano Zampini PetscBool nnsp_has_const = PETSC_FALSE; 1408a75bf7bfSStefano Zampini const Vec *nnsp_vecs = NULL; 1409a75bf7bfSStefano Zampini PetscInt nnsp_nvecs = 0; 1410a75bf7bfSStefano Zampini VecScatter nnsp_vscat = NULL; 1411a75bf7bfSStefano Zampini PetscCall(MatGetNullSpace(pcbddc->discretegradient, &nnsp)); 1412a75bf7bfSStefano Zampini if (nnsp) PetscCall(MatNullSpaceGetVecs(nnsp, &nnsp_has_const, &nnsp_nvecs, &nnsp_vecs)); 1413a75bf7bfSStefano Zampini if (nnsp_has_const || nnsp_nvecs) { /* create scatter to import edge constraints */ 1414a75bf7bfSStefano Zampini IS allextcols, gallextcols, galleedges, is_E_to_zero; 1415a75bf7bfSStefano Zampini Vec E, V; 1416a75bf7bfSStefano Zampini PetscInt *eedgesidxs; 1417a75bf7bfSStefano Zampini const PetscScalar *evals; 1418a75bf7bfSStefano Zampini 1419a75bf7bfSStefano Zampini PetscCall(MatCreateVecs(pc->pmat, &E, NULL)); 1420a75bf7bfSStefano Zampini PetscCall(MatCreateVecs(pcbddc->discretegradient, &V, NULL)); 1421a75bf7bfSStefano Zampini PetscCall(ISConcatenate(PETSC_COMM_SELF, nee, extcols, &allextcols)); 1422a75bf7bfSStefano Zampini cum = 0; 1423a75bf7bfSStefano Zampini for (i = 0; i < nee; i++) { 1424a75bf7bfSStefano Zampini PetscInt j; 1425a75bf7bfSStefano Zampini 1426a75bf7bfSStefano Zampini PetscCall(ISGetLocalSize(eedges[i], &j)); 14278c5add6aSPierre Jolivet PetscCheck(j, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Zero sized edge %" PetscInt_FMT, i); 1428a75bf7bfSStefano Zampini cum += j - 1; 1429a75bf7bfSStefano Zampini } 1430a75bf7bfSStefano Zampini PetscCall(PetscMalloc1(PetscMax(cum, pc->pmat->rmap->n), &eedgesidxs)); 1431a75bf7bfSStefano Zampini cum = 0; 1432a75bf7bfSStefano Zampini for (i = 0; i < nee; i++) { 1433a75bf7bfSStefano Zampini const PetscInt *idxs; 1434a75bf7bfSStefano Zampini PetscInt j; 1435a75bf7bfSStefano Zampini 1436a75bf7bfSStefano Zampini PetscCall(ISGetLocalSize(eedges[i], &j)); 1437a75bf7bfSStefano Zampini PetscCall(ISGetIndices(eedges[i], &idxs)); 1438a75bf7bfSStefano Zampini PetscCall(PetscArraycpy(eedgesidxs + cum, idxs, j - 1)); /* last on the edge is primal */ 1439a75bf7bfSStefano Zampini PetscCall(ISRestoreIndices(eedges[i], &idxs)); 1440a75bf7bfSStefano Zampini cum += j - 1; 1441a75bf7bfSStefano Zampini } 1442a75bf7bfSStefano Zampini PetscCall(ISLocalToGlobalMappingApply(al2g, cum, eedgesidxs, eedgesidxs)); 1443a75bf7bfSStefano Zampini PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cum, eedgesidxs, PETSC_USE_POINTER, &galleedges)); 1444a75bf7bfSStefano Zampini PetscCall(ISLocalToGlobalMappingApplyIS(vl2g, allextcols, &gallextcols)); 1445a75bf7bfSStefano Zampini PetscCall(VecScatterCreate(V, gallextcols, E, galleedges, &nnsp_vscat)); 1446a75bf7bfSStefano Zampini PetscCall(ISDestroy(&allextcols)); 1447a75bf7bfSStefano Zampini PetscCall(ISDestroy(&gallextcols)); 1448a75bf7bfSStefano Zampini PetscCall(ISDestroy(&galleedges)); 1449a75bf7bfSStefano Zampini 1450a75bf7bfSStefano Zampini /* identify dofs we must zero if importing user-defined near nullspace from pmat */ 1451a75bf7bfSStefano Zampini PetscCall(VecSet(E, 1.0)); 1452a75bf7bfSStefano Zampini PetscCall(VecSetValues(E, cum, eedgesidxs, NULL, INSERT_VALUES)); 1453a75bf7bfSStefano Zampini PetscCall(VecAssemblyBegin(E)); 1454a75bf7bfSStefano Zampini PetscCall(VecAssemblyEnd(E)); 1455a75bf7bfSStefano Zampini PetscCall(VecGetArrayRead(E, &evals)); 1456a75bf7bfSStefano Zampini for (i = 0, cum = 0; i < pc->pmat->rmap->n; i++) 1457a75bf7bfSStefano Zampini if (evals[i] == 0.0) eedgesidxs[cum++] = i + pc->pmat->rmap->rstart; 1458a75bf7bfSStefano Zampini PetscCall(VecRestoreArrayRead(E, &evals)); 1459a75bf7bfSStefano Zampini PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cum, eedgesidxs, PETSC_COPY_VALUES, &is_E_to_zero)); 1460a75bf7bfSStefano Zampini PetscCall(PetscFree(eedgesidxs)); 1461a75bf7bfSStefano Zampini 1462a75bf7bfSStefano Zampini PetscCall(PetscObjectCompose((PetscObject)nnsp_vscat, "__V_Vec", (PetscObject)V)); 1463a75bf7bfSStefano Zampini PetscCall(PetscObjectCompose((PetscObject)nnsp_vscat, "__E_Vec", (PetscObject)E)); 1464a75bf7bfSStefano Zampini PetscCall(PetscObjectCompose((PetscObject)nnsp_vscat, "__E_zero", (PetscObject)is_E_to_zero)); 1465a75bf7bfSStefano Zampini PetscCall(ISDestroy(&is_E_to_zero)); 1466a75bf7bfSStefano Zampini PetscCall(VecDestroy(&V)); 1467a75bf7bfSStefano Zampini PetscCall(VecDestroy(&E)); 1468a75bf7bfSStefano Zampini } 14691e0482f5SStefano Zampini #if defined(PRINT_GDET) 14701e0482f5SStefano Zampini inc = 0; 14711e0482f5SStefano Zampini lev = pcbddc->current_level; 14721e0482f5SStefano Zampini #endif 1473213b8bfaSStefano Zampini 1474213b8bfaSStefano Zampini /* Insert values in the change of basis matrix */ 1475a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 1476a13144ffSStefano Zampini Mat Gins = NULL, GKins = NULL; 14771e0482f5SStefano Zampini IS cornersis = NULL; 14781e0482f5SStefano Zampini PetscScalar cvals[2]; 1479a13144ffSStefano Zampini 148048a46eb9SPierre Jolivet if (pcbddc->nedcG) PetscCall(ISCreateGeneral(PETSC_COMM_SELF, 2, corners + 2 * i, PETSC_USE_POINTER, &cornersis)); 14819566063dSJacob Faibussowitsch PetscCall(PCBDDCComputeNedelecChangeEdge(lG, eedges[i], extrows[i], extcols[i], cornersis, &Gins, &GKins, cvals, work, rwork)); 1482a13144ffSStefano Zampini if (Gins && GKins) { 14831683a169SBarry Smith const PetscScalar *data; 1484a13144ffSStefano Zampini const PetscInt *rows, *cols; 1485a13144ffSStefano Zampini PetscInt nrh, nch, nrc, ncc; 1486a13144ffSStefano Zampini 14879566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &cols)); 1488a13144ffSStefano Zampini /* H1 */ 14899566063dSJacob Faibussowitsch PetscCall(ISGetIndices(extrows[i], &rows)); 14909566063dSJacob Faibussowitsch PetscCall(MatGetSize(Gins, &nrh, &nch)); 14919566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(Gins, &data)); 14929566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(T, nrh, rows, nch, cols, data, INSERT_VALUES)); 14939566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(Gins, &data)); 14949566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(extrows[i], &rows)); 1495a13144ffSStefano Zampini /* complement */ 14969566063dSJacob Faibussowitsch PetscCall(MatGetSize(GKins, &nrc, &ncc)); 149763a3b9bcSJacob Faibussowitsch PetscCheck(ncc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Constant function has not been generated for coarse edge %" PetscInt_FMT, i); 149863a3b9bcSJacob 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); 149963a3b9bcSJacob 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); 15009566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(GKins, &data)); 15019566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(T, nrc, cols, ncc, cols + nch, data, INSERT_VALUES)); 15029566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(GKins, &data)); 15031e0482f5SStefano Zampini 15041e0482f5SStefano Zampini /* coarse discrete gradient */ 15051e0482f5SStefano Zampini if (pcbddc->nedcG) { 15061e0482f5SStefano Zampini PetscInt cols[2]; 15071e0482f5SStefano Zampini 15081e0482f5SStefano Zampini cols[0] = 2 * i; 15091e0482f5SStefano Zampini cols[1] = 2 * i + 1; 15109566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(pcbddc->nedcG, 1, &i, 2, cols, cvals, INSERT_VALUES)); 15111e0482f5SStefano Zampini } 15129566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &cols)); 1513a13144ffSStefano Zampini } 15149566063dSJacob Faibussowitsch PetscCall(ISDestroy(&extrows[i])); 15159566063dSJacob Faibussowitsch PetscCall(ISDestroy(&extcols[i])); 15169566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cornersis)); 15179566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Gins)); 15189566063dSJacob Faibussowitsch PetscCall(MatDestroy(&GKins)); 1519a13144ffSStefano Zampini } 15200b61a303SStefano Zampini 1521a75bf7bfSStefano Zampini /* import edge constraints */ 1522a75bf7bfSStefano Zampini if (nnsp_vscat) { 1523a75bf7bfSStefano Zampini Vec V, E, *quadvecs; 1524a75bf7bfSStefano Zampini PetscInt nvecs, nvecs_orth; 1525a75bf7bfSStefano Zampini MatNullSpace onnsp = NULL; 1526a75bf7bfSStefano Zampini PetscBool onnsp_has_const = PETSC_FALSE; 1527a75bf7bfSStefano Zampini const Vec *onnsp_vecs = NULL; 1528a75bf7bfSStefano Zampini PetscInt onnsp_nvecs = 0, new_nnsp_nvecs, old_nnsp_nvecs; 1529a75bf7bfSStefano Zampini IS is_E_to_zero; 15300b61a303SStefano Zampini 1531a75bf7bfSStefano Zampini /* import nearnullspace from preconditioning matrix if user-defined */ 1532a75bf7bfSStefano Zampini PetscCall(MatGetNearNullSpace(pc->pmat, &onnsp)); 1533a75bf7bfSStefano Zampini if (onnsp) { 1534a75bf7bfSStefano Zampini PetscBool isinternal; 15350b61a303SStefano Zampini 1536a75bf7bfSStefano Zampini PetscCall(PetscStrcmp("_internal_BDDC_nedelec_nnsp", ((PetscObject)onnsp)->name, &isinternal)); 1537a75bf7bfSStefano Zampini if (!isinternal) PetscCall(MatNullSpaceGetVecs(onnsp, &onnsp_has_const, &onnsp_nvecs, &onnsp_vecs)); 15380b61a303SStefano Zampini } 1539a75bf7bfSStefano Zampini new_nnsp_nvecs = nnsp_nvecs + (nnsp_has_const ? 1 : 0); 1540a75bf7bfSStefano Zampini old_nnsp_nvecs = onnsp_nvecs + (onnsp_has_const ? 1 : 0); 1541a75bf7bfSStefano Zampini nvecs = old_nnsp_nvecs + new_nnsp_nvecs; 1542a75bf7bfSStefano Zampini PetscCall(PetscMalloc1(nvecs, &quadvecs)); 1543a75bf7bfSStefano Zampini 1544a75bf7bfSStefano Zampini PetscCall(PetscObjectQuery((PetscObject)nnsp_vscat, "__V_Vec", (PetscObject *)&V)); 1545a75bf7bfSStefano Zampini PetscCall(PetscObjectQuery((PetscObject)nnsp_vscat, "__E_Vec", (PetscObject *)&E)); 1546a75bf7bfSStefano Zampini PetscCall(PetscObjectQuery((PetscObject)nnsp_vscat, "__E_zero", (PetscObject *)&is_E_to_zero)); 1547a75bf7bfSStefano Zampini for (i = 0; i < nvecs; i++) PetscCall(VecDuplicate(E, &quadvecs[i])); 1548a75bf7bfSStefano Zampini cum = 0; 1549a75bf7bfSStefano Zampini if (nnsp_has_const) { 1550a75bf7bfSStefano Zampini PetscCall(VecSet(V, 1.0)); 1551a75bf7bfSStefano Zampini PetscCall(VecScatterBegin(nnsp_vscat, V, quadvecs[0], INSERT_VALUES, SCATTER_FORWARD)); 1552a75bf7bfSStefano Zampini PetscCall(VecScatterEnd(nnsp_vscat, V, quadvecs[0], INSERT_VALUES, SCATTER_FORWARD)); 1553a75bf7bfSStefano Zampini cum = 1; 1554a75bf7bfSStefano Zampini } 1555a75bf7bfSStefano Zampini for (i = 0; i < nnsp_nvecs; i++) { 1556a75bf7bfSStefano Zampini PetscCall(VecScatterBegin(nnsp_vscat, nnsp_vecs[i], quadvecs[i + cum], INSERT_VALUES, SCATTER_FORWARD)); 1557a75bf7bfSStefano Zampini PetscCall(VecScatterEnd(nnsp_vscat, nnsp_vecs[i], quadvecs[i + cum], INSERT_VALUES, SCATTER_FORWARD)); 1558a75bf7bfSStefano Zampini } 1559a75bf7bfSStefano Zampini 1560a75bf7bfSStefano Zampini /* Now add old nnsp if present */ 1561a75bf7bfSStefano Zampini cum = 0; 1562a75bf7bfSStefano Zampini if (onnsp_has_const) { 1563a75bf7bfSStefano Zampini PetscCall(VecSet(quadvecs[new_nnsp_nvecs], 1.0)); 1564a75bf7bfSStefano Zampini PetscCall(VecISSet(quadvecs[new_nnsp_nvecs], is_E_to_zero, 0)); 1565a75bf7bfSStefano Zampini cum = 1; 1566a75bf7bfSStefano Zampini } 1567a75bf7bfSStefano Zampini for (i = 0; i < onnsp_nvecs; i++) { 1568a75bf7bfSStefano Zampini PetscCall(VecCopy(onnsp_vecs[i], quadvecs[i + cum + new_nnsp_nvecs])); 1569a75bf7bfSStefano Zampini PetscCall(VecISSet(quadvecs[i + cum + new_nnsp_nvecs], is_E_to_zero, 0)); 1570a75bf7bfSStefano Zampini } 1571a75bf7bfSStefano Zampini nvecs_orth = nvecs; 1572a75bf7bfSStefano Zampini PetscCall(PCBDDCOrthonormalizeVecs(&nvecs_orth, quadvecs)); 1573a75bf7bfSStefano Zampini PetscCall(MatNullSpaceCreate(PetscObjectComm((PetscObject)pc), PETSC_FALSE, nvecs_orth, quadvecs, &nnsp)); 1574a75bf7bfSStefano Zampini for (i = 0; i < nvecs; i++) PetscCall(VecDestroy(&quadvecs[i])); 1575a75bf7bfSStefano Zampini PetscCall(PetscFree(quadvecs)); 1576a75bf7bfSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)nnsp, "_internal_BDDC_nedelec_nnsp")); 15770b61a303SStefano Zampini PetscCall(MatSetNearNullSpace(pc->pmat, nnsp)); 15780b61a303SStefano Zampini PetscCall(MatNullSpaceDestroy(&nnsp)); 15790b61a303SStefano Zampini } 1580a75bf7bfSStefano Zampini PetscCall(VecScatterDestroy(&nnsp_vscat)); 1581a75bf7bfSStefano Zampini PetscCall(ISLocalToGlobalMappingDestroy(&vl2g)); 15829566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&el2g)); 1583732a5147SStefano Zampini PetscCall(ISLocalToGlobalMappingDestroy(&al2g)); 1584a13144ffSStefano Zampini 1585a13144ffSStefano Zampini /* Start assembling */ 15869566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(T, MAT_FINAL_ASSEMBLY)); 15871baa6e33SBarry Smith if (pcbddc->nedcG) PetscCall(MatAssemblyBegin(pcbddc->nedcG, MAT_FINAL_ASSEMBLY)); 1588a13144ffSStefano Zampini 1589a13144ffSStefano Zampini /* Free */ 1590c2151214SStefano Zampini if (fl2g) { 15919566063dSJacob Faibussowitsch PetscCall(ISDestroy(&primals)); 159248a46eb9SPierre Jolivet for (i = 0; i < nee; i++) PetscCall(ISDestroy(&eedges[i])); 15939566063dSJacob Faibussowitsch PetscCall(PetscFree(eedges)); 1594c2151214SStefano Zampini } 1595eee23b56SStefano Zampini 1596eee23b56SStefano Zampini /* hack mat_graph with primal dofs on the coarse edges */ 1597eee23b56SStefano Zampini { 1598eee23b56SStefano Zampini PCBDDCGraph graph = pcbddc->mat_graph; 1599eee23b56SStefano Zampini PetscInt *oqueue = graph->queue; 1600eee23b56SStefano Zampini PetscInt *ocptr = graph->cptr; 1601eee23b56SStefano Zampini PetscInt ncc, *idxs; 1602eee23b56SStefano Zampini 1603eee23b56SStefano Zampini /* find first primal edge */ 1604eee23b56SStefano Zampini if (pcbddc->nedclocal) { 16059566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->nedclocal, (const PetscInt **)&idxs)); 1606eee23b56SStefano Zampini } else { 16071baa6e33SBarry Smith if (fl2g) PetscCall(ISLocalToGlobalMappingApply(fl2g, nee, cedges, cedges)); 1608eee23b56SStefano Zampini idxs = cedges; 1609eee23b56SStefano Zampini } 1610eee23b56SStefano Zampini cum = 0; 1611eee23b56SStefano Zampini while (cum < nee && cedges[cum] < 0) cum++; 1612eee23b56SStefano Zampini 1613eee23b56SStefano Zampini /* adapt connected components */ 16149566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(graph->nvtxs + 1, &graph->cptr, ocptr[graph->ncc], &graph->queue)); 1615eee23b56SStefano Zampini graph->cptr[0] = 0; 1616eee23b56SStefano Zampini for (i = 0, ncc = 0; i < graph->ncc; i++) { 1617eee23b56SStefano Zampini PetscInt lc = ocptr[i + 1] - ocptr[i]; 1618eee23b56SStefano Zampini if (cum != nee && oqueue[ocptr[i + 1] - 1] == cedges[cum]) { /* this cc has a primal dof */ 1619eee23b56SStefano Zampini graph->cptr[ncc + 1] = graph->cptr[ncc] + 1; 1620eee23b56SStefano Zampini graph->queue[graph->cptr[ncc]] = cedges[cum]; 1621eee23b56SStefano Zampini ncc++; 1622eee23b56SStefano Zampini lc--; 1623eee23b56SStefano Zampini cum++; 1624eee23b56SStefano Zampini while (cum < nee && cedges[cum] < 0) cum++; 1625eee23b56SStefano Zampini } 1626eee23b56SStefano Zampini graph->cptr[ncc + 1] = graph->cptr[ncc] + lc; 1627eee23b56SStefano Zampini for (j = 0; j < lc; j++) graph->queue[graph->cptr[ncc] + j] = oqueue[ocptr[i] + j]; 1628eee23b56SStefano Zampini ncc++; 1629eee23b56SStefano Zampini } 1630eee23b56SStefano Zampini graph->ncc = ncc; 163148a46eb9SPierre Jolivet if (pcbddc->nedclocal) PetscCall(ISRestoreIndices(pcbddc->nedclocal, (const PetscInt **)&idxs)); 16329566063dSJacob Faibussowitsch PetscCall(PetscFree2(ocptr, oqueue)); 1633eee23b56SStefano Zampini } 16349566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&fl2g)); 16359566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, NULL, NULL, &nee, &alleedges, &allprimals)); 16369566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphResetCSR(pcbddc->mat_graph)); 1637eee23b56SStefano Zampini 16389566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nedfieldlocal)); 16399566063dSJacob Faibussowitsch PetscCall(PetscFree(extrow)); 16409566063dSJacob Faibussowitsch PetscCall(PetscFree2(work, rwork)); 16419566063dSJacob Faibussowitsch PetscCall(PetscFree(corners)); 16429566063dSJacob Faibussowitsch PetscCall(PetscFree(cedges)); 16439566063dSJacob Faibussowitsch PetscCall(PetscFree(extrows)); 16449566063dSJacob Faibussowitsch PetscCall(PetscFree(extcols)); 16459566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lG)); 1646a13144ffSStefano Zampini 1647a13144ffSStefano Zampini /* Complete assembling */ 16489566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(T, MAT_FINAL_ASSEMBLY)); 16499de2952eSStefano Zampini PetscCall(MatViewFromOptions(T, (PetscObject)pc, "-pc_bddc_nedelec_change_view")); 16501e0482f5SStefano Zampini if (pcbddc->nedcG) { 16519566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->nedcG, MAT_FINAL_ASSEMBLY)); 1652a4cdd7efSStefano Zampini PetscCall(MatViewFromOptions(pcbddc->nedcG, (PetscObject)pc, "-pc_bddc_nedelec_coarse_change_view")); 16531e0482f5SStefano Zampini } 1654a13144ffSStefano Zampini 16550b61a303SStefano Zampini PetscCall(ISDestroy(&elements_corners)); 16560b61a303SStefano Zampini 1657a13144ffSStefano Zampini /* set change of basis */ 16580b61a303SStefano Zampini PetscCall(PCBDDCSetChangeOfBasisMat(pc, T, PETSC_FALSE)); 16599566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 16603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1661a13144ffSStefano Zampini } 1662a13144ffSStefano Zampini 1663d8203eabSStefano Zampini /* the near-null space of BDDC carries information on quadrature weights, 1664d8203eabSStefano Zampini and these can be collinear -> so cheat with MatNullSpaceCreate 1665d8203eabSStefano Zampini and create a suitable set of basis vectors first */ 1666d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCNullSpaceCreate(MPI_Comm comm, PetscBool has_const, PetscInt nvecs, Vec quad_vecs[], MatNullSpace *nnsp) 1667d71ae5a4SJacob Faibussowitsch { 1668d8203eabSStefano Zampini PetscInt i; 1669d8203eabSStefano Zampini 1670d8203eabSStefano Zampini PetscFunctionBegin; 1671d8203eabSStefano Zampini for (i = 0; i < nvecs; i++) { 1672d8203eabSStefano Zampini PetscInt first, last; 1673d8203eabSStefano Zampini 16749566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(quad_vecs[i], &first, &last)); 16757827d75bSBarry Smith PetscCheck(last - first >= 2 * nvecs || !has_const, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented"); 1676d8203eabSStefano Zampini if (i >= first && i < last) { 1677d8203eabSStefano Zampini PetscScalar *data; 16789566063dSJacob Faibussowitsch PetscCall(VecGetArray(quad_vecs[i], &data)); 1679d8203eabSStefano Zampini if (!has_const) { 1680d8203eabSStefano Zampini data[i - first] = 1.; 1681d8203eabSStefano Zampini } else { 168286fa73c5SStefano Zampini data[2 * i - first] = 1. / PetscSqrtReal(2.); 168386fa73c5SStefano Zampini data[2 * i - first + 1] = -1. / PetscSqrtReal(2.); 1684d8203eabSStefano Zampini } 16859566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(quad_vecs[i], &data)); 1686d8203eabSStefano Zampini } 16879566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)quad_vecs[i])); 1688d8203eabSStefano Zampini } 16899566063dSJacob Faibussowitsch PetscCall(MatNullSpaceCreate(comm, has_const, nvecs, quad_vecs, nnsp)); 1690d8203eabSStefano Zampini for (i = 0; i < nvecs; i++) { /* reset vectors */ 1691d8203eabSStefano Zampini PetscInt first, last; 16929566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(quad_vecs[i])); 16939566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(quad_vecs[i], &first, &last)); 1694d8203eabSStefano Zampini if (i >= first && i < last) { 1695d8203eabSStefano Zampini PetscScalar *data; 16969566063dSJacob Faibussowitsch PetscCall(VecGetArray(quad_vecs[i], &data)); 1697d8203eabSStefano Zampini if (!has_const) { 1698d8203eabSStefano Zampini data[i - first] = 0.; 1699d8203eabSStefano Zampini } else { 170086fa73c5SStefano Zampini data[2 * i - first] = 0.; 170186fa73c5SStefano Zampini data[2 * i - first + 1] = 0.; 1702d8203eabSStefano Zampini } 17039566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(quad_vecs[i], &data)); 1704d8203eabSStefano Zampini } 17059566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)quad_vecs[i])); 17069566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(quad_vecs[i])); 1707d8203eabSStefano Zampini } 17083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1709d8203eabSStefano Zampini } 1710d8203eabSStefano Zampini 1711d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, PetscBool transpose, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp) 1712d71ae5a4SJacob Faibussowitsch { 1713a198735bSStefano Zampini Mat loc_divudotp; 17149de2952eSStefano Zampini Vec p, v, quad_vec; 17158ae0ca82SStefano Zampini ISLocalToGlobalMapping map; 17169de2952eSStefano Zampini PetscScalar *array; 1717669cc0f4SStefano Zampini 1718669cc0f4SStefano Zampini PetscFunctionBegin; 17199566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, &quad_vec, NULL)); 17208ae0ca82SStefano Zampini if (!transpose) { 17219566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(A, &map, NULL)); 17228ae0ca82SStefano Zampini } else { 17239566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(A, NULL, &map)); 17248ae0ca82SStefano Zampini } 17259de2952eSStefano Zampini PetscCall(PCBDDCNullSpaceCreate(PetscObjectComm((PetscObject)A), PETSC_FALSE, 1, &quad_vec, nnsp)); 17269de2952eSStefano Zampini PetscCall(VecLockReadPop(quad_vec)); 17279de2952eSStefano Zampini PetscCall(VecSetLocalToGlobalMapping(quad_vec, map)); 1728d8203eabSStefano Zampini 1729669cc0f4SStefano Zampini /* compute local quad vec */ 17309566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(divudotp, &loc_divudotp)); 17318ae0ca82SStefano Zampini if (!transpose) { 17329566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(loc_divudotp, &v, &p)); 17338ae0ca82SStefano Zampini } else { 17349566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(loc_divudotp, &p, &v)); 17358ae0ca82SStefano Zampini } 17369de2952eSStefano Zampini /* the assumption here is that the constant vector interpolates the constant on the L2 conforming space */ 17379566063dSJacob Faibussowitsch PetscCall(VecSet(p, 1.)); 17388ae0ca82SStefano Zampini if (!transpose) { 17399566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(loc_divudotp, p, v)); 17408ae0ca82SStefano Zampini } else { 17419566063dSJacob Faibussowitsch PetscCall(MatMult(loc_divudotp, p, v)); 17428ae0ca82SStefano Zampini } 17439de2952eSStefano Zampini PetscCall(VecDestroy(&p)); 1744fa23a32eSStefano Zampini if (vl2l) { 1745187c917aSStefano Zampini Mat lA; 1746187c917aSStefano Zampini VecScatter sc; 17479de2952eSStefano Zampini Vec vins; 1748187c917aSStefano Zampini 17499566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A, &lA)); 17509566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(lA, &vins, NULL)); 17519566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(v, NULL, vins, vl2l, &sc)); 17529566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sc, v, vins, INSERT_VALUES, SCATTER_FORWARD)); 17539566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sc, v, vins, INSERT_VALUES, SCATTER_FORWARD)); 17549566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sc)); 17559566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 17569de2952eSStefano Zampini v = vins; 1757669cc0f4SStefano Zampini } 17589de2952eSStefano Zampini 17599de2952eSStefano Zampini /* mask summation of interface values */ 17609de2952eSStefano Zampini PetscInt n, *mmask, *mask, *idxs, nmr, nr; 17619de2952eSStefano Zampini const PetscInt *degree; 17629de2952eSStefano Zampini PetscSF msf; 17639de2952eSStefano Zampini 17649de2952eSStefano Zampini PetscCall(VecGetLocalSize(v, &n)); 17659de2952eSStefano Zampini PetscCall(PetscSFGetGraph(graph->interface_subset_sf, &nr, NULL, NULL, NULL)); 17669de2952eSStefano Zampini PetscCall(PetscSFGetMultiSF(graph->interface_subset_sf, &msf)); 17679de2952eSStefano Zampini PetscCall(PetscSFGetGraph(msf, &nmr, NULL, NULL, NULL)); 17689de2952eSStefano Zampini PetscCall(PetscCalloc3(nmr, &mmask, n, &mask, n, &idxs)); 17699de2952eSStefano Zampini PetscCall(PetscSFComputeDegreeBegin(graph->interface_subset_sf, °ree)); 17709de2952eSStefano Zampini PetscCall(PetscSFComputeDegreeEnd(graph->interface_subset_sf, °ree)); 17719de2952eSStefano Zampini for (PetscInt i = 0, c = 0; i < nr; i++) { 17729de2952eSStefano Zampini mmask[c] = 1; 17739de2952eSStefano Zampini c += degree[i]; 17749de2952eSStefano Zampini } 17759de2952eSStefano Zampini PetscCall(PetscSFScatterBegin(graph->interface_subset_sf, MPIU_INT, mmask, mask)); 17769de2952eSStefano Zampini PetscCall(PetscSFScatterEnd(graph->interface_subset_sf, MPIU_INT, mmask, mask)); 17779de2952eSStefano Zampini PetscCall(VecGetArray(v, &array)); 17789de2952eSStefano Zampini for (PetscInt i = 0; i < n; i++) { 17799de2952eSStefano Zampini array[i] *= mask[i]; 17809de2952eSStefano Zampini idxs[i] = i; 17819de2952eSStefano Zampini } 17829de2952eSStefano Zampini PetscCall(VecSetValuesLocal(quad_vec, n, idxs, array, ADD_VALUES)); 17839de2952eSStefano Zampini PetscCall(VecRestoreArray(v, &array)); 17849de2952eSStefano Zampini PetscCall(PetscFree3(mmask, mask, idxs)); 17859de2952eSStefano Zampini PetscCall(VecDestroy(&v)); 17869de2952eSStefano Zampini PetscCall(VecAssemblyBegin(quad_vec)); 17879de2952eSStefano Zampini PetscCall(VecAssemblyEnd(quad_vec)); 17889de2952eSStefano Zampini PetscCall(VecViewFromOptions(quad_vec, NULL, "-pc_bddc_quad_vec_view")); 17899de2952eSStefano Zampini PetscCall(VecLockReadPush(quad_vec)); 17909de2952eSStefano Zampini PetscCall(VecDestroy(&quad_vec)); 17913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1792669cc0f4SStefano Zampini } 1793669cc0f4SStefano Zampini 1794d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCAddPrimalVerticesLocalIS(PC pc, IS primalv) 1795d71ae5a4SJacob Faibussowitsch { 17967620a527SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 17977620a527SStefano Zampini 17987620a527SStefano Zampini PetscFunctionBegin; 17997620a527SStefano Zampini if (primalv) { 18007620a527SStefano Zampini if (pcbddc->user_primal_vertices_local) { 18017620a527SStefano Zampini IS list[2], newp; 18027620a527SStefano Zampini 18037620a527SStefano Zampini list[0] = primalv; 18047620a527SStefano Zampini list[1] = pcbddc->user_primal_vertices_local; 18059566063dSJacob Faibussowitsch PetscCall(ISConcatenate(PetscObjectComm((PetscObject)pc), 2, list, &newp)); 18069566063dSJacob Faibussowitsch PetscCall(ISSortRemoveDups(newp)); 18079566063dSJacob Faibussowitsch PetscCall(ISDestroy(&list[1])); 18087620a527SStefano Zampini pcbddc->user_primal_vertices_local = newp; 18097620a527SStefano Zampini } else { 18109566063dSJacob Faibussowitsch PetscCall(PCBDDCSetPrimalVerticesLocalIS(pc, primalv)); 18117620a527SStefano Zampini } 18127620a527SStefano Zampini } 18133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18147620a527SStefano Zampini } 1815669cc0f4SStefano Zampini 1816d71ae5a4SJacob Faibussowitsch static PetscErrorCode func_coords_private(PetscInt dim, PetscReal t, const PetscReal X[], PetscInt Nf, PetscScalar *out, void *ctx) 1817d71ae5a4SJacob Faibussowitsch { 18181c7a958bSStefano Zampini PetscInt f, *comp = (PetscInt *)ctx; 18191c7a958bSStefano Zampini 18201c7a958bSStefano Zampini PetscFunctionBegin; 18211c7a958bSStefano Zampini for (f = 0; f < Nf; f++) out[f] = X[*comp]; 18223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18231c7a958bSStefano Zampini } 1824674ae819SStefano Zampini 1825d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc) 1826d71ae5a4SJacob Faibussowitsch { 18271f4df5f7SStefano Zampini Vec local, global; 18281f4df5f7SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 18291f4df5f7SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 18305c5e10d6SStefano Zampini PetscBool monolithic = PETSC_FALSE; 18311f4df5f7SStefano Zampini 18321f4df5f7SStefano Zampini PetscFunctionBegin; 1833d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)pc), ((PetscObject)pc)->prefix, "BDDC topology options", "PC"); 18349566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_monolithic", "Discard any information on dofs splitting", NULL, monolithic, &monolithic, NULL)); 1835d0609cedSBarry Smith PetscOptionsEnd(); 18361f4df5f7SStefano Zampini /* need to convert from global to local topology information and remove references to information in global ordering */ 18379566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(pc->pmat, &global, NULL)); 18389566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(matis->A, &local, NULL)); 18399566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(global, PETSC_TRUE)); 18409566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(local, PETSC_TRUE)); 18416a8fc67bSStefano Zampini if (monolithic) { /* just get block size to properly compute vertices */ 184248a46eb9SPierre Jolivet if (pcbddc->vertex_size == 1) PetscCall(MatGetBlockSize(pc->pmat, &pcbddc->vertex_size)); 18436a8fc67bSStefano Zampini goto boundary; 18446a8fc67bSStefano Zampini } 18455c5e10d6SStefano Zampini 18461f4df5f7SStefano Zampini if (pcbddc->user_provided_isfordofs) { 18471f4df5f7SStefano Zampini if (pcbddc->n_ISForDofs) { 18481f4df5f7SStefano Zampini PetscInt i; 18490c85b387SStefano Zampini 18509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->n_ISForDofs, &pcbddc->ISForDofsLocal)); 18511f4df5f7SStefano Zampini for (i = 0; i < pcbddc->n_ISForDofs; i++) { 18520c85b387SStefano Zampini PetscInt bs; 18530c85b387SStefano Zampini 18549566063dSJacob Faibussowitsch PetscCall(PCBDDCGlobalToLocal(matis->rctx, global, local, pcbddc->ISForDofs[i], &pcbddc->ISForDofsLocal[i])); 18559566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(pcbddc->ISForDofs[i], &bs)); 18569566063dSJacob Faibussowitsch PetscCall(ISSetBlockSize(pcbddc->ISForDofsLocal[i], bs)); 18579566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->ISForDofs[i])); 18581f4df5f7SStefano Zampini } 18591f4df5f7SStefano Zampini pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs; 18601f4df5f7SStefano Zampini pcbddc->n_ISForDofs = 0; 18619566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->ISForDofs)); 18621f4df5f7SStefano Zampini } 18631f4df5f7SStefano Zampini } else { 186421ef3d20SStefano Zampini if (!pcbddc->n_ISForDofsLocal) { /* field split not present */ 186521ef3d20SStefano Zampini DM dm; 186621ef3d20SStefano Zampini 18679566063dSJacob Faibussowitsch PetscCall(MatGetDM(pc->pmat, &dm)); 186848a46eb9SPierre Jolivet if (!dm) PetscCall(PCGetDM(pc, &dm)); 186921ef3d20SStefano Zampini if (dm) { 187021ef3d20SStefano Zampini IS *fields; 187121ef3d20SStefano Zampini PetscInt nf, i; 18720c85b387SStefano Zampini 18739566063dSJacob Faibussowitsch PetscCall(DMCreateFieldDecomposition(dm, &nf, NULL, &fields, NULL)); 18749566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nf, &pcbddc->ISForDofsLocal)); 187521ef3d20SStefano Zampini for (i = 0; i < nf; i++) { 18760c85b387SStefano Zampini PetscInt bs; 18770c85b387SStefano Zampini 18789566063dSJacob Faibussowitsch PetscCall(PCBDDCGlobalToLocal(matis->rctx, global, local, fields[i], &pcbddc->ISForDofsLocal[i])); 18799566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(fields[i], &bs)); 18809566063dSJacob Faibussowitsch PetscCall(ISSetBlockSize(pcbddc->ISForDofsLocal[i], bs)); 18819566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fields[i])); 188221ef3d20SStefano Zampini } 18839566063dSJacob Faibussowitsch PetscCall(PetscFree(fields)); 188421ef3d20SStefano Zampini pcbddc->n_ISForDofsLocal = nf; 188521ef3d20SStefano Zampini } else { /* See if MATIS has fields attached by the conversion from MatNest */ 188621ef3d20SStefano Zampini PetscContainer c; 188721ef3d20SStefano Zampini 18889566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc->pmat, "_convert_nest_lfields", (PetscObject *)&c)); 188921ef3d20SStefano Zampini if (c) { 189021ef3d20SStefano Zampini MatISLocalFields lf; 18919566063dSJacob Faibussowitsch PetscCall(PetscContainerGetPointer(c, (void **)&lf)); 18929566063dSJacob Faibussowitsch PetscCall(PCBDDCSetDofsSplittingLocal(pc, lf->nr, lf->rf)); 189321ef3d20SStefano Zampini } else { /* fallback, create the default fields if bs > 1 */ 18941f4df5f7SStefano Zampini PetscInt i, n = matis->A->rmap->n; 18959566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(pc->pmat, &i)); 189621ef3d20SStefano Zampini if (i > 1) { 1897986cdee1SStefano Zampini pcbddc->n_ISForDofsLocal = i; 18989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->n_ISForDofsLocal, &pcbddc->ISForDofsLocal)); 189948a46eb9SPierre 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])); 19001f4df5f7SStefano Zampini } 190121ef3d20SStefano Zampini } 190221ef3d20SStefano Zampini } 19037a0e7b2cSstefano_zampini } else { 19047a0e7b2cSstefano_zampini PetscInt i; 190548a46eb9SPierre Jolivet for (i = 0; i < pcbddc->n_ISForDofsLocal; i++) PetscCall(PCBDDCConsistencyCheckIS(pc, MPI_LAND, &pcbddc->ISForDofsLocal[i])); 19061f4df5f7SStefano Zampini } 1907986cdee1SStefano Zampini } 19081f4df5f7SStefano Zampini 19095c5e10d6SStefano Zampini boundary: 19101f4df5f7SStefano Zampini if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) { 19119566063dSJacob Faibussowitsch PetscCall(PCBDDCGlobalToLocal(matis->rctx, global, local, pcbddc->DirichletBoundaries, &pcbddc->DirichletBoundariesLocal)); 19127a0e7b2cSstefano_zampini } else if (pcbddc->DirichletBoundariesLocal) { 19139566063dSJacob Faibussowitsch PetscCall(PCBDDCConsistencyCheckIS(pc, MPI_LAND, &pcbddc->DirichletBoundariesLocal)); 19141f4df5f7SStefano Zampini } 19151f4df5f7SStefano Zampini if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) { 19169566063dSJacob Faibussowitsch PetscCall(PCBDDCGlobalToLocal(matis->rctx, global, local, pcbddc->NeumannBoundaries, &pcbddc->NeumannBoundariesLocal)); 19177a0e7b2cSstefano_zampini } else if (pcbddc->NeumannBoundariesLocal) { 19189566063dSJacob Faibussowitsch PetscCall(PCBDDCConsistencyCheckIS(pc, MPI_LOR, &pcbddc->NeumannBoundariesLocal)); 19191f4df5f7SStefano Zampini } 192048a46eb9SPierre 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)); 19219566063dSJacob Faibussowitsch PetscCall(VecDestroy(&global)); 19229566063dSJacob Faibussowitsch PetscCall(VecDestroy(&local)); 19239de2952eSStefano Zampini /* detect local disconnected subdomains if requested or needed */ 19249de2952eSStefano Zampini if (pcbddc->detect_disconnected || matis->allow_repeated) { 19257620a527SStefano Zampini IS primalv = NULL; 19260b61a303SStefano Zampini PetscInt nel; 19278361f951SStefano Zampini PetscBool filter = pcbddc->detect_disconnected_filter; 19287a0e7b2cSstefano_zampini 19290b61a303SStefano Zampini for (PetscInt i = 0; i < pcbddc->n_local_subs; i++) PetscCall(ISDestroy(&pcbddc->local_subs[i])); 19309566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->local_subs)); 19310b61a303SStefano Zampini PetscCall(MatGetVariableBlockSizes(matis->A, &nel, NULL)); 19320b61a303SStefano Zampini if (matis->allow_repeated && nel) { 19330b61a303SStefano Zampini const PetscInt *elsizes; 19340b61a303SStefano Zampini 19350b61a303SStefano Zampini pcbddc->n_local_subs = nel; 19360b61a303SStefano Zampini PetscCall(MatGetVariableBlockSizes(matis->A, NULL, &elsizes)); 19370b61a303SStefano Zampini PetscCall(PetscMalloc1(nel, &pcbddc->local_subs)); 19380b61a303SStefano Zampini for (PetscInt i = 0, c = 0; i < nel; i++) { 19390b61a303SStefano Zampini PetscCall(ISCreateStride(PETSC_COMM_SELF, elsizes[i], c, 1, &pcbddc->local_subs[i])); 19400b61a303SStefano Zampini c += elsizes[i]; 19410b61a303SStefano Zampini } 19420b61a303SStefano Zampini } else { 19439566063dSJacob Faibussowitsch PetscCall(PCBDDCDetectDisconnectedComponents(pc, filter, &pcbddc->n_local_subs, &pcbddc->local_subs, &primalv)); 19440b61a303SStefano Zampini } 19459566063dSJacob Faibussowitsch PetscCall(PCBDDCAddPrimalVerticesLocalIS(pc, primalv)); 19469566063dSJacob Faibussowitsch PetscCall(ISDestroy(&primalv)); 19477620a527SStefano Zampini } 19487620a527SStefano Zampini /* early stage corner detection */ 19497620a527SStefano Zampini { 19507620a527SStefano Zampini DM dm; 19517620a527SStefano Zampini 19529566063dSJacob Faibussowitsch PetscCall(MatGetDM(pc->pmat, &dm)); 195348a46eb9SPierre Jolivet if (!dm) PetscCall(PCGetDM(pc, &dm)); 19547620a527SStefano Zampini if (dm) { 19557620a527SStefano Zampini PetscBool isda; 19567620a527SStefano Zampini 19579566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMDA, &isda)); 19587620a527SStefano Zampini if (isda) { 19597620a527SStefano Zampini ISLocalToGlobalMapping l2l; 19607620a527SStefano Zampini IS corners; 19617620a527SStefano Zampini Mat lA; 19624f819b78SStefano Zampini PetscBool gl, lo; 19637620a527SStefano Zampini 19644f819b78SStefano Zampini { 19654f819b78SStefano Zampini Vec cvec; 19664f819b78SStefano Zampini const PetscScalar *coords; 19674f819b78SStefano Zampini PetscInt dof, n, cdim; 19684f819b78SStefano Zampini PetscBool memc = PETSC_TRUE; 19694f819b78SStefano Zampini 19709566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL)); 19719566063dSJacob Faibussowitsch PetscCall(DMGetCoordinates(dm, &cvec)); 19729566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(cvec, &n)); 19739566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(cvec, &cdim)); 19744f819b78SStefano Zampini n /= cdim; 19759566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->mat_graph->coords)); 19769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dof * n * cdim, &pcbddc->mat_graph->coords)); 19779566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cvec, &coords)); 19784f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX) 19794f819b78SStefano Zampini memc = PETSC_FALSE; 19804f819b78SStefano Zampini #endif 19814f819b78SStefano Zampini if (dof != 1) memc = PETSC_FALSE; 19824f819b78SStefano Zampini if (memc) { 19839566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pcbddc->mat_graph->coords, coords, cdim * n * dof)); 19844f819b78SStefano Zampini } else { /* BDDC graph does not use any blocked information, we need to replicate the data */ 19854f819b78SStefano Zampini PetscReal *bcoords = pcbddc->mat_graph->coords; 19864f819b78SStefano Zampini PetscInt i, b, d; 19874f819b78SStefano Zampini 19884f819b78SStefano Zampini for (i = 0; i < n; i++) { 19894f819b78SStefano Zampini for (b = 0; b < dof; b++) { 1990ad540459SPierre Jolivet for (d = 0; d < cdim; d++) bcoords[i * dof * cdim + b * cdim + d] = PetscRealPart(coords[i * cdim + d]); 19914f819b78SStefano Zampini } 19924f819b78SStefano Zampini } 19934f819b78SStefano Zampini } 19949566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(cvec, &coords)); 19954f819b78SStefano Zampini pcbddc->mat_graph->cdim = cdim; 19964f819b78SStefano Zampini pcbddc->mat_graph->cnloc = dof * n; 19974f819b78SStefano Zampini pcbddc->mat_graph->cloc = PETSC_FALSE; 19984f819b78SStefano Zampini } 19999566063dSJacob Faibussowitsch PetscCall(DMDAGetSubdomainCornersIS(dm, &corners)); 20009566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->pmat, &lA)); 20019566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(lA, &l2l, NULL)); 20029566063dSJacob Faibussowitsch PetscCall(MatISRestoreLocalMat(pc->pmat, &lA)); 20034f819b78SStefano Zampini lo = (PetscBool)(l2l && corners); 20045440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&lo, &gl, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)pc))); 20054f819b78SStefano Zampini if (gl) { /* From PETSc's DMDA */ 20067620a527SStefano Zampini const PetscInt *idx; 200772ed36d8SStefano Zampini PetscInt dof, bs, *idxout, n; 20087620a527SStefano Zampini 20099566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL)); 20109566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(l2l, &bs)); 20119566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(corners, &n)); 20129566063dSJacob Faibussowitsch PetscCall(ISGetIndices(corners, &idx)); 201372ed36d8SStefano Zampini if (bs == dof) { 20149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &idxout)); 20159566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(l2l, n, idx, idxout)); 201672ed36d8SStefano Zampini } else { /* the original DMDA local-to-local map have been modified */ 201772ed36d8SStefano Zampini PetscInt i, d; 201872ed36d8SStefano Zampini 20199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dof * n, &idxout)); 20209371c9d4SSatish Balay for (i = 0; i < n; i++) 20219371c9d4SSatish Balay for (d = 0; d < dof; d++) idxout[dof * i + d] = dof * idx[i] + d; 20229566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(l2l, dof * n, idxout, idxout)); 202372ed36d8SStefano Zampini 202472ed36d8SStefano Zampini bs = 1; 202572ed36d8SStefano Zampini n *= dof; 202672ed36d8SStefano Zampini } 20279566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(corners, &idx)); 20289566063dSJacob Faibussowitsch PetscCall(DMDARestoreSubdomainCornersIS(dm, &corners)); 20299566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)pc), bs, n, idxout, PETSC_OWN_POINTER, &corners)); 20309566063dSJacob Faibussowitsch PetscCall(PCBDDCAddPrimalVerticesLocalIS(pc, corners)); 20319566063dSJacob Faibussowitsch PetscCall(ISDestroy(&corners)); 20321c7a958bSStefano Zampini pcbddc->corner_selected = PETSC_TRUE; 20334f819b78SStefano Zampini pcbddc->corner_selection = PETSC_TRUE; 20344f819b78SStefano Zampini } 203548a46eb9SPierre Jolivet if (corners) PetscCall(DMDARestoreSubdomainCornersIS(dm, &corners)); 20367620a527SStefano Zampini } 20377620a527SStefano Zampini } 20387620a527SStefano Zampini } 20391c7a958bSStefano Zampini if (pcbddc->corner_selection && !pcbddc->mat_graph->cdim) { 20401c7a958bSStefano Zampini DM dm; 20411c7a958bSStefano Zampini 20429566063dSJacob Faibussowitsch PetscCall(MatGetDM(pc->pmat, &dm)); 204348a46eb9SPierre Jolivet if (!dm) PetscCall(PCGetDM(pc, &dm)); 20444f819b78SStefano Zampini if (dm) { /* this can get very expensive, I need to find a faster alternative */ 20451c7a958bSStefano Zampini Vec vcoords; 20461c7a958bSStefano Zampini PetscSection section; 20471c7a958bSStefano Zampini PetscReal *coords; 20481c7a958bSStefano Zampini PetscInt d, cdim, nl, nf, **ctxs; 20491c7a958bSStefano Zampini PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal *, PetscInt, PetscScalar *, void *); 205051ab8ad6SStefano Zampini /* debug coordinates */ 205151ab8ad6SStefano Zampini PetscViewer viewer; 205251ab8ad6SStefano Zampini PetscBool flg; 205351ab8ad6SStefano Zampini PetscViewerFormat format; 205451ab8ad6SStefano Zampini const char *prefix; 20551c7a958bSStefano Zampini 20569566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 20579566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 20589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &nf)); 20599566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dm, &vcoords)); 20609566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vcoords, &nl)); 20619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl * cdim, &coords)); 20629566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nf, &funcs, nf, &ctxs)); 20639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nf, &ctxs[0])); 20641c7a958bSStefano Zampini for (d = 0; d < nf; d++) funcs[d] = func_coords_private; 20651c7a958bSStefano Zampini for (d = 1; d < nf; d++) ctxs[d] = ctxs[d - 1] + 1; 206651ab8ad6SStefano Zampini 206751ab8ad6SStefano Zampini /* debug coordinates */ 206851ab8ad6SStefano Zampini PetscCall(PCGetOptionsPrefix(pc, &prefix)); 2069648c30bcSBarry Smith PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)vcoords), ((PetscObject)vcoords)->options, prefix, "-pc_bddc_coords_vec_view", &viewer, &format, &flg)); 207051ab8ad6SStefano Zampini if (flg) PetscCall(PetscViewerPushFormat(viewer, format)); 20711c7a958bSStefano Zampini for (d = 0; d < cdim; d++) { 20721c7a958bSStefano Zampini PetscInt i; 20731c7a958bSStefano Zampini const PetscScalar *v; 207451ab8ad6SStefano Zampini char name[16]; 20751c7a958bSStefano Zampini 20761c7a958bSStefano Zampini for (i = 0; i < nf; i++) ctxs[i][0] = d; 2077835f2295SStefano Zampini PetscCall(PetscSNPrintf(name, sizeof(name), "bddc_coords_%" PetscInt_FMT, d)); 207851ab8ad6SStefano Zampini PetscCall(PetscObjectSetName((PetscObject)vcoords, name)); 20799566063dSJacob Faibussowitsch PetscCall(DMProjectFunction(dm, 0.0, funcs, (void **)ctxs, INSERT_VALUES, vcoords)); 208051ab8ad6SStefano Zampini if (flg) PetscCall(VecView(vcoords, viewer)); 20819566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vcoords, &v)); 20821c7a958bSStefano Zampini for (i = 0; i < nl; i++) coords[i * cdim + d] = PetscRealPart(v[i]); 20839566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vcoords, &v)); 20841c7a958bSStefano Zampini } 20859566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vcoords)); 20869566063dSJacob Faibussowitsch PetscCall(PCSetCoordinates(pc, cdim, nl, coords)); 20879566063dSJacob Faibussowitsch PetscCall(PetscFree(coords)); 20889566063dSJacob Faibussowitsch PetscCall(PetscFree(ctxs[0])); 20899566063dSJacob Faibussowitsch PetscCall(PetscFree2(funcs, ctxs)); 209051ab8ad6SStefano Zampini if (flg) { 209151ab8ad6SStefano Zampini PetscCall(PetscViewerPopFormat(viewer)); 2092648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&viewer)); 209351ab8ad6SStefano Zampini } 20941c7a958bSStefano Zampini } 20951c7a958bSStefano Zampini } 20963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20977a0e7b2cSstefano_zampini } 20987a0e7b2cSstefano_zampini 2099d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCConsistencyCheckIS(PC pc, MPI_Op mop, IS *is) 2100d71ae5a4SJacob Faibussowitsch { 2101f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)pc->pmat->data; 21027a0e7b2cSstefano_zampini IS nis; 21037a0e7b2cSstefano_zampini const PetscInt *idxs; 21047a0e7b2cSstefano_zampini PetscInt i, nd, n = matis->A->rmap->n, *nidxs, nnd; 21057a0e7b2cSstefano_zampini 21067a0e7b2cSstefano_zampini PetscFunctionBegin; 210757508eceSPierre Jolivet PetscCheck(mop == MPI_LAND || mop == MPI_LOR, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Supported are MPI_LAND and MPI_LOR"); 21087a0e7b2cSstefano_zampini if (mop == MPI_LAND) { 21097a0e7b2cSstefano_zampini /* init rootdata with true */ 21101bd50df1SStefano Zampini for (i = 0; i < pc->pmat->rmap->n; i++) matis->sf_rootdata[i] = 1; 21117a0e7b2cSstefano_zampini } else { 21129566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_rootdata, pc->pmat->rmap->n)); 21137a0e7b2cSstefano_zampini } 21149566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_leafdata, n)); 21159566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(*is, &nd)); 21169566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*is, &idxs)); 21177a0e7b2cSstefano_zampini for (i = 0; i < nd; i++) 21189371c9d4SSatish Balay if (-1 < idxs[i] && idxs[i] < n) matis->sf_leafdata[idxs[i]] = 1; 21199566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*is, &idxs)); 21209566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, matis->sf_leafdata, matis->sf_rootdata, mop)); 21219566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, matis->sf_leafdata, matis->sf_rootdata, mop)); 21229566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 21239566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 21247a0e7b2cSstefano_zampini if (mop == MPI_LAND) { 21259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nd, &nidxs)); 21267a0e7b2cSstefano_zampini } else { 21279566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &nidxs)); 21287a0e7b2cSstefano_zampini } 21297a0e7b2cSstefano_zampini for (i = 0, nnd = 0; i < n; i++) 21309371c9d4SSatish Balay if (matis->sf_leafdata[i]) nidxs[nnd++] = i; 2131f4f49eeaSPierre Jolivet PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)*is), nnd, nidxs, PETSC_OWN_POINTER, &nis)); 21329566063dSJacob Faibussowitsch PetscCall(ISDestroy(is)); 21337a0e7b2cSstefano_zampini *is = nis; 21343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21351f4df5f7SStefano Zampini } 21361f4df5f7SStefano Zampini 2137d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignRemoveInterior(PC pc, Vec r, Vec z) 2138d71ae5a4SJacob Faibussowitsch { 2139f4f49eeaSPierre Jolivet PC_IS *pcis = (PC_IS *)pc->data; 2140f4f49eeaSPierre Jolivet PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 21413e589ea0SStefano Zampini 21423e589ea0SStefano Zampini PetscFunctionBegin; 21433ba16761SJacob Faibussowitsch if (!pcbddc->benign_have_null) PetscFunctionReturn(PETSC_SUCCESS); 21443e589ea0SStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 21453e589ea0SStefano Zampini Vec swap; 21463e589ea0SStefano Zampini 21479566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, r, pcbddc->work_change)); 21483e589ea0SStefano Zampini swap = pcbddc->work_change; 21493e589ea0SStefano Zampini pcbddc->work_change = r; 21503e589ea0SStefano Zampini r = swap; 21513e589ea0SStefano Zampini } 21529566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 21539566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 21549566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 21559566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D)); 21569566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 21579566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D)); 21589566063dSJacob Faibussowitsch PetscCall(VecSet(z, 0.)); 21599566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE)); 21609566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE)); 21613e589ea0SStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 2162f913dca9SStefano Zampini pcbddc->work_change = r; 21639566063dSJacob Faibussowitsch PetscCall(VecCopy(z, pcbddc->work_change)); 21649566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcbddc->work_change, z)); 21653e589ea0SStefano Zampini } 21663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21673e589ea0SStefano Zampini } 21683e589ea0SStefano Zampini 2169ba38deedSJacob Faibussowitsch static PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose) 2170d71ae5a4SJacob Faibussowitsch { 2171a3df083aSStefano Zampini PCBDDCBenignMatMult_ctx ctx; 2172a3df083aSStefano Zampini PetscBool apply_right, apply_left, reset_x; 2173a3df083aSStefano Zampini 2174a3df083aSStefano Zampini PetscFunctionBegin; 21759566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(A, &ctx)); 2176a3df083aSStefano Zampini if (transpose) { 2177a3df083aSStefano Zampini apply_right = ctx->apply_left; 2178a3df083aSStefano Zampini apply_left = ctx->apply_right; 2179a3df083aSStefano Zampini } else { 2180a3df083aSStefano Zampini apply_right = ctx->apply_right; 2181a3df083aSStefano Zampini apply_left = ctx->apply_left; 2182a3df083aSStefano Zampini } 2183a3df083aSStefano Zampini reset_x = PETSC_FALSE; 2184a3df083aSStefano Zampini if (apply_right) { 2185a3df083aSStefano Zampini const PetscScalar *ax; 2186a3df083aSStefano Zampini PetscInt nl, i; 2187a3df083aSStefano Zampini 21889566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(x, &nl)); 21899566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &ax)); 21909566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(ctx->work, ax, nl)); 21919566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &ax)); 2192a3df083aSStefano Zampini for (i = 0; i < ctx->benign_n; i++) { 2193a3df083aSStefano Zampini PetscScalar sum, val; 2194a3df083aSStefano Zampini const PetscInt *idxs; 2195a3df083aSStefano Zampini PetscInt nz, j; 21969566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(ctx->benign_zerodiag_subs[i], &nz)); 21979566063dSJacob Faibussowitsch PetscCall(ISGetIndices(ctx->benign_zerodiag_subs[i], &idxs)); 2198a3df083aSStefano Zampini sum = 0.; 2199a3df083aSStefano Zampini if (ctx->apply_p0) { 2200a3df083aSStefano Zampini val = ctx->work[idxs[nz - 1]]; 2201a3df083aSStefano Zampini for (j = 0; j < nz - 1; j++) { 2202a3df083aSStefano Zampini sum += ctx->work[idxs[j]]; 2203a3df083aSStefano Zampini ctx->work[idxs[j]] += val; 2204a3df083aSStefano Zampini } 2205a3df083aSStefano Zampini } else { 2206ad540459SPierre Jolivet for (j = 0; j < nz - 1; j++) sum += ctx->work[idxs[j]]; 2207a3df083aSStefano Zampini } 2208a3df083aSStefano Zampini ctx->work[idxs[nz - 1]] -= sum; 22099566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(ctx->benign_zerodiag_subs[i], &idxs)); 2210a3df083aSStefano Zampini } 22119566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(x, ctx->work)); 2212a3df083aSStefano Zampini reset_x = PETSC_TRUE; 2213a3df083aSStefano Zampini } 2214a3df083aSStefano Zampini if (transpose) { 22159566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(ctx->A, x, y)); 2216a3df083aSStefano Zampini } else { 22179566063dSJacob Faibussowitsch PetscCall(MatMult(ctx->A, x, y)); 2218a3df083aSStefano Zampini } 22191baa6e33SBarry Smith if (reset_x) PetscCall(VecResetArray(x)); 2220a3df083aSStefano Zampini if (apply_left) { 2221a3df083aSStefano Zampini PetscScalar *ay; 2222a3df083aSStefano Zampini PetscInt i; 2223a3df083aSStefano Zampini 22249566063dSJacob Faibussowitsch PetscCall(VecGetArray(y, &ay)); 2225a3df083aSStefano Zampini for (i = 0; i < ctx->benign_n; i++) { 2226a3df083aSStefano Zampini PetscScalar sum, val; 2227a3df083aSStefano Zampini const PetscInt *idxs; 2228a3df083aSStefano Zampini PetscInt nz, j; 22299566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(ctx->benign_zerodiag_subs[i], &nz)); 22309566063dSJacob Faibussowitsch PetscCall(ISGetIndices(ctx->benign_zerodiag_subs[i], &idxs)); 2231a3df083aSStefano Zampini val = -ay[idxs[nz - 1]]; 2232a3df083aSStefano Zampini if (ctx->apply_p0) { 2233a3df083aSStefano Zampini sum = 0.; 2234a3df083aSStefano Zampini for (j = 0; j < nz - 1; j++) { 2235a3df083aSStefano Zampini sum += ay[idxs[j]]; 2236a3df083aSStefano Zampini ay[idxs[j]] += val; 2237a3df083aSStefano Zampini } 2238a3df083aSStefano Zampini ay[idxs[nz - 1]] += sum; 2239a3df083aSStefano Zampini } else { 2240ad540459SPierre Jolivet for (j = 0; j < nz - 1; j++) ay[idxs[j]] += val; 2241a3df083aSStefano Zampini ay[idxs[nz - 1]] = 0.; 2242a3df083aSStefano Zampini } 22439566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(ctx->benign_zerodiag_subs[i], &idxs)); 2244a3df083aSStefano Zampini } 22459566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(y, &ay)); 2246a3df083aSStefano Zampini } 22473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2248a3df083aSStefano Zampini } 2249a3df083aSStefano Zampini 2250ba38deedSJacob Faibussowitsch static PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y) 2251d71ae5a4SJacob Faibussowitsch { 2252a3df083aSStefano Zampini PetscFunctionBegin; 22539566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignMatMult_Private_Private(A, x, y, PETSC_TRUE)); 22543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2255a3df083aSStefano Zampini } 2256a3df083aSStefano Zampini 2257ba38deedSJacob Faibussowitsch static PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y) 2258d71ae5a4SJacob Faibussowitsch { 2259a3df083aSStefano Zampini PetscFunctionBegin; 22609566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignMatMult_Private_Private(A, x, y, PETSC_FALSE)); 22613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2262a3df083aSStefano Zampini } 2263a3df083aSStefano Zampini 2264d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore) 2265d71ae5a4SJacob Faibussowitsch { 2266a3df083aSStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 2267a3df083aSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 2268a3df083aSStefano Zampini PCBDDCBenignMatMult_ctx ctx; 2269a3df083aSStefano Zampini 2270a3df083aSStefano Zampini PetscFunctionBegin; 2271a3df083aSStefano Zampini if (!restore) { 22721dd7afcfSStefano Zampini Mat A_IB, A_BI; 2273a3df083aSStefano Zampini PetscScalar *work; 2274b334f244SStefano Zampini PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL; 2275a3df083aSStefano Zampini 227628b400f6SJacob Faibussowitsch PetscCheck(!pcbddc->benign_original_mat, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Benign original mat has not been restored"); 22773ba16761SJacob Faibussowitsch if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(PETSC_SUCCESS); 22789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n, &work)); 22799566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &A_IB)); 22809566063dSJacob Faibussowitsch PetscCall(MatSetSizes(A_IB, pcis->n - pcis->n_B, pcis->n_B, PETSC_DECIDE, PETSC_DECIDE)); 22819566063dSJacob Faibussowitsch PetscCall(MatSetType(A_IB, MATSHELL)); 228257d50842SBarry Smith PetscCall(MatShellSetOperation(A_IB, MATOP_MULT, (PetscErrorCodeFn *)PCBDDCBenignMatMult_Private)); 228357d50842SBarry Smith PetscCall(MatShellSetOperation(A_IB, MATOP_MULT_TRANSPOSE, (PetscErrorCodeFn *)PCBDDCBenignMatMultTranspose_Private)); 22849566063dSJacob Faibussowitsch PetscCall(PetscNew(&ctx)); 22859566063dSJacob Faibussowitsch PetscCall(MatShellSetContext(A_IB, ctx)); 2286a3df083aSStefano Zampini ctx->apply_left = PETSC_TRUE; 2287a3df083aSStefano Zampini ctx->apply_right = PETSC_FALSE; 2288a3df083aSStefano Zampini ctx->apply_p0 = PETSC_FALSE; 2289a3df083aSStefano Zampini ctx->benign_n = pcbddc->benign_n; 2290059032f7SStefano Zampini if (reuse) { 2291a3df083aSStefano Zampini ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs; 22921dd7afcfSStefano Zampini ctx->free = PETSC_FALSE; 2293059032f7SStefano Zampini } else { /* TODO: could be optimized for successive solves */ 2294059032f7SStefano Zampini ISLocalToGlobalMapping N_to_D; 2295059032f7SStefano Zampini PetscInt i; 2296059032f7SStefano Zampini 22979566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(pcis->is_I_local, &N_to_D)); 22989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->benign_n, &ctx->benign_zerodiag_subs)); 229948a46eb9SPierre 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])); 23009566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&N_to_D)); 23011dd7afcfSStefano Zampini ctx->free = PETSC_TRUE; 2302059032f7SStefano Zampini } 2303a3df083aSStefano Zampini ctx->A = pcis->A_IB; 2304a3df083aSStefano Zampini ctx->work = work; 23059566063dSJacob Faibussowitsch PetscCall(MatSetUp(A_IB)); 23069566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A_IB, MAT_FINAL_ASSEMBLY)); 23079566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A_IB, MAT_FINAL_ASSEMBLY)); 2308a3df083aSStefano Zampini pcis->A_IB = A_IB; 2309a3df083aSStefano Zampini 2310a3df083aSStefano Zampini /* A_BI as A_IB^T */ 23119566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(A_IB, &A_BI)); 2312a3df083aSStefano Zampini pcbddc->benign_original_mat = pcis->A_BI; 2313a3df083aSStefano Zampini pcis->A_BI = A_BI; 2314a3df083aSStefano Zampini } else { 23153ba16761SJacob Faibussowitsch if (!pcbddc->benign_original_mat) PetscFunctionReturn(PETSC_SUCCESS); 23169566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(pcis->A_IB, &ctx)); 23179566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_IB)); 2318a3df083aSStefano Zampini pcis->A_IB = ctx->A; 23191dd7afcfSStefano Zampini ctx->A = NULL; 23209566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_BI)); 23211dd7afcfSStefano Zampini pcis->A_BI = pcbddc->benign_original_mat; 23221dd7afcfSStefano Zampini pcbddc->benign_original_mat = NULL; 23231dd7afcfSStefano Zampini if (ctx->free) { 2324059032f7SStefano Zampini PetscInt i; 232548a46eb9SPierre Jolivet for (i = 0; i < ctx->benign_n; i++) PetscCall(ISDestroy(&ctx->benign_zerodiag_subs[i])); 23269566063dSJacob Faibussowitsch PetscCall(PetscFree(ctx->benign_zerodiag_subs)); 2327059032f7SStefano Zampini } 23289566063dSJacob Faibussowitsch PetscCall(PetscFree(ctx->work)); 23299566063dSJacob Faibussowitsch PetscCall(PetscFree(ctx)); 2330a3df083aSStefano Zampini } 23313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2332a3df083aSStefano Zampini } 2333a3df083aSStefano Zampini 2334a3df083aSStefano Zampini /* used just in bddc debug mode */ 2335ba38deedSJacob Faibussowitsch static PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B) 2336d71ae5a4SJacob Faibussowitsch { 2337a3df083aSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 2338a3df083aSStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 2339a3df083aSStefano Zampini Mat An; 2340a3df083aSStefano Zampini 2341a3df083aSStefano Zampini PetscFunctionBegin; 23429566063dSJacob Faibussowitsch PetscCall(MatPtAP(matis->A, pcbddc->benign_change, MAT_INITIAL_MATRIX, 2.0, &An)); 23439566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns(An, pcbddc->benign_n, pcbddc->benign_p0_lidx, 1.0, NULL, NULL)); 2344a3df083aSStefano Zampini if (is1) { 23459566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(An, is1, is2, MAT_INITIAL_MATRIX, B)); 23469566063dSJacob Faibussowitsch PetscCall(MatDestroy(&An)); 2347a3df083aSStefano Zampini } else { 2348a3df083aSStefano Zampini *B = An; 2349a3df083aSStefano Zampini } 23503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2351a3df083aSStefano Zampini } 2352a3df083aSStefano Zampini 23531cf9b237SStefano Zampini /* TODO: add reuse flag */ 2354d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B) 2355d71ae5a4SJacob Faibussowitsch { 23561cf9b237SStefano Zampini Mat Bt; 23571cf9b237SStefano Zampini PetscScalar *a, *bdata; 23581cf9b237SStefano Zampini const PetscInt *ii, *ij; 23591cf9b237SStefano Zampini PetscInt m, n, i, nnz, *bii, *bij; 23601cf9b237SStefano Zampini PetscBool flg_row; 23611cf9b237SStefano Zampini 23621cf9b237SStefano Zampini PetscFunctionBegin; 23639566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &n, &m)); 23649566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &ij, &flg_row)); 23659566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &a)); 23661cf9b237SStefano Zampini nnz = n; 23671cf9b237SStefano Zampini for (i = 0; i < ii[n]; i++) { 23681cf9b237SStefano Zampini if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++; 23691cf9b237SStefano Zampini } 23709566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n + 1, &bii)); 23719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &bij)); 23729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &bdata)); 23731cf9b237SStefano Zampini nnz = 0; 23741cf9b237SStefano Zampini bii[0] = 0; 23751cf9b237SStefano Zampini for (i = 0; i < n; i++) { 23761cf9b237SStefano Zampini PetscInt j; 23771cf9b237SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 23781cf9b237SStefano Zampini PetscScalar entry = a[j]; 23793272d46bSStefano Zampini if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || (n == m && ij[j] == i)) { 23801cf9b237SStefano Zampini bij[nnz] = ij[j]; 23811cf9b237SStefano Zampini bdata[nnz] = entry; 23821cf9b237SStefano Zampini nnz++; 23831cf9b237SStefano Zampini } 23841cf9b237SStefano Zampini } 23851cf9b237SStefano Zampini bii[i + 1] = nnz; 23861cf9b237SStefano Zampini } 23879566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &a)); 23889566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A), n, m, bii, bij, bdata, &Bt)); 23899566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &ij, &flg_row)); 23901cf9b237SStefano Zampini { 2391f4f49eeaSPierre Jolivet Mat_SeqAIJ *b = (Mat_SeqAIJ *)Bt->data; 23921cf9b237SStefano Zampini b->free_a = PETSC_TRUE; 23931cf9b237SStefano Zampini b->free_ij = PETSC_TRUE; 23941cf9b237SStefano Zampini } 239548a46eb9SPierre Jolivet if (*B == A) PetscCall(MatDestroy(&A)); 23961cf9b237SStefano Zampini *B = Bt; 23973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23981cf9b237SStefano Zampini } 23991cf9b237SStefano Zampini 2400d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCDetectDisconnectedComponents(PC pc, PetscBool filter, PetscInt *ncc, IS *cc[], IS *primalv) 2401d71ae5a4SJacob Faibussowitsch { 2402c80a6c00SStefano Zampini Mat B = NULL; 2403c80a6c00SStefano Zampini DM dm; 24044f1b2e48SStefano Zampini IS is_dummy, *cc_n; 24054f1b2e48SStefano Zampini ISLocalToGlobalMapping l2gmap_dummy; 24064f1b2e48SStefano Zampini PCBDDCGraph graph; 2407c80a6c00SStefano Zampini PetscInt *xadj_filtered = NULL, *adjncy_filtered = NULL; 24084f1b2e48SStefano Zampini PetscInt i, n; 24094f1b2e48SStefano Zampini PetscInt *xadj, *adjncy; 2410c80a6c00SStefano Zampini PetscBool isplex = PETSC_FALSE; 24114f1b2e48SStefano Zampini 24124f1b2e48SStefano Zampini PetscFunctionBegin; 2413a2eca866SStefano Zampini if (ncc) *ncc = 0; 2414a2eca866SStefano Zampini if (cc) *cc = NULL; 2415a2eca866SStefano Zampini if (primalv) *primalv = NULL; 24169566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphCreate(&graph)); 24179566063dSJacob Faibussowitsch PetscCall(MatGetDM(pc->pmat, &dm)); 241848a46eb9SPierre Jolivet if (!dm) PetscCall(PCGetDM(pc, &dm)); 2419f9635d15SStefano Zampini if (dm) PetscCall(PetscObjectTypeCompareAny((PetscObject)dm, &isplex, DMPLEX, DMP4EST, DMP8EST, "")); 24208361f951SStefano Zampini if (filter) isplex = PETSC_FALSE; 24218361f951SStefano Zampini 2422c80a6c00SStefano Zampini if (isplex) { /* this code has been modified from plexpartition.c */ 2423c80a6c00SStefano Zampini PetscInt p, pStart, pEnd, a, adjSize, idx, size, nroots; 2424c80a6c00SStefano Zampini PetscInt *adj = NULL; 2425c80a6c00SStefano Zampini IS cellNumbering; 2426c80a6c00SStefano Zampini const PetscInt *cellNum; 2427c80a6c00SStefano Zampini PetscBool useCone, useClosure; 2428c80a6c00SStefano Zampini PetscSection section; 2429c80a6c00SStefano Zampini PetscSegBuffer adjBuffer; 2430c80a6c00SStefano Zampini PetscSF sfPoint; 2431c80a6c00SStefano Zampini 2432f9635d15SStefano Zampini PetscCall(DMConvert(dm, DMPLEX, &dm)); 24339566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd)); 24349566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 24359566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL)); 2436c80a6c00SStefano Zampini /* Build adjacency graph via a section/segbuffer */ 24379566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 24389566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 24399566063dSJacob Faibussowitsch PetscCall(PetscSegBufferCreate(sizeof(PetscInt), 1000, &adjBuffer)); 2440c80a6c00SStefano Zampini /* Always use FVM adjacency to create partitioner graph */ 24419566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 24429566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE)); 24439566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellNumbering(dm, &cellNumbering)); 24449566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cellNumbering, &cellNum)); 2445c80a6c00SStefano Zampini for (n = 0, p = pStart; p < pEnd; p++) { 2446c80a6c00SStefano Zampini /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 24479371c9d4SSatish Balay if (nroots > 0) { 24489371c9d4SSatish Balay if (cellNum[p] < 0) continue; 24499371c9d4SSatish Balay } 2450c80a6c00SStefano Zampini adjSize = PETSC_DETERMINE; 24519566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj)); 2452c80a6c00SStefano Zampini for (a = 0; a < adjSize; ++a) { 2453c80a6c00SStefano Zampini const PetscInt point = adj[a]; 24545cef3d0dSStefano Zampini if (pStart <= point && point < pEnd) { 2455c80a6c00SStefano Zampini PetscInt *PETSC_RESTRICT pBuf; 24569566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(section, p, 1)); 24579566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGetInts(adjBuffer, 1, &pBuf)); 2458c80a6c00SStefano Zampini *pBuf = point; 2459c80a6c00SStefano Zampini } 2460c80a6c00SStefano Zampini } 2461c80a6c00SStefano Zampini n++; 2462c80a6c00SStefano Zampini } 24639566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dm, useCone, useClosure)); 2464c80a6c00SStefano Zampini /* Derive CSR graph from section/segbuffer */ 24659566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 24669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &size)); 24679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n + 1, &xadj)); 2468c80a6c00SStefano Zampini for (idx = 0, p = pStart; p < pEnd; p++) { 24699371c9d4SSatish Balay if (nroots > 0) { 24709371c9d4SSatish Balay if (cellNum[p] < 0) continue; 24719371c9d4SSatish Balay } 2472f4f49eeaSPierre Jolivet PetscCall(PetscSectionGetOffset(section, p, &xadj[idx++])); 2473c80a6c00SStefano Zampini } 2474c80a6c00SStefano Zampini xadj[n] = size; 24759566063dSJacob Faibussowitsch PetscCall(PetscSegBufferExtractAlloc(adjBuffer, &adjncy)); 2476c80a6c00SStefano Zampini /* Clean up */ 24779566063dSJacob Faibussowitsch PetscCall(PetscSegBufferDestroy(&adjBuffer)); 24789566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 24799566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 2480c80a6c00SStefano Zampini graph->xadj = xadj; 2481c80a6c00SStefano Zampini graph->adjncy = adjncy; 2482c80a6c00SStefano Zampini } else { 2483c80a6c00SStefano Zampini Mat A; 24848361f951SStefano Zampini PetscBool isseqaij, flg_row; 2485c80a6c00SStefano Zampini 24869566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->pmat, &A)); 248763c961adSStefano Zampini if (!A->rmap->N || !A->cmap->N) { 24889566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphDestroy(&graph)); 24893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 249063c961adSStefano Zampini } 24919566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isseqaij)); 24924f1b2e48SStefano Zampini if (!isseqaij && filter) { 24931cf9b237SStefano Zampini PetscBool isseqdense; 24941cf9b237SStefano Zampini 24959566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATSEQDENSE, &isseqdense)); 24961cf9b237SStefano Zampini if (!isseqdense) { 24979566063dSJacob Faibussowitsch PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &B)); 24981cf9b237SStefano Zampini } else { /* TODO: rectangular case and LDA */ 24991cf9b237SStefano Zampini PetscScalar *array; 25001cf9b237SStefano Zampini PetscReal chop = 1.e-6; 25011cf9b237SStefano Zampini 25029566063dSJacob Faibussowitsch PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &B)); 25039566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(B, &array)); 25049566063dSJacob Faibussowitsch PetscCall(MatGetSize(B, &n, NULL)); 25051cf9b237SStefano Zampini for (i = 0; i < n; i++) { 25061cf9b237SStefano Zampini PetscInt j; 25071cf9b237SStefano Zampini for (j = i + 1; j < n; j++) { 25081cf9b237SStefano Zampini PetscReal thresh = chop * (PetscAbsScalar(array[i * (n + 1)]) + PetscAbsScalar(array[j * (n + 1)])); 25091cf9b237SStefano Zampini if (PetscAbsScalar(array[i * n + j]) < thresh) array[i * n + j] = 0.; 25101cf9b237SStefano Zampini if (PetscAbsScalar(array[j * n + i]) < thresh) array[j * n + i] = 0.; 25111cf9b237SStefano Zampini } 25121cf9b237SStefano Zampini } 25139566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(B, &array)); 25149566063dSJacob Faibussowitsch PetscCall(MatConvert(B, MATSEQAIJ, MAT_INPLACE_MATRIX, &B)); 25151cf9b237SStefano Zampini } 25164f1b2e48SStefano Zampini } else { 25179566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 25184f1b2e48SStefano Zampini B = A; 25194f1b2e48SStefano Zampini } 25209566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(B, 0, PETSC_TRUE, PETSC_FALSE, &n, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &flg_row)); 25214f1b2e48SStefano Zampini 25224f1b2e48SStefano Zampini /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */ 25234f1b2e48SStefano Zampini if (filter) { 25244f1b2e48SStefano Zampini PetscScalar *data; 25254f1b2e48SStefano Zampini PetscInt j, cum; 25264f1b2e48SStefano Zampini 25279566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(n + 1, &xadj_filtered, xadj[n], &adjncy_filtered)); 25289566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(B, &data)); 25294f1b2e48SStefano Zampini cum = 0; 25304f1b2e48SStefano Zampini for (i = 0; i < n; i++) { 25314f1b2e48SStefano Zampini PetscInt t; 25324f1b2e48SStefano Zampini 25334f1b2e48SStefano Zampini for (j = xadj[i]; j < xadj[i + 1]; j++) { 2534ad540459SPierre Jolivet if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) continue; 25354f1b2e48SStefano Zampini adjncy_filtered[cum + xadj_filtered[i]++] = adjncy[j]; 25364f1b2e48SStefano Zampini } 25374f1b2e48SStefano Zampini t = xadj_filtered[i]; 25384f1b2e48SStefano Zampini xadj_filtered[i] = cum; 25394f1b2e48SStefano Zampini cum += t; 25404f1b2e48SStefano Zampini } 25419566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(B, &data)); 25424f1b2e48SStefano Zampini graph->xadj = xadj_filtered; 25434f1b2e48SStefano Zampini graph->adjncy = adjncy_filtered; 25444f1b2e48SStefano Zampini } else { 25454f1b2e48SStefano Zampini graph->xadj = xadj; 25464f1b2e48SStefano Zampini graph->adjncy = adjncy; 25474f1b2e48SStefano Zampini } 2548c80a6c00SStefano Zampini } 2549c80a6c00SStefano Zampini /* compute local connected components using PCBDDCGraph */ 25509de2952eSStefano Zampini graph->seq_graph = PETSC_TRUE; /* analyze local connected components (i.e. disconnected subdomains) irrespective of dofs count */ 25519566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, n, 0, 1, &is_dummy)); 25529566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is_dummy, &l2gmap_dummy)); 25539566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_dummy)); 25541690c2aeSBarry Smith PetscCall(PCBDDCGraphInit(graph, l2gmap_dummy, n, PETSC_INT_MAX)); 25559566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&l2gmap_dummy)); 25569566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphSetUp(graph, 1, NULL, NULL, 0, NULL, NULL)); 25579566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphComputeConnectedComponents(graph)); 2558c80a6c00SStefano Zampini 25594f1b2e48SStefano Zampini /* partial clean up */ 25609566063dSJacob Faibussowitsch PetscCall(PetscFree2(xadj_filtered, adjncy_filtered)); 2561c80a6c00SStefano Zampini if (B) { 2562c80a6c00SStefano Zampini PetscBool flg_row; 25639566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(B, 0, PETSC_TRUE, PETSC_FALSE, &n, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &flg_row)); 25649566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 25654f1b2e48SStefano Zampini } 2566c80a6c00SStefano Zampini if (isplex) { 25679566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 25689566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 2569c80a6c00SStefano Zampini } 25704f1b2e48SStefano Zampini 25714f1b2e48SStefano Zampini /* get back data */ 2572c80a6c00SStefano Zampini if (isplex) { 2573c80a6c00SStefano Zampini if (ncc) *ncc = graph->ncc; 2574c80a6c00SStefano Zampini if (cc || primalv) { 2575c80a6c00SStefano Zampini Mat A; 2576f9635d15SStefano Zampini PetscBT btv, btvt, btvc; 2577c80a6c00SStefano Zampini PetscSection subSection; 2578c80a6c00SStefano Zampini PetscInt *ids, cum, cump, *cids, *pids; 2579f9635d15SStefano Zampini PetscInt dim, cStart, cEnd, fStart, fEnd, vStart, vEnd, pStart, pEnd; 2580c80a6c00SStefano Zampini 2581f9635d15SStefano Zampini PetscCall(DMGetDimension(dm, &dim)); 25829566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubdomainSection(dm, &subSection)); 2583f9635d15SStefano Zampini PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 2584f9635d15SStefano Zampini PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 2585f9635d15SStefano Zampini PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 2586f9635d15SStefano Zampini PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 25879566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->pmat, &A)); 25889566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(A->rmap->n, &ids, graph->ncc + 1, &cids, A->rmap->n, &pids)); 25899566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(A->rmap->n, &btv)); 25909566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(A->rmap->n, &btvt)); 2591f9635d15SStefano Zampini PetscCall(PetscBTCreate(pEnd - pStart, &btvc)); 2592f9635d15SStefano Zampini 2593f9635d15SStefano Zampini /* First see if we find corners for the subdomains, i.e. a vertex 2594f9635d15SStefano Zampini shared by at least dim subdomain boundary faces. This does not 2595f9635d15SStefano Zampini cover all the possible cases with simplices but it is enough 2596f9635d15SStefano Zampini for tensor cells */ 2597f9635d15SStefano Zampini if (vStart != fStart && dim <= 3) { 2598f9635d15SStefano Zampini for (PetscInt c = cStart; c < cEnd; c++) { 2599f9635d15SStefano Zampini PetscInt nf, cnt = 0, mcnt = dim, *cfaces; 2600f9635d15SStefano Zampini const PetscInt *faces; 2601f9635d15SStefano Zampini 2602f9635d15SStefano Zampini PetscCall(DMPlexGetConeSize(dm, c, &nf)); 2603f9635d15SStefano Zampini PetscCall(DMGetWorkArray(dm, nf, MPIU_INT, &cfaces)); 2604f9635d15SStefano Zampini PetscCall(DMPlexGetCone(dm, c, &faces)); 2605f9635d15SStefano Zampini for (PetscInt f = 0; f < nf; f++) { 2606f9635d15SStefano Zampini PetscInt nc, ff; 2607f9635d15SStefano Zampini 2608f9635d15SStefano Zampini PetscCall(DMPlexGetSupportSize(dm, faces[f], &nc)); 2609f9635d15SStefano Zampini PetscCall(DMPlexGetTreeParent(dm, faces[f], &ff, NULL)); 2610f9635d15SStefano Zampini if (nc == 1 && faces[f] == ff) cfaces[cnt++] = faces[f]; 2611f9635d15SStefano Zampini } 2612f9635d15SStefano Zampini if (cnt >= mcnt) { 2613f9635d15SStefano Zampini PetscInt size, *closure = NULL; 2614f9635d15SStefano Zampini 2615f9635d15SStefano Zampini PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &size, &closure)); 2616f9635d15SStefano Zampini for (PetscInt k = 0; k < 2 * size; k += 2) { 2617f9635d15SStefano Zampini PetscInt v = closure[k]; 2618f9635d15SStefano Zampini if (v >= vStart && v < vEnd) { 2619f9635d15SStefano Zampini PetscInt vsize, *vclosure = NULL; 2620f9635d15SStefano Zampini 2621f9635d15SStefano Zampini cnt = 0; 2622f9635d15SStefano Zampini PetscCall(DMPlexGetTransitiveClosure(dm, v, PETSC_FALSE, &vsize, &vclosure)); 2623f9635d15SStefano Zampini for (PetscInt vk = 0; vk < 2 * vsize; vk += 2) { 2624f9635d15SStefano Zampini PetscInt f = vclosure[vk]; 2625f9635d15SStefano Zampini if (f >= fStart && f < fEnd) { 2626f9635d15SStefano Zampini PetscInt nc, ff; 2627f9635d15SStefano Zampini PetscBool valid = PETSC_FALSE; 2628f9635d15SStefano Zampini 2629f9635d15SStefano Zampini for (PetscInt fk = 0; fk < nf; fk++) 2630f9635d15SStefano Zampini if (f == cfaces[fk]) valid = PETSC_TRUE; 2631f9635d15SStefano Zampini if (!valid) continue; 2632f9635d15SStefano Zampini PetscCall(DMPlexGetSupportSize(dm, f, &nc)); 2633f9635d15SStefano Zampini PetscCall(DMPlexGetTreeParent(dm, f, &ff, NULL)); 2634f9635d15SStefano Zampini if (nc == 1 && f == ff) cnt++; 2635f9635d15SStefano Zampini } 2636f9635d15SStefano Zampini } 2637f9635d15SStefano Zampini if (cnt >= mcnt) PetscCall(PetscBTSet(btvc, v - pStart)); 2638f9635d15SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure(dm, v, PETSC_FALSE, &vsize, &vclosure)); 2639f9635d15SStefano Zampini } 2640f9635d15SStefano Zampini } 2641f9635d15SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &size, &closure)); 2642f9635d15SStefano Zampini } 2643f9635d15SStefano Zampini PetscCall(DMRestoreWorkArray(dm, nf, MPIU_INT, &cfaces)); 2644f9635d15SStefano Zampini } 2645f9635d15SStefano Zampini } 2646c80a6c00SStefano Zampini 2647c80a6c00SStefano Zampini cids[0] = 0; 2648c80a6c00SStefano Zampini for (i = 0, cump = 0, cum = 0; i < graph->ncc; i++) { 2649c80a6c00SStefano Zampini PetscInt j; 2650c80a6c00SStefano Zampini 26519566063dSJacob Faibussowitsch PetscCall(PetscBTMemzero(A->rmap->n, btvt)); 2652c80a6c00SStefano Zampini for (j = graph->cptr[i]; j < graph->cptr[i + 1]; j++) { 2653c80a6c00SStefano Zampini PetscInt k, size, *closure = NULL, cell = graph->queue[j]; 2654c80a6c00SStefano Zampini 26559566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &size, &closure)); 2656c80a6c00SStefano Zampini for (k = 0; k < 2 * size; k += 2) { 265720c3699dSStefano Zampini PetscInt s, pp, p = closure[k], off, dof, cdof; 2658c80a6c00SStefano Zampini 26599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(subSection, p, &cdof)); 26609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(subSection, p, &off)); 26619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subSection, p, &dof)); 2662c80a6c00SStefano Zampini for (s = 0; s < dof - cdof; s++) { 2663c80a6c00SStefano Zampini if (PetscBTLookupSet(btvt, off + s)) continue; 2664f9635d15SStefano Zampini if (PetscBTLookup(btvc, p - pStart)) pids[cump++] = off + s; /* subdomain corner */ 2665f9635d15SStefano Zampini else if (!PetscBTLookup(btv, off + s)) ids[cum++] = off + s; 2666e432b41dSStefano Zampini else pids[cump++] = off + s; /* cross-vertex */ 2667c80a6c00SStefano Zampini } 26689566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL)); 266920c3699dSStefano Zampini if (pp != p) { 26709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(subSection, pp, &cdof)); 26719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(subSection, pp, &off)); 26729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subSection, pp, &dof)); 267320c3699dSStefano Zampini for (s = 0; s < dof - cdof; s++) { 267420c3699dSStefano Zampini if (PetscBTLookupSet(btvt, off + s)) continue; 2675f9635d15SStefano Zampini if (PetscBTLookup(btvc, pp - pStart)) pids[cump++] = off + s; /* subdomain corner */ 2676f9635d15SStefano Zampini else if (!PetscBTLookup(btv, off + s)) ids[cum++] = off + s; 2677e432b41dSStefano Zampini else pids[cump++] = off + s; /* cross-vertex */ 267820c3699dSStefano Zampini } 267920c3699dSStefano Zampini } 2680c80a6c00SStefano Zampini } 26819566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &size, &closure)); 2682c80a6c00SStefano Zampini } 2683c80a6c00SStefano Zampini cids[i + 1] = cum; 2684c80a6c00SStefano Zampini /* mark dofs as already assigned */ 268548a46eb9SPierre Jolivet for (j = cids[i]; j < cids[i + 1]; j++) PetscCall(PetscBTSet(btv, ids[j])); 2686c80a6c00SStefano Zampini } 2687c80a6c00SStefano Zampini if (cc) { 26889566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(graph->ncc, &cc_n)); 268948a46eb9SPierre 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])); 2690c80a6c00SStefano Zampini *cc = cc_n; 2691c80a6c00SStefano Zampini } 26921baa6e33SBarry Smith if (primalv) PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), cump, pids, PETSC_COPY_VALUES, primalv)); 26939566063dSJacob Faibussowitsch PetscCall(PetscFree3(ids, cids, pids)); 26949566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btv)); 26959566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btvt)); 2696f9635d15SStefano Zampini PetscCall(PetscBTDestroy(&btvc)); 2697f9635d15SStefano Zampini PetscCall(DMDestroy(&dm)); 2698c80a6c00SStefano Zampini } 2699c80a6c00SStefano Zampini } else { 27001cf9b237SStefano Zampini if (ncc) *ncc = graph->ncc; 27011cf9b237SStefano Zampini if (cc) { 27029566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(graph->ncc, &cc_n)); 270348a46eb9SPierre 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])); 27044f1b2e48SStefano Zampini *cc = cc_n; 27051cf9b237SStefano Zampini } 2706c80a6c00SStefano Zampini } 27074f1b2e48SStefano Zampini /* clean up graph */ 27080a545947SLisandro Dalcin graph->xadj = NULL; 27090a545947SLisandro Dalcin graph->adjncy = NULL; 27109566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphDestroy(&graph)); 27113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 27124f1b2e48SStefano Zampini } 27134f1b2e48SStefano Zampini 2714d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag) 2715d71ae5a4SJacob Faibussowitsch { 27165408967cSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 2717f4f49eeaSPierre Jolivet PC_IS *pcis = (PC_IS *)pc->data; 2718dee84bffSStefano Zampini IS dirIS = NULL; 27194f1b2e48SStefano Zampini PetscInt i; 27205408967cSStefano Zampini 27215408967cSStefano Zampini PetscFunctionBegin; 27229566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph, &dirIS)); 27235408967cSStefano Zampini if (zerodiag) { 27245408967cSStefano Zampini Mat A; 27255408967cSStefano Zampini Vec vec3_N; 27265408967cSStefano Zampini PetscScalar *vals; 27275408967cSStefano Zampini const PetscInt *idxs; 2728d12d3064SStefano Zampini PetscInt nz, *count; 27295408967cSStefano Zampini 27305408967cSStefano Zampini /* p0 */ 27319566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_N, 0.)); 27329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n, &vals)); 27339566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zerodiag, &nz)); 27349566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zerodiag, &idxs)); 27354f1b2e48SStefano Zampini for (i = 0; i < nz; i++) vals[i] = 1.; 27369566063dSJacob Faibussowitsch PetscCall(VecSetValues(pcis->vec1_N, nz, idxs, vals, INSERT_VALUES)); 27379566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(pcis->vec1_N)); 27389566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(pcis->vec1_N)); 27395408967cSStefano Zampini /* v_I */ 27409566063dSJacob Faibussowitsch PetscCall(VecSetRandom(pcis->vec2_N, NULL)); 27415408967cSStefano Zampini for (i = 0; i < nz; i++) vals[i] = 0.; 27429566063dSJacob Faibussowitsch PetscCall(VecSetValues(pcis->vec2_N, nz, idxs, vals, INSERT_VALUES)); 27439566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zerodiag, &idxs)); 27449566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_B_local, &idxs)); 27455408967cSStefano Zampini for (i = 0; i < pcis->n_B; i++) vals[i] = 0.; 27469566063dSJacob Faibussowitsch PetscCall(VecSetValues(pcis->vec2_N, pcis->n_B, idxs, vals, INSERT_VALUES)); 27479566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_B_local, &idxs)); 27485408967cSStefano Zampini if (dirIS) { 27495408967cSStefano Zampini PetscInt n; 27505408967cSStefano Zampini 27519566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(dirIS, &n)); 27529566063dSJacob Faibussowitsch PetscCall(ISGetIndices(dirIS, &idxs)); 27535408967cSStefano Zampini for (i = 0; i < n; i++) vals[i] = 0.; 27549566063dSJacob Faibussowitsch PetscCall(VecSetValues(pcis->vec2_N, n, idxs, vals, INSERT_VALUES)); 27559566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(dirIS, &idxs)); 27565408967cSStefano Zampini } 27579566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(pcis->vec2_N)); 27589566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(pcis->vec2_N)); 27599566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_N, &vec3_N)); 27609566063dSJacob Faibussowitsch PetscCall(VecSet(vec3_N, 0.)); 27619566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->pmat, &A)); 27629566063dSJacob Faibussowitsch PetscCall(MatMult(A, pcis->vec1_N, vec3_N)); 27639566063dSJacob Faibussowitsch PetscCall(VecDot(vec3_N, pcis->vec2_N, &vals[0])); 27647827d75bSBarry 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])); 27659566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 27669566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vec3_N)); 2767d12d3064SStefano Zampini 2768d12d3064SStefano Zampini /* there should not be any pressure dofs lying on the interface */ 27699566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pcis->n, &count)); 27709566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_B_local, &idxs)); 2771d12d3064SStefano Zampini for (i = 0; i < pcis->n_B; i++) count[idxs[i]]++; 27729566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_B_local, &idxs)); 27739566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zerodiag, &idxs)); 277463a3b9bcSJacob 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]); 27759566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zerodiag, &idxs)); 27769566063dSJacob Faibussowitsch PetscCall(PetscFree(count)); 27775408967cSStefano Zampini } 27789566063dSJacob Faibussowitsch PetscCall(ISDestroy(&dirIS)); 27795408967cSStefano Zampini 27805408967cSStefano Zampini /* check PCBDDCBenignGetOrSetP0 */ 27819566063dSJacob Faibussowitsch PetscCall(VecSetRandom(pcis->vec1_global, NULL)); 27824f1b2e48SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) pcbddc->benign_p0[i] = -PetscGlobalRank - i; 27839566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc, pcis->vec1_global, PETSC_FALSE)); 27844f1b2e48SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) pcbddc->benign_p0[i] = 1; 27859566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc, pcis->vec1_global, PETSC_TRUE)); 2786f2a566d8SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) { 2787f2a566d8SStefano Zampini PetscInt val = PetscRealPart(pcbddc->benign_p0[i]); 278863a3b9bcSJacob 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)); 2789f2a566d8SStefano Zampini } 27903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 27915408967cSStefano Zampini } 27925408967cSStefano Zampini 2793d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, PetscBool reuse, IS *zerodiaglocal) 2794d71ae5a4SJacob Faibussowitsch { 2795339f8db1SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 2796f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)pc->pmat->data; 27973b03f7bbSStefano Zampini IS pressures = NULL, zerodiag = NULL, *bzerodiag = NULL, zerodiag_save, *zerodiag_subs; 27983b03f7bbSStefano Zampini PetscInt nz, n, benign_n, bsp = 1; 27994edc6404Sstefano_zampini PetscInt *interior_dofs, n_interior_dofs, nneu; 28004edc6404Sstefano_zampini PetscBool sorted, have_null, has_null_pressures, recompute_zerodiag, checkb; 2801339f8db1SStefano Zampini 2802339f8db1SStefano Zampini PetscFunctionBegin; 28033b03f7bbSStefano Zampini if (reuse) goto project_b0; 28049566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pcbddc->benign_sf)); 28059566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->benign_B0)); 280648a46eb9SPierre Jolivet for (n = 0; n < pcbddc->benign_n; n++) PetscCall(ISDestroy(&pcbddc->benign_zerodiag_subs[n])); 28079566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->benign_zerodiag_subs)); 28083b03f7bbSStefano Zampini has_null_pressures = PETSC_TRUE; 28093b03f7bbSStefano Zampini have_null = PETSC_TRUE; 28103b03f7bbSStefano Zampini /* if a local information on dofs is present, gets pressure dofs from command line (uses the last field is not provided) 28113b03f7bbSStefano Zampini Without local information, it uses only the zerodiagonal dofs (ok if the pressure block is all zero and it is a scalar field) 28124f1b2e48SStefano Zampini Checks if all the pressure dofs in each subdomain have a zero diagonal 28134f1b2e48SStefano Zampini If not, a change of basis on pressures is not needed 28141ae86dd6SStefano Zampini since the local Schur complements are already SPD 28154f1b2e48SStefano Zampini */ 281640fa8d13SStefano Zampini if (pcbddc->n_ISForDofsLocal) { 28177fbe2174Sstefano_zampini IS iP = NULL; 28183b03f7bbSStefano Zampini PetscInt p, *pp; 281947c5ace7SStefano Zampini PetscBool flg, blocked = PETSC_FALSE; 28204f1b2e48SStefano Zampini 28219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->n_ISForDofsLocal, &pp)); 28223b03f7bbSStefano Zampini n = pcbddc->n_ISForDofsLocal; 2823d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)pc), ((PetscObject)pc)->prefix, "BDDC benign options", "PC"); 28249566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-pc_bddc_pressure_field", "Field id for pressures", NULL, pp, &n, &flg)); 282547c5ace7SStefano Zampini PetscCall(PetscOptionsBool("-pc_bddc_pressure_blocked", "Use blocked pressure fields", NULL, blocked, &blocked, NULL)); 2826d0609cedSBarry Smith PetscOptionsEnd(); 28273b03f7bbSStefano Zampini if (!flg) { 28283b03f7bbSStefano Zampini n = 1; 28293b03f7bbSStefano Zampini pp[0] = pcbddc->n_ISForDofsLocal - 1; 28303b03f7bbSStefano Zampini } 28313b03f7bbSStefano Zampini 28323b03f7bbSStefano Zampini bsp = 0; 28333b03f7bbSStefano Zampini for (p = 0; p < n; p++) { 283447c5ace7SStefano Zampini PetscInt bs = 1; 28353b03f7bbSStefano Zampini 283663a3b9bcSJacob 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]); 283747c5ace7SStefano Zampini if (blocked) PetscCall(ISGetBlockSize(pcbddc->ISForDofsLocal[pp[p]], &bs)); 28383b03f7bbSStefano Zampini bsp += bs; 28393b03f7bbSStefano Zampini } 28409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bsp, &bzerodiag)); 28413b03f7bbSStefano Zampini bsp = 0; 28423b03f7bbSStefano Zampini for (p = 0; p < n; p++) { 28433b03f7bbSStefano Zampini const PetscInt *idxs; 284447c5ace7SStefano Zampini PetscInt b, bs = 1, npl, *bidxs; 28453b03f7bbSStefano Zampini 284647c5ace7SStefano Zampini if (blocked) PetscCall(ISGetBlockSize(pcbddc->ISForDofsLocal[pp[p]], &bs)); 28479566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->ISForDofsLocal[pp[p]], &npl)); 28489566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->ISForDofsLocal[pp[p]], &idxs)); 28499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(npl / bs, &bidxs)); 28503b03f7bbSStefano Zampini for (b = 0; b < bs; b++) { 28513b03f7bbSStefano Zampini PetscInt i; 28523b03f7bbSStefano Zampini 28533b03f7bbSStefano Zampini for (i = 0; i < npl / bs; i++) bidxs[i] = idxs[bs * i + b]; 28549566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, npl / bs, bidxs, PETSC_COPY_VALUES, &bzerodiag[bsp])); 28553b03f7bbSStefano Zampini bsp++; 28563b03f7bbSStefano Zampini } 28579566063dSJacob Faibussowitsch PetscCall(PetscFree(bidxs)); 28589566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->ISForDofsLocal[pp[p]], &idxs)); 28593b03f7bbSStefano Zampini } 28609566063dSJacob Faibussowitsch PetscCall(ISConcatenate(PETSC_COMM_SELF, bsp, bzerodiag, &pressures)); 28613b03f7bbSStefano Zampini 28627fbe2174Sstefano_zampini /* remove zeroed out pressures if we are setting up a BDDC solver for a saddle-point FETI-DP */ 28639566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lP", (PetscObject *)&iP)); 28647fbe2174Sstefano_zampini if (iP) { 28657fbe2174Sstefano_zampini IS newpressures; 28667fbe2174Sstefano_zampini 28679566063dSJacob Faibussowitsch PetscCall(ISDifference(pressures, iP, &newpressures)); 28689566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pressures)); 28697fbe2174Sstefano_zampini pressures = newpressures; 28707fbe2174Sstefano_zampini } 28719566063dSJacob Faibussowitsch PetscCall(ISSorted(pressures, &sorted)); 287248a46eb9SPierre Jolivet if (!sorted) PetscCall(ISSort(pressures)); 28739566063dSJacob Faibussowitsch PetscCall(PetscFree(pp)); 287440fa8d13SStefano Zampini } 28753b03f7bbSStefano Zampini 287697d764eeSStefano Zampini /* pcis has not been setup yet, so get the local size from the subdomain matrix */ 28779566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pcbddc->local_mat, &n, NULL)); 287827b6a85dSStefano Zampini if (!n) pcbddc->benign_change_explicit = PETSC_TRUE; 28799566063dSJacob Faibussowitsch PetscCall(MatFindZeroDiagonals(pcbddc->local_mat, &zerodiag)); 28809566063dSJacob Faibussowitsch PetscCall(ISSorted(zerodiag, &sorted)); 288148a46eb9SPierre Jolivet if (!sorted) PetscCall(ISSort(zerodiag)); 28829566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)zerodiag)); 28834edc6404Sstefano_zampini zerodiag_save = zerodiag; 28849566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zerodiag, &nz)); 28854f1b2e48SStefano Zampini if (!nz) { 28864f1b2e48SStefano Zampini if (n) have_null = PETSC_FALSE; 28874f1b2e48SStefano Zampini has_null_pressures = PETSC_FALSE; 28889566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zerodiag)); 288940fa8d13SStefano Zampini } 28904f1b2e48SStefano Zampini recompute_zerodiag = PETSC_FALSE; 28913b03f7bbSStefano Zampini 28924f1b2e48SStefano Zampini /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */ 28934f1b2e48SStefano Zampini zerodiag_subs = NULL; 28943b03f7bbSStefano Zampini benign_n = 0; 28951f4df5f7SStefano Zampini n_interior_dofs = 0; 28961f4df5f7SStefano Zampini interior_dofs = NULL; 28974edc6404Sstefano_zampini nneu = 0; 289848a46eb9SPierre Jolivet if (pcbddc->NeumannBoundariesLocal) PetscCall(ISGetLocalSize(pcbddc->NeumannBoundariesLocal, &nneu)); 28993369cb78Sstefano_zampini checkb = (PetscBool)(!pcbddc->NeumannBoundariesLocal || pcbddc->current_level); 29004edc6404Sstefano_zampini if (checkb) { /* need to compute interior nodes */ 29019de2952eSStefano Zampini PetscInt n, i; 29029de2952eSStefano Zampini PetscInt *count; 29039de2952eSStefano Zampini ISLocalToGlobalMapping mapping; 29041f4df5f7SStefano Zampini 29059de2952eSStefano Zampini PetscCall(MatISGetLocalToGlobalMapping(pc->pmat, &mapping, NULL)); 29069de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingGetNodeInfo(mapping, &n, &count, NULL)); 29079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &interior_dofs)); 29081f4df5f7SStefano Zampini for (i = 0; i < n; i++) 29099de2952eSStefano Zampini if (count[i] < 2) interior_dofs[n_interior_dofs++] = i; 29109de2952eSStefano Zampini PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(mapping, &n, &count, NULL)); 29111f4df5f7SStefano Zampini } 29124f1b2e48SStefano Zampini if (has_null_pressures) { 29134f1b2e48SStefano Zampini IS *subs; 29144edc6404Sstefano_zampini PetscInt nsubs, i, j, nl; 29151f4df5f7SStefano Zampini const PetscInt *idxs; 29161f4df5f7SStefano Zampini PetscScalar *array; 29171f4df5f7SStefano Zampini Vec *work; 29184f1b2e48SStefano Zampini 29194f1b2e48SStefano Zampini subs = pcbddc->local_subs; 29204f1b2e48SStefano Zampini nsubs = pcbddc->n_local_subs; 29211f4df5f7SStefano 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) */ 29224edc6404Sstefano_zampini if (checkb) { 29239566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(matis->y, 2, &work)); 29249566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zerodiag, &nl)); 29259566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zerodiag, &idxs)); 29261f4df5f7SStefano Zampini /* work[0] = 1_p */ 29279566063dSJacob Faibussowitsch PetscCall(VecSet(work[0], 0.)); 29289566063dSJacob Faibussowitsch PetscCall(VecGetArray(work[0], &array)); 29291f4df5f7SStefano Zampini for (j = 0; j < nl; j++) array[idxs[j]] = 1.; 29309566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(work[0], &array)); 29311f4df5f7SStefano Zampini /* work[0] = 1_v */ 29329566063dSJacob Faibussowitsch PetscCall(VecSet(work[1], 1.)); 29339566063dSJacob Faibussowitsch PetscCall(VecGetArray(work[1], &array)); 29341f4df5f7SStefano Zampini for (j = 0; j < nl; j++) array[idxs[j]] = 0.; 29359566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(work[1], &array)); 29369566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zerodiag, &idxs)); 29371f4df5f7SStefano Zampini } 29383b03f7bbSStefano Zampini 29393b03f7bbSStefano Zampini if (nsubs > 1 || bsp > 1) { 29403b03f7bbSStefano Zampini IS *is; 29413b03f7bbSStefano Zampini PetscInt b, totb; 29423b03f7bbSStefano Zampini 29433b03f7bbSStefano Zampini totb = bsp; 29443b03f7bbSStefano Zampini is = bsp > 1 ? bzerodiag : &zerodiag; 29453b03f7bbSStefano Zampini nsubs = PetscMax(nsubs, 1); 29469566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nsubs * totb, &zerodiag_subs)); 29473b03f7bbSStefano Zampini for (b = 0; b < totb; b++) { 29484f1b2e48SStefano Zampini for (i = 0; i < nsubs; i++) { 29494f1b2e48SStefano Zampini ISLocalToGlobalMapping l2g; 29504f1b2e48SStefano Zampini IS t_zerodiag_subs; 29514f1b2e48SStefano Zampini PetscInt nl; 29524f1b2e48SStefano Zampini 29533b03f7bbSStefano Zampini if (subs) { 29549566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(subs[i], &l2g)); 29553b03f7bbSStefano Zampini } else { 29563b03f7bbSStefano Zampini IS tis; 29573b03f7bbSStefano Zampini 29589566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pcbddc->local_mat, &nl, NULL)); 29599566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, nl, 0, 1, &tis)); 29609566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(tis, &l2g)); 29619566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tis)); 29623b03f7bbSStefano Zampini } 29639566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(l2g, IS_GTOLM_DROP, is[b], &t_zerodiag_subs)); 29649566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(t_zerodiag_subs, &nl)); 29654f1b2e48SStefano Zampini if (nl) { 29664f1b2e48SStefano Zampini PetscBool valid = PETSC_TRUE; 29674f1b2e48SStefano Zampini 29684edc6404Sstefano_zampini if (checkb) { 29699566063dSJacob Faibussowitsch PetscCall(VecSet(matis->x, 0)); 29709566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(subs[i], &nl)); 29719566063dSJacob Faibussowitsch PetscCall(ISGetIndices(subs[i], &idxs)); 29729566063dSJacob Faibussowitsch PetscCall(VecGetArray(matis->x, &array)); 29731f4df5f7SStefano Zampini for (j = 0; j < nl; j++) array[idxs[j]] = 1.; 29749566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(matis->x, &array)); 29759566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(subs[i], &idxs)); 29769566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(matis->x, work[0], matis->x)); 29779566063dSJacob Faibussowitsch PetscCall(MatMult(matis->A, matis->x, matis->y)); 29789566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(matis->y, work[1], matis->y)); 29799566063dSJacob Faibussowitsch PetscCall(VecGetArray(matis->y, &array)); 29801f4df5f7SStefano Zampini for (j = 0; j < n_interior_dofs; j++) { 29811f4df5f7SStefano Zampini if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) { 29821f4df5f7SStefano Zampini valid = PETSC_FALSE; 29831f4df5f7SStefano Zampini break; 29841f4df5f7SStefano Zampini } 29851f4df5f7SStefano Zampini } 29869566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(matis->y, &array)); 29871f4df5f7SStefano Zampini } 29886632bad2Sstefano_zampini if (valid && nneu) { 29896632bad2Sstefano_zampini const PetscInt *idxs; 29901f4df5f7SStefano Zampini PetscInt nzb; 29911f4df5f7SStefano Zampini 29929566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->NeumannBoundariesLocal, &idxs)); 29939566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(l2g, IS_GTOLM_DROP, nneu, idxs, &nzb, NULL)); 29949566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->NeumannBoundariesLocal, &idxs)); 29951f4df5f7SStefano Zampini if (nzb) valid = PETSC_FALSE; 29961f4df5f7SStefano Zampini } 29971f4df5f7SStefano Zampini if (valid && pressures) { 29983b03f7bbSStefano Zampini IS t_pressure_subs, tmp; 29993b03f7bbSStefano Zampini PetscInt i1, i2; 30003b03f7bbSStefano Zampini 30019566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(l2g, IS_GTOLM_DROP, pressures, &t_pressure_subs)); 30029566063dSJacob Faibussowitsch PetscCall(ISEmbed(t_zerodiag_subs, t_pressure_subs, PETSC_TRUE, &tmp)); 30039566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(tmp, &i1)); 30049566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(t_zerodiag_subs, &i2)); 30053b03f7bbSStefano Zampini if (i2 != i1) valid = PETSC_FALSE; 30069566063dSJacob Faibussowitsch PetscCall(ISDestroy(&t_pressure_subs)); 30079566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tmp)); 30084f1b2e48SStefano Zampini } 30094f1b2e48SStefano Zampini if (valid) { 30109566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(l2g, t_zerodiag_subs, &zerodiag_subs[benign_n])); 30113b03f7bbSStefano Zampini benign_n++; 30123b03f7bbSStefano Zampini } else recompute_zerodiag = PETSC_TRUE; 30134f1b2e48SStefano Zampini } 30149566063dSJacob Faibussowitsch PetscCall(ISDestroy(&t_zerodiag_subs)); 30159566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&l2g)); 30164f1b2e48SStefano Zampini } 30173b03f7bbSStefano Zampini } 30184f1b2e48SStefano Zampini } else { /* there's just one subdomain (or zero if they have not been detected */ 30194f1b2e48SStefano Zampini PetscBool valid = PETSC_TRUE; 30201f4df5f7SStefano Zampini 30216632bad2Sstefano_zampini if (nneu) valid = PETSC_FALSE; 302248a46eb9SPierre Jolivet if (valid && pressures) PetscCall(ISEqual(pressures, zerodiag, &valid)); 30234edc6404Sstefano_zampini if (valid && checkb) { 30249566063dSJacob Faibussowitsch PetscCall(MatMult(matis->A, work[0], matis->x)); 30259566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(matis->x, work[1], matis->x)); 30269566063dSJacob Faibussowitsch PetscCall(VecGetArray(matis->x, &array)); 30271f4df5f7SStefano Zampini for (j = 0; j < n_interior_dofs; j++) { 30281f4df5f7SStefano Zampini if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) { 30291f4df5f7SStefano Zampini valid = PETSC_FALSE; 30301f4df5f7SStefano Zampini break; 30311f4df5f7SStefano Zampini } 30321f4df5f7SStefano Zampini } 30339566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(matis->x, &array)); 30341f4df5f7SStefano Zampini } 30354f1b2e48SStefano Zampini if (valid) { 30363b03f7bbSStefano Zampini benign_n = 1; 30379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(benign_n, &zerodiag_subs)); 30389566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)zerodiag)); 30394f1b2e48SStefano Zampini zerodiag_subs[0] = zerodiag; 30404f1b2e48SStefano Zampini } 30414f1b2e48SStefano Zampini } 304248a46eb9SPierre Jolivet if (checkb) PetscCall(VecDestroyVecs(2, &work)); 30431f4df5f7SStefano Zampini } 30449566063dSJacob Faibussowitsch PetscCall(PetscFree(interior_dofs)); 30454f1b2e48SStefano Zampini 30463b03f7bbSStefano Zampini if (!benign_n) { 3047b9b0e38cSStefano Zampini PetscInt n; 3048b9b0e38cSStefano Zampini 30499566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zerodiag)); 30504f1b2e48SStefano Zampini recompute_zerodiag = PETSC_FALSE; 30519566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pcbddc->local_mat, &n, NULL)); 305276a58201SStefano Zampini if (n) have_null = PETSC_FALSE; 3053b9b0e38cSStefano Zampini } 30544f1b2e48SStefano Zampini 30554f1b2e48SStefano Zampini /* final check for null pressures */ 305648a46eb9SPierre Jolivet if (zerodiag && pressures) PetscCall(ISEqual(pressures, zerodiag, &have_null)); 30574f1b2e48SStefano Zampini 30584f1b2e48SStefano Zampini if (recompute_zerodiag) { 30599566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zerodiag)); 30603b03f7bbSStefano Zampini if (benign_n == 1) { 30619566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)zerodiag_subs[0])); 30624f1b2e48SStefano Zampini zerodiag = zerodiag_subs[0]; 30634f1b2e48SStefano Zampini } else { 30644f1b2e48SStefano Zampini PetscInt i, nzn, *new_idxs; 30654f1b2e48SStefano Zampini 30664f1b2e48SStefano Zampini nzn = 0; 30673b03f7bbSStefano Zampini for (i = 0; i < benign_n; i++) { 30684f1b2e48SStefano Zampini PetscInt ns; 30699566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zerodiag_subs[i], &ns)); 30704f1b2e48SStefano Zampini nzn += ns; 30714f1b2e48SStefano Zampini } 30729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nzn, &new_idxs)); 30734f1b2e48SStefano Zampini nzn = 0; 30743b03f7bbSStefano Zampini for (i = 0; i < benign_n; i++) { 30754f1b2e48SStefano Zampini PetscInt ns, *idxs; 30769566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zerodiag_subs[i], &ns)); 30779566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zerodiag_subs[i], (const PetscInt **)&idxs)); 30789566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(new_idxs + nzn, idxs, ns)); 30799566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zerodiag_subs[i], (const PetscInt **)&idxs)); 30804f1b2e48SStefano Zampini nzn += ns; 30814f1b2e48SStefano Zampini } 30829566063dSJacob Faibussowitsch PetscCall(PetscSortInt(nzn, new_idxs)); 30839566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nzn, new_idxs, PETSC_OWN_POINTER, &zerodiag)); 30844f1b2e48SStefano Zampini } 30854f1b2e48SStefano Zampini have_null = PETSC_FALSE; 30864f1b2e48SStefano Zampini } 30874f1b2e48SStefano Zampini 30883b03f7bbSStefano Zampini /* determines if the coarse solver will be singular or not */ 30895440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&have_null, &pcbddc->benign_null, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)pc))); 30903b03f7bbSStefano Zampini 3091669cc0f4SStefano Zampini /* Prepare matrix to compute no-net-flux */ 3092a198735bSStefano Zampini if (pcbddc->compute_nonetflux && !pcbddc->divudotp) { 3093a198735bSStefano Zampini Mat A, loc_divudotp; 3094a198735bSStefano Zampini ISLocalToGlobalMapping rl2g, cl2g, l2gmap; 3095a198735bSStefano Zampini IS row, col, isused = NULL; 3096a198735bSStefano Zampini PetscInt M, N, n, st, n_isused; 3097a198735bSStefano Zampini 30981f4df5f7SStefano Zampini if (pressures) { 30991f4df5f7SStefano Zampini isused = pressures; 31001f4df5f7SStefano Zampini } else { 31014edc6404Sstefano_zampini isused = zerodiag_save; 31021f4df5f7SStefano Zampini } 31039566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(pc->pmat, &l2gmap, NULL)); 31049566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->pmat, &A)); 31059566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &n, NULL)); 31067827d75bSBarry 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"); 3107a198735bSStefano Zampini n_isused = 0; 310848a46eb9SPierre Jolivet if (isused) PetscCall(ISGetLocalSize(isused, &n_isused)); 31099566063dSJacob Faibussowitsch PetscCallMPI(MPI_Scan(&n_isused, &st, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)pc))); 3110a198735bSStefano Zampini st = st - n_isused; 31111ae86dd6SStefano Zampini if (n) { 3112a198735bSStefano Zampini const PetscInt *gidxs; 3113a198735bSStefano Zampini 31149566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, isused, NULL, MAT_INITIAL_MATRIX, &loc_divudotp)); 31159566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(l2gmap, &gidxs)); 3116a198735bSStefano Zampini /* TODO: extend ISCreateStride with st = PETSC_DECIDE */ 31179566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)pc), n_isused, st, 1, &row)); 31189566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), n, gidxs, PETSC_COPY_VALUES, &col)); 31199566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(l2gmap, &gidxs)); 31201ae86dd6SStefano Zampini } else { 31219566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, 0, 0, 1, NULL, &loc_divudotp)); 31229566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)pc), n_isused, st, 1, &row)); 31239566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), 0, NULL, PETSC_COPY_VALUES, &col)); 3124a198735bSStefano Zampini } 31259566063dSJacob Faibussowitsch PetscCall(MatGetSize(pc->pmat, NULL, &N)); 31269566063dSJacob Faibussowitsch PetscCall(ISGetSize(row, &M)); 31279566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(row, &rl2g)); 31289566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(col, &cl2g)); 31299566063dSJacob Faibussowitsch PetscCall(ISDestroy(&row)); 31309566063dSJacob Faibussowitsch PetscCall(ISDestroy(&col)); 31319566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)pc), &pcbddc->divudotp)); 31329566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->divudotp, MATIS)); 31339566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->divudotp, PETSC_DECIDE, PETSC_DECIDE, M, N)); 31349566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(pcbddc->divudotp, rl2g, cl2g)); 31359566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 31369566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 31379566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(pcbddc->divudotp, loc_divudotp)); 31389566063dSJacob Faibussowitsch PetscCall(MatDestroy(&loc_divudotp)); 31399566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pcbddc->divudotp, MAT_FINAL_ASSEMBLY)); 31409566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->divudotp, MAT_FINAL_ASSEMBLY)); 31411ae86dd6SStefano Zampini } 31429566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zerodiag_save)); 31439566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pressures)); 31443b03f7bbSStefano Zampini if (bzerodiag) { 31453b03f7bbSStefano Zampini PetscInt i; 3146b3afcdbeSStefano Zampini 314748a46eb9SPierre Jolivet for (i = 0; i < bsp; i++) PetscCall(ISDestroy(&bzerodiag[i])); 31489566063dSJacob Faibussowitsch PetscCall(PetscFree(bzerodiag)); 31493b03f7bbSStefano Zampini } 31503b03f7bbSStefano Zampini pcbddc->benign_n = benign_n; 31513b03f7bbSStefano Zampini pcbddc->benign_zerodiag_subs = zerodiag_subs; 31523b03f7bbSStefano Zampini 31533b03f7bbSStefano Zampini /* determines if the problem has subdomains with 0 pressure block */ 31543b03f7bbSStefano Zampini have_null = (PetscBool)(!!pcbddc->benign_n); 31555440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&have_null, &pcbddc->benign_have_null, 1, MPI_C_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 31563b03f7bbSStefano Zampini 31573b03f7bbSStefano Zampini project_b0: 31589566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pcbddc->local_mat, &n, NULL)); 3159b3afcdbeSStefano Zampini /* change of basis and p0 dofs */ 31603b03f7bbSStefano Zampini if (pcbddc->benign_n) { 31614f1b2e48SStefano Zampini PetscInt i, s, *nnz; 31624f1b2e48SStefano Zampini 3163339f8db1SStefano Zampini /* local change of basis for pressures */ 31649566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->benign_change)); 31659566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat), &pcbddc->benign_change)); 31669566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->benign_change, MATAIJ)); 31679566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->benign_change, n, n, PETSC_DECIDE, PETSC_DECIDE)); 31689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &nnz)); 3169aa0d93e9SStefano Zampini for (i = 0; i < n; i++) nnz[i] = 1; /* defaults to identity */ 31704f1b2e48SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) { 3171aa0d93e9SStefano Zampini const PetscInt *idxs; 31724f1b2e48SStefano Zampini PetscInt nzs, j; 31734f1b2e48SStefano Zampini 31749566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[i], &nzs)); 31759566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->benign_zerodiag_subs[i], &idxs)); 31764f1b2e48SStefano Zampini for (j = 0; j < nzs - 1; j++) nnz[idxs[j]] = 2; /* change on pressures */ 31774f1b2e48SStefano Zampini nnz[idxs[nzs - 1]] = nzs; /* last local pressure dof in subdomain */ 31789566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->benign_zerodiag_subs[i], &idxs)); 31794f1b2e48SStefano Zampini } 31809566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(pcbddc->benign_change, 0, nnz)); 31819566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->benign_change, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 31829566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 3183aa0d93e9SStefano Zampini /* set identity by default */ 318448a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall(MatSetValue(pcbddc->benign_change, i, i, 1., INSERT_VALUES)); 31859566063dSJacob Faibussowitsch PetscCall(PetscFree3(pcbddc->benign_p0_lidx, pcbddc->benign_p0_gidx, pcbddc->benign_p0)); 31869566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(pcbddc->benign_n, &pcbddc->benign_p0_lidx, pcbddc->benign_n, &pcbddc->benign_p0_gidx, pcbddc->benign_n, &pcbddc->benign_p0)); 3187339f8db1SStefano Zampini /* set change on pressures */ 31884f1b2e48SStefano Zampini for (s = 0; s < pcbddc->benign_n; s++) { 31894f1b2e48SStefano Zampini PetscScalar *array; 3190aa0d93e9SStefano Zampini const PetscInt *idxs; 31914f1b2e48SStefano Zampini PetscInt nzs; 31924f1b2e48SStefano Zampini 31939566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[s], &nzs)); 31949566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->benign_zerodiag_subs[s], &idxs)); 31954f1b2e48SStefano Zampini for (i = 0; i < nzs - 1; i++) { 3196339f8db1SStefano Zampini PetscScalar vals[2]; 3197339f8db1SStefano Zampini PetscInt cols[2]; 3198339f8db1SStefano Zampini 3199339f8db1SStefano Zampini cols[0] = idxs[i]; 32004f1b2e48SStefano Zampini cols[1] = idxs[nzs - 1]; 3201339f8db1SStefano Zampini vals[0] = 1.; 3202b0f5fe93SStefano Zampini vals[1] = 1.; 32039566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->benign_change, 1, cols, 2, cols, vals, INSERT_VALUES)); 3204339f8db1SStefano Zampini } 32059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nzs, &array)); 32064f1b2e48SStefano Zampini for (i = 0; i < nzs - 1; i++) array[i] = -1.; 32074f1b2e48SStefano Zampini array[nzs - 1] = 1.; 32089566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->benign_change, 1, idxs + nzs - 1, nzs, idxs, array, INSERT_VALUES)); 32094f1b2e48SStefano Zampini /* store local idxs for p0 */ 32104f1b2e48SStefano Zampini pcbddc->benign_p0_lidx[s] = idxs[nzs - 1]; 32119566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->benign_zerodiag_subs[s], &idxs)); 32129566063dSJacob Faibussowitsch PetscCall(PetscFree(array)); 32134f1b2e48SStefano Zampini } 32149566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pcbddc->benign_change, MAT_FINAL_ASSEMBLY)); 32159566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->benign_change, MAT_FINAL_ASSEMBLY)); 32163b03f7bbSStefano Zampini 3217a3df083aSStefano Zampini /* project if needed */ 3218a3df083aSStefano Zampini if (pcbddc->benign_change_explicit) { 32191dd7afcfSStefano Zampini Mat M; 32201dd7afcfSStefano Zampini 32219566063dSJacob Faibussowitsch PetscCall(MatPtAP(pcbddc->local_mat, pcbddc->benign_change, MAT_INITIAL_MATRIX, 2.0, &M)); 32229566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 32239566063dSJacob Faibussowitsch PetscCall(MatSeqAIJCompress(M, &pcbddc->local_mat)); 32249566063dSJacob Faibussowitsch PetscCall(MatDestroy(&M)); 3225a3df083aSStefano Zampini } 32264f1b2e48SStefano Zampini /* store global idxs for p0 */ 32279566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(matis->rmapping, pcbddc->benign_n, pcbddc->benign_p0_lidx, pcbddc->benign_p0_gidx)); 3228339f8db1SStefano Zampini } 3229339f8db1SStefano Zampini *zerodiaglocal = zerodiag; 32303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3231339f8db1SStefano Zampini } 3232339f8db1SStefano Zampini 3233d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get) 3234d71ae5a4SJacob Faibussowitsch { 3235efc2fbd9SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 3236de9d7bd0SStefano Zampini PetscScalar *array; 3237efc2fbd9SStefano Zampini 3238efc2fbd9SStefano Zampini PetscFunctionBegin; 3239efc2fbd9SStefano Zampini if (!pcbddc->benign_sf) { 32409566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)pc), &pcbddc->benign_sf)); 32419566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(pcbddc->benign_sf, pc->pmat->rmap, pcbddc->benign_n, NULL, PETSC_OWN_POINTER, pcbddc->benign_p0_gidx)); 3242efc2fbd9SStefano Zampini } 3243de9d7bd0SStefano Zampini if (get) { 32449566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, (const PetscScalar **)&array)); 32459566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pcbddc->benign_sf, MPIU_SCALAR, array, pcbddc->benign_p0, MPI_REPLACE)); 32469566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pcbddc->benign_sf, MPIU_SCALAR, array, pcbddc->benign_p0, MPI_REPLACE)); 32479566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, (const PetscScalar **)&array)); 3248de9d7bd0SStefano Zampini } else { 32499566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 32509566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(pcbddc->benign_sf, MPIU_SCALAR, pcbddc->benign_p0, array, MPI_REPLACE)); 32519566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(pcbddc->benign_sf, MPIU_SCALAR, pcbddc->benign_p0, array, MPI_REPLACE)); 32529566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 3253efc2fbd9SStefano Zampini } 32543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3255efc2fbd9SStefano Zampini } 3256efc2fbd9SStefano Zampini 3257d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop) 3258d71ae5a4SJacob Faibussowitsch { 3259c263805aSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 3260c263805aSStefano Zampini 3261c263805aSStefano Zampini PetscFunctionBegin; 3262c263805aSStefano Zampini /* TODO: add error checking 3263c263805aSStefano Zampini - avoid nested pop (or push) calls. 3264c263805aSStefano Zampini - cannot push before pop. 32651c604dc7SStefano Zampini - cannot call this if pcbddc->local_mat is NULL 3266c263805aSStefano Zampini */ 32673ba16761SJacob Faibussowitsch if (!pcbddc->benign_n) PetscFunctionReturn(PETSC_SUCCESS); 3268c263805aSStefano Zampini if (pop) { 3269a3df083aSStefano Zampini if (pcbddc->benign_change_explicit) { 32704f1b2e48SStefano Zampini IS is_p0; 32714f1b2e48SStefano Zampini MatReuse reuse; 3272c263805aSStefano Zampini 3273c263805aSStefano Zampini /* extract B_0 */ 32744f1b2e48SStefano Zampini reuse = MAT_INITIAL_MATRIX; 3275ad540459SPierre Jolivet if (pcbddc->benign_B0) reuse = MAT_REUSE_MATRIX; 32769566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, pcbddc->benign_n, pcbddc->benign_p0_lidx, PETSC_COPY_VALUES, &is_p0)); 32779566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, is_p0, NULL, reuse, &pcbddc->benign_B0)); 3278c263805aSStefano Zampini /* remove rows and cols from local problem */ 32799566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->local_mat, MAT_KEEP_NONZERO_PATTERN, PETSC_TRUE)); 32809566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->local_mat, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_FALSE)); 32819566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumnsIS(pcbddc->local_mat, is_p0, 1.0, NULL, NULL)); 32829566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_p0)); 3283a3df083aSStefano Zampini } else { 3284a3df083aSStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 3285a3df083aSStefano Zampini PetscScalar *vals; 3286a3df083aSStefano Zampini PetscInt i, n, *idxs_ins; 3287a3df083aSStefano Zampini 32889566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(matis->y, &n)); 32899566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n, &idxs_ins, n, &vals)); 3290a3df083aSStefano Zampini if (!pcbddc->benign_B0) { 32910b5adadeSStefano Zampini PetscInt *nnz; 32929566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat), &pcbddc->benign_B0)); 32939566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->benign_B0, MATAIJ)); 32949566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->benign_B0, pcbddc->benign_n, n, PETSC_DECIDE, PETSC_DECIDE)); 32959566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->benign_n, &nnz)); 3296331e053bSStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) { 32979566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[i], &nnz[i])); 3298331e053bSStefano Zampini nnz[i] = n - nnz[i]; 3299331e053bSStefano Zampini } 33009566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(pcbddc->benign_B0, 0, nnz)); 33019566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->benign_B0, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 33029566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 3303331e053bSStefano Zampini } 3304a3df083aSStefano Zampini 3305a3df083aSStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) { 3306a3df083aSStefano Zampini PetscScalar *array; 3307a3df083aSStefano Zampini PetscInt *idxs, j, nz, cum; 3308a3df083aSStefano Zampini 33099566063dSJacob Faibussowitsch PetscCall(VecSet(matis->x, 0.)); 33109566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[i], &nz)); 33119566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->benign_zerodiag_subs[i], (const PetscInt **)&idxs)); 3312a3df083aSStefano Zampini for (j = 0; j < nz; j++) vals[j] = 1.; 33139566063dSJacob Faibussowitsch PetscCall(VecSetValues(matis->x, nz, idxs, vals, INSERT_VALUES)); 33149566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(matis->x)); 33159566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(matis->x)); 33169566063dSJacob Faibussowitsch PetscCall(VecSet(matis->y, 0.)); 33179566063dSJacob Faibussowitsch PetscCall(MatMult(matis->A, matis->x, matis->y)); 33189566063dSJacob Faibussowitsch PetscCall(VecGetArray(matis->y, &array)); 3319a3df083aSStefano Zampini cum = 0; 3320a3df083aSStefano Zampini for (j = 0; j < n; j++) { 332122db5ddcSStefano Zampini if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) { 3322a3df083aSStefano Zampini vals[cum] = array[j]; 3323a3df083aSStefano Zampini idxs_ins[cum] = j; 3324a3df083aSStefano Zampini cum++; 3325a3df083aSStefano Zampini } 3326a3df083aSStefano Zampini } 33279566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->benign_B0, 1, &i, cum, idxs_ins, vals, INSERT_VALUES)); 33289566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(matis->y, &array)); 33299566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->benign_zerodiag_subs[i], (const PetscInt **)&idxs)); 3330a3df083aSStefano Zampini } 33319566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pcbddc->benign_B0, MAT_FINAL_ASSEMBLY)); 33329566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->benign_B0, MAT_FINAL_ASSEMBLY)); 33339566063dSJacob Faibussowitsch PetscCall(PetscFree2(idxs_ins, vals)); 3334a3df083aSStefano Zampini } 3335c263805aSStefano Zampini } else { /* push */ 33364f1b2e48SStefano Zampini 33370fdf79fbSJacob Faibussowitsch PetscCheck(pcbddc->benign_change_explicit, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Cannot push B0!"); 33380fdf79fbSJacob Faibussowitsch for (PetscInt i = 0; i < pcbddc->benign_n; i++) { 33394f1b2e48SStefano Zampini PetscScalar *B0_vals; 33404f1b2e48SStefano Zampini PetscInt *B0_cols, B0_ncol; 33414f1b2e48SStefano Zampini 33429566063dSJacob Faibussowitsch PetscCall(MatGetRow(pcbddc->benign_B0, i, &B0_ncol, (const PetscInt **)&B0_cols, (const PetscScalar **)&B0_vals)); 33439566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->local_mat, 1, pcbddc->benign_p0_lidx + i, B0_ncol, B0_cols, B0_vals, INSERT_VALUES)); 33449566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->local_mat, B0_ncol, B0_cols, 1, pcbddc->benign_p0_lidx + i, B0_vals, INSERT_VALUES)); 33459566063dSJacob Faibussowitsch PetscCall(MatSetValue(pcbddc->local_mat, pcbddc->benign_p0_lidx[i], pcbddc->benign_p0_lidx[i], 0.0, INSERT_VALUES)); 33469566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(pcbddc->benign_B0, i, &B0_ncol, (const PetscInt **)&B0_cols, (const PetscScalar **)&B0_vals)); 33474f1b2e48SStefano Zampini } 33489566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pcbddc->local_mat, MAT_FINAL_ASSEMBLY)); 33499566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->local_mat, MAT_FINAL_ASSEMBLY)); 3350c263805aSStefano Zampini } 33513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3352c263805aSStefano Zampini } 3353c263805aSStefano Zampini 3354d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCAdaptiveSelection(PC pc) 3355d71ae5a4SJacob Faibussowitsch { 3356b1b3d7a2SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 335708122e43SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 335897b17b2cSPierre Jolivet PetscBLASInt B_neigs, B_ierr, B_lwork; 335908122e43SStefano Zampini PetscBLASInt *B_iwork, *B_ifail; 336008122e43SStefano Zampini PetscScalar *work, lwork; 336108122e43SStefano Zampini PetscScalar *St, *S, *eigv; 336208122e43SStefano Zampini PetscScalar *Sarray, *Starray; 3363bd2a564bSStefano Zampini PetscReal *eigs, thresh, lthresh, uthresh; 33641b968477SStefano Zampini PetscInt i, nmax, nmin, nv, cum, mss, cum2, cumarray, maxneigs; 336532fe681dSStefano Zampini PetscBool allocated_S_St, upart; 336608122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 336708122e43SStefano Zampini PetscReal *rwork; 336808122e43SStefano Zampini #endif 3369b1b3d7a2SStefano Zampini 3370b1b3d7a2SStefano Zampini PetscFunctionBegin; 33713ba16761SJacob Faibussowitsch if (!pcbddc->adaptive_selection) PetscFunctionReturn(PETSC_SUCCESS); 337228b400f6SJacob Faibussowitsch PetscCheck(sub_schurs, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Adaptive selection of constraints requires SubSchurs data"); 337332fe681dSStefano 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"); 33749371c9d4SSatish 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, 33759371c9d4SSatish Balay sub_schurs->is_posdef); 33769566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_AdaptiveSetUp[pcbddc->current_level], pc, 0, 0, 0)); 337706a4e24aSStefano Zampini 3378fd14bc51SStefano Zampini if (pcbddc->dbg_flag) { 337932fe681dSStefano Zampini if (!pcbddc->dbg_viewer) pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc)); 33809566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 33819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 33829566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Check adaptive selection of constraints\n")); 33839566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 3384fd14bc51SStefano Zampini } 3385fd14bc51SStefano Zampini 338648a46eb9SPierre 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)); 3387e496cd5dSStefano Zampini 338808122e43SStefano Zampini /* max size of subsets */ 338908122e43SStefano Zampini mss = 0; 339008122e43SStefano Zampini for (i = 0; i < sub_schurs->n_subs; i++) { 339108122e43SStefano Zampini PetscInt subset_size; 3392862806e4SStefano Zampini 33939566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->is_subs[i], &subset_size)); 339408122e43SStefano Zampini mss = PetscMax(mss, subset_size); 339508122e43SStefano Zampini } 339608122e43SStefano Zampini 339708122e43SStefano Zampini /* min/max and threshold */ 339808122e43SStefano Zampini nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss; 3399f6f667cfSStefano Zampini nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0; 340008122e43SStefano Zampini nmax = PetscMax(nmin, nmax); 3401f6f667cfSStefano Zampini allocated_S_St = PETSC_FALSE; 3402bd2a564bSStefano Zampini if (nmin || !sub_schurs->is_posdef) { /* XXX */ 3403f6f667cfSStefano Zampini allocated_S_St = PETSC_TRUE; 3404f6f667cfSStefano Zampini } 340508122e43SStefano Zampini 340608122e43SStefano Zampini /* allocate lapack workspace */ 340708122e43SStefano Zampini cum = cum2 = 0; 340808122e43SStefano Zampini maxneigs = 0; 340908122e43SStefano Zampini for (i = 0; i < sub_schurs->n_subs; i++) { 341008122e43SStefano Zampini PetscInt n, subset_size; 3411f6f667cfSStefano Zampini 34129566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->is_subs[i], &subset_size)); 341308122e43SStefano Zampini n = PetscMin(subset_size, nmax); 34149162d606SStefano Zampini cum += subset_size; 34159162d606SStefano Zampini cum2 += subset_size * n; 341608122e43SStefano Zampini maxneigs = PetscMax(maxneigs, n); 341708122e43SStefano Zampini } 34187ebab0bbSStefano Zampini lwork = 0; 341908122e43SStefano Zampini if (mss) { 34207ebab0bbSStefano Zampini PetscScalar sdummy = 0.; 342108122e43SStefano Zampini PetscBLASInt B_itype = 1; 34226497c311SBarry Smith PetscBLASInt B_N, idummy = 0; 34237ebab0bbSStefano Zampini PetscReal rdummy = 0., zero = 0.0; 34244c6709b3SStefano Zampini PetscReal eps = 0.0; /* dlamch? */ 342508122e43SStefano Zampini 34260fdf79fbSJacob Faibussowitsch PetscCheck(sub_schurs->is_symmetric, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not yet implemented"); 34276497c311SBarry Smith PetscCall(PetscBLASIntCast(mss, &B_N)); 342808122e43SStefano Zampini B_lwork = -1; 34297ebab0bbSStefano Zampini /* some implementations may complain about NULL pointers, even if we are querying */ 34307ebab0bbSStefano Zampini S = &sdummy; 34317ebab0bbSStefano Zampini St = &sdummy; 34327ebab0bbSStefano Zampini eigs = &rdummy; 34337ebab0bbSStefano Zampini eigv = &sdummy; 34347ebab0bbSStefano Zampini B_iwork = &idummy; 34357ebab0bbSStefano Zampini B_ifail = &idummy; 3436d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX) 34377ebab0bbSStefano Zampini rwork = &rdummy; 3438d1710679SStefano Zampini #endif 34398bec7fa6SStefano Zampini thresh = 1.0; 34409566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 344108122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 344297b17b2cSPierre 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)); 344308122e43SStefano Zampini #else 344497b17b2cSPierre 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)); 344508122e43SStefano Zampini #endif 3446835f2295SStefano Zampini PetscCheck(B_ierr == 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in query to SYGVX Lapack routine %" PetscBLASInt_FMT, B_ierr); 34479566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 344808122e43SStefano Zampini } 344908122e43SStefano Zampini 345008122e43SStefano Zampini nv = 0; 3451d62866d3SStefano 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) */ 34529566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->is_vertices, &nv)); 345308122e43SStefano Zampini } 34549566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(lwork), &B_lwork)); 345548a46eb9SPierre Jolivet if (allocated_S_St) PetscCall(PetscMalloc2(mss * mss, &S, mss * mss, &St)); 34569566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(mss * mss, &eigv, mss, &eigs, B_lwork, &work, 5 * mss, &B_iwork, mss, &B_ifail)); 345708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 34589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(7 * mss, &rwork)); 345908122e43SStefano Zampini #endif 34609371c9d4SSatish 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, 34619371c9d4SSatish Balay &pcbddc->adaptive_constraints_data)); 34629566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(pcbddc->adaptive_constraints_n, nv + sub_schurs->n_subs)); 346308122e43SStefano Zampini 346408122e43SStefano Zampini maxneigs = 0; 346572b8c272SStefano Zampini cum = cumarray = 0; 34669162d606SStefano Zampini pcbddc->adaptive_constraints_idxs_ptr[0] = 0; 34679162d606SStefano Zampini pcbddc->adaptive_constraints_data_ptr[0] = 0; 3468d62866d3SStefano Zampini if (sub_schurs->is_vertices && pcbddc->use_vertices) { 346908122e43SStefano Zampini const PetscInt *idxs; 347008122e43SStefano Zampini 34719566063dSJacob Faibussowitsch PetscCall(ISGetIndices(sub_schurs->is_vertices, &idxs)); 347208122e43SStefano Zampini for (cum = 0; cum < nv; cum++) { 347308122e43SStefano Zampini pcbddc->adaptive_constraints_n[cum] = 1; 347408122e43SStefano Zampini pcbddc->adaptive_constraints_idxs[cum] = idxs[cum]; 347508122e43SStefano Zampini pcbddc->adaptive_constraints_data[cum] = 1.0; 34769162d606SStefano Zampini pcbddc->adaptive_constraints_idxs_ptr[cum + 1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + 1; 34779162d606SStefano Zampini pcbddc->adaptive_constraints_data_ptr[cum + 1] = pcbddc->adaptive_constraints_data_ptr[cum] + 1; 347808122e43SStefano Zampini } 34799566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(sub_schurs->is_vertices, &idxs)); 348008122e43SStefano Zampini } 348108122e43SStefano Zampini 348208122e43SStefano Zampini if (mss) { /* multilevel */ 348332fe681dSStefano Zampini if (sub_schurs->gdsw) { 348432fe681dSStefano Zampini PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_all, &Sarray)); 348532fe681dSStefano Zampini PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all, &Starray)); 348632fe681dSStefano Zampini } else { 34879566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all, &Sarray)); 34889566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all, &Starray)); 348908122e43SStefano Zampini } 349032fe681dSStefano Zampini } 349108122e43SStefano Zampini 3492bd2a564bSStefano Zampini lthresh = pcbddc->adaptive_threshold[0]; 3493bd2a564bSStefano Zampini uthresh = pcbddc->adaptive_threshold[1]; 349432fe681dSStefano Zampini upart = pcbddc->use_deluxe_scaling; 349508122e43SStefano Zampini for (i = 0; i < sub_schurs->n_subs; i++) { 349608122e43SStefano Zampini const PetscInt *idxs; 34979d54b7f4SStefano Zampini PetscReal upper, lower; 3498862806e4SStefano Zampini PetscInt j, subset_size, eigs_start = 0; 349908122e43SStefano Zampini PetscBLASInt B_N; 3500aff50787SStefano Zampini PetscBool same_data = PETSC_FALSE; 3501bd2a564bSStefano Zampini PetscBool scal = PETSC_FALSE; 350208122e43SStefano Zampini 350332fe681dSStefano Zampini if (upart) { 35049d54b7f4SStefano Zampini upper = PETSC_MAX_REAL; 3505bd2a564bSStefano Zampini lower = uthresh; 35069d54b7f4SStefano Zampini } else { 350732fe681dSStefano Zampini if (sub_schurs->gdsw) { 350832fe681dSStefano Zampini upper = uthresh; 350932fe681dSStefano Zampini lower = PETSC_MIN_REAL; 351032fe681dSStefano Zampini } else { 351128b400f6SJacob Faibussowitsch PetscCheck(sub_schurs->is_posdef, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not yet implemented without deluxe scaling"); 3512bd2a564bSStefano Zampini upper = 1. / uthresh; 35139d54b7f4SStefano Zampini lower = 0.; 35149d54b7f4SStefano Zampini } 351532fe681dSStefano Zampini } 35169566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->is_subs[i], &subset_size)); 35179566063dSJacob Faibussowitsch PetscCall(ISGetIndices(sub_schurs->is_subs[i], &idxs)); 35189566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(subset_size, &B_N)); 3519bd2a564bSStefano Zampini /* this is experimental: we assume the dofs have been properly grouped to have 3520bd2a564bSStefano Zampini the diagonal blocks Schur complements either positive or negative definite (true for Stokes) */ 3521bd2a564bSStefano Zampini if (!sub_schurs->is_posdef) { 3522bd2a564bSStefano Zampini Mat T; 3523bd2a564bSStefano Zampini 3524bd2a564bSStefano Zampini for (j = 0; j < subset_size; j++) { 3525bd2a564bSStefano Zampini if (PetscRealPart(*(Sarray + cumarray + j * (subset_size + 1))) < 0.0) { 35269566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, subset_size, subset_size, Sarray + cumarray, &T)); 35279566063dSJacob Faibussowitsch PetscCall(MatScale(T, -1.0)); 35289566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 35299566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, subset_size, subset_size, Starray + cumarray, &T)); 35309566063dSJacob Faibussowitsch PetscCall(MatScale(T, -1.0)); 35319566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 3532bd2a564bSStefano Zampini if (sub_schurs->change_primal_sub) { 3533bd2a564bSStefano Zampini PetscInt nz, k; 3534bd2a564bSStefano Zampini const PetscInt *idxs; 3535bd2a564bSStefano Zampini 35369566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->change_primal_sub[i], &nz)); 35379566063dSJacob Faibussowitsch PetscCall(ISGetIndices(sub_schurs->change_primal_sub[i], &idxs)); 3538bd2a564bSStefano Zampini for (k = 0; k < nz; k++) { 3539bd2a564bSStefano Zampini *(Sarray + cumarray + idxs[k] * (subset_size + 1)) *= -1.0; 3540bd2a564bSStefano Zampini *(Starray + cumarray + idxs[k] * (subset_size + 1)) = 0.0; 3541bd2a564bSStefano Zampini } 35429566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(sub_schurs->change_primal_sub[i], &idxs)); 3543bd2a564bSStefano Zampini } 3544bd2a564bSStefano Zampini scal = PETSC_TRUE; 3545bd2a564bSStefano Zampini break; 3546bd2a564bSStefano Zampini } 3547bd2a564bSStefano Zampini } 3548bd2a564bSStefano Zampini } 3549bd2a564bSStefano Zampini 3550f6f667cfSStefano Zampini if (allocated_S_St) { /* S and S_t should be copied since we could need them later */ 3551bd2a564bSStefano Zampini if (sub_schurs->is_symmetric) { 3552aff50787SStefano Zampini PetscInt j, k; 3553580bdb30SBarry Smith if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscArraycmp() later */ 35549566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(S, subset_size * subset_size)); 35559566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(St, subset_size * subset_size)); 355608122e43SStefano Zampini } 355708122e43SStefano Zampini for (j = 0; j < subset_size; j++) { 3558aff50787SStefano Zampini for (k = j; k < subset_size; k++) { 3559aff50787SStefano Zampini S[j * subset_size + k] = Sarray[cumarray + j * subset_size + k]; 3560aff50787SStefano Zampini St[j * subset_size + k] = Starray[cumarray + j * subset_size + k]; 3561aff50787SStefano Zampini } 356208122e43SStefano Zampini } 356308122e43SStefano Zampini } else { 35649566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 35659566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 356608122e43SStefano Zampini } 35678bec7fa6SStefano Zampini } else { 3568f6f667cfSStefano Zampini S = Sarray + cumarray; 3569f6f667cfSStefano Zampini St = Starray + cumarray; 35708bec7fa6SStefano Zampini } 3571aff50787SStefano Zampini /* see if we can save some work */ 357248a46eb9SPierre Jolivet if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) PetscCall(PetscArraycmp(S, St, subset_size * subset_size, &same_data)); 3573aff50787SStefano Zampini 3574b7ab4a40SStefano Zampini if (same_data && !sub_schurs->change) { /* there's no need of constraints here */ 3575aff50787SStefano Zampini B_neigs = 0; 3576aff50787SStefano Zampini } else { 357797b17b2cSPierre Jolivet PetscBLASInt B_itype = 1, B_IL = 1, B_IU = 0; 35784c6709b3SStefano Zampini PetscReal eps = -1.0; /* dlamch? */ 35799552c7c7SStefano Zampini PetscInt nmin_s; 3580bd2a564bSStefano Zampini PetscBool compute_range; 3581bd2a564bSStefano Zampini 35820fdf79fbSJacob Faibussowitsch PetscCheck(sub_schurs->is_symmetric, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not yet implemented"); 35839036ceccSStefano Zampini B_neigs = 0; 3584bd2a564bSStefano Zampini compute_range = (PetscBool)!same_data; 3585bd2a564bSStefano Zampini if (nmin >= subset_size) compute_range = PETSC_FALSE; 358608122e43SStefano Zampini 3587fd14bc51SStefano Zampini if (pcbddc->dbg_flag) { 3588a4cdd7efSStefano Zampini PetscInt nc = 0, c = pcbddc->mat_graph->nodes[idxs[0]].count, w = pcbddc->mat_graph->nodes[idxs[0]].which_dof; 3589d16cbb6bSStefano Zampini 359048a46eb9SPierre Jolivet if (sub_schurs->change_primal_sub) PetscCall(ISGetLocalSize(sub_schurs->change_primal_sub[i], &nc)); 35919de2952eSStefano Zampini PetscCall( 35929de2952eSStefano 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)); 3593b7ab4a40SStefano Zampini } 3594b7ab4a40SStefano Zampini 35959566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 3596b7ab4a40SStefano Zampini if (compute_range) { 3597d16cbb6bSStefano Zampini /* ask for eigenvalues larger than thresh */ 3598bd2a564bSStefano Zampini if (sub_schurs->is_posdef) { 359908122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 3600792fecdfSBarry 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)); 360108122e43SStefano Zampini #else 3602792fecdfSBarry 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)); 360308122e43SStefano Zampini #endif 36049566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 3605bd2a564bSStefano Zampini } else { /* no theory so far, but it works nicely */ 36069036ceccSStefano Zampini PetscInt recipe = 0, recipe_m = 1; 3607bd2a564bSStefano Zampini PetscReal bb[2]; 3608bd2a564bSStefano Zampini 36099566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)pc)->prefix, "-pc_bddc_adaptive_recipe", &recipe, NULL)); 3610bd2a564bSStefano Zampini switch (recipe) { 3611bd2a564bSStefano Zampini case 0: 36129371c9d4SSatish Balay if (scal) { 36139371c9d4SSatish Balay bb[0] = PETSC_MIN_REAL; 36149371c9d4SSatish Balay bb[1] = lthresh; 36159371c9d4SSatish Balay } else { 36169371c9d4SSatish Balay bb[0] = uthresh; 36179371c9d4SSatish Balay bb[1] = PETSC_MAX_REAL; 36189371c9d4SSatish Balay } 3619bd2a564bSStefano 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_neigs, eigs, eigv, &B_N, work, &B_lwork, rwork, B_iwork, B_ifail, &B_ierr)); 3621bd2a564bSStefano 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_neigs, eigs, eigv, &B_N, work, &B_lwork, B_iwork, B_ifail, &B_ierr)); 3623bd2a564bSStefano Zampini #endif 36249566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 3625bd2a564bSStefano Zampini break; 3626d71ae5a4SJacob Faibussowitsch case 1: 3627d71ae5a4SJacob Faibussowitsch bb[0] = PETSC_MIN_REAL; 3628d71ae5a4SJacob Faibussowitsch bb[1] = lthresh * lthresh; 3629bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3630792fecdfSBarry 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)); 3631bd2a564bSStefano Zampini #else 3632792fecdfSBarry 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)); 3633bd2a564bSStefano Zampini #endif 36349566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 3635bd2a564bSStefano Zampini if (!scal) { 36369036ceccSStefano Zampini PetscBLASInt B_neigs2 = 0; 3637bd2a564bSStefano Zampini 36389371c9d4SSatish Balay bb[0] = PetscMax(lthresh * lthresh, uthresh); 36399371c9d4SSatish Balay bb[1] = PETSC_MAX_REAL; 36409566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 36419566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 3642bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3643792fecdfSBarry 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)); 3644bd2a564bSStefano Zampini #else 3645792fecdfSBarry 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)); 3646bd2a564bSStefano Zampini #endif 36479566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 3648bd2a564bSStefano Zampini B_neigs += B_neigs2; 3649bd2a564bSStefano Zampini } 3650bd2a564bSStefano Zampini break; 36519036ceccSStefano Zampini case 2: 36529036ceccSStefano Zampini if (scal) { 36539036ceccSStefano Zampini bb[0] = PETSC_MIN_REAL; 36549036ceccSStefano Zampini bb[1] = 0; 36559036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3656792fecdfSBarry 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)); 36579036ceccSStefano Zampini #else 3658792fecdfSBarry 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)); 36599036ceccSStefano Zampini #endif 36609566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 36619036ceccSStefano Zampini } else { 36629036ceccSStefano Zampini PetscBLASInt B_neigs2 = 0; 366313bcc0bdSJacob Faibussowitsch PetscBool do_copy = PETSC_FALSE; 36649036ceccSStefano Zampini 36659036ceccSStefano Zampini lthresh = PetscMax(lthresh, 0.0); 36669036ceccSStefano Zampini if (lthresh > 0.0) { 36679036ceccSStefano Zampini bb[0] = PETSC_MIN_REAL; 36689036ceccSStefano Zampini bb[1] = lthresh * lthresh; 36699036ceccSStefano Zampini 367013bcc0bdSJacob Faibussowitsch do_copy = PETSC_TRUE; 36719036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3672792fecdfSBarry 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)); 36739036ceccSStefano Zampini #else 3674792fecdfSBarry 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)); 36759036ceccSStefano Zampini #endif 36769566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 36779036ceccSStefano Zampini } 36789036ceccSStefano Zampini bb[0] = PetscMax(lthresh * lthresh, uthresh); 36799036ceccSStefano Zampini bb[1] = PETSC_MAX_REAL; 368013bcc0bdSJacob Faibussowitsch if (do_copy) { 36819566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 36829566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 36839036ceccSStefano Zampini } 36849036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3685792fecdfSBarry 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)); 36869036ceccSStefano Zampini #else 3687792fecdfSBarry 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)); 36889036ceccSStefano Zampini #endif 36899566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 36909036ceccSStefano Zampini B_neigs += B_neigs2; 36919036ceccSStefano Zampini } 36929036ceccSStefano Zampini break; 36939036ceccSStefano Zampini case 3: 36949036ceccSStefano Zampini if (scal) { 36959566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)pc)->prefix, "-pc_bddc_adaptive_recipe3_min_scal", &recipe_m, NULL)); 36969036ceccSStefano Zampini } else { 36979566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)pc)->prefix, "-pc_bddc_adaptive_recipe3_min", &recipe_m, NULL)); 36989036ceccSStefano Zampini } 36999036ceccSStefano Zampini if (!scal) { 37009036ceccSStefano Zampini bb[0] = uthresh; 37019036ceccSStefano Zampini bb[1] = PETSC_MAX_REAL; 37029036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3703792fecdfSBarry 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)); 37049036ceccSStefano Zampini #else 3705792fecdfSBarry 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)); 37069036ceccSStefano Zampini #endif 37079566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 37089036ceccSStefano Zampini } 37099036ceccSStefano Zampini if (recipe_m > 0 && B_N - B_neigs > 0) { 37109036ceccSStefano Zampini PetscBLASInt B_neigs2 = 0; 37119036ceccSStefano Zampini 37129566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(PetscMin(recipe_m, B_N - B_neigs), &B_IU)); 37139566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 37149566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 37159036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3716792fecdfSBarry 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)); 37179036ceccSStefano Zampini #else 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 * B_N, &B_N, work, &B_lwork, B_iwork, B_ifail, &B_ierr)); 37199036ceccSStefano Zampini #endif 37209566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 37219036ceccSStefano Zampini B_neigs += B_neigs2; 37229036ceccSStefano Zampini } 37239036ceccSStefano Zampini break; 3724d71ae5a4SJacob Faibussowitsch case 4: 3725d71ae5a4SJacob Faibussowitsch bb[0] = PETSC_MIN_REAL; 3726d71ae5a4SJacob Faibussowitsch bb[1] = lthresh; 372748cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX) 3728792fecdfSBarry 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)); 372948cebe81SStefano Zampini #else 3730792fecdfSBarry 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)); 373148cebe81SStefano Zampini #endif 37329566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 373348cebe81SStefano Zampini { 373448cebe81SStefano Zampini PetscBLASInt B_neigs2 = 0; 373548cebe81SStefano Zampini 37369371c9d4SSatish Balay bb[0] = PetscMax(lthresh + PETSC_SMALL, uthresh); 37379371c9d4SSatish Balay bb[1] = PETSC_MAX_REAL; 37389566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 37399566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 374048cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX) 3741792fecdfSBarry 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)); 374248cebe81SStefano Zampini #else 3743792fecdfSBarry 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)); 374448cebe81SStefano Zampini #endif 37459566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 374648cebe81SStefano Zampini B_neigs += B_neigs2; 374748cebe81SStefano Zampini } 374848cebe81SStefano Zampini break; 374980db8efeSStefano Zampini case 5: /* same as before: first compute all eigenvalues, then filter */ 375080db8efeSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3751792fecdfSBarry 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)); 375280db8efeSStefano Zampini #else 3753792fecdfSBarry 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)); 375480db8efeSStefano Zampini #endif 37559566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 375680db8efeSStefano Zampini { 375780db8efeSStefano Zampini PetscInt e, k, ne; 375880db8efeSStefano Zampini for (e = 0, ne = 0; e < B_neigs; e++) { 375980db8efeSStefano Zampini if (eigs[e] < lthresh || eigs[e] > uthresh) { 376080db8efeSStefano Zampini for (k = 0; k < B_N; k++) S[ne * B_N + k] = eigv[e * B_N + k]; 376180db8efeSStefano Zampini eigs[ne] = eigs[e]; 376280db8efeSStefano Zampini ne++; 376380db8efeSStefano Zampini } 376480db8efeSStefano Zampini } 37659566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(eigv, S, B_N * ne)); 37666497c311SBarry Smith PetscCall(PetscBLASIntCast(ne, &B_neigs)); 376780db8efeSStefano Zampini } 376880db8efeSStefano Zampini break; 3769d71ae5a4SJacob Faibussowitsch default: 3770d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Unknown recipe %" PetscInt_FMT, recipe); 3771bd2a564bSStefano Zampini } 3772bd2a564bSStefano Zampini } 3773bd2a564bSStefano Zampini } else if (!same_data) { /* this is just to see all the eigenvalues */ 37746497c311SBarry Smith PetscCall(PetscBLASIntCast(PetscMax(1, PetscMin(B_N, nmax)), &B_IU)); 3775d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3776792fecdfSBarry 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)); 3777d16cbb6bSStefano Zampini #else 3778792fecdfSBarry 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)); 3779d16cbb6bSStefano Zampini #endif 37809566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 3781b03ebc13SStefano Zampini } else { /* same_data is true, so just get the adaptive functional requested by the user */ 3782b7ab4a40SStefano Zampini PetscInt k; 378328b400f6SJacob Faibussowitsch PetscCheck(sub_schurs->change_primal_sub, PETSC_COMM_SELF, PETSC_ERR_PLIB, "This should not happen"); 37849566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->change_primal_sub[i], &nmax)); 37859566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(nmax, &B_neigs)); 3786b7ab4a40SStefano Zampini nmin = nmax; 37879566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(eigv, subset_size * nmax)); 3788b7ab4a40SStefano Zampini for (k = 0; k < nmax; k++) { 3789b7ab4a40SStefano Zampini eigs[k] = 1. / PETSC_SMALL; 3790b7ab4a40SStefano Zampini eigv[k * (subset_size + 1)] = 1.0; 3791b7ab4a40SStefano Zampini } 3792d16cbb6bSStefano Zampini } 37939566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 379408122e43SStefano Zampini if (B_ierr) { 379563a3b9bcSJacob Faibussowitsch PetscCheck(B_ierr >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in SYGVX Lapack routine: illegal value for argument %" PetscBLASInt_FMT, -B_ierr); 379663a3b9bcSJacob 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); 379763a3b9bcSJacob 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); 379808122e43SStefano Zampini } 379908122e43SStefano Zampini 380008122e43SStefano Zampini if (B_neigs > nmax) { 380148a46eb9SPierre Jolivet if (pcbddc->dbg_flag) PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " found %" PetscBLASInt_FMT " eigs, more than maximum required %" PetscInt_FMT ".\n", B_neigs, nmax)); 380232fe681dSStefano Zampini if (upart) eigs_start = scal ? 0 : B_neigs - nmax; 38036497c311SBarry Smith PetscCall(PetscBLASIntCast(nmax, &B_neigs)); 380408122e43SStefano Zampini } 380508122e43SStefano Zampini 38069552c7c7SStefano Zampini nmin_s = PetscMin(nmin, B_N); 38079552c7c7SStefano Zampini if (B_neigs < nmin_s) { 38089036ceccSStefano Zampini PetscBLASInt B_neigs2 = 0; 380908122e43SStefano Zampini 381032fe681dSStefano Zampini if (upart) { 3811bd2a564bSStefano Zampini if (scal) { 38126497c311SBarry Smith PetscCall(PetscBLASIntCast(nmin_s, &B_IU)); 3813bd2a564bSStefano Zampini B_IL = B_neigs + 1; 3814bd2a564bSStefano Zampini } else { 38156497c311SBarry Smith PetscCall(PetscBLASIntCast(B_N - nmin_s + 1, &B_IL)); 38169d54b7f4SStefano Zampini B_IU = B_N - B_neigs; 3817bd2a564bSStefano Zampini } 38189d54b7f4SStefano Zampini } else { 38199d54b7f4SStefano Zampini B_IL = B_neigs + 1; 38206497c311SBarry Smith PetscCall(PetscBLASIntCast(nmin_s, &B_IU)); 38219d54b7f4SStefano Zampini } 3822fd14bc51SStefano Zampini if (pcbddc->dbg_flag) { 382363a3b9bcSJacob 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)); 3824fd14bc51SStefano Zampini } 3825bd2a564bSStefano Zampini if (sub_schurs->is_symmetric) { 38261ae86dd6SStefano Zampini PetscInt j, k; 382708122e43SStefano Zampini for (j = 0; j < subset_size; j++) { 38281ae86dd6SStefano Zampini for (k = j; k < subset_size; k++) { 38291ae86dd6SStefano Zampini S[j * subset_size + k] = Sarray[cumarray + j * subset_size + k]; 38301ae86dd6SStefano Zampini St[j * subset_size + k] = Starray[cumarray + j * subset_size + k]; 383108122e43SStefano Zampini } 383208122e43SStefano Zampini } 383308122e43SStefano Zampini } else { 38349566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 38359566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 383608122e43SStefano Zampini } 38379566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 383808122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 3839792fecdfSBarry 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)); 384008122e43SStefano Zampini #else 3841792fecdfSBarry 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)); 384208122e43SStefano Zampini #endif 38439566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 38449566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 384508122e43SStefano Zampini B_neigs += B_neigs2; 384608122e43SStefano Zampini } 384708122e43SStefano Zampini if (B_ierr) { 384863a3b9bcSJacob Faibussowitsch PetscCheck(B_ierr >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in SYGVX Lapack routine: illegal value for argument %" PetscBLASInt_FMT, -B_ierr); 384963a3b9bcSJacob 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); 385063a3b9bcSJacob 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); 385108122e43SStefano Zampini } 3852fd14bc51SStefano Zampini if (pcbddc->dbg_flag) { 385363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " -> Got %" PetscBLASInt_FMT " eigs\n", B_neigs)); 385408122e43SStefano Zampini for (j = 0; j < B_neigs; j++) { 385532fe681dSStefano Zampini if (!sub_schurs->gdsw) { 385608122e43SStefano Zampini if (eigs[j] == 0.0) { 38579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " Inf\n")); 385808122e43SStefano Zampini } else { 385932fe681dSStefano Zampini if (upart) { 386063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.6e\n", (double)eigs[j + eigs_start])); 38619d54b7f4SStefano Zampini } else { 3862835f2295SStefano Zampini PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.6e\n", (double)(1 / eigs[j + eigs_start]))); 38639d54b7f4SStefano Zampini } 3864fd14bc51SStefano Zampini } 386532fe681dSStefano Zampini } else { 386632fe681dSStefano Zampini double pg = (double)eigs[j + eigs_start]; 386732fe681dSStefano Zampini if (pg < 2 * PETSC_SMALL) pg = 0.0; 386832fe681dSStefano Zampini PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.6e\n", pg)); 386932fe681dSStefano Zampini } 387008122e43SStefano Zampini } 387108122e43SStefano Zampini } 3872aff50787SStefano Zampini } 38736c3e6151SStefano Zampini /* change the basis back to the original one */ 38746c3e6151SStefano Zampini if (sub_schurs->change) { 387572b8c272SStefano Zampini Mat change, phi, phit; 38766c3e6151SStefano Zampini 387703dfb2d7SStefano Zampini if (pcbddc->dbg_flag > 2) { 38786c3e6151SStefano Zampini PetscInt ii; 38796c3e6151SStefano Zampini for (ii = 0; ii < B_neigs; ii++) { 388063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " -> Eigenvector (old basis) %" PetscInt_FMT "/%" PetscBLASInt_FMT " (%" PetscBLASInt_FMT ")\n", ii, B_neigs, B_N)); 38816c3e6151SStefano Zampini for (j = 0; j < B_N; j++) { 3882684229deSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3883684229deSStefano Zampini PetscReal r = PetscRealPart(eigv[(ii + eigs_start) * subset_size + j]); 3884684229deSStefano Zampini PetscReal c = PetscImaginaryPart(eigv[(ii + eigs_start) * subset_size + j]); 388563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.4e + %1.4e i\n", (double)r, (double)c)); 3886684229deSStefano Zampini #else 388763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.4e\n", (double)(eigv[(ii + eigs_start) * subset_size + j]))); 3888684229deSStefano Zampini #endif 38896c3e6151SStefano Zampini } 38906c3e6151SStefano Zampini } 38916c3e6151SStefano Zampini } 38929566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(sub_schurs->change[i], &change, NULL)); 38939566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, subset_size, B_neigs, eigv + eigs_start * subset_size, &phit)); 3894fb842aefSJose E. Roman PetscCall(MatMatMult(change, phit, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &phi)); 38959566063dSJacob Faibussowitsch PetscCall(MatCopy(phi, phit, SAME_NONZERO_PATTERN)); 38969566063dSJacob Faibussowitsch PetscCall(MatDestroy(&phit)); 38979566063dSJacob Faibussowitsch PetscCall(MatDestroy(&phi)); 38986c3e6151SStefano Zampini } 38998bec7fa6SStefano Zampini maxneigs = PetscMax(B_neigs, maxneigs); 39008bec7fa6SStefano Zampini pcbddc->adaptive_constraints_n[i + nv] = B_neigs; 39019162d606SStefano Zampini if (B_neigs) { 39029566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pcbddc->adaptive_constraints_data + pcbddc->adaptive_constraints_data_ptr[cum], eigv + eigs_start * subset_size, B_neigs * subset_size)); 3903fd14bc51SStefano Zampini 3904fd14bc51SStefano Zampini if (pcbddc->dbg_flag > 1) { 39059552c7c7SStefano Zampini PetscInt ii; 39069552c7c7SStefano Zampini for (ii = 0; ii < B_neigs; ii++) { 390763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " -> Eigenvector %" PetscInt_FMT "/%" PetscBLASInt_FMT " (%" PetscBLASInt_FMT ")\n", ii, B_neigs, B_N)); 39089552c7c7SStefano Zampini for (j = 0; j < B_N; j++) { 3909ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3910ac47001eSStefano Zampini PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii * subset_size + j + pcbddc->adaptive_constraints_data_ptr[cum]]); 3911ac47001eSStefano Zampini PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii * subset_size + j + pcbddc->adaptive_constraints_data_ptr[cum]]); 391263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.4e + %1.4e i\n", (double)r, (double)c)); 3913ac47001eSStefano Zampini #else 391463a3b9bcSJacob 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]]))); 3915ac47001eSStefano Zampini #endif 39169552c7c7SStefano Zampini } 39179552c7c7SStefano Zampini } 3918fd14bc51SStefano Zampini } 39199566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pcbddc->adaptive_constraints_idxs + pcbddc->adaptive_constraints_idxs_ptr[cum], idxs, subset_size)); 39209162d606SStefano Zampini pcbddc->adaptive_constraints_idxs_ptr[cum + 1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size; 39219162d606SStefano Zampini pcbddc->adaptive_constraints_data_ptr[cum + 1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size * B_neigs; 39229162d606SStefano Zampini cum++; 392308122e43SStefano Zampini } 39249566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(sub_schurs->is_subs[i], &idxs)); 392508122e43SStefano Zampini /* shift for next computation */ 392608122e43SStefano Zampini cumarray += subset_size * subset_size; 392708122e43SStefano Zampini } 39281baa6e33SBarry Smith if (pcbddc->dbg_flag) PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 392908122e43SStefano Zampini 393008122e43SStefano Zampini if (mss) { 393132fe681dSStefano Zampini if (sub_schurs->gdsw) { 393232fe681dSStefano Zampini PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_all, &Sarray)); 393332fe681dSStefano Zampini PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all, &Starray)); 393432fe681dSStefano Zampini } else { 39359566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all, &Sarray)); 39369566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all, &Starray)); 3937f6f667cfSStefano Zampini /* destroy matrices (junk) */ 39389566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sub_schurs->sum_S_Ej_inv_all)); 39399566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sub_schurs->sum_S_Ej_tilda_all)); 394008122e43SStefano Zampini } 394132fe681dSStefano Zampini } 39421baa6e33SBarry Smith if (allocated_S_St) PetscCall(PetscFree2(S, St)); 39439566063dSJacob Faibussowitsch PetscCall(PetscFree5(eigv, eigs, work, B_iwork, B_ifail)); 394408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 39459566063dSJacob Faibussowitsch PetscCall(PetscFree(rwork)); 394608122e43SStefano Zampini #endif 394708122e43SStefano Zampini if (pcbddc->dbg_flag) { 39481b968477SStefano Zampini PetscInt maxneigs_r; 3949462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&maxneigs, &maxneigs_r, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)pc))); 395063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Maximum number of constraints per cc %" PetscInt_FMT "\n", maxneigs_r)); 395108122e43SStefano Zampini } 39529566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_AdaptiveSetUp[pcbddc->current_level], pc, 0, 0, 0)); 39533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 395408122e43SStefano Zampini } 3955b1b3d7a2SStefano Zampini 3956d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpSolvers(PC pc) 3957d71ae5a4SJacob Faibussowitsch { 39589de2952eSStefano Zampini Mat coarse_submat; 3959c8587f34SStefano Zampini 3960c8587f34SStefano Zampini PetscFunctionBegin; 3961f4ddd8eeSStefano Zampini /* Setup local scatters R_to_B and (optionally) R_to_D */ 39625e8657edSStefano Zampini /* PCBDDCSetUpLocalWorkVectors should be called first! */ 39639566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpLocalScatters(pc)); 3964c8587f34SStefano Zampini 3965684f6988SStefano Zampini /* Setup local neumann solver ksp_R */ 39660fccc4e9SStefano Zampini /* PCBDDCSetUpLocalScatters should be called first! */ 39679566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpLocalSolvers(pc, PETSC_FALSE, PETSC_TRUE)); 3968c8587f34SStefano Zampini 39698629588bSStefano Zampini /* 39708629588bSStefano Zampini Setup local correction and local part of coarse basis. 39718629588bSStefano Zampini Gives back the dense local part of the coarse matrix in column major ordering 39728629588bSStefano Zampini */ 39739de2952eSStefano Zampini PetscCall(PCBDDCSetUpCorrection(pc, &coarse_submat)); 39748629588bSStefano Zampini 39758629588bSStefano Zampini /* Compute total number of coarse nodes and setup coarse solver */ 39769de2952eSStefano Zampini PetscCall(PCBDDCSetUpCoarseSolver(pc, coarse_submat)); 39779de2952eSStefano Zampini PetscCall(MatDestroy(&coarse_submat)); 39783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3979c8587f34SStefano Zampini } 3980c8587f34SStefano Zampini 3981d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCResetCustomization(PC pc) 3982d71ae5a4SJacob Faibussowitsch { 3983674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 3984674ae819SStefano Zampini 3985674ae819SStefano Zampini PetscFunctionBegin; 39869566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices)); 39879566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local)); 39889566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundaries)); 39899566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal)); 39909566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundaries)); 39919566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&pcbddc->onearnullspace)); 39929566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->onearnullvecs_state)); 39939566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal)); 39949566063dSJacob Faibussowitsch PetscCall(PCBDDCSetDofsSplitting(pc, 0, NULL)); 39959566063dSJacob Faibussowitsch PetscCall(PCBDDCSetDofsSplittingLocal(pc, 0, NULL)); 39963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3997674ae819SStefano Zampini } 3998674ae819SStefano Zampini 3999d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCResetTopography(PC pc) 4000d71ae5a4SJacob Faibussowitsch { 4001674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 40024f1b2e48SStefano Zampini PetscInt i; 4003674ae819SStefano Zampini 4004674ae819SStefano Zampini PetscFunctionBegin; 40059566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->nedcG)); 40069566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->nedclocal)); 40079566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->discretegradient)); 40089566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->user_ChangeOfBasisMatrix)); 40099566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->ChangeOfBasisMatrix)); 40109566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->switch_static_change)); 40119566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->work_change)); 40129566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->ConstraintMatrix)); 40139566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->divudotp)); 40149566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->divudotp_vl2l)); 40159566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphDestroy(&pcbddc->mat_graph)); 401648a46eb9SPierre Jolivet for (i = 0; i < pcbddc->n_local_subs; i++) PetscCall(ISDestroy(&pcbddc->local_subs[i])); 4017e68a0315Sstefano_zampini pcbddc->n_local_subs = 0; 40189566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->local_subs)); 40199566063dSJacob Faibussowitsch PetscCall(PCBDDCSubSchursDestroy(&pcbddc->sub_schurs)); 4020c703fcc7SStefano Zampini pcbddc->graphanalyzed = PETSC_FALSE; 40218af8fcf9SStefano Zampini pcbddc->recompute_topography = PETSC_TRUE; 40221c7a958bSStefano Zampini pcbddc->corner_selected = PETSC_FALSE; 40233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4024674ae819SStefano Zampini } 4025674ae819SStefano Zampini 4026d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCResetSolvers(PC pc) 4027d71ae5a4SJacob Faibussowitsch { 4028674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 4029674ae819SStefano Zampini 4030674ae819SStefano Zampini PetscFunctionBegin; 40319566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->coarse_vec)); 40329566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_phi_B)); 40339566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_phi_D)); 40349566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_psi_B)); 40359566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_psi_D)); 40369566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_P)); 40379566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_C)); 40389566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_auxmat2)); 40399566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_auxmat1)); 40409566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_R)); 40419566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec2_R)); 40429566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->is_R_local)); 40439566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->R_to_B)); 40449566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->R_to_D)); 40459566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->coarse_loc_to_glob)); 40469566063dSJacob Faibussowitsch PetscCall(KSPReset(pcbddc->ksp_D)); 40479566063dSJacob Faibussowitsch PetscCall(KSPReset(pcbddc->ksp_R)); 40489566063dSJacob Faibussowitsch PetscCall(KSPReset(pcbddc->coarse_ksp)); 40499566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 40509566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->primal_indices_local_idxs)); 40519566063dSJacob Faibussowitsch PetscCall(PetscFree2(pcbddc->local_primal_ref_node, pcbddc->local_primal_ref_mult)); 40529566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->global_primal_indices)); 40539566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->coarse_subassembling)); 40549566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->benign_change)); 40559566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->benign_vec)); 40569566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignShellMat(pc, PETSC_TRUE)); 40579566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->benign_B0)); 40589566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pcbddc->benign_sf)); 4059ca92afb2SStefano Zampini if (pcbddc->benign_zerodiag_subs) { 4060ca92afb2SStefano Zampini PetscInt i; 406148a46eb9SPierre Jolivet for (i = 0; i < pcbddc->benign_n; i++) PetscCall(ISDestroy(&pcbddc->benign_zerodiag_subs[i])); 40629566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->benign_zerodiag_subs)); 4063ca92afb2SStefano Zampini } 40649566063dSJacob Faibussowitsch PetscCall(PetscFree3(pcbddc->benign_p0_lidx, pcbddc->benign_p0_gidx, pcbddc->benign_p0)); 40653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4066674ae819SStefano Zampini } 4067674ae819SStefano Zampini 4068d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc) 4069d71ae5a4SJacob Faibussowitsch { 40706bfb1811SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 40716bfb1811SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 40726bfb1811SStefano Zampini VecType impVecType; 40734f1b2e48SStefano Zampini PetscInt n_constraints, n_R, old_size; 40746bfb1811SStefano Zampini 40756bfb1811SStefano Zampini PetscFunctionBegin; 40764f1b2e48SStefano Zampini n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices; 4077b371cd4fSStefano Zampini n_R = pcis->n - pcbddc->n_vertices; 40789566063dSJacob Faibussowitsch PetscCall(VecGetType(pcis->vec1_N, &impVecType)); 4079e7b262bdSStefano Zampini /* local work vectors (try to avoid unneeded work)*/ 4080e7b262bdSStefano Zampini /* R nodes */ 4081e7b262bdSStefano Zampini old_size = -1; 408248a46eb9SPierre Jolivet if (pcbddc->vec1_R) PetscCall(VecGetSize(pcbddc->vec1_R, &old_size)); 4083e7b262bdSStefano Zampini if (n_R != old_size) { 40849566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_R)); 40859566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec2_R)); 40869566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N), &pcbddc->vec1_R)); 40879566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pcbddc->vec1_R, PETSC_DECIDE, n_R)); 40889566063dSJacob Faibussowitsch PetscCall(VecSetType(pcbddc->vec1_R, impVecType)); 40899566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcbddc->vec1_R, &pcbddc->vec2_R)); 4090e7b262bdSStefano Zampini } 4091e7b262bdSStefano Zampini /* local primal dofs */ 4092e7b262bdSStefano Zampini old_size = -1; 409348a46eb9SPierre Jolivet if (pcbddc->vec1_P) PetscCall(VecGetSize(pcbddc->vec1_P, &old_size)); 4094e9189074SStefano Zampini if (pcbddc->local_primal_size != old_size) { 40959566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_P)); 40969566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N), &pcbddc->vec1_P)); 40979566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pcbddc->vec1_P, PETSC_DECIDE, pcbddc->local_primal_size)); 40989566063dSJacob Faibussowitsch PetscCall(VecSetType(pcbddc->vec1_P, impVecType)); 4099e7b262bdSStefano Zampini } 4100e7b262bdSStefano Zampini /* local explicit constraints */ 4101e7b262bdSStefano Zampini old_size = -1; 410248a46eb9SPierre Jolivet if (pcbddc->vec1_C) PetscCall(VecGetSize(pcbddc->vec1_C, &old_size)); 4103e7b262bdSStefano Zampini if (n_constraints && n_constraints != old_size) { 41049566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_C)); 41059566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N), &pcbddc->vec1_C)); 41069566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pcbddc->vec1_C, PETSC_DECIDE, n_constraints)); 41079566063dSJacob Faibussowitsch PetscCall(VecSetType(pcbddc->vec1_C, impVecType)); 410883b7ccabSStefano Zampini } 41093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 41106bfb1811SStefano Zampini } 41116bfb1811SStefano Zampini 41129de2952eSStefano Zampini static PetscErrorCode MatSetValuesSubMat(Mat A, Mat S, PetscInt nr, const PetscInt rows[], PetscInt nc, const PetscInt cols[], InsertMode imode) 4113d71ae5a4SJacob Faibussowitsch { 41149de2952eSStefano Zampini PetscBool flg; 41159de2952eSStefano Zampini const PetscScalar *a; 41169de2952eSStefano Zampini 41179de2952eSStefano Zampini PetscFunctionBegin; 41189de2952eSStefano Zampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)S, MATSEQDENSE, &flg)); 41199de2952eSStefano Zampini if (flg) { 41209de2952eSStefano Zampini PetscCall(MatDenseGetArrayRead(S, &a)); 41219de2952eSStefano Zampini PetscCall(MatSetOption(A, MAT_ROW_ORIENTED, PETSC_FALSE)); 41229de2952eSStefano Zampini PetscCall(MatSetValues(A, nr, rows, nc, cols, a, imode)); 41239de2952eSStefano Zampini PetscCall(MatSetOption(A, MAT_ROW_ORIENTED, PETSC_TRUE)); 41249de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayRead(S, &a)); 41259de2952eSStefano Zampini } else { 41269de2952eSStefano Zampini const PetscInt *ii, *jj; 41279de2952eSStefano Zampini PetscInt n; 41289de2952eSStefano Zampini PetscInt buf[8192], *bufc = NULL; 41299de2952eSStefano Zampini PetscBool freeb = PETSC_FALSE; 41309de2952eSStefano Zampini Mat Sm = S; 41319de2952eSStefano Zampini 41329de2952eSStefano Zampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)S, MATSEQAIJ, &flg)); 41339de2952eSStefano Zampini if (!flg) PetscCall(MatConvert(S, MATSEQAIJ, MAT_INITIAL_MATRIX, &Sm)); 41349de2952eSStefano Zampini else PetscCall(PetscObjectReference((PetscObject)S)); 41359de2952eSStefano Zampini PetscCall(MatSeqAIJGetArrayRead(Sm, &a)); 41369de2952eSStefano Zampini PetscCall(MatGetRowIJ(Sm, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &flg)); 41379de2952eSStefano Zampini PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Cannot get IJ structure"); 41389de2952eSStefano Zampini if (nc <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 41399de2952eSStefano Zampini bufc = buf; 41409de2952eSStefano Zampini } else { 41419de2952eSStefano Zampini PetscCall(PetscMalloc1(nc, &bufc)); 41429de2952eSStefano Zampini freeb = PETSC_TRUE; 41439de2952eSStefano Zampini } 41449de2952eSStefano Zampini 41459de2952eSStefano Zampini for (PetscInt i = 0; i < n; i++) { 41469de2952eSStefano Zampini const PetscInt nci = ii[i + 1] - ii[i]; 41479de2952eSStefano Zampini 41489de2952eSStefano Zampini for (PetscInt j = 0; j < nci; j++) bufc[j] = cols[jj[ii[i] + j]]; 41499de2952eSStefano Zampini PetscCall(MatSetValues(A, 1, rows + i, nci, bufc, a + ii[i], imode)); 41509de2952eSStefano Zampini } 41519de2952eSStefano Zampini PetscCall(MatRestoreRowIJ(Sm, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &flg)); 41529de2952eSStefano Zampini PetscCall(MatSeqAIJRestoreArrayRead(Sm, &a)); 41539de2952eSStefano Zampini PetscCall(MatDestroy(&Sm)); 41549de2952eSStefano Zampini if (freeb) PetscCall(PetscFree(bufc)); 41559de2952eSStefano Zampini } 41569de2952eSStefano Zampini PetscCall(MatAssemblyBegin(A, MAT_FLUSH_ASSEMBLY)); 41579de2952eSStefano Zampini PetscCall(MatAssemblyEnd(A, MAT_FLUSH_ASSEMBLY)); 41589de2952eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 41599de2952eSStefano Zampini } 41609de2952eSStefano Zampini 41619de2952eSStefano Zampini static PetscErrorCode MatCreateSeqAIJFromDenseExpand(Mat D, PetscInt n, const PetscInt j[], Mat *mat) 41629de2952eSStefano Zampini { 41639de2952eSStefano Zampini Mat_SeqAIJ *aij; 41649de2952eSStefano Zampini PetscInt *ii, *jj; 41659de2952eSStefano Zampini PetscScalar *aa; 41669de2952eSStefano Zampini PetscInt nnz = 0, m, nc; 41679de2952eSStefano Zampini const PetscScalar *a; 41689de2952eSStefano Zampini const PetscScalar zero = 0.0; 41699de2952eSStefano Zampini 41709de2952eSStefano Zampini PetscFunctionBegin; 41719de2952eSStefano Zampini PetscCall(MatGetLocalSize(D, &m, &nc)); 41729de2952eSStefano Zampini PetscCall(MatDenseGetArrayRead(D, &a)); 41739de2952eSStefano Zampini PetscCall(PetscMalloc1(m + 1, &ii)); 41749de2952eSStefano Zampini PetscCall(PetscMalloc1(m * nc, &jj)); 41759de2952eSStefano Zampini PetscCall(PetscMalloc1(m * nc, &aa)); 41769de2952eSStefano Zampini ii[0] = 0; 41779de2952eSStefano Zampini for (PetscInt k = 0; k < m; k++) { 41789de2952eSStefano Zampini for (PetscInt s = 0; s < nc; s++) { 41799de2952eSStefano Zampini const PetscInt c = s + k * nc; 41809de2952eSStefano Zampini const PetscScalar v = a[k + s * m]; 41819de2952eSStefano Zampini 41829de2952eSStefano Zampini if (PetscUnlikely(j[c] < 0 || v == zero)) continue; 41839de2952eSStefano Zampini jj[nnz] = j[c]; 41849de2952eSStefano Zampini aa[nnz] = a[k + s * m]; 41859de2952eSStefano Zampini nnz++; 41869de2952eSStefano Zampini } 41879de2952eSStefano Zampini ii[k + 1] = nnz; 41889de2952eSStefano Zampini } 41899de2952eSStefano Zampini 41909de2952eSStefano Zampini PetscCall(MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)D), m, n, ii, jj, aa, mat)); 41919de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayRead(D, &a)); 41929de2952eSStefano Zampini 41939de2952eSStefano Zampini aij = (Mat_SeqAIJ *)(*mat)->data; 41949de2952eSStefano Zampini aij->free_a = PETSC_TRUE; 41959de2952eSStefano Zampini aij->free_ij = PETSC_TRUE; 41969de2952eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 41979de2952eSStefano Zampini } 41989de2952eSStefano Zampini 41999de2952eSStefano Zampini /* adapted from MatInvertVariableBlockDiagonal_SeqAIJ */ 42009de2952eSStefano Zampini static PetscErrorCode MatSeqAIJInvertVariableBlockDiagonalMat(Mat A, PetscInt nblocks, const PetscInt *bsizes, Mat *B) 42019de2952eSStefano Zampini { 42029de2952eSStefano Zampini PetscInt n = A->rmap->n, ncnt = 0, ncnt2 = 0, bsizemax = 0, *v_pivots = NULL; 42039de2952eSStefano Zampini const PetscBool allowzeropivot = PETSC_FALSE; 42049de2952eSStefano Zampini PetscBool zeropivotdetected = PETSC_FALSE; 42059de2952eSStefano Zampini const PetscReal shift = 0.0; 42069de2952eSStefano Zampini PetscInt ipvt[5], *ii, *jj, *indi, *indj; 42079de2952eSStefano Zampini PetscScalar work[25], *v_work = NULL, *aa, *diag; 42089de2952eSStefano Zampini PetscLogDouble flops = 0.0; 42099de2952eSStefano Zampini 42109de2952eSStefano Zampini PetscFunctionBegin; 42119de2952eSStefano Zampini PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Not for rectangular matrices"); 42129de2952eSStefano Zampini for (PetscInt i = 0; i < nblocks; i++) { 42139de2952eSStefano Zampini ncnt += bsizes[i]; 42149de2952eSStefano Zampini ncnt2 += PetscSqr(bsizes[i]); 42159de2952eSStefano Zampini } 42169de2952eSStefano 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); 42179de2952eSStefano Zampini for (PetscInt i = 0; i < nblocks; i++) bsizemax = PetscMax(bsizemax, bsizes[i]); 42189de2952eSStefano Zampini if (bsizemax > 7) PetscCall(PetscMalloc2(bsizemax, &v_work, bsizemax, &v_pivots)); 42199de2952eSStefano Zampini 42209de2952eSStefano Zampini PetscCall(PetscMalloc1(n + 1, &ii)); 42219de2952eSStefano Zampini PetscCall(PetscMalloc1(ncnt2, &jj)); 42229de2952eSStefano Zampini PetscCall(PetscCalloc1(ncnt2, &aa)); 42239de2952eSStefano Zampini 42249de2952eSStefano Zampini ncnt = 0; 42259de2952eSStefano Zampini ii[0] = 0; 42269de2952eSStefano Zampini indi = ii; 42279de2952eSStefano Zampini indj = jj; 42289de2952eSStefano Zampini diag = aa; 42299de2952eSStefano Zampini for (PetscInt i = 0; i < nblocks; i++) { 42309de2952eSStefano Zampini const PetscInt bs = bsizes[i]; 42319de2952eSStefano Zampini 42329de2952eSStefano Zampini for (PetscInt k = 0; k < bs; k++) { 42339de2952eSStefano Zampini indi[k + 1] = indi[k] + bs; 42349de2952eSStefano Zampini for (PetscInt j = 0; j < bs; j++) indj[k * bs + j] = ncnt + j; 42359de2952eSStefano Zampini } 42369de2952eSStefano Zampini PetscCall(MatGetValues(A, bs, indj, bs, indj, diag)); 42379de2952eSStefano Zampini switch (bs) { 42389de2952eSStefano Zampini case 1: 42399de2952eSStefano Zampini *diag = 1.0 / (*diag); 42409de2952eSStefano Zampini break; 42419de2952eSStefano Zampini case 2: 42429de2952eSStefano Zampini PetscCall(PetscKernel_A_gets_inverse_A_2(diag, shift, allowzeropivot, &zeropivotdetected)); 42439de2952eSStefano Zampini break; 42449de2952eSStefano Zampini case 3: 42459de2952eSStefano Zampini PetscCall(PetscKernel_A_gets_inverse_A_3(diag, shift, allowzeropivot, &zeropivotdetected)); 42469de2952eSStefano Zampini break; 42479de2952eSStefano Zampini case 4: 42489de2952eSStefano Zampini PetscCall(PetscKernel_A_gets_inverse_A_4(diag, shift, allowzeropivot, &zeropivotdetected)); 42499de2952eSStefano Zampini break; 42509de2952eSStefano Zampini case 5: 42519de2952eSStefano Zampini PetscCall(PetscKernel_A_gets_inverse_A_5(diag, ipvt, work, shift, allowzeropivot, &zeropivotdetected)); 42529de2952eSStefano Zampini break; 42539de2952eSStefano Zampini case 6: 42549de2952eSStefano Zampini PetscCall(PetscKernel_A_gets_inverse_A_6(diag, shift, allowzeropivot, &zeropivotdetected)); 42559de2952eSStefano Zampini break; 42569de2952eSStefano Zampini case 7: 42579de2952eSStefano Zampini PetscCall(PetscKernel_A_gets_inverse_A_7(diag, shift, allowzeropivot, &zeropivotdetected)); 42589de2952eSStefano Zampini break; 42599de2952eSStefano Zampini default: 42609de2952eSStefano Zampini PetscCall(PetscKernel_A_gets_inverse_A(bs, diag, v_pivots, v_work, allowzeropivot, &zeropivotdetected)); 42619de2952eSStefano Zampini } 42629de2952eSStefano Zampini ncnt += bs; 42639de2952eSStefano Zampini flops += 2.0 * PetscPowInt(bs, 3) / 3.0; 42649de2952eSStefano Zampini diag += bs * bs; 42659de2952eSStefano Zampini indj += bs * bs; 42669de2952eSStefano Zampini indi += bs; 42679de2952eSStefano Zampini } 42689de2952eSStefano Zampini PetscCall(PetscLogFlops(flops)); 42699de2952eSStefano Zampini PetscCall(PetscFree2(v_work, v_pivots)); 42709de2952eSStefano Zampini PetscCall(MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A), n, n, ii, jj, aa, B)); 42719de2952eSStefano Zampini { 42729de2952eSStefano Zampini Mat_SeqAIJ *aij = (Mat_SeqAIJ *)(*B)->data; 42739de2952eSStefano Zampini aij->free_a = PETSC_TRUE; 42749de2952eSStefano Zampini aij->free_ij = PETSC_TRUE; 42759de2952eSStefano Zampini } 42769de2952eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 42779de2952eSStefano Zampini } 42789de2952eSStefano Zampini 42799de2952eSStefano Zampini static PetscErrorCode MatDenseScatter(Mat A, PetscSF sf, Mat B) 42809de2952eSStefano Zampini { 42819de2952eSStefano Zampini const PetscScalar *rarr; 42829de2952eSStefano Zampini PetscScalar *larr; 42839de2952eSStefano Zampini PetscSF vsf; 42849de2952eSStefano Zampini PetscInt n, rld, lld; 42859de2952eSStefano Zampini 42869de2952eSStefano Zampini PetscFunctionBegin; 42879de2952eSStefano Zampini PetscCall(MatGetSize(A, NULL, &n)); 42889de2952eSStefano Zampini PetscCall(MatDenseGetLDA(A, &rld)); 42899de2952eSStefano Zampini PetscCall(MatDenseGetLDA(B, &lld)); 42909de2952eSStefano Zampini PetscCall(MatDenseGetArrayRead(A, &rarr)); 42919de2952eSStefano Zampini PetscCall(MatDenseGetArrayWrite(B, &larr)); 42929de2952eSStefano Zampini PetscCall(PetscSFCreateStridedSF(sf, n, rld, lld, &vsf)); 42939de2952eSStefano Zampini PetscCall(PetscSFBcastBegin(vsf, MPIU_SCALAR, rarr, larr, MPI_REPLACE)); 42949de2952eSStefano Zampini PetscCall(PetscSFBcastEnd(vsf, MPIU_SCALAR, rarr, larr, MPI_REPLACE)); 42959de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayRead(A, &rarr)); 42969de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayWrite(B, &larr)); 42979de2952eSStefano Zampini PetscCall(PetscSFDestroy(&vsf)); 42989de2952eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 42999de2952eSStefano Zampini } 43009de2952eSStefano Zampini 43019de2952eSStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, Mat *coarse_submat) 43029de2952eSStefano Zampini { 430388ebb749SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 430488ebb749SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 43059de2952eSStefano Zampini PCBDDCGraph graph = pcbddc->mat_graph; 4306d62866d3SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 430725084f0cSStefano Zampini /* submatrices of local problem */ 43089de2952eSStefano Zampini Mat A_RV = NULL, A_VR, A_VV, local_auxmat2_R = NULL; 430906656605SStefano Zampini /* submatrices of local coarse problem */ 43109de2952eSStefano Zampini Mat S_CV = NULL, S_VC = NULL, S_CC = NULL; 431125084f0cSStefano Zampini /* working matrices */ 431206656605SStefano Zampini Mat C_CR; 43139de2952eSStefano Zampini 431425084f0cSStefano Zampini /* additional working stuff */ 431506656605SStefano Zampini PC pc_R; 43169de2952eSStefano Zampini IS is_R, is_V, is_C; 43179de2952eSStefano Zampini const PetscInt *idx_V, *idx_C; 4318c58f9fdbSStefano Zampini Mat F, Brhs = NULL; 43195cbda25cSStefano Zampini Vec dummy_vec; 4320*d7974de0SStefano Zampini PetscBool isPreonly, isLU, isCHOL, need_benign_correction, sparserhs; 432106656605SStefano Zampini PetscInt *idx_V_B; 43229de2952eSStefano Zampini PetscInt lda_rhs, n_vertices, n_constraints, *p0_lidx_I; 43239de2952eSStefano Zampini PetscInt n_eff_vertices, n_eff_constraints; 432406656605SStefano Zampini PetscInt i, n_R, n_D, n_B; 432506656605SStefano Zampini PetscScalar one = 1.0, m_one = -1.0; 432688ebb749SStefano Zampini 43279de2952eSStefano Zampini /* Multi-element support */ 43289de2952eSStefano Zampini PetscBool multi_element = graph->multi_element; 43299de2952eSStefano Zampini PetscInt *V_to_eff_V = NULL, *C_to_eff_C = NULL; 43309de2952eSStefano Zampini PetscInt *B_eff_V_J = NULL, *R_eff_V_J = NULL, *B_eff_C_J = NULL, *R_eff_C_J = NULL; 43319de2952eSStefano Zampini IS is_C_perm = NULL; 43329de2952eSStefano Zampini PetscInt n_C_bss = 0, *C_bss = NULL; 43339de2952eSStefano Zampini Mat coarse_phi_multi; 43349de2952eSStefano Zampini 433588ebb749SStefano Zampini PetscFunctionBegin; 43367827d75bSBarry 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"); 43379566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_CorrectionSetUp[pcbddc->current_level], pc, 0, 0, 0)); 4338ffd830a3SStefano Zampini 4339ffd830a3SStefano Zampini /* Set Non-overlapping dimensions */ 4340b371cd4fSStefano Zampini n_vertices = pcbddc->n_vertices; 43414f1b2e48SStefano Zampini n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices; 4342b371cd4fSStefano Zampini n_B = pcis->n_B; 4343b371cd4fSStefano Zampini n_D = pcis->n - n_B; 434488ebb749SStefano Zampini n_R = pcis->n - n_vertices; 434588ebb749SStefano Zampini 434688ebb749SStefano Zampini /* vertices in boundary numbering */ 43479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_vertices, &idx_V_B)); 43489566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(pcis->BtoNmap, IS_GTOLM_DROP, n_vertices, pcbddc->local_primal_ref_node, &i, idx_V_B)); 434963a3b9bcSJacob 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); 435088ebb749SStefano Zampini 43519de2952eSStefano Zampini /* these two cases still need to be optimized */ 43529de2952eSStefano Zampini if (pcbddc->benign_saddle_point || !pcbddc->symmetric_primal) multi_element = PETSC_FALSE; 43539de2952eSStefano Zampini 435406656605SStefano Zampini /* Subdomain contribution (Non-overlapping) to coarse matrix */ 43559de2952eSStefano Zampini if (multi_element) { 43569de2952eSStefano Zampini PetscCheck(!pcbddc->benign_n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not yet implemented"); 43579de2952eSStefano Zampini 43589de2952eSStefano Zampini PetscCall(MatCreate(PETSC_COMM_SELF, coarse_submat)); 43599de2952eSStefano Zampini PetscCall(MatSetSizes(*coarse_submat, pcbddc->local_primal_size, pcbddc->local_primal_size, pcbddc->local_primal_size, pcbddc->local_primal_size)); 43609de2952eSStefano Zampini PetscCall(MatSetType(*coarse_submat, MATSEQAIJ)); 43619de2952eSStefano Zampini PetscCall(MatSetOption(*coarse_submat, MAT_IGNORE_ZERO_ENTRIES, PETSC_TRUE)); 43629de2952eSStefano Zampini PetscCall(MatSetOption(*coarse_submat, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 43639de2952eSStefano Zampini 43649de2952eSStefano Zampini /* group vertices and constraints by subdomain id */ 43659de2952eSStefano Zampini const PetscInt *vidxs = pcbddc->primal_indices_local_idxs; 43669de2952eSStefano Zampini const PetscInt *cidxs = pcbddc->primal_indices_local_idxs + n_vertices; 43679de2952eSStefano Zampini PetscInt *count_eff, *V_eff_to_V, *C_eff_to_C, *nnz; 43689de2952eSStefano Zampini PetscInt n_el = PetscMax(graph->n_local_subs, 1); 43699de2952eSStefano Zampini 43709de2952eSStefano Zampini PetscCall(PetscCalloc1(2 * n_el, &count_eff)); 43719de2952eSStefano Zampini PetscCall(PetscMalloc1(n_vertices, &V_to_eff_V)); 43729de2952eSStefano Zampini PetscCall(PetscMalloc1(n_constraints, &C_to_eff_C)); 43739de2952eSStefano Zampini for (PetscInt i = 0; i < n_vertices; i++) { 43749de2952eSStefano Zampini PetscInt s = 2 * graph->nodes[vidxs[i]].local_sub; 43759de2952eSStefano Zampini 43769de2952eSStefano Zampini V_to_eff_V[i] = count_eff[s]; 43779de2952eSStefano Zampini count_eff[s] += 1; 43789de2952eSStefano Zampini } 43799de2952eSStefano Zampini for (PetscInt i = 0; i < n_constraints; i++) { 43809de2952eSStefano Zampini PetscInt s = 2 * graph->nodes[cidxs[i]].local_sub + 1; 43819de2952eSStefano Zampini 43829de2952eSStefano Zampini C_to_eff_C[i] = count_eff[s]; 43839de2952eSStefano Zampini count_eff[s] += 1; 43849de2952eSStefano Zampini } 43859de2952eSStefano Zampini 43869de2952eSStefano Zampini /* preallocation */ 43879de2952eSStefano Zampini PetscCall(PetscMalloc1(n_vertices + n_constraints, &nnz)); 43889de2952eSStefano Zampini for (PetscInt i = 0; i < n_vertices; i++) { 43899de2952eSStefano Zampini PetscInt s = 2 * graph->nodes[vidxs[i]].local_sub; 43909de2952eSStefano Zampini 43919de2952eSStefano Zampini nnz[i] = count_eff[s] + count_eff[s + 1]; 43929de2952eSStefano Zampini } 43939de2952eSStefano Zampini for (PetscInt i = 0; i < n_constraints; i++) { 43949de2952eSStefano Zampini PetscInt s = 2 * graph->nodes[cidxs[i]].local_sub; 43959de2952eSStefano Zampini 43969de2952eSStefano Zampini nnz[i + n_vertices] = count_eff[s] + count_eff[s + 1]; 43979de2952eSStefano Zampini } 43989de2952eSStefano Zampini PetscCall(MatSeqAIJSetPreallocation(*coarse_submat, 0, nnz)); 43999de2952eSStefano Zampini PetscCall(PetscFree(nnz)); 44009de2952eSStefano Zampini 44019de2952eSStefano Zampini n_eff_vertices = 0; 44029de2952eSStefano Zampini n_eff_constraints = 0; 44039de2952eSStefano Zampini for (PetscInt i = 0; i < n_el; i++) { 44049de2952eSStefano Zampini n_eff_vertices = PetscMax(n_eff_vertices, count_eff[2 * i]); 44059de2952eSStefano Zampini n_eff_constraints = PetscMax(n_eff_constraints, count_eff[2 * i + 1]); 44069de2952eSStefano Zampini count_eff[2 * i] = 0; 44079de2952eSStefano Zampini count_eff[2 * i + 1] = 0; 44089de2952eSStefano Zampini } 44099de2952eSStefano Zampini 44109de2952eSStefano Zampini const PetscInt *idx; 44119de2952eSStefano Zampini PetscCall(PetscMalloc2(n_el * n_eff_vertices, &V_eff_to_V, n_el * n_eff_constraints, &C_eff_to_C)); 44129de2952eSStefano Zampini 44139de2952eSStefano Zampini for (PetscInt i = 0; i < n_vertices; i++) { 44149de2952eSStefano Zampini const PetscInt e = graph->nodes[vidxs[i]].local_sub; 44159de2952eSStefano Zampini const PetscInt s = 2 * e; 44169de2952eSStefano Zampini 44179de2952eSStefano Zampini V_eff_to_V[e * n_eff_vertices + count_eff[s]] = i; 44189de2952eSStefano Zampini count_eff[s] += 1; 44199de2952eSStefano Zampini } 44209de2952eSStefano Zampini for (PetscInt i = 0; i < n_constraints; i++) { 44219de2952eSStefano Zampini const PetscInt e = graph->nodes[cidxs[i]].local_sub; 44229de2952eSStefano Zampini const PetscInt s = 2 * e + 1; 44239de2952eSStefano Zampini 44249de2952eSStefano Zampini C_eff_to_C[e * n_eff_constraints + count_eff[s]] = i; 44259de2952eSStefano Zampini count_eff[s] += 1; 44269de2952eSStefano Zampini } 44279de2952eSStefano Zampini 44289de2952eSStefano Zampini PetscCall(PetscMalloc1(n_R * n_eff_vertices, &R_eff_V_J)); 44299de2952eSStefano Zampini PetscCall(PetscMalloc1(n_R * n_eff_constraints, &R_eff_C_J)); 44309de2952eSStefano Zampini PetscCall(PetscMalloc1(n_B * n_eff_vertices, &B_eff_V_J)); 44319de2952eSStefano Zampini PetscCall(PetscMalloc1(n_B * n_eff_constraints, &B_eff_C_J)); 44329de2952eSStefano Zampini for (PetscInt i = 0; i < n_R * n_eff_vertices; i++) R_eff_V_J[i] = -1; 44339de2952eSStefano Zampini for (PetscInt i = 0; i < n_R * n_eff_constraints; i++) R_eff_C_J[i] = -1; 44349de2952eSStefano Zampini for (PetscInt i = 0; i < n_B * n_eff_vertices; i++) B_eff_V_J[i] = -1; 44359de2952eSStefano Zampini for (PetscInt i = 0; i < n_B * n_eff_constraints; i++) B_eff_C_J[i] = -1; 44369de2952eSStefano Zampini 44379de2952eSStefano Zampini PetscCall(ISGetIndices(pcbddc->is_R_local, &idx)); 44389de2952eSStefano Zampini for (PetscInt i = 0; i < n_R; i++) { 44399de2952eSStefano Zampini const PetscInt e = graph->nodes[idx[i]].local_sub; 44409de2952eSStefano Zampini const PetscInt s = 2 * e; 44419de2952eSStefano Zampini PetscInt j; 44429de2952eSStefano Zampini 44439de2952eSStefano 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]; 44449de2952eSStefano 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]; 44459de2952eSStefano Zampini } 44469de2952eSStefano Zampini PetscCall(ISRestoreIndices(pcbddc->is_R_local, &idx)); 44479de2952eSStefano Zampini PetscCall(ISGetIndices(pcis->is_B_local, &idx)); 44489de2952eSStefano Zampini for (PetscInt i = 0; i < n_B; i++) { 44499de2952eSStefano Zampini const PetscInt e = graph->nodes[idx[i]].local_sub; 44509de2952eSStefano Zampini const PetscInt s = 2 * e; 44519de2952eSStefano Zampini PetscInt j; 44529de2952eSStefano Zampini 44539de2952eSStefano 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]; 44549de2952eSStefano 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]; 44559de2952eSStefano Zampini } 44569de2952eSStefano Zampini PetscCall(ISRestoreIndices(pcis->is_B_local, &idx)); 44579de2952eSStefano Zampini 44589de2952eSStefano Zampini /* permutation and blocksizes for block invert of S_CC */ 44599de2952eSStefano Zampini PetscInt *idxp; 44609de2952eSStefano Zampini 44619de2952eSStefano Zampini PetscCall(PetscMalloc1(n_constraints, &idxp)); 44629de2952eSStefano Zampini PetscCall(PetscMalloc1(n_el, &C_bss)); 44639de2952eSStefano Zampini n_C_bss = 0; 44649de2952eSStefano Zampini for (PetscInt e = 0, cnt = 0; e < n_el; e++) { 44659de2952eSStefano Zampini const PetscInt nc = count_eff[2 * e + 1]; 44669de2952eSStefano Zampini 44679de2952eSStefano Zampini if (nc) C_bss[n_C_bss++] = nc; 4468ac530a7eSPierre Jolivet for (PetscInt c = 0; c < nc; c++) idxp[cnt + c] = C_eff_to_C[e * n_eff_constraints + c]; 44699de2952eSStefano Zampini cnt += nc; 44709de2952eSStefano Zampini } 44719de2952eSStefano Zampini 44729de2952eSStefano Zampini PetscCall(ISCreateGeneral(PETSC_COMM_SELF, n_constraints, idxp, PETSC_OWN_POINTER, &is_C_perm)); 44739de2952eSStefano Zampini 44749de2952eSStefano Zampini PetscCall(PetscFree2(V_eff_to_V, C_eff_to_C)); 44759de2952eSStefano Zampini PetscCall(PetscFree(count_eff)); 44769de2952eSStefano Zampini } else { 44779de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, pcbddc->local_primal_size, pcbddc->local_primal_size, NULL, coarse_submat)); 44789de2952eSStefano Zampini n_eff_constraints = n_constraints; 44799de2952eSStefano Zampini n_eff_vertices = n_vertices; 44809de2952eSStefano Zampini } 448106656605SStefano Zampini 448206656605SStefano Zampini /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */ 44839566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_R, &pc_R)); 44849566063dSJacob Faibussowitsch PetscCall(PCSetUp(pc_R)); 4485*d7974de0SStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)pcbddc->ksp_R, KSPPREONLY, &isPreonly)); 44869566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_R, PCLU, &isLU)); 44879566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_R, PCCHOLESKY, &isCHOL)); 4488ffd830a3SStefano Zampini lda_rhs = n_R; 4489a3df083aSStefano Zampini need_benign_correction = PETSC_FALSE; 4490*d7974de0SStefano Zampini F = NULL; 4491*d7974de0SStefano Zampini if (isPreonly && (isLU || isCHOL)) { 44929566063dSJacob Faibussowitsch PetscCall(PCFactorGetMatrix(pc_R, &F)); 4493b334f244SStefano Zampini } else if (sub_schurs && sub_schurs->reuse_solver) { 4494df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 4495d62866d3SStefano Zampini MatFactorType type; 4496d62866d3SStefano Zampini 4497df4d28bfSStefano Zampini F = reuse_solver->F; 44989566063dSJacob Faibussowitsch PetscCall(MatGetFactorType(F, &type)); 4499d62866d3SStefano Zampini if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE; 45007ebab0bbSStefano Zampini if (type == MAT_FACTOR_LU) isLU = PETSC_TRUE; 45019566063dSJacob Faibussowitsch PetscCall(MatGetSize(F, &lda_rhs, NULL)); 450222db5ddcSStefano Zampini need_benign_correction = (PetscBool)(!!reuse_solver->benign_n); 4503*d7974de0SStefano Zampini } 450406656605SStefano Zampini 4505c58f9fdbSStefano Zampini /* determine if we can use a sparse right-hand side */ 4506c58f9fdbSStefano Zampini sparserhs = PETSC_FALSE; 45079de2952eSStefano Zampini if (F && !multi_element) { 4508ea799195SBarry Smith MatSolverType solver; 4509c58f9fdbSStefano Zampini 45109566063dSJacob Faibussowitsch PetscCall(MatFactorGetSolverType(F, &solver)); 45119566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(solver, MATSOLVERMUMPS, &sparserhs)); 4512c58f9fdbSStefano Zampini } 4513c58f9fdbSStefano Zampini 45145cbda25cSStefano Zampini /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */ 45155cbda25cSStefano Zampini dummy_vec = NULL; 45165cbda25cSStefano Zampini if (need_benign_correction && lda_rhs != n_R && F) { 45179566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N), &dummy_vec)); 45189566063dSJacob Faibussowitsch PetscCall(VecSetSizes(dummy_vec, lda_rhs, PETSC_DECIDE)); 45199566063dSJacob Faibussowitsch PetscCall(VecSetType(dummy_vec, ((PetscObject)pcis->vec1_N)->type_name)); 45205cbda25cSStefano Zampini } 45215cbda25cSStefano Zampini 45229566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_auxmat1)); 45239566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_auxmat2)); 45247ebab0bbSStefano Zampini 45259de2952eSStefano Zampini PetscCall(ISCreateStride(PETSC_COMM_SELF, n_R, 0, 1, &is_R)); 45269de2952eSStefano Zampini PetscCall(ISCreateStride(PETSC_COMM_SELF, n_vertices, 0, 1, &is_V)); 45279de2952eSStefano Zampini PetscCall(ISCreateStride(PETSC_COMM_SELF, n_constraints, n_vertices, 1, &is_C)); 45289de2952eSStefano Zampini PetscCall(ISGetIndices(is_V, &idx_V)); 45299de2952eSStefano Zampini PetscCall(ISGetIndices(is_C, &idx_C)); 45309de2952eSStefano Zampini 453188ebb749SStefano Zampini /* Precompute stuffs needed for preprocessing and application of BDDC*/ 453288ebb749SStefano Zampini if (n_constraints) { 45339de2952eSStefano Zampini Mat C_B; 453406656605SStefano Zampini 453525084f0cSStefano Zampini /* Extract constraints on R nodes: C_{CR} */ 45369de2952eSStefano Zampini PetscCall(MatCreateSubMatrix(pcbddc->ConstraintMatrix, is_C, pcbddc->is_R_local, MAT_INITIAL_MATRIX, &C_CR)); 45379de2952eSStefano Zampini PetscCall(MatCreateSubMatrix(pcbddc->ConstraintMatrix, is_C, pcis->is_B_local, MAT_INITIAL_MATRIX, &C_B)); 453888ebb749SStefano Zampini 453980677318SStefano Zampini /* Assemble local_auxmat2_R = (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */ 454080677318SStefano Zampini /* Assemble pcbddc->local_auxmat2 = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */ 4541c58f9fdbSStefano Zampini if (!sparserhs) { 45429de2952eSStefano Zampini PetscScalar *marr; 45439de2952eSStefano Zampini 45449de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, lda_rhs, n_eff_constraints, NULL, &Brhs)); 45459de2952eSStefano Zampini PetscCall(MatDenseGetArrayWrite(Brhs, &marr)); 454688ebb749SStefano Zampini for (i = 0; i < n_constraints; i++) { 454706656605SStefano Zampini const PetscScalar *row_cmat_values; 454806656605SStefano Zampini const PetscInt *row_cmat_indices; 45499de2952eSStefano Zampini PetscInt size_of_constraint, j, col = C_to_eff_C ? C_to_eff_C[i] : i; 455088ebb749SStefano Zampini 45519566063dSJacob Faibussowitsch PetscCall(MatGetRow(C_CR, i, &size_of_constraint, &row_cmat_indices, &row_cmat_values)); 45529de2952eSStefano Zampini for (j = 0; j < size_of_constraint; j++) marr[row_cmat_indices[j] + col * lda_rhs] = -row_cmat_values[j]; 45539566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(C_CR, i, &size_of_constraint, &row_cmat_indices, &row_cmat_values)); 455406656605SStefano Zampini } 45559de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayWrite(Brhs, &marr)); 4556c58f9fdbSStefano Zampini } else { 4557c58f9fdbSStefano Zampini Mat tC_CR; 4558c58f9fdbSStefano Zampini 45599566063dSJacob Faibussowitsch PetscCall(MatScale(C_CR, -1.0)); 4560c58f9fdbSStefano Zampini if (lda_rhs != n_R) { 4561c58f9fdbSStefano Zampini PetscScalar *aa; 4562c58f9fdbSStefano Zampini PetscInt r, *ii, *jj; 4563c58f9fdbSStefano Zampini PetscBool done; 4564c58f9fdbSStefano Zampini 45659566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(C_CR, 0, PETSC_FALSE, PETSC_FALSE, &r, (const PetscInt **)&ii, (const PetscInt **)&jj, &done)); 456628b400f6SJacob Faibussowitsch PetscCheck(done, PETSC_COMM_SELF, PETSC_ERR_PLIB, "GetRowIJ failed"); 45679566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(C_CR, &aa)); 45689566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, n_constraints, lda_rhs, ii, jj, aa, &tC_CR)); 45699566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(C_CR, 0, PETSC_FALSE, PETSC_FALSE, &r, (const PetscInt **)&ii, (const PetscInt **)&jj, &done)); 457028b400f6SJacob Faibussowitsch PetscCheck(done, PETSC_COMM_SELF, PETSC_ERR_PLIB, "RestoreRowIJ failed"); 4571c58f9fdbSStefano Zampini } else { 45729566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)C_CR)); 4573c58f9fdbSStefano Zampini tC_CR = C_CR; 4574c58f9fdbSStefano Zampini } 45759566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(tC_CR, &Brhs)); 45769566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tC_CR)); 4577c58f9fdbSStefano Zampini } 45789de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, lda_rhs, n_eff_constraints, NULL, &local_auxmat2_R)); 457906656605SStefano Zampini if (F) { 4580a3df083aSStefano Zampini if (need_benign_correction) { 4581df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 4582a3df083aSStefano Zampini 458372b8c272SStefano Zampini /* rhs is already zero on interior dofs, no need to change the rhs */ 45849566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(reuse_solver->benign_save_vals, pcbddc->benign_n)); 4585a3df083aSStefano Zampini } 45869566063dSJacob Faibussowitsch PetscCall(MatMatSolve(F, Brhs, local_auxmat2_R)); 4587a3df083aSStefano Zampini if (need_benign_correction) { 4588a3df083aSStefano Zampini PetscScalar *marr; 4589df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 4590a3df083aSStefano Zampini 45919de2952eSStefano Zampini /* XXX multi_element? */ 45929566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(local_auxmat2_R, &marr)); 45935cbda25cSStefano Zampini if (lda_rhs != n_R) { 45949de2952eSStefano Zampini for (i = 0; i < n_eff_constraints; i++) { 45959566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dummy_vec, marr + i * lda_rhs)); 45969566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, dummy_vec, NULL, PETSC_TRUE, PETSC_TRUE)); 45979566063dSJacob Faibussowitsch PetscCall(VecResetArray(dummy_vec)); 45985cbda25cSStefano Zampini } 45995cbda25cSStefano Zampini } else { 46009de2952eSStefano Zampini for (i = 0; i < n_eff_constraints; i++) { 46019566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, marr + i * lda_rhs)); 46029566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, pcbddc->vec1_R, NULL, PETSC_TRUE, PETSC_TRUE)); 46039566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 4604a3df083aSStefano Zampini } 46055cbda25cSStefano Zampini } 46069566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(local_auxmat2_R, &marr)); 4607a3df083aSStefano Zampini } 460806656605SStefano Zampini } else { 46099de2952eSStefano Zampini const PetscScalar *barr; 461080677318SStefano Zampini PetscScalar *marr; 461180677318SStefano Zampini 46129de2952eSStefano Zampini PetscCall(MatDenseGetArrayRead(Brhs, &barr)); 46139566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(local_auxmat2_R, &marr)); 46149de2952eSStefano Zampini for (i = 0; i < n_eff_constraints; i++) { 46159de2952eSStefano Zampini PetscCall(VecPlaceArray(pcbddc->vec1_R, barr + i * lda_rhs)); 46169566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec2_R, marr + i * lda_rhs)); 46179566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec2_R)); 46189566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec2_R)); 46199566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 46209566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec2_R)); 462106656605SStefano Zampini } 46229de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayRead(Brhs, &barr)); 46239566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(local_auxmat2_R, &marr)); 462406656605SStefano Zampini } 46251baa6e33SBarry Smith if (sparserhs) PetscCall(MatScale(C_CR, -1.0)); 46269566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Brhs)); 46279de2952eSStefano Zampini /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR})^{-1} */ 462880677318SStefano Zampini if (!pcbddc->switch_static) { 46299de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_B, n_eff_constraints, NULL, &pcbddc->local_auxmat2)); 46309de2952eSStefano Zampini for (i = 0; i < n_eff_constraints; i++) { 4631ab2d12f3SJunchao Zhang Vec r, b; 46329566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVecRead(local_auxmat2_R, i, &r)); 46339566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVec(pcbddc->local_auxmat2, i, &b)); 46349566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, r, b, INSERT_VALUES, SCATTER_FORWARD)); 46359566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, r, b, INSERT_VALUES, SCATTER_FORWARD)); 46369566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVec(pcbddc->local_auxmat2, i, &b)); 46379566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVecRead(local_auxmat2_R, i, &r)); 463880677318SStefano Zampini } 46399de2952eSStefano Zampini if (multi_element) { 46409de2952eSStefano Zampini Mat T; 4641ffd830a3SStefano Zampini 46429de2952eSStefano Zampini PetscCall(MatCreateSeqAIJFromDenseExpand(local_auxmat2_R, n_constraints, R_eff_C_J, &T)); 46439de2952eSStefano Zampini PetscCall(MatDestroy(&local_auxmat2_R)); 46449de2952eSStefano Zampini local_auxmat2_R = T; 46459de2952eSStefano Zampini PetscCall(MatCreateSeqAIJFromDenseExpand(pcbddc->local_auxmat2, n_constraints, B_eff_C_J, &T)); 46469de2952eSStefano Zampini PetscCall(MatDestroy(&pcbddc->local_auxmat2)); 46479de2952eSStefano Zampini pcbddc->local_auxmat2 = T; 46489de2952eSStefano Zampini } 4649fb842aefSJose E. Roman PetscCall(MatMatMult(C_B, pcbddc->local_auxmat2, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &S_CC)); 46509de2952eSStefano Zampini } else { 46519de2952eSStefano Zampini if (multi_element) { 46529de2952eSStefano Zampini Mat T; 46539de2952eSStefano Zampini 46549de2952eSStefano Zampini PetscCall(MatCreateSeqAIJFromDenseExpand(local_auxmat2_R, n_constraints, R_eff_C_J, &T)); 46559de2952eSStefano Zampini PetscCall(MatDestroy(&local_auxmat2_R)); 46569de2952eSStefano Zampini local_auxmat2_R = T; 46579de2952eSStefano Zampini } 46589de2952eSStefano Zampini if (lda_rhs != n_R) { 46599de2952eSStefano Zampini PetscCall(MatCreateSubMatrix(local_auxmat2_R, is_R, NULL, MAT_INITIAL_MATRIX, &pcbddc->local_auxmat2)); 4660ffd830a3SStefano Zampini } else { 46619566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)local_auxmat2_R)); 466280677318SStefano Zampini pcbddc->local_auxmat2 = local_auxmat2_R; 4663ffd830a3SStefano Zampini } 4664fb842aefSJose E. Roman PetscCall(MatMatMult(C_CR, pcbddc->local_auxmat2, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &S_CC)); 466580677318SStefano Zampini } 46669de2952eSStefano Zampini PetscCall(MatScale(S_CC, m_one)); 46679de2952eSStefano Zampini if (multi_element) { 46689de2952eSStefano Zampini Mat T, T2; 46699de2952eSStefano Zampini IS isp, ispi; 46709de2952eSStefano Zampini 46719de2952eSStefano Zampini isp = is_C_perm; 46729de2952eSStefano Zampini 46739de2952eSStefano Zampini PetscCall(ISInvertPermutation(isp, PETSC_DECIDE, &ispi)); 46749de2952eSStefano Zampini PetscCall(MatPermute(S_CC, isp, isp, &T)); 46759de2952eSStefano Zampini PetscCall(MatSeqAIJInvertVariableBlockDiagonalMat(T, n_C_bss, C_bss, &T2)); 46769de2952eSStefano Zampini PetscCall(MatDestroy(&T)); 46779de2952eSStefano Zampini PetscCall(MatDestroy(&S_CC)); 46789de2952eSStefano Zampini PetscCall(MatPermute(T2, ispi, ispi, &S_CC)); 46799de2952eSStefano Zampini PetscCall(MatDestroy(&T2)); 46809de2952eSStefano Zampini PetscCall(ISDestroy(&ispi)); 468180677318SStefano Zampini } else { 46829de2952eSStefano Zampini if (isCHOL) { 46839de2952eSStefano Zampini PetscCall(MatCholeskyFactor(S_CC, NULL, NULL)); 46849de2952eSStefano Zampini } else { 46859de2952eSStefano Zampini PetscCall(MatLUFactor(S_CC, NULL, NULL, NULL)); 468680677318SStefano Zampini } 46879de2952eSStefano Zampini PetscCall(MatSeqDenseInvertFactors_Private(S_CC)); 46889de2952eSStefano Zampini } 468980677318SStefano Zampini /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */ 4690fb842aefSJose E. Roman PetscCall(MatMatMult(S_CC, C_B, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &pcbddc->local_auxmat1)); 46919566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C_B)); 46929de2952eSStefano Zampini PetscCall(MatSetValuesSubMat(*coarse_submat, S_CC, n_constraints, idx_C, n_constraints, idx_C, INSERT_VALUES)); 4693f4ddd8eeSStefano Zampini } 4694fc227af8SStefano Zampini 4695fc227af8SStefano Zampini /* Get submatrices from subdomain matrix */ 469688ebb749SStefano Zampini if (n_vertices) { 46977ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 46987ebab0bbSStefano Zampini PetscBool oldpin; 46997ebab0bbSStefano Zampini #endif 470006656605SStefano Zampini IS is_aux; 47013a50541eSStefano Zampini 4702b334f244SStefano Zampini if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */ 47036816873aSStefano Zampini IS tis; 47046816873aSStefano Zampini 47059566063dSJacob Faibussowitsch PetscCall(ISDuplicate(pcbddc->is_R_local, &tis)); 47069566063dSJacob Faibussowitsch PetscCall(ISSort(tis)); 47079566063dSJacob Faibussowitsch PetscCall(ISComplement(tis, 0, pcis->n, &is_aux)); 47089566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tis)); 47096816873aSStefano Zampini } else { 47109566063dSJacob Faibussowitsch PetscCall(ISComplement(pcbddc->is_R_local, 0, pcis->n, &is_aux)); 47116816873aSStefano Zampini } 47127ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 4713b470e4b4SRichard Tran Mills oldpin = pcbddc->local_mat->boundtocpu; 47147ebab0bbSStefano Zampini #endif 47159566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(pcbddc->local_mat, PETSC_TRUE)); 47169566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcbddc->is_R_local, is_aux, MAT_INITIAL_MATRIX, &A_RV)); 47179566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, is_aux, pcbddc->is_R_local, MAT_INITIAL_MATRIX, &A_VR)); 47189de2952eSStefano Zampini /* TODO REMOVE: MatMatMult(A_VR,A_RRmA_RV) below may raise an error */ 47199566063dSJacob Faibussowitsch PetscCall(MatConvert(A_VR, MATSEQAIJ, MAT_INPLACE_MATRIX, &A_VR)); 47209566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, is_aux, is_aux, MAT_INITIAL_MATRIX, &A_VV)); 47217ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 47229566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(pcbddc->local_mat, oldpin)); 47237ebab0bbSStefano Zampini #endif 47249566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_aux)); 472588ebb749SStefano Zampini } 47269de2952eSStefano Zampini PetscCall(ISDestroy(&is_C_perm)); 47279de2952eSStefano Zampini PetscCall(PetscFree(C_bss)); 472888ebb749SStefano Zampini 47294f1b2e48SStefano Zampini p0_lidx_I = NULL; 47304f1b2e48SStefano Zampini if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) { 4731d12edf2fSStefano Zampini const PetscInt *idxs; 4732d12edf2fSStefano Zampini 47339566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_I_local, &idxs)); 47349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->benign_n, &p0_lidx_I)); 473548a46eb9SPierre 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])); 47369566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_I_local, &idxs)); 4737d12edf2fSStefano Zampini } 4738d16cbb6bSStefano Zampini 47399de2952eSStefano Zampini /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */ 47409de2952eSStefano Zampini 47419de2952eSStefano Zampini /* Matrices of coarse basis functions (local) */ 47429de2952eSStefano Zampini PetscCall(MatDestroy(&pcbddc->coarse_phi_B)); 47439de2952eSStefano Zampini PetscCall(MatDestroy(&pcbddc->coarse_psi_B)); 47449de2952eSStefano Zampini PetscCall(MatDestroy(&pcbddc->coarse_phi_D)); 47459de2952eSStefano Zampini PetscCall(MatDestroy(&pcbddc->coarse_psi_D)); 47469de2952eSStefano Zampini if (!multi_element) { 47479de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_B, pcbddc->local_primal_size, NULL, &pcbddc->coarse_phi_B)); 47489de2952eSStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_D, pcbddc->local_primal_size, NULL, &pcbddc->coarse_phi_D)); 47499de2952eSStefano Zampini coarse_phi_multi = NULL; 47509de2952eSStefano Zampini } else { /* Create temporary NEST matrix to hold coarse basis functions blocks */ 47519de2952eSStefano Zampini IS is_rows[2] = {pcbddc->is_R_local, NULL}; 47529de2952eSStefano Zampini IS is_cols[2] = {is_V, is_C}; 47539de2952eSStefano Zampini 47549de2952eSStefano Zampini PetscCall(ISCreateGeneral(PETSC_COMM_SELF, n_vertices, pcbddc->local_primal_ref_node, PETSC_USE_POINTER, &is_rows[1])); 47559de2952eSStefano Zampini PetscCall(MatCreateNest(PETSC_COMM_SELF, 2, is_rows, 2, is_cols, NULL, &coarse_phi_multi)); 47569de2952eSStefano Zampini PetscCall(ISDestroy(&is_rows[1])); 47579de2952eSStefano Zampini } 47589de2952eSStefano Zampini 475906656605SStefano Zampini /* vertices */ 476006656605SStefano Zampini if (n_vertices) { 4761c58f9fdbSStefano Zampini PetscBool restoreavr = PETSC_FALSE; 47629de2952eSStefano Zampini Mat A_RRmA_RV = NULL; 476316f15bc4SStefano Zampini 47649de2952eSStefano Zampini PetscCall(MatSetValuesSubMat(*coarse_submat, A_VV, n_vertices, idx_V, n_vertices, idx_V, ADD_VALUES)); 47659de2952eSStefano Zampini PetscCall(MatDestroy(&A_VV)); 476604708bb6SStefano Zampini 476716f15bc4SStefano Zampini if (n_R) { 47689de2952eSStefano Zampini Mat A_RV_bcorr = NULL, S_VV; 476906656605SStefano Zampini 47709566063dSJacob Faibussowitsch PetscCall(MatScale(A_RV, m_one)); 477114393ed6SStefano Zampini if (need_benign_correction) { 477214393ed6SStefano Zampini ISLocalToGlobalMapping RtoN; 477314393ed6SStefano Zampini IS is_p0; 477414393ed6SStefano Zampini PetscInt *idxs_p0, n; 477514393ed6SStefano Zampini 47769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->benign_n, &idxs_p0)); 47779566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local, &RtoN)); 47789566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(RtoN, IS_GTOLM_DROP, pcbddc->benign_n, pcbddc->benign_p0_lidx, &n, idxs_p0)); 477963a3b9bcSJacob 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); 47809566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&RtoN)); 47819566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, n, idxs_p0, PETSC_OWN_POINTER, &is_p0)); 47829566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A_RV, is_p0, NULL, MAT_INITIAL_MATRIX, &A_RV_bcorr)); 47839566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_p0)); 478414393ed6SStefano Zampini } 478514393ed6SStefano Zampini 47869de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, lda_rhs, n_eff_vertices, NULL, &A_RRmA_RV)); 4787c58f9fdbSStefano Zampini if (!sparserhs || need_benign_correction) { 47889de2952eSStefano Zampini if (lda_rhs == n_R && !multi_element) { 47899566063dSJacob Faibussowitsch PetscCall(MatConvert(A_RV, MATDENSE, MAT_INPLACE_MATRIX, &A_RV)); 4790ffd830a3SStefano Zampini } else { 47919de2952eSStefano Zampini Mat T; 4792ca92afb2SStefano Zampini PetscScalar *av, *array; 4793ca92afb2SStefano Zampini const PetscInt *xadj, *adjncy; 4794ca92afb2SStefano Zampini PetscInt n; 4795ca92afb2SStefano Zampini PetscBool flg_row; 4796ffd830a3SStefano Zampini 47979de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, lda_rhs, n_eff_vertices, NULL, &T)); 47989de2952eSStefano Zampini PetscCall(MatDenseGetArrayWrite(T, &array)); 47999566063dSJacob Faibussowitsch PetscCall(MatConvert(A_RV, MATSEQAIJ, MAT_INPLACE_MATRIX, &A_RV)); 48009566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A_RV, 0, PETSC_FALSE, PETSC_FALSE, &n, &xadj, &adjncy, &flg_row)); 48019566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A_RV, &av)); 4802ca92afb2SStefano Zampini for (i = 0; i < n; i++) { 4803ca92afb2SStefano Zampini PetscInt j; 48049de2952eSStefano 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]; 4805ffd830a3SStefano Zampini } 48069566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A_RV, 0, PETSC_FALSE, PETSC_FALSE, &n, &xadj, &adjncy, &flg_row)); 48079de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayWrite(T, &array)); 48089566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RV)); 48099de2952eSStefano Zampini A_RV = T; 4810ffd830a3SStefano Zampini } 4811a3df083aSStefano Zampini if (need_benign_correction) { 4812df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 4813a3df083aSStefano Zampini PetscScalar *marr; 4814a3df083aSStefano Zampini 48159de2952eSStefano Zampini /* XXX multi_element */ 48169566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(A_RV, &marr)); 481714393ed6SStefano Zampini /* need \Phi^T A_RV = (I+L)A_RV, L given by 481814393ed6SStefano Zampini 481914393ed6SStefano Zampini | 0 0 0 | (V) 482014393ed6SStefano Zampini L = | 0 0 -1 | (P-p0) 482114393ed6SStefano Zampini | 0 0 -1 | (p0) 482214393ed6SStefano Zampini 482314393ed6SStefano Zampini */ 4824df4d28bfSStefano Zampini for (i = 0; i < reuse_solver->benign_n; i++) { 482514393ed6SStefano Zampini const PetscScalar *vals; 482614393ed6SStefano Zampini const PetscInt *idxs, *idxs_zero; 482714393ed6SStefano Zampini PetscInt n, j, nz; 482814393ed6SStefano Zampini 48299566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i], &nz)); 48309566063dSJacob Faibussowitsch PetscCall(ISGetIndices(reuse_solver->benign_zerodiag_subs[i], &idxs_zero)); 48319566063dSJacob Faibussowitsch PetscCall(MatGetRow(A_RV_bcorr, i, &n, &idxs, &vals)); 483214393ed6SStefano Zampini for (j = 0; j < n; j++) { 483314393ed6SStefano Zampini PetscScalar val = vals[j]; 483414393ed6SStefano Zampini PetscInt k, col = idxs[j]; 483514393ed6SStefano Zampini for (k = 0; k < nz; k++) marr[idxs_zero[k] + lda_rhs * col] -= val; 483614393ed6SStefano Zampini } 48379566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(A_RV_bcorr, i, &n, &idxs, &vals)); 48389566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i], &idxs_zero)); 483914393ed6SStefano Zampini } 48409566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(A_RV, &marr)); 484172b8c272SStefano Zampini } 48429566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A_RV)); 4843c58f9fdbSStefano Zampini Brhs = A_RV; 4844c58f9fdbSStefano Zampini } else { 4845c58f9fdbSStefano Zampini Mat tA_RVT, A_RVT; 4846c58f9fdbSStefano Zampini 4847c58f9fdbSStefano Zampini if (!pcbddc->symmetric_primal) { 4848fb6280fbSStefano Zampini /* A_RV already scaled by -1 */ 48499566063dSJacob Faibussowitsch PetscCall(MatTranspose(A_RV, MAT_INITIAL_MATRIX, &A_RVT)); 4850c58f9fdbSStefano Zampini } else { 4851c58f9fdbSStefano Zampini restoreavr = PETSC_TRUE; 48529566063dSJacob Faibussowitsch PetscCall(MatScale(A_VR, -1.0)); 48539566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A_VR)); 4854c58f9fdbSStefano Zampini A_RVT = A_VR; 4855c58f9fdbSStefano Zampini } 4856c58f9fdbSStefano Zampini if (lda_rhs != n_R) { 4857c58f9fdbSStefano Zampini PetscScalar *aa; 4858c58f9fdbSStefano Zampini PetscInt r, *ii, *jj; 4859c58f9fdbSStefano Zampini PetscBool done; 4860c58f9fdbSStefano Zampini 48619566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A_RVT, 0, PETSC_FALSE, PETSC_FALSE, &r, (const PetscInt **)&ii, (const PetscInt **)&jj, &done)); 486228b400f6SJacob Faibussowitsch PetscCheck(done, PETSC_COMM_SELF, PETSC_ERR_PLIB, "GetRowIJ failed"); 48639566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A_RVT, &aa)); 48649566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, n_vertices, lda_rhs, ii, jj, aa, &tA_RVT)); 48659566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A_RVT, 0, PETSC_FALSE, PETSC_FALSE, &r, (const PetscInt **)&ii, (const PetscInt **)&jj, &done)); 486628b400f6SJacob Faibussowitsch PetscCheck(done, PETSC_COMM_SELF, PETSC_ERR_PLIB, "RestoreRowIJ failed"); 4867c58f9fdbSStefano Zampini } else { 48689566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A_RVT)); 4869c58f9fdbSStefano Zampini tA_RVT = A_RVT; 4870c58f9fdbSStefano Zampini } 48719566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(tA_RVT, &Brhs)); 48729566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tA_RVT)); 48739566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RVT)); 4874c58f9fdbSStefano Zampini } 487572b8c272SStefano Zampini if (F) { 487614393ed6SStefano Zampini /* need to correct the rhs */ 487772b8c272SStefano Zampini if (need_benign_correction) { 487872b8c272SStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 487972b8c272SStefano Zampini PetscScalar *marr; 488072b8c272SStefano Zampini 48819566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(Brhs, &marr)); 48825cbda25cSStefano Zampini if (lda_rhs != n_R) { 48839de2952eSStefano Zampini for (i = 0; i < n_eff_vertices; i++) { 48849566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dummy_vec, marr + i * lda_rhs)); 48859566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, dummy_vec, NULL, PETSC_FALSE, PETSC_TRUE)); 48869566063dSJacob Faibussowitsch PetscCall(VecResetArray(dummy_vec)); 48875cbda25cSStefano Zampini } 48885cbda25cSStefano Zampini } else { 48899de2952eSStefano Zampini for (i = 0; i < n_eff_vertices; i++) { 48909566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, marr + i * lda_rhs)); 48919566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, pcbddc->vec1_R, NULL, PETSC_FALSE, PETSC_TRUE)); 48929566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 4893a3df083aSStefano Zampini } 48945cbda25cSStefano Zampini } 48959566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(Brhs, &marr)); 4896a3df083aSStefano Zampini } 48979566063dSJacob Faibussowitsch PetscCall(MatMatSolve(F, Brhs, A_RRmA_RV)); 48981baa6e33SBarry Smith if (restoreavr) PetscCall(MatScale(A_VR, -1.0)); 489914393ed6SStefano Zampini /* need to correct the solution */ 4900a3df083aSStefano Zampini if (need_benign_correction) { 4901df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 4902a3df083aSStefano Zampini PetscScalar *marr; 4903a3df083aSStefano Zampini 49049566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(A_RRmA_RV, &marr)); 49055cbda25cSStefano Zampini if (lda_rhs != n_R) { 49069de2952eSStefano Zampini for (i = 0; i < n_eff_vertices; i++) { 49079566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dummy_vec, marr + i * lda_rhs)); 49089566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, dummy_vec, NULL, PETSC_TRUE, PETSC_TRUE)); 49099566063dSJacob Faibussowitsch PetscCall(VecResetArray(dummy_vec)); 49105cbda25cSStefano Zampini } 49115cbda25cSStefano Zampini } else { 49129de2952eSStefano Zampini for (i = 0; i < n_eff_vertices; i++) { 49139566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, marr + i * lda_rhs)); 49149566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, pcbddc->vec1_R, NULL, PETSC_TRUE, PETSC_TRUE)); 49159566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 4916a3df083aSStefano Zampini } 49175cbda25cSStefano Zampini } 49189566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(A_RRmA_RV, &marr)); 4919a3df083aSStefano Zampini } 492006656605SStefano Zampini } else { 49219de2952eSStefano Zampini const PetscScalar *barr; 49229de2952eSStefano Zampini PetscScalar *marr; 49239de2952eSStefano Zampini 49249de2952eSStefano Zampini PetscCall(MatDenseGetArrayRead(Brhs, &barr)); 49259de2952eSStefano Zampini PetscCall(MatDenseGetArray(A_RRmA_RV, &marr)); 49269de2952eSStefano Zampini for (i = 0; i < n_eff_vertices; i++) { 49279de2952eSStefano Zampini PetscCall(VecPlaceArray(pcbddc->vec1_R, barr + i * lda_rhs)); 49289de2952eSStefano Zampini PetscCall(VecPlaceArray(pcbddc->vec2_R, marr + i * lda_rhs)); 49299566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec2_R)); 49309566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec2_R)); 49319566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 49329566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec2_R)); 493306656605SStefano Zampini } 49349de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayRead(Brhs, &barr)); 49359de2952eSStefano Zampini PetscCall(MatDenseRestoreArray(A_RRmA_RV, &marr)); 493606656605SStefano Zampini } 49379566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RV)); 49389566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Brhs)); 4939ffd830a3SStefano Zampini /* S_VV and S_CV */ 494006656605SStefano Zampini if (n_constraints) { 494106656605SStefano Zampini Mat B; 494280677318SStefano Zampini 49439de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_B, n_eff_vertices, NULL, &B)); 49449de2952eSStefano Zampini PetscCall(MatDenseScatter(A_RRmA_RV, pcbddc->R_to_B, B)); 49459de2952eSStefano Zampini 49469de2952eSStefano Zampini /* S_CV = pcbddc->local_auxmat1 * B */ 49479de2952eSStefano Zampini if (multi_element) { 49489de2952eSStefano Zampini Mat T; 49499de2952eSStefano Zampini 49509de2952eSStefano Zampini PetscCall(MatCreateSeqAIJFromDenseExpand(B, n_vertices, B_eff_V_J, &T)); 49519de2952eSStefano Zampini PetscCall(MatDestroy(&B)); 49529de2952eSStefano Zampini B = T; 495380677318SStefano Zampini } 49549de2952eSStefano Zampini PetscCall(MatProductCreate(pcbddc->local_auxmat1, B, NULL, &S_CV)); 49559566063dSJacob Faibussowitsch PetscCall(MatProductSetType(S_CV, MATPRODUCT_AB)); 49569566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(S_CV)); 49579566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(S_CV)); 49589566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(S_CV)); 49599566063dSJacob Faibussowitsch PetscCall(MatProductClear(S_CV)); 49609566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 49619de2952eSStefano Zampini 49629de2952eSStefano Zampini /* B = local_auxmat2_R * S_CV */ 49639de2952eSStefano Zampini PetscCall(MatProductCreate(local_auxmat2_R, S_CV, NULL, &B)); 49649566063dSJacob Faibussowitsch PetscCall(MatProductSetType(B, MATPRODUCT_AB)); 49659566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(B)); 49669566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(B)); 49679566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(B)); 49684222ddf1SHong Zhang 49699566063dSJacob Faibussowitsch PetscCall(MatScale(S_CV, m_one)); 49709de2952eSStefano Zampini PetscCall(MatSetValuesSubMat(*coarse_submat, S_CV, n_constraints, idx_C, n_vertices, idx_V, INSERT_VALUES)); 497114393ed6SStefano Zampini 49729de2952eSStefano Zampini if (multi_element) { 49739de2952eSStefano Zampini Mat T; 49749de2952eSStefano Zampini 49759de2952eSStefano Zampini PetscCall(MatCreateSeqAIJFromDenseExpand(A_RRmA_RV, n_vertices, R_eff_V_J, &T)); 49769de2952eSStefano Zampini PetscCall(MatDestroy(&A_RRmA_RV)); 49779de2952eSStefano Zampini A_RRmA_RV = T; 49789de2952eSStefano Zampini } 49799de2952eSStefano Zampini PetscCall(MatAXPY(A_RRmA_RV, 1.0, B, UNKNOWN_NONZERO_PATTERN)); /* XXX ? */ 49809de2952eSStefano Zampini PetscCall(MatDestroy(&B)); 49819de2952eSStefano Zampini } else if (multi_element) { 49829de2952eSStefano Zampini Mat T; 49839de2952eSStefano Zampini 49849de2952eSStefano Zampini PetscCall(MatCreateSeqAIJFromDenseExpand(A_RRmA_RV, n_vertices, R_eff_V_J, &T)); 49859de2952eSStefano Zampini PetscCall(MatDestroy(&A_RRmA_RV)); 49869de2952eSStefano Zampini A_RRmA_RV = T; 49879de2952eSStefano Zampini } 49889de2952eSStefano Zampini 49899de2952eSStefano Zampini if (lda_rhs != n_R) { 49909de2952eSStefano Zampini Mat T; 49919de2952eSStefano Zampini 49929de2952eSStefano Zampini PetscCall(MatCreateSubMatrix(A_RRmA_RV, is_R, NULL, MAT_INITIAL_MATRIX, &T)); 49939de2952eSStefano Zampini PetscCall(MatDestroy(&A_RRmA_RV)); 49949de2952eSStefano Zampini A_RRmA_RV = T; 49959de2952eSStefano Zampini } 49969de2952eSStefano Zampini 49979de2952eSStefano Zampini /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */ 49989de2952eSStefano Zampini if (need_benign_correction) { /* XXX SPARSE */ 49999de2952eSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 50009de2952eSStefano Zampini PetscScalar *sums; 50019de2952eSStefano Zampini const PetscScalar *marr; 50029de2952eSStefano Zampini 50039de2952eSStefano Zampini PetscCall(MatDenseGetArrayRead(A_RRmA_RV, &marr)); 50049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_vertices, &sums)); 5005df4d28bfSStefano Zampini for (i = 0; i < reuse_solver->benign_n; i++) { 500614393ed6SStefano Zampini const PetscScalar *vals; 500714393ed6SStefano Zampini const PetscInt *idxs, *idxs_zero; 500814393ed6SStefano Zampini PetscInt n, j, nz; 500914393ed6SStefano Zampini 50109566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i], &nz)); 50119566063dSJacob Faibussowitsch PetscCall(ISGetIndices(reuse_solver->benign_zerodiag_subs[i], &idxs_zero)); 501214393ed6SStefano Zampini for (j = 0; j < n_vertices; j++) { 501314393ed6SStefano Zampini sums[j] = 0.; 50149de2952eSStefano Zampini for (PetscInt k = 0; k < nz; k++) sums[j] += marr[idxs_zero[k] + j * n_R]; 501514393ed6SStefano Zampini } 50169566063dSJacob Faibussowitsch PetscCall(MatGetRow(A_RV_bcorr, i, &n, &idxs, &vals)); 501714393ed6SStefano Zampini for (j = 0; j < n; j++) { 501814393ed6SStefano Zampini PetscScalar val = vals[j]; 50199de2952eSStefano 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)); 502014393ed6SStefano Zampini } 50219566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(A_RV_bcorr, i, &n, &idxs, &vals)); 50229566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i], &idxs_zero)); 502314393ed6SStefano Zampini } 50249566063dSJacob Faibussowitsch PetscCall(PetscFree(sums)); 50259566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RV_bcorr)); 50269de2952eSStefano Zampini PetscCall(MatDenseRestoreArrayRead(A_RRmA_RV, &marr)); 502714393ed6SStefano Zampini } 50289de2952eSStefano Zampini 5029fb842aefSJose E. Roman PetscCall(MatMatMult(A_VR, A_RRmA_RV, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &S_VV)); 50309de2952eSStefano Zampini PetscCall(MatSetValuesSubMat(*coarse_submat, S_VV, n_vertices, idx_V, n_vertices, idx_V, ADD_VALUES)); 50319de2952eSStefano Zampini PetscCall(MatDestroy(&S_VV)); 5032d16cbb6bSStefano Zampini } 5033d16cbb6bSStefano Zampini 503406656605SStefano Zampini /* coarse basis functions */ 50359de2952eSStefano Zampini if (coarse_phi_multi) { 50369de2952eSStefano Zampini Mat Vid; 503716f15bc4SStefano Zampini 50389de2952eSStefano Zampini PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, n_vertices, n_vertices, 1, NULL, &Vid)); 50399de2952eSStefano Zampini PetscCall(MatShift_Basic(Vid, 1.0)); 50409de2952eSStefano Zampini PetscCall(MatNestSetSubMat(coarse_phi_multi, 0, 0, A_RRmA_RV)); 50419de2952eSStefano Zampini PetscCall(MatNestSetSubMat(coarse_phi_multi, 1, 0, Vid)); 50429de2952eSStefano Zampini PetscCall(MatDestroy(&Vid)); 50439de2952eSStefano Zampini } else { 50449de2952eSStefano Zampini if (A_RRmA_RV) { 50459de2952eSStefano Zampini PetscCall(MatDenseScatter(A_RRmA_RV, pcbddc->R_to_B, pcbddc->coarse_phi_B)); 504606656605SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 50479de2952eSStefano Zampini PetscCall(MatDenseScatter(A_RRmA_RV, pcbddc->R_to_D, pcbddc->coarse_phi_D)); 50489de2952eSStefano Zampini if (pcbddc->benign_n) { 50493a7d0413SPierre Jolivet for (i = 0; i < n_vertices; i++) PetscCall(MatSetValues(pcbddc->coarse_phi_D, pcbddc->benign_n, p0_lidx_I, 1, &i, NULL, INSERT_VALUES)); 50508a162dc6SStefano Zampini PetscCall(MatAssemblyBegin(pcbddc->coarse_phi_D, MAT_FINAL_ASSEMBLY)); 50518a162dc6SStefano Zampini PetscCall(MatAssemblyEnd(pcbddc->coarse_phi_D, MAT_FINAL_ASSEMBLY)); 5052ab2d12f3SJunchao Zhang } 505306656605SStefano Zampini } 505406656605SStefano Zampini } 50559de2952eSStefano Zampini for (i = 0; i < n_vertices; i++) PetscCall(MatSetValues(pcbddc->coarse_phi_B, 1, &idx_V_B[i], 1, &i, &one, INSERT_VALUES)); 50569de2952eSStefano Zampini PetscCall(MatAssemblyBegin(pcbddc->coarse_phi_B, MAT_FINAL_ASSEMBLY)); 50579de2952eSStefano Zampini PetscCall(MatAssemblyEnd(pcbddc->coarse_phi_B, MAT_FINAL_ASSEMBLY)); 50589de2952eSStefano Zampini } 50599de2952eSStefano Zampini PetscCall(MatDestroy(&A_RRmA_RV)); 50609de2952eSStefano Zampini } 50619566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RV)); 50629566063dSJacob Faibussowitsch PetscCall(VecDestroy(&dummy_vec)); 506306656605SStefano Zampini 506406656605SStefano Zampini if (n_constraints) { 50659de2952eSStefano Zampini Mat B, B2; 506606656605SStefano Zampini 50679566063dSJacob Faibussowitsch PetscCall(MatScale(S_CC, m_one)); 50689de2952eSStefano Zampini PetscCall(MatProductCreate(local_auxmat2_R, S_CC, NULL, &B)); 50699566063dSJacob Faibussowitsch PetscCall(MatProductSetType(B, MATPRODUCT_AB)); 50709566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(B)); 50719566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(B)); 50729566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(B)); 5073a961b312SStefano Zampini 507406656605SStefano Zampini if (n_vertices) { 507503dfb2d7SStefano Zampini if (isCHOL || need_benign_correction) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */ 50769de2952eSStefano Zampini PetscCall(MatTranspose(S_CV, MAT_INITIAL_MATRIX, &S_VC)); 507780677318SStefano Zampini } else { 5078ffd830a3SStefano Zampini if (lda_rhs != n_R) { 50799de2952eSStefano Zampini Mat tB; 508006656605SStefano Zampini 50819de2952eSStefano Zampini PetscCall(MatCreateSubMatrix(B, is_R, NULL, MAT_INITIAL_MATRIX, &tB)); 50829de2952eSStefano Zampini PetscCall(MatDestroy(&B)); 50839de2952eSStefano Zampini B = tB; 50849de2952eSStefano Zampini } 5085fb842aefSJose E. Roman PetscCall(MatMatMult(A_VR, B, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &S_VC)); 50869de2952eSStefano Zampini } 50879de2952eSStefano Zampini PetscCall(MatSetValuesSubMat(*coarse_submat, S_VC, n_vertices, idx_V, n_constraints, idx_C, INSERT_VALUES)); 50889de2952eSStefano Zampini } 50899de2952eSStefano Zampini 50909de2952eSStefano Zampini /* coarse basis functions */ 50919de2952eSStefano Zampini if (coarse_phi_multi) { 50929de2952eSStefano Zampini PetscCall(MatNestSetSubMat(coarse_phi_multi, 0, 1, B)); 50939de2952eSStefano Zampini } else { 50949de2952eSStefano Zampini PetscCall(MatDenseGetSubMatrix(pcbddc->coarse_phi_B, PETSC_DECIDE, PETSC_DECIDE, n_vertices, n_vertices + n_constraints, &B2)); 50959de2952eSStefano Zampini PetscCall(MatDenseScatter(B, pcbddc->R_to_B, B2)); 50969de2952eSStefano Zampini PetscCall(MatDenseRestoreSubMatrix(pcbddc->coarse_phi_B, &B2)); 509706656605SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 50989de2952eSStefano Zampini PetscCall(MatDenseGetSubMatrix(pcbddc->coarse_phi_D, PETSC_DECIDE, PETSC_DECIDE, n_vertices, n_vertices + n_constraints, &B2)); 50999de2952eSStefano Zampini PetscCall(MatDenseScatter(B, pcbddc->R_to_D, B2)); 51009de2952eSStefano Zampini if (pcbddc->benign_n) { 51013a7d0413SPierre Jolivet for (i = 0; i < n_constraints; i++) PetscCall(MatSetValues(B2, pcbddc->benign_n, p0_lidx_I, 1, &i, NULL, INSERT_VALUES)); 510206656605SStefano Zampini } 51039de2952eSStefano Zampini PetscCall(MatDenseRestoreSubMatrix(pcbddc->coarse_phi_D, &B2)); 510406656605SStefano Zampini } 510506656605SStefano Zampini } 51069de2952eSStefano Zampini PetscCall(MatDestroy(&B)); 51079de2952eSStefano Zampini } 51089de2952eSStefano Zampini 51099de2952eSStefano Zampini /* assemble sparse coarse basis functions */ 51109de2952eSStefano Zampini if (coarse_phi_multi) { 51119de2952eSStefano Zampini Mat T; 51129de2952eSStefano Zampini 51139de2952eSStefano Zampini PetscCall(MatConvert(coarse_phi_multi, MATSEQAIJ, MAT_INITIAL_MATRIX, &T)); 51149de2952eSStefano Zampini PetscCall(MatDestroy(&coarse_phi_multi)); 51159de2952eSStefano Zampini PetscCall(MatCreateSubMatrix(T, pcis->is_B_local, NULL, MAT_INITIAL_MATRIX, &pcbddc->coarse_phi_B)); 51163a7d0413SPierre Jolivet if (pcbddc->switch_static || pcbddc->dbg_flag) PetscCall(MatCreateSubMatrix(T, pcis->is_I_local, NULL, MAT_INITIAL_MATRIX, &pcbddc->coarse_phi_D)); 51179de2952eSStefano Zampini PetscCall(MatDestroy(&T)); 51189de2952eSStefano Zampini } 51199de2952eSStefano Zampini PetscCall(MatDestroy(&local_auxmat2_R)); 51209566063dSJacob Faibussowitsch PetscCall(PetscFree(p0_lidx_I)); 512172b8c272SStefano Zampini 512272b8c272SStefano Zampini /* coarse matrix entries relative to B_0 */ 512372b8c272SStefano Zampini if (pcbddc->benign_n) { 512472b8c272SStefano Zampini Mat B0_B, B0_BPHI; 512572b8c272SStefano Zampini IS is_dummy; 51261683a169SBarry Smith const PetscScalar *data; 512772b8c272SStefano Zampini PetscInt j; 512872b8c272SStefano Zampini 51299566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pcbddc->benign_n, 0, 1, &is_dummy)); 51309566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->benign_B0, is_dummy, pcis->is_B_local, MAT_INITIAL_MATRIX, &B0_B)); 51319566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_dummy)); 51329566063dSJacob Faibussowitsch PetscCall(MatMatMult(B0_B, pcbddc->coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &B0_BPHI)); 51339566063dSJacob Faibussowitsch PetscCall(MatConvert(B0_BPHI, MATSEQDENSE, MAT_INPLACE_MATRIX, &B0_BPHI)); 51349566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(B0_BPHI, &data)); 513572b8c272SStefano Zampini for (j = 0; j < pcbddc->benign_n; j++) { 513672b8c272SStefano Zampini PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j; 513772b8c272SStefano Zampini for (i = 0; i < pcbddc->local_primal_size; i++) { 51389de2952eSStefano Zampini PetscCall(MatSetValue(*coarse_submat, primal_idx, i, data[i * pcbddc->benign_n + j], INSERT_VALUES)); 51399de2952eSStefano Zampini PetscCall(MatSetValue(*coarse_submat, i, primal_idx, data[i * pcbddc->benign_n + j], INSERT_VALUES)); 514072b8c272SStefano Zampini } 514172b8c272SStefano Zampini } 51429566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(B0_BPHI, &data)); 51439566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B0_B)); 51449566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B0_BPHI)); 514572b8c272SStefano Zampini } 5146019a44ceSStefano Zampini 514706656605SStefano Zampini /* compute other basis functions for non-symmetric problems */ 51483301b35fSStefano Zampini if (!pcbddc->symmetric_primal) { 5149ffd830a3SStefano Zampini Mat B_V = NULL, B_C = NULL; 51509de2952eSStefano Zampini PetscScalar *marray, *work; 515106656605SStefano Zampini 51529de2952eSStefano Zampini /* TODO multi_element MatDenseScatter */ 515306656605SStefano Zampini if (n_constraints) { 5154ffd830a3SStefano Zampini Mat S_CCT, C_CRT; 515506656605SStefano Zampini 51569de2952eSStefano Zampini PetscCall(MatScale(S_CC, m_one)); 51579566063dSJacob Faibussowitsch PetscCall(MatTranspose(C_CR, MAT_INITIAL_MATRIX, &C_CRT)); 51589566063dSJacob Faibussowitsch PetscCall(MatTranspose(S_CC, MAT_INITIAL_MATRIX, &S_CCT)); 5159fb842aefSJose E. Roman PetscCall(MatMatMult(C_CRT, S_CCT, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &B_C)); 51609de2952eSStefano Zampini PetscCall(MatConvert(B_C, MATDENSE, MAT_INPLACE_MATRIX, &B_C)); 51619566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_CCT)); 516206656605SStefano Zampini if (n_vertices) { 5163ffd830a3SStefano Zampini Mat S_VCT; 516406656605SStefano Zampini 51659566063dSJacob Faibussowitsch PetscCall(MatTranspose(S_VC, MAT_INITIAL_MATRIX, &S_VCT)); 5166fb842aefSJose E. Roman PetscCall(MatMatMult(C_CRT, S_VCT, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &B_V)); 51679566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_VCT)); 51689de2952eSStefano Zampini PetscCall(MatConvert(B_V, MATDENSE, MAT_INPLACE_MATRIX, &B_V)); 516906656605SStefano Zampini } 51709566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C_CRT)); 51715b782168SStefano Zampini } else { 51729566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_R, n_vertices, NULL, &B_V)); 517306656605SStefano Zampini } 517416f15bc4SStefano Zampini if (n_vertices && n_R) { 5175ffd830a3SStefano Zampini PetscScalar *av, *marray; 5176ffd830a3SStefano Zampini const PetscInt *xadj, *adjncy; 5177ffd830a3SStefano Zampini PetscInt n; 5178ffd830a3SStefano Zampini PetscBool flg_row; 517906656605SStefano Zampini 5180ffd830a3SStefano Zampini /* B_V = B_V - A_VR^T */ 51819566063dSJacob Faibussowitsch PetscCall(MatConvert(A_VR, MATSEQAIJ, MAT_INPLACE_MATRIX, &A_VR)); 51829566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A_VR, 0, PETSC_FALSE, PETSC_FALSE, &n, &xadj, &adjncy, &flg_row)); 51839566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A_VR, &av)); 51849566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(B_V, &marray)); 5185ffd830a3SStefano Zampini for (i = 0; i < n; i++) { 5186ffd830a3SStefano Zampini PetscInt j; 5187ffd830a3SStefano Zampini for (j = xadj[i]; j < xadj[i + 1]; j++) marray[i * n_R + adjncy[j]] -= av[j]; 5188ffd830a3SStefano Zampini } 51899566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(B_V, &marray)); 51909566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A_VR, 0, PETSC_FALSE, PETSC_FALSE, &n, &xadj, &adjncy, &flg_row)); 51919566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_VR)); 519206656605SStefano Zampini } 519306656605SStefano Zampini 5194ffd830a3SStefano Zampini /* currently there's no support for MatTransposeMatSolve(F,B,X) */ 51959de2952eSStefano Zampini PetscCall(PetscMalloc1(n_R * pcbddc->local_primal_size, &work)); 5196abc8f43dSstefano_zampini if (n_vertices) { 51979566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(B_V, &marray)); 5198ffd830a3SStefano Zampini for (i = 0; i < n_vertices; i++) { 51999566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, marray + i * n_R)); 52009566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec2_R, work + i * n_R)); 52019566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec2_R)); 52029566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec2_R)); 52039566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 52049566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec2_R)); 520506656605SStefano Zampini } 52069566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(B_V, &marray)); 5207abc8f43dSstefano_zampini } 52085b782168SStefano Zampini if (B_C) { 52099566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(B_C, &marray)); 5210ffd830a3SStefano Zampini for (i = n_vertices; i < n_constraints + n_vertices; i++) { 52119566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, marray + (i - n_vertices) * n_R)); 52129566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec2_R, work + i * n_R)); 52139566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec2_R)); 52149566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec2_R)); 52159566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 52169566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec2_R)); 521706656605SStefano Zampini } 52189566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(B_C, &marray)); 52195b782168SStefano Zampini } 522006656605SStefano Zampini /* coarse basis functions */ 52219de2952eSStefano Zampini PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_B, pcbddc->local_primal_size, NULL, &pcbddc->coarse_psi_B)); 52229de2952eSStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_D, pcbddc->local_primal_size, NULL, &pcbddc->coarse_psi_D)); 522306656605SStefano Zampini for (i = 0; i < pcbddc->local_primal_size; i++) { 5224ab2d12f3SJunchao Zhang Vec v; 522506656605SStefano Zampini 52269566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, work + i * n_R)); 52279566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVec(pcbddc->coarse_psi_B, i, &v)); 52289566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 52299566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 523006656605SStefano Zampini if (i < n_vertices) { 5231ab2d12f3SJunchao Zhang PetscScalar one = 1.0; 52329566063dSJacob Faibussowitsch PetscCall(VecSetValues(v, 1, &idx_V_B[i], &one, INSERT_VALUES)); 52339566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(v)); 52349566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(v)); 523506656605SStefano Zampini } 52369566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_psi_B, i, &v)); 523706656605SStefano Zampini 523806656605SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 52399566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVec(pcbddc->coarse_psi_D, i, &v)); 52409566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_D, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 52419566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_D, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 52429566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_psi_D, i, &v)); 524306656605SStefano Zampini } 52449566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 524506656605SStefano Zampini } 52469566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B_V)); 52479566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B_C)); 52489de2952eSStefano Zampini PetscCall(PetscFree(work)); 52499de2952eSStefano Zampini } else { 52509de2952eSStefano Zampini PetscCall(PetscObjectReference((PetscObject)pcbddc->coarse_phi_B)); 52519de2952eSStefano Zampini pcbddc->coarse_psi_B = pcbddc->coarse_phi_B; 52529de2952eSStefano Zampini PetscCall(PetscObjectReference((PetscObject)pcbddc->coarse_phi_D)); 52539de2952eSStefano Zampini pcbddc->coarse_psi_D = pcbddc->coarse_phi_D; 525406656605SStefano Zampini } 52559de2952eSStefano Zampini PetscCall(MatAssemblyBegin(*coarse_submat, MAT_FINAL_ASSEMBLY)); 52569de2952eSStefano Zampini PetscCall(MatAssemblyEnd(*coarse_submat, MAT_FINAL_ASSEMBLY)); 5257a6e023c1Sstefano_zampini 5258d62866d3SStefano Zampini /* free memory */ 52599de2952eSStefano Zampini PetscCall(PetscFree(V_to_eff_V)); 52609de2952eSStefano Zampini PetscCall(PetscFree(C_to_eff_C)); 52619de2952eSStefano Zampini PetscCall(PetscFree(R_eff_V_J)); 52629de2952eSStefano Zampini PetscCall(PetscFree(R_eff_C_J)); 52639de2952eSStefano Zampini PetscCall(PetscFree(B_eff_V_J)); 52649de2952eSStefano Zampini PetscCall(PetscFree(B_eff_C_J)); 52659de2952eSStefano Zampini PetscCall(ISDestroy(&is_R)); 52669de2952eSStefano Zampini PetscCall(ISRestoreIndices(is_V, &idx_V)); 52679de2952eSStefano Zampini PetscCall(ISRestoreIndices(is_C, &idx_C)); 52689de2952eSStefano Zampini PetscCall(ISDestroy(&is_V)); 52699de2952eSStefano Zampini PetscCall(ISDestroy(&is_C)); 52709566063dSJacob Faibussowitsch PetscCall(PetscFree(idx_V_B)); 52719566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_CV)); 52729566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_VC)); 52739566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_CC)); 527448a46eb9SPierre Jolivet if (n_vertices) PetscCall(MatDestroy(&A_VR)); 527548a46eb9SPierre Jolivet if (n_constraints) PetscCall(MatDestroy(&C_CR)); 52769566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_CorrectionSetUp[pcbddc->current_level], pc, 0, 0, 0)); 52778ead10e4SStefano Zampini 5278da81f932SPierre Jolivet /* Checking coarse_sub_mat and coarse basis functions */ 527988ebb749SStefano Zampini /* Symmetric case : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */ 528088ebb749SStefano Zampini /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */ 5281d12edf2fSStefano Zampini if (pcbddc->dbg_flag) { 528225084f0cSStefano Zampini Mat AUXMAT, TM1, TM2, TM3, TM4; 528388ebb749SStefano Zampini Mat coarse_phi_D, coarse_phi_B; 528488ebb749SStefano Zampini Mat coarse_psi_D, coarse_psi_B; 528588ebb749SStefano Zampini Mat A_II, A_BB, A_IB, A_BI; 52868bec7fa6SStefano Zampini Mat C_B, CPHI; 52878bec7fa6SStefano Zampini IS is_dummy; 52888bec7fa6SStefano Zampini Vec mones; 528988ebb749SStefano Zampini MatType checkmattype = MATSEQAIJ; 529088ebb749SStefano Zampini PetscReal real_value; 529188ebb749SStefano Zampini 5292a3df083aSStefano Zampini if (pcbddc->benign_n && !pcbddc->benign_change_explicit) { 5293a3df083aSStefano Zampini Mat A; 52949566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignProject(pc, NULL, NULL, &A)); 52959566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, pcis->is_I_local, pcis->is_I_local, MAT_INITIAL_MATRIX, &A_II)); 52969566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, pcis->is_I_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &A_IB)); 52979566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, pcis->is_B_local, pcis->is_I_local, MAT_INITIAL_MATRIX, &A_BI)); 52989566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, pcis->is_B_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &A_BB)); 52999566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 5300a3df083aSStefano Zampini } else { 53019566063dSJacob Faibussowitsch PetscCall(MatConvert(pcis->A_II, checkmattype, MAT_INITIAL_MATRIX, &A_II)); 53029566063dSJacob Faibussowitsch PetscCall(MatConvert(pcis->A_IB, checkmattype, MAT_INITIAL_MATRIX, &A_IB)); 53039566063dSJacob Faibussowitsch PetscCall(MatConvert(pcis->A_BI, checkmattype, MAT_INITIAL_MATRIX, &A_BI)); 53049566063dSJacob Faibussowitsch PetscCall(MatConvert(pcis->A_BB, checkmattype, MAT_INITIAL_MATRIX, &A_BB)); 5305a3df083aSStefano Zampini } 53069566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->coarse_phi_D, checkmattype, MAT_INITIAL_MATRIX, &coarse_phi_D)); 53079566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->coarse_phi_B, checkmattype, MAT_INITIAL_MATRIX, &coarse_phi_B)); 5308ffd830a3SStefano Zampini if (!pcbddc->symmetric_primal) { 53099566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->coarse_psi_D, checkmattype, MAT_INITIAL_MATRIX, &coarse_psi_D)); 53109566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->coarse_psi_B, checkmattype, MAT_INITIAL_MATRIX, &coarse_psi_B)); 531188ebb749SStefano Zampini } 53129566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 53139566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Check coarse sub mat computation (symmetric %d)\n", pcbddc->symmetric_primal)); 53149566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 5315ffd830a3SStefano Zampini if (!pcbddc->symmetric_primal) { 53169566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_II, coarse_phi_D, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 53179566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_psi_D, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM1)); 53189566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 53199566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_BB, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 53209566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_psi_B, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM2)); 53219566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 53229566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_IB, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 53239566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_psi_D, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM3)); 53249566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 53259566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_BI, coarse_phi_D, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 53269566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_psi_B, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM4)); 53279566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 532888ebb749SStefano Zampini } else { 53299566063dSJacob Faibussowitsch PetscCall(MatPtAP(A_II, coarse_phi_D, MAT_INITIAL_MATRIX, 1.0, &TM1)); 53309566063dSJacob Faibussowitsch PetscCall(MatPtAP(A_BB, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &TM2)); 53319566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_IB, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 53329566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_phi_D, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM3)); 53339566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 53349566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_BI, coarse_phi_D, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 53359566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_phi_B, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM4)); 53369566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 533788ebb749SStefano Zampini } 53389566063dSJacob Faibussowitsch PetscCall(MatAXPY(TM1, one, TM2, DIFFERENT_NONZERO_PATTERN)); 53399566063dSJacob Faibussowitsch PetscCall(MatAXPY(TM1, one, TM3, DIFFERENT_NONZERO_PATTERN)); 53409566063dSJacob Faibussowitsch PetscCall(MatAXPY(TM1, one, TM4, DIFFERENT_NONZERO_PATTERN)); 53419566063dSJacob Faibussowitsch PetscCall(MatConvert(TM1, MATSEQDENSE, MAT_INPLACE_MATRIX, &TM1)); 53424f1b2e48SStefano Zampini if (pcbddc->benign_n) { 5343fc227af8SStefano Zampini Mat B0_B, B0_BPHI; 53441683a169SBarry Smith const PetscScalar *data2; 53451683a169SBarry Smith PetscScalar *data; 53464f1b2e48SStefano Zampini PetscInt j; 5347d12edf2fSStefano Zampini 53489566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pcbddc->benign_n, 0, 1, &is_dummy)); 53499566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->benign_B0, is_dummy, pcis->is_B_local, MAT_INITIAL_MATRIX, &B0_B)); 53509566063dSJacob Faibussowitsch PetscCall(MatMatMult(B0_B, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &B0_BPHI)); 53519566063dSJacob Faibussowitsch PetscCall(MatConvert(B0_BPHI, MATSEQDENSE, MAT_INPLACE_MATRIX, &B0_BPHI)); 53529566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(TM1, &data)); 53539566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(B0_BPHI, &data2)); 53544f1b2e48SStefano Zampini for (j = 0; j < pcbddc->benign_n; j++) { 53554f1b2e48SStefano Zampini PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j; 5356d12edf2fSStefano Zampini for (i = 0; i < pcbddc->local_primal_size; i++) { 53574f1b2e48SStefano Zampini data[primal_idx * pcbddc->local_primal_size + i] += data2[i * pcbddc->benign_n + j]; 53584f1b2e48SStefano Zampini data[i * pcbddc->local_primal_size + primal_idx] += data2[i * pcbddc->benign_n + j]; 53594f1b2e48SStefano Zampini } 5360d12edf2fSStefano Zampini } 53619566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(TM1, &data)); 53629566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(B0_BPHI, &data2)); 53639566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B0_B)); 53649566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_dummy)); 53659566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B0_BPHI)); 5366d12edf2fSStefano Zampini } 53679de2952eSStefano Zampini PetscCall(MatAXPY(TM1, m_one, *coarse_submat, DIFFERENT_NONZERO_PATTERN)); 53689566063dSJacob Faibussowitsch PetscCall(MatNorm(TM1, NORM_FROBENIUS, &real_value)); 53699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 537063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d matrix error % 1.14e\n", PetscGlobalRank, (double)real_value)); 53718bec7fa6SStefano Zampini 53728bec7fa6SStefano Zampini /* check constraints */ 53739566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pcbddc->local_primal_size - pcbddc->benign_n, 0, 1, &is_dummy)); 53749566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->ConstraintMatrix, is_dummy, pcis->is_B_local, MAT_INITIAL_MATRIX, &C_B)); 53754f1b2e48SStefano Zampini if (!pcbddc->benign_n) { /* TODO: add benign case */ 53769566063dSJacob Faibussowitsch PetscCall(MatMatMult(C_B, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &CPHI)); 5377a00504b5SStefano Zampini } else { 5378a00504b5SStefano Zampini PetscScalar *data; 5379a00504b5SStefano Zampini Mat tmat; 53809566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(pcbddc->coarse_phi_B, &data)); 53819566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, pcis->n_B, pcbddc->local_primal_size - pcbddc->benign_n, data, &tmat)); 53829566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(pcbddc->coarse_phi_B, &data)); 53839566063dSJacob Faibussowitsch PetscCall(MatMatMult(C_B, tmat, MAT_INITIAL_MATRIX, 1.0, &CPHI)); 53849566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tmat)); 5385a00504b5SStefano Zampini } 53869566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(CPHI, &mones, NULL)); 53879566063dSJacob Faibussowitsch PetscCall(VecSet(mones, -1.0)); 53889566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(CPHI, mones, ADD_VALUES)); 53899566063dSJacob Faibussowitsch PetscCall(MatNorm(CPHI, NORM_FROBENIUS, &real_value)); 539063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d phi constraints error % 1.14e\n", PetscGlobalRank, (double)real_value)); 5391ffd830a3SStefano Zampini if (!pcbddc->symmetric_primal) { 53929566063dSJacob Faibussowitsch PetscCall(MatMatMult(C_B, coarse_psi_B, MAT_REUSE_MATRIX, 1.0, &CPHI)); 53939566063dSJacob Faibussowitsch PetscCall(VecSet(mones, -1.0)); 53949566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(CPHI, mones, ADD_VALUES)); 53959566063dSJacob Faibussowitsch PetscCall(MatNorm(CPHI, NORM_FROBENIUS, &real_value)); 539663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d psi constraints error % 1.14e\n", PetscGlobalRank, (double)real_value)); 539788ebb749SStefano Zampini } 53989566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C_B)); 53999566063dSJacob Faibussowitsch PetscCall(MatDestroy(&CPHI)); 54009566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_dummy)); 54019566063dSJacob Faibussowitsch PetscCall(VecDestroy(&mones)); 54029566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 54039566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_II)); 54049566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_BB)); 54059566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_IB)); 54069566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_BI)); 54079566063dSJacob Faibussowitsch PetscCall(MatDestroy(&TM1)); 54089566063dSJacob Faibussowitsch PetscCall(MatDestroy(&TM2)); 54099566063dSJacob Faibussowitsch PetscCall(MatDestroy(&TM3)); 54109566063dSJacob Faibussowitsch PetscCall(MatDestroy(&TM4)); 54119566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_phi_D)); 54129566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_phi_B)); 5413ffd830a3SStefano Zampini if (!pcbddc->symmetric_primal) { 54149566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_psi_D)); 54159566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_psi_B)); 541688ebb749SStefano Zampini } 541788ebb749SStefano Zampini } 54187ebab0bbSStefano Zampini 54199de2952eSStefano Zampini #if 0 54209de2952eSStefano Zampini { 54219de2952eSStefano Zampini PetscViewer viewer; 54229de2952eSStefano Zampini char filename[256]; 54239de2952eSStefano Zampini 54249de2952eSStefano Zampini PetscCall(PetscSNPrintf(filename, PETSC_STATIC_ARRAY_LENGTH(filename), "details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level)); 54259de2952eSStefano Zampini PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer)); 54269de2952eSStefano Zampini PetscCall(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB)); 54279de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)*coarse_submat,"coarse submat")); 54289de2952eSStefano Zampini PetscCall(MatView(*coarse_submat,viewer)); 54299de2952eSStefano Zampini if (pcbddc->coarse_phi_B) { 54309de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B")); 54319de2952eSStefano Zampini PetscCall(MatView(pcbddc->coarse_phi_B,viewer)); 54329de2952eSStefano Zampini } 54339de2952eSStefano Zampini if (pcbddc->coarse_phi_D) { 54349de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D")); 54359de2952eSStefano Zampini PetscCall(MatView(pcbddc->coarse_phi_D,viewer)); 54369de2952eSStefano Zampini } 54379de2952eSStefano Zampini if (pcbddc->coarse_psi_B) { 54389de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B")); 54399de2952eSStefano Zampini PetscCall(MatView(pcbddc->coarse_psi_B,viewer)); 54409de2952eSStefano Zampini } 54419de2952eSStefano Zampini if (pcbddc->coarse_psi_D) { 54429de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D")); 54439de2952eSStefano Zampini PetscCall(MatView(pcbddc->coarse_psi_D,viewer)); 54449de2952eSStefano Zampini } 54459de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcbddc->local_mat,"A")); 54469de2952eSStefano Zampini PetscCall(MatView(pcbddc->local_mat,viewer)); 54479de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcbddc->ConstraintMatrix,"C")); 54489de2952eSStefano Zampini PetscCall(MatView(pcbddc->ConstraintMatrix,viewer)); 54499de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcis->is_I_local,"I")); 54509de2952eSStefano Zampini PetscCall(ISView(pcis->is_I_local,viewer)); 54519de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcis->is_B_local,"B")); 54529de2952eSStefano Zampini PetscCall(ISView(pcis->is_B_local,viewer)); 54539de2952eSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcbddc->is_R_local,"R")); 54549de2952eSStefano Zampini PetscCall(ISView(pcbddc->is_R_local,viewer)); 5455648c30bcSBarry Smith PetscCall(PetscViewerDestroy(&viewer)); 54569de2952eSStefano Zampini } 54579de2952eSStefano Zampini #endif 54589de2952eSStefano Zampini 54599de2952eSStefano Zampini /* device support */ 54609de2952eSStefano Zampini { 54619de2952eSStefano Zampini PetscBool iscuda, iship, iskokkos; 54629de2952eSStefano Zampini MatType mtype = NULL; 54639de2952eSStefano Zampini 54649de2952eSStefano Zampini PetscCall(PetscObjectTypeCompareAny((PetscObject)pcis->vec1_N, &iscuda, VECCUDA, VECMPICUDA, VECSEQCUDA, "")); 54659de2952eSStefano Zampini PetscCall(PetscObjectTypeCompareAny((PetscObject)pcis->vec1_N, &iship, VECHIP, VECMPIHIP, VECSEQHIP, "")); 54669de2952eSStefano Zampini PetscCall(PetscObjectTypeCompareAny((PetscObject)pcis->vec1_N, &iskokkos, VECKOKKOS, VECMPIKOKKOS, VECSEQKOKKOS, "")); 54679de2952eSStefano Zampini if (iskokkos) { 54689de2952eSStefano Zampini if (PetscDefined(HAVE_MACRO_KOKKOS_ENABLE_CUDA)) iscuda = PETSC_TRUE; 54699de2952eSStefano Zampini else if (PetscDefined(HAVE_MACRO_KOKKOS_ENABLE_HIP)) iship = PETSC_TRUE; 54709de2952eSStefano Zampini } 54719de2952eSStefano Zampini if (iskokkos) mtype = multi_element ? MATSEQAIJKOKKOS : (iscuda ? MATSEQDENSECUDA : MATSEQDENSEHIP); 54729de2952eSStefano Zampini else if (iship) mtype = multi_element ? MATSEQAIJHIPSPARSE : MATSEQDENSEHIP; 54739de2952eSStefano Zampini else if (iscuda) mtype = multi_element ? MATSEQAIJCUSPARSE : MATSEQDENSECUDA; 54749de2952eSStefano Zampini if (mtype) { 54759de2952eSStefano Zampini if (pcbddc->local_auxmat1) PetscCall(MatConvert(pcbddc->local_auxmat1, mtype, MAT_INPLACE_MATRIX, &pcbddc->local_auxmat1)); 54769de2952eSStefano Zampini if (pcbddc->local_auxmat2) PetscCall(MatConvert(pcbddc->local_auxmat2, mtype, MAT_INPLACE_MATRIX, &pcbddc->local_auxmat2)); 54779de2952eSStefano Zampini if (pcbddc->coarse_phi_B) PetscCall(MatConvert(pcbddc->coarse_phi_B, mtype, MAT_INPLACE_MATRIX, &pcbddc->coarse_phi_B)); 54789de2952eSStefano Zampini if (pcbddc->coarse_phi_D) PetscCall(MatConvert(pcbddc->coarse_phi_D, mtype, MAT_INPLACE_MATRIX, &pcbddc->coarse_phi_D)); 54799de2952eSStefano Zampini if (pcbddc->coarse_psi_B) PetscCall(MatConvert(pcbddc->coarse_psi_B, mtype, MAT_INPLACE_MATRIX, &pcbddc->coarse_psi_B)); 54809de2952eSStefano Zampini if (pcbddc->coarse_psi_D) PetscCall(MatConvert(pcbddc->coarse_psi_D, mtype, MAT_INPLACE_MATRIX, &pcbddc->coarse_psi_D)); 54817ebab0bbSStefano Zampini } 54827ebab0bbSStefano Zampini } 54833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 548488ebb749SStefano Zampini } 548588ebb749SStefano Zampini 5486d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat *B) 5487d71ae5a4SJacob Faibussowitsch { 5488d65f70fdSStefano Zampini Mat *work_mat; 5489d65f70fdSStefano Zampini IS isrow_s, iscol_s; 5490d65f70fdSStefano Zampini PetscBool rsorted, csorted; 5491c43ebad9SStefano Zampini PetscInt rsize, *idxs_perm_r = NULL, csize, *idxs_perm_c = NULL; 5492aa0d41d4SStefano Zampini 5493aa0d41d4SStefano Zampini PetscFunctionBegin; 54949566063dSJacob Faibussowitsch PetscCall(ISSorted(isrow, &rsorted)); 54959566063dSJacob Faibussowitsch PetscCall(ISSorted(iscol, &csorted)); 54969566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isrow, &rsize)); 54979566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(iscol, &csize)); 5498aa0d41d4SStefano Zampini 5499d65f70fdSStefano Zampini if (!rsorted) { 5500906d46d4SStefano Zampini const PetscInt *idxs; 5501906d46d4SStefano Zampini PetscInt *idxs_sorted, i; 5502aa0d41d4SStefano Zampini 55039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rsize, &idxs_perm_r)); 55049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rsize, &idxs_sorted)); 5505ad540459SPierre Jolivet for (i = 0; i < rsize; i++) idxs_perm_r[i] = i; 55069566063dSJacob Faibussowitsch PetscCall(ISGetIndices(isrow, &idxs)); 55079566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithPermutation(rsize, idxs, idxs_perm_r)); 5508ad540459SPierre Jolivet for (i = 0; i < rsize; i++) idxs_sorted[i] = idxs[idxs_perm_r[i]]; 55099566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(isrow, &idxs)); 55109566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, rsize, idxs_sorted, PETSC_OWN_POINTER, &isrow_s)); 5511d65f70fdSStefano Zampini } else { 55129566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)isrow)); 5513d65f70fdSStefano Zampini isrow_s = isrow; 5514aa0d41d4SStefano Zampini } 5515906d46d4SStefano Zampini 5516d65f70fdSStefano Zampini if (!csorted) { 5517d65f70fdSStefano Zampini if (isrow == iscol) { 55189566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)isrow_s)); 5519d65f70fdSStefano Zampini iscol_s = isrow_s; 5520d65f70fdSStefano Zampini } else { 5521d65f70fdSStefano Zampini const PetscInt *idxs; 5522d65f70fdSStefano Zampini PetscInt *idxs_sorted, i; 5523906d46d4SStefano Zampini 55249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(csize, &idxs_perm_c)); 55259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(csize, &idxs_sorted)); 5526ad540459SPierre Jolivet for (i = 0; i < csize; i++) idxs_perm_c[i] = i; 55279566063dSJacob Faibussowitsch PetscCall(ISGetIndices(iscol, &idxs)); 55289566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithPermutation(csize, idxs, idxs_perm_c)); 5529ad540459SPierre Jolivet for (i = 0; i < csize; i++) idxs_sorted[i] = idxs[idxs_perm_c[i]]; 55309566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(iscol, &idxs)); 55319566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, csize, idxs_sorted, PETSC_OWN_POINTER, &iscol_s)); 5532d65f70fdSStefano Zampini } 5533d65f70fdSStefano Zampini } else { 55349566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)iscol)); 5535d65f70fdSStefano Zampini iscol_s = iscol; 5536d65f70fdSStefano Zampini } 5537d65f70fdSStefano Zampini 55389566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(A, 1, &isrow_s, &iscol_s, MAT_INITIAL_MATRIX, &work_mat)); 5539d65f70fdSStefano Zampini 5540d65f70fdSStefano Zampini if (!rsorted || !csorted) { 5541906d46d4SStefano Zampini Mat new_mat; 5542d65f70fdSStefano Zampini IS is_perm_r, is_perm_c; 5543906d46d4SStefano Zampini 5544d65f70fdSStefano Zampini if (!rsorted) { 5545d65f70fdSStefano Zampini PetscInt *idxs_r, i; 55469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rsize, &idxs_r)); 5547ad540459SPierre Jolivet for (i = 0; i < rsize; i++) idxs_r[idxs_perm_r[i]] = i; 55489566063dSJacob Faibussowitsch PetscCall(PetscFree(idxs_perm_r)); 55499566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, rsize, idxs_r, PETSC_OWN_POINTER, &is_perm_r)); 5550d65f70fdSStefano Zampini } else { 55519566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, rsize, 0, 1, &is_perm_r)); 5552906d46d4SStefano Zampini } 55539566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(is_perm_r)); 5554d65f70fdSStefano Zampini 5555d65f70fdSStefano Zampini if (!csorted) { 5556d65f70fdSStefano Zampini if (isrow_s == iscol_s) { 55579566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is_perm_r)); 5558d65f70fdSStefano Zampini is_perm_c = is_perm_r; 5559d65f70fdSStefano Zampini } else { 5560d65f70fdSStefano Zampini PetscInt *idxs_c, i; 556128b400f6SJacob Faibussowitsch PetscCheck(idxs_perm_c, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Permutation array not present"); 55629566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(csize, &idxs_c)); 5563ad540459SPierre Jolivet for (i = 0; i < csize; i++) idxs_c[idxs_perm_c[i]] = i; 55649566063dSJacob Faibussowitsch PetscCall(PetscFree(idxs_perm_c)); 55659566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, csize, idxs_c, PETSC_OWN_POINTER, &is_perm_c)); 5566d65f70fdSStefano Zampini } 5567d65f70fdSStefano Zampini } else { 55689566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, csize, 0, 1, &is_perm_c)); 5569d65f70fdSStefano Zampini } 55709566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(is_perm_c)); 5571d65f70fdSStefano Zampini 55729566063dSJacob Faibussowitsch PetscCall(MatPermute(work_mat[0], is_perm_r, is_perm_c, &new_mat)); 55739566063dSJacob Faibussowitsch PetscCall(MatDestroy(&work_mat[0])); 5574d65f70fdSStefano Zampini work_mat[0] = new_mat; 55759566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_perm_r)); 55769566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_perm_c)); 5577d65f70fdSStefano Zampini } 5578d65f70fdSStefano Zampini 55799566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)work_mat[0])); 5580d65f70fdSStefano Zampini *B = work_mat[0]; 55819566063dSJacob Faibussowitsch PetscCall(MatDestroyMatrices(1, &work_mat)); 55829566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isrow_s)); 55839566063dSJacob Faibussowitsch PetscCall(ISDestroy(&iscol_s)); 55843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5585d65f70fdSStefano Zampini } 5586d65f70fdSStefano Zampini 55877b103a85SStefano Zampini static PetscErrorCode MatPtAPWithPrefix_Private(Mat A, Mat P, PetscReal fill, const char *prefix, Mat *C) 55887b103a85SStefano Zampini { 55897b103a85SStefano Zampini PetscFunctionBegin; 55907b103a85SStefano Zampini PetscCall(MatProductCreate(A, P, NULL, C)); 55917b103a85SStefano Zampini PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 55927b103a85SStefano Zampini PetscCall(MatProductSetAlgorithm(*C, "default")); 55937b103a85SStefano Zampini PetscCall(MatProductSetFill(*C, fill)); 55947b103a85SStefano Zampini PetscCall(MatSetOptionsPrefix(*C, prefix)); 55957b103a85SStefano Zampini PetscCall(MatProductSetFromOptions(*C)); 55967b103a85SStefano Zampini PetscCall(MatProductSymbolic(*C)); 55977b103a85SStefano Zampini PetscCall(MatProductNumeric(*C)); 55987b103a85SStefano Zampini (*C)->symmetric = A->symmetric; 55997b103a85SStefano Zampini (*C)->spd = A->spd; 56007b103a85SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 56017b103a85SStefano Zampini } 56027b103a85SStefano Zampini 5603d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix) 5604d71ae5a4SJacob Faibussowitsch { 5605aa0d41d4SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 56065e8657edSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 5607022d8d2bSstefano_zampini Mat new_mat, lA; 56085e8657edSStefano Zampini IS is_local, is_global; 5609d65f70fdSStefano Zampini PetscInt local_size; 5610b94d7dedSBarry Smith PetscBool isseqaij, issym, isset; 56117b103a85SStefano Zampini char ptapprefix[256]; 5612aa0d41d4SStefano Zampini 5613aa0d41d4SStefano Zampini PetscFunctionBegin; 56149566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 56159566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A, &local_size, NULL)); 56169de2952eSStefano Zampini if (pcbddc->mat_graph->multi_element) { 56179de2952eSStefano Zampini Mat *mats, *bdiags; 56189de2952eSStefano Zampini IS *gsubs; 56199de2952eSStefano Zampini PetscInt nsubs = pcbddc->n_local_subs; 56209de2952eSStefano Zampini 56219de2952eSStefano Zampini PetscCall(PetscCalloc1(nsubs * nsubs, &mats)); 56227b103a85SStefano Zampini #if 1 56239de2952eSStefano Zampini PetscCall(PetscMalloc1(nsubs, &gsubs)); 56249de2952eSStefano Zampini for (PetscInt i = 0; i < nsubs; i++) PetscCall(ISLocalToGlobalMappingApplyIS(matis->rmapping, pcbddc->local_subs[i], &gsubs[i])); 56259de2952eSStefano Zampini PetscCall(MatCreateSubMatrices(ChangeOfBasisMatrix, nsubs, gsubs, gsubs, MAT_INITIAL_MATRIX, &bdiags)); 56269de2952eSStefano Zampini for (PetscInt i = 0; i < nsubs; i++) PetscCall(ISDestroy(&gsubs[i])); 56279de2952eSStefano Zampini PetscCall(PetscFree(gsubs)); 56287b103a85SStefano Zampini #else /* this does not work since MatCreateSubMatrices does not support repeated indices */ 56297b103a85SStefano Zampini Mat *tmats; 56307b103a85SStefano Zampini PetscCall(ISCreateStride(PetscObjectComm((PetscObject)matis->A), local_size, 0, 1, &is_local)); 56317b103a85SStefano Zampini PetscCall(ISLocalToGlobalMappingApplyIS(matis->rmapping, is_local, &is_global)); 56327b103a85SStefano Zampini PetscCall(ISDestroy(&is_local)); 56337b103a85SStefano Zampini PetscCall(MatSetOption(ChangeOfBasisMatrix, MAT_SUBMAT_SINGLEIS, PETSC_TRUE)); 56347b103a85SStefano Zampini PetscCall(MatCreateSubMatrices(ChangeOfBasisMatrix, 1, &is_global, &is_global, MAT_INITIAL_MATRIX, &tmats)); 56357b103a85SStefano Zampini PetscCall(ISDestroy(&is_global)); 56367b103a85SStefano Zampini PetscCall(MatCreateSubMatrices(tmats[0], nsubs, pcbddc->local_subs, pcbddc->local_subs, MAT_INITIAL_MATRIX, &bdiags)); 56377b103a85SStefano Zampini PetscCall(MatDestroySubMatrices(1, &tmats)); 56387b103a85SStefano Zampini #endif 56399de2952eSStefano Zampini for (PetscInt i = 0; i < nsubs; i++) mats[i * (1 + nsubs)] = bdiags[i]; 56409de2952eSStefano Zampini PetscCall(MatCreateNest(PETSC_COMM_SELF, nsubs, pcbddc->local_subs, nsubs, pcbddc->local_subs, mats, &new_mat)); 56419de2952eSStefano Zampini PetscCall(MatConvert(new_mat, MATSEQAIJ, MAT_INPLACE_MATRIX, &new_mat)); 56429de2952eSStefano Zampini PetscCall(MatDestroySubMatrices(nsubs, &bdiags)); 56439de2952eSStefano Zampini PetscCall(PetscFree(mats)); 56449de2952eSStefano Zampini } else { 56459566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)matis->A), local_size, 0, 1, &is_local)); 56469566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(matis->rmapping, is_local, &is_global)); 56479566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_local)); 56489566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrixUnsorted(ChangeOfBasisMatrix, is_global, is_global, &new_mat)); 56499566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_global)); 56509de2952eSStefano Zampini } 5651906d46d4SStefano Zampini if (pcbddc->dbg_flag) { 5652906d46d4SStefano Zampini Vec x, x_change; 5653906d46d4SStefano Zampini PetscReal error; 5654906d46d4SStefano Zampini 56559566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(ChangeOfBasisMatrix, &x, &x_change)); 56569566063dSJacob Faibussowitsch PetscCall(VecSetRandom(x, NULL)); 56579566063dSJacob Faibussowitsch PetscCall(MatMult(ChangeOfBasisMatrix, x, x_change)); 56589566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->cctx, x, matis->x, INSERT_VALUES, SCATTER_FORWARD)); 56599566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->cctx, x, matis->x, INSERT_VALUES, SCATTER_FORWARD)); 56609566063dSJacob Faibussowitsch PetscCall(MatMult(new_mat, matis->x, matis->y)); 566188428137SStefano Zampini if (!pcbddc->change_interior) { 566288428137SStefano Zampini const PetscScalar *x, *y, *v; 566388428137SStefano Zampini PetscReal lerror = 0.; 566488428137SStefano Zampini PetscInt i; 566588428137SStefano Zampini 56669566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(matis->x, &x)); 56679566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(matis->y, &y)); 56689566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(matis->counter, &v)); 566988428137SStefano Zampini for (i = 0; i < local_size; i++) 56709371c9d4SSatish Balay if (PetscRealPart(v[i]) < 1.5 && PetscAbsScalar(x[i] - y[i]) > lerror) lerror = PetscAbsScalar(x[i] - y[i]); 56719566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(matis->x, &x)); 56729566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(matis->y, &y)); 56739566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(matis->counter, &v)); 5674462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&lerror, &error, 1, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)pc))); 5675637e8532SStefano Zampini if (error > PETSC_SMALL) { 5676637e8532SStefano Zampini if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) { 567763a3b9bcSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_PLIB, "Error global vs local change on I: %1.6e", (double)error); 5678637e8532SStefano Zampini } else { 567963a3b9bcSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "Error global vs local change on I: %1.6e", (double)error); 5680637e8532SStefano Zampini } 5681637e8532SStefano Zampini } 568288428137SStefano Zampini } 56839566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, matis->y, x, INSERT_VALUES, SCATTER_REVERSE)); 56849566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, matis->y, x, INSERT_VALUES, SCATTER_REVERSE)); 56859566063dSJacob Faibussowitsch PetscCall(VecAXPY(x, -1.0, x_change)); 56869566063dSJacob Faibussowitsch PetscCall(VecNorm(x, NORM_INFINITY, &error)); 5687637e8532SStefano Zampini if (error > PETSC_SMALL) { 5688637e8532SStefano Zampini if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) { 568963a3b9bcSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_PLIB, "Error global vs local change on N: %1.6e", (double)error); 5690637e8532SStefano Zampini } else { 569163a3b9bcSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "Error global vs local change on N: %1.6e", (double)error); 5692637e8532SStefano Zampini } 5693637e8532SStefano Zampini } 56949566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 56959566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x_change)); 5696906d46d4SStefano Zampini } 5697906d46d4SStefano Zampini 5698022d8d2bSstefano_zampini /* lA is present if we are setting up an inner BDDC for a saddle point FETI-DP */ 56999566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lA", (PetscObject *)&lA)); 5700022d8d2bSstefano_zampini 570122d5777bSStefano Zampini /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */ 57027b103a85SStefano Zampini if (((PetscObject)pc)->prefix) PetscCall(PetscSNPrintf(ptapprefix, sizeof(ptapprefix), "%spc_bddc_change_", ((PetscObject)pc)->prefix)); 57037b103a85SStefano Zampini else PetscCall(PetscSNPrintf(ptapprefix, sizeof(ptapprefix), "pc_bddc_change_")); 57049566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQAIJ, &isseqaij)); 570522d5777bSStefano Zampini if (isseqaij) { 57069566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 57077b103a85SStefano Zampini PetscCall(MatPtAPWithPrefix_Private(matis->A, new_mat, PETSC_DEFAULT, ptapprefix, &pcbddc->local_mat)); 5708022d8d2bSstefano_zampini if (lA) { 5709022d8d2bSstefano_zampini Mat work; 57107b103a85SStefano Zampini PetscCall(MatPtAPWithPrefix_Private(lA, new_mat, PETSC_DEFAULT, ptapprefix, &work)); 57119566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_lA", (PetscObject)work)); 57129566063dSJacob Faibussowitsch PetscCall(MatDestroy(&work)); 5713022d8d2bSstefano_zampini } 5714aa0d41d4SStefano Zampini } else { 5715a00504b5SStefano Zampini Mat work_mat; 57161cf9b237SStefano Zampini 57179566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 57189566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &work_mat)); 57197b103a85SStefano Zampini PetscCall(MatPtAPWithPrefix_Private(work_mat, new_mat, PETSC_DEFAULT, ptapprefix, &pcbddc->local_mat)); 57209566063dSJacob Faibussowitsch PetscCall(MatDestroy(&work_mat)); 5721022d8d2bSstefano_zampini if (lA) { 5722022d8d2bSstefano_zampini Mat work; 57239566063dSJacob Faibussowitsch PetscCall(MatConvert(lA, MATSEQAIJ, MAT_INITIAL_MATRIX, &work_mat)); 57247b103a85SStefano Zampini PetscCall(MatPtAPWithPrefix_Private(work_mat, new_mat, PETSC_DEFAULT, ptapprefix, &work)); 57259566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_lA", (PetscObject)work)); 57269566063dSJacob Faibussowitsch PetscCall(MatDestroy(&work)); 5727022d8d2bSstefano_zampini } 5728aa0d41d4SStefano Zampini } 5729b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(matis->A, &isset, &issym)); 5730b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(pcbddc->local_mat, MAT_SYMMETRIC, issym)); 57319566063dSJacob Faibussowitsch PetscCall(MatDestroy(&new_mat)); 57323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5733aa0d41d4SStefano Zampini } 5734aa0d41d4SStefano Zampini 5735d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpLocalScatters(PC pc) 5736d71ae5a4SJacob Faibussowitsch { 5737f4f49eeaSPierre Jolivet PC_IS *pcis = (PC_IS *)pc->data; 5738a64d13efSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 5739d62866d3SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 574053892102SStefano Zampini PetscInt *idx_R_local = NULL; 57413a50541eSStefano Zampini PetscInt n_vertices, i, j, n_R, n_D, n_B; 57423a50541eSStefano Zampini PetscInt vbs, bs; 57436816873aSStefano Zampini PetscBT bitmask = NULL; 5744a64d13efSStefano Zampini 5745a64d13efSStefano Zampini PetscFunctionBegin; 5746b23d619eSStefano Zampini /* 5747b23d619eSStefano Zampini No need to setup local scatters if 5748b23d619eSStefano Zampini - primal space is unchanged 5749b23d619eSStefano Zampini AND 5750b23d619eSStefano Zampini - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains) 5751b23d619eSStefano Zampini AND 5752b23d619eSStefano Zampini - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine 5753b23d619eSStefano Zampini */ 57543ba16761SJacob Faibussowitsch if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) PetscFunctionReturn(PETSC_SUCCESS); 5755f4ddd8eeSStefano Zampini /* destroy old objects */ 57569566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->is_R_local)); 57579566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->R_to_B)); 57589566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->R_to_D)); 5759a64d13efSStefano Zampini /* Set Non-overlapping dimensions */ 5760b371cd4fSStefano Zampini n_B = pcis->n_B; 5761b371cd4fSStefano Zampini n_D = pcis->n - n_B; 5762b371cd4fSStefano Zampini n_vertices = pcbddc->n_vertices; 57633a50541eSStefano Zampini 5764e602f447SPierre Jolivet /* Dohrmann's notation: dofs split in R (Remaining: all dofs but the vertices) and V (Vertices) */ 57656816873aSStefano Zampini 576653892102SStefano Zampini /* create auxiliary bitmask and allocate workspace */ 5767b334f244SStefano Zampini if (!sub_schurs || !sub_schurs->reuse_solver) { 57689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n - n_vertices, &idx_R_local)); 57699566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(pcis->n, &bitmask)); 577048a46eb9SPierre Jolivet for (i = 0; i < n_vertices; i++) PetscCall(PetscBTSet(bitmask, pcbddc->local_primal_ref_node[i])); 57714641a718SStefano Zampini 5772a64d13efSStefano Zampini for (i = 0, n_R = 0; i < pcis->n; i++) { 5773ad540459SPierre Jolivet if (!PetscBTLookup(bitmask, i)) idx_R_local[n_R++] = i; 5774a64d13efSStefano Zampini } 5775df4d28bfSStefano Zampini } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */ 5776df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 57776816873aSStefano Zampini 57789566063dSJacob Faibussowitsch PetscCall(ISGetIndices(reuse_solver->is_R, (const PetscInt **)&idx_R_local)); 57799566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(reuse_solver->is_R, &n_R)); 57806816873aSStefano Zampini } 57813a50541eSStefano Zampini 57823a50541eSStefano Zampini /* Block code */ 57833a50541eSStefano Zampini vbs = 1; 57849566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(pcbddc->local_mat, &bs)); 57853a50541eSStefano Zampini if (bs > 1 && !(n_vertices % bs)) { 57863a50541eSStefano Zampini PetscBool is_blocked = PETSC_TRUE; 57873a50541eSStefano Zampini PetscInt *vary; 5788b334f244SStefano Zampini if (!sub_schurs || !sub_schurs->reuse_solver) { 57899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n / bs, &vary)); 57909566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(vary, pcis->n / bs)); 5791d3df7717SStefano Zampini /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */ 5792d3df7717SStefano 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 */ 57930e6343abSStefano Zampini for (i = 0; i < n_vertices; i++) vary[pcbddc->local_primal_ref_node[i] / bs]++; 5794d3df7717SStefano Zampini for (i = 0; i < pcis->n / bs; i++) { 57953a50541eSStefano Zampini if (vary[i] != 0 && vary[i] != bs) { 57963a50541eSStefano Zampini is_blocked = PETSC_FALSE; 57973a50541eSStefano Zampini break; 57983a50541eSStefano Zampini } 57993a50541eSStefano Zampini } 58009566063dSJacob Faibussowitsch PetscCall(PetscFree(vary)); 5801d3df7717SStefano Zampini } else { 5802d3df7717SStefano Zampini /* Verify directly the R set */ 5803d3df7717SStefano Zampini for (i = 0; i < n_R / bs; i++) { 5804d3df7717SStefano Zampini PetscInt j, node = idx_R_local[bs * i]; 5805d3df7717SStefano Zampini for (j = 1; j < bs; j++) { 5806d3df7717SStefano Zampini if (node != idx_R_local[bs * i + j] - j) { 5807d3df7717SStefano Zampini is_blocked = PETSC_FALSE; 5808d3df7717SStefano Zampini break; 5809d3df7717SStefano Zampini } 5810d3df7717SStefano Zampini } 5811d3df7717SStefano Zampini } 5812d3df7717SStefano Zampini } 58133a50541eSStefano Zampini if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */ 58143a50541eSStefano Zampini vbs = bs; 5815ad540459SPierre Jolivet for (i = 0; i < n_R / vbs; i++) idx_R_local[i] = idx_R_local[vbs * i] / vbs; 58163a50541eSStefano Zampini } 58173a50541eSStefano Zampini } 58189566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF, vbs, n_R / vbs, idx_R_local, PETSC_COPY_VALUES, &pcbddc->is_R_local)); 5819b334f244SStefano Zampini if (sub_schurs && sub_schurs->reuse_solver) { 5820df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 582153892102SStefano Zampini 58229566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(reuse_solver->is_R, (const PetscInt **)&idx_R_local)); 58239566063dSJacob Faibussowitsch PetscCall(ISDestroy(&reuse_solver->is_R)); 58249566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->is_R_local)); 5825df4d28bfSStefano Zampini reuse_solver->is_R = pcbddc->is_R_local; 582653892102SStefano Zampini } else { 58279566063dSJacob Faibussowitsch PetscCall(PetscFree(idx_R_local)); 582853892102SStefano Zampini } 5829a64d13efSStefano Zampini 5830a64d13efSStefano Zampini /* print some info if requested */ 5831a64d13efSStefano Zampini if (pcbddc->dbg_flag) { 58329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 58339566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 58349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 58359566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d local dimensions\n", PetscGlobalRank)); 583663a3b9bcSJacob 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)); 58379371c9d4SSatish 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, 58389371c9d4SSatish Balay pcbddc->local_primal_size - n_vertices - pcbddc->benign_n, pcbddc->local_primal_size)); 58399566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 5840a64d13efSStefano Zampini } 5841a64d13efSStefano Zampini 5842a64d13efSStefano Zampini /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */ 5843b334f244SStefano Zampini if (!sub_schurs || !sub_schurs->reuse_solver) { 58446816873aSStefano Zampini IS is_aux1, is_aux2; 58456816873aSStefano Zampini PetscInt *aux_array1, *aux_array2, *is_indices, *idx_R_local; 58466816873aSStefano Zampini 58479566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->is_R_local, (const PetscInt **)&idx_R_local)); 58489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n_B - n_vertices, &aux_array1)); 58499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n_B - n_vertices, &aux_array2)); 58509566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_I_local, (const PetscInt **)&is_indices)); 585148a46eb9SPierre Jolivet for (i = 0; i < n_D; i++) PetscCall(PetscBTSet(bitmask, is_indices[i])); 58529566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_I_local, (const PetscInt **)&is_indices)); 5853a64d13efSStefano Zampini for (i = 0, j = 0; i < n_R; i++) { 5854ad540459SPierre Jolivet if (!PetscBTLookup(bitmask, idx_R_local[i])) aux_array1[j++] = i; 5855a64d13efSStefano Zampini } 58569566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, aux_array1, PETSC_OWN_POINTER, &is_aux1)); 58579566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_B_local, (const PetscInt **)&is_indices)); 5858a64d13efSStefano Zampini for (i = 0, j = 0; i < n_B; i++) { 5859ad540459SPierre Jolivet if (!PetscBTLookup(bitmask, is_indices[i])) aux_array2[j++] = i; 5860a64d13efSStefano Zampini } 58619566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_B_local, (const PetscInt **)&is_indices)); 58629566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, aux_array2, PETSC_OWN_POINTER, &is_aux2)); 58639566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(pcbddc->vec1_R, is_aux1, pcis->vec1_B, is_aux2, &pcbddc->R_to_B)); 58649566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_aux1)); 58659566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_aux2)); 5866a64d13efSStefano Zampini 58678eeda7d8SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 58689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_D, &aux_array1)); 5869a64d13efSStefano Zampini for (i = 0, j = 0; i < n_R; i++) { 5870ad540459SPierre Jolivet if (PetscBTLookup(bitmask, idx_R_local[i])) aux_array1[j++] = i; 5871a64d13efSStefano Zampini } 58729566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, aux_array1, PETSC_OWN_POINTER, &is_aux1)); 58739566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(pcbddc->vec1_R, is_aux1, pcis->vec1_D, (IS)0, &pcbddc->R_to_D)); 58749566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_aux1)); 5875a64d13efSStefano Zampini } 58769566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&bitmask)); 58779566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->is_R_local, (const PetscInt **)&idx_R_local)); 5878d62866d3SStefano Zampini } else { 5879df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 58806816873aSStefano Zampini IS tis; 58816816873aSStefano Zampini PetscInt schur_size; 58826816873aSStefano Zampini 58839566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(reuse_solver->is_B, &schur_size)); 58849566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, schur_size, n_D, 1, &tis)); 58859566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(pcbddc->vec1_R, tis, pcis->vec1_B, reuse_solver->is_B, &pcbddc->R_to_B)); 58869566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tis)); 58876816873aSStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 58889566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, n_D, 0, 1, &tis)); 58899566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(pcbddc->vec1_R, tis, pcis->vec1_D, (IS)0, &pcbddc->R_to_D)); 58909566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tis)); 5891d62866d3SStefano Zampini } 5892d62866d3SStefano Zampini } 58933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5894a64d13efSStefano Zampini } 5895a64d13efSStefano Zampini 5896e1614d24SStefano Zampini PetscErrorCode MatNullSpacePropagateAny_Private(Mat A, IS is, Mat B) 5897d71ae5a4SJacob Faibussowitsch { 589892cccca0SStefano Zampini MatNullSpace NullSpace; 589992cccca0SStefano Zampini Mat dmat; 590092cccca0SStefano Zampini const Vec *nullvecs; 590192cccca0SStefano Zampini Vec v, v2, *nullvecs2; 59026d9e27e4SStefano Zampini VecScatter sct = NULL; 5903eb06acf8SStefano Zampini PetscScalar *ddata; 5904295df10fSStefano Zampini PetscInt k, nnsp_size, bsiz, bsiz2, n, N, bs; 590592cccca0SStefano Zampini PetscBool nnsp_has_cnst; 590692cccca0SStefano Zampini 590792cccca0SStefano Zampini PetscFunctionBegin; 59086d9e27e4SStefano Zampini if (!is && !B) { /* MATIS */ 59096d9e27e4SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 59106d9e27e4SStefano Zampini 591148a46eb9SPierre Jolivet if (!B) PetscCall(MatISGetLocalMat(A, &B)); 59126d9e27e4SStefano Zampini sct = matis->cctx; 59139566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)sct)); 59146d9e27e4SStefano Zampini } else { 59159566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(B, &NullSpace)); 591648a46eb9SPierre Jolivet if (!NullSpace) PetscCall(MatGetNearNullSpace(B, &NullSpace)); 59173ba16761SJacob Faibussowitsch if (NullSpace) PetscFunctionReturn(PETSC_SUCCESS); 59186d9e27e4SStefano Zampini } 59199566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(A, &NullSpace)); 592048a46eb9SPierre Jolivet if (!NullSpace) PetscCall(MatGetNearNullSpace(A, &NullSpace)); 59213ba16761SJacob Faibussowitsch if (!NullSpace) PetscFunctionReturn(PETSC_SUCCESS); 59226d9e27e4SStefano Zampini 59239566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, &v, NULL)); 59249566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(B, &v2, NULL)); 592548a46eb9SPierre Jolivet if (!sct) PetscCall(VecScatterCreate(v, is, v2, NULL, &sct)); 5926835f2295SStefano Zampini PetscCall(MatNullSpaceGetVecs(NullSpace, &nnsp_has_cnst, &nnsp_size, &nullvecs)); 5927295df10fSStefano Zampini bsiz = bsiz2 = nnsp_size + !!nnsp_has_cnst; 59289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bsiz, &nullvecs2)); 59299566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(v2, &bs)); 59309566063dSJacob Faibussowitsch PetscCall(VecGetSize(v2, &N)); 59319566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v2, &n)); 59329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n * bsiz, &ddata)); 593392cccca0SStefano Zampini for (k = 0; k < nnsp_size; k++) { 59349566063dSJacob Faibussowitsch PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)B), bs, n, N, ddata + n * k, &nullvecs2[k])); 59359566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sct, nullvecs[k], nullvecs2[k], INSERT_VALUES, SCATTER_FORWARD)); 59369566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sct, nullvecs[k], nullvecs2[k], INSERT_VALUES, SCATTER_FORWARD)); 593792cccca0SStefano Zampini } 593892cccca0SStefano Zampini if (nnsp_has_cnst) { 59399566063dSJacob Faibussowitsch PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)B), bs, n, N, ddata + n * nnsp_size, &nullvecs2[nnsp_size])); 59409566063dSJacob Faibussowitsch PetscCall(VecSet(nullvecs2[nnsp_size], 1.0)); 594192cccca0SStefano Zampini } 59429566063dSJacob Faibussowitsch PetscCall(PCBDDCOrthonormalizeVecs(&bsiz2, nullvecs2)); 59439566063dSJacob Faibussowitsch PetscCall(MatNullSpaceCreate(PetscObjectComm((PetscObject)B), PETSC_FALSE, bsiz2, nullvecs2, &NullSpace)); 5944295df10fSStefano Zampini 59459566063dSJacob Faibussowitsch PetscCall(MatCreateDense(PetscObjectComm((PetscObject)B), n, PETSC_DECIDE, N, bsiz2, ddata, &dmat)); 594649abdd8aSBarry Smith PetscCall(PetscObjectContainerCompose((PetscObject)dmat, "_PBDDC_Null_dmat_arr", ddata, PetscCtxDestroyDefault)); 59479566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)NullSpace, "_PBDDC_Null_dmat", (PetscObject)dmat)); 59489566063dSJacob Faibussowitsch PetscCall(MatDestroy(&dmat)); 5949eb06acf8SStefano Zampini 595048a46eb9SPierre Jolivet for (k = 0; k < bsiz; k++) PetscCall(VecDestroy(&nullvecs2[k])); 59519566063dSJacob Faibussowitsch PetscCall(PetscFree(nullvecs2)); 59529566063dSJacob Faibussowitsch PetscCall(MatSetNearNullSpace(B, NullSpace)); 59539566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&NullSpace)); 59549566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 59559566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v2)); 59569566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sct)); 59573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 595892cccca0SStefano Zampini } 5959304d26faSStefano Zampini 5960d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann) 5961d71ae5a4SJacob Faibussowitsch { 5962304d26faSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 5963304d26faSStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 5964304d26faSStefano Zampini PC pc_temp; 5965304d26faSStefano Zampini Mat A_RR; 596692cccca0SStefano Zampini MatNullSpace nnsp; 5967f4ddd8eeSStefano Zampini MatReuse reuse; 5968304d26faSStefano Zampini PetscScalar m_one = -1.0; 5969304d26faSStefano Zampini PetscReal value; 597004708bb6SStefano Zampini PetscInt n_D, n_R; 5971b94d7dedSBarry Smith PetscBool issbaij, opts, isset, issym; 59720cd8b6e2SStefano Zampini PetscBool f = PETSC_FALSE; 5973312be037SStefano Zampini char dir_prefix[256], neu_prefix[256], str_level[16]; 5974e604994aSStefano Zampini size_t len; 5975304d26faSStefano Zampini 5976304d26faSStefano Zampini PetscFunctionBegin; 59779566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_LocalSolvers[pcbddc->current_level], pc, 0, 0, 0)); 59786d9e27e4SStefano Zampini /* approximate solver, propagate NearNullSpace if needed */ 59796d9e27e4SStefano Zampini if (!pc->setupcalled && (pcbddc->NullSpace_corr[0] || pcbddc->NullSpace_corr[2])) { 59806d9e27e4SStefano Zampini MatNullSpace gnnsp1, gnnsp2; 59816d9e27e4SStefano Zampini PetscBool lhas, ghas; 59826d9e27e4SStefano Zampini 59839566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pcbddc->local_mat, &nnsp)); 59849566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pc->pmat, &gnnsp1)); 59859566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(pc->pmat, &gnnsp2)); 59866d9e27e4SStefano Zampini lhas = nnsp ? PETSC_TRUE : PETSC_FALSE; 59875440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&lhas, &ghas, 1, MPI_C_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 598848a46eb9SPierre Jolivet if (!ghas && (gnnsp1 || gnnsp2)) PetscCall(MatNullSpacePropagateAny_Private(pc->pmat, NULL, NULL)); 59896d9e27e4SStefano Zampini } 59906d9e27e4SStefano Zampini 5991e604994aSStefano Zampini /* compute prefixes */ 5992c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(dir_prefix, "", sizeof(dir_prefix))); 5993c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(neu_prefix, "", sizeof(neu_prefix))); 5994e604994aSStefano Zampini if (!pcbddc->current_level) { 59959566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(dir_prefix, ((PetscObject)pc)->prefix, sizeof(dir_prefix))); 59969566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(neu_prefix, ((PetscObject)pc)->prefix, sizeof(neu_prefix))); 59979566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(dir_prefix, "pc_bddc_dirichlet_", sizeof(dir_prefix))); 59989566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(neu_prefix, "pc_bddc_neumann_", sizeof(neu_prefix))); 5999e604994aSStefano Zampini } else { 6000835f2295SStefano Zampini PetscCall(PetscSNPrintf(str_level, sizeof(str_level), "l%" PetscInt_FMT "_", pcbddc->current_level)); 60019566063dSJacob Faibussowitsch PetscCall(PetscStrlen(((PetscObject)pc)->prefix, &len)); 6002e604994aSStefano Zampini len -= 15; /* remove "pc_bddc_coarse_" */ 6003312be037SStefano Zampini if (pcbddc->current_level > 1) len -= 3; /* remove "lX_" with X level number */ 6004312be037SStefano Zampini if (pcbddc->current_level > 10) len -= 1; /* remove another char from level number */ 6005a126751eSBarry Smith /* Nonstandard use of PetscStrncpy() to only copy a portion of the input string */ 60069566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(dir_prefix, ((PetscObject)pc)->prefix, len + 1)); 60079566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(neu_prefix, ((PetscObject)pc)->prefix, len + 1)); 60089566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(dir_prefix, "pc_bddc_dirichlet_", sizeof(dir_prefix))); 60099566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(neu_prefix, "pc_bddc_neumann_", sizeof(neu_prefix))); 60109566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(dir_prefix, str_level, sizeof(dir_prefix))); 60119566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(neu_prefix, str_level, sizeof(neu_prefix))); 6012e604994aSStefano Zampini } 6013e604994aSStefano Zampini 6014304d26faSStefano Zampini /* DIRICHLET PROBLEM */ 6015684f6988SStefano Zampini if (dirichlet) { 6016d5574798SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 6017450f8f5eSStefano Zampini if (pcbddc->benign_n && !pcbddc->benign_change_explicit) { 60187827d75bSBarry Smith PetscCheck(sub_schurs && sub_schurs->reuse_solver, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not yet implemented"); 6019450f8f5eSStefano Zampini if (pcbddc->dbg_flag) { 6020a3df083aSStefano Zampini Mat A_IIn; 6021a3df083aSStefano Zampini 60229566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignProject(pc, pcis->is_I_local, pcis->is_I_local, &A_IIn)); 60239566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_II)); 6024a3df083aSStefano Zampini pcis->A_II = A_IIn; 6025a3df083aSStefano Zampini } 6026450f8f5eSStefano Zampini } 6027b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(pcbddc->local_mat, &isset, &issym)); 6028b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(pcis->A_II, MAT_SYMMETRIC, issym)); 6029b94d7dedSBarry Smith 6030ac78edfcSStefano Zampini /* Matrix for Dirichlet problem is pcis->A_II */ 6031964fefecSStefano Zampini n_D = pcis->n - pcis->n_B; 603292cccca0SStefano Zampini opts = PETSC_FALSE; 6033304d26faSStefano Zampini if (!pcbddc->ksp_D) { /* create object if not yet build */ 603492cccca0SStefano Zampini opts = PETSC_TRUE; 60359566063dSJacob Faibussowitsch PetscCall(KSPCreate(PETSC_COMM_SELF, &pcbddc->ksp_D)); 60363821be0aSBarry Smith PetscCall(KSPSetNestLevel(pcbddc->ksp_D, pc->kspnestlevel)); 60379566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D, (PetscObject)pc, 1)); 6038304d26faSStefano Zampini /* default */ 60399566063dSJacob Faibussowitsch PetscCall(KSPSetType(pcbddc->ksp_D, KSPPREONLY)); 60409566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(pcbddc->ksp_D, dir_prefix)); 60419566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pcis->pA_II, MATSEQSBAIJ, &issbaij)); 60429566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_D, &pc_temp)); 60439577ea80SStefano Zampini if (issbaij) { 60449566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCCHOLESKY)); 60459577ea80SStefano Zampini } else { 60469566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCLU)); 60479577ea80SStefano Zampini } 60489566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(pcbddc->ksp_D, pc->erroriffailure)); 604992cccca0SStefano Zampini } 60509566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(pcis->pA_II, ((PetscObject)pcbddc->ksp_D)->prefix)); 60519de2952eSStefano Zampini PetscCall(MatViewFromOptions(pcis->pA_II, NULL, "-mat_view")); 60529566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(pcbddc->ksp_D, pcis->A_II, pcis->pA_II)); 6053304d26faSStefano Zampini /* Allow user's customization */ 60541baa6e33SBarry Smith if (opts) PetscCall(KSPSetFromOptions(pcbddc->ksp_D)); 60559566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pcis->pA_II, &nnsp)); 60566d9e27e4SStefano Zampini if (pcbddc->NullSpace_corr[0] && !nnsp) { /* approximate solver, propagate NearNullSpace */ 60579566063dSJacob Faibussowitsch PetscCall(MatNullSpacePropagateAny_Private(pcbddc->local_mat, pcis->is_I_local, pcis->pA_II)); 605892cccca0SStefano Zampini } 60599566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pcis->pA_II, &nnsp)); 60609566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_D, &pc_temp)); 60610cd8b6e2SStefano Zampini PetscCall(PetscObjectHasFunction((PetscObject)pc_temp, "PCSetCoordinates_C", &f)); 606292cccca0SStefano Zampini if (f && pcbddc->mat_graph->cloc && !nnsp) { 6063cd18cfedSStefano Zampini PetscReal *coords = pcbddc->mat_graph->coords, *scoords; 6064cd18cfedSStefano Zampini const PetscInt *idxs; 6065cd18cfedSStefano Zampini PetscInt cdim = pcbddc->mat_graph->cdim, nl, i, d; 6066cd18cfedSStefano Zampini 60679566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcis->is_I_local, &nl)); 60689566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_I_local, &idxs)); 60699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl * cdim, &scoords)); 6070cd18cfedSStefano Zampini for (i = 0; i < nl; i++) { 6071ad540459SPierre Jolivet for (d = 0; d < cdim; d++) scoords[i * cdim + d] = coords[idxs[i] * cdim + d]; 6072cd18cfedSStefano Zampini } 60739566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_I_local, &idxs)); 60749566063dSJacob Faibussowitsch PetscCall(PCSetCoordinates(pc_temp, cdim, nl, scoords)); 60759566063dSJacob Faibussowitsch PetscCall(PetscFree(scoords)); 6076cd18cfedSStefano Zampini } 6077b334f244SStefano Zampini if (sub_schurs && sub_schurs->reuse_solver) { 6078df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 6079d62866d3SStefano Zampini 60809566063dSJacob Faibussowitsch PetscCall(KSPSetPC(pcbddc->ksp_D, reuse_solver->interior_solver)); 6081d5574798SStefano Zampini } 608292cccca0SStefano Zampini 6083304d26faSStefano Zampini /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */ 6084304d26faSStefano Zampini if (!n_D) { 60859566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_D, &pc_temp)); 60869566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCNONE)); 6087304d26faSStefano Zampini } 60889566063dSJacob Faibussowitsch PetscCall(KSPSetUp(pcbddc->ksp_D)); 6089304d26faSStefano Zampini /* set ksp_D into pcis data */ 60909566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->ksp_D)); 60919566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&pcis->ksp_D)); 6092304d26faSStefano Zampini pcis->ksp_D = pcbddc->ksp_D; 6093684f6988SStefano Zampini } 6094304d26faSStefano Zampini 6095304d26faSStefano Zampini /* NEUMANN PROBLEM */ 60960a545947SLisandro Dalcin A_RR = NULL; 6097684f6988SStefano Zampini if (neumann) { 6098d62866d3SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 609904708bb6SStefano Zampini PetscInt ibs, mbs; 6100b94d7dedSBarry Smith PetscBool issbaij, reuse_neumann_solver, isset, issym; 610104708bb6SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 61020aa714b2SStefano Zampini 61030aa714b2SStefano Zampini reuse_neumann_solver = PETSC_FALSE; 61040aa714b2SStefano Zampini if (sub_schurs && sub_schurs->reuse_solver) { 61050aa714b2SStefano Zampini IS iP; 61060aa714b2SStefano Zampini 61070aa714b2SStefano Zampini reuse_neumann_solver = PETSC_TRUE; 61089566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)sub_schurs->A, "__KSPFETIDP_iP", (PetscObject *)&iP)); 61090aa714b2SStefano Zampini if (iP) reuse_neumann_solver = PETSC_FALSE; 61100aa714b2SStefano Zampini } 6111f4ddd8eeSStefano Zampini /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */ 61129566063dSJacob Faibussowitsch PetscCall(ISGetSize(pcbddc->is_R_local, &n_R)); 6113f4ddd8eeSStefano Zampini if (pcbddc->ksp_R) { /* already created ksp */ 6114f4ddd8eeSStefano Zampini PetscInt nn_R; 61159566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(pcbddc->ksp_R, NULL, &A_RR)); 61169566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A_RR)); 61179566063dSJacob Faibussowitsch PetscCall(MatGetSize(A_RR, &nn_R, NULL)); 6118f4ddd8eeSStefano Zampini if (nn_R != n_R) { /* old ksp is not reusable, so reset it */ 61199566063dSJacob Faibussowitsch PetscCall(KSPReset(pcbddc->ksp_R)); 61209566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 6121f4ddd8eeSStefano Zampini reuse = MAT_INITIAL_MATRIX; 6122f4ddd8eeSStefano Zampini } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */ 6123727cdba6SStefano Zampini if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */ 61249566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 6125f4ddd8eeSStefano Zampini reuse = MAT_INITIAL_MATRIX; 6126f4ddd8eeSStefano Zampini } else { /* safe to reuse the matrix */ 6127f4ddd8eeSStefano Zampini reuse = MAT_REUSE_MATRIX; 6128f4ddd8eeSStefano Zampini } 6129f4ddd8eeSStefano Zampini } 6130f4ddd8eeSStefano Zampini /* last check */ 6131d1e9a80fSBarry Smith if (pc->flag == DIFFERENT_NONZERO_PATTERN) { 61329566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 6133f4ddd8eeSStefano Zampini reuse = MAT_INITIAL_MATRIX; 6134f4ddd8eeSStefano Zampini } 6135f4ddd8eeSStefano Zampini } else { /* first time, so we need to create the matrix */ 6136f4ddd8eeSStefano Zampini reuse = MAT_INITIAL_MATRIX; 6137f4ddd8eeSStefano Zampini } 6138365a3a41SStefano Zampini /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection 6139365a3a41SStefano Zampini TODO: Get Rid of these conversions */ 61409566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(pcbddc->local_mat, &mbs)); 61419566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(pcbddc->is_R_local, &ibs)); 61429566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pcbddc->local_mat, MATSEQSBAIJ, &issbaij)); 614304708bb6SStefano Zampini if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */ 614404708bb6SStefano Zampini if (matis->A == pcbddc->local_mat) { 61459566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 61469566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &pcbddc->local_mat)); 6147af732b37SStefano Zampini } else { 61489566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->local_mat, MATSEQAIJ, MAT_INPLACE_MATRIX, &pcbddc->local_mat)); 61496816873aSStefano Zampini } 61504cf0e950SBarry Smith } else if (issbaij) { /* need to convert to BAIJ to get off-diagonal blocks */ 615104708bb6SStefano Zampini if (matis->A == pcbddc->local_mat) { 61529566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 61539566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, mbs > 1 ? MATSEQBAIJ : MATSEQAIJ, MAT_INITIAL_MATRIX, &pcbddc->local_mat)); 615404708bb6SStefano Zampini } else { 61559566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->local_mat, mbs > 1 ? MATSEQBAIJ : MATSEQAIJ, MAT_INPLACE_MATRIX, &pcbddc->local_mat)); 615604708bb6SStefano Zampini } 615704708bb6SStefano Zampini } 6158a00504b5SStefano Zampini /* extract A_RR */ 61590aa714b2SStefano Zampini if (reuse_neumann_solver) { 6160a00504b5SStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 6161a00504b5SStefano Zampini 6162a00504b5SStefano Zampini if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */ 61639566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 6164a00504b5SStefano Zampini if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */ 61659566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignProject(pc, pcbddc->is_R_local, pcbddc->is_R_local, &A_RR)); 616616e386b8SStefano Zampini } else { 61679566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcbddc->is_R_local, pcbddc->is_R_local, MAT_INITIAL_MATRIX, &A_RR)); 6168a00504b5SStefano Zampini } 6169a00504b5SStefano Zampini } else { 61709566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 61719566063dSJacob Faibussowitsch PetscCall(PCGetOperators(reuse_solver->correction_solver, &A_RR, NULL)); 61729566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A_RR)); 6173a00504b5SStefano Zampini } 6174a00504b5SStefano Zampini } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */ 61759566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcbddc->is_R_local, pcbddc->is_R_local, reuse, &A_RR)); 617616e386b8SStefano Zampini } 6177b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(pcbddc->local_mat, &isset, &issym)); 6178b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(A_RR, MAT_SYMMETRIC, issym)); 617992cccca0SStefano Zampini opts = PETSC_FALSE; 6180f4ddd8eeSStefano Zampini if (!pcbddc->ksp_R) { /* create object if not present */ 618192cccca0SStefano Zampini opts = PETSC_TRUE; 61829566063dSJacob Faibussowitsch PetscCall(KSPCreate(PETSC_COMM_SELF, &pcbddc->ksp_R)); 61833821be0aSBarry Smith PetscCall(KSPSetNestLevel(pcbddc->ksp_R, pc->kspnestlevel)); 61849566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R, (PetscObject)pc, 1)); 6185304d26faSStefano Zampini /* default */ 61869566063dSJacob Faibussowitsch PetscCall(KSPSetType(pcbddc->ksp_R, KSPPREONLY)); 61879566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(pcbddc->ksp_R, neu_prefix)); 61889566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_R, &pc_temp)); 61899566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A_RR, MATSEQSBAIJ, &issbaij)); 61909577ea80SStefano Zampini if (issbaij) { 61919566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCCHOLESKY)); 61929577ea80SStefano Zampini } else { 61939566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCLU)); 61949577ea80SStefano Zampini } 61959566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(pcbddc->ksp_R, pc->erroriffailure)); 619692cccca0SStefano Zampini } 61979566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(A_RR, ((PetscObject)pcbddc->ksp_R)->prefix)); 61989de2952eSStefano Zampini PetscCall(MatViewFromOptions(A_RR, NULL, "-mat_view")); 61999de2952eSStefano Zampini PetscCall(KSPSetOperators(pcbddc->ksp_R, A_RR, A_RR)); 620092cccca0SStefano Zampini if (opts) { /* Allow user's customization once */ 62019566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(pcbddc->ksp_R)); 620292cccca0SStefano Zampini } 62039566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(A_RR, &nnsp)); 62046d9e27e4SStefano Zampini if (pcbddc->NullSpace_corr[2] && !nnsp) { /* approximate solver, propagate NearNullSpace */ 62059566063dSJacob Faibussowitsch PetscCall(MatNullSpacePropagateAny_Private(pcbddc->local_mat, pcbddc->is_R_local, A_RR)); 620692cccca0SStefano Zampini } 62079566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(A_RR, &nnsp)); 62089566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_R, &pc_temp)); 62090cd8b6e2SStefano Zampini PetscCall(PetscObjectHasFunction((PetscObject)pc_temp, "PCSetCoordinates_C", &f)); 621092cccca0SStefano Zampini if (f && pcbddc->mat_graph->cloc && !nnsp) { 6211cd18cfedSStefano Zampini PetscReal *coords = pcbddc->mat_graph->coords, *scoords; 6212cd18cfedSStefano Zampini const PetscInt *idxs; 6213cd18cfedSStefano Zampini PetscInt cdim = pcbddc->mat_graph->cdim, nl, i, d; 6214cd18cfedSStefano Zampini 62159566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->is_R_local, &nl)); 62169566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->is_R_local, &idxs)); 62179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl * cdim, &scoords)); 6218cd18cfedSStefano Zampini for (i = 0; i < nl; i++) { 6219ad540459SPierre Jolivet for (d = 0; d < cdim; d++) scoords[i * cdim + d] = coords[idxs[i] * cdim + d]; 6220cd18cfedSStefano Zampini } 62219566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->is_R_local, &idxs)); 62229566063dSJacob Faibussowitsch PetscCall(PCSetCoordinates(pc_temp, cdim, nl, scoords)); 62239566063dSJacob Faibussowitsch PetscCall(PetscFree(scoords)); 6224cd18cfedSStefano Zampini } 622592cccca0SStefano Zampini 6226304d26faSStefano Zampini /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */ 6227304d26faSStefano Zampini if (!n_R) { 62289566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_R, &pc_temp)); 62299566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCNONE)); 6230304d26faSStefano Zampini } 6231df4d28bfSStefano Zampini /* Reuse solver if it is present */ 62320aa714b2SStefano Zampini if (reuse_neumann_solver) { 6233df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 6234d62866d3SStefano Zampini 62359566063dSJacob Faibussowitsch PetscCall(KSPSetPC(pcbddc->ksp_R, reuse_solver->correction_solver)); 6236d62866d3SStefano Zampini } 62379566063dSJacob Faibussowitsch PetscCall(KSPSetUp(pcbddc->ksp_R)); 6238684f6988SStefano Zampini } 6239304d26faSStefano Zampini 6240684f6988SStefano Zampini if (pcbddc->dbg_flag) { 62419566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 62429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 62439566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 6244684f6988SStefano Zampini } 62459566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_LocalSolvers[pcbddc->current_level], pc, 0, 0, 0)); 6246c7017625SStefano Zampini 6247c7017625SStefano Zampini /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */ 624848a46eb9SPierre Jolivet if (pcbddc->NullSpace_corr[0]) PetscCall(PCBDDCSetUseExactDirichlet(pc, PETSC_FALSE)); 624948a46eb9SPierre Jolivet if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) PetscCall(PCBDDCNullSpaceAssembleCorrection(pc, PETSC_TRUE, pcbddc->NullSpace_corr[1])); 625048a46eb9SPierre Jolivet if (neumann && pcbddc->NullSpace_corr[2]) PetscCall(PCBDDCNullSpaceAssembleCorrection(pc, PETSC_FALSE, pcbddc->NullSpace_corr[3])); 6251c7017625SStefano Zampini /* check Dirichlet and Neumann solvers */ 6252c7017625SStefano Zampini if (pcbddc->dbg_flag) { 6253684f6988SStefano Zampini if (dirichlet) { /* Dirichlet */ 62549566063dSJacob Faibussowitsch PetscCall(VecSetRandom(pcis->vec1_D, NULL)); 62559566063dSJacob Faibussowitsch PetscCall(MatMult(pcis->A_II, pcis->vec1_D, pcis->vec2_D)); 62569566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec2_D, pcis->vec2_D)); 62579566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D)); 62589566063dSJacob Faibussowitsch PetscCall(VecAXPY(pcis->vec1_D, m_one, pcis->vec2_D)); 62599566063dSJacob Faibussowitsch PetscCall(VecNorm(pcis->vec1_D, NORM_INFINITY, &value)); 6260f4f49eeaSPierre 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)); 62619566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 6262304d26faSStefano Zampini } 6263684f6988SStefano Zampini if (neumann) { /* Neumann */ 62649566063dSJacob Faibussowitsch PetscCall(VecSetRandom(pcbddc->vec1_R, NULL)); 62659566063dSJacob Faibussowitsch PetscCall(MatMult(A_RR, pcbddc->vec1_R, pcbddc->vec2_R)); 62669566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_R, pcbddc->vec2_R, pcbddc->vec2_R)); 62679566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec2_R)); 62689566063dSJacob Faibussowitsch PetscCall(VecAXPY(pcbddc->vec1_R, m_one, pcbddc->vec2_R)); 62699566063dSJacob Faibussowitsch PetscCall(VecNorm(pcbddc->vec1_R, NORM_INFINITY, &value)); 6270f4f49eeaSPierre 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)); 62719566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 6272304d26faSStefano Zampini } 6273684f6988SStefano Zampini } 62745cbda25cSStefano Zampini /* free Neumann problem's matrix */ 62759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 62763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6277304d26faSStefano Zampini } 6278304d26faSStefano Zampini 6279d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose) 6280d71ae5a4SJacob Faibussowitsch { 6281f4f49eeaSPierre Jolivet PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 6282be83ff47SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 6283b334f244SStefano Zampini PetscBool reuse_solver = sub_schurs ? (sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE) : PETSC_FALSE; 6284674ae819SStefano Zampini 6285674ae819SStefano Zampini PetscFunctionBegin; 628648a46eb9SPierre Jolivet if (!reuse_solver) PetscCall(VecSet(pcbddc->vec1_R, 0.)); 628780677318SStefano Zampini if (!pcbddc->switch_static) { 628880677318SStefano Zampini if (applytranspose && pcbddc->local_auxmat1) { 62899566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->local_auxmat2, inout_B, pcbddc->vec1_C)); 62909566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(pcbddc->local_auxmat1, pcbddc->vec1_C, inout_B, inout_B)); 629120c7b377SStefano Zampini } 6292b334f244SStefano Zampini if (!reuse_solver) { 62939566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 62949566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 629520c7b377SStefano Zampini } else { 6296df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 6297be83ff47SStefano Zampini 62989566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(reuse_solver->correction_scatter_B, inout_B, reuse_solver->rhs_B, INSERT_VALUES, SCATTER_FORWARD)); 62999566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(reuse_solver->correction_scatter_B, inout_B, reuse_solver->rhs_B, INSERT_VALUES, SCATTER_FORWARD)); 630020c7b377SStefano Zampini } 6301be83ff47SStefano Zampini } else { 63029566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 63039566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 63049566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_D, inout_D, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 63059566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_D, inout_D, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 630680677318SStefano Zampini if (applytranspose && pcbddc->local_auxmat1) { 63079566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->local_auxmat2, pcbddc->vec1_R, pcbddc->vec1_C)); 63089566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(pcbddc->local_auxmat1, pcbddc->vec1_C, inout_B, inout_B)); 63099566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 63109566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 6311674ae819SStefano Zampini } 6312674ae819SStefano Zampini } 63139566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][1], pc, 0, 0, 0)); 6314b334f244SStefano Zampini if (!reuse_solver || pcbddc->switch_static) { 631580677318SStefano Zampini if (applytranspose) { 63169566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec1_R)); 631780677318SStefano Zampini } else { 63189566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec1_R)); 631980677318SStefano Zampini } 63209566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec1_R)); 6321be83ff47SStefano Zampini } else { 6322df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 6323be83ff47SStefano Zampini 6324be83ff47SStefano Zampini if (applytranspose) { 63259566063dSJacob Faibussowitsch PetscCall(MatFactorSolveSchurComplementTranspose(reuse_solver->F, reuse_solver->rhs_B, reuse_solver->sol_B)); 6326be83ff47SStefano Zampini } else { 63279566063dSJacob Faibussowitsch PetscCall(MatFactorSolveSchurComplement(reuse_solver->F, reuse_solver->rhs_B, reuse_solver->sol_B)); 6328be83ff47SStefano Zampini } 6329be83ff47SStefano Zampini } 63309566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][1], pc, 0, 0, 0)); 63319566063dSJacob Faibussowitsch PetscCall(VecSet(inout_B, 0.)); 633280677318SStefano Zampini if (!pcbddc->switch_static) { 6333b334f244SStefano Zampini if (!reuse_solver) { 63349566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 63359566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 6336be83ff47SStefano Zampini } else { 6337df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 6338be83ff47SStefano Zampini 63399566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(reuse_solver->correction_scatter_B, reuse_solver->sol_B, inout_B, INSERT_VALUES, SCATTER_REVERSE)); 63409566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(reuse_solver->correction_scatter_B, reuse_solver->sol_B, inout_B, INSERT_VALUES, SCATTER_REVERSE)); 6341be83ff47SStefano Zampini } 634280677318SStefano Zampini if (!applytranspose && pcbddc->local_auxmat1) { 63439566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->local_auxmat1, inout_B, pcbddc->vec1_C)); 63449566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pcbddc->local_auxmat2, pcbddc->vec1_C, inout_B, inout_B)); 634580677318SStefano Zampini } 634680677318SStefano Zampini } else { 63479566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 63489566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 63499566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_D, pcbddc->vec1_R, inout_D, INSERT_VALUES, SCATTER_FORWARD)); 63509566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_D, pcbddc->vec1_R, inout_D, INSERT_VALUES, SCATTER_FORWARD)); 635180677318SStefano Zampini if (!applytranspose && pcbddc->local_auxmat1) { 63529566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->local_auxmat1, inout_B, pcbddc->vec1_C)); 63539566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pcbddc->local_auxmat2, pcbddc->vec1_C, pcbddc->vec1_R, pcbddc->vec1_R)); 635480677318SStefano Zampini } 63559566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 63569566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 63579566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_D, pcbddc->vec1_R, inout_D, INSERT_VALUES, SCATTER_FORWARD)); 63589566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_D, pcbddc->vec1_R, inout_D, INSERT_VALUES, SCATTER_FORWARD)); 6359674ae819SStefano Zampini } 63603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6361674ae819SStefano Zampini } 6362674ae819SStefano Zampini 6363dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */ 6364d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose) 6365d71ae5a4SJacob Faibussowitsch { 6366f4f49eeaSPierre Jolivet PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 6367f4f49eeaSPierre Jolivet PC_IS *pcis = (PC_IS *)pc->data; 6368674ae819SStefano Zampini const PetscScalar zero = 0.0; 6369674ae819SStefano Zampini 6370674ae819SStefano Zampini PetscFunctionBegin; 6371dc359a40SStefano Zampini /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */ 63724fee134fSStefano Zampini if (!pcbddc->benign_apply_coarse_only) { 6373dc359a40SStefano Zampini if (applytranspose) { 63749566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->coarse_phi_B, pcis->vec1_B, pcbddc->vec1_P)); 63759566063dSJacob Faibussowitsch if (pcbddc->switch_static) PetscCall(MatMultTransposeAdd(pcbddc->coarse_phi_D, pcis->vec1_D, pcbddc->vec1_P, pcbddc->vec1_P)); 6376dc359a40SStefano Zampini } else { 63779566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->coarse_psi_B, pcis->vec1_B, pcbddc->vec1_P)); 63789566063dSJacob Faibussowitsch if (pcbddc->switch_static) PetscCall(MatMultTransposeAdd(pcbddc->coarse_psi_D, pcis->vec1_D, pcbddc->vec1_P, pcbddc->vec1_P)); 637915aaf578SStefano Zampini } 63804fee134fSStefano Zampini } else { 63819566063dSJacob Faibussowitsch PetscCall(VecSet(pcbddc->vec1_P, zero)); 63824fee134fSStefano Zampini } 6383efc2fbd9SStefano Zampini 6384efc2fbd9SStefano Zampini /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */ 63854f1b2e48SStefano Zampini if (pcbddc->benign_n) { 6386efc2fbd9SStefano Zampini PetscScalar *array; 63874f1b2e48SStefano Zampini PetscInt j; 6388efc2fbd9SStefano Zampini 63899566063dSJacob Faibussowitsch PetscCall(VecGetArray(pcbddc->vec1_P, &array)); 63904f1b2e48SStefano Zampini for (j = 0; j < pcbddc->benign_n; j++) array[pcbddc->local_primal_size - pcbddc->benign_n + j] += pcbddc->benign_p0[j]; 63919566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pcbddc->vec1_P, &array)); 6392efc2fbd9SStefano Zampini } 6393efc2fbd9SStefano Zampini 639412edc857SStefano Zampini /* start communications from local primal nodes to rhs of coarse solver */ 63959566063dSJacob Faibussowitsch PetscCall(VecSet(pcbddc->coarse_vec, zero)); 63969566063dSJacob Faibussowitsch PetscCall(PCBDDCScatterCoarseDataBegin(pc, ADD_VALUES, SCATTER_FORWARD)); 63979566063dSJacob Faibussowitsch PetscCall(PCBDDCScatterCoarseDataEnd(pc, ADD_VALUES, SCATTER_FORWARD)); 639812edc857SStefano Zampini 63999f00e9b4SStefano Zampini /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */ 6400a1cb837bSStefano Zampini PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][2], pc, 0, 0, 0)); 640112edc857SStefano Zampini if (pcbddc->coarse_ksp) { 640251694757SStefano Zampini Mat coarse_mat; 6403964fefecSStefano Zampini Vec rhs, sol; 640451694757SStefano Zampini MatNullSpace nullsp; 640527b6a85dSStefano Zampini PetscBool isbddc = PETSC_FALSE; 6406964fefecSStefano Zampini 640727b6a85dSStefano Zampini if (pcbddc->benign_have_null) { 640827b6a85dSStefano Zampini PC coarse_pc; 640927b6a85dSStefano Zampini 64109566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &coarse_pc)); 64119566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)coarse_pc, PCBDDC, &isbddc)); 641227b6a85dSStefano Zampini /* we need to propagate to coarser levels the need for a possible benign correction */ 641327b6a85dSStefano Zampini if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) { 6414f4f49eeaSPierre Jolivet PC_BDDC *coarsepcbddc = (PC_BDDC *)coarse_pc->data; 641527b6a85dSStefano Zampini coarsepcbddc->benign_skip_correction = PETSC_FALSE; 64163bca92a6SStefano Zampini coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE; 641727b6a85dSStefano Zampini } 641827b6a85dSStefano Zampini } 64199566063dSJacob Faibussowitsch PetscCall(KSPGetRhs(pcbddc->coarse_ksp, &rhs)); 64209566063dSJacob Faibussowitsch PetscCall(KSPGetSolution(pcbddc->coarse_ksp, &sol)); 64219566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(pcbddc->coarse_ksp, &coarse_mat, NULL)); 642212edc857SStefano Zampini if (applytranspose) { 642328b400f6SJacob Faibussowitsch PetscCheck(!pcbddc->benign_apply_coarse_only, PetscObjectComm((PetscObject)pcbddc->coarse_ksp), PETSC_ERR_SUP, "Not yet implemented"); 64249566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->coarse_ksp, rhs, sol)); 64259566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->coarse_ksp, pc, sol)); 64269566063dSJacob Faibussowitsch PetscCall(MatGetTransposeNullSpace(coarse_mat, &nullsp)); 64271baa6e33SBarry Smith if (nullsp) PetscCall(MatNullSpaceRemove(nullsp, sol)); 64282701bc32SStefano Zampini } else { 64299566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(coarse_mat, &nullsp)); 64301f4df5f7SStefano Zampini if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */ 64312701bc32SStefano Zampini PC coarse_pc; 64322701bc32SStefano Zampini 64331baa6e33SBarry Smith if (nullsp) PetscCall(MatNullSpaceRemove(nullsp, rhs)); 64349566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &coarse_pc)); 64359566063dSJacob Faibussowitsch PetscCall(PCPreSolve(coarse_pc, pcbddc->coarse_ksp)); 64369566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignRemoveInterior(coarse_pc, rhs, sol)); 64379566063dSJacob Faibussowitsch PetscCall(PCPostSolve(coarse_pc, pcbddc->coarse_ksp)); 643812edc857SStefano Zampini } else { 64399566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->coarse_ksp, rhs, sol)); 64409566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->coarse_ksp, pc, sol)); 64411baa6e33SBarry Smith if (nullsp) PetscCall(MatNullSpaceRemove(nullsp, sol)); 644212edc857SStefano Zampini } 64432701bc32SStefano Zampini } 64441d82a3b6SStefano Zampini /* we don't need the benign correction at coarser levels anymore */ 644527b6a85dSStefano Zampini if (pcbddc->benign_have_null && isbddc) { 644627b6a85dSStefano Zampini PC coarse_pc; 644727b6a85dSStefano Zampini PC_BDDC *coarsepcbddc; 644827b6a85dSStefano Zampini 64499566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &coarse_pc)); 6450f4f49eeaSPierre Jolivet coarsepcbddc = (PC_BDDC *)coarse_pc->data; 645127b6a85dSStefano Zampini coarsepcbddc->benign_skip_correction = PETSC_TRUE; 64523bca92a6SStefano Zampini coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE; 645327b6a85dSStefano Zampini } 645412edc857SStefano Zampini } 6455a1cb837bSStefano Zampini PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][2], pc, 0, 0, 0)); 6456674ae819SStefano Zampini 6457674ae819SStefano Zampini /* Local solution on R nodes */ 6458a1cb837bSStefano Zampini if (!pcbddc->benign_apply_coarse_only) PetscCall(PCBDDCSolveSubstructureCorrection(pc, pcis->vec1_B, pcis->vec1_D, applytranspose)); 64599f00e9b4SStefano Zampini /* communications from coarse sol to local primal nodes */ 64609566063dSJacob Faibussowitsch PetscCall(PCBDDCScatterCoarseDataBegin(pc, INSERT_VALUES, SCATTER_REVERSE)); 64619566063dSJacob Faibussowitsch PetscCall(PCBDDCScatterCoarseDataEnd(pc, INSERT_VALUES, SCATTER_REVERSE)); 6462674ae819SStefano Zampini 64634fee134fSStefano Zampini /* Sum contributions from the two levels */ 64644fee134fSStefano Zampini if (!pcbddc->benign_apply_coarse_only) { 6465dc359a40SStefano Zampini if (applytranspose) { 64669566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pcbddc->coarse_psi_B, pcbddc->vec1_P, pcis->vec1_B, pcis->vec1_B)); 64679566063dSJacob Faibussowitsch if (pcbddc->switch_static) PetscCall(MatMultAdd(pcbddc->coarse_psi_D, pcbddc->vec1_P, pcis->vec1_D, pcis->vec1_D)); 6468dc359a40SStefano Zampini } else { 64699566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pcbddc->coarse_phi_B, pcbddc->vec1_P, pcis->vec1_B, pcis->vec1_B)); 64709566063dSJacob Faibussowitsch if (pcbddc->switch_static) PetscCall(MatMultAdd(pcbddc->coarse_phi_D, pcbddc->vec1_P, pcis->vec1_D, pcis->vec1_D)); 6471dc359a40SStefano Zampini } 6472efc2fbd9SStefano Zampini /* store p0 */ 64734f1b2e48SStefano Zampini if (pcbddc->benign_n) { 6474efc2fbd9SStefano Zampini PetscScalar *array; 64754f1b2e48SStefano Zampini PetscInt j; 6476efc2fbd9SStefano Zampini 64779566063dSJacob Faibussowitsch PetscCall(VecGetArray(pcbddc->vec1_P, &array)); 64784f1b2e48SStefano Zampini for (j = 0; j < pcbddc->benign_n; j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size - pcbddc->benign_n + j]; 64799566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pcbddc->vec1_P, &array)); 6480efc2fbd9SStefano Zampini } 64814fee134fSStefano Zampini } else { /* expand the coarse solution */ 64824fee134fSStefano Zampini if (applytranspose) { 64839566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->coarse_psi_B, pcbddc->vec1_P, pcis->vec1_B)); 64844fee134fSStefano Zampini } else { 64859566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->coarse_phi_B, pcbddc->vec1_P, pcis->vec1_B)); 64864fee134fSStefano Zampini } 64874fee134fSStefano Zampini } 64883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6489674ae819SStefano Zampini } 6490674ae819SStefano Zampini 6491d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc, InsertMode imode, ScatterMode smode) 6492d71ae5a4SJacob Faibussowitsch { 6493f4f49eeaSPierre Jolivet PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 649412edc857SStefano Zampini Vec from, to; 64957ebab0bbSStefano Zampini const PetscScalar *array; 6496674ae819SStefano Zampini 6497674ae819SStefano Zampini PetscFunctionBegin; 649812edc857SStefano Zampini if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */ 649912edc857SStefano Zampini from = pcbddc->coarse_vec; 650012edc857SStefano Zampini to = pcbddc->vec1_P; 650112edc857SStefano Zampini if (pcbddc->coarse_ksp) { /* get array from coarse processes */ 650212edc857SStefano Zampini Vec tvec; 650358da7f69SStefano Zampini 65049566063dSJacob Faibussowitsch PetscCall(KSPGetRhs(pcbddc->coarse_ksp, &tvec)); 65059566063dSJacob Faibussowitsch PetscCall(VecResetArray(tvec)); 65069566063dSJacob Faibussowitsch PetscCall(KSPGetSolution(pcbddc->coarse_ksp, &tvec)); 65079566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(tvec, &array)); 65089566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(from, array)); 65099566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(tvec, &array)); 651012edc857SStefano Zampini } 6511dd8e379bSPierre Jolivet } else { /* from local to global -> put data in coarse right-hand side */ 651212edc857SStefano Zampini from = pcbddc->vec1_P; 651312edc857SStefano Zampini to = pcbddc->coarse_vec; 651412edc857SStefano Zampini } 65159566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob, from, to, imode, smode)); 65163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6517674ae819SStefano Zampini } 6518674ae819SStefano Zampini 6519d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode) 6520d71ae5a4SJacob Faibussowitsch { 6521f4f49eeaSPierre Jolivet PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 652212edc857SStefano Zampini Vec from, to; 65237ebab0bbSStefano Zampini const PetscScalar *array; 6524674ae819SStefano Zampini 6525674ae819SStefano Zampini PetscFunctionBegin; 652612edc857SStefano Zampini if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */ 652712edc857SStefano Zampini from = pcbddc->coarse_vec; 652812edc857SStefano Zampini to = pcbddc->vec1_P; 6529dd8e379bSPierre Jolivet } else { /* from local to global -> put data in coarse right-hand side */ 653012edc857SStefano Zampini from = pcbddc->vec1_P; 653112edc857SStefano Zampini to = pcbddc->coarse_vec; 653212edc857SStefano Zampini } 65339566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob, from, to, imode, smode)); 653412edc857SStefano Zampini if (smode == SCATTER_FORWARD) { 653512edc857SStefano Zampini if (pcbddc->coarse_ksp) { /* get array from coarse processes */ 653612edc857SStefano Zampini Vec tvec; 653758da7f69SStefano Zampini 65389566063dSJacob Faibussowitsch PetscCall(KSPGetRhs(pcbddc->coarse_ksp, &tvec)); 65399566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(to, &array)); 65409566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(tvec, array)); 65419566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(to, &array)); 654258da7f69SStefano Zampini } 654358da7f69SStefano Zampini } else { 654458da7f69SStefano Zampini if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */ 65459566063dSJacob Faibussowitsch PetscCall(VecResetArray(from)); 654612edc857SStefano Zampini } 654712edc857SStefano Zampini } 65483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6549674ae819SStefano Zampini } 6550674ae819SStefano Zampini 6551d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCConstraintsSetUp(PC pc) 6552d71ae5a4SJacob Faibussowitsch { 6553f4f49eeaSPierre Jolivet PC_IS *pcis = (PC_IS *)pc->data; 6554674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 6555674ae819SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 6556984c4197SStefano Zampini /* one and zero */ 6557984c4197SStefano Zampini PetscScalar one = 1.0, zero = 0.0; 6558984c4197SStefano Zampini /* space to store constraints and their local indices */ 65599162d606SStefano Zampini PetscScalar *constraints_data; 65609162d606SStefano Zampini PetscInt *constraints_idxs, *constraints_idxs_B; 65619162d606SStefano Zampini PetscInt *constraints_idxs_ptr, *constraints_data_ptr; 65629162d606SStefano Zampini PetscInt *constraints_n; 6563984c4197SStefano Zampini /* iterators */ 6564b3d85658SStefano Zampini PetscInt i, j, k, total_counts, total_counts_cc, cum; 6565984c4197SStefano Zampini /* BLAS integers */ 6566e310c8b4SStefano Zampini PetscBLASInt lwork, lierr; 6567e310c8b4SStefano Zampini PetscBLASInt Blas_N, Blas_M, Blas_K, Blas_one = 1; 6568c4303822SStefano Zampini PetscBLASInt Blas_LDA, Blas_LDB, Blas_LDC; 6569727cdba6SStefano Zampini /* reuse */ 65700e6343abSStefano Zampini PetscInt olocal_primal_size, olocal_primal_size_cc; 65710e6343abSStefano Zampini PetscInt *olocal_primal_ref_node, *olocal_primal_ref_mult; 6572984c4197SStefano Zampini /* change of basis */ 6573b3d85658SStefano Zampini PetscBool qr_needed; 65749162d606SStefano Zampini PetscBT change_basis, qr_needed_idx; 6575984c4197SStefano Zampini /* auxiliary stuff */ 657664efe560SStefano Zampini PetscInt *nnz, *is_indices; 65778a0068c3SStefano Zampini PetscInt ncc; 6578984c4197SStefano Zampini /* some quantities */ 657945a1bb75SStefano Zampini PetscInt n_vertices, total_primal_vertices, valid_constraints; 6580a58a30b4SStefano Zampini PetscInt size_of_constraint, max_size_of_constraint = 0, max_constraints, temp_constraints; 658157715f18SStefano Zampini PetscReal tol; /* tolerance for retaining eigenmodes */ 6582984c4197SStefano Zampini 6583674ae819SStefano Zampini PetscFunctionBegin; 658457715f18SStefano Zampini tol = PetscSqrtReal(PETSC_SMALL); 65858e61c736SStefano Zampini /* Destroy Mat objects computed previously */ 65869566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->ChangeOfBasisMatrix)); 65879566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->ConstraintMatrix)); 65889566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->switch_static_change)); 6589088faed8SStefano Zampini /* save info on constraints from previous setup (if any) */ 6590088faed8SStefano Zampini olocal_primal_size = pcbddc->local_primal_size; 65910e6343abSStefano Zampini olocal_primal_size_cc = pcbddc->local_primal_size_cc; 65929566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(olocal_primal_size_cc, &olocal_primal_ref_node, olocal_primal_size_cc, &olocal_primal_ref_mult)); 65939566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(olocal_primal_ref_node, pcbddc->local_primal_ref_node, olocal_primal_size_cc)); 65949566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(olocal_primal_ref_mult, pcbddc->local_primal_ref_mult, olocal_primal_size_cc)); 65959566063dSJacob Faibussowitsch PetscCall(PetscFree2(pcbddc->local_primal_ref_node, pcbddc->local_primal_ref_mult)); 65969566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->primal_indices_local_idxs)); 6597cf5a6209SStefano Zampini 6598cf5a6209SStefano Zampini if (!pcbddc->adaptive_selection) { 65999162d606SStefano Zampini IS ISForVertices, *ISForFaces, *ISForEdges; 6600cf5a6209SStefano Zampini MatNullSpace nearnullsp; 6601cf5a6209SStefano Zampini const Vec *nearnullvecs; 6602cf5a6209SStefano Zampini Vec *localnearnullsp; 6603cf5a6209SStefano Zampini PetscScalar *array; 660432fe681dSStefano Zampini PetscInt n_ISForFaces, n_ISForEdges, nnsp_size, o_nf, o_ne; 6605cf5a6209SStefano Zampini PetscBool nnsp_has_cnst; 6606674ae819SStefano Zampini /* LAPACK working arrays for SVD or POD */ 6607b3d85658SStefano Zampini PetscBool skip_lapack, boolforchange; 6608674ae819SStefano Zampini PetscScalar *work; 6609674ae819SStefano Zampini PetscReal *singular_vals; 6610674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX) 6611674ae819SStefano Zampini PetscReal *rwork; 6612674ae819SStefano Zampini #endif 661355080a34SStefano Zampini PetscScalar *temp_basis = NULL, *correlation_mat = NULL; 6614964fefecSStefano Zampini PetscBLASInt dummy_int = 1; 6615964fefecSStefano Zampini PetscScalar dummy_scalar = 1.; 661655080a34SStefano Zampini PetscBool use_pod = PETSC_FALSE; 6617674ae819SStefano Zampini 661855080a34SStefano Zampini /* MKL SVD with same input gives different results on different processes! */ 6619b88df2e7SBarry Smith #if defined(PETSC_MISSING_LAPACK_GESVD) || defined(PETSC_HAVE_MKL_LIBS) 662055080a34SStefano Zampini use_pod = PETSC_TRUE; 662155080a34SStefano Zampini #endif 6622674ae819SStefano Zampini /* Get index sets for faces, edges and vertices from graph */ 66239566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, &n_ISForFaces, &ISForFaces, &n_ISForEdges, &ISForEdges, &ISForVertices)); 662432fe681dSStefano Zampini o_nf = n_ISForFaces; 662532fe681dSStefano Zampini o_ne = n_ISForEdges; 662632fe681dSStefano Zampini n_vertices = 0; 662732fe681dSStefano Zampini if (ISForVertices) PetscCall(ISGetSize(ISForVertices, &n_vertices)); 6628e4d548c7SStefano Zampini /* print some info */ 66295c643e28SStefano Zampini if (pcbddc->dbg_flag && (!pcbddc->sub_schurs || pcbddc->sub_schurs_rebuild)) { 663032fe681dSStefano Zampini if (!pcbddc->dbg_viewer) pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc)); 66319566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphASCIIView(pcbddc->mat_graph, pcbddc->dbg_flag, pcbddc->dbg_viewer)); 66329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 66339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "--------------------------------------------------------------\n")); 663432fe681dSStefano Zampini PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate vertices (%d)\n", PetscGlobalRank, n_vertices, pcbddc->use_vertices)); 663563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate edges (%d)\n", PetscGlobalRank, n_ISForEdges, pcbddc->use_edges)); 663663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate faces (%d)\n", PetscGlobalRank, n_ISForFaces, pcbddc->use_faces)); 66379566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 66389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer)); 6639e4d548c7SStefano Zampini } 6640e4d548c7SStefano Zampini 664132fe681dSStefano Zampini if (!pcbddc->use_vertices) n_vertices = 0; 664232fe681dSStefano Zampini if (!pcbddc->use_edges) n_ISForEdges = 0; 664332fe681dSStefano Zampini if (!pcbddc->use_faces) n_ISForFaces = 0; 664470022509SStefano Zampini 6645674ae819SStefano Zampini /* check if near null space is attached to global mat */ 6646ac530a7eSPierre Jolivet if (pcbddc->use_nnsp) PetscCall(MatGetNearNullSpace(pc->pmat, &nearnullsp)); 6647ac530a7eSPierre Jolivet else nearnullsp = NULL; 66486d9e27e4SStefano Zampini 6649674ae819SStefano Zampini if (nearnullsp) { 66509566063dSJacob Faibussowitsch PetscCall(MatNullSpaceGetVecs(nearnullsp, &nnsp_has_cnst, &nnsp_size, &nearnullvecs)); 6651f4ddd8eeSStefano Zampini /* remove any stored info */ 66529566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&pcbddc->onearnullspace)); 66539566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->onearnullvecs_state)); 6654f4ddd8eeSStefano Zampini /* store information for BDDC solver reuse */ 66559566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)nearnullsp)); 6656f4ddd8eeSStefano Zampini pcbddc->onearnullspace = nearnullsp; 66579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnsp_size, &pcbddc->onearnullvecs_state)); 665848a46eb9SPierre Jolivet for (i = 0; i < nnsp_size; i++) PetscCall(PetscObjectStateGet((PetscObject)nearnullvecs[i], &pcbddc->onearnullvecs_state[i])); 6659984c4197SStefano Zampini } else { /* if near null space is not provided BDDC uses constants by default */ 6660984c4197SStefano Zampini nnsp_size = 0; 6661674ae819SStefano Zampini nnsp_has_cnst = PETSC_TRUE; 6662674ae819SStefano Zampini } 6663984c4197SStefano Zampini /* get max number of constraints on a single cc */ 6664984c4197SStefano Zampini max_constraints = nnsp_size; 6665984c4197SStefano Zampini if (nnsp_has_cnst) max_constraints++; 6666984c4197SStefano Zampini 6667674ae819SStefano Zampini /* 6668674ae819SStefano Zampini Evaluate maximum storage size needed by the procedure 66699162d606SStefano Zampini - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]" 66709162d606SStefano Zampini - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]" 66719162d606SStefano Zampini There can be multiple constraints per connected component 6672674ae819SStefano Zampini */ 66739162d606SStefano Zampini ncc = n_vertices + n_ISForFaces + n_ISForEdges; 66749566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(ncc + 1, &constraints_idxs_ptr, ncc + 1, &constraints_data_ptr, ncc, &constraints_n)); 66759162d606SStefano Zampini 66769162d606SStefano Zampini total_counts = n_ISForFaces + n_ISForEdges; 66779162d606SStefano Zampini total_counts *= max_constraints; 6678674ae819SStefano Zampini total_counts += n_vertices; 66799566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(total_counts, &change_basis)); 66809162d606SStefano Zampini 6681674ae819SStefano Zampini total_counts = 0; 6682674ae819SStefano Zampini max_size_of_constraint = 0; 6683674ae819SStefano Zampini for (i = 0; i < n_ISForEdges + n_ISForFaces; i++) { 66849162d606SStefano Zampini IS used_is; 6685674ae819SStefano Zampini if (i < n_ISForEdges) { 66869162d606SStefano Zampini used_is = ISForEdges[i]; 6687674ae819SStefano Zampini } else { 66889162d606SStefano Zampini used_is = ISForFaces[i - n_ISForEdges]; 6689674ae819SStefano Zampini } 66909566063dSJacob Faibussowitsch PetscCall(ISGetSize(used_is, &j)); 6691674ae819SStefano Zampini total_counts += j; 6692674ae819SStefano Zampini max_size_of_constraint = PetscMax(j, max_size_of_constraint); 6693674ae819SStefano Zampini } 66949566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(total_counts * max_constraints + n_vertices, &constraints_data, total_counts + n_vertices, &constraints_idxs, total_counts + n_vertices, &constraints_idxs_B)); 66959162d606SStefano Zampini 6696984c4197SStefano Zampini /* get local part of global near null space vectors */ 66979566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnsp_size, &localnearnullsp)); 6698984c4197SStefano Zampini for (k = 0; k < nnsp_size; k++) { 66999566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_N, &localnearnullsp[k])); 67009566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, nearnullvecs[k], localnearnullsp[k], INSERT_VALUES, SCATTER_FORWARD)); 67019566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, nearnullvecs[k], localnearnullsp[k], INSERT_VALUES, SCATTER_FORWARD)); 6702984c4197SStefano Zampini } 6703674ae819SStefano Zampini 6704242a89d7SStefano Zampini /* whether or not to skip lapack calls */ 6705242a89d7SStefano Zampini skip_lapack = PETSC_TRUE; 6706a773dcb8SStefano Zampini if (n_ISForFaces + n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE; 6707242a89d7SStefano Zampini 6708984c4197SStefano Zampini /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */ 6709a773dcb8SStefano Zampini if (!skip_lapack) { 6710674ae819SStefano Zampini PetscScalar temp_work; 6711911cabfeSStefano Zampini 671255080a34SStefano Zampini if (use_pod) { 6713984c4197SStefano Zampini /* Proper Orthogonal Decomposition (POD) using the snapshot method */ 67149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_constraints * max_constraints, &correlation_mat)); 67159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_constraints, &singular_vals)); 67169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_size_of_constraint * max_constraints, &temp_basis)); 6717674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX) 67189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(3 * max_constraints, &rwork)); 6719674ae819SStefano Zampini #endif 6720674ae819SStefano Zampini /* now we evaluate the optimal workspace using query with lwork=-1 */ 67219566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_constraints, &Blas_N)); 67229566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_constraints, &Blas_LDA)); 6723674ae819SStefano Zampini lwork = -1; 67249566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6725674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX) 6726792fecdfSBarry Smith PetscCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &Blas_N, correlation_mat, &Blas_LDA, singular_vals, &temp_work, &lwork, &lierr)); 6727674ae819SStefano Zampini #else 6728792fecdfSBarry Smith PetscCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &Blas_N, correlation_mat, &Blas_LDA, singular_vals, &temp_work, &lwork, rwork, &lierr)); 6729674ae819SStefano Zampini #endif 67309566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 6731835f2295SStefano Zampini PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in query to SYEV Lapack routine %" PetscBLASInt_FMT, lierr); 673255080a34SStefano Zampini } else { 673355080a34SStefano Zampini #if !defined(PETSC_MISSING_LAPACK_GESVD) 6734674ae819SStefano Zampini /* SVD */ 6735674ae819SStefano Zampini PetscInt max_n, min_n; 6736674ae819SStefano Zampini max_n = max_size_of_constraint; 6737984c4197SStefano Zampini min_n = max_constraints; 6738984c4197SStefano Zampini if (max_size_of_constraint < max_constraints) { 6739674ae819SStefano Zampini min_n = max_size_of_constraint; 6740984c4197SStefano Zampini max_n = max_constraints; 6741674ae819SStefano Zampini } 67429566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(min_n, &singular_vals)); 6743674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX) 67449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(5 * min_n, &rwork)); 6745674ae819SStefano Zampini #endif 6746674ae819SStefano Zampini /* now we evaluate the optimal workspace using query with lwork=-1 */ 6747674ae819SStefano Zampini lwork = -1; 67489566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_n, &Blas_M)); 67499566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(min_n, &Blas_N)); 67509566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_n, &Blas_LDA)); 67519566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6752674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX) 6753792fecdfSBarry 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)); 6754674ae819SStefano Zampini #else 6755792fecdfSBarry 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)); 6756674ae819SStefano Zampini #endif 67579566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 6758835f2295SStefano Zampini PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in query to GESVD Lapack routine %" PetscBLASInt_FMT, lierr); 675955080a34SStefano Zampini #else 676055080a34SStefano Zampini SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "This should not happen"); 6761984c4197SStefano Zampini #endif /* on missing GESVD */ 676255080a34SStefano Zampini } 6763674ae819SStefano Zampini /* Allocate optimal workspace */ 67649566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(temp_work), &lwork)); 67659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(lwork, &work)); 6766674ae819SStefano Zampini } 6767674ae819SStefano Zampini /* Now we can loop on constraining sets */ 6768674ae819SStefano Zampini total_counts = 0; 67699162d606SStefano Zampini constraints_idxs_ptr[0] = 0; 67709162d606SStefano Zampini constraints_data_ptr[0] = 0; 6771674ae819SStefano Zampini /* vertices */ 67729162d606SStefano Zampini if (n_vertices) { 67739566063dSJacob Faibussowitsch PetscCall(ISGetIndices(ISForVertices, (const PetscInt **)&is_indices)); 67749566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(constraints_idxs, is_indices, n_vertices)); 6775674ae819SStefano Zampini for (i = 0; i < n_vertices; i++) { 67769162d606SStefano Zampini constraints_n[total_counts] = 1; 67779162d606SStefano Zampini constraints_data[total_counts] = 1.0; 67789162d606SStefano Zampini constraints_idxs_ptr[total_counts + 1] = constraints_idxs_ptr[total_counts] + 1; 67799162d606SStefano Zampini constraints_data_ptr[total_counts + 1] = constraints_data_ptr[total_counts] + 1; 6780674ae819SStefano Zampini total_counts++; 6781674ae819SStefano Zampini } 67829566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(ISForVertices, (const PetscInt **)&is_indices)); 6783674ae819SStefano Zampini } 6784984c4197SStefano Zampini 6785674ae819SStefano Zampini /* edges and faces */ 67869162d606SStefano Zampini total_counts_cc = total_counts; 6787911cabfeSStefano Zampini for (ncc = 0; ncc < n_ISForEdges + n_ISForFaces; ncc++) { 67889162d606SStefano Zampini IS used_is; 67899162d606SStefano Zampini PetscBool idxs_copied = PETSC_FALSE; 67909162d606SStefano Zampini 6791911cabfeSStefano Zampini if (ncc < n_ISForEdges) { 67929162d606SStefano Zampini used_is = ISForEdges[ncc]; 6793984c4197SStefano Zampini boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */ 6794674ae819SStefano Zampini } else { 67959162d606SStefano Zampini used_is = ISForFaces[ncc - n_ISForEdges]; 6796984c4197SStefano Zampini boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */ 6797674ae819SStefano Zampini } 6798674ae819SStefano Zampini temp_constraints = 0; /* zero the number of constraints I have on this conn comp */ 67999162d606SStefano Zampini 68009566063dSJacob Faibussowitsch PetscCall(ISGetSize(used_is, &size_of_constraint)); 680132fe681dSStefano Zampini if (!size_of_constraint) continue; 68029566063dSJacob Faibussowitsch PetscCall(ISGetIndices(used_is, (const PetscInt **)&is_indices)); 6803674ae819SStefano Zampini if (nnsp_has_cnst) { 68045b08dc53SStefano Zampini PetscScalar quad_value; 68059162d606SStefano Zampini 68069566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc], is_indices, size_of_constraint)); 68079162d606SStefano Zampini idxs_copied = PETSC_TRUE; 68089162d606SStefano Zampini 6809a773dcb8SStefano Zampini if (!pcbddc->use_nnsp_true) { 6810674ae819SStefano Zampini quad_value = (PetscScalar)(1.0 / PetscSqrtReal((PetscReal)size_of_constraint)); 6811a773dcb8SStefano Zampini } else { 6812a773dcb8SStefano Zampini quad_value = 1.0; 6813a773dcb8SStefano Zampini } 6814ad540459SPierre Jolivet for (j = 0; j < size_of_constraint; j++) constraints_data[constraints_data_ptr[total_counts_cc] + j] = quad_value; 68159162d606SStefano Zampini temp_constraints++; 6816674ae819SStefano Zampini total_counts++; 6817674ae819SStefano Zampini } 6818674ae819SStefano Zampini for (k = 0; k < nnsp_size; k++) { 6819984c4197SStefano Zampini PetscReal real_value; 68209162d606SStefano Zampini PetscScalar *ptr_to_data; 68219162d606SStefano Zampini 68229566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(localnearnullsp[k], (const PetscScalar **)&array)); 68239162d606SStefano Zampini ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc] + temp_constraints * size_of_constraint]; 6824ad540459SPierre Jolivet for (j = 0; j < size_of_constraint; j++) ptr_to_data[j] = array[is_indices[j]]; 68259566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(localnearnullsp[k], (const PetscScalar **)&array)); 6826984c4197SStefano Zampini /* check if array is null on the connected component */ 68279566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 6828792fecdfSBarry Smith PetscCallBLAS("BLASasum", real_value = BLASasum_(&Blas_N, ptr_to_data, &Blas_one)); 682957715f18SStefano Zampini if (real_value > tol * size_of_constraint) { /* keep indices and values */ 6830674ae819SStefano Zampini temp_constraints++; 6831674ae819SStefano Zampini total_counts++; 68329162d606SStefano Zampini if (!idxs_copied) { 68339566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc], is_indices, size_of_constraint)); 68349162d606SStefano Zampini idxs_copied = PETSC_TRUE; 6835674ae819SStefano Zampini } 6836674ae819SStefano Zampini } 68379162d606SStefano Zampini } 68389566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(used_is, (const PetscInt **)&is_indices)); 683945a1bb75SStefano Zampini valid_constraints = temp_constraints; 6840eb97c9d2SStefano Zampini if (!pcbddc->use_nnsp_true && temp_constraints) { 6841a773dcb8SStefano Zampini if (temp_constraints == 1) { /* just normalize the constraint */ 68429162d606SStefano Zampini PetscScalar norm, *ptr_to_data; 68439162d606SStefano Zampini 68449162d606SStefano Zampini ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]]; 68459566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 6846792fecdfSBarry Smith PetscCallBLAS("BLASdot", norm = BLASdot_(&Blas_N, ptr_to_data, &Blas_one, ptr_to_data, &Blas_one)); 6847a773dcb8SStefano Zampini norm = 1.0 / PetscSqrtReal(PetscRealPart(norm)); 6848792fecdfSBarry Smith PetscCallBLAS("BLASscal", BLASscal_(&Blas_N, &norm, ptr_to_data, &Blas_one)); 6849a773dcb8SStefano Zampini } else { /* perform SVD */ 68509162d606SStefano Zampini PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]]; 6851674ae819SStefano Zampini 685255080a34SStefano Zampini if (use_pod) { 6853984c4197SStefano Zampini /* SVD: Y = U*S*V^H -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag 6854984c4197SStefano Zampini POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2) 6855984c4197SStefano Zampini -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined 6856984c4197SStefano Zampini the constraints basis will differ (by a complex factor with absolute value equal to 1) 6857984c4197SStefano Zampini from that computed using LAPACKgesvd 6858984c4197SStefano Zampini -> This is due to a different computation of eigenvectors in LAPACKheev 6859984c4197SStefano Zampini -> The quality of the POD-computed basis will be the same */ 68609566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(correlation_mat, temp_constraints * temp_constraints)); 6861674ae819SStefano Zampini /* Store upper triangular part of correlation matrix */ 68629566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 68639566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6864674ae819SStefano Zampini for (j = 0; j < temp_constraints; j++) { 686548a46eb9SPierre 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)); 6866674ae819SStefano Zampini } 6867e310c8b4SStefano Zampini /* compute eigenvalues and eigenvectors of correlation matrix */ 68689566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_N)); 68699566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_LDA)); 6870674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX) 6871792fecdfSBarry Smith PetscCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &Blas_N, correlation_mat, &Blas_LDA, singular_vals, work, &lwork, &lierr)); 6872674ae819SStefano Zampini #else 6873792fecdfSBarry Smith PetscCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &Blas_N, correlation_mat, &Blas_LDA, singular_vals, work, &lwork, rwork, &lierr)); 6874674ae819SStefano Zampini #endif 68759566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 6876835f2295SStefano Zampini PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in SYEV Lapack routine %" PetscBLASInt_FMT, lierr); 6877984c4197SStefano Zampini /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */ 6878674ae819SStefano Zampini j = 0; 687987b3baaaSStefano Zampini while (j < temp_constraints && singular_vals[j] / singular_vals[temp_constraints - 1] < tol) j++; 6880674ae819SStefano Zampini total_counts = total_counts - j; 688145a1bb75SStefano Zampini valid_constraints = temp_constraints - j; 6882e310c8b4SStefano Zampini /* scale and copy POD basis into used quadrature memory */ 68839566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_M)); 68849566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_N)); 68859566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_K)); 68869566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 68879566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_LDB)); 68889566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDC)); 6889674ae819SStefano Zampini if (j < temp_constraints) { 6890984c4197SStefano Zampini PetscInt ii; 6891984c4197SStefano Zampini for (k = j; k < temp_constraints; k++) singular_vals[k] = 1.0 / PetscSqrtReal(singular_vals[k]); 68929566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6893792fecdfSBarry 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)); 68949566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 6895984c4197SStefano Zampini for (k = 0; k < temp_constraints - j; k++) { 6896ad540459SPierre 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]; 6897674ae819SStefano Zampini } 6898674ae819SStefano Zampini } 689955080a34SStefano Zampini } else { 690055080a34SStefano Zampini #if !defined(PETSC_MISSING_LAPACK_GESVD) 69019566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_M)); 69029566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_N)); 69039566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 69049566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6905674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX) 6906792fecdfSBarry 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)); 6907674ae819SStefano Zampini #else 6908792fecdfSBarry 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)); 6909674ae819SStefano Zampini #endif 6910835f2295SStefano Zampini PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in GESVD Lapack routine %" PetscBLASInt_FMT, lierr); 69119566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 6912984c4197SStefano Zampini /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */ 6913e310c8b4SStefano Zampini k = temp_constraints; 6914e310c8b4SStefano Zampini if (k > size_of_constraint) k = size_of_constraint; 6915674ae819SStefano Zampini j = 0; 691687b3baaaSStefano Zampini while (j < k && singular_vals[k - j - 1] / singular_vals[0] < tol) j++; 691745a1bb75SStefano Zampini valid_constraints = k - j; 6918911cabfeSStefano Zampini total_counts = total_counts - temp_constraints + valid_constraints; 691955080a34SStefano Zampini #else 692055080a34SStefano Zampini SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "This should not happen"); 6921984c4197SStefano Zampini #endif /* on missing GESVD */ 6922674ae819SStefano Zampini } 6923a773dcb8SStefano Zampini } 692455080a34SStefano Zampini } 69259162d606SStefano Zampini /* update pointers information */ 69269162d606SStefano Zampini if (valid_constraints) { 69279162d606SStefano Zampini constraints_n[total_counts_cc] = valid_constraints; 69289162d606SStefano Zampini constraints_idxs_ptr[total_counts_cc + 1] = constraints_idxs_ptr[total_counts_cc] + size_of_constraint; 69299162d606SStefano Zampini constraints_data_ptr[total_counts_cc + 1] = constraints_data_ptr[total_counts_cc] + size_of_constraint * valid_constraints; 69309162d606SStefano Zampini /* set change_of_basis flag */ 69313ba16761SJacob Faibussowitsch if (boolforchange) PetscCall(PetscBTSet(change_basis, total_counts_cc)); 6932b3d85658SStefano Zampini total_counts_cc++; 693345a1bb75SStefano Zampini } 693445a1bb75SStefano Zampini } 6935984c4197SStefano Zampini /* free workspace */ 69368f1c130eSStefano Zampini if (!skip_lapack) { 69379566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 6938984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX) 69399566063dSJacob Faibussowitsch PetscCall(PetscFree(rwork)); 6940984c4197SStefano Zampini #endif 69419566063dSJacob Faibussowitsch PetscCall(PetscFree(singular_vals)); 69429566063dSJacob Faibussowitsch PetscCall(PetscFree(correlation_mat)); 69439566063dSJacob Faibussowitsch PetscCall(PetscFree(temp_basis)); 6944984c4197SStefano Zampini } 694548a46eb9SPierre Jolivet for (k = 0; k < nnsp_size; k++) PetscCall(VecDestroy(&localnearnullsp[k])); 69469566063dSJacob Faibussowitsch PetscCall(PetscFree(localnearnullsp)); 6947cf5a6209SStefano Zampini /* free index sets of faces, edges and vertices */ 694832fe681dSStefano Zampini PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, &o_nf, &ISForFaces, &o_ne, &ISForEdges, &ISForVertices)); 694908122e43SStefano Zampini } else { 695008122e43SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 6951984c4197SStefano Zampini 695208122e43SStefano Zampini total_counts = 0; 695308122e43SStefano Zampini n_vertices = 0; 695448a46eb9SPierre Jolivet if (sub_schurs->is_vertices && pcbddc->use_vertices) PetscCall(ISGetLocalSize(sub_schurs->is_vertices, &n_vertices)); 695508122e43SStefano Zampini max_constraints = 0; 69569162d606SStefano Zampini total_counts_cc = 0; 695708122e43SStefano Zampini for (i = 0; i < sub_schurs->n_subs + n_vertices; i++) { 695808122e43SStefano Zampini total_counts += pcbddc->adaptive_constraints_n[i]; 69599162d606SStefano Zampini if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++; 696008122e43SStefano Zampini max_constraints = PetscMax(max_constraints, pcbddc->adaptive_constraints_n[i]); 696108122e43SStefano Zampini } 69629162d606SStefano Zampini constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr; 69639162d606SStefano Zampini constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr; 69649162d606SStefano Zampini constraints_idxs = pcbddc->adaptive_constraints_idxs; 69659162d606SStefano Zampini constraints_data = pcbddc->adaptive_constraints_data; 696674d5cdf7SStefano Zampini /* constraints_n differs from pcbddc->adaptive_constraints_n */ 69679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(total_counts_cc, &constraints_n)); 69689162d606SStefano Zampini total_counts_cc = 0; 69699162d606SStefano Zampini for (i = 0; i < sub_schurs->n_subs + n_vertices; i++) { 6970ad540459SPierre Jolivet if (pcbddc->adaptive_constraints_n[i]) constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i]; 697108122e43SStefano Zampini } 697208122e43SStefano Zampini 69738bec7fa6SStefano Zampini max_size_of_constraint = 0; 69749162d606SStefano 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]); 69759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(constraints_idxs_ptr[total_counts_cc], &constraints_idxs_B)); 697608122e43SStefano Zampini /* Change of basis */ 69779566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(total_counts_cc, &change_basis)); 697808122e43SStefano Zampini if (pcbddc->use_change_of_basis) { 697908122e43SStefano Zampini for (i = 0; i < sub_schurs->n_subs; i++) { 698048a46eb9SPierre Jolivet if (PetscBTLookup(sub_schurs->is_edge, i) || pcbddc->use_change_on_faces) PetscCall(PetscBTSet(change_basis, i + n_vertices)); 698108122e43SStefano Zampini } 698208122e43SStefano Zampini } 698308122e43SStefano Zampini } 6984984c4197SStefano Zampini pcbddc->local_primal_size = total_counts; 69859566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->local_primal_size + pcbddc->benign_n, &pcbddc->primal_indices_local_idxs)); 698608122e43SStefano Zampini 69879162d606SStefano Zampini /* map constraints_idxs in boundary numbering */ 698832fe681dSStefano Zampini if (pcbddc->use_change_of_basis) { 69899566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(pcis->BtoNmap, IS_GTOLM_DROP, constraints_idxs_ptr[total_counts_cc], constraints_idxs, &i, constraints_idxs_B)); 699063a3b9bcSJacob 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); 699132fe681dSStefano Zampini } 6992674ae819SStefano Zampini 6993674ae819SStefano Zampini /* Create constraint matrix */ 69949566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &pcbddc->ConstraintMatrix)); 69959566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->ConstraintMatrix, MATAIJ)); 69969566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->ConstraintMatrix, pcbddc->local_primal_size, pcis->n, pcbddc->local_primal_size, pcis->n)); 6997984c4197SStefano Zampini 6998984c4197SStefano Zampini /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */ 6999a717540cSStefano Zampini /* determine if a QR strategy is needed for change of basis */ 70005a52fde0SStefano Zampini qr_needed = pcbddc->use_qr_single; 70019566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(total_counts_cc, &qr_needed_idx)); 7002984c4197SStefano Zampini total_primal_vertices = 0; 7003b3d85658SStefano Zampini pcbddc->local_primal_size_cc = 0; 70049162d606SStefano Zampini for (i = 0; i < total_counts_cc; i++) { 70059162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[i + 1] - constraints_idxs_ptr[i]; 700672b8c272SStefano Zampini if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) { 70079162d606SStefano Zampini pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]]; 7008b3d85658SStefano Zampini pcbddc->local_primal_size_cc += 1; 700964efe560SStefano Zampini } else if (PetscBTLookup(change_basis, i)) { 7010ad540459SPierre Jolivet for (k = 0; k < constraints_n[i]; k++) pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i] + k]; 7011b3d85658SStefano Zampini pcbddc->local_primal_size_cc += constraints_n[i]; 701291af6908SStefano Zampini if (constraints_n[i] > 1 || pcbddc->use_qr_single) { 70133ba16761SJacob Faibussowitsch PetscCall(PetscBTSet(qr_needed_idx, i)); 7014a717540cSStefano Zampini qr_needed = PETSC_TRUE; 7015a717540cSStefano Zampini } 7016fa434743SStefano Zampini } else { 7017b3d85658SStefano Zampini pcbddc->local_primal_size_cc += 1; 7018fa434743SStefano Zampini } 7019a717540cSStefano Zampini } 7020b371cd4fSStefano Zampini /* note that the local variable n_vertices used below stores the number of pointwise constraints */ 7021b371cd4fSStefano Zampini pcbddc->n_vertices = total_primal_vertices; 7022674ae819SStefano Zampini /* permute indices in order to have a sorted set of vertices */ 70239566063dSJacob Faibussowitsch PetscCall(PetscSortInt(total_primal_vertices, pcbddc->primal_indices_local_idxs)); 70249566063dSJacob 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)); 70259566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pcbddc->local_primal_ref_node, pcbddc->primal_indices_local_idxs, total_primal_vertices)); 70260e6343abSStefano Zampini for (i = 0; i < total_primal_vertices; i++) pcbddc->local_primal_ref_mult[i] = 1; 7027984c4197SStefano Zampini 7028984c4197SStefano Zampini /* nonzero structure of constraint matrix */ 702974d5cdf7SStefano Zampini /* and get reference dof for local constraints */ 70309566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->local_primal_size, &nnz)); 7031984c4197SStefano Zampini for (i = 0; i < total_primal_vertices; i++) nnz[i] = 1; 703274d5cdf7SStefano Zampini 7033984c4197SStefano Zampini j = total_primal_vertices; 703474d5cdf7SStefano Zampini total_counts = total_primal_vertices; 7035b3d85658SStefano Zampini cum = total_primal_vertices; 70369162d606SStefano Zampini for (i = n_vertices; i < total_counts_cc; i++) { 70374641a718SStefano Zampini if (!PetscBTLookup(change_basis, i)) { 7038b3d85658SStefano Zampini pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]]; 7039b3d85658SStefano Zampini pcbddc->local_primal_ref_mult[cum] = constraints_n[i]; 7040b3d85658SStefano Zampini cum++; 70419162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[i + 1] - constraints_idxs_ptr[i]; 704274d5cdf7SStefano Zampini for (k = 0; k < constraints_n[i]; k++) { 704374d5cdf7SStefano Zampini pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i] + k]; 704474d5cdf7SStefano Zampini nnz[j + k] = size_of_constraint; 704574d5cdf7SStefano Zampini } 70469162d606SStefano Zampini j += constraints_n[i]; 7047674ae819SStefano Zampini } 7048674ae819SStefano Zampini } 70499566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix, 0, nnz)); 70509566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->ConstraintMatrix, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 7051a75bf7bfSStefano Zampini PetscCall(MatSetOption(pcbddc->ConstraintMatrix, MAT_IGNORE_ZERO_ENTRIES, PETSC_TRUE)); 70529566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 7053088faed8SStefano Zampini 7054674ae819SStefano Zampini /* set values in constraint matrix */ 705548a46eb9SPierre Jolivet for (i = 0; i < total_primal_vertices; i++) PetscCall(MatSetValue(pcbddc->ConstraintMatrix, i, pcbddc->local_primal_ref_node[i], 1.0, INSERT_VALUES)); 7056984c4197SStefano Zampini total_counts = total_primal_vertices; 70579162d606SStefano Zampini for (i = n_vertices; i < total_counts_cc; i++) { 70584641a718SStefano Zampini if (!PetscBTLookup(change_basis, i)) { 70599162d606SStefano Zampini PetscInt *cols; 70609162d606SStefano Zampini 70619162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[i + 1] - constraints_idxs_ptr[i]; 70629162d606SStefano Zampini cols = constraints_idxs + constraints_idxs_ptr[i]; 70639162d606SStefano Zampini for (k = 0; k < constraints_n[i]; k++) { 70649162d606SStefano Zampini PetscInt row = total_counts + k; 70659162d606SStefano Zampini PetscScalar *vals; 70669162d606SStefano Zampini 70679162d606SStefano Zampini vals = constraints_data + constraints_data_ptr[i] + k * size_of_constraint; 70689566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->ConstraintMatrix, 1, &row, size_of_constraint, cols, vals, INSERT_VALUES)); 70699162d606SStefano Zampini } 70709162d606SStefano Zampini total_counts += constraints_n[i]; 7071674ae819SStefano Zampini } 7072674ae819SStefano Zampini } 7073674ae819SStefano Zampini /* assembling */ 70749566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pcbddc->ConstraintMatrix, MAT_FINAL_ASSEMBLY)); 70759566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->ConstraintMatrix, MAT_FINAL_ASSEMBLY)); 70769566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(pcbddc->ConstraintMatrix, (PetscObject)pc, "-pc_bddc_constraint_mat_view")); 7077088faed8SStefano Zampini 7078674ae819SStefano Zampini /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */ 7079674ae819SStefano Zampini if (pcbddc->use_change_of_basis) { 7080026de310SStefano Zampini /* dual and primal dofs on a single cc */ 7081984c4197SStefano Zampini PetscInt dual_dofs, primal_dofs; 7082984c4197SStefano Zampini /* working stuff for GEQRF */ 70835a52fde0SStefano Zampini PetscScalar *qr_basis = NULL, *qr_tau = NULL, *qr_work = NULL, lqr_work_t; 7084984c4197SStefano Zampini PetscBLASInt lqr_work; 7085984c4197SStefano Zampini /* working stuff for UNGQR */ 70863c377650SSatish Balay PetscScalar *gqr_work = NULL, lgqr_work_t = 0.0; 7087984c4197SStefano Zampini PetscBLASInt lgqr_work; 7088984c4197SStefano Zampini /* working stuff for TRTRS */ 70895a52fde0SStefano Zampini PetscScalar *trs_rhs = NULL; 70903f08241aSStefano Zampini PetscBLASInt Blas_NRHS; 7091984c4197SStefano Zampini /* pointers for values insertion into change of basis matrix */ 7092984c4197SStefano Zampini PetscInt *start_rows, *start_cols; 7093984c4197SStefano Zampini PetscScalar *start_vals; 7094984c4197SStefano Zampini /* working stuff for values insertion */ 70954641a718SStefano Zampini PetscBT is_primal; 709664efe560SStefano Zampini PetscInt *aux_primal_numbering_B; 7097906d46d4SStefano Zampini /* matrix sizes */ 7098906d46d4SStefano Zampini PetscInt global_size, local_size; 7099906d46d4SStefano Zampini /* temporary change of basis */ 7100906d46d4SStefano Zampini Mat localChangeOfBasisMatrix; 7101cf5a6209SStefano Zampini /* extra space for debugging */ 71025a52fde0SStefano Zampini PetscScalar *dbg_work = NULL; 7103984c4197SStefano Zampini 71049566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &localChangeOfBasisMatrix)); 71059566063dSJacob Faibussowitsch PetscCall(MatSetType(localChangeOfBasisMatrix, MATAIJ)); 71069566063dSJacob Faibussowitsch PetscCall(MatSetSizes(localChangeOfBasisMatrix, pcis->n, pcis->n, pcis->n, pcis->n)); 7107906d46d4SStefano Zampini /* nonzeros for local mat */ 71089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n, &nnz)); 71091dd7afcfSStefano Zampini if (!pcbddc->benign_change || pcbddc->fake_change) { 7110bbb9e6c6SStefano Zampini for (i = 0; i < pcis->n; i++) nnz[i] = 1; 71111dd7afcfSStefano Zampini } else { 71121dd7afcfSStefano Zampini const PetscInt *ii; 71131dd7afcfSStefano Zampini PetscInt n; 71141dd7afcfSStefano Zampini PetscBool flg_row; 71159566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(pcbddc->benign_change, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, NULL, &flg_row)); 71161dd7afcfSStefano Zampini for (i = 0; i < n; i++) nnz[i] = ii[i + 1] - ii[i]; 71179566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(pcbddc->benign_change, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, NULL, &flg_row)); 71181dd7afcfSStefano Zampini } 71199162d606SStefano Zampini for (i = n_vertices; i < total_counts_cc; i++) { 7120a717540cSStefano Zampini if (PetscBTLookup(change_basis, i)) { 71219162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[i + 1] - constraints_idxs_ptr[i]; 7122a717540cSStefano Zampini if (PetscBTLookup(qr_needed_idx, i)) { 71239162d606SStefano Zampini for (j = 0; j < size_of_constraint; j++) nnz[constraints_idxs[constraints_idxs_ptr[i] + j]] = size_of_constraint; 7124a717540cSStefano Zampini } else { 71259162d606SStefano Zampini nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint; 71269162d606SStefano Zampini for (j = 1; j < size_of_constraint; j++) nnz[constraints_idxs[constraints_idxs_ptr[i] + j]] = 2; 7127a717540cSStefano Zampini } 7128a717540cSStefano Zampini } 7129a717540cSStefano Zampini } 71309566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(localChangeOfBasisMatrix, 0, nnz)); 71319566063dSJacob Faibussowitsch PetscCall(MatSetOption(localChangeOfBasisMatrix, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 71329566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 71331dd7afcfSStefano Zampini /* Set interior change in the matrix */ 71341dd7afcfSStefano Zampini if (!pcbddc->benign_change || pcbddc->fake_change) { 713548a46eb9SPierre Jolivet for (i = 0; i < pcis->n; i++) PetscCall(MatSetValue(localChangeOfBasisMatrix, i, i, 1.0, INSERT_VALUES)); 71361dd7afcfSStefano Zampini } else { 71371dd7afcfSStefano Zampini const PetscInt *ii, *jj; 71381dd7afcfSStefano Zampini PetscScalar *aa; 71391dd7afcfSStefano Zampini PetscInt n; 71401dd7afcfSStefano Zampini PetscBool flg_row; 71419566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(pcbddc->benign_change, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &flg_row)); 71429566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(pcbddc->benign_change, &aa)); 714348a46eb9SPierre 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)); 71449566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(pcbddc->benign_change, &aa)); 71459566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(pcbddc->benign_change, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &flg_row)); 71461dd7afcfSStefano Zampini } 7147a717540cSStefano Zampini 7148a717540cSStefano Zampini if (pcbddc->dbg_flag) { 71499566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "--------------------------------------------------------------\n")); 71509566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Checking change of basis computation for subdomain %04d\n", PetscGlobalRank)); 7151a717540cSStefano Zampini } 7152a717540cSStefano Zampini 7153a717540cSStefano Zampini /* Now we loop on the constraints which need a change of basis */ 7154a717540cSStefano Zampini /* 7155a717540cSStefano Zampini Change of basis matrix is evaluated similarly to the FIRST APPROACH in 7156a717540cSStefano Zampini Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1) 7157a717540cSStefano Zampini 71587c625d9fSStefano Zampini Basic blocks of change of basis matrix T computed: 7159a717540cSStefano Zampini 71607c625d9fSStefano 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) 7161a6b551f4SStefano Zampini 7162a6b551f4SStefano Zampini | 1 0 ... 0 s_1/S | 7163a6b551f4SStefano Zampini | 0 1 ... 0 s_2/S | 7164a717540cSStefano Zampini | ... | 7165a6b551f4SStefano Zampini | 0 ... 1 s_{n-1}/S | 7166a6b551f4SStefano Zampini | -s_1/s_n ... -s_{n-1}/s_n s_n/S | 7167a717540cSStefano Zampini 7168a6b551f4SStefano Zampini with S = \sum_{i=1}^n s_i^2 7169a6b551f4SStefano Zampini NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering 7170a6b551f4SStefano Zampini in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering 7171a6b551f4SStefano Zampini 7172a6b551f4SStefano Zampini - QR decomposition of constraints otherwise 7173a717540cSStefano Zampini */ 71745a52fde0SStefano Zampini if (qr_needed && max_size_of_constraint) { 7175984c4197SStefano Zampini /* space to store Q */ 71769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_size_of_constraint * max_size_of_constraint, &qr_basis)); 71774e64d54eSstefano_zampini /* array to store scaling factors for reflectors */ 71789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_constraints, &qr_tau)); 7179984c4197SStefano Zampini /* first we issue queries for optimal work */ 71809566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_size_of_constraint, &Blas_M)); 71819566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_constraints, &Blas_N)); 71829566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_size_of_constraint, &Blas_LDA)); 7183984c4197SStefano Zampini lqr_work = -1; 7184792fecdfSBarry Smith PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&Blas_M, &Blas_N, qr_basis, &Blas_LDA, qr_tau, &lqr_work_t, &lqr_work, &lierr)); 7185835f2295SStefano Zampini PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in query to GEQRF Lapack routine %" PetscBLASInt_FMT, lierr); 71869566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t), &lqr_work)); 718759b05608SBarry Smith PetscCall(PetscMalloc1(lqr_work, &qr_work)); 7188984c4197SStefano Zampini lgqr_work = -1; 71899566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_size_of_constraint, &Blas_M)); 71909566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_size_of_constraint, &Blas_N)); 71919566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_constraints, &Blas_K)); 71929566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_size_of_constraint, &Blas_LDA)); 71933f08241aSStefano Zampini if (Blas_K > Blas_M) Blas_K = Blas_M; /* adjust just for computing optimal work */ 7194792fecdfSBarry Smith PetscCallBLAS("LAPACKorgqr", LAPACKorgqr_(&Blas_M, &Blas_N, &Blas_K, qr_basis, &Blas_LDA, qr_tau, &lgqr_work_t, &lgqr_work, &lierr)); 7195835f2295SStefano Zampini PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in query to ORGQR/UNGQR Lapack routine %" PetscBLASInt_FMT, lierr); 71969566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t), &lgqr_work)); 719759b05608SBarry Smith PetscCall(PetscMalloc1(lgqr_work, &gqr_work)); 7198984c4197SStefano Zampini /* array to store rhs and solution of triangular solver */ 71999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_constraints * max_constraints, &trs_rhs)); 7200a717540cSStefano Zampini /* allocating workspace for check */ 720148a46eb9SPierre Jolivet if (pcbddc->dbg_flag) PetscCall(PetscMalloc1(max_size_of_constraint * (max_constraints + max_size_of_constraint), &dbg_work)); 7202a717540cSStefano Zampini } 7203984c4197SStefano Zampini /* array to store whether a node is primal or not */ 72049566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(pcis->n_B, &is_primal)); 72059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(total_primal_vertices, &aux_primal_numbering_B)); 72069566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(pcis->BtoNmap, IS_GTOLM_DROP, total_primal_vertices, pcbddc->local_primal_ref_node, &i, aux_primal_numbering_B)); 720763a3b9bcSJacob 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); 720848a46eb9SPierre Jolivet for (i = 0; i < total_primal_vertices; i++) PetscCall(PetscBTSet(is_primal, aux_primal_numbering_B[i])); 72099566063dSJacob Faibussowitsch PetscCall(PetscFree(aux_primal_numbering_B)); 7210984c4197SStefano Zampini 7211a717540cSStefano Zampini /* loop on constraints and see whether or not they need a change of basis and compute it */ 72129162d606SStefano Zampini for (total_counts = n_vertices; total_counts < total_counts_cc; total_counts++) { 72139162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[total_counts + 1] - constraints_idxs_ptr[total_counts]; 72144641a718SStefano Zampini if (PetscBTLookup(change_basis, total_counts)) { 7215984c4197SStefano Zampini /* get constraint info */ 72169162d606SStefano Zampini primal_dofs = constraints_n[total_counts]; 7217984c4197SStefano Zampini dual_dofs = size_of_constraint - primal_dofs; 7218984c4197SStefano Zampini 721948a46eb9SPierre 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)); 7220984c4197SStefano Zampini 7221fa434743SStefano Zampini if (PetscBTLookup(qr_needed_idx, total_counts)) { /* QR */ 7222a717540cSStefano Zampini 7223a717540cSStefano Zampini /* copy quadrature constraints for change of basis check */ 722448a46eb9SPierre Jolivet if (pcbddc->dbg_flag) PetscCall(PetscArraycpy(dbg_work, &constraints_data[constraints_data_ptr[total_counts]], size_of_constraint * primal_dofs)); 7225984c4197SStefano Zampini /* copy temporary constraints into larger work vector (in order to store all columns of Q) */ 72269566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(qr_basis, &constraints_data[constraints_data_ptr[total_counts]], size_of_constraint * primal_dofs)); 7227984c4197SStefano Zampini 7228984c4197SStefano Zampini /* compute QR decomposition of constraints */ 72299566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_M)); 72309566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_N)); 72319566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 72329566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 7233792fecdfSBarry Smith PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&Blas_M, &Blas_N, qr_basis, &Blas_LDA, qr_tau, qr_work, &lqr_work, &lierr)); 7234835f2295SStefano Zampini PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in GEQRF Lapack routine %" PetscBLASInt_FMT, lierr); 72359566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 7236984c4197SStefano Zampini 7237a5b23f4aSJose E. Roman /* explicitly compute R^-T */ 72389566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(trs_rhs, primal_dofs * primal_dofs)); 7239984c4197SStefano Zampini for (j = 0; j < primal_dofs; j++) trs_rhs[j * (primal_dofs + 1)] = 1.0; 72409566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_N)); 72419566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_NRHS)); 72429566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 72439566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_LDB)); 72449566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 7245792fecdfSBarry Smith PetscCallBLAS("LAPACKtrtrs", LAPACKtrtrs_("U", "T", "N", &Blas_N, &Blas_NRHS, qr_basis, &Blas_LDA, trs_rhs, &Blas_LDB, &lierr)); 7246835f2295SStefano Zampini PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in TRTRS Lapack routine %" PetscBLASInt_FMT, lierr); 72479566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 7248984c4197SStefano Zampini 7249a717540cSStefano Zampini /* explicitly compute all columns of Q (Q = [Q1 | Q2]) overwriting QR factorization in qr_basis */ 72509566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_M)); 72519566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 72529566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_K)); 72539566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 72549566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 7255792fecdfSBarry Smith PetscCallBLAS("LAPACKorgqr", LAPACKorgqr_(&Blas_M, &Blas_N, &Blas_K, qr_basis, &Blas_LDA, qr_tau, gqr_work, &lgqr_work, &lierr)); 7256835f2295SStefano Zampini PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ORGQR/UNGQR Lapack routine %" PetscBLASInt_FMT, lierr); 72579566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 7258984c4197SStefano Zampini 7259984c4197SStefano Zampini /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints 7260984c4197SStefano Zampini i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below) 7261984c4197SStefano Zampini where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */ 72629566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_M)); 72639566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_N)); 72649566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_K)); 72659566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 72669566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_LDB)); 72679566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDC)); 72689566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 7269792fecdfSBarry 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)); 72709566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 72719566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(qr_basis, &constraints_data[constraints_data_ptr[total_counts]], size_of_constraint * primal_dofs)); 7272984c4197SStefano Zampini 7273984c4197SStefano Zampini /* insert values in change of basis matrix respecting global ordering of new primal dofs */ 72749162d606SStefano Zampini start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]]; 7275984c4197SStefano Zampini /* insert cols for primal dofs */ 7276984c4197SStefano Zampini for (j = 0; j < primal_dofs; j++) { 7277984c4197SStefano Zampini start_vals = &qr_basis[j * size_of_constraint]; 72789162d606SStefano Zampini start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts] + j]; 72799566063dSJacob Faibussowitsch PetscCall(MatSetValues(localChangeOfBasisMatrix, size_of_constraint, start_rows, 1, start_cols, start_vals, INSERT_VALUES)); 7280984c4197SStefano Zampini } 7281984c4197SStefano Zampini /* insert cols for dual dofs */ 7282984c4197SStefano Zampini for (j = 0, k = 0; j < dual_dofs; k++) { 72839162d606SStefano Zampini if (!PetscBTLookup(is_primal, constraints_idxs_B[constraints_idxs_ptr[total_counts] + k])) { 7284984c4197SStefano Zampini start_vals = &qr_basis[(primal_dofs + j) * size_of_constraint]; 72859162d606SStefano Zampini start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts] + k]; 72869566063dSJacob Faibussowitsch PetscCall(MatSetValues(localChangeOfBasisMatrix, size_of_constraint, start_rows, 1, start_cols, start_vals, INSERT_VALUES)); 7287984c4197SStefano Zampini j++; 7288674ae819SStefano Zampini } 7289674ae819SStefano Zampini } 7290984c4197SStefano Zampini 7291984c4197SStefano Zampini /* check change of basis */ 7292984c4197SStefano Zampini if (pcbddc->dbg_flag) { 7293984c4197SStefano Zampini PetscInt ii, jj; 7294984c4197SStefano Zampini PetscBool valid_qr = PETSC_TRUE; 72959566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_M)); 72969566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 72979566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_K)); 72989566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 72999566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDB)); 73009566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_LDC)); 73019566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 7302792fecdfSBarry 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)); 73039566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 7304984c4197SStefano Zampini for (jj = 0; jj < size_of_constraint; jj++) { 7305984c4197SStefano Zampini for (ii = 0; ii < primal_dofs; ii++) { 7306cf5a6209SStefano Zampini if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint * primal_dofs + jj * primal_dofs + ii]) > 1.e-12) valid_qr = PETSC_FALSE; 7307c068d9bbSLisandro 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; 7308674ae819SStefano Zampini } 7309674ae819SStefano Zampini } 7310984c4197SStefano Zampini if (!valid_qr) { 73119566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "\t-> wrong change of basis!\n")); 7312984c4197SStefano Zampini for (jj = 0; jj < size_of_constraint; jj++) { 7313984c4197SStefano Zampini for (ii = 0; ii < primal_dofs; ii++) { 7314cf5a6209SStefano Zampini if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint * primal_dofs + jj * primal_dofs + ii]) > 1.e-12) { 731563a3b9bcSJacob 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]))); 7316674ae819SStefano Zampini } 7317c068d9bbSLisandro Dalcin if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint * primal_dofs + jj * primal_dofs + ii] - (PetscReal)1) > 1.e-12) { 731863a3b9bcSJacob 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]))); 7319984c4197SStefano Zampini } 7320984c4197SStefano Zampini } 7321984c4197SStefano Zampini } 7322674ae819SStefano Zampini } else { 73239566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "\t-> right change of basis!\n")); 7324674ae819SStefano Zampini } 7325674ae819SStefano Zampini } 7326a717540cSStefano Zampini } else { /* simple transformation block */ 7327a717540cSStefano Zampini PetscInt row, col; 7328a6b551f4SStefano Zampini PetscScalar val, norm; 7329a6b551f4SStefano Zampini 73309566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 7331792fecdfSBarry 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)); 7332a717540cSStefano Zampini for (j = 0; j < size_of_constraint; j++) { 73339162d606SStefano Zampini PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts] + j]; 73349162d606SStefano Zampini row = constraints_idxs[constraints_idxs_ptr[total_counts] + j]; 7335bbb9e6c6SStefano Zampini if (!PetscBTLookup(is_primal, row_B)) { 73369162d606SStefano Zampini col = constraints_idxs[constraints_idxs_ptr[total_counts]]; 73379566063dSJacob Faibussowitsch PetscCall(MatSetValue(localChangeOfBasisMatrix, row, row, 1.0, INSERT_VALUES)); 73389566063dSJacob Faibussowitsch PetscCall(MatSetValue(localChangeOfBasisMatrix, row, col, constraints_data[constraints_data_ptr[total_counts] + j] / norm, INSERT_VALUES)); 7339a717540cSStefano Zampini } else { 7340a717540cSStefano Zampini for (k = 0; k < size_of_constraint; k++) { 73419162d606SStefano Zampini col = constraints_idxs[constraints_idxs_ptr[total_counts] + k]; 7342a717540cSStefano Zampini if (row != col) { 73439162d606SStefano Zampini val = -constraints_data[constraints_data_ptr[total_counts] + k] / constraints_data[constraints_data_ptr[total_counts]]; 7344a717540cSStefano Zampini } else { 73459162d606SStefano Zampini val = constraints_data[constraints_data_ptr[total_counts]] / norm; 7346a717540cSStefano Zampini } 73479566063dSJacob Faibussowitsch PetscCall(MatSetValue(localChangeOfBasisMatrix, row, col, val, INSERT_VALUES)); 7348a717540cSStefano Zampini } 7349a717540cSStefano Zampini } 7350a717540cSStefano Zampini } 735148a46eb9SPierre Jolivet if (pcbddc->dbg_flag) PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "\t-> using standard change of basis\n")); 7352a717540cSStefano Zampini } 7353984c4197SStefano Zampini } else { 735448a46eb9SPierre 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)); 7355674ae819SStefano Zampini } 7356674ae819SStefano Zampini } 7357a717540cSStefano Zampini 7358a717540cSStefano Zampini /* free workspace */ 7359a717540cSStefano Zampini if (qr_needed) { 73601baa6e33SBarry Smith if (pcbddc->dbg_flag) PetscCall(PetscFree(dbg_work)); 73619566063dSJacob Faibussowitsch PetscCall(PetscFree(trs_rhs)); 73629566063dSJacob Faibussowitsch PetscCall(PetscFree(qr_tau)); 73639566063dSJacob Faibussowitsch PetscCall(PetscFree(qr_work)); 73649566063dSJacob Faibussowitsch PetscCall(PetscFree(gqr_work)); 73659566063dSJacob Faibussowitsch PetscCall(PetscFree(qr_basis)); 7366674ae819SStefano Zampini } 73679566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&is_primal)); 73689566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(localChangeOfBasisMatrix, MAT_FINAL_ASSEMBLY)); 73699566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(localChangeOfBasisMatrix, MAT_FINAL_ASSEMBLY)); 7370906d46d4SStefano Zampini 7371906d46d4SStefano Zampini /* assembling of global change of variable */ 737288c03ad3SStefano Zampini if (!pcbddc->fake_change) { 7373bbb9e6c6SStefano Zampini Mat tmat; 737416f15bc4SStefano Zampini 73759566063dSJacob Faibussowitsch PetscCall(VecGetSize(pcis->vec1_global, &global_size)); 73769566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(pcis->vec1_global, &local_size)); 73779566063dSJacob Faibussowitsch PetscCall(MatDuplicate(pc->pmat, MAT_DO_NOT_COPY_VALUES, &tmat)); 73789566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(tmat, localChangeOfBasisMatrix)); 73799566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(tmat, MAT_FINAL_ASSEMBLY)); 73809566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(tmat, MAT_FINAL_ASSEMBLY)); 7381ac7f1a8bSStefano Zampini PetscCall(MatConvert(tmat, MATAIJ, MAT_INITIAL_MATRIX, &pcbddc->ChangeOfBasisMatrix)); 73829566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tmat)); 73839566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_global, 0.0)); 73849566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_N, 1.0)); 73859566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_N, pcis->vec1_global, ADD_VALUES, SCATTER_REVERSE)); 73869566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_N, pcis->vec1_global, ADD_VALUES, SCATTER_REVERSE)); 73879566063dSJacob Faibussowitsch PetscCall(VecReciprocal(pcis->vec1_global)); 73889566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(pcbddc->ChangeOfBasisMatrix, pcis->vec1_global, NULL)); 738988c03ad3SStefano Zampini 7390906d46d4SStefano Zampini /* check */ 7391906d46d4SStefano Zampini if (pcbddc->dbg_flag) { 7392906d46d4SStefano Zampini PetscReal error; 7393906d46d4SStefano Zampini Vec x, x_change; 7394906d46d4SStefano Zampini 73959566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_global, &x)); 73969566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_global, &x_change)); 73979566063dSJacob Faibussowitsch PetscCall(VecSetRandom(x, NULL)); 73989566063dSJacob Faibussowitsch PetscCall(VecCopy(x, pcis->vec1_global)); 73999566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, x, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD)); 74009566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, x, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD)); 74019566063dSJacob Faibussowitsch PetscCall(MatMult(localChangeOfBasisMatrix, pcis->vec1_N, pcis->vec2_N)); 74029566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, pcis->vec2_N, x, INSERT_VALUES, SCATTER_REVERSE)); 74039566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, pcis->vec2_N, x, INSERT_VALUES, SCATTER_REVERSE)); 74049566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcis->vec1_global, x_change)); 74059566063dSJacob Faibussowitsch PetscCall(VecAXPY(x, -1.0, x_change)); 74069566063dSJacob Faibussowitsch PetscCall(VecNorm(x, NORM_INFINITY, &error)); 7407049d1499SBarry Smith PetscCheck(error <= PETSC_SMALL, PetscObjectComm((PetscObject)pc), PETSC_ERR_PLIB, "Error global vs local change on N: %1.6e", (double)error); 74089566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 74099566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x_change)); 7410906d46d4SStefano Zampini } 7411b96c3477SStefano Zampini /* adapt sub_schurs computed (if any) */ 7412b96c3477SStefano Zampini if (pcbddc->use_deluxe_scaling) { 7413b96c3477SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 7414bf3a8328SStefano Zampini 741508401ef6SPierre 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"); 7416b334f244SStefano Zampini if (sub_schurs && sub_schurs->S_Ej_all) { 7417ac632422SStefano Zampini Mat S_new, tmat; 7418bf3a8328SStefano Zampini IS is_all_N, is_V_Sall = NULL; 7419bbb9e6c6SStefano Zampini 74209566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(pcis->BtoNmap, sub_schurs->is_Ej_all, &is_all_N)); 74219566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(localChangeOfBasisMatrix, is_all_N, is_all_N, MAT_INITIAL_MATRIX, &tmat)); 7422bf3a8328SStefano Zampini if (pcbddc->deluxe_zerorows) { 7423bf3a8328SStefano Zampini ISLocalToGlobalMapping NtoSall; 7424bf3a8328SStefano Zampini IS is_V; 74259566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, pcbddc->n_vertices, pcbddc->local_primal_ref_node, PETSC_COPY_VALUES, &is_V)); 74269566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is_all_N, &NtoSall)); 74279566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(NtoSall, IS_GTOLM_DROP, is_V, &is_V_Sall)); 74289566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&NtoSall)); 74299566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_V)); 7430bf3a8328SStefano Zampini } 74319566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_all_N)); 74329566063dSJacob Faibussowitsch PetscCall(MatPtAP(sub_schurs->S_Ej_all, tmat, MAT_INITIAL_MATRIX, 1.0, &S_new)); 74339566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sub_schurs->S_Ej_all)); 74349566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)S_new)); 7435bf3a8328SStefano Zampini if (pcbddc->deluxe_zerorows) { 7436bf3a8328SStefano Zampini const PetscScalar *array; 7437bf3a8328SStefano Zampini const PetscInt *idxs_V, *idxs_all; 7438bf3a8328SStefano Zampini PetscInt i, n_V; 7439bf3a8328SStefano Zampini 74409566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumnsIS(S_new, is_V_Sall, 1., NULL, NULL)); 74419566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is_V_Sall, &n_V)); 74429566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is_V_Sall, &idxs_V)); 74439566063dSJacob Faibussowitsch PetscCall(ISGetIndices(sub_schurs->is_Ej_all, &idxs_all)); 74449566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(pcis->D, &array)); 7445b087196eSStefano Zampini for (i = 0; i < n_V; i++) { 7446b087196eSStefano Zampini PetscScalar val; 7447b087196eSStefano Zampini PetscInt idx; 7448b087196eSStefano Zampini 7449b087196eSStefano Zampini idx = idxs_V[i]; 7450b087196eSStefano Zampini val = array[idxs_all[idxs_V[i]]]; 74519566063dSJacob Faibussowitsch PetscCall(MatSetValue(S_new, idx, idx, val, INSERT_VALUES)); 7452b087196eSStefano Zampini } 74539566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(S_new, MAT_FINAL_ASSEMBLY)); 74549566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(S_new, MAT_FINAL_ASSEMBLY)); 74559566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(pcis->D, &array)); 74569566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(sub_schurs->is_Ej_all, &idxs_all)); 74579566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is_V_Sall, &idxs_V)); 7458bf3a8328SStefano Zampini } 7459ac632422SStefano Zampini sub_schurs->S_Ej_all = S_new; 74609566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_new)); 7461ac632422SStefano Zampini if (sub_schurs->sum_S_Ej_all) { 74629566063dSJacob Faibussowitsch PetscCall(MatPtAP(sub_schurs->sum_S_Ej_all, tmat, MAT_INITIAL_MATRIX, 1.0, &S_new)); 74639566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sub_schurs->sum_S_Ej_all)); 74649566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)S_new)); 74651baa6e33SBarry Smith if (pcbddc->deluxe_zerorows) PetscCall(MatZeroRowsColumnsIS(S_new, is_V_Sall, 1., NULL, NULL)); 7466ac632422SStefano Zampini sub_schurs->sum_S_Ej_all = S_new; 74679566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_new)); 7468ac632422SStefano Zampini } 74699566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_V_Sall)); 74709566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tmat)); 7471b96c3477SStefano Zampini } 7472c9db6a07SStefano Zampini /* destroy any change of basis context in sub_schurs */ 7473b334f244SStefano Zampini if (sub_schurs && sub_schurs->change) { 7474c9db6a07SStefano Zampini PetscInt i; 7475c9db6a07SStefano Zampini 747648a46eb9SPierre Jolivet for (i = 0; i < sub_schurs->n_subs; i++) PetscCall(KSPDestroy(&sub_schurs->change[i])); 74779566063dSJacob Faibussowitsch PetscCall(PetscFree(sub_schurs->change)); 7478c9db6a07SStefano Zampini } 7479b96c3477SStefano Zampini } 748016909a7fSStefano Zampini if (pcbddc->switch_static) { /* need to save the local change */ 748116909a7fSStefano Zampini pcbddc->switch_static_change = localChangeOfBasisMatrix; 748216909a7fSStefano Zampini } else { 74839566063dSJacob Faibussowitsch PetscCall(MatDestroy(&localChangeOfBasisMatrix)); 748416909a7fSStefano Zampini } 74851dd7afcfSStefano Zampini /* determine if any process has changed the pressures locally */ 748627b6a85dSStefano Zampini pcbddc->change_interior = pcbddc->benign_have_null; 748772b8c272SStefano Zampini } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */ 74889566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->ConstraintMatrix)); 748972b8c272SStefano Zampini pcbddc->ConstraintMatrix = localChangeOfBasisMatrix; 749072b8c272SStefano Zampini pcbddc->use_qr_single = qr_needed; 749172b8c272SStefano Zampini } 74921dd7afcfSStefano Zampini } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) { 749327b6a85dSStefano Zampini if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) { 74949566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix)); 7495b9b85e73SStefano Zampini pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix; 7496906d46d4SStefano Zampini } else { 74971dd7afcfSStefano Zampini Mat benign_global = NULL; 749827b6a85dSStefano Zampini if (pcbddc->benign_have_null) { 74991dd7afcfSStefano Zampini Mat M; 75001dd7afcfSStefano Zampini 75019e9b7b1fSStefano Zampini pcbddc->change_interior = PETSC_TRUE; 75029566063dSJacob Faibussowitsch PetscCall(VecCopy(matis->counter, pcis->vec1_N)); 75039566063dSJacob Faibussowitsch PetscCall(VecReciprocal(pcis->vec1_N)); 75049566063dSJacob Faibussowitsch PetscCall(MatDuplicate(pc->pmat, MAT_DO_NOT_COPY_VALUES, &benign_global)); 75059e9b7b1fSStefano Zampini if (pcbddc->benign_change) { 75069566063dSJacob Faibussowitsch PetscCall(MatDuplicate(pcbddc->benign_change, MAT_COPY_VALUES, &M)); 75079566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(M, pcis->vec1_N, NULL)); 7508906d46d4SStefano Zampini } else { 75099566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, pcis->n, pcis->n, 1, NULL, &M)); 75109566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(M, pcis->vec1_N, INSERT_VALUES)); 7511906d46d4SStefano Zampini } 75129566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(benign_global, M)); 75139566063dSJacob Faibussowitsch PetscCall(MatDestroy(&M)); 75149566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(benign_global, MAT_FINAL_ASSEMBLY)); 75159566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(benign_global, MAT_FINAL_ASSEMBLY)); 75161dd7afcfSStefano Zampini } 75171dd7afcfSStefano Zampini if (pcbddc->user_ChangeOfBasisMatrix) { 7518fb842aefSJose E. Roman PetscCall(MatMatMult(pcbddc->user_ChangeOfBasisMatrix, benign_global, MAT_INITIAL_MATRIX, PETSC_DETERMINE, &pcbddc->ChangeOfBasisMatrix)); 75199566063dSJacob Faibussowitsch PetscCall(MatDestroy(&benign_global)); 752027b6a85dSStefano Zampini } else if (pcbddc->benign_have_null) { 75211dd7afcfSStefano Zampini pcbddc->ChangeOfBasisMatrix = benign_global; 75221dd7afcfSStefano Zampini } 75231dd7afcfSStefano Zampini } 752416909a7fSStefano Zampini if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */ 752516909a7fSStefano Zampini IS is_global; 752616909a7fSStefano Zampini const PetscInt *gidxs; 752716909a7fSStefano Zampini 75289566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->rmapping, &gidxs)); 75299566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), pcis->n, gidxs, PETSC_COPY_VALUES, &is_global)); 75309566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->rmapping, &gidxs)); 75319566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix, is_global, is_global, &pcbddc->switch_static_change)); 75329566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_global)); 753316909a7fSStefano Zampini } 75341dd7afcfSStefano Zampini } 753548a46eb9SPierre Jolivet if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->work_change)); 7536a717540cSStefano Zampini 753772b8c272SStefano Zampini if (!pcbddc->fake_change) { 75384f1b2e48SStefano Zampini /* add pressure dofs to set of primal nodes for numbering purposes */ 75394f1b2e48SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) { 75404f1b2e48SStefano Zampini pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i]; 75414f1b2e48SStefano Zampini pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i]; 7542019a44ceSStefano Zampini pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1; 7543019a44ceSStefano Zampini pcbddc->local_primal_size_cc++; 7544019a44ceSStefano Zampini pcbddc->local_primal_size++; 7545019a44ceSStefano Zampini } 7546019a44ceSStefano Zampini 7547019a44ceSStefano Zampini /* check if a new primal space has been introduced (also take into account benign trick) */ 7548727cdba6SStefano Zampini pcbddc->new_primal_space_local = PETSC_TRUE; 7549727cdba6SStefano Zampini if (olocal_primal_size == pcbddc->local_primal_size) { 75509566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(pcbddc->local_primal_ref_node, olocal_primal_ref_node, olocal_primal_size_cc, &pcbddc->new_primal_space_local)); 7551c1c8e736SStefano Zampini pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local); 75520e6343abSStefano Zampini if (!pcbddc->new_primal_space_local) { 75539566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(pcbddc->local_primal_ref_mult, olocal_primal_ref_mult, olocal_primal_size_cc, &pcbddc->new_primal_space_local)); 7554727cdba6SStefano Zampini pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local); 7555727cdba6SStefano Zampini } 75560e6343abSStefano Zampini } 7557727cdba6SStefano Zampini /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */ 75585440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&pcbddc->new_primal_space_local, &pcbddc->new_primal_space, 1, MPI_C_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 755972b8c272SStefano Zampini } 75609566063dSJacob Faibussowitsch PetscCall(PetscFree2(olocal_primal_ref_node, olocal_primal_ref_mult)); 7561727cdba6SStefano Zampini 7562a717540cSStefano Zampini /* flush dbg viewer */ 75631baa6e33SBarry Smith if (pcbddc->dbg_flag) PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 7564a717540cSStefano Zampini 7565e310c8b4SStefano Zampini /* free workspace */ 75669566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&qr_needed_idx)); 75679566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&change_basis)); 756808122e43SStefano Zampini if (!pcbddc->adaptive_selection) { 75699566063dSJacob Faibussowitsch PetscCall(PetscFree3(constraints_idxs_ptr, constraints_data_ptr, constraints_n)); 75709566063dSJacob Faibussowitsch PetscCall(PetscFree3(constraints_data, constraints_idxs, constraints_idxs_B)); 757108122e43SStefano Zampini } else { 7572d0609cedSBarry 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)); 75739566063dSJacob Faibussowitsch PetscCall(PetscFree(constraints_n)); 75749566063dSJacob Faibussowitsch PetscCall(PetscFree(constraints_idxs_B)); 757508122e43SStefano Zampini } 75763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7577674ae819SStefano Zampini } 7578674ae819SStefano Zampini 7579d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCAnalyzeInterface(PC pc) 7580d71ae5a4SJacob Faibussowitsch { 758171582508SStefano Zampini ISLocalToGlobalMapping map; 7582674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 7583674ae819SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 758466da6bd7Sstefano_zampini PetscInt i, N; 758566da6bd7Sstefano_zampini PetscBool rcsr = PETSC_FALSE; 7586674ae819SStefano Zampini 7587674ae819SStefano Zampini PetscFunctionBegin; 75888af8fcf9SStefano Zampini if (pcbddc->recompute_topography) { 7589b03ebc13SStefano Zampini pcbddc->graphanalyzed = PETSC_FALSE; 75908e61c736SStefano Zampini /* Reset previously computed graph */ 75919566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphReset(pcbddc->mat_graph)); 7592674ae819SStefano Zampini /* Init local Graph struct */ 75939566063dSJacob Faibussowitsch PetscCall(MatGetSize(pc->pmat, &N, NULL)); 75949566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(pc->pmat, &map, NULL)); 75959566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphInit(pcbddc->mat_graph, map, N, pcbddc->graphmaxcount)); 7596674ae819SStefano Zampini 759748a46eb9SPierre Jolivet if (pcbddc->user_primal_vertices_local && !pcbddc->user_primal_vertices) PetscCall(PCBDDCConsistencyCheckIS(pc, MPI_LOR, &pcbddc->user_primal_vertices_local)); 7598575ad6abSStefano Zampini /* Check validity of the csr graph passed in by the user */ 75999371c9d4SSatish 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, 76009371c9d4SSatish Balay pcbddc->mat_graph->nvtxs); 76019577ea80SStefano Zampini 7602674ae819SStefano Zampini /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */ 760366da6bd7Sstefano_zampini if (!pcbddc->mat_graph->xadj && pcbddc->use_local_adj) { 76044d379d7bSStefano Zampini PetscInt *xadj, *adjncy; 76054d379d7bSStefano Zampini PetscInt nvtxs; 76069de2952eSStefano Zampini PetscBool flg_row; 76079de2952eSStefano Zampini Mat A; 7608674ae819SStefano Zampini 76099de2952eSStefano Zampini PetscCall(PetscObjectReference((PetscObject)matis->A)); 76109de2952eSStefano Zampini A = matis->A; 76119de2952eSStefano Zampini for (PetscInt i = 0; i < pcbddc->local_adj_square; i++) { 76129de2952eSStefano Zampini Mat AtA; 76139de2952eSStefano Zampini 76149de2952eSStefano Zampini PetscCall(MatProductCreate(A, A, NULL, &AtA)); 76159de2952eSStefano Zampini PetscCall(MatSetOptionsPrefix(AtA, "pc_bddc_graph_")); 76169de2952eSStefano Zampini PetscCall(MatProductSetType(AtA, MATPRODUCT_AtB)); 76179de2952eSStefano Zampini PetscCall(MatProductSetFromOptions(AtA)); 76189de2952eSStefano Zampini PetscCall(MatProductSymbolic(AtA)); 76199de2952eSStefano Zampini PetscCall(MatProductClear(AtA)); 76209de2952eSStefano Zampini /* we only need the sparsity, cheat and tell PETSc the matrix has been assembled */ 76219de2952eSStefano Zampini AtA->assembled = PETSC_TRUE; 76229de2952eSStefano Zampini PetscCall(MatDestroy(&A)); 76239de2952eSStefano Zampini A = AtA; 76249de2952eSStefano Zampini } 76259de2952eSStefano Zampini PetscCall(MatGetRowIJ(A, 0, PETSC_TRUE, PETSC_FALSE, &nvtxs, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &flg_row)); 76262fffb893SStefano Zampini if (flg_row) { 76279566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLocalAdjacencyGraph(pc, nvtxs, xadj, adjncy, PETSC_COPY_VALUES)); 7628b96c3477SStefano Zampini pcbddc->computed_rowadj = PETSC_TRUE; 76299de2952eSStefano Zampini PetscCall(MatRestoreRowIJ(A, 0, PETSC_TRUE, PETSC_FALSE, &nvtxs, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &flg_row)); 763066da6bd7Sstefano_zampini rcsr = PETSC_TRUE; 7631674ae819SStefano Zampini } 76329de2952eSStefano Zampini PetscCall(MatDestroy(&A)); 76339de2952eSStefano Zampini } 76341baa6e33SBarry Smith if (pcbddc->dbg_flag) PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 7635674ae819SStefano Zampini 7636ab8c8b98SStefano Zampini if (pcbddc->mat_graph->cdim && !pcbddc->mat_graph->cloc) { 7637ab8c8b98SStefano Zampini PetscReal *lcoords; 7638ab8c8b98SStefano Zampini PetscInt n; 7639ab8c8b98SStefano Zampini MPI_Datatype dimrealtype; 7640835f2295SStefano Zampini PetscMPIInt cdimi; 7641ab8c8b98SStefano Zampini 76424f819b78SStefano Zampini /* TODO: support for blocked */ 764363a3b9bcSJacob 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); 76449566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(matis->A, &n, NULL)); 76459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->mat_graph->cdim * n, &lcoords)); 7646835f2295SStefano Zampini PetscCall(PetscMPIIntCast(pcbddc->mat_graph->cdim, &cdimi)); 7647835f2295SStefano Zampini PetscCallMPI(MPI_Type_contiguous(cdimi, MPIU_REAL, &dimrealtype)); 76489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&dimrealtype)); 76499566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, dimrealtype, pcbddc->mat_graph->coords, lcoords, MPI_REPLACE)); 76509566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, dimrealtype, pcbddc->mat_graph->coords, lcoords, MPI_REPLACE)); 76519566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&dimrealtype)); 76529566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->mat_graph->coords)); 7653ab8c8b98SStefano Zampini 7654ab8c8b98SStefano Zampini pcbddc->mat_graph->coords = lcoords; 7655ab8c8b98SStefano Zampini pcbddc->mat_graph->cloc = PETSC_TRUE; 7656ab8c8b98SStefano Zampini pcbddc->mat_graph->cnloc = n; 7657ab8c8b98SStefano Zampini } 76589371c9d4SSatish 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, 76599371c9d4SSatish Balay pcbddc->mat_graph->nvtxs); 7660625961bdSStefano Zampini pcbddc->mat_graph->active_coords = (PetscBool)(pcbddc->corner_selection && pcbddc->mat_graph->cdim && !pcbddc->corner_selected); 7661ab8c8b98SStefano Zampini 76624f1b2e48SStefano Zampini /* attach info on disconnected subdomains if present */ 76634f1b2e48SStefano Zampini if (pcbddc->n_local_subs) { 766420c3699dSStefano Zampini PetscInt *local_subs, n, totn; 76654f1b2e48SStefano Zampini 76669566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(matis->A, &n, NULL)); 76679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &local_subs)); 766820c3699dSStefano Zampini for (i = 0; i < n; i++) local_subs[i] = pcbddc->n_local_subs; 76694f1b2e48SStefano Zampini for (i = 0; i < pcbddc->n_local_subs; i++) { 76704f1b2e48SStefano Zampini const PetscInt *idxs; 76714f1b2e48SStefano Zampini PetscInt nl, j; 76724f1b2e48SStefano Zampini 76739566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->local_subs[i], &nl)); 76749566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->local_subs[i], &idxs)); 767571582508SStefano Zampini for (j = 0; j < nl; j++) local_subs[idxs[j]] = i; 76769566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->local_subs[i], &idxs)); 76774f1b2e48SStefano Zampini } 767820c3699dSStefano Zampini for (i = 0, totn = 0; i < n; i++) totn = PetscMax(totn, local_subs[i]); 767920c3699dSStefano Zampini pcbddc->mat_graph->n_local_subs = totn + 1; 76804f1b2e48SStefano Zampini pcbddc->mat_graph->local_subs = local_subs; 76814f1b2e48SStefano Zampini } 76829de2952eSStefano Zampini 76839de2952eSStefano Zampini /* Setup of Graph */ 76849de2952eSStefano Zampini PetscCall(PCBDDCGraphSetUp(pcbddc->mat_graph, pcbddc->vertex_size, pcbddc->NeumannBoundariesLocal, pcbddc->DirichletBoundariesLocal, pcbddc->n_ISForDofsLocal, pcbddc->ISForDofsLocal, pcbddc->user_primal_vertices_local)); 76858af8fcf9SStefano Zampini } 76864f1b2e48SStefano Zampini 7687cac5312eSStefano Zampini if (!pcbddc->graphanalyzed) { 7688674ae819SStefano Zampini /* Graph's connected components analysis */ 76899566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph)); 769071582508SStefano Zampini pcbddc->graphanalyzed = PETSC_TRUE; 76914f819b78SStefano Zampini pcbddc->corner_selected = pcbddc->corner_selection; 76928af8fcf9SStefano Zampini } 769366da6bd7Sstefano_zampini if (rcsr) pcbddc->mat_graph->nvtxs_csr = 0; 76943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7695674ae819SStefano Zampini } 7696674ae819SStefano Zampini 7697d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt *nio, Vec vecs[]) 7698d71ae5a4SJacob Faibussowitsch { 7699295df10fSStefano Zampini PetscInt i, j, n; 77009a7d3425SStefano Zampini PetscScalar *alphas; 7701295df10fSStefano Zampini PetscReal norm, *onorms; 77029a7d3425SStefano Zampini 77039a7d3425SStefano Zampini PetscFunctionBegin; 7704295df10fSStefano Zampini n = *nio; 77053ba16761SJacob Faibussowitsch if (!n) PetscFunctionReturn(PETSC_SUCCESS); 77069566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n, &alphas, n, &onorms)); 77079566063dSJacob Faibussowitsch PetscCall(VecNormalize(vecs[0], &norm)); 770892cccca0SStefano Zampini if (norm < PETSC_SMALL) { 7709295df10fSStefano Zampini onorms[0] = 0.0; 77109566063dSJacob Faibussowitsch PetscCall(VecSet(vecs[0], 0.0)); 7711295df10fSStefano Zampini } else { 7712295df10fSStefano Zampini onorms[0] = norm; 771392cccca0SStefano Zampini } 7714295df10fSStefano Zampini 77158c0031efSStefano Zampini for (i = 1; i < n; i++) { 77169566063dSJacob Faibussowitsch PetscCall(VecMDot(vecs[i], i, vecs, alphas)); 77178c0031efSStefano Zampini for (j = 0; j < i; j++) alphas[j] = PetscConj(-alphas[j]); 77189566063dSJacob Faibussowitsch PetscCall(VecMAXPY(vecs[i], i, alphas, vecs)); 77199566063dSJacob Faibussowitsch PetscCall(VecNormalize(vecs[i], &norm)); 772092cccca0SStefano Zampini if (norm < PETSC_SMALL) { 7721295df10fSStefano Zampini onorms[i] = 0.0; 77229566063dSJacob Faibussowitsch PetscCall(VecSet(vecs[i], 0.0)); 7723295df10fSStefano Zampini } else { 7724295df10fSStefano Zampini onorms[i] = norm; 772592cccca0SStefano Zampini } 77269a7d3425SStefano Zampini } 7727295df10fSStefano Zampini /* push nonzero vectors at the beginning */ 7728295df10fSStefano Zampini for (i = 0; i < n; i++) { 7729295df10fSStefano Zampini if (onorms[i] == 0.0) { 7730295df10fSStefano Zampini for (j = i + 1; j < n; j++) { 7731295df10fSStefano Zampini if (onorms[j] != 0.0) { 77329566063dSJacob Faibussowitsch PetscCall(VecCopy(vecs[j], vecs[i])); 7733e1614d24SStefano Zampini onorms[i] = onorms[j]; 7734295df10fSStefano Zampini onorms[j] = 0.0; 7735e1614d24SStefano Zampini break; 7736295df10fSStefano Zampini } 7737295df10fSStefano Zampini } 7738295df10fSStefano Zampini } 7739295df10fSStefano Zampini } 7740295df10fSStefano Zampini for (i = 0, *nio = 0; i < n; i++) *nio += onorms[i] != 0.0 ? 1 : 0; 77419566063dSJacob Faibussowitsch PetscCall(PetscFree2(alphas, onorms)); 77423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 77439a7d3425SStefano Zampini } 77449a7d3425SStefano Zampini 7745ba38deedSJacob Faibussowitsch static PetscErrorCode PCBDDCMatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS *is_sends, PetscBool *have_void) 7746d71ae5a4SJacob Faibussowitsch { 7747e432b41dSStefano Zampini ISLocalToGlobalMapping mapping; 774857de7509SStefano Zampini Mat A; 7749e7931f94SStefano Zampini PetscInt n_neighs, *neighs, *n_shared, **shared; 7750e7931f94SStefano Zampini PetscMPIInt size, rank, color; 775152e5ac9dSStefano Zampini PetscInt *xadj, *adjncy; 775252e5ac9dSStefano Zampini PetscInt *adjncy_wgt, *v_wgt, *ranks_send_to_idx; 7753bb360cb4SStefano Zampini PetscInt im_active, active_procs, N, n, i, j, threshold = 2; 775457de7509SStefano Zampini PetscInt void_procs, *procs_candidates = NULL; 775527b6a85dSStefano Zampini PetscInt xadj_count, *count; 775627b6a85dSStefano Zampini PetscBool ismatis, use_vwgt = PETSC_FALSE; 775727b6a85dSStefano Zampini PetscSubcomm psubcomm; 775827b6a85dSStefano Zampini MPI_Comm subcomm; 7759a57a6d2fSStefano Zampini 7760e7931f94SStefano Zampini PetscFunctionBegin; 776157de7509SStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 77629566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)mat, MATIS, &ismatis)); 776328b400f6SJacob 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); 776457de7509SStefano Zampini PetscValidLogicalCollectiveInt(mat, *n_subdomains, 2); 776557de7509SStefano Zampini PetscValidLogicalCollectiveInt(mat, redprocs, 3); 776663a3b9bcSJacob Faibussowitsch PetscCheck(*n_subdomains > 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Invalid number of subdomains requested %" PetscInt_FMT, *n_subdomains); 776757de7509SStefano Zampini 776857de7509SStefano Zampini if (have_void) *have_void = PETSC_FALSE; 77699566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 77709566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)mat), &rank)); 77719566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(mat, &A)); 77729566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &n, NULL)); 7773bb360cb4SStefano Zampini im_active = !!n; 7774462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&im_active, &active_procs, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 777557de7509SStefano Zampini void_procs = size - active_procs; 777615229ffcSPierre Jolivet /* get ranks of non-active processes in mat communicator */ 777757de7509SStefano Zampini if (void_procs) { 777857de7509SStefano Zampini PetscInt ncand; 777957de7509SStefano Zampini 778057de7509SStefano Zampini if (have_void) *have_void = PETSC_TRUE; 77819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &procs_candidates)); 77829566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allgather(&im_active, 1, MPIU_INT, procs_candidates, 1, MPIU_INT, PetscObjectComm((PetscObject)mat))); 778357de7509SStefano Zampini for (i = 0, ncand = 0; i < size; i++) { 7784ad540459SPierre Jolivet if (!procs_candidates[i]) procs_candidates[ncand++] = i; 778557de7509SStefano Zampini } 778657de7509SStefano Zampini /* force n_subdomains to be not greater that the number of non-active processes */ 778757de7509SStefano Zampini *n_subdomains = PetscMin(void_procs, *n_subdomains); 778857de7509SStefano Zampini } 778957de7509SStefano Zampini 7790bb360cb4SStefano Zampini /* number of subdomains requested greater than active processes or matrix size -> just shift the matrix 77919dddd249SSatish Balay number of subdomains requested 1 -> send to rank-0 or first candidate in voids */ 77929566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &N, NULL)); 7793bb360cb4SStefano Zampini if (active_procs < *n_subdomains || *n_subdomains == 1 || N <= *n_subdomains) { 779414f0bfb9SStefano Zampini PetscInt issize, isidx, dest; 7795b96ec092SStefano Zampini PetscBool default_sub; 7796b96ec092SStefano Zampini 779714f0bfb9SStefano Zampini if (*n_subdomains == 1) dest = 0; 779814f0bfb9SStefano Zampini else dest = rank; 779957de7509SStefano Zampini if (im_active) { 780057de7509SStefano Zampini issize = 1; 780157de7509SStefano Zampini if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */ 780214f0bfb9SStefano Zampini isidx = procs_candidates[dest]; 780357de7509SStefano Zampini } else { 780414f0bfb9SStefano Zampini isidx = dest; 780557de7509SStefano Zampini } 780657de7509SStefano Zampini } else { 780757de7509SStefano Zampini issize = 0; 7808b96ec092SStefano Zampini isidx = rank; 780957de7509SStefano Zampini } 7810bb360cb4SStefano Zampini if (*n_subdomains != 1) *n_subdomains = active_procs; 78119566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), issize, &isidx, PETSC_COPY_VALUES, is_sends)); 7812b96ec092SStefano Zampini default_sub = (PetscBool)(isidx == rank); 78135440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &default_sub, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)mat))); 7814b96ec092SStefano Zampini if (default_sub) PetscCall(PetscObjectSetName((PetscObject)*is_sends, "default subassembling")); 78159566063dSJacob Faibussowitsch PetscCall(PetscFree(procs_candidates)); 78163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 781757de7509SStefano Zampini } 78189de2952eSStefano Zampini PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)A)->prefix, "-mat_is_partitioning_use_vwgt", &use_vwgt, NULL)); 78199de2952eSStefano Zampini PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)A)->prefix, "-mat_is_partitioning_threshold", &threshold, NULL)); 782027b6a85dSStefano Zampini threshold = PetscMax(threshold, 2); 7821e7931f94SStefano Zampini 7822e7931f94SStefano Zampini /* Get info on mapping */ 78239566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(mat, &mapping, NULL)); 78249566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetInfo(mapping, &n_neighs, &neighs, &n_shared, &shared)); 7825e7931f94SStefano Zampini 7826e7931f94SStefano Zampini /* build local CSR graph of subdomains' connectivity */ 78279566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2, &xadj)); 7828e7931f94SStefano Zampini xadj[0] = 0; 7829e7931f94SStefano Zampini xadj[1] = PetscMax(n_neighs - 1, 0); 78309566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(xadj[1], &adjncy)); 78319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(xadj[1], &adjncy_wgt)); 78329566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(n, &count)); 783327b6a85dSStefano Zampini for (i = 1; i < n_neighs; i++) 78349371c9d4SSatish Balay for (j = 0; j < n_shared[i]; j++) count[shared[i][j]] += 1; 7835e7931f94SStefano Zampini 783627b6a85dSStefano Zampini xadj_count = 0; 78372b510759SStefano Zampini for (i = 1; i < n_neighs; i++) { 783827b6a85dSStefano Zampini for (j = 0; j < n_shared[i]; j++) { 783927b6a85dSStefano Zampini if (count[shared[i][j]] < threshold) { 7840d023bfaeSStefano Zampini adjncy[xadj_count] = neighs[i]; 7841d023bfaeSStefano Zampini adjncy_wgt[xadj_count] = n_shared[i]; 7842d023bfaeSStefano Zampini xadj_count++; 784327b6a85dSStefano Zampini break; 784427b6a85dSStefano Zampini } 7845e7931f94SStefano Zampini } 7846e7931f94SStefano Zampini } 7847d023bfaeSStefano Zampini xadj[1] = xadj_count; 78489566063dSJacob Faibussowitsch PetscCall(PetscFree(count)); 78499566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreInfo(mapping, &n_neighs, &neighs, &n_shared, &shared)); 78509566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(xadj[1], adjncy, adjncy_wgt)); 7851e7931f94SStefano Zampini 78529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &ranks_send_to_idx)); 7853e7931f94SStefano Zampini 785427b6a85dSStefano Zampini /* Restrict work on active processes only */ 78559566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(im_active, &color)); 785627b6a85dSStefano Zampini if (void_procs) { 78579566063dSJacob Faibussowitsch PetscCall(PetscSubcommCreate(PetscObjectComm((PetscObject)mat), &psubcomm)); 78589566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetNumber(psubcomm, 2)); /* 2 groups, active process and not active processes */ 78599566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetTypeGeneral(psubcomm, color, rank)); 786027b6a85dSStefano Zampini subcomm = PetscSubcommChild(psubcomm); 786127b6a85dSStefano Zampini } else { 786227b6a85dSStefano Zampini psubcomm = NULL; 786327b6a85dSStefano Zampini subcomm = PetscObjectComm((PetscObject)mat); 786427b6a85dSStefano Zampini } 786527b6a85dSStefano Zampini 786627b6a85dSStefano Zampini v_wgt = NULL; 786727b6a85dSStefano Zampini if (!color) { 78689566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 78699566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 78709566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy_wgt)); 7871c8587f34SStefano Zampini } else { 787252e5ac9dSStefano Zampini Mat subdomain_adj; 787352e5ac9dSStefano Zampini IS new_ranks, new_ranks_contig; 787452e5ac9dSStefano Zampini MatPartitioning partitioner; 78756497c311SBarry Smith PetscInt rstart, rend; 78766497c311SBarry Smith PetscMPIInt irstart = 0, irend = 0; 787752e5ac9dSStefano Zampini PetscInt *is_indices, *oldranks; 787857de7509SStefano Zampini PetscMPIInt size; 7879b0c7d250SStefano Zampini PetscBool aggregate; 7880b0c7d250SStefano Zampini 78819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(subcomm, &size)); 788227b6a85dSStefano Zampini if (void_procs) { 788327b6a85dSStefano Zampini PetscInt prank = rank; 78849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &oldranks)); 78859566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allgather(&prank, 1, MPIU_INT, oldranks, 1, MPIU_INT, subcomm)); 788648a46eb9SPierre Jolivet for (i = 0; i < xadj[1]; i++) PetscCall(PetscFindInt(adjncy[i], size, oldranks, &adjncy[i])); 78879566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(xadj[1], adjncy, adjncy_wgt)); 788827b6a85dSStefano Zampini } else { 788927b6a85dSStefano Zampini oldranks = NULL; 789027b6a85dSStefano Zampini } 7891b0c7d250SStefano Zampini aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE); 789227b6a85dSStefano Zampini if (aggregate) { /* TODO: all this part could be made more efficient */ 7893b0c7d250SStefano Zampini PetscInt lrows, row, ncols, *cols; 7894b0c7d250SStefano Zampini PetscMPIInt nrank; 7895b0c7d250SStefano Zampini PetscScalar *vals; 7896b0c7d250SStefano Zampini 78979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(subcomm, &nrank)); 7898b0c7d250SStefano Zampini lrows = 0; 7899b0c7d250SStefano Zampini if (nrank < redprocs) { 7900b0c7d250SStefano Zampini lrows = size / redprocs; 7901b0c7d250SStefano Zampini if (nrank < size % redprocs) lrows++; 7902b0c7d250SStefano Zampini } 79039566063dSJacob Faibussowitsch PetscCall(MatCreateAIJ(subcomm, lrows, lrows, size, size, 50, NULL, 50, NULL, &subdomain_adj)); 79049566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(subdomain_adj, &rstart, &rend)); 7905835f2295SStefano Zampini PetscCall(PetscMPIIntCast(rstart, &irstart)); 7906835f2295SStefano Zampini PetscCall(PetscMPIIntCast(rend, &irend)); 79079566063dSJacob Faibussowitsch PetscCall(MatSetOption(subdomain_adj, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_FALSE)); 79089566063dSJacob Faibussowitsch PetscCall(MatSetOption(subdomain_adj, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 7909b0c7d250SStefano Zampini row = nrank; 7910b0c7d250SStefano Zampini ncols = xadj[1] - xadj[0]; 7911b0c7d250SStefano Zampini cols = adjncy; 79129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncols, &vals)); 7913b0c7d250SStefano Zampini for (i = 0; i < ncols; i++) vals[i] = adjncy_wgt[i]; 79149566063dSJacob Faibussowitsch PetscCall(MatSetValues(subdomain_adj, 1, &row, ncols, cols, vals, INSERT_VALUES)); 79159566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(subdomain_adj, MAT_FINAL_ASSEMBLY)); 79169566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(subdomain_adj, MAT_FINAL_ASSEMBLY)); 79179566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 79189566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 79199566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy_wgt)); 79209566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 792127b6a85dSStefano Zampini if (use_vwgt) { 792227b6a85dSStefano Zampini Vec v; 792327b6a85dSStefano Zampini const PetscScalar *array; 792427b6a85dSStefano Zampini PetscInt nl; 792527b6a85dSStefano Zampini 79269566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(subdomain_adj, &v, NULL)); 79279566063dSJacob Faibussowitsch PetscCall(VecSetValue(v, row, (PetscScalar)n, INSERT_VALUES)); 79289566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(v)); 79299566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(v)); 79309566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &nl)); 79319566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &array)); 79329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl, &v_wgt)); 793322db5ddcSStefano Zampini for (i = 0; i < nl; i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]); 79349566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &array)); 79359566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 793627b6a85dSStefano Zampini } 7937b0c7d250SStefano Zampini } else { 7938835f2295SStefano Zampini PetscCall(MatCreateMPIAdj(subcomm, 1, size, xadj, adjncy, adjncy_wgt, &subdomain_adj)); 793927b6a85dSStefano Zampini if (use_vwgt) { 79409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &v_wgt)); 7941bb360cb4SStefano Zampini v_wgt[0] = n; 794227b6a85dSStefano Zampini } 7943b0c7d250SStefano Zampini } 79449566063dSJacob Faibussowitsch /* PetscCall(MatView(subdomain_adj,0)); */ 7945e7931f94SStefano Zampini 7946e7931f94SStefano Zampini /* Partition */ 79479566063dSJacob Faibussowitsch PetscCall(MatPartitioningCreate(subcomm, &partitioner)); 7948ce64c636SStefano Zampini #if defined(PETSC_HAVE_PTSCOTCH) 79499566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetType(partitioner, MATPARTITIONINGPTSCOTCH)); 7950ce64c636SStefano Zampini #elif defined(PETSC_HAVE_PARMETIS) 79519566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetType(partitioner, MATPARTITIONINGPARMETIS)); 7952ce64c636SStefano Zampini #else 79539566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetType(partitioner, MATPARTITIONINGAVERAGE)); 7954ce64c636SStefano Zampini #endif 79559566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetAdjacency(partitioner, subdomain_adj)); 79561baa6e33SBarry Smith if (v_wgt) PetscCall(MatPartitioningSetVertexWeights(partitioner, v_wgt)); 7957835f2295SStefano Zampini *n_subdomains = PetscMin(size, *n_subdomains); 79589566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetNParts(partitioner, *n_subdomains)); 79599566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetFromOptions(partitioner)); 79609566063dSJacob Faibussowitsch PetscCall(MatPartitioningApply(partitioner, &new_ranks)); 79619566063dSJacob Faibussowitsch /* PetscCall(MatPartitioningView(partitioner,0)); */ 7962e7931f94SStefano Zampini 796352e5ac9dSStefano Zampini /* renumber new_ranks to avoid "holes" in new set of processors */ 79649566063dSJacob Faibussowitsch PetscCall(ISRenumber(new_ranks, NULL, NULL, &new_ranks_contig)); 79659566063dSJacob Faibussowitsch PetscCall(ISDestroy(&new_ranks)); 79669566063dSJacob Faibussowitsch PetscCall(ISGetIndices(new_ranks_contig, (const PetscInt **)&is_indices)); 796757de7509SStefano Zampini if (!aggregate) { 796857de7509SStefano Zampini if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */ 79696bdcaf15SBarry Smith PetscAssert(oldranks, PETSC_COMM_SELF, PETSC_ERR_PLIB, "This should not happen"); 797057de7509SStefano Zampini ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]]; 797127b6a85dSStefano Zampini } else if (oldranks) { 7972b0c7d250SStefano Zampini ranks_send_to_idx[0] = oldranks[is_indices[0]]; 797327b6a85dSStefano Zampini } else { 797427b6a85dSStefano Zampini ranks_send_to_idx[0] = is_indices[0]; 797557de7509SStefano Zampini } 797628143c3dSStefano Zampini } else { 79777fb8a5e4SKarl Rupp PetscInt idx = 0; 7978b0c7d250SStefano Zampini PetscMPIInt tag; 7979b0c7d250SStefano Zampini MPI_Request *reqs; 7980b0c7d250SStefano Zampini 79819566063dSJacob Faibussowitsch PetscCall(PetscObjectGetNewTag((PetscObject)subdomain_adj, &tag)); 79829566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rend - rstart, &reqs)); 79836497c311SBarry Smith for (PetscMPIInt i = irstart; i < irend; i++) PetscCallMPI(MPIU_Isend(is_indices + i - rstart, 1, MPIU_INT, i, tag, subcomm, &reqs[i - rstart])); 79846497c311SBarry Smith PetscCallMPI(MPIU_Recv(&idx, 1, MPIU_INT, MPI_ANY_SOURCE, tag, subcomm, MPI_STATUS_IGNORE)); 79856497c311SBarry Smith PetscCallMPI(MPI_Waitall(irend - irstart, reqs, MPI_STATUSES_IGNORE)); 79869566063dSJacob Faibussowitsch PetscCall(PetscFree(reqs)); 798757de7509SStefano Zampini if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */ 79886bdcaf15SBarry Smith PetscAssert(oldranks, PETSC_COMM_SELF, PETSC_ERR_PLIB, "This should not happen"); 79897fb8a5e4SKarl Rupp ranks_send_to_idx[0] = procs_candidates[oldranks[idx]]; 799027b6a85dSStefano Zampini } else if (oldranks) { 79917fb8a5e4SKarl Rupp ranks_send_to_idx[0] = oldranks[idx]; 799227b6a85dSStefano Zampini } else { 79937fb8a5e4SKarl Rupp ranks_send_to_idx[0] = idx; 799428143c3dSStefano Zampini } 799557de7509SStefano Zampini } 79969566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(new_ranks_contig, (const PetscInt **)&is_indices)); 7997e7931f94SStefano Zampini /* clean up */ 79989566063dSJacob Faibussowitsch PetscCall(PetscFree(oldranks)); 79999566063dSJacob Faibussowitsch PetscCall(ISDestroy(&new_ranks_contig)); 80009566063dSJacob Faibussowitsch PetscCall(MatDestroy(&subdomain_adj)); 80019566063dSJacob Faibussowitsch PetscCall(MatPartitioningDestroy(&partitioner)); 8002e7931f94SStefano Zampini } 80039566063dSJacob Faibussowitsch PetscCall(PetscSubcommDestroy(&psubcomm)); 80049566063dSJacob Faibussowitsch PetscCall(PetscFree(procs_candidates)); 8005e7931f94SStefano Zampini 8006e7931f94SStefano Zampini /* assemble parallel IS for sends */ 8007e7931f94SStefano Zampini i = 1; 800827b6a85dSStefano Zampini if (!color) i = 0; 80099566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), i, ranks_send_to_idx, PETSC_OWN_POINTER, is_sends)); 80103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8011e7931f94SStefano Zampini } 8012e7931f94SStefano Zampini 80139371c9d4SSatish Balay typedef enum { 80149371c9d4SSatish Balay MATDENSE_PRIVATE = 0, 80159371c9d4SSatish Balay MATAIJ_PRIVATE, 80169371c9d4SSatish Balay MATBAIJ_PRIVATE, 80179371c9d4SSatish Balay MATSBAIJ_PRIVATE 80189371c9d4SSatish Balay } MatTypePrivate; 8019e7931f94SStefano Zampini 8020ba38deedSJacob 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[]) 8021d71ae5a4SJacob Faibussowitsch { 802270cf5478SStefano Zampini Mat local_mat; 8023e7931f94SStefano Zampini IS is_sends_internal; 80249d30be91SStefano Zampini PetscInt rows, cols, new_local_rows; 80251ae86dd6SStefano Zampini PetscInt i, bs, buf_size_idxs, buf_size_idxs_is, buf_size_vals, buf_size_vecs; 80269d30be91SStefano Zampini PetscBool ismatis, isdense, newisdense, destroy_mat; 8027e7931f94SStefano Zampini ISLocalToGlobalMapping l2gmap; 8028e7931f94SStefano Zampini PetscInt *l2gmap_indices; 8029e7931f94SStefano Zampini const PetscInt *is_indices; 8030e7931f94SStefano Zampini MatType new_local_type; 8031e7931f94SStefano Zampini /* buffers */ 8032e7931f94SStefano Zampini PetscInt *ptr_idxs, *send_buffer_idxs, *recv_buffer_idxs; 803328143c3dSStefano Zampini PetscInt *ptr_idxs_is, *send_buffer_idxs_is, *recv_buffer_idxs_is; 80349d30be91SStefano Zampini PetscInt *recv_buffer_idxs_local; 80351683a169SBarry Smith PetscScalar *ptr_vals, *recv_buffer_vals; 80361683a169SBarry Smith const PetscScalar *send_buffer_vals; 80371ae86dd6SStefano Zampini PetscScalar *ptr_vecs, *send_buffer_vecs, *recv_buffer_vecs; 8038e7931f94SStefano Zampini /* MPI */ 803928143c3dSStefano Zampini MPI_Comm comm, comm_n; 804028143c3dSStefano Zampini PetscSubcomm subcomm; 8041e569e4e1SStefano Zampini PetscMPIInt n_sends, n_recvs, size; 804228143c3dSStefano Zampini PetscMPIInt *iflags, *ilengths_idxs, *ilengths_vals, *ilengths_idxs_is; 804328143c3dSStefano Zampini PetscMPIInt *onodes, *onodes_is, *olengths_idxs, *olengths_idxs_is, *olengths_vals; 804460b1fa21SPierre Jolivet PetscMPIInt len, tag_idxs, tag_idxs_is, tag_vals, tag_vecs, source_dest; 80451ae86dd6SStefano Zampini MPI_Request *send_req_idxs, *send_req_idxs_is, *send_req_vals, *send_req_vecs; 80461ae86dd6SStefano Zampini MPI_Request *recv_req_idxs, *recv_req_idxs_is, *recv_req_vals, *recv_req_vecs; 8047e7931f94SStefano Zampini 8048e7931f94SStefano Zampini PetscFunctionBegin; 804957de7509SStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 80509566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)mat, MATIS, &ismatis)); 80515f80ce2aSJacob 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); 805257de7509SStefano Zampini PetscValidLogicalCollectiveInt(mat, n_subdomains, 3); 805357de7509SStefano Zampini PetscValidLogicalCollectiveBool(mat, restrict_comm, 4); 805457de7509SStefano Zampini PetscValidLogicalCollectiveBool(mat, restrict_full, 5); 805557de7509SStefano Zampini PetscValidLogicalCollectiveBool(mat, reuse, 6); 805657de7509SStefano Zampini PetscValidLogicalCollectiveInt(mat, nis, 8); 80571ae86dd6SStefano Zampini PetscValidLogicalCollectiveInt(mat, nvecs, 10); 80581ae86dd6SStefano Zampini if (nvecs) { 805908401ef6SPierre Jolivet PetscCheck(nvecs <= 1, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Just 1 vector supported"); 80601ae86dd6SStefano Zampini PetscValidHeaderSpecific(nnsp_vec[0], VEC_CLASSID, 11); 80611ae86dd6SStefano Zampini } 806257de7509SStefano Zampini /* further checks */ 80639566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(mat, &local_mat)); 80649566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)local_mat, MATSEQDENSE, &isdense)); 80655f80ce2aSJacob Faibussowitsch PetscCheck(isdense, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE"); 80669de2952eSStefano Zampini 80679566063dSJacob Faibussowitsch PetscCall(MatGetSize(local_mat, &rows, &cols)); 80685f80ce2aSJacob Faibussowitsch PetscCheck(rows == cols, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Local MATIS matrices should be square"); 806957de7509SStefano Zampini if (reuse && *mat_n) { 807070cf5478SStefano Zampini PetscInt mrows, mcols, mnrows, mncols; 807157de7509SStefano Zampini PetscValidHeaderSpecific(*mat_n, MAT_CLASSID, 7); 80729566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)*mat_n, MATIS, &ismatis)); 80735f80ce2aSJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)*mat_n), PETSC_ERR_SUP, "Cannot reuse a matrix which is not of type MATIS"); 80749566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &mrows, &mcols)); 80759566063dSJacob Faibussowitsch PetscCall(MatGetSize(*mat_n, &mnrows, &mncols)); 807663a3b9bcSJacob Faibussowitsch PetscCheck(mrows == mnrows, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix! Wrong number of rows %" PetscInt_FMT " != %" PetscInt_FMT, mrows, mnrows); 807763a3b9bcSJacob Faibussowitsch PetscCheck(mcols == mncols, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix! Wrong number of cols %" PetscInt_FMT " != %" PetscInt_FMT, mcols, mncols); 807870cf5478SStefano Zampini } 80799566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(local_mat, &bs)); 8080064a246eSJacob Faibussowitsch PetscValidLogicalCollectiveInt(mat, bs, 1); 808157de7509SStefano Zampini 8082e7931f94SStefano Zampini /* prepare IS for sending if not provided */ 8083e7931f94SStefano Zampini if (!is_sends) { 80845f80ce2aSJacob Faibussowitsch PetscCheck(n_subdomains, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "You should specify either an IS or a target number of subdomains"); 80859566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISGetSubassemblingPattern(mat, &n_subdomains, 0, &is_sends_internal, NULL)); 8086c8587f34SStefano Zampini } else { 80879566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is_sends)); 8088e7931f94SStefano Zampini is_sends_internal = is_sends; 8089c8587f34SStefano Zampini } 8090e7931f94SStefano Zampini 8091e7931f94SStefano Zampini /* get comm */ 80929566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 8093e7931f94SStefano Zampini 8094e7931f94SStefano Zampini /* compute number of sends */ 80959566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is_sends_internal, &i)); 80969566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(i, &n_sends)); 8097e7931f94SStefano Zampini 8098e7931f94SStefano Zampini /* compute number of receives */ 80999566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 81009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &iflags)); 81019566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(iflags, size)); 81029566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is_sends_internal, &is_indices)); 8103e7931f94SStefano Zampini for (i = 0; i < n_sends; i++) iflags[is_indices[i]] = 1; 81049566063dSJacob Faibussowitsch PetscCall(PetscGatherNumberOfMessages(comm, iflags, NULL, &n_recvs)); 81059566063dSJacob Faibussowitsch PetscCall(PetscFree(iflags)); 8106e7931f94SStefano Zampini 810728143c3dSStefano Zampini /* restrict comm if requested */ 81080a545947SLisandro Dalcin subcomm = NULL; 810928143c3dSStefano Zampini destroy_mat = PETSC_FALSE; 811028143c3dSStefano Zampini if (restrict_comm) { 8111779c1cceSStefano Zampini PetscMPIInt color, subcommsize; 8112779c1cceSStefano Zampini 811328143c3dSStefano Zampini color = 0; 811453a05cb3SStefano Zampini if (restrict_full) { 81156aad120cSJose E. Roman if (!n_recvs) color = 1; /* processes not receiving anything will not participate in new comm (full restriction) */ 811653a05cb3SStefano Zampini } else { 81176aad120cSJose 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 */ 811853a05cb3SStefano Zampini } 8119462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&color, &subcommsize, 1, MPI_INT, MPI_SUM, comm)); 8120e569e4e1SStefano Zampini subcommsize = size - subcommsize; 812128143c3dSStefano Zampini /* check if reuse has been requested */ 812257de7509SStefano Zampini if (reuse) { 812328143c3dSStefano Zampini if (*mat_n) { 812428143c3dSStefano Zampini PetscMPIInt subcommsize2; 81259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n), &subcommsize2)); 81265f80ce2aSJacob Faibussowitsch PetscCheck(subcommsize == subcommsize2, PetscObjectComm((PetscObject)*mat_n), PETSC_ERR_PLIB, "Cannot reuse matrix! wrong subcomm size %d != %d", subcommsize, subcommsize2); 812728143c3dSStefano Zampini comm_n = PetscObjectComm((PetscObject)*mat_n); 812828143c3dSStefano Zampini } else { 812928143c3dSStefano Zampini comm_n = PETSC_COMM_SELF; 813028143c3dSStefano Zampini } 813128143c3dSStefano Zampini } else { /* MAT_INITIAL_MATRIX */ 8132779c1cceSStefano Zampini PetscMPIInt rank; 8133779c1cceSStefano Zampini 81349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 81359566063dSJacob Faibussowitsch PetscCall(PetscSubcommCreate(comm, &subcomm)); 81369566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetNumber(subcomm, 2)); 81379566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetTypeGeneral(subcomm, color, rank)); 8138306c2d5bSBarry Smith comm_n = PetscSubcommChild(subcomm); 813928143c3dSStefano Zampini } 814028143c3dSStefano Zampini /* flag to destroy *mat_n if not significative */ 814128143c3dSStefano Zampini if (color) destroy_mat = PETSC_TRUE; 814228143c3dSStefano Zampini } else { 814328143c3dSStefano Zampini comm_n = comm; 814428143c3dSStefano Zampini } 814528143c3dSStefano Zampini 8146e7931f94SStefano Zampini /* prepare send/receive buffers */ 81479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &ilengths_idxs)); 81489566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(ilengths_idxs, size)); 81499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &ilengths_vals)); 81509566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(ilengths_vals, size)); 815148a46eb9SPierre Jolivet if (nis) PetscCall(PetscCalloc1(size, &ilengths_idxs_is)); 8152e7931f94SStefano Zampini 815328143c3dSStefano Zampini /* Get data from local matrices */ 8154e432b41dSStefano Zampini PetscCheck(isdense, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Subassembling of AIJ local matrices not yet implemented"); 8155e7931f94SStefano Zampini /* TODO: See below some guidelines on how to prepare the local buffers */ 8156e7931f94SStefano Zampini /* 8157e7931f94SStefano Zampini send_buffer_vals should contain the raw values of the local matrix 8158e7931f94SStefano Zampini send_buffer_idxs should contain: 8159e7931f94SStefano Zampini - MatType_PRIVATE type 8160e7931f94SStefano Zampini - PetscInt size_of_l2gmap 8161e7931f94SStefano Zampini - PetscInt global_row_indices[size_of_l2gmap] 8162e7931f94SStefano Zampini - PetscInt all_other_info_which_is_needed_to_compute_preallocation_and_set_values 8163e7931f94SStefano Zampini */ 8164e432b41dSStefano Zampini { 8165e432b41dSStefano Zampini ISLocalToGlobalMapping mapping; 8166e432b41dSStefano Zampini 81679566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(mat, &mapping, NULL)); 81689566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(local_mat, &send_buffer_vals)); 81699566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(mapping, &i)); 81709566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(i + 2, &send_buffer_idxs)); 8171e7931f94SStefano Zampini send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE; 8172e7931f94SStefano Zampini send_buffer_idxs[1] = i; 81739566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(mapping, (const PetscInt **)&ptr_idxs)); 81749566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&send_buffer_idxs[2], ptr_idxs, i)); 81759566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(mapping, (const PetscInt **)&ptr_idxs)); 81769566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(i, &len)); 8177e7931f94SStefano Zampini for (i = 0; i < n_sends; i++) { 8178e7931f94SStefano Zampini ilengths_vals[is_indices[i]] = len * len; 8179e7931f94SStefano Zampini ilengths_idxs[is_indices[i]] = len + 2; 8180c8587f34SStefano Zampini } 8181c8587f34SStefano Zampini } 81829566063dSJacob Faibussowitsch PetscCall(PetscGatherMessageLengths2(comm, n_sends, n_recvs, ilengths_idxs, ilengths_vals, &onodes, &olengths_idxs, &olengths_vals)); 818328143c3dSStefano Zampini /* additional is (if any) */ 818428143c3dSStefano Zampini if (nis) { 818528143c3dSStefano Zampini PetscMPIInt psum; 818628143c3dSStefano Zampini PetscInt j; 818728143c3dSStefano Zampini for (j = 0, psum = 0; j < nis; j++) { 818828143c3dSStefano Zampini PetscInt plen; 81899566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isarray[j], &plen)); 81909566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(plen, &len)); 81916aad120cSJose E. Roman psum += len + 1; /* indices + length */ 819228143c3dSStefano Zampini } 81939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(psum, &send_buffer_idxs_is)); 819428143c3dSStefano Zampini for (j = 0, psum = 0; j < nis; j++) { 819528143c3dSStefano Zampini PetscInt plen; 819628143c3dSStefano Zampini const PetscInt *is_array_idxs; 81979566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isarray[j], &plen)); 819828143c3dSStefano Zampini send_buffer_idxs_is[psum] = plen; 81999566063dSJacob Faibussowitsch PetscCall(ISGetIndices(isarray[j], &is_array_idxs)); 82009566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&send_buffer_idxs_is[psum + 1], is_array_idxs, plen)); 82019566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(isarray[j], &is_array_idxs)); 82026aad120cSJose E. Roman psum += plen + 1; /* indices + length */ 820328143c3dSStefano Zampini } 8204ad540459SPierre Jolivet for (i = 0; i < n_sends; i++) ilengths_idxs_is[is_indices[i]] = psum; 82059566063dSJacob Faibussowitsch PetscCall(PetscGatherMessageLengths(comm, n_sends, n_recvs, ilengths_idxs_is, &onodes_is, &olengths_idxs_is)); 820628143c3dSStefano Zampini } 82079566063dSJacob Faibussowitsch PetscCall(MatISRestoreLocalMat(mat, &local_mat)); 820828143c3dSStefano Zampini 8209e7931f94SStefano Zampini buf_size_idxs = 0; 8210e7931f94SStefano Zampini buf_size_vals = 0; 821128143c3dSStefano Zampini buf_size_idxs_is = 0; 82121ae86dd6SStefano Zampini buf_size_vecs = 0; 8213e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 8214835f2295SStefano Zampini buf_size_idxs += olengths_idxs[i]; 8215835f2295SStefano Zampini buf_size_vals += olengths_vals[i]; 8216835f2295SStefano Zampini if (nis) buf_size_idxs_is += olengths_idxs_is[i]; 8217835f2295SStefano Zampini if (nvecs) buf_size_vecs += olengths_idxs[i]; 8218e7931f94SStefano Zampini } 82199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(buf_size_idxs, &recv_buffer_idxs)); 82209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(buf_size_vals, &recv_buffer_vals)); 82219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(buf_size_idxs_is, &recv_buffer_idxs_is)); 82229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(buf_size_vecs, &recv_buffer_vecs)); 8223e7931f94SStefano Zampini 8224e7931f94SStefano Zampini /* get new tags for clean communications */ 82259566063dSJacob Faibussowitsch PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag_idxs)); 82269566063dSJacob Faibussowitsch PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag_vals)); 82279566063dSJacob Faibussowitsch PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag_idxs_is)); 82289566063dSJacob Faibussowitsch PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag_vecs)); 8229e7931f94SStefano Zampini 8230e7931f94SStefano Zampini /* allocate for requests */ 82319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_sends, &send_req_idxs)); 82329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_sends, &send_req_vals)); 82339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_sends, &send_req_idxs_is)); 82349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_sends, &send_req_vecs)); 82359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_recvs, &recv_req_idxs)); 82369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_recvs, &recv_req_vals)); 82379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_recvs, &recv_req_idxs_is)); 82389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_recvs, &recv_req_vecs)); 8239e7931f94SStefano Zampini 8240e7931f94SStefano Zampini /* communications */ 8241e7931f94SStefano Zampini ptr_idxs = recv_buffer_idxs; 8242e7931f94SStefano Zampini ptr_vals = recv_buffer_vals; 824328143c3dSStefano Zampini ptr_idxs_is = recv_buffer_idxs_is; 82441ae86dd6SStefano Zampini ptr_vecs = recv_buffer_vecs; 8245e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 8246e91c04dfSPierre Jolivet PetscCallMPI(MPIU_Irecv(ptr_idxs, olengths_idxs[i], MPIU_INT, onodes[i], tag_idxs, comm, &recv_req_idxs[i])); 8247e91c04dfSPierre Jolivet PetscCallMPI(MPIU_Irecv(ptr_vals, olengths_vals[i], MPIU_SCALAR, onodes[i], tag_vals, comm, &recv_req_vals[i])); 8248e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 8249e7931f94SStefano Zampini ptr_vals += olengths_vals[i]; 825028143c3dSStefano Zampini if (nis) { 8251e91c04dfSPierre 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])); 825228143c3dSStefano Zampini ptr_idxs_is += olengths_idxs_is[i]; 825328143c3dSStefano Zampini } 82541ae86dd6SStefano Zampini if (nvecs) { 8255e91c04dfSPierre Jolivet PetscCallMPI(MPIU_Irecv(ptr_vecs, olengths_idxs[i] - 2, MPIU_SCALAR, onodes[i], tag_vecs, comm, &recv_req_vecs[i])); 82561ae86dd6SStefano Zampini ptr_vecs += olengths_idxs[i] - 2; 82571ae86dd6SStefano Zampini } 8258e7931f94SStefano Zampini } 8259e7931f94SStefano Zampini for (i = 0; i < n_sends; i++) { 826060b1fa21SPierre Jolivet PetscCall(PetscMPIIntCast(is_indices[i], &source_dest)); 826160b1fa21SPierre Jolivet PetscCallMPI(MPIU_Isend(send_buffer_idxs, ilengths_idxs[source_dest], MPIU_INT, source_dest, tag_idxs, comm, &send_req_idxs[i])); 826260b1fa21SPierre Jolivet PetscCallMPI(MPIU_Isend(send_buffer_vals, ilengths_vals[source_dest], MPIU_SCALAR, source_dest, tag_vals, comm, &send_req_vals[i])); 826360b1fa21SPierre 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])); 82641ae86dd6SStefano Zampini if (nvecs) { 82659566063dSJacob Faibussowitsch PetscCall(VecGetArray(nnsp_vec[0], &send_buffer_vecs)); 826660b1fa21SPierre Jolivet PetscCallMPI(MPIU_Isend(send_buffer_vecs, ilengths_idxs[source_dest] - 2, MPIU_SCALAR, source_dest, tag_vecs, comm, &send_req_vecs[i])); 82671ae86dd6SStefano Zampini } 8268e7931f94SStefano Zampini } 82699566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is_sends_internal, &is_indices)); 82709566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_sends_internal)); 8271e7931f94SStefano Zampini 8272e7931f94SStefano Zampini /* assemble new l2g map */ 82739566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_recvs, recv_req_idxs, MPI_STATUSES_IGNORE)); 8274e7931f94SStefano Zampini ptr_idxs = recv_buffer_idxs; 82759d30be91SStefano Zampini new_local_rows = 0; 8276e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 82779d30be91SStefano Zampini new_local_rows += *(ptr_idxs + 1); /* second element is the local size of the l2gmap */ 8278e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 8279e7931f94SStefano Zampini } 82809566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(new_local_rows, &l2gmap_indices)); 8281e7931f94SStefano Zampini ptr_idxs = recv_buffer_idxs; 82829d30be91SStefano Zampini new_local_rows = 0; 8283e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 82849566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&l2gmap_indices[new_local_rows], ptr_idxs + 2, *(ptr_idxs + 1))); 82859d30be91SStefano Zampini new_local_rows += *(ptr_idxs + 1); /* second element is the local size of the l2gmap */ 8286e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 8287e7931f94SStefano Zampini } 82889566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&new_local_rows, l2gmap_indices)); 82899566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(comm_n, 1, new_local_rows, l2gmap_indices, PETSC_COPY_VALUES, &l2gmap)); 82909566063dSJacob Faibussowitsch PetscCall(PetscFree(l2gmap_indices)); 8291e7931f94SStefano Zampini 8292e7931f94SStefano Zampini /* infer new local matrix type from received local matrices type */ 8293e7931f94SStefano Zampini /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */ 8294e7931f94SStefano 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) */ 8295e7931f94SStefano Zampini if (n_recvs) { 829628143c3dSStefano Zampini MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0]; 8297e7931f94SStefano Zampini ptr_idxs = recv_buffer_idxs; 8298e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 8299e7931f94SStefano Zampini if ((PetscInt)new_local_type_private != *ptr_idxs) { 8300e7931f94SStefano Zampini new_local_type_private = MATAIJ_PRIVATE; 8301e7931f94SStefano Zampini break; 8302e7931f94SStefano Zampini } 8303e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 8304e7931f94SStefano Zampini } 8305e7931f94SStefano Zampini switch (new_local_type_private) { 830628143c3dSStefano Zampini case MATDENSE_PRIVATE: 8307e7931f94SStefano Zampini new_local_type = MATSEQAIJ; 8308e7931f94SStefano Zampini bs = 1; 8309e7931f94SStefano Zampini break; 8310e7931f94SStefano Zampini case MATAIJ_PRIVATE: 8311e7931f94SStefano Zampini new_local_type = MATSEQAIJ; 8312e7931f94SStefano Zampini bs = 1; 8313e7931f94SStefano Zampini break; 8314d71ae5a4SJacob Faibussowitsch case MATBAIJ_PRIVATE: 8315d71ae5a4SJacob Faibussowitsch new_local_type = MATSEQBAIJ; 8316d71ae5a4SJacob Faibussowitsch break; 8317d71ae5a4SJacob Faibussowitsch case MATSBAIJ_PRIVATE: 8318d71ae5a4SJacob Faibussowitsch new_local_type = MATSEQSBAIJ; 8319d71ae5a4SJacob Faibussowitsch break; 8320d71ae5a4SJacob Faibussowitsch default: 8321d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_SUP, "Unsupported private type %d in %s", new_local_type_private, PETSC_FUNCTION_NAME); 8322e7931f94SStefano Zampini } 8323ed8ed4edSstefano_zampini } else { /* by default, new_local_type is seqaij */ 8324ed8ed4edSstefano_zampini new_local_type = MATSEQAIJ; 832528143c3dSStefano Zampini bs = 1; 8326e7931f94SStefano Zampini } 8327e7931f94SStefano Zampini 832870cf5478SStefano Zampini /* create MATIS object if needed */ 832957de7509SStefano Zampini if (!reuse) { 83309566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &rows, &cols)); 83319566063dSJacob Faibussowitsch PetscCall(MatCreateIS(comm_n, bs, PETSC_DECIDE, PETSC_DECIDE, rows, cols, l2gmap, l2gmap, mat_n)); 833270cf5478SStefano Zampini } else { 833370cf5478SStefano Zampini /* it also destroys the local matrices */ 833457de7509SStefano Zampini if (*mat_n) { 83359566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*mat_n, l2gmap, l2gmap)); 833657de7509SStefano Zampini } else { /* this is a fake object */ 83379566063dSJacob Faibussowitsch PetscCall(MatCreateIS(comm_n, bs, PETSC_DECIDE, PETSC_DECIDE, rows, cols, l2gmap, l2gmap, mat_n)); 833857de7509SStefano Zampini } 833970cf5478SStefano Zampini } 83409566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*mat_n, &local_mat)); 83419566063dSJacob Faibussowitsch PetscCall(MatSetType(local_mat, new_local_type)); 83429d30be91SStefano Zampini 83439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_recvs, recv_req_vals, MPI_STATUSES_IGNORE)); 83449d30be91SStefano Zampini 83459d30be91SStefano Zampini /* Global to local map of received indices */ 83469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(buf_size_idxs, &recv_buffer_idxs_local)); /* needed for values insertion */ 83479566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(l2gmap, IS_GTOLM_MASK, buf_size_idxs, recv_buffer_idxs, &i, recv_buffer_idxs_local)); 83489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&l2gmap)); 83499d30be91SStefano Zampini 83509d30be91SStefano Zampini /* restore attributes -> type of incoming data and its size */ 83519d30be91SStefano Zampini buf_size_idxs = 0; 83529d30be91SStefano Zampini for (i = 0; i < n_recvs; i++) { 83539d30be91SStefano Zampini recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs]; 83549d30be91SStefano Zampini recv_buffer_idxs_local[buf_size_idxs + 1] = recv_buffer_idxs[buf_size_idxs + 1]; 8355835f2295SStefano Zampini buf_size_idxs += olengths_idxs[i]; 83569d30be91SStefano Zampini } 83579566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_buffer_idxs)); 83589d30be91SStefano Zampini 83599d30be91SStefano Zampini /* set preallocation */ 83609566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)local_mat, MATSEQDENSE, &newisdense)); 83619d30be91SStefano Zampini if (!newisdense) { 83620a545947SLisandro Dalcin PetscInt *new_local_nnz = NULL; 83639d30be91SStefano Zampini 83649d30be91SStefano Zampini ptr_idxs = recv_buffer_idxs_local; 836548a46eb9SPierre Jolivet if (n_recvs) PetscCall(PetscCalloc1(new_local_rows, &new_local_nnz)); 83669d30be91SStefano Zampini for (i = 0; i < n_recvs; i++) { 83679d30be91SStefano Zampini PetscInt j; 83689d30be91SStefano Zampini if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */ 8369ad540459SPierre Jolivet for (j = 0; j < *(ptr_idxs + 1); j++) new_local_nnz[*(ptr_idxs + 2 + j)] += *(ptr_idxs + 1); 83709d30be91SStefano Zampini } else { 83719d30be91SStefano Zampini /* TODO */ 83729d30be91SStefano Zampini } 83739d30be91SStefano Zampini ptr_idxs += olengths_idxs[i]; 83749d30be91SStefano Zampini } 83759d30be91SStefano Zampini if (new_local_nnz) { 83769d30be91SStefano Zampini for (i = 0; i < new_local_rows; i++) new_local_nnz[i] = PetscMin(new_local_nnz[i], new_local_rows); 83779566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(local_mat, 0, new_local_nnz)); 83789d30be91SStefano Zampini for (i = 0; i < new_local_rows; i++) new_local_nnz[i] /= bs; 83799566063dSJacob Faibussowitsch PetscCall(MatSeqBAIJSetPreallocation(local_mat, bs, 0, new_local_nnz)); 83809d30be91SStefano Zampini for (i = 0; i < new_local_rows; i++) new_local_nnz[i] = PetscMax(new_local_nnz[i] - i, 0); 83819566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(local_mat, bs, 0, new_local_nnz)); 83829d30be91SStefano Zampini } else { 83839566063dSJacob Faibussowitsch PetscCall(MatSetUp(local_mat)); 83849d30be91SStefano Zampini } 83859566063dSJacob Faibussowitsch PetscCall(PetscFree(new_local_nnz)); 83869d30be91SStefano Zampini } else { 83879566063dSJacob Faibussowitsch PetscCall(MatSetUp(local_mat)); 83889d30be91SStefano Zampini } 8389e7931f94SStefano Zampini 8390e7931f94SStefano Zampini /* set values */ 8391e7931f94SStefano Zampini ptr_vals = recv_buffer_vals; 83929d30be91SStefano Zampini ptr_idxs = recv_buffer_idxs_local; 8393e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 8394e7931f94SStefano Zampini if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */ 83959566063dSJacob Faibussowitsch PetscCall(MatSetOption(local_mat, MAT_ROW_ORIENTED, PETSC_FALSE)); 83969566063dSJacob Faibussowitsch PetscCall(MatSetValues(local_mat, *(ptr_idxs + 1), ptr_idxs + 2, *(ptr_idxs + 1), ptr_idxs + 2, ptr_vals, ADD_VALUES)); 83979566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(local_mat, MAT_FLUSH_ASSEMBLY)); 83989566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(local_mat, MAT_FLUSH_ASSEMBLY)); 83999566063dSJacob Faibussowitsch PetscCall(MatSetOption(local_mat, MAT_ROW_ORIENTED, PETSC_TRUE)); 840028143c3dSStefano Zampini } else { 840128143c3dSStefano Zampini /* TODO */ 8402e7931f94SStefano Zampini } 8403e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 8404e7931f94SStefano Zampini ptr_vals += olengths_vals[i]; 8405e7931f94SStefano Zampini } 84069566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(local_mat, MAT_FINAL_ASSEMBLY)); 84079566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(local_mat, MAT_FINAL_ASSEMBLY)); 84089566063dSJacob Faibussowitsch PetscCall(MatISRestoreLocalMat(*mat_n, &local_mat)); 84099566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat_n, MAT_FINAL_ASSEMBLY)); 84109566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat_n, MAT_FINAL_ASSEMBLY)); 84119566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_buffer_vals)); 8412e7931f94SStefano Zampini 8413dfd14d43SStefano Zampini #if 0 841428143c3dSStefano Zampini if (!restrict_comm) { /* check */ 8415e7931f94SStefano Zampini Vec lvec,rvec; 8416e7931f94SStefano Zampini PetscReal infty_error; 8417e7931f94SStefano Zampini 84189566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(mat,&rvec,&lvec)); 84199566063dSJacob Faibussowitsch PetscCall(VecSetRandom(rvec,NULL)); 84209566063dSJacob Faibussowitsch PetscCall(MatMult(mat,rvec,lvec)); 84219566063dSJacob Faibussowitsch PetscCall(VecScale(lvec,-1.0)); 84229566063dSJacob Faibussowitsch PetscCall(MatMultAdd(*mat_n,rvec,lvec,lvec)); 84239566063dSJacob Faibussowitsch PetscCall(VecNorm(lvec,NORM_INFINITY,&infty_error)); 84249566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error)); 84259566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rvec)); 84269566063dSJacob Faibussowitsch PetscCall(VecDestroy(&lvec)); 8427e7931f94SStefano Zampini } 842828143c3dSStefano Zampini #endif 8429e7931f94SStefano Zampini 843028143c3dSStefano Zampini /* assemble new additional is (if any) */ 843128143c3dSStefano Zampini if (nis) { 843228143c3dSStefano Zampini PetscInt **temp_idxs, *count_is, j, psum; 843328143c3dSStefano Zampini 84349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_recvs, recv_req_idxs_is, MPI_STATUSES_IGNORE)); 84359566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nis, &count_is)); 843628143c3dSStefano Zampini ptr_idxs = recv_buffer_idxs_is; 843728143c3dSStefano Zampini psum = 0; 843828143c3dSStefano Zampini for (i = 0; i < n_recvs; i++) { 843928143c3dSStefano Zampini for (j = 0; j < nis; j++) { 844028143c3dSStefano Zampini PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */ 844128143c3dSStefano Zampini count_is[j] += plen; /* increment counting of buffer for j-th IS */ 844228143c3dSStefano Zampini psum += plen; 844328143c3dSStefano Zampini ptr_idxs += plen + 1; /* shift pointer to received data */ 844428143c3dSStefano Zampini } 844528143c3dSStefano Zampini } 84469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nis, &temp_idxs)); 84479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(psum, &temp_idxs[0])); 84488e3a54c0SPierre Jolivet for (i = 1; i < nis; i++) temp_idxs[i] = PetscSafePointerPlusOffset(temp_idxs[i - 1], count_is[i - 1]); 84499566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(count_is, nis)); 845028143c3dSStefano Zampini ptr_idxs = recv_buffer_idxs_is; 845128143c3dSStefano Zampini for (i = 0; i < n_recvs; i++) { 845228143c3dSStefano Zampini for (j = 0; j < nis; j++) { 845328143c3dSStefano Zampini PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */ 84549566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&temp_idxs[j][count_is[j]], ptr_idxs + 1, plen)); 845528143c3dSStefano Zampini count_is[j] += plen; /* increment starting point of buffer for j-th IS */ 845628143c3dSStefano Zampini ptr_idxs += plen + 1; /* shift pointer to received data */ 845728143c3dSStefano Zampini } 845828143c3dSStefano Zampini } 845928143c3dSStefano Zampini for (i = 0; i < nis; i++) { 84609566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isarray[i])); 84619566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&count_is[i], temp_idxs[i])); 84629566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm_n, count_is[i], temp_idxs[i], PETSC_COPY_VALUES, &isarray[i])); 846328143c3dSStefano Zampini } 84649566063dSJacob Faibussowitsch PetscCall(PetscFree(count_is)); 84659566063dSJacob Faibussowitsch PetscCall(PetscFree(temp_idxs[0])); 84669566063dSJacob Faibussowitsch PetscCall(PetscFree(temp_idxs)); 846728143c3dSStefano Zampini } 8468e7931f94SStefano Zampini /* free workspace */ 84699566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_buffer_idxs_is)); 84709566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_sends, send_req_idxs, MPI_STATUSES_IGNORE)); 84719566063dSJacob Faibussowitsch PetscCall(PetscFree(send_buffer_idxs)); 84729566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_sends, send_req_vals, MPI_STATUSES_IGNORE)); 8473e7931f94SStefano Zampini if (isdense) { 84749566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(mat, &local_mat)); 84759566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(local_mat, &send_buffer_vals)); 84769566063dSJacob Faibussowitsch PetscCall(MatISRestoreLocalMat(mat, &local_mat)); 8477e7931f94SStefano Zampini } else { 84789566063dSJacob Faibussowitsch /* PetscCall(PetscFree(send_buffer_vals)); */ 8479e7931f94SStefano Zampini } 848028143c3dSStefano Zampini if (nis) { 84819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_sends, send_req_idxs_is, MPI_STATUSES_IGNORE)); 84829566063dSJacob Faibussowitsch PetscCall(PetscFree(send_buffer_idxs_is)); 848328143c3dSStefano Zampini } 84841ae86dd6SStefano Zampini 84851ae86dd6SStefano Zampini if (nvecs) { 84869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_recvs, recv_req_vecs, MPI_STATUSES_IGNORE)); 84879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_sends, send_req_vecs, MPI_STATUSES_IGNORE)); 84889566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(nnsp_vec[0], &send_buffer_vecs)); 84899566063dSJacob Faibussowitsch PetscCall(VecDestroy(&nnsp_vec[0])); 84909566063dSJacob Faibussowitsch PetscCall(VecCreate(comm_n, &nnsp_vec[0])); 84919566063dSJacob Faibussowitsch PetscCall(VecSetSizes(nnsp_vec[0], new_local_rows, PETSC_DECIDE)); 84929566063dSJacob Faibussowitsch PetscCall(VecSetType(nnsp_vec[0], VECSTANDARD)); 84931ae86dd6SStefano Zampini /* set values */ 84941ae86dd6SStefano Zampini ptr_vals = recv_buffer_vecs; 84951ae86dd6SStefano Zampini ptr_idxs = recv_buffer_idxs_local; 84969566063dSJacob Faibussowitsch PetscCall(VecGetArray(nnsp_vec[0], &send_buffer_vecs)); 84971ae86dd6SStefano Zampini for (i = 0; i < n_recvs; i++) { 84981ae86dd6SStefano Zampini PetscInt j; 8499ad540459SPierre Jolivet for (j = 0; j < *(ptr_idxs + 1); j++) send_buffer_vecs[*(ptr_idxs + 2 + j)] += *(ptr_vals + j); 85001ae86dd6SStefano Zampini ptr_idxs += olengths_idxs[i]; 85011ae86dd6SStefano Zampini ptr_vals += olengths_idxs[i] - 2; 85021ae86dd6SStefano Zampini } 85039566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(nnsp_vec[0], &send_buffer_vecs)); 85049566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(nnsp_vec[0])); 85059566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(nnsp_vec[0])); 85061ae86dd6SStefano Zampini } 85071ae86dd6SStefano Zampini 85089566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_buffer_vecs)); 85099566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_buffer_idxs_local)); 85109566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_req_idxs)); 85119566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_req_vals)); 85129566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_req_vecs)); 85139566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_req_idxs_is)); 85149566063dSJacob Faibussowitsch PetscCall(PetscFree(send_req_idxs)); 85159566063dSJacob Faibussowitsch PetscCall(PetscFree(send_req_vals)); 85169566063dSJacob Faibussowitsch PetscCall(PetscFree(send_req_vecs)); 85179566063dSJacob Faibussowitsch PetscCall(PetscFree(send_req_idxs_is)); 85189566063dSJacob Faibussowitsch PetscCall(PetscFree(ilengths_vals)); 85199566063dSJacob Faibussowitsch PetscCall(PetscFree(ilengths_idxs)); 85209566063dSJacob Faibussowitsch PetscCall(PetscFree(olengths_vals)); 85219566063dSJacob Faibussowitsch PetscCall(PetscFree(olengths_idxs)); 85229566063dSJacob Faibussowitsch PetscCall(PetscFree(onodes)); 852328143c3dSStefano Zampini if (nis) { 85249566063dSJacob Faibussowitsch PetscCall(PetscFree(ilengths_idxs_is)); 85259566063dSJacob Faibussowitsch PetscCall(PetscFree(olengths_idxs_is)); 85269566063dSJacob Faibussowitsch PetscCall(PetscFree(onodes_is)); 852728143c3dSStefano Zampini } 85289566063dSJacob Faibussowitsch PetscCall(PetscSubcommDestroy(&subcomm)); 85296aad120cSJose E. Roman if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not participate */ 85309566063dSJacob Faibussowitsch PetscCall(MatDestroy(mat_n)); 853148a46eb9SPierre Jolivet for (i = 0; i < nis; i++) PetscCall(ISDestroy(&isarray[i])); 85321ae86dd6SStefano Zampini if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */ 85339566063dSJacob Faibussowitsch PetscCall(VecDestroy(&nnsp_vec[0])); 85341ae86dd6SStefano Zampini } 853553a05cb3SStefano Zampini *mat_n = NULL; 853628143c3dSStefano Zampini } 85373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8538e7931f94SStefano Zampini } 8539a57a6d2fSStefano Zampini 854012edc857SStefano Zampini /* temporary hack into ksp private data structure */ 8541af0996ceSBarry Smith #include <petsc/private/kspimpl.h> 854212edc857SStefano Zampini 85439de2952eSStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc, Mat coarse_submat) 8544d71ae5a4SJacob Faibussowitsch { 8545c8587f34SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 8546c8587f34SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 85479de2952eSStefano Zampini PCBDDCGraph graph = pcbddc->mat_graph; 85489de2952eSStefano Zampini Mat coarse_mat, coarse_mat_is; 85491ae86dd6SStefano Zampini Mat coarsedivudotp = NULL; 85501e0482f5SStefano Zampini Mat coarseG, t_coarse_mat_is; 85519881197aSStefano Zampini MatNullSpace CoarseNullSpace = NULL; 855220a2ab83SStefano Zampini ISLocalToGlobalMapping coarse_islg; 85534f819b78SStefano Zampini IS coarse_is, *isarray, corners; 85546e683305SStefano Zampini PetscInt i, im_active = -1, active_procs = -1; 855530368db7SStefano Zampini PetscInt nis, nisdofs, nisneu, nisvert; 85569de2952eSStefano Zampini PetscInt coarse_eqs_per_proc, coarsening_ratio; 8557f9eb5b7dSStefano Zampini PC pc_temp; 8558c8587f34SStefano Zampini PCType coarse_pc_type; 8559c8587f34SStefano Zampini KSPType coarse_ksp_type; 8560f9eb5b7dSStefano Zampini PetscBool multilevel_requested, multilevel_allowed; 85619de2952eSStefano Zampini PetscBool coarse_reuse, multi_element = graph->multi_element; 85621e0482f5SStefano Zampini PetscInt ncoarse, nedcfield; 856368457ee5SStefano Zampini PetscBool compute_vecs = PETSC_FALSE; 856422bc73bbSStefano Zampini PetscScalar *array; 856557de7509SStefano Zampini MatReuse coarse_mat_reuse; 856657de7509SStefano Zampini PetscBool restr, full_restr, have_void; 8567e569e4e1SStefano Zampini PetscMPIInt size; 8568fdc09c96SStefano Zampini 8569c8587f34SStefano Zampini PetscFunctionBegin; 85709566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_CoarseSetUp[pcbddc->current_level], pc, 0, 0, 0)); 8571c8587f34SStefano Zampini /* Assign global numbering to coarse dofs */ 857268457ee5SStefano 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 */ 8573fa7f1dd8SStefano Zampini PetscInt ocoarse_size; 85745a75c04eSSatish Balay compute_vecs = PETSC_TRUE; 85757de4f681Sstefano_zampini 85767de4f681Sstefano_zampini pcbddc->new_primal_space = PETSC_TRUE; 8577fa7f1dd8SStefano Zampini ocoarse_size = pcbddc->coarse_size; 85789566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->global_primal_indices)); 85799566063dSJacob Faibussowitsch PetscCall(PCBDDCComputePrimalNumbering(pc, &pcbddc->coarse_size, &pcbddc->global_primal_indices)); 8580f4ddd8eeSStefano Zampini /* see if we can avoid some work */ 8581fa7f1dd8SStefano Zampini if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */ 858251bea450SStefano Zampini /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */ 858351bea450SStefano Zampini if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) { 85849566063dSJacob Faibussowitsch PetscCall(KSPReset(pcbddc->coarse_ksp)); 8585fa7f1dd8SStefano Zampini coarse_reuse = PETSC_FALSE; 8586fa7f1dd8SStefano Zampini } else { /* we can safely reuse already computed coarse matrix */ 8587fa7f1dd8SStefano Zampini coarse_reuse = PETSC_TRUE; 8588f4ddd8eeSStefano Zampini } 8589fa7f1dd8SStefano Zampini } else { /* there's no coarse ksp, so we need to create the coarse matrix too */ 8590fa7f1dd8SStefano Zampini coarse_reuse = PETSC_FALSE; 8591f4ddd8eeSStefano Zampini } 859270cf5478SStefano Zampini /* reset any subassembling information */ 859348a46eb9SPierre Jolivet if (!coarse_reuse || pcbddc->recompute_topography) PetscCall(ISDestroy(&pcbddc->coarse_subassembling)); 85946e683305SStefano Zampini } else { /* primal space is unchanged, so we can reuse coarse matrix */ 8595fa7f1dd8SStefano Zampini coarse_reuse = PETSC_TRUE; 8596f4ddd8eeSStefano Zampini } 859757de7509SStefano Zampini if (coarse_reuse && pcbddc->coarse_ksp) { 85989566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(pcbddc->coarse_ksp, &coarse_mat, NULL)); 85999566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coarse_mat)); 860057de7509SStefano Zampini coarse_mat_reuse = MAT_REUSE_MATRIX; 860118a45a71SStefano Zampini } else { 860257de7509SStefano Zampini coarse_mat = NULL; 860357de7509SStefano Zampini coarse_mat_reuse = MAT_INITIAL_MATRIX; 86046e683305SStefano Zampini } 8605e7931f94SStefano Zampini 8606abbbba34SStefano Zampini /* creates temporary l2gmap and IS for coarse indexes */ 86079566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), pcbddc->local_primal_size, pcbddc->global_primal_indices, PETSC_COPY_VALUES, &coarse_is)); 86089566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(coarse_is, &coarse_islg)); 8609abbbba34SStefano Zampini 8610abbbba34SStefano Zampini /* creates temporary MATIS object for coarse matrix */ 86119de2952eSStefano Zampini PetscCall(MatCreate(PetscObjectComm((PetscObject)pc), &t_coarse_mat_is)); 86129de2952eSStefano Zampini PetscCall(MatSetType(t_coarse_mat_is, MATIS)); 86139de2952eSStefano Zampini PetscCall(MatSetSizes(t_coarse_mat_is, PETSC_DECIDE, PETSC_DECIDE, pcbddc->coarse_size, pcbddc->coarse_size)); 8614b96ec092SStefano Zampini PetscCall(MatISSetAllowRepeated(t_coarse_mat_is, multi_element)); 86159de2952eSStefano Zampini PetscCall(MatSetLocalToGlobalMapping(t_coarse_mat_is, coarse_islg, coarse_islg)); 86169de2952eSStefano Zampini PetscCall(MatISSetLocalMat(t_coarse_mat_is, coarse_submat)); 86179566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(t_coarse_mat_is, MAT_FINAL_ASSEMBLY)); 86189566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(t_coarse_mat_is, MAT_FINAL_ASSEMBLY)); 86199de2952eSStefano Zampini PetscCall(MatViewFromOptions(t_coarse_mat_is, (PetscObject)pc, "-pc_bddc_coarse_mat_is_view")); 8620abbbba34SStefano Zampini 862157de7509SStefano Zampini /* count "active" (i.e. with positive local size) and "void" processes */ 8622f4f49eeaSPierre Jolivet im_active = !!pcis->n; 8623462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&im_active, &active_procs, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)pc))); 862457de7509SStefano Zampini 862514f0bfb9SStefano Zampini /* determine number of processes partecipating to coarse solver and compute subassembling pattern */ 862628d58a37SPierre Jolivet /* restr : whether we want to exclude senders (which are not receivers) from the subassembling pattern */ 862757de7509SStefano Zampini /* full_restr : just use the receivers from the subassembling pattern */ 86289566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size)); 862957de7509SStefano Zampini coarse_mat_is = NULL; 863057de7509SStefano Zampini multilevel_allowed = PETSC_FALSE; 863157de7509SStefano Zampini multilevel_requested = PETSC_FALSE; 8632e569e4e1SStefano Zampini coarse_eqs_per_proc = PetscMin(PetscMax(pcbddc->coarse_size, 1), pcbddc->coarse_eqs_per_proc); 86339de2952eSStefano Zampini if (coarse_eqs_per_proc < 0 || size == 1) coarse_eqs_per_proc = PetscMax(pcbddc->coarse_size, 1); 863457de7509SStefano Zampini if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE; 8635e569e4e1SStefano Zampini if (pcbddc->coarse_size <= pcbddc->coarse_eqs_limit) multilevel_requested = PETSC_FALSE; 86369de2952eSStefano Zampini coarsening_ratio = multi_element ? 1 : pcbddc->coarsening_ratio; 863757de7509SStefano Zampini if (multilevel_requested) { 86389de2952eSStefano Zampini ncoarse = active_procs / coarsening_ratio; 863957de7509SStefano Zampini restr = PETSC_FALSE; 864057de7509SStefano Zampini full_restr = PETSC_FALSE; 864157de7509SStefano Zampini } else { 8642e569e4e1SStefano Zampini ncoarse = pcbddc->coarse_size / coarse_eqs_per_proc + !!(pcbddc->coarse_size % coarse_eqs_per_proc); 864357de7509SStefano Zampini restr = PETSC_TRUE; 864457de7509SStefano Zampini full_restr = PETSC_TRUE; 864557de7509SStefano Zampini } 8646b96ec092SStefano Zampini if (!pcbddc->coarse_size || (size == 1 && !multi_element)) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE; 864757de7509SStefano Zampini ncoarse = PetscMax(1, ncoarse); 864857de7509SStefano Zampini if (!pcbddc->coarse_subassembling) { 86499de2952eSStefano Zampini if (coarsening_ratio > 1) { 8650bb360cb4SStefano Zampini if (multilevel_requested) { 86519566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISGetSubassemblingPattern(pc->pmat, &ncoarse, pcbddc->coarse_adj_red, &pcbddc->coarse_subassembling, &have_void)); 8652bb360cb4SStefano Zampini } else { 86539566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISGetSubassemblingPattern(t_coarse_mat_is, &ncoarse, pcbddc->coarse_adj_red, &pcbddc->coarse_subassembling, &have_void)); 8654bb360cb4SStefano Zampini } 8655a198735bSStefano Zampini } else { 86567de4f681Sstefano_zampini PetscMPIInt rank; 865728d58a37SPierre Jolivet 86589566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc), &rank)); 8659835f2295SStefano Zampini have_void = (active_procs == size) ? PETSC_FALSE : PETSC_TRUE; 86609566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)pc), 1, rank, 1, &pcbddc->coarse_subassembling)); 8661b96ec092SStefano Zampini PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_subassembling, "default subassembling")); 8662a198735bSStefano Zampini } 866357de7509SStefano Zampini } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */ 866457de7509SStefano Zampini PetscInt psum; 866557de7509SStefano Zampini if (pcbddc->coarse_ksp) psum = 1; 866657de7509SStefano Zampini else psum = 0; 8667462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&psum, &ncoarse, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)pc))); 8668075e25bcSStefano Zampini have_void = ncoarse < size ? PETSC_TRUE : PETSC_FALSE; 866957de7509SStefano Zampini } 867057de7509SStefano Zampini /* determine if we can go multilevel */ 867157de7509SStefano Zampini if (multilevel_requested) { 867257de7509SStefano Zampini if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */ 867357de7509SStefano Zampini else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */ 867457de7509SStefano Zampini } 867557de7509SStefano Zampini if (multilevel_allowed && have_void) restr = PETSC_TRUE; 867657de7509SStefano Zampini 8677e4d548c7SStefano Zampini /* dump subassembling pattern */ 867848a46eb9SPierre Jolivet if (pcbddc->dbg_flag && multilevel_allowed) PetscCall(ISView(pcbddc->coarse_subassembling, pcbddc->dbg_viewer)); 86796e683305SStefano Zampini /* compute dofs splitting and neumann boundaries for coarse dofs */ 86801e0482f5SStefano Zampini nedcfield = -1; 86814f819b78SStefano Zampini corners = NULL; 86828966356dSPierre Jolivet if (multilevel_allowed && !coarse_reuse && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal || pcbddc->nedclocal || pcbddc->corner_selected)) { /* protects from unneeded computations */ 86836e683305SStefano Zampini PetscInt *tidxs, *tidxs2, nout, tsize, i; 86846e683305SStefano Zampini const PetscInt *idxs; 86856e683305SStefano Zampini ISLocalToGlobalMapping tmap; 86866e683305SStefano Zampini 86876e683305SStefano Zampini /* create map between primal indices (in local representative ordering) and local primal numbering */ 86889566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PETSC_COMM_SELF, 1, pcbddc->local_primal_size, pcbddc->primal_indices_local_idxs, PETSC_COPY_VALUES, &tmap)); 86896e683305SStefano Zampini /* allocate space for temporary storage */ 86909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->local_primal_size, &tidxs)); 86919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->local_primal_size, &tidxs2)); 86926e683305SStefano Zampini /* allocate for IS array */ 86936e683305SStefano Zampini nisdofs = pcbddc->n_ISForDofsLocal; 86941e0482f5SStefano Zampini if (pcbddc->nedclocal) { 86951e0482f5SStefano Zampini if (pcbddc->nedfield > -1) { 86961e0482f5SStefano Zampini nedcfield = pcbddc->nedfield; 86971e0482f5SStefano Zampini } else { 86981e0482f5SStefano Zampini nedcfield = 0; 869963a3b9bcSJacob Faibussowitsch PetscCheck(!nisdofs, PetscObjectComm((PetscObject)pc), PETSC_ERR_PLIB, "This should not happen (%" PetscInt_FMT ")", nisdofs); 87001e0482f5SStefano Zampini nisdofs = 1; 87011e0482f5SStefano Zampini } 87021e0482f5SStefano Zampini } 87036e683305SStefano Zampini nisneu = !!pcbddc->NeumannBoundariesLocal; 870427b6a85dSStefano Zampini nisvert = 0; /* nisvert is not used */ 870530368db7SStefano Zampini nis = nisdofs + nisneu + nisvert; 87069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nis, &isarray)); 87076e683305SStefano Zampini /* dofs splitting */ 87086e683305SStefano Zampini for (i = 0; i < nisdofs; i++) { 87099566063dSJacob Faibussowitsch /* PetscCall(ISView(pcbddc->ISForDofsLocal[i],0)); */ 87101e0482f5SStefano Zampini if (nedcfield != i) { 87119566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->ISForDofsLocal[i], &tsize)); 87129566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->ISForDofsLocal[i], &idxs)); 87139566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(tmap, IS_GTOLM_DROP, tsize, idxs, &nout, tidxs)); 87149566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->ISForDofsLocal[i], &idxs)); 87151e0482f5SStefano Zampini } else { 87169566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->nedclocal, &tsize)); 87179566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->nedclocal, &idxs)); 87189566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(tmap, IS_GTOLM_DROP, tsize, idxs, &nout, tidxs)); 871963a3b9bcSJacob Faibussowitsch PetscCheck(tsize == nout, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Failed when mapping coarse nedelec field! %" PetscInt_FMT " != %" PetscInt_FMT, tsize, nout); 87209566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->nedclocal, &idxs)); 87211e0482f5SStefano Zampini } 87229566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(coarse_islg, nout, tidxs, tidxs2)); 87239566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), nout, tidxs2, PETSC_COPY_VALUES, &isarray[i])); 87249566063dSJacob Faibussowitsch /* PetscCall(ISView(isarray[i],0)); */ 87256e683305SStefano Zampini } 87266e683305SStefano Zampini /* neumann boundaries */ 87276e683305SStefano Zampini if (pcbddc->NeumannBoundariesLocal) { 87289566063dSJacob Faibussowitsch /* PetscCall(ISView(pcbddc->NeumannBoundariesLocal,0)); */ 87299566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->NeumannBoundariesLocal, &tsize)); 87309566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->NeumannBoundariesLocal, &idxs)); 87319566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(tmap, IS_GTOLM_DROP, tsize, idxs, &nout, tidxs)); 87329566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->NeumannBoundariesLocal, &idxs)); 87339566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(coarse_islg, nout, tidxs, tidxs2)); 87349566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), nout, tidxs2, PETSC_COPY_VALUES, &isarray[nisdofs])); 87359566063dSJacob Faibussowitsch /* PetscCall(ISView(isarray[nisdofs],0)); */ 87366e683305SStefano Zampini } 87374f819b78SStefano Zampini /* coordinates */ 87384f819b78SStefano Zampini if (pcbddc->corner_selected) { 87399566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &corners)); 87409566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(corners, &tsize)); 87419566063dSJacob Faibussowitsch PetscCall(ISGetIndices(corners, &idxs)); 87429566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(tmap, IS_GTOLM_DROP, tsize, idxs, &nout, tidxs)); 874363a3b9bcSJacob Faibussowitsch PetscCheck(tsize == nout, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Failed when mapping corners! %" PetscInt_FMT " != %" PetscInt_FMT, tsize, nout); 87449566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(corners, &idxs)); 87459566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &corners)); 87469566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(coarse_islg, nout, tidxs, tidxs2)); 87479566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), nout, tidxs2, PETSC_COPY_VALUES, &corners)); 87484f819b78SStefano Zampini } 87499566063dSJacob Faibussowitsch PetscCall(PetscFree(tidxs)); 87509566063dSJacob Faibussowitsch PetscCall(PetscFree(tidxs2)); 87519566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&tmap)); 87526e683305SStefano Zampini } else { 87536e683305SStefano Zampini nis = 0; 87546e683305SStefano Zampini nisdofs = 0; 87556e683305SStefano Zampini nisneu = 0; 875630368db7SStefano Zampini nisvert = 0; 87576e683305SStefano Zampini isarray = NULL; 87586e683305SStefano Zampini } 87596e683305SStefano Zampini /* destroy no longer needed map */ 87609566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&coarse_islg)); 87616e683305SStefano Zampini 876257de7509SStefano Zampini /* subassemble */ 876357de7509SStefano Zampini if (multilevel_allowed) { 87641ae86dd6SStefano Zampini Vec vp[1]; 87651ae86dd6SStefano Zampini PetscInt nvecs = 0; 87669de2952eSStefano Zampini PetscBool reuse; 87671ae86dd6SStefano Zampini 87681ae86dd6SStefano Zampini vp[0] = NULL; 87699de2952eSStefano Zampini /* XXX HDIV also */ 87701ae86dd6SStefano Zampini if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */ 87719566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pc), &vp[0])); 87729566063dSJacob Faibussowitsch PetscCall(VecSetSizes(vp[0], pcbddc->local_primal_size, PETSC_DECIDE)); 87739566063dSJacob Faibussowitsch PetscCall(VecSetType(vp[0], VECSTANDARD)); 87741ae86dd6SStefano Zampini nvecs = 1; 87751ae86dd6SStefano Zampini 87761ae86dd6SStefano Zampini if (pcbddc->divudotp) { 8777a198735bSStefano Zampini Mat B, loc_divudotp; 87781ae86dd6SStefano Zampini Vec v, p; 87791ae86dd6SStefano Zampini IS dummy; 87801ae86dd6SStefano Zampini PetscInt np; 87811ae86dd6SStefano Zampini 87829566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pcbddc->divudotp, &loc_divudotp)); 87839566063dSJacob Faibussowitsch PetscCall(MatGetSize(loc_divudotp, &np, NULL)); 87849566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, np, 0, 1, &dummy)); 87859566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(loc_divudotp, dummy, pcis->is_B_local, MAT_INITIAL_MATRIX, &B)); 87869566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(B, &v, &p)); 87879566063dSJacob Faibussowitsch PetscCall(VecSet(p, 1.)); 87889566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(B, p, v)); 87899566063dSJacob Faibussowitsch PetscCall(VecDestroy(&p)); 87909566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 87919566063dSJacob Faibussowitsch PetscCall(VecGetArray(vp[0], &array)); 87929566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_P, array)); 87939566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->coarse_phi_B, v, pcbddc->vec1_P)); 87949566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_P)); 87959566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(vp[0], &array)); 87969566063dSJacob Faibussowitsch PetscCall(ISDestroy(&dummy)); 87979566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 879874e2c79eSStefano Zampini } 87991ae86dd6SStefano Zampini } 88009de2952eSStefano Zampini if (coarse_mat) reuse = PETSC_TRUE; 88019de2952eSStefano Zampini else reuse = PETSC_FALSE; 88029de2952eSStefano Zampini if (multi_element) { 88039de2952eSStefano Zampini PetscCall(PetscObjectReference((PetscObject)t_coarse_mat_is)); 88049de2952eSStefano Zampini coarse_mat_is = t_coarse_mat_is; 88059de2952eSStefano Zampini } else { 88065440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &reuse, 1, MPI_C_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 88079de2952eSStefano Zampini if (reuse) { 88089566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISSubassemble(t_coarse_mat_is, pcbddc->coarse_subassembling, 0, restr, full_restr, PETSC_TRUE, &coarse_mat, nis, isarray, nvecs, vp)); 880974e2c79eSStefano Zampini } else { 88109566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISSubassemble(t_coarse_mat_is, pcbddc->coarse_subassembling, 0, restr, full_restr, PETSC_FALSE, &coarse_mat_is, nis, isarray, nvecs, vp)); 88111ae86dd6SStefano Zampini } 88121ae86dd6SStefano Zampini if (vp[0]) { /* vp[0] could have been placed on a different set of processes */ 88131683a169SBarry Smith PetscScalar *arraym; 88141683a169SBarry Smith const PetscScalar *arrayv; 88151ae86dd6SStefano Zampini PetscInt nl; 88169566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vp[0], &nl)); 88179566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, 1, nl, NULL, &coarsedivudotp)); 88189566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(coarsedivudotp, &arraym)); 88199566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vp[0], &arrayv)); 88209566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(arraym, arrayv, nl)); 88219566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vp[0], &arrayv)); 88229566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(coarsedivudotp, &arraym)); 88239566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vp[0])); 8824a198735bSStefano Zampini } else { 88259566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, 0, 0, 1, NULL, &coarsedivudotp)); 88261ae86dd6SStefano Zampini } 88279de2952eSStefano Zampini } 88281ae86dd6SStefano Zampini } else { 8829b96ec092SStefano Zampini PetscBool default_sub; 8830b96ec092SStefano Zampini 8831b96ec092SStefano Zampini PetscCall(PetscStrcmp(((PetscObject)pcbddc->coarse_subassembling)->name, "default subassembling", &default_sub)); 8832b96ec092SStefano Zampini if (!default_sub) PetscCall(PCBDDCMatISSubassemble(t_coarse_mat_is, pcbddc->coarse_subassembling, 0, restr, full_restr, PETSC_FALSE, &coarse_mat_is, 0, NULL, 0, NULL)); 88339de2952eSStefano Zampini else { 88349de2952eSStefano Zampini PetscCall(PetscObjectReference((PetscObject)t_coarse_mat_is)); 88359de2952eSStefano Zampini coarse_mat_is = t_coarse_mat_is; 88369de2952eSStefano Zampini } 88376e683305SStefano Zampini } 883857de7509SStefano Zampini if (coarse_mat_is || coarse_mat) { 883957de7509SStefano Zampini if (!multilevel_allowed) { 88409566063dSJacob Faibussowitsch PetscCall(MatConvert(coarse_mat_is, MATAIJ, coarse_mat_reuse, &coarse_mat)); 88416e683305SStefano Zampini } else { 884257de7509SStefano Zampini /* if this matrix is present, it means we are not reusing the coarse matrix */ 884357de7509SStefano Zampini if (coarse_mat_is) { 884428b400f6SJacob Faibussowitsch PetscCheck(!coarse_mat, PetscObjectComm((PetscObject)coarse_mat_is), PETSC_ERR_PLIB, "This should not happen"); 88459566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coarse_mat_is)); 884657de7509SStefano Zampini coarse_mat = coarse_mat_is; 884757de7509SStefano Zampini } 8848779c1cceSStefano Zampini } 8849779c1cceSStefano Zampini } 88509566063dSJacob Faibussowitsch PetscCall(MatDestroy(&t_coarse_mat_is)); 88519566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_mat_is)); 88526e683305SStefano Zampini 88536e683305SStefano Zampini /* create local to global scatters for coarse problem */ 885468457ee5SStefano Zampini if (compute_vecs) { 88556e683305SStefano Zampini PetscInt lrows; 88569566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->coarse_vec)); 885757de7509SStefano Zampini if (coarse_mat) { 88589566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(coarse_mat, &lrows, NULL)); 88596e683305SStefano Zampini } else { 88606e683305SStefano Zampini lrows = 0; 88616e683305SStefano Zampini } 88629566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pc), &pcbddc->coarse_vec)); 88639566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pcbddc->coarse_vec, lrows, PETSC_DECIDE)); 88649566063dSJacob Faibussowitsch PetscCall(VecSetType(pcbddc->coarse_vec, coarse_mat ? coarse_mat->defaultvectype : VECSTANDARD)); 88659566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->coarse_loc_to_glob)); 88669566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(pcbddc->vec1_P, NULL, pcbddc->coarse_vec, coarse_is, &pcbddc->coarse_loc_to_glob)); 88676e683305SStefano Zampini } 88689566063dSJacob Faibussowitsch PetscCall(ISDestroy(&coarse_is)); 8869c8587f34SStefano Zampini 8870f9eb5b7dSStefano Zampini /* set defaults for coarse KSP and PC */ 8871f9eb5b7dSStefano Zampini if (multilevel_allowed) { 8872f9eb5b7dSStefano Zampini coarse_ksp_type = KSPRICHARDSON; 8873f9eb5b7dSStefano Zampini coarse_pc_type = PCBDDC; 8874f9eb5b7dSStefano Zampini } else { 8875f9eb5b7dSStefano Zampini coarse_ksp_type = KSPPREONLY; 8876f9eb5b7dSStefano Zampini coarse_pc_type = PCREDUNDANT; 8877c8587f34SStefano Zampini } 8878c8587f34SStefano Zampini 88796e683305SStefano Zampini /* print some info if requested */ 88806e683305SStefano Zampini if (pcbddc->dbg_flag) { 88816e683305SStefano Zampini if (!multilevel_allowed) { 88829566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 88836e683305SStefano Zampini if (multilevel_requested) { 88849de2952eSStefano 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)); 88856e683305SStefano Zampini } else if (pcbddc->max_levels) { 888663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Maximum number of requested levels reached (%" PetscInt_FMT ")\n", pcbddc->max_levels)); 88876e683305SStefano Zampini } 88889566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 88896e683305SStefano Zampini } 88906e683305SStefano Zampini } 88916e683305SStefano Zampini 88921e0482f5SStefano Zampini /* communicate coarse discrete gradient */ 88931e0482f5SStefano Zampini coarseG = NULL; 88941e0482f5SStefano Zampini if (pcbddc->nedcG && multilevel_allowed) { 88951e0482f5SStefano Zampini MPI_Comm ccomm; 88961e0482f5SStefano Zampini if (coarse_mat) { 88971e0482f5SStefano Zampini ccomm = PetscObjectComm((PetscObject)coarse_mat); 88981e0482f5SStefano Zampini } else { 88991e0482f5SStefano Zampini ccomm = MPI_COMM_NULL; 89001e0482f5SStefano Zampini } 89019566063dSJacob Faibussowitsch PetscCall(MatMPIAIJRestrict(pcbddc->nedcG, ccomm, &coarseG)); 89021e0482f5SStefano Zampini } 89031e0482f5SStefano Zampini 8904f9eb5b7dSStefano Zampini /* create the coarse KSP object only once with defaults */ 890557de7509SStefano Zampini if (coarse_mat) { 890628d58a37SPierre Jolivet PetscBool isredundant, isbddc, force, valid; 89076a1308c2SStefano Zampini PetscViewer dbg_viewer = NULL; 8908b94d7dedSBarry Smith PetscBool isset, issym, isher, isspd; 89097274672aSStefano Zampini 89106e683305SStefano Zampini if (pcbddc->dbg_flag) { 891157de7509SStefano Zampini dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat)); 89129566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIAddTab(dbg_viewer, 2 * pcbddc->current_level)); 89136e683305SStefano Zampini } 8914f9eb5b7dSStefano Zampini if (!pcbddc->coarse_ksp) { 8915312be037SStefano Zampini char prefix[256], str_level[16]; 8916e604994aSStefano Zampini size_t len; 89171e0482f5SStefano Zampini 89189566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)coarse_mat), &pcbddc->coarse_ksp)); 89193821be0aSBarry Smith PetscCall(KSPSetNestLevel(pcbddc->coarse_ksp, pc->kspnestlevel)); 89209566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(pcbddc->coarse_ksp, pc->erroriffailure)); 89219566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp, (PetscObject)pc, 1)); 8922fb842aefSJose E. Roman PetscCall(KSPSetTolerances(pcbddc->coarse_ksp, PETSC_CURRENT, PETSC_CURRENT, PETSC_CURRENT, 1)); 89239566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(pcbddc->coarse_ksp, coarse_mat, coarse_mat)); 89249566063dSJacob Faibussowitsch PetscCall(KSPSetType(pcbddc->coarse_ksp, coarse_ksp_type)); 89259566063dSJacob Faibussowitsch PetscCall(KSPSetNormType(pcbddc->coarse_ksp, KSP_NORM_NONE)); 89269566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &pc_temp)); 89271e0482f5SStefano Zampini /* TODO is this logic correct? should check for coarse_mat type */ 89289566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, coarse_pc_type)); 8929e604994aSStefano Zampini /* prefix */ 8930c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(prefix, "", sizeof(prefix))); 8931c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(str_level, "", sizeof(str_level))); 8932e604994aSStefano Zampini if (!pcbddc->current_level) { 89339566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(prefix, ((PetscObject)pc)->prefix, sizeof(prefix))); 89349566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, "pc_bddc_coarse_", sizeof(prefix))); 8935c8587f34SStefano Zampini } else { 89369566063dSJacob Faibussowitsch PetscCall(PetscStrlen(((PetscObject)pc)->prefix, &len)); 8937312be037SStefano Zampini if (pcbddc->current_level > 1) len -= 3; /* remove "lX_" with X level number */ 8938312be037SStefano Zampini if (pcbddc->current_level > 10) len -= 1; /* remove another char from level number */ 8939a126751eSBarry Smith /* Nonstandard use of PetscStrncpy() to copy only a portion of the string */ 89409566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(prefix, ((PetscObject)pc)->prefix, len + 1)); 8941835f2295SStefano Zampini PetscCall(PetscSNPrintf(str_level, sizeof(str_level), "l%" PetscInt_FMT "_", pcbddc->current_level)); 89429566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, str_level, sizeof(prefix))); 8943e604994aSStefano Zampini } 89449566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(pcbddc->coarse_ksp, prefix)); 89453e3c6dadSStefano Zampini /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */ 89469566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLevel(pc_temp, pcbddc->current_level + 1)); 89479566063dSJacob Faibussowitsch PetscCall(PCBDDCSetCoarseningRatio(pc_temp, pcbddc->coarsening_ratio)); 89489566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLevels(pc_temp, pcbddc->max_levels)); 8949f9eb5b7dSStefano Zampini /* allow user customization */ 89509566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(pcbddc->coarse_ksp)); 8951e569e4e1SStefano Zampini /* get some info after set from options */ 89529566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &pc_temp)); 895328d58a37SPierre Jolivet /* multilevel cannot be done with coarse PC different from BDDC, NN, HPDDM, unless forced to */ 895428d58a37SPierre Jolivet force = PETSC_FALSE; 89559566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)pc_temp)->prefix, "-pc_type_forced", &force, NULL)); 89569566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)pc_temp, &valid, PCBDDC, PCNN, PCHPDDM, "")); 89579566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp, PCBDDC, &isbddc)); 895828d58a37SPierre Jolivet if (multilevel_allowed && !force && !valid) { 8959e569e4e1SStefano Zampini isbddc = PETSC_TRUE; 89609566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCBDDC)); 89619566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLevel(pc_temp, pcbddc->current_level + 1)); 89629566063dSJacob Faibussowitsch PetscCall(PCBDDCSetCoarseningRatio(pc_temp, pcbddc->coarsening_ratio)); 89639566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLevels(pc_temp, pcbddc->max_levels)); 89644f819b78SStefano Zampini if (pc_temp->ops->setfromoptions) { /* need to setfromoptions again, skipping the pc_type */ 8965d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)pc_temp); 8966dbbe0bcdSBarry Smith PetscCall((*pc_temp->ops->setfromoptions)(pc_temp, PetscOptionsObject)); 8967dbbe0bcdSBarry Smith PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)pc_temp, PetscOptionsObject)); 8968d0609cedSBarry Smith PetscOptionsEnd(); 89694f819b78SStefano Zampini pc_temp->setfromoptionscalled++; 89704f819b78SStefano Zampini } 8971e569e4e1SStefano Zampini } 89723e3c6dadSStefano Zampini } 89733e3c6dadSStefano Zampini /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */ 89749566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &pc_temp)); 89753e3c6dadSStefano Zampini if (nisdofs) { 89769566063dSJacob Faibussowitsch PetscCall(PCBDDCSetDofsSplitting(pc_temp, nisdofs, isarray)); 897748a46eb9SPierre Jolivet for (i = 0; i < nisdofs; i++) PetscCall(ISDestroy(&isarray[i])); 89783e3c6dadSStefano Zampini } 89793e3c6dadSStefano Zampini if (nisneu) { 89809566063dSJacob Faibussowitsch PetscCall(PCBDDCSetNeumannBoundaries(pc_temp, isarray[nisdofs])); 89819566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isarray[nisdofs])); 8982312be037SStefano Zampini } 898330368db7SStefano Zampini if (nisvert) { 89849566063dSJacob Faibussowitsch PetscCall(PCBDDCSetPrimalVerticesIS(pc_temp, isarray[nis - 1])); 89859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isarray[nis - 1])); 898630368db7SStefano Zampini } 89871baa6e33SBarry Smith if (coarseG) PetscCall(PCBDDCSetDiscreteGradient(pc_temp, coarseG, 1, nedcfield, PETSC_FALSE, PETSC_TRUE)); 8988f9eb5b7dSStefano Zampini 8989f9eb5b7dSStefano Zampini /* get some info after set from options */ 89909566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp, PCBDDC, &isbddc)); 89914f819b78SStefano Zampini 8992b76f3995Sstefano_zampini /* multilevel can only be requested via -pc_bddc_levels or PCBDDCSetLevels */ 899348a46eb9SPierre Jolivet if (isbddc && !multilevel_allowed) PetscCall(PCSetType(pc_temp, coarse_pc_type)); 899428d58a37SPierre Jolivet /* multilevel cannot be done with coarse PC different from BDDC, NN, HPDDM, unless forced to */ 899528d58a37SPierre Jolivet force = PETSC_FALSE; 89969566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)pc_temp)->prefix, "-pc_type_forced", &force, NULL)); 89979566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)pc_temp, &valid, PCBDDC, PCNN, PCHPDDM, "")); 899848a46eb9SPierre Jolivet if (multilevel_requested && multilevel_allowed && !valid && !force) PetscCall(PCSetType(pc_temp, PCBDDC)); 89999566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp, PCREDUNDANT, &isredundant)); 90004f3a063dSStefano Zampini if (isredundant) { 90014f3a063dSStefano Zampini KSP inner_ksp; 90024f3a063dSStefano Zampini PC inner_pc; 90039326c5c6Sstefano_zampini 90049566063dSJacob Faibussowitsch PetscCall(PCRedundantGetKSP(pc_temp, &inner_ksp)); 90059566063dSJacob Faibussowitsch PetscCall(KSPGetPC(inner_ksp, &inner_pc)); 90064f3a063dSStefano Zampini } 9007f9eb5b7dSStefano Zampini 900857de7509SStefano Zampini /* parameters which miss an API */ 90099566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp, PCBDDC, &isbddc)); 901057de7509SStefano Zampini if (isbddc) { 9011720d30f9SStefano Zampini PC_BDDC *pcbddc_coarse = (PC_BDDC *)pc_temp->data; 90127274672aSStefano Zampini 9013720d30f9SStefano Zampini pcbddc_coarse->detect_disconnected = PETSC_TRUE; 901457de7509SStefano Zampini pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc; 9015e569e4e1SStefano Zampini pcbddc_coarse->coarse_eqs_limit = pcbddc->coarse_eqs_limit; 901627b6a85dSStefano Zampini pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null; 901727b6a85dSStefano Zampini if (pcbddc_coarse->benign_saddle_point) { 9018a198735bSStefano Zampini Mat coarsedivudotp_is; 9019a198735bSStefano Zampini ISLocalToGlobalMapping l2gmap, rl2g, cl2g; 9020a198735bSStefano Zampini IS row, col; 9021a198735bSStefano Zampini const PetscInt *gidxs; 9022a198735bSStefano Zampini PetscInt n, st, M, N; 9023a198735bSStefano Zampini 90249566063dSJacob Faibussowitsch PetscCall(MatGetSize(coarsedivudotp, &n, NULL)); 90259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Scan(&n, &st, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)coarse_mat))); 9026a198735bSStefano Zampini st = st - n; 90279566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)coarse_mat), 1, st, 1, &row)); 90289566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(coarse_mat, &l2gmap, NULL)); 90299566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(l2gmap, &n)); 90309566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(l2gmap, &gidxs)); 90319566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat), n, gidxs, PETSC_COPY_VALUES, &col)); 90329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(l2gmap, &gidxs)); 90339566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(row, &rl2g)); 90349566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(col, &cl2g)); 90359566063dSJacob Faibussowitsch PetscCall(ISGetSize(row, &M)); 90369566063dSJacob Faibussowitsch PetscCall(MatGetSize(coarse_mat, &N, NULL)); 90379566063dSJacob Faibussowitsch PetscCall(ISDestroy(&row)); 90389566063dSJacob Faibussowitsch PetscCall(ISDestroy(&col)); 90399566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)coarse_mat), &coarsedivudotp_is)); 90409566063dSJacob Faibussowitsch PetscCall(MatSetType(coarsedivudotp_is, MATIS)); 90419566063dSJacob Faibussowitsch PetscCall(MatSetSizes(coarsedivudotp_is, PETSC_DECIDE, PETSC_DECIDE, M, N)); 90429566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(coarsedivudotp_is, rl2g, cl2g)); 90439566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 90449566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 90459566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(coarsedivudotp_is, coarsedivudotp)); 90469566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarsedivudotp)); 90479566063dSJacob Faibussowitsch PetscCall(PCBDDCSetDivergenceMat(pc_temp, coarsedivudotp_is, PETSC_FALSE, NULL)); 90489566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarsedivudotp_is)); 9049720d30f9SStefano Zampini pcbddc_coarse->adaptive_userdefined = PETSC_TRUE; 9050bd2a564bSStefano Zampini if (pcbddc->adaptive_threshold[0] == 0.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE; 9051720d30f9SStefano Zampini } 9052d4d8cf7bSStefano Zampini } 90539881197aSStefano Zampini 90543301b35fSStefano Zampini /* propagate symmetry info of coarse matrix */ 90559566063dSJacob Faibussowitsch PetscCall(MatSetOption(coarse_mat, MAT_STRUCTURALLY_SYMMETRIC, PETSC_TRUE)); 9056b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(pc->pmat, &isset, &issym)); 9057b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(coarse_mat, MAT_SYMMETRIC, issym)); 9058b94d7dedSBarry Smith PetscCall(MatIsHermitianKnown(pc->pmat, &isset, &isher)); 9059b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(coarse_mat, MAT_HERMITIAN, isher)); 9060b94d7dedSBarry Smith PetscCall(MatIsSPDKnown(pc->pmat, &isset, &isspd)); 9061b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(coarse_mat, MAT_SPD, isspd)); 9062b94d7dedSBarry Smith 906348a46eb9SPierre Jolivet if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) PetscCall(MatSetOption(coarse_mat, MAT_SPD, PETSC_TRUE)); 90646e683305SStefano Zampini /* set operators */ 90659566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(coarse_mat, (PetscObject)pc, "-pc_bddc_coarse_mat_view")); 90669566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(coarse_mat, ((PetscObject)pcbddc->coarse_ksp)->prefix)); 90679566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(pcbddc->coarse_ksp, coarse_mat, coarse_mat)); 90681baa6e33SBarry Smith if (pcbddc->dbg_flag) PetscCall(PetscViewerASCIISubtractTab(dbg_viewer, 2 * pcbddc->current_level)); 90696e683305SStefano Zampini } 90709566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarseG)); 90719566063dSJacob Faibussowitsch PetscCall(PetscFree(isarray)); 9072b1ecc7b1SStefano Zampini #if 0 9073b9b85e73SStefano Zampini { 9074b9b85e73SStefano Zampini PetscViewer viewer; 9075b9b85e73SStefano Zampini char filename[256]; 9076a364092eSJacob Faibussowitsch PetscCall(PetscSNPrintf(filename, PETSC_STATIC_ARRAY_LENGTH(filename), "coarse_mat_level%d.m",pcbddc->current_level)); 90779566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer)); 90789566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB)); 90799566063dSJacob Faibussowitsch PetscCall(MatView(coarse_mat,viewer)); 90809566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 90819566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 9082b9b85e73SStefano Zampini } 9083b9b85e73SStefano Zampini #endif 9084f9eb5b7dSStefano Zampini 90854f819b78SStefano Zampini if (corners) { 90864f819b78SStefano Zampini Vec gv; 90874f819b78SStefano Zampini IS is; 90884f819b78SStefano Zampini const PetscInt *idxs; 90894f819b78SStefano Zampini PetscInt i, d, N, n, cdim = pcbddc->mat_graph->cdim; 90904f819b78SStefano Zampini PetscScalar *coords; 90914f819b78SStefano Zampini 909228b400f6SJacob Faibussowitsch PetscCheck(pcbddc->mat_graph->cloc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing local coordinates"); 90939566063dSJacob Faibussowitsch PetscCall(VecGetSize(pcbddc->coarse_vec, &N)); 90949566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(pcbddc->coarse_vec, &n)); 90959566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pcbddc->coarse_vec), &gv)); 90969566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(gv, cdim)); 90979566063dSJacob Faibussowitsch PetscCall(VecSetSizes(gv, n * cdim, N * cdim)); 90989566063dSJacob Faibussowitsch PetscCall(VecSetType(gv, VECSTANDARD)); 90999566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(gv)); 91009566063dSJacob Faibussowitsch PetscCall(VecSet(gv, PETSC_MAX_REAL)); /* we only propagate coordinates from vertices constraints */ 91014f819b78SStefano Zampini 91029566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &is)); 91039566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &n)); 91049566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, &idxs)); 91059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n * cdim, &coords)); 91064f819b78SStefano Zampini for (i = 0; i < n; i++) { 9107ad540459SPierre Jolivet for (d = 0; d < cdim; d++) coords[cdim * i + d] = pcbddc->mat_graph->coords[cdim * idxs[i] + d]; 91084f819b78SStefano Zampini } 91099566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, &idxs)); 91109566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &is)); 91114f819b78SStefano Zampini 91129566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(corners, &n)); 91139566063dSJacob Faibussowitsch PetscCall(ISGetIndices(corners, &idxs)); 91149566063dSJacob Faibussowitsch PetscCall(VecSetValuesBlocked(gv, n, idxs, coords, INSERT_VALUES)); 91159566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(corners, &idxs)); 91169566063dSJacob Faibussowitsch PetscCall(PetscFree(coords)); 91179566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(gv)); 91189566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(gv)); 91199566063dSJacob Faibussowitsch PetscCall(VecGetArray(gv, &coords)); 91204f819b78SStefano Zampini if (pcbddc->coarse_ksp) { 91214f819b78SStefano Zampini PC coarse_pc; 91224f819b78SStefano Zampini PetscBool isbddc; 91234f819b78SStefano Zampini 91249566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &coarse_pc)); 91259566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)coarse_pc, PCBDDC, &isbddc)); 91264f819b78SStefano Zampini if (isbddc) { /* coarse coordinates have PETSC_MAX_REAL, specific for BDDC */ 91274f819b78SStefano Zampini PetscReal *realcoords; 91284f819b78SStefano Zampini 91299566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(gv, &n)); 91304f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX) 91319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &realcoords)); 91324f819b78SStefano Zampini for (i = 0; i < n; i++) realcoords[i] = PetscRealPart(coords[i]); 91334f819b78SStefano Zampini #else 91344f819b78SStefano Zampini realcoords = coords; 91354f819b78SStefano Zampini #endif 91369566063dSJacob Faibussowitsch PetscCall(PCSetCoordinates(coarse_pc, cdim, n / cdim, realcoords)); 91374f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX) 91389566063dSJacob Faibussowitsch PetscCall(PetscFree(realcoords)); 91394f819b78SStefano Zampini #endif 91404f819b78SStefano Zampini } 91414f819b78SStefano Zampini } 91429566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(gv, &coords)); 91439566063dSJacob Faibussowitsch PetscCall(VecDestroy(&gv)); 91444f819b78SStefano Zampini } 91459566063dSJacob Faibussowitsch PetscCall(ISDestroy(&corners)); 91464f819b78SStefano Zampini 914798a51de6SStefano Zampini if (pcbddc->coarse_ksp) { 914898a51de6SStefano Zampini Vec crhs, csol; 914904708bb6SStefano Zampini 91509566063dSJacob Faibussowitsch PetscCall(KSPGetSolution(pcbddc->coarse_ksp, &csol)); 91519566063dSJacob Faibussowitsch PetscCall(KSPGetRhs(pcbddc->coarse_ksp, &crhs)); 9152f4f49eeaSPierre Jolivet if (!csol) PetscCall(MatCreateVecs(coarse_mat, &pcbddc->coarse_ksp->vec_sol, NULL)); 9153f4f49eeaSPierre Jolivet if (!crhs) PetscCall(MatCreateVecs(coarse_mat, NULL, &pcbddc->coarse_ksp->vec_rhs)); 9154b0f5fe93SStefano Zampini } 91559566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarsedivudotp)); 9156b0f5fe93SStefano Zampini 9157b0f5fe93SStefano Zampini /* compute null space for coarse solver if the benign trick has been requested */ 9158b0f5fe93SStefano Zampini if (pcbddc->benign_null) { 91599566063dSJacob Faibussowitsch PetscCall(VecSet(pcbddc->vec1_P, 0.)); 916048a46eb9SPierre 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)); 91619566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(pcbddc->vec1_P)); 91629566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(pcbddc->vec1_P)); 91639566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob, pcbddc->vec1_P, pcbddc->coarse_vec, INSERT_VALUES, SCATTER_FORWARD)); 91649566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob, pcbddc->vec1_P, pcbddc->coarse_vec, INSERT_VALUES, SCATTER_FORWARD)); 9165b0f5fe93SStefano Zampini if (coarse_mat) { 9166b0f5fe93SStefano Zampini Vec nullv; 9167b0f5fe93SStefano Zampini PetscScalar *array, *array2; 9168b0f5fe93SStefano Zampini PetscInt nl; 9169b0f5fe93SStefano Zampini 91709566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(coarse_mat, &nullv, NULL)); 91719566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(nullv, &nl)); 91729566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(pcbddc->coarse_vec, (const PetscScalar **)&array)); 91739566063dSJacob Faibussowitsch PetscCall(VecGetArray(nullv, &array2)); 91749566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(array2, array, nl)); 91759566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(nullv, &array2)); 91769566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(pcbddc->coarse_vec, (const PetscScalar **)&array)); 91779566063dSJacob Faibussowitsch PetscCall(VecNormalize(nullv, NULL)); 91789566063dSJacob Faibussowitsch PetscCall(MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat), PETSC_FALSE, 1, &nullv, &CoarseNullSpace)); 91799566063dSJacob Faibussowitsch PetscCall(VecDestroy(&nullv)); 9180b0f5fe93SStefano Zampini } 9181b0f5fe93SStefano Zampini } 91829566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_CoarseSetUp[pcbddc->current_level], pc, 0, 0, 0)); 9183b0f5fe93SStefano Zampini 91849566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_CoarseSolver[pcbddc->current_level], pc, 0, 0, 0)); 9185b0f5fe93SStefano Zampini if (pcbddc->coarse_ksp) { 9186b0f5fe93SStefano Zampini PetscBool ispreonly; 9187b0f5fe93SStefano Zampini 9188b0f5fe93SStefano Zampini if (CoarseNullSpace) { 9189b0f5fe93SStefano Zampini PetscBool isnull; 91907c625d9fSStefano Zampini 91919566063dSJacob Faibussowitsch PetscCall(MatNullSpaceTest(CoarseNullSpace, coarse_mat, &isnull)); 91921baa6e33SBarry Smith if (isnull) PetscCall(MatSetNullSpace(coarse_mat, CoarseNullSpace)); 9193bef83e63SStefano Zampini /* TODO: add local nullspaces (if any) */ 9194b0f5fe93SStefano Zampini } 9195b0f5fe93SStefano Zampini /* setup coarse ksp */ 91969566063dSJacob Faibussowitsch PetscCall(KSPSetUp(pcbddc->coarse_ksp)); 9197cbcc2c2aSStefano Zampini /* Check coarse problem if in debug mode or if solving with an iterative method */ 91989566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp, KSPPREONLY, &ispreonly)); 91996e683305SStefano Zampini if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates)) { 9200c8587f34SStefano Zampini KSP check_ksp; 92012b510759SStefano Zampini KSPType check_ksp_type; 9202c8587f34SStefano Zampini PC check_pc; 92036e683305SStefano Zampini Vec check_vec, coarse_vec; 92046a1308c2SStefano Zampini PetscReal abs_infty_error, infty_error, lambda_min = 1.0, lambda_max = 1.0; 92052b510759SStefano Zampini PetscInt its; 92066e683305SStefano Zampini PetscBool compute_eigs; 92076e683305SStefano Zampini PetscReal *eigs_r, *eigs_c; 92086e683305SStefano Zampini PetscInt neigs; 92098e185a42SStefano Zampini const char *prefix; 9210c8587f34SStefano Zampini 92112b510759SStefano Zampini /* Create ksp object suitable for estimation of extreme eigenvalues */ 92129566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp), &check_ksp)); 92133821be0aSBarry Smith PetscCall(KSPSetNestLevel(check_ksp, pc->kspnestlevel)); 92149566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)check_ksp, (PetscObject)pcbddc->coarse_ksp, 0)); 92159566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(pcbddc->coarse_ksp, PETSC_FALSE)); 92169566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(check_ksp, coarse_mat, coarse_mat)); 9217fb842aefSJose E. Roman PetscCall(KSPSetTolerances(check_ksp, 1.e-12, 1.e-12, PETSC_CURRENT, pcbddc->coarse_size)); 9218e4d548c7SStefano Zampini /* prevent from setup unneeded object */ 92199566063dSJacob Faibussowitsch PetscCall(KSPGetPC(check_ksp, &check_pc)); 92209566063dSJacob Faibussowitsch PetscCall(PCSetType(check_pc, PCNONE)); 92212b510759SStefano Zampini if (ispreonly) { 92222b510759SStefano Zampini check_ksp_type = KSPPREONLY; 92236e683305SStefano Zampini compute_eigs = PETSC_FALSE; 92242b510759SStefano Zampini } else { 9225cbcc2c2aSStefano Zampini check_ksp_type = KSPGMRES; 92266e683305SStefano Zampini compute_eigs = PETSC_TRUE; 9227c8587f34SStefano Zampini } 92289566063dSJacob Faibussowitsch PetscCall(KSPSetType(check_ksp, check_ksp_type)); 92299566063dSJacob Faibussowitsch PetscCall(KSPSetComputeSingularValues(check_ksp, compute_eigs)); 92309566063dSJacob Faibussowitsch PetscCall(KSPSetComputeEigenvalues(check_ksp, compute_eigs)); 92319566063dSJacob Faibussowitsch PetscCall(KSPGMRESSetRestart(check_ksp, pcbddc->coarse_size + 1)); 92329566063dSJacob Faibussowitsch PetscCall(KSPGetOptionsPrefix(pcbddc->coarse_ksp, &prefix)); 92339566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(check_ksp, prefix)); 92349566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(check_ksp, "check_")); 92359566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(check_ksp)); 92369566063dSJacob Faibussowitsch PetscCall(KSPSetUp(check_ksp)); 92379566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &check_pc)); 92389566063dSJacob Faibussowitsch PetscCall(KSPSetPC(check_ksp, check_pc)); 9239c8587f34SStefano Zampini /* create random vec */ 92409566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(coarse_mat, &coarse_vec, &check_vec)); 92419566063dSJacob Faibussowitsch PetscCall(VecSetRandom(check_vec, NULL)); 92429566063dSJacob Faibussowitsch PetscCall(MatMult(coarse_mat, check_vec, coarse_vec)); 9243c8587f34SStefano Zampini /* solve coarse problem */ 92449566063dSJacob Faibussowitsch PetscCall(KSPSolve(check_ksp, coarse_vec, coarse_vec)); 92459566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(check_ksp, pc, coarse_vec)); 9246cbcc2c2aSStefano Zampini /* set eigenvalue estimation if preonly has not been requested */ 92476e683305SStefano Zampini if (compute_eigs) { 92489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->coarse_size + 1, &eigs_r)); 92499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->coarse_size + 1, &eigs_c)); 92509566063dSJacob Faibussowitsch PetscCall(KSPComputeEigenvalues(check_ksp, pcbddc->coarse_size + 1, eigs_r, eigs_c, &neigs)); 92511ae86dd6SStefano Zampini if (neigs) { 92526e683305SStefano Zampini lambda_max = eigs_r[neigs - 1]; 92536e683305SStefano Zampini lambda_min = eigs_r[0]; 92546e683305SStefano Zampini if (pcbddc->use_coarse_estimates) { 92552701bc32SStefano Zampini if (lambda_max >= lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */ 92569566063dSJacob Faibussowitsch PetscCall(KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp, lambda_max + PETSC_SMALL, lambda_min)); 92579566063dSJacob Faibussowitsch PetscCall(KSPRichardsonSetScale(pcbddc->coarse_ksp, 2.0 / (lambda_max + lambda_min))); 9258cbcc2c2aSStefano Zampini } 9259c8587f34SStefano Zampini } 9260c8587f34SStefano Zampini } 92611ae86dd6SStefano Zampini } 9262cbcc2c2aSStefano Zampini 9263c8587f34SStefano Zampini /* check coarse problem residual error */ 92646e683305SStefano Zampini if (pcbddc->dbg_flag) { 92656e683305SStefano Zampini PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp)); 92669566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIAddTab(dbg_viewer, 2 * (pcbddc->current_level + 1))); 92679566063dSJacob Faibussowitsch PetscCall(VecAXPY(check_vec, -1.0, coarse_vec)); 92689566063dSJacob Faibussowitsch PetscCall(VecNorm(check_vec, NORM_INFINITY, &infty_error)); 92699566063dSJacob Faibussowitsch PetscCall(MatMult(coarse_mat, check_vec, coarse_vec)); 92709566063dSJacob Faibussowitsch PetscCall(VecNorm(coarse_vec, NORM_INFINITY, &abs_infty_error)); 92719566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(dbg_viewer, "Coarse problem details (use estimates %d)\n", pcbddc->use_coarse_estimates)); 9272f4f49eeaSPierre Jolivet PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)pcbddc->coarse_ksp, dbg_viewer)); 927357508eceSPierre Jolivet PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)check_pc, dbg_viewer)); 927463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(dbg_viewer, "Coarse problem exact infty_error : %1.6e\n", (double)infty_error)); 927563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(dbg_viewer, "Coarse problem residual infty_error: %1.6e\n", (double)abs_infty_error)); 927648a46eb9SPierre Jolivet if (CoarseNullSpace) PetscCall(PetscViewerASCIIPrintf(dbg_viewer, "Coarse problem is singular\n")); 92776e683305SStefano Zampini if (compute_eigs) { 92786e683305SStefano Zampini PetscReal lambda_max_s, lambda_min_s; 9279b03ebc13SStefano Zampini KSPConvergedReason reason; 92809566063dSJacob Faibussowitsch PetscCall(KSPGetType(check_ksp, &check_ksp_type)); 92819566063dSJacob Faibussowitsch PetscCall(KSPGetIterationNumber(check_ksp, &its)); 92829566063dSJacob Faibussowitsch PetscCall(KSPGetConvergedReason(check_ksp, &reason)); 92839566063dSJacob Faibussowitsch PetscCall(KSPComputeExtremeSingularValues(check_ksp, &lambda_max_s, &lambda_min_s)); 928463a3b9bcSJacob 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)); 928548a46eb9SPierre Jolivet for (i = 0; i < neigs; i++) PetscCall(PetscViewerASCIIPrintf(dbg_viewer, "%1.6e %1.6ei\n", (double)eigs_r[i], (double)eigs_c[i])); 92866e683305SStefano Zampini } 92879566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(dbg_viewer)); 92889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISubtractTab(dbg_viewer, 2 * (pcbddc->current_level + 1))); 92896e683305SStefano Zampini } 92909566063dSJacob Faibussowitsch PetscCall(VecDestroy(&check_vec)); 92919566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coarse_vec)); 92929566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&check_ksp)); 92936e683305SStefano Zampini if (compute_eigs) { 92949566063dSJacob Faibussowitsch PetscCall(PetscFree(eigs_r)); 92959566063dSJacob Faibussowitsch PetscCall(PetscFree(eigs_c)); 9296c8587f34SStefano Zampini } 92976e683305SStefano Zampini } 92986e683305SStefano Zampini } 92999566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&CoarseNullSpace)); 9300cbcc2c2aSStefano Zampini /* print additional info */ 9301cbcc2c2aSStefano Zampini if (pcbddc->dbg_flag) { 93026e683305SStefano Zampini /* waits until all processes reaches this point */ 93039566063dSJacob Faibussowitsch PetscCall(PetscBarrier((PetscObject)pc)); 930463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Coarse solver setup completed at level %" PetscInt_FMT "\n", pcbddc->current_level)); 93059566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 9306cbcc2c2aSStefano Zampini } 9307cbcc2c2aSStefano Zampini 93082b510759SStefano Zampini /* free memory */ 93099566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_mat)); 93109566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_CoarseSolver[pcbddc->current_level], pc, 0, 0, 0)); 93113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9312c8587f34SStefano Zampini } 9313674ae819SStefano Zampini 9314d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCComputePrimalNumbering(PC pc, PetscInt *coarse_size_n, PetscInt **local_primal_indices_n) 9315d71ae5a4SJacob Faibussowitsch { 9316f34684f1SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 9317f34684f1SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 9318dc456d91SStefano Zampini IS subset, subset_mult, subset_n; 9319dc456d91SStefano Zampini PetscInt local_size, coarse_size = 0; 932073be2a3aSStefano Zampini PetscInt *local_primal_indices = NULL; 9321dc456d91SStefano Zampini const PetscInt *t_local_primal_indices; 9322f34684f1SStefano Zampini 9323f34684f1SStefano Zampini PetscFunctionBegin; 9324f34684f1SStefano Zampini /* Compute global number of coarse dofs */ 932508401ef6SPierre Jolivet PetscCheck(!pcbddc->local_primal_size || pcbddc->local_primal_ref_node, PETSC_COMM_SELF, PETSC_ERR_PLIB, "BDDC ConstraintsSetUp should be called first"); 9326f4f49eeaSPierre Jolivet PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc->pmat), pcbddc->local_primal_size_cc, pcbddc->local_primal_ref_node, PETSC_COPY_VALUES, &subset_n)); 93279566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(pcis->mapping, subset_n, &subset)); 93289566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subset_n)); 9329f4f49eeaSPierre Jolivet PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc->pmat), pcbddc->local_primal_size_cc, pcbddc->local_primal_ref_mult, PETSC_COPY_VALUES, &subset_mult)); 93309566063dSJacob Faibussowitsch PetscCall(ISRenumber(subset, subset_mult, &coarse_size, &subset_n)); 93319566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subset)); 93329566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subset_mult)); 93339566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(subset_n, &local_size)); 933463a3b9bcSJacob 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); 93359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(local_size, &local_primal_indices)); 93369566063dSJacob Faibussowitsch PetscCall(ISGetIndices(subset_n, &t_local_primal_indices)); 93379566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(local_primal_indices, t_local_primal_indices, local_size)); 93389566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(subset_n, &t_local_primal_indices)); 93399566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subset_n)); 9340f34684f1SStefano Zampini 9341f34684f1SStefano Zampini if (pcbddc->dbg_flag) { 93429566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 93439566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 93449de2952eSStefano Zampini PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Size of coarse problem is %" PetscInt_FMT "\n", coarse_size)); 93459566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 9346f34684f1SStefano Zampini } 93476080607fSStefano Zampini 9348f34684f1SStefano Zampini /* get back data */ 9349f34684f1SStefano Zampini *coarse_size_n = coarse_size; 9350f34684f1SStefano Zampini *local_primal_indices_n = local_primal_indices; 93513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9352674ae819SStefano Zampini } 9353674ae819SStefano Zampini 9354d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx, Vec gwork, Vec lwork, IS globalis, IS *localis) 9355d71ae5a4SJacob Faibussowitsch { 9356e456f2a8SStefano Zampini IS localis_t; 9357a7dc3881SStefano Zampini PetscInt i, lsize, *idxs, n; 9358e456f2a8SStefano Zampini PetscScalar *vals; 9359e456f2a8SStefano Zampini 9360e456f2a8SStefano Zampini PetscFunctionBegin; 9361a7dc3881SStefano Zampini /* get indices in local ordering exploiting local to global map */ 93629566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(globalis, &lsize)); 93639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(lsize, &vals)); 9364e456f2a8SStefano Zampini for (i = 0; i < lsize; i++) vals[i] = 1.0; 93659566063dSJacob Faibussowitsch PetscCall(ISGetIndices(globalis, (const PetscInt **)&idxs)); 93669566063dSJacob Faibussowitsch PetscCall(VecSet(gwork, 0.0)); 93679566063dSJacob Faibussowitsch PetscCall(VecSet(lwork, 0.0)); 93681035eff8SStefano Zampini if (idxs) { /* multilevel guard */ 93699566063dSJacob Faibussowitsch PetscCall(VecSetOption(gwork, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE)); 93709566063dSJacob Faibussowitsch PetscCall(VecSetValues(gwork, lsize, idxs, vals, INSERT_VALUES)); 93711035eff8SStefano Zampini } 93729566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(gwork)); 93739566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(globalis, (const PetscInt **)&idxs)); 93749566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 93759566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(gwork)); 9376a7dc3881SStefano Zampini /* now compute set in local ordering */ 93779566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(g2l_ctx, gwork, lwork, INSERT_VALUES, SCATTER_FORWARD)); 93789566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(g2l_ctx, gwork, lwork, INSERT_VALUES, SCATTER_FORWARD)); 93799566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(lwork, (const PetscScalar **)&vals)); 93809566063dSJacob Faibussowitsch PetscCall(VecGetSize(lwork, &n)); 9381a7dc3881SStefano Zampini for (i = 0, lsize = 0; i < n; i++) { 9382ad540459SPierre Jolivet if (PetscRealPart(vals[i]) > 0.5) lsize++; 9383e456f2a8SStefano Zampini } 93849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(lsize, &idxs)); 9385a7dc3881SStefano Zampini for (i = 0, lsize = 0; i < n; i++) { 9386ad540459SPierre Jolivet if (PetscRealPart(vals[i]) > 0.5) idxs[lsize++] = i; 9387e456f2a8SStefano Zampini } 93889566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(lwork, (const PetscScalar **)&vals)); 93899566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)gwork), lsize, idxs, PETSC_OWN_POINTER, &localis_t)); 9390e456f2a8SStefano Zampini *localis = localis_t; 93913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9392e456f2a8SStefano Zampini } 9393906d46d4SStefano Zampini 9394d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCComputeFakeChange(PC pc, PetscBool constraints, PCBDDCGraph graph, PCBDDCSubSchurs schurs, Mat *change, IS *change_primal, IS *change_primal_mult, PetscBool *change_with_qr) 9395d71ae5a4SJacob Faibussowitsch { 93967c625d9fSStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 93977c625d9fSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 93987c625d9fSStefano Zampini PC_IS *pcisf; 93997c625d9fSStefano Zampini PC_BDDC *pcbddcf; 94007c625d9fSStefano Zampini PC pcf; 94017c625d9fSStefano Zampini 94027c625d9fSStefano Zampini PetscFunctionBegin; 94037c625d9fSStefano Zampini PetscCall(PCCreate(PetscObjectComm((PetscObject)pc), &pcf)); 94047c625d9fSStefano Zampini PetscCall(PCSetOperators(pcf, pc->mat, pc->pmat)); 94057c625d9fSStefano Zampini PetscCall(PCSetType(pcf, PCBDDC)); 94067c625d9fSStefano Zampini 94077c625d9fSStefano Zampini pcisf = (PC_IS *)pcf->data; 940832fe681dSStefano Zampini pcbddcf = (PC_BDDC *)pcf->data; 940932fe681dSStefano Zampini 94107c625d9fSStefano Zampini pcisf->is_B_local = pcis->is_B_local; 94117c625d9fSStefano Zampini pcisf->vec1_N = pcis->vec1_N; 94127c625d9fSStefano Zampini pcisf->BtoNmap = pcis->BtoNmap; 94137c625d9fSStefano Zampini pcisf->n = pcis->n; 94147c625d9fSStefano Zampini pcisf->n_B = pcis->n_B; 94157c625d9fSStefano Zampini 94167c625d9fSStefano Zampini PetscCall(PetscFree(pcbddcf->mat_graph)); 941732fe681dSStefano Zampini PetscCall(PetscFree(pcbddcf->sub_schurs)); 94187c625d9fSStefano Zampini pcbddcf->mat_graph = graph ? graph : pcbddc->mat_graph; 941932fe681dSStefano Zampini pcbddcf->sub_schurs = schurs; 942032fe681dSStefano Zampini pcbddcf->adaptive_selection = schurs ? PETSC_TRUE : PETSC_FALSE; 942132fe681dSStefano Zampini pcbddcf->adaptive_threshold[0] = pcbddc->adaptive_threshold[0]; 942232fe681dSStefano Zampini pcbddcf->adaptive_threshold[1] = pcbddc->adaptive_threshold[1]; 942332fe681dSStefano Zampini pcbddcf->adaptive_nmin = pcbddc->adaptive_nmin; 942432fe681dSStefano Zampini pcbddcf->adaptive_nmax = pcbddc->adaptive_nmax; 94257c625d9fSStefano Zampini pcbddcf->use_faces = PETSC_TRUE; 942632fe681dSStefano Zampini pcbddcf->use_change_of_basis = (PetscBool)!constraints; 942732fe681dSStefano Zampini pcbddcf->use_change_on_faces = (PetscBool)!constraints; 942832fe681dSStefano Zampini pcbddcf->use_qr_single = (PetscBool)!constraints; 94297c625d9fSStefano Zampini pcbddcf->fake_change = PETSC_TRUE; 943032fe681dSStefano Zampini pcbddcf->dbg_flag = pcbddc->dbg_flag; 943132fe681dSStefano Zampini 943232fe681dSStefano Zampini PetscCall(PCBDDCAdaptiveSelection(pcf)); 94337c625d9fSStefano Zampini PetscCall(PCBDDCConstraintsSetUp(pcf)); 94347c625d9fSStefano Zampini 94357c625d9fSStefano Zampini *change = pcbddcf->ConstraintMatrix; 94367c625d9fSStefano 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)); 94377c625d9fSStefano 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)); 94387c625d9fSStefano Zampini if (change_with_qr) *change_with_qr = pcbddcf->use_qr_single; 94397c625d9fSStefano Zampini 944032fe681dSStefano Zampini if (schurs) pcbddcf->sub_schurs = NULL; 94417c625d9fSStefano Zampini pcbddcf->ConstraintMatrix = NULL; 944232fe681dSStefano Zampini pcbddcf->mat_graph = NULL; 944332fe681dSStefano Zampini pcisf->is_B_local = NULL; 944432fe681dSStefano Zampini pcisf->vec1_N = NULL; 944532fe681dSStefano Zampini pcisf->BtoNmap = NULL; 94467c625d9fSStefano Zampini PetscCall(PCDestroy(&pcf)); 94473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 94487c625d9fSStefano Zampini } 94497c625d9fSStefano Zampini 9450d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpSubSchurs(PC pc) 9451d71ae5a4SJacob Faibussowitsch { 9452a64f4aa4SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 9453b96c3477SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 9454b96c3477SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 9455a64f4aa4SStefano Zampini Mat S_j; 9456b96c3477SStefano Zampini PetscInt *used_xadj, *used_adjncy; 9457b96c3477SStefano Zampini PetscBool free_used_adj; 9458b96c3477SStefano Zampini 9459b96c3477SStefano Zampini PetscFunctionBegin; 94609566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Schurs[pcbddc->current_level], pc, 0, 0, 0)); 9461b96c3477SStefano Zampini /* decide the adjacency to be used for determining internal problems for local schur on subsets */ 9462b96c3477SStefano Zampini free_used_adj = PETSC_FALSE; 946308122e43SStefano Zampini if (pcbddc->sub_schurs_layers == -1) { 9464b96c3477SStefano Zampini used_xadj = NULL; 9465b96c3477SStefano Zampini used_adjncy = NULL; 9466b96c3477SStefano Zampini } else { 946708122e43SStefano Zampini if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) { 946808122e43SStefano Zampini used_xadj = pcbddc->mat_graph->xadj; 946908122e43SStefano Zampini used_adjncy = pcbddc->mat_graph->adjncy; 947008122e43SStefano Zampini } else if (pcbddc->computed_rowadj) { 9471b96c3477SStefano Zampini used_xadj = pcbddc->mat_graph->xadj; 9472b96c3477SStefano Zampini used_adjncy = pcbddc->mat_graph->adjncy; 9473b96c3477SStefano Zampini } else { 94742fffb893SStefano Zampini PetscBool flg_row = PETSC_FALSE; 9475b96c3477SStefano Zampini const PetscInt *xadj, *adjncy; 9476b96c3477SStefano Zampini PetscInt nvtxs; 9477b96c3477SStefano Zampini 94789566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(pcbddc->local_mat, 0, PETSC_TRUE, PETSC_FALSE, &nvtxs, &xadj, &adjncy, &flg_row)); 94792fffb893SStefano Zampini if (flg_row) { 94809566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nvtxs + 1, &used_xadj, xadj[nvtxs], &used_adjncy)); 94819566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(used_xadj, xadj, nvtxs + 1)); 94829566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(used_adjncy, adjncy, xadj[nvtxs])); 9483b96c3477SStefano Zampini free_used_adj = PETSC_TRUE; 94842fffb893SStefano Zampini } else { 94852fffb893SStefano Zampini pcbddc->sub_schurs_layers = -1; 94862fffb893SStefano Zampini used_xadj = NULL; 94872fffb893SStefano Zampini used_adjncy = NULL; 94882fffb893SStefano Zampini } 94899566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(pcbddc->local_mat, 0, PETSC_TRUE, PETSC_FALSE, &nvtxs, &xadj, &adjncy, &flg_row)); 9490b96c3477SStefano Zampini } 9491b96c3477SStefano Zampini } 9492d5574798SStefano Zampini 9493d5574798SStefano Zampini /* setup sub_schurs data */ 94949566063dSJacob Faibussowitsch PetscCall(MatCreateSchurComplement(pcis->A_II, pcis->pA_II, pcis->A_IB, pcis->A_BI, pcis->A_BB, &S_j)); 9495df4d28bfSStefano Zampini if (!sub_schurs->schur_explicit) { 9496df4d28bfSStefano Zampini /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */ 94979566063dSJacob Faibussowitsch PetscCall(MatSchurComplementSetKSP(S_j, pcbddc->ksp_D)); 94989566063dSJacob 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)); 9499a64f4aa4SStefano Zampini } else { 950072b8c272SStefano Zampini Mat change = NULL; 95019d54b7f4SStefano Zampini Vec scaling = NULL; 9502111315fdSstefano_zampini IS change_primal = NULL, iP; 9503111315fdSstefano_zampini PetscInt benign_n; 9504111315fdSstefano_zampini PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis; 95057ebab0bbSStefano Zampini PetscBool need_change = PETSC_FALSE; 9506111315fdSstefano_zampini PetscBool discrete_harmonic = PETSC_FALSE; 9507a3df083aSStefano Zampini 95085feab87aSStefano Zampini if (!pcbddc->use_vertices && reuse_solvers) { 95095feab87aSStefano Zampini PetscInt n_vertices; 95105feab87aSStefano Zampini 95119566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->is_vertices, &n_vertices)); 95122034aafcSStefano Zampini reuse_solvers = (PetscBool)!n_vertices; 95135feab87aSStefano Zampini } 9514a3df083aSStefano Zampini if (!pcbddc->benign_change_explicit) { 9515a3df083aSStefano Zampini benign_n = pcbddc->benign_n; 9516ca92afb2SStefano Zampini } else { 9517a3df083aSStefano Zampini benign_n = 0; 9518ca92afb2SStefano Zampini } 9519b7ab4a40SStefano Zampini /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc. 9520b7ab4a40SStefano Zampini We need a global reduction to avoid possible deadlocks. 9521b7ab4a40SStefano Zampini We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */ 952272b8c272SStefano Zampini if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) { 952322db5ddcSStefano Zampini PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change); 95245440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&have_loc_change, &need_change, 1, MPI_C_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 952522db5ddcSStefano Zampini need_change = (PetscBool)(!need_change); 9526b7ab4a40SStefano Zampini } 95277c625d9fSStefano Zampini /* If the user defines additional constraints, we import them here */ 9528b7ab4a40SStefano Zampini if (need_change) { 952928b400f6SJacob Faibussowitsch PetscCheck(!pcbddc->sub_schurs_rebuild, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot compute change of basis with a different graph"); 953032fe681dSStefano Zampini PetscCall(PCBDDCComputeFakeChange(pc, PETSC_FALSE, NULL, NULL, &change, &change_primal, NULL, &sub_schurs->change_with_qr)); 953188c03ad3SStefano Zampini } 95329d54b7f4SStefano Zampini if (!pcbddc->use_deluxe_scaling) scaling = pcis->D; 9533111315fdSstefano_zampini 95349566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_iP", (PetscObject *)&iP)); 9535111315fdSstefano_zampini if (iP) { 9536d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)iP), sub_schurs->prefix, "BDDC sub_schurs options", "PC"); 95379566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-sub_schurs_discrete_harmonic", NULL, NULL, discrete_harmonic, &discrete_harmonic, NULL)); 9538d0609cedSBarry Smith PetscOptionsEnd(); 9539111315fdSstefano_zampini } 9540111315fdSstefano_zampini if (discrete_harmonic) { 9541111315fdSstefano_zampini Mat A; 95429566063dSJacob Faibussowitsch PetscCall(MatDuplicate(pcbddc->local_mat, MAT_COPY_VALUES, &A)); 95439566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumnsIS(A, iP, 1.0, NULL, NULL)); 95449566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A, "__KSPFETIDP_iP", (PetscObject)iP)); 95459371c9d4SSatish 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, 95469371c9d4SSatish Balay pcbddc->benign_zerodiag_subs, change, change_primal)); 95479566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 9548111315fdSstefano_zampini } else { 95499371c9d4SSatish 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, 95509371c9d4SSatish Balay pcbddc->benign_p0_lidx, pcbddc->benign_zerodiag_subs, change, change_primal)); 9551111315fdSstefano_zampini } 95529566063dSJacob Faibussowitsch PetscCall(MatDestroy(&change)); 95539566063dSJacob Faibussowitsch PetscCall(ISDestroy(&change_primal)); 9554ca92afb2SStefano Zampini } 95559566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_j)); 9556b96c3477SStefano Zampini 9557b96c3477SStefano Zampini /* free adjacency */ 95581baa6e33SBarry Smith if (free_used_adj) PetscCall(PetscFree2(used_xadj, used_adjncy)); 95599566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Schurs[pcbddc->current_level], pc, 0, 0, 0)); 95603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9561b96c3477SStefano Zampini } 9562b96c3477SStefano Zampini 9563d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCInitSubSchurs(PC pc) 9564d71ae5a4SJacob Faibussowitsch { 9565b96c3477SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 9566b96c3477SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 9567b96c3477SStefano Zampini PCBDDCGraph graph; 9568b96c3477SStefano Zampini 9569b96c3477SStefano Zampini PetscFunctionBegin; 9570b96c3477SStefano Zampini /* attach interface graph for determining subsets */ 957108122e43SStefano Zampini if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */ 95723301b35fSStefano Zampini IS verticesIS, verticescomm; 95733301b35fSStefano Zampini PetscInt vsize, *idxs; 9574b96c3477SStefano Zampini 95759566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &verticesIS)); 95769566063dSJacob Faibussowitsch PetscCall(ISGetSize(verticesIS, &vsize)); 95779566063dSJacob Faibussowitsch PetscCall(ISGetIndices(verticesIS, (const PetscInt **)&idxs)); 95789566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), vsize, idxs, PETSC_COPY_VALUES, &verticescomm)); 95799566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(verticesIS, (const PetscInt **)&idxs)); 95809566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &verticesIS)); 95819566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphCreate(&graph)); 95829566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphInit(graph, pcbddc->mat_graph->l2gmap, pcbddc->mat_graph->nvtxs_global, pcbddc->graphmaxcount)); 95839566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphSetUp(graph, pcbddc->mat_graph->custom_minimal_size, NULL, pcbddc->DirichletBoundariesLocal, 0, NULL, verticescomm)); 95849566063dSJacob Faibussowitsch PetscCall(ISDestroy(&verticescomm)); 95859566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphComputeConnectedComponents(graph)); 9586b96c3477SStefano Zampini } else { 9587b96c3477SStefano Zampini graph = pcbddc->mat_graph; 9588b96c3477SStefano Zampini } 9589e4d548c7SStefano Zampini /* print some info */ 95905c643e28SStefano Zampini if (pcbddc->dbg_flag && !pcbddc->sub_schurs_rebuild) { 9591e4d548c7SStefano Zampini IS vertices; 9592e4d548c7SStefano Zampini PetscInt nv, nedges, nfaces; 95939566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphASCIIView(graph, pcbddc->dbg_flag, pcbddc->dbg_viewer)); 95949566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(graph, &nfaces, NULL, &nedges, NULL, &vertices)); 95959566063dSJacob Faibussowitsch PetscCall(ISGetSize(vertices, &nv)); 95969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 95979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "--------------------------------------------------------------\n")); 959863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate vertices (%d)\n", PetscGlobalRank, nv, pcbddc->use_vertices)); 959963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate edges (%d)\n", PetscGlobalRank, nedges, pcbddc->use_edges)); 960063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate faces (%d)\n", PetscGlobalRank, nfaces, pcbddc->use_faces)); 96019566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 96029566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer)); 96039566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(graph, &nfaces, NULL, &nedges, NULL, &vertices)); 9604e4d548c7SStefano Zampini } 9605b96c3477SStefano Zampini 9606b96c3477SStefano Zampini /* sub_schurs init */ 960748a46eb9SPierre Jolivet if (!pcbddc->sub_schurs) PetscCall(PCBDDCSubSchursCreate(&pcbddc->sub_schurs)); 960832fe681dSStefano 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)); 9609a64f4aa4SStefano Zampini 9610b96c3477SStefano Zampini /* free graph struct */ 961148a46eb9SPierre Jolivet if (pcbddc->sub_schurs_rebuild) PetscCall(PCBDDCGraphDestroy(&graph)); 96123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9613b96c3477SStefano Zampini } 9614fa34dd3eSStefano Zampini 96159de2952eSStefano Zampini static PetscErrorCode PCBDDCViewGlobalIS(PC pc, IS is, PetscViewer viewer) 96169de2952eSStefano Zampini { 96179de2952eSStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 96189de2952eSStefano Zampini PetscInt n = pc->pmat->rmap->n, ln, ni, st; 96199de2952eSStefano Zampini const PetscInt *idxs; 96209de2952eSStefano Zampini IS gis; 96219de2952eSStefano Zampini 96229de2952eSStefano Zampini PetscFunctionBegin; 96239de2952eSStefano Zampini if (!is) PetscFunctionReturn(PETSC_SUCCESS); 96249de2952eSStefano Zampini PetscCall(MatGetOwnershipRange(pc->pmat, &st, NULL)); 96259de2952eSStefano Zampini PetscCall(MatGetLocalSize(matis->A, NULL, &ln)); 96269de2952eSStefano Zampini PetscCall(PetscArrayzero(matis->sf_leafdata, ln)); 96279de2952eSStefano Zampini PetscCall(PetscArrayzero(matis->sf_rootdata, n)); 96289de2952eSStefano Zampini PetscCall(ISGetLocalSize(is, &ni)); 96299de2952eSStefano Zampini PetscCall(ISGetIndices(is, &idxs)); 96309de2952eSStefano Zampini for (PetscInt i = 0; i < ni; i++) { 96319de2952eSStefano Zampini if (idxs[i] < 0 || idxs[i] >= ln) continue; 96329de2952eSStefano Zampini matis->sf_leafdata[idxs[i]] = 1; 96339de2952eSStefano Zampini } 96349de2952eSStefano Zampini PetscCall(ISRestoreIndices(is, &idxs)); 96359de2952eSStefano Zampini PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, matis->sf_leafdata, matis->sf_rootdata, MPI_SUM)); 96369de2952eSStefano Zampini PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, matis->sf_leafdata, matis->sf_rootdata, MPI_SUM)); 96379de2952eSStefano Zampini ln = 0; 96389de2952eSStefano Zampini for (PetscInt i = 0; i < n; i++) { 96399de2952eSStefano Zampini if (matis->sf_rootdata[i]) matis->sf_rootdata[ln++] = i + st; 96409de2952eSStefano Zampini } 96419de2952eSStefano Zampini PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), ln, matis->sf_rootdata, PETSC_USE_POINTER, &gis)); 96429de2952eSStefano Zampini PetscCall(ISView(gis, viewer)); 96439de2952eSStefano Zampini PetscCall(ISDestroy(&gis)); 96449de2952eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 96459de2952eSStefano Zampini } 96469de2952eSStefano Zampini 96479de2952eSStefano Zampini PetscErrorCode PCBDDCLoadOrViewCustomization(PC pc, PetscBool load, const char *outfile) 96489de2952eSStefano Zampini { 96499de2952eSStefano Zampini PetscInt header[11]; 96509de2952eSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 96519de2952eSStefano Zampini PetscViewer viewer; 96529de2952eSStefano Zampini MPI_Comm comm = PetscObjectComm((PetscObject)pc); 96539de2952eSStefano Zampini 96549de2952eSStefano Zampini PetscFunctionBegin; 96559de2952eSStefano Zampini PetscCall(PetscViewerBinaryOpen(comm, outfile ? outfile : "bddc_dump.dat", load ? FILE_MODE_READ : FILE_MODE_WRITE, &viewer)); 96569de2952eSStefano Zampini if (load) { 96579de2952eSStefano Zampini IS is; 96589de2952eSStefano Zampini Mat A; 96599de2952eSStefano Zampini 96609de2952eSStefano Zampini PetscCall(PetscViewerBinaryRead(viewer, header, PETSC_STATIC_ARRAY_LENGTH(header), NULL, PETSC_INT)); 96619de2952eSStefano Zampini PetscCheck(header[0] == 0 || header[0] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 96629de2952eSStefano Zampini PetscCheck(header[1] == 0 || header[1] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 96639de2952eSStefano Zampini PetscCheck(header[2] >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 96649de2952eSStefano Zampini PetscCheck(header[3] == 0 || header[3] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 96659de2952eSStefano Zampini PetscCheck(header[4] == 0 || header[4] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 96669de2952eSStefano Zampini PetscCheck(header[5] >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 96679de2952eSStefano Zampini PetscCheck(header[7] == 0 || header[7] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 96689de2952eSStefano Zampini PetscCheck(header[8] == 0 || header[8] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 96699de2952eSStefano Zampini PetscCheck(header[9] == 0 || header[9] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 96709de2952eSStefano Zampini PetscCheck(header[10] == 0 || header[10] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a BDDC dump next in file"); 96719de2952eSStefano Zampini if (header[0]) { 96729de2952eSStefano Zampini PetscCall(ISCreate(comm, &is)); 96739de2952eSStefano Zampini PetscCall(ISLoad(is, viewer)); 96749de2952eSStefano Zampini PetscCall(PCBDDCSetDirichletBoundaries(pc, is)); 96759de2952eSStefano Zampini PetscCall(ISDestroy(&is)); 96769de2952eSStefano Zampini } 96779de2952eSStefano Zampini if (header[1]) { 96789de2952eSStefano Zampini PetscCall(ISCreate(comm, &is)); 96799de2952eSStefano Zampini PetscCall(ISLoad(is, viewer)); 96809de2952eSStefano Zampini PetscCall(PCBDDCSetNeumannBoundaries(pc, is)); 96819de2952eSStefano Zampini PetscCall(ISDestroy(&is)); 96829de2952eSStefano Zampini } 96839de2952eSStefano Zampini if (header[2]) { 96849de2952eSStefano Zampini IS *isarray; 96859de2952eSStefano Zampini 96869de2952eSStefano Zampini PetscCall(PetscMalloc1(header[2], &isarray)); 96879de2952eSStefano Zampini for (PetscInt i = 0; i < header[2]; i++) { 96889de2952eSStefano Zampini PetscCall(ISCreate(comm, &isarray[i])); 96899de2952eSStefano Zampini PetscCall(ISLoad(isarray[i], viewer)); 96909de2952eSStefano Zampini } 96919de2952eSStefano Zampini PetscCall(PCBDDCSetDofsSplitting(pc, header[2], isarray)); 96929de2952eSStefano Zampini for (PetscInt i = 0; i < header[2]; i++) PetscCall(ISDestroy(&isarray[i])); 96939de2952eSStefano Zampini PetscCall(PetscFree(isarray)); 96949de2952eSStefano Zampini } 96959de2952eSStefano Zampini if (header[3]) { 96969de2952eSStefano Zampini PetscCall(ISCreate(comm, &is)); 96979de2952eSStefano Zampini PetscCall(ISLoad(is, viewer)); 96989de2952eSStefano Zampini PetscCall(PCBDDCSetPrimalVerticesIS(pc, is)); 96999de2952eSStefano Zampini PetscCall(ISDestroy(&is)); 97009de2952eSStefano Zampini } 97019de2952eSStefano Zampini if (header[4]) { 97029de2952eSStefano Zampini PetscCall(MatCreate(comm, &A)); 97039de2952eSStefano Zampini PetscCall(MatSetType(A, MATAIJ)); 97049de2952eSStefano Zampini PetscCall(MatLoad(A, viewer)); 97059de2952eSStefano Zampini PetscCall(PCBDDCSetDiscreteGradient(pc, A, header[5], header[6], (PetscBool)header[7], (PetscBool)header[8])); 97069de2952eSStefano Zampini PetscCall(MatDestroy(&A)); 97079de2952eSStefano Zampini } 97089de2952eSStefano Zampini if (header[9]) { 97099de2952eSStefano Zampini PetscCall(MatCreate(comm, &A)); 97109de2952eSStefano Zampini PetscCall(MatSetType(A, MATIS)); 97119de2952eSStefano Zampini PetscCall(MatLoad(A, viewer)); 97129de2952eSStefano Zampini PetscCall(PCBDDCSetDivergenceMat(pc, A, (PetscBool)header[10], NULL)); 97139de2952eSStefano Zampini PetscCall(MatDestroy(&A)); 97149de2952eSStefano Zampini } 97159de2952eSStefano Zampini } else { 97169de2952eSStefano Zampini header[0] = (PetscInt)!!pcbddc->DirichletBoundariesLocal; 97179de2952eSStefano Zampini header[1] = (PetscInt)!!pcbddc->NeumannBoundariesLocal; 97189de2952eSStefano Zampini header[2] = pcbddc->n_ISForDofsLocal; 97199de2952eSStefano Zampini header[3] = (PetscInt)!!pcbddc->user_primal_vertices_local; 97209de2952eSStefano Zampini header[4] = (PetscInt)!!pcbddc->discretegradient; 97219de2952eSStefano Zampini header[5] = pcbddc->nedorder; 97229de2952eSStefano Zampini header[6] = pcbddc->nedfield; 97239de2952eSStefano Zampini header[7] = (PetscInt)pcbddc->nedglobal; 97249de2952eSStefano Zampini header[8] = (PetscInt)pcbddc->conforming; 97259de2952eSStefano Zampini header[9] = (PetscInt)!!pcbddc->divudotp; 97269de2952eSStefano Zampini header[10] = (PetscInt)pcbddc->divudotp_trans; 97279de2952eSStefano Zampini if (header[4]) header[3] = 0; 97289de2952eSStefano Zampini 97299de2952eSStefano Zampini PetscCall(PetscViewerBinaryWrite(viewer, header, PETSC_STATIC_ARRAY_LENGTH(header), PETSC_INT)); 97309de2952eSStefano Zampini PetscCall(PCBDDCViewGlobalIS(pc, pcbddc->DirichletBoundariesLocal, viewer)); 97319de2952eSStefano Zampini PetscCall(PCBDDCViewGlobalIS(pc, pcbddc->NeumannBoundariesLocal, viewer)); 97329de2952eSStefano Zampini for (PetscInt i = 0; i < header[2]; i++) PetscCall(PCBDDCViewGlobalIS(pc, pcbddc->ISForDofsLocal[i], viewer)); 97339de2952eSStefano Zampini if (header[3]) PetscCall(PCBDDCViewGlobalIS(pc, pcbddc->user_primal_vertices_local, viewer)); 97349de2952eSStefano Zampini if (header[4]) PetscCall(MatView(pcbddc->discretegradient, viewer)); 97359de2952eSStefano Zampini if (header[9]) PetscCall(MatView(pcbddc->divudotp, viewer)); 97369de2952eSStefano Zampini } 97379de2952eSStefano Zampini PetscCall(PetscViewerDestroy(&viewer)); 97389de2952eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 97399de2952eSStefano Zampini } 97409de2952eSStefano Zampini 97411e0482f5SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h> 9742ba38deedSJacob Faibussowitsch static PetscErrorCode MatMPIAIJRestrict(Mat A, MPI_Comm ccomm, Mat *B) 9743d71ae5a4SJacob Faibussowitsch { 97441e0482f5SStefano Zampini Mat At; 97451e0482f5SStefano Zampini IS rows; 97461e0482f5SStefano Zampini PetscInt rst, ren; 97471e0482f5SStefano Zampini PetscLayout rmap; 97481e0482f5SStefano Zampini 97491e0482f5SStefano Zampini PetscFunctionBegin; 97501e0482f5SStefano Zampini rst = ren = 0; 97511e0482f5SStefano Zampini if (ccomm != MPI_COMM_NULL) { 97529566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(ccomm, &rmap)); 97539566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetSize(rmap, A->rmap->N)); 97549566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(rmap, 1)); 97559566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rmap)); 97569566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rmap, &rst, &ren)); 97571e0482f5SStefano Zampini } 97589566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), ren - rst, rst, 1, &rows)); 97599566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, rows, NULL, MAT_INITIAL_MATRIX, &At)); 97609566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rows)); 97611e0482f5SStefano Zampini 97621e0482f5SStefano Zampini if (ccomm != MPI_COMM_NULL) { 97631e0482f5SStefano Zampini Mat_MPIAIJ *a, *b; 97641e0482f5SStefano Zampini IS from, to; 97651e0482f5SStefano Zampini Vec gvec; 97661e0482f5SStefano Zampini PetscInt lsize; 97671e0482f5SStefano Zampini 97689566063dSJacob Faibussowitsch PetscCall(MatCreate(ccomm, B)); 97699566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B, ren - rst, PETSC_DECIDE, PETSC_DECIDE, At->cmap->N)); 97709566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, MATAIJ)); 977157508eceSPierre Jolivet PetscCall(PetscLayoutDestroy(&(*B)->rmap)); 97729566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp((*B)->cmap)); 97731e0482f5SStefano Zampini a = (Mat_MPIAIJ *)At->data; 97741e0482f5SStefano Zampini b = (Mat_MPIAIJ *)(*B)->data; 97759566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(ccomm, &b->size)); 97769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(ccomm, &b->rank)); 97779566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)a->A)); 97789566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)a->B)); 97791e0482f5SStefano Zampini b->A = a->A; 97801e0482f5SStefano Zampini b->B = a->B; 97811e0482f5SStefano Zampini 97821e0482f5SStefano Zampini b->donotstash = a->donotstash; 97831e0482f5SStefano Zampini b->roworiented = a->roworiented; 97840a545947SLisandro Dalcin b->rowindices = NULL; 97850a545947SLisandro Dalcin b->rowvalues = NULL; 97861e0482f5SStefano Zampini b->getrowactive = PETSC_FALSE; 97871e0482f5SStefano Zampini 97881e0482f5SStefano Zampini (*B)->rmap = rmap; 97891e0482f5SStefano Zampini (*B)->factortype = A->factortype; 97901e0482f5SStefano Zampini (*B)->assembled = PETSC_TRUE; 97911e0482f5SStefano Zampini (*B)->insertmode = NOT_SET_VALUES; 97921e0482f5SStefano Zampini (*B)->preallocated = PETSC_TRUE; 97931e0482f5SStefano Zampini 97941e0482f5SStefano Zampini if (a->colmap) { 97951e0482f5SStefano Zampini #if defined(PETSC_USE_CTABLE) 9796eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIDuplicate(a->colmap, &b->colmap)); 97971e0482f5SStefano Zampini #else 97989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(At->cmap->N, &b->colmap)); 97999566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(b->colmap, a->colmap, At->cmap->N)); 98001e0482f5SStefano Zampini #endif 98010a545947SLisandro Dalcin } else b->colmap = NULL; 98021e0482f5SStefano Zampini if (a->garray) { 98031e0482f5SStefano Zampini PetscInt len; 98041e0482f5SStefano Zampini len = a->B->cmap->n; 98059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(len + 1, &b->garray)); 98069566063dSJacob Faibussowitsch if (len) PetscCall(PetscArraycpy(b->garray, a->garray, len)); 98070a545947SLisandro Dalcin } else b->garray = NULL; 98081e0482f5SStefano Zampini 98099566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)a->lvec)); 98101e0482f5SStefano Zampini b->lvec = a->lvec; 98111e0482f5SStefano Zampini 98121e0482f5SStefano Zampini /* cannot use VecScatterCopy */ 98139566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(b->lvec, &lsize)); 98149566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(ccomm, lsize, b->garray, PETSC_USE_POINTER, &from)); 98159566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, lsize, 0, 1, &to)); 98169566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(*B, &gvec, NULL)); 98179566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(gvec, from, b->lvec, to, &b->Mvctx)); 98189566063dSJacob Faibussowitsch PetscCall(ISDestroy(&from)); 98199566063dSJacob Faibussowitsch PetscCall(ISDestroy(&to)); 98209566063dSJacob Faibussowitsch PetscCall(VecDestroy(&gvec)); 98211e0482f5SStefano Zampini } 98229566063dSJacob Faibussowitsch PetscCall(MatDestroy(&At)); 98233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 98241e0482f5SStefano Zampini } 98259de2952eSStefano Zampini 98269de2952eSStefano Zampini /* same as MatCreateSubMatrix(A, rows, NULL,...) but allows repeated rows */ 98279de2952eSStefano Zampini static PetscErrorCode MatAIJExtractRows(Mat A, IS rows, Mat *sA) 98289de2952eSStefano Zampini { 98299de2952eSStefano Zampini PetscBool isaij; 98309de2952eSStefano Zampini MPI_Comm comm; 98319de2952eSStefano Zampini 98329de2952eSStefano Zampini PetscFunctionBegin; 98339de2952eSStefano Zampini PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 98349de2952eSStefano Zampini PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)A, &isaij, MATSEQAIJ, MATMPIAIJ, "")); 98359de2952eSStefano Zampini PetscCheck(isaij, comm, PETSC_ERR_SUP, "Not implemented"); 98369de2952eSStefano Zampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isaij)); 98379de2952eSStefano Zampini if (isaij) { /* SeqAIJ supports repeated rows */ 98389de2952eSStefano Zampini PetscCall(MatCreateSubMatrix(A, rows, NULL, MAT_INITIAL_MATRIX, sA)); 98399de2952eSStefano Zampini } else { 98409de2952eSStefano Zampini Mat A_loc; 98419de2952eSStefano Zampini Mat_SeqAIJ *da; 98429de2952eSStefano Zampini PetscSF sf; 98439de2952eSStefano Zampini PetscInt ni, *di, *dj, m = A->rmap->n, c, *ldata, *rdata; 98449de2952eSStefano Zampini PetscScalar *daa; 98459de2952eSStefano Zampini const PetscInt *idxs; 98469de2952eSStefano Zampini const PetscSFNode *iremotes; 98479de2952eSStefano Zampini PetscSFNode *remotes; 98489de2952eSStefano Zampini 98499de2952eSStefano Zampini /* SF for incoming rows */ 98509de2952eSStefano Zampini PetscCall(PetscSFCreate(comm, &sf)); 98519de2952eSStefano Zampini PetscCall(ISGetLocalSize(rows, &ni)); 98529de2952eSStefano Zampini PetscCall(ISGetIndices(rows, &idxs)); 98539de2952eSStefano Zampini PetscCall(PetscSFSetGraphLayout(sf, A->rmap, ni, NULL, PETSC_USE_POINTER, idxs)); 98549de2952eSStefano Zampini PetscCall(ISRestoreIndices(rows, &idxs)); 98559de2952eSStefano Zampini 98569de2952eSStefano Zampini PetscCall(MatMPIAIJGetLocalMat(A, MAT_INITIAL_MATRIX, &A_loc)); 98579de2952eSStefano Zampini da = (Mat_SeqAIJ *)A_loc->data; 98589de2952eSStefano Zampini PetscCall(PetscMalloc2(2 * ni, &ldata, 2 * m, &rdata)); 98599de2952eSStefano Zampini for (PetscInt i = 0; i < m; i++) { 98609de2952eSStefano Zampini rdata[2 * i + 0] = da->i[i + 1] - da->i[i]; 98619de2952eSStefano Zampini rdata[2 * i + 1] = da->i[i]; 98629de2952eSStefano Zampini } 98639de2952eSStefano Zampini PetscCall(PetscSFBcastBegin(sf, MPIU_2INT, rdata, ldata, MPI_REPLACE)); 98649de2952eSStefano Zampini PetscCall(PetscSFBcastEnd(sf, MPIU_2INT, rdata, ldata, MPI_REPLACE)); 98659de2952eSStefano Zampini PetscCall(PetscMalloc1(ni + 1, &di)); 98669de2952eSStefano Zampini di[0] = 0; 98679de2952eSStefano Zampini for (PetscInt i = 0; i < ni; i++) di[i + 1] = di[i] + ldata[2 * i + 0]; 98689de2952eSStefano Zampini PetscCall(PetscMalloc1(di[ni], &dj)); 98699de2952eSStefano Zampini PetscCall(PetscMalloc1(di[ni], &daa)); 98709de2952eSStefano Zampini PetscCall(PetscMalloc1(di[ni], &remotes)); 98719de2952eSStefano Zampini 98729de2952eSStefano Zampini PetscCall(PetscSFGetGraph(sf, NULL, NULL, NULL, &iremotes)); 98739de2952eSStefano Zampini 98749de2952eSStefano Zampini /* SF graph for nonzeros */ 98759de2952eSStefano Zampini c = 0; 98769de2952eSStefano Zampini for (PetscInt i = 0; i < ni; i++) { 9877835f2295SStefano Zampini const PetscInt rank = iremotes[i].rank; 98789de2952eSStefano Zampini const PetscInt rsize = ldata[2 * i]; 98799de2952eSStefano Zampini for (PetscInt j = 0; j < rsize; j++) { 98809de2952eSStefano Zampini remotes[c].rank = rank; 98819de2952eSStefano Zampini remotes[c].index = ldata[2 * i + 1] + j; 98829de2952eSStefano Zampini c++; 98839de2952eSStefano Zampini } 98849de2952eSStefano Zampini } 98859de2952eSStefano Zampini PetscCheck(c == di[ni], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of local nonzeros %" PetscInt_FMT " != %" PetscInt_FMT, c, di[ni]); 98869de2952eSStefano Zampini PetscCall(PetscSFSetGraph(sf, da->i[m], di[ni], NULL, PETSC_USE_POINTER, remotes, PETSC_USE_POINTER)); 98879de2952eSStefano Zampini PetscCall(PetscSFBcastBegin(sf, MPIU_INT, da->j, dj, MPI_REPLACE)); 98889de2952eSStefano Zampini PetscCall(PetscSFBcastEnd(sf, MPIU_INT, da->j, dj, MPI_REPLACE)); 98899de2952eSStefano Zampini PetscCall(PetscSFBcastBegin(sf, MPIU_SCALAR, da->a, daa, MPI_REPLACE)); 98909de2952eSStefano Zampini PetscCall(PetscSFBcastEnd(sf, MPIU_SCALAR, da->a, daa, MPI_REPLACE)); 98919de2952eSStefano Zampini 98929de2952eSStefano Zampini PetscCall(MatCreateMPIAIJWithArrays(comm, ni, A->cmap->n, PETSC_DECIDE, A->cmap->N, di, dj, daa, sA)); 98939de2952eSStefano Zampini PetscCall(MatDestroy(&A_loc)); 98949de2952eSStefano Zampini PetscCall(PetscSFDestroy(&sf)); 98959de2952eSStefano Zampini PetscCall(PetscFree(di)); 98969de2952eSStefano Zampini PetscCall(PetscFree(dj)); 98979de2952eSStefano Zampini PetscCall(PetscFree(daa)); 98989de2952eSStefano Zampini PetscCall(PetscFree(remotes)); 98999de2952eSStefano Zampini PetscCall(PetscFree2(ldata, rdata)); 99009de2952eSStefano Zampini } 99019de2952eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 99029de2952eSStefano Zampini } 9903