11cf9b237SStefano Zampini #include <../src/mat/impls/aij/seq/aij.h> 25e5bbd0aSStefano Zampini #include <petsc/private/pcbddcimpl.h> 35e5bbd0aSStefano Zampini #include <petsc/private/pcbddcprivateimpl.h> 4837cedc9SStefano Zampini #include <../src/mat/impls/dense/seq/dense.h> 5c80a6c00SStefano Zampini #include <petscdmplex.h> 6674ae819SStefano Zampini #include <petscblaslapack.h> 7daf8a457SStefano Zampini #include <petsc/private/sfimpl.h> 8c80a6c00SStefano Zampini #include <petsc/private/dmpleximpl.h> 97620a527SStefano Zampini #include <petscdmda.h> 10674ae819SStefano Zampini 111e0482f5SStefano Zampini static PetscErrorCode MatMPIAIJRestrict(Mat, MPI_Comm, Mat *); 121e0482f5SStefano Zampini 13f498cd09SStefano Zampini /* if range is true, it returns B s.t. span{B} = range(A) 14f498cd09SStefano Zampini if range is false, it returns B s.t. range(B) _|_ range(A) */ 15ba38deedSJacob Faibussowitsch static PetscErrorCode MatDenseOrthogonalRangeOrComplement(Mat A, PetscBool range, PetscInt lw, PetscScalar *work, PetscReal *rwork, Mat *B) 16d71ae5a4SJacob Faibussowitsch { 17a13144ffSStefano Zampini PetscScalar *uwork, *data, *U, ds = 0.; 18a13144ffSStefano Zampini PetscReal *sing; 19a13144ffSStefano Zampini PetscBLASInt bM, bN, lwork, lierr, di = 1; 20a13144ffSStefano Zampini PetscInt ulw, i, nr, nc, n; 21abee2b68SSebastian Grimberg #if defined(PETSC_USE_COMPLEX) 22abee2b68SSebastian Grimberg PetscReal *rwork2; 23abee2b68SSebastian Grimberg #endif 24a13144ffSStefano Zampini 25a13144ffSStefano Zampini PetscFunctionBegin; 269566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &nr, &nc)); 273ba16761SJacob Faibussowitsch if (!nr || !nc) PetscFunctionReturn(PETSC_SUCCESS); 28a13144ffSStefano Zampini 29a13144ffSStefano Zampini /* workspace */ 30a13144ffSStefano Zampini if (!work) { 31a13144ffSStefano Zampini ulw = PetscMax(PetscMax(1, 5 * PetscMin(nr, nc)), 3 * PetscMin(nr, nc) + PetscMax(nr, nc)); 329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ulw, &uwork)); 33a13144ffSStefano Zampini } else { 34a13144ffSStefano Zampini ulw = lw; 35a13144ffSStefano Zampini uwork = work; 36a13144ffSStefano Zampini } 37a13144ffSStefano Zampini n = PetscMin(nr, nc); 38a13144ffSStefano Zampini if (!rwork) { 399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &sing)); 40a13144ffSStefano Zampini } else { 41a13144ffSStefano Zampini sing = rwork; 42a13144ffSStefano Zampini } 43a13144ffSStefano Zampini 44a13144ffSStefano Zampini /* SVD */ 459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nr * nr, &U)); 469566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(nr, &bM)); 479566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(nc, &bN)); 489566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(ulw, &lwork)); 499566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(A, &data)); 509566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 51abee2b68SSebastian Grimberg #if !defined(PETSC_USE_COMPLEX) 52792fecdfSBarry Smith PetscCallBLAS("LAPACKgesvd", LAPACKgesvd_("A", "N", &bM, &bN, data, &bM, sing, U, &bM, &ds, &di, uwork, &lwork, &lierr)); 53abee2b68SSebastian Grimberg #else 549566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(5 * n, &rwork2)); 55792fecdfSBarry Smith PetscCallBLAS("LAPACKgesvd", LAPACKgesvd_("A", "N", &bM, &bN, data, &bM, sing, U, &bM, &ds, &di, uwork, &lwork, rwork2, &lierr)); 569566063dSJacob Faibussowitsch PetscCall(PetscFree(rwork2)); 57abee2b68SSebastian Grimberg #endif 589566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 5928b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in GESVD Lapack routine %d", (int)lierr); 609566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(A, &data)); 619371c9d4SSatish Balay for (i = 0; i < n; i++) 629371c9d4SSatish Balay if (sing[i] < PETSC_SMALL) break; 6348a46eb9SPierre Jolivet if (!rwork) PetscCall(PetscFree(sing)); 6448a46eb9SPierre Jolivet if (!work) PetscCall(PetscFree(uwork)); 65a13144ffSStefano Zampini /* create B */ 66f498cd09SStefano Zampini if (!range) { 679566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, nr, nr - i, NULL, B)); 689566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(*B, &data)); 699566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data, U + nr * i, (nr - i) * nr)); 70f498cd09SStefano Zampini } else { 719566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, nr, i, NULL, B)); 729566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(*B, &data)); 739566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data, U, i * nr)); 74f498cd09SStefano Zampini } 759566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(*B, &data)); 769566063dSJacob Faibussowitsch PetscCall(PetscFree(U)); 773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 78a13144ffSStefano Zampini } 79a13144ffSStefano Zampini 801e0482f5SStefano Zampini /* TODO REMOVE */ 811e0482f5SStefano Zampini #if defined(PRINT_GDET) 821e0482f5SStefano Zampini static int inc = 0; 831e0482f5SStefano Zampini static int lev = 0; 841e0482f5SStefano Zampini #endif 851e0482f5SStefano Zampini 86ba38deedSJacob 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) 87d71ae5a4SJacob Faibussowitsch { 88a13144ffSStefano Zampini Mat GE, GEd; 89a13144ffSStefano Zampini PetscInt rsize, csize, esize; 90a13144ffSStefano Zampini PetscScalar *ptr; 91a13144ffSStefano Zampini 92a13144ffSStefano Zampini PetscFunctionBegin; 939566063dSJacob Faibussowitsch PetscCall(ISGetSize(edge, &esize)); 943ba16761SJacob Faibussowitsch if (!esize) PetscFunctionReturn(PETSC_SUCCESS); 959566063dSJacob Faibussowitsch PetscCall(ISGetSize(extrow, &rsize)); 969566063dSJacob Faibussowitsch PetscCall(ISGetSize(extcol, &csize)); 97a13144ffSStefano Zampini 98a13144ffSStefano Zampini /* gradients */ 99a13144ffSStefano Zampini ptr = work + 5 * esize; 1009566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lG, extrow, extcol, MAT_INITIAL_MATRIX, &GE)); 1019566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, rsize, csize, ptr, Gins)); 1029566063dSJacob Faibussowitsch PetscCall(MatConvert(GE, MATSEQDENSE, MAT_REUSE_MATRIX, Gins)); 1039566063dSJacob Faibussowitsch PetscCall(MatDestroy(&GE)); 104a13144ffSStefano Zampini 105a13144ffSStefano Zampini /* constants */ 106a13144ffSStefano Zampini ptr += rsize * csize; 1079566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, esize, csize, ptr, &GEd)); 1089566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lG, edge, extcol, MAT_INITIAL_MATRIX, &GE)); 1099566063dSJacob Faibussowitsch PetscCall(MatConvert(GE, MATSEQDENSE, MAT_REUSE_MATRIX, &GEd)); 1109566063dSJacob Faibussowitsch PetscCall(MatDestroy(&GE)); 1119566063dSJacob Faibussowitsch PetscCall(MatDenseOrthogonalRangeOrComplement(GEd, PETSC_FALSE, 5 * esize, work, rwork, GKins)); 1129566063dSJacob Faibussowitsch PetscCall(MatDestroy(&GEd)); 1131e0482f5SStefano Zampini 1141e0482f5SStefano Zampini if (corners) { 1151e0482f5SStefano Zampini Mat GEc; 1161683a169SBarry Smith const PetscScalar *vals; 1171683a169SBarry Smith PetscScalar v; 1181e0482f5SStefano Zampini 1199566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lG, edge, corners, MAT_INITIAL_MATRIX, &GEc)); 1209566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(GEc, *GKins, MAT_INITIAL_MATRIX, 1.0, &GEd)); 1219566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(GEd, &vals)); 122a8f51744SPierre Jolivet /* v = PetscAbsScalar(vals[0]); */ 123637e8532SStefano Zampini v = 1.; 1241e0482f5SStefano Zampini cvals[0] = vals[0] / v; 1251e0482f5SStefano Zampini cvals[1] = vals[1] / v; 1269566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(GEd, &vals)); 1279566063dSJacob Faibussowitsch PetscCall(MatScale(*GKins, 1. / v)); 1281e0482f5SStefano Zampini #if defined(PRINT_GDET) 1291e0482f5SStefano Zampini { 1301e0482f5SStefano Zampini PetscViewer viewer; 1311e0482f5SStefano Zampini char filename[256]; 132a364092eSJacob Faibussowitsch PetscCall(PetscSNPrintf(filename, PETSC_STATIC_ARRAY_LENGTH(filename), "Gdet_l%d_r%d_cc%d.m", lev, PetscGlobalRank, inc++)); 1339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF, filename, &viewer)); 1349566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_MATLAB)); 1359566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)GEc, "GEc")); 1369566063dSJacob Faibussowitsch PetscCall(MatView(GEc, viewer)); 137*f4f49eeaSPierre Jolivet PetscCall(PetscObjectSetName((PetscObject)*GKins, "GK")); 1389566063dSJacob Faibussowitsch PetscCall(MatView(*GKins, viewer)); 1399566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)GEd, "Gproj")); 1409566063dSJacob Faibussowitsch PetscCall(MatView(GEd, viewer)); 1419566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 1421e0482f5SStefano Zampini } 1431e0482f5SStefano Zampini #endif 1449566063dSJacob Faibussowitsch PetscCall(MatDestroy(&GEd)); 1459566063dSJacob Faibussowitsch PetscCall(MatDestroy(&GEc)); 1461e0482f5SStefano Zampini } 1473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 148a13144ffSStefano Zampini } 149a13144ffSStefano Zampini 150d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCNedelecSupport(PC pc) 151d71ae5a4SJacob Faibussowitsch { 152a13144ffSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 153a13144ffSStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 1540569b399SStefano Zampini Mat G, T, conn, lG, lGt, lGis, lGall, lGe, lGinit; 155eee23b56SStefano Zampini Vec tvec; 156a13144ffSStefano Zampini PetscSF sfv; 1571e0482f5SStefano Zampini ISLocalToGlobalMapping el2g, vl2g, fl2g, al2g; 158a13144ffSStefano Zampini MPI_Comm comm; 159c2151214SStefano Zampini IS lned, primals, allprimals, nedfieldlocal; 160c2151214SStefano Zampini IS *eedges, *extrows, *extcols, *alleedges; 1617d871cd7SStefano Zampini PetscBT btv, bte, btvc, btb, btbd, btvcand, btvi, btee, bter; 162a13144ffSStefano Zampini PetscScalar *vals, *work; 163a13144ffSStefano Zampini PetscReal *rwork; 164a13144ffSStefano Zampini const PetscInt *idxs, *ii, *jj, *iit, *jjt; 1651e0482f5SStefano Zampini PetscInt ne, nv, Lv, order, n, field; 166a13144ffSStefano Zampini PetscInt n_neigh, *neigh, *n_shared, **shared; 167eee23b56SStefano Zampini PetscInt i, j, extmem, cum, maxsize, nee; 168b03ebc13SStefano Zampini PetscInt *extrow, *extrowcum, *marks, *vmarks, *gidxs; 169a13144ffSStefano Zampini PetscInt *sfvleaves, *sfvroots; 170b03ebc13SStefano Zampini PetscInt *corners, *cedges; 171637e8532SStefano Zampini PetscInt *ecount, **eneighs, *vcount, **vneighs; 172b03ebc13SStefano Zampini PetscInt *emarks; 173213b8bfaSStefano Zampini PetscBool print, eerr, done, lrc[2], conforming, global, singular, setprimal; 174a13144ffSStefano Zampini 175a13144ffSStefano Zampini PetscFunctionBegin; 176213b8bfaSStefano Zampini /* If the discrete gradient is defined for a subset of dofs and global is true, 177213b8bfaSStefano Zampini it assumes G is given in global ordering for all the dofs. 178213b8bfaSStefano Zampini Otherwise, the ordering is global for the Nedelec field */ 179213b8bfaSStefano Zampini order = pcbddc->nedorder; 180213b8bfaSStefano Zampini conforming = pcbddc->conforming; 181213b8bfaSStefano Zampini field = pcbddc->nedfield; 182213b8bfaSStefano Zampini global = pcbddc->nedglobal; 183213b8bfaSStefano Zampini setprimal = PETSC_FALSE; 184a13144ffSStefano Zampini print = PETSC_FALSE; 185213b8bfaSStefano Zampini singular = 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)); 1909566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_nedelec_singular", "Infer nullspace from discrete gradient", NULL, singular, &singular, NULL)); 1919566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_nedelec_order", "Test variable order code (to be removed)", NULL, order, &order, NULL)); 192213b8bfaSStefano Zampini /* print debug info TODO: to be removed */ 1939566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_nedelec_print", "Print debug info", NULL, print, &print, NULL)); 194d0609cedSBarry Smith PetscOptionsEnd(); 195213b8bfaSStefano Zampini 196213b8bfaSStefano Zampini /* Return if there are no edges in the decomposition and the problem is not singular */ 1979566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(pc->pmat, &al2g, NULL)); 1989566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(al2g, &n)); 1999566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)pc, &comm)); 200213b8bfaSStefano Zampini if (!singular) { 2019566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(matis->counter, (const PetscScalar **)&vals)); 202a13144ffSStefano Zampini lrc[0] = PETSC_FALSE; 203c2151214SStefano Zampini for (i = 0; i < n; i++) { 204a13144ffSStefano Zampini if (PetscRealPart(vals[i]) > 2.) { 205a13144ffSStefano Zampini lrc[0] = PETSC_TRUE; 206a13144ffSStefano Zampini break; 207a13144ffSStefano Zampini } 208a13144ffSStefano Zampini } 2099566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(matis->counter, (const PetscScalar **)&vals)); 2101c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&lrc[0], &lrc[1], 1, MPIU_BOOL, MPI_LOR, comm)); 2113ba16761SJacob Faibussowitsch if (!lrc[1]) PetscFunctionReturn(PETSC_SUCCESS); 212213b8bfaSStefano Zampini } 213a13144ffSStefano Zampini 214213b8bfaSStefano Zampini /* Get Nedelec field */ 21563a3b9bcSJacob 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); 216213b8bfaSStefano Zampini if (pcbddc->n_ISForDofsLocal && field >= 0) { 2179566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->ISForDofsLocal[field])); 218c2151214SStefano Zampini nedfieldlocal = pcbddc->ISForDofsLocal[field]; 2199566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(nedfieldlocal, &ne)); 220213b8bfaSStefano Zampini } else if (!pcbddc->n_ISForDofsLocal && field != PETSC_DECIDE) { 221213b8bfaSStefano Zampini ne = n; 222213b8bfaSStefano Zampini nedfieldlocal = NULL; 223213b8bfaSStefano Zampini global = PETSC_TRUE; 224213b8bfaSStefano Zampini } else if (field == PETSC_DECIDE) { 225213b8bfaSStefano Zampini PetscInt rst, ren, *idx; 226213b8bfaSStefano Zampini 2279566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_leafdata, n)); 2289566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_rootdata, pc->pmat->rmap->n)); 2299566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(pcbddc->discretegradient, &rst, &ren)); 230213b8bfaSStefano Zampini for (i = rst; i < ren; i++) { 231213b8bfaSStefano Zampini PetscInt nc; 232213b8bfaSStefano Zampini 2339566063dSJacob Faibussowitsch PetscCall(MatGetRow(pcbddc->discretegradient, i, &nc, NULL, NULL)); 234213b8bfaSStefano Zampini if (nc > 1) matis->sf_rootdata[i - rst] = 1; 2359566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(pcbddc->discretegradient, i, &nc, NULL, NULL)); 236213b8bfaSStefano Zampini } 2379566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 2389566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 2399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &idx)); 2409371c9d4SSatish Balay for (i = 0, ne = 0; i < n; i++) 2419371c9d4SSatish Balay if (matis->sf_leafdata[i]) idx[ne++] = i; 2429566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, ne, idx, PETSC_OWN_POINTER, &nedfieldlocal)); 243213b8bfaSStefano Zampini } else { 244213b8bfaSStefano Zampini SETERRQ(comm, PETSC_ERR_USER, "When multiple fields are present, the Nedelec field has to be specified"); 245213b8bfaSStefano Zampini } 246213b8bfaSStefano Zampini 247213b8bfaSStefano Zampini /* Sanity checks */ 2487827d75bSBarry Smith PetscCheck(order || conforming, comm, PETSC_ERR_SUP, "Variable order and non-conforming spaces are not supported at the same time"); 24928b400f6SJacob Faibussowitsch PetscCheck(!pcbddc->user_ChangeOfBasisMatrix, comm, PETSC_ERR_SUP, "Cannot generate Nedelec support with user defined change of basis"); 25063a3b9bcSJacob 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); 251213b8bfaSStefano Zampini 252213b8bfaSStefano Zampini /* Just set primal dofs and return */ 2531e0482f5SStefano Zampini if (setprimal) { 254eee23b56SStefano Zampini IS enedfieldlocal; 255eee23b56SStefano Zampini PetscInt *eidxs; 256eee23b56SStefano Zampini 2579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ne, &eidxs)); 2589566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(matis->counter, (const PetscScalar **)&vals)); 259213b8bfaSStefano Zampini if (nedfieldlocal) { 2609566063dSJacob Faibussowitsch PetscCall(ISGetIndices(nedfieldlocal, &idxs)); 261eee23b56SStefano Zampini for (i = 0, cum = 0; i < ne; i++) { 262ad540459SPierre Jolivet if (PetscRealPart(vals[idxs[i]]) > 2.) eidxs[cum++] = idxs[i]; 263eee23b56SStefano Zampini } 2649566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(nedfieldlocal, &idxs)); 265213b8bfaSStefano Zampini } else { 266213b8bfaSStefano Zampini for (i = 0, cum = 0; i < ne; i++) { 267ad540459SPierre Jolivet if (PetscRealPart(vals[i]) > 2.) eidxs[cum++] = i; 268213b8bfaSStefano Zampini } 269213b8bfaSStefano Zampini } 2709566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(matis->counter, (const PetscScalar **)&vals)); 2719566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, cum, eidxs, PETSC_COPY_VALUES, &enedfieldlocal)); 2729566063dSJacob Faibussowitsch PetscCall(PCBDDCSetPrimalVerticesLocalIS(pc, enedfieldlocal)); 2739566063dSJacob Faibussowitsch PetscCall(PetscFree(eidxs)); 2749566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nedfieldlocal)); 2759566063dSJacob Faibussowitsch PetscCall(ISDestroy(&enedfieldlocal)); 2763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2771e0482f5SStefano Zampini } 278a13144ffSStefano Zampini 279213b8bfaSStefano Zampini /* Compute some l2g maps */ 280213b8bfaSStefano Zampini if (nedfieldlocal) { 281c2151214SStefano Zampini IS is; 282c2151214SStefano Zampini 283c2151214SStefano Zampini /* need to map from the local Nedelec field to local numbering */ 2849566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(nedfieldlocal, &fl2g)); 2851e0482f5SStefano Zampini /* need to map from the local Nedelec field to global numbering for the whole dofs*/ 2869566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(al2g, nedfieldlocal, &is)); 2879566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &al2g)); 2881e0482f5SStefano Zampini /* need to map from the local Nedelec field to global numbering (for Nedelec only) */ 2891e0482f5SStefano Zampini if (global) { 2909566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)al2g)); 2911e0482f5SStefano Zampini el2g = al2g; 2921e0482f5SStefano Zampini } else { 2931e0482f5SStefano Zampini IS gis; 2941e0482f5SStefano Zampini 2959566063dSJacob Faibussowitsch PetscCall(ISRenumber(is, NULL, NULL, &gis)); 2969566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(gis, &el2g)); 2979566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gis)); 2981e0482f5SStefano Zampini } 2999566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 300c2151214SStefano Zampini } else { 3011e0482f5SStefano Zampini /* restore default */ 3021e0482f5SStefano Zampini pcbddc->nedfield = -1; 3031e0482f5SStefano Zampini /* one ref for the destruction of al2g, one for el2g */ 3049566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)al2g)); 3059566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)al2g)); 3061e0482f5SStefano Zampini el2g = al2g; 307c2151214SStefano Zampini fl2g = NULL; 308c2151214SStefano Zampini } 309a13144ffSStefano Zampini 310213b8bfaSStefano Zampini /* Start communication to drop connections for interior edges (for cc analysis only) */ 3119566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_leafdata, n)); 3129566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_rootdata, pc->pmat->rmap->n)); 313c2151214SStefano Zampini if (nedfieldlocal) { 3149566063dSJacob Faibussowitsch PetscCall(ISGetIndices(nedfieldlocal, &idxs)); 315c2151214SStefano Zampini for (i = 0; i < ne; i++) matis->sf_leafdata[idxs[i]] = 1; 3169566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(nedfieldlocal, &idxs)); 317c2151214SStefano Zampini } else { 318c2151214SStefano Zampini for (i = 0; i < ne; i++) matis->sf_leafdata[i] = 1; 319c2151214SStefano Zampini } 3209566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, matis->sf_leafdata, matis->sf_rootdata, MPI_SUM)); 3219566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, matis->sf_leafdata, matis->sf_rootdata, MPI_SUM)); 322213b8bfaSStefano Zampini 323213b8bfaSStefano Zampini if (!singular) { /* drop connections with interior edges to avoid unneeded communications and memory movements */ 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 } 349213b8bfaSStefano Zampini } else { /* we need the entire G to infer the nullspace */ 3509566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->discretegradient)); 351213b8bfaSStefano Zampini G = pcbddc->discretegradient; 352213b8bfaSStefano Zampini } 353a13144ffSStefano Zampini 354a13144ffSStefano Zampini /* Extract subdomain relevant rows of G */ 3559566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(el2g, &idxs)); 3569566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, ne, idxs, PETSC_USE_POINTER, &lned)); 3579566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(G, lned, NULL, MAT_INITIAL_MATRIX, &lGall)); 3589566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(el2g, &idxs)); 3599566063dSJacob Faibussowitsch PetscCall(ISDestroy(&lned)); 3609566063dSJacob Faibussowitsch PetscCall(MatConvert(lGall, MATIS, MAT_INITIAL_MATRIX, &lGis)); 3619566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGall)); 3629566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(lGis, &lG)); 363a13144ffSStefano Zampini 364213b8bfaSStefano Zampini /* SF for nodal dofs communications */ 3659566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(G, NULL, &Lv)); 3669566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(lGis, NULL, &vl2g)); 3679566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)vl2g)); 3689566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(vl2g, &nv)); 3699566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &sfv)); 3709566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(vl2g, &idxs)); 3719566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(sfv, lGis->cmap, nv, NULL, PETSC_OWN_POINTER, idxs)); 3729566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(vl2g, &idxs)); 373213b8bfaSStefano Zampini i = singular ? 2 : 1; 3749566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(i * nv, &sfvleaves, i * Lv, &sfvroots)); 375a13144ffSStefano Zampini 3761e0482f5SStefano Zampini /* Destroy temporary G created in MATIS format and modified G */ 3779566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)lG)); 3789566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGis)); 3799566063dSJacob Faibussowitsch PetscCall(MatDestroy(&G)); 380a13144ffSStefano Zampini 381213b8bfaSStefano Zampini if (print) { 3829566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)lG, "initial_lG")); 3839566063dSJacob Faibussowitsch PetscCall(MatView(lG, NULL)); 384213b8bfaSStefano Zampini } 385213b8bfaSStefano Zampini 386213b8bfaSStefano Zampini /* Save lG for values insertion in change of basis */ 3879566063dSJacob Faibussowitsch PetscCall(MatDuplicate(lG, MAT_COPY_VALUES, &lGinit)); 3880569b399SStefano Zampini 389a13144ffSStefano Zampini /* Analyze the edge-nodes connections (duplicate lG) */ 3909566063dSJacob Faibussowitsch PetscCall(MatDuplicate(lG, MAT_COPY_VALUES, &lGe)); 3919566063dSJacob Faibussowitsch PetscCall(MatSetOption(lGe, MAT_KEEP_NONZERO_PATTERN, PETSC_FALSE)); 3929566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(nv, &btv)); 3939566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(ne, &bte)); 3949566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(ne, &btb)); 3959566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(ne, &btbd)); 3969566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(nv, &btvcand)); 397a13144ffSStefano Zampini /* need to import the boundary specification to ensure the 398a13144ffSStefano Zampini proper detection of coarse edges' endpoints */ 399a13144ffSStefano Zampini if (pcbddc->DirichletBoundariesLocal) { 400c2151214SStefano Zampini IS is; 401c2151214SStefano Zampini 402c2151214SStefano Zampini if (fl2g) { 4039566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(fl2g, IS_GTOLM_MASK, pcbddc->DirichletBoundariesLocal, &is)); 404c2151214SStefano Zampini } else { 405c2151214SStefano Zampini is = pcbddc->DirichletBoundariesLocal; 406c2151214SStefano Zampini } 4079566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &cum)); 4089566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, &idxs)); 409a13144ffSStefano Zampini for (i = 0; i < cum; i++) { 410a13144ffSStefano Zampini if (idxs[i] >= 0) { 4119566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btb, idxs[i])); 4129566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btbd, idxs[i])); 413a13144ffSStefano Zampini } 414a13144ffSStefano Zampini } 4159566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, &idxs)); 41648a46eb9SPierre Jolivet if (fl2g) PetscCall(ISDestroy(&is)); 417a13144ffSStefano Zampini } 418a13144ffSStefano Zampini if (pcbddc->NeumannBoundariesLocal) { 419c2151214SStefano Zampini IS is; 420c2151214SStefano Zampini 421c2151214SStefano Zampini if (fl2g) { 4229566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(fl2g, IS_GTOLM_MASK, pcbddc->NeumannBoundariesLocal, &is)); 423c2151214SStefano Zampini } else { 424c2151214SStefano Zampini is = pcbddc->NeumannBoundariesLocal; 425c2151214SStefano Zampini } 4269566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &cum)); 4279566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, &idxs)); 428a13144ffSStefano Zampini for (i = 0; i < cum; i++) { 42948a46eb9SPierre Jolivet if (idxs[i] >= 0) PetscCall(PetscBTSet(btb, idxs[i])); 430a13144ffSStefano Zampini } 4319566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, &idxs)); 43248a46eb9SPierre Jolivet if (fl2g) PetscCall(ISDestroy(&is)); 433c2151214SStefano Zampini } 434c2151214SStefano Zampini 435213b8bfaSStefano Zampini /* Count neighs per dof */ 4369566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetNodeInfo(el2g, NULL, &ecount, &eneighs)); 4379566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetNodeInfo(vl2g, NULL, &vcount, &vneighs)); 438637e8532SStefano Zampini 4397d871cd7SStefano Zampini /* need to remove coarse faces' dofs and coarse edges' dirichlet dofs 4407d871cd7SStefano Zampini for proper detection of coarse edges' endpoints */ 4419566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(ne, &btee)); 44262b0c6f7SStefano Zampini for (i = 0; i < ne; i++) { 44348a46eb9SPierre Jolivet if ((ecount[i] > 2 && !PetscBTLookup(btbd, i)) || (ecount[i] == 2 && PetscBTLookup(btb, i))) PetscCall(PetscBTSet(btee, i)); 44462b0c6f7SStefano Zampini } 4459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ne, &marks)); 44662b0c6f7SStefano Zampini if (!conforming) { 4479566063dSJacob Faibussowitsch PetscCall(MatTranspose(lGe, MAT_INITIAL_MATRIX, &lGt)); 4489566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 44962b0c6f7SStefano Zampini } 4509566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGe, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 4519566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(lGe, &vals)); 45262b0c6f7SStefano Zampini cum = 0; 453a13144ffSStefano Zampini for (i = 0; i < ne; i++) { 454dec27d64SStefano Zampini /* eliminate rows corresponding to edge dofs belonging to coarse faces */ 45562b0c6f7SStefano Zampini if (!PetscBTLookup(btee, i)) { 456a13144ffSStefano Zampini marks[cum++] = i; 457dec27d64SStefano Zampini continue; 458dec27d64SStefano Zampini } 459dec27d64SStefano Zampini /* set badly connected edge dofs as primal */ 46062b0c6f7SStefano Zampini if (!conforming) { 46162b0c6f7SStefano Zampini if (ii[i + 1] - ii[i] != order + 1) { /* every row of G on the coarse edge should list order+1 nodal dofs */ 462a13144ffSStefano Zampini marks[cum++] = i; 4639566063dSJacob Faibussowitsch PetscCall(PetscBTSet(bte, i)); 46448a46eb9SPierre Jolivet for (j = ii[i]; j < ii[i + 1]; j++) PetscCall(PetscBTSet(btv, jj[j])); 46562b0c6f7SStefano Zampini } else { 466aaa8cc7dSPierre Jolivet /* every edge dofs should be connected through a certain number of nodal dofs 46762b0c6f7SStefano Zampini to other edge dofs belonging to coarse edges 46862b0c6f7SStefano Zampini - at most 2 endpoints 46962b0c6f7SStefano Zampini - order-1 interior nodal dofs 47062b0c6f7SStefano Zampini - no undefined nodal dofs (nconn < order) 47162b0c6f7SStefano Zampini */ 47262b0c6f7SStefano Zampini PetscInt ends = 0, ints = 0, undef = 0; 47362b0c6f7SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 47462b0c6f7SStefano Zampini PetscInt v = jj[j], k; 47562b0c6f7SStefano Zampini PetscInt nconn = iit[v + 1] - iit[v]; 4769371c9d4SSatish Balay for (k = iit[v]; k < iit[v + 1]; k++) 4779371c9d4SSatish Balay if (!PetscBTLookup(btee, jjt[k])) nconn--; 47862b0c6f7SStefano Zampini if (nconn > order) ends++; 47962b0c6f7SStefano Zampini else if (nconn == order) ints++; 48062b0c6f7SStefano Zampini else undef++; 48162b0c6f7SStefano Zampini } 48262b0c6f7SStefano Zampini if (undef || ends > 2 || ints != order - 1) { 48362b0c6f7SStefano Zampini marks[cum++] = i; 4849566063dSJacob Faibussowitsch PetscCall(PetscBTSet(bte, i)); 48548a46eb9SPierre Jolivet for (j = ii[i]; j < ii[i + 1]; j++) PetscCall(PetscBTSet(btv, jj[j])); 48662b0c6f7SStefano Zampini } 48762b0c6f7SStefano Zampini } 488a13144ffSStefano Zampini } 489dec27d64SStefano Zampini /* We assume the order on the element edge is ii[i+1]-ii[i]-1 */ 490dec27d64SStefano Zampini if (!order && ii[i + 1] != ii[i]) { 491dec27d64SStefano Zampini PetscScalar val = 1. / (ii[i + 1] - ii[i] - 1); 492dec27d64SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) vals[j] = val; 493a13144ffSStefano Zampini } 494dec27d64SStefano Zampini } 4959566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btee)); 4969566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(lGe, &vals)); 4979566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGe, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 49862b0c6f7SStefano Zampini if (!conforming) { 4999566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 5009566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGt)); 50162b0c6f7SStefano Zampini } 5029566063dSJacob Faibussowitsch PetscCall(MatZeroRows(lGe, cum, marks, 0., NULL, NULL)); 503637e8532SStefano Zampini 504b03ebc13SStefano Zampini /* identify splitpoints and corner candidates */ 5059566063dSJacob Faibussowitsch PetscCall(MatTranspose(lGe, MAT_INITIAL_MATRIX, &lGt)); 506a13144ffSStefano Zampini if (print) { 5079566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)lGe, "edgerestr_lG")); 5089566063dSJacob Faibussowitsch PetscCall(MatView(lGe, NULL)); 5099566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)lGt, "edgerestr_lGt")); 5109566063dSJacob Faibussowitsch PetscCall(MatView(lGt, NULL)); 511a13144ffSStefano Zampini } 5129566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 5139566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(lGt, &vals)); 514a13144ffSStefano Zampini for (i = 0; i < nv; i++) { 515637e8532SStefano Zampini PetscInt ord = order, test = ii[i + 1] - ii[i], vc = vcount[i]; 5167d871cd7SStefano Zampini PetscBool sneighs = PETSC_TRUE, bdir = PETSC_FALSE; 517b03ebc13SStefano Zampini if (!order) { /* variable order */ 518dec27d64SStefano Zampini PetscReal vorder = 0.; 519dec27d64SStefano Zampini 520dec27d64SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) vorder += PetscRealPart(vals[j]); 521dec27d64SStefano Zampini test = PetscFloorReal(vorder + 10. * PETSC_SQRT_MACHINE_EPSILON); 52263a3b9bcSJacob Faibussowitsch PetscCheck(vorder - test <= PETSC_SQRT_MACHINE_EPSILON, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected value for vorder: %g (%" PetscInt_FMT ")", (double)vorder, test); 523dec27d64SStefano Zampini ord = 1; 524dec27d64SStefano Zampini } 5256bdcaf15SBarry Smith PetscAssert(test % ord == 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected number of edge dofs %" PetscInt_FMT " connected with nodal dof %" PetscInt_FMT " with order %" PetscInt_FMT, test, i, ord); 526637e8532SStefano Zampini for (j = ii[i]; j < ii[i + 1] && sneighs; j++) { 5277d871cd7SStefano Zampini if (PetscBTLookup(btbd, jj[j])) { 5287d871cd7SStefano Zampini bdir = PETSC_TRUE; 5297d871cd7SStefano Zampini break; 5307d871cd7SStefano Zampini } 531637e8532SStefano Zampini if (vc != ecount[jj[j]]) { 532637e8532SStefano Zampini sneighs = PETSC_FALSE; 533637e8532SStefano Zampini } else { 534637e8532SStefano Zampini PetscInt k, *vn = vneighs[i], *en = eneighs[jj[j]]; 535637e8532SStefano Zampini for (k = 0; k < vc; k++) { 536637e8532SStefano Zampini if (vn[k] != en[k]) { 537637e8532SStefano Zampini sneighs = PETSC_FALSE; 538637e8532SStefano Zampini break; 539637e8532SStefano Zampini } 540637e8532SStefano Zampini } 541637e8532SStefano Zampini } 542637e8532SStefano Zampini } 5437d871cd7SStefano Zampini if (!sneighs || test >= 3 * ord || bdir) { /* splitpoints */ 5443ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, "SPLITPOINT %" PetscInt_FMT " (%s %s %s)\n", i, PetscBools[!sneighs], PetscBools[test >= 3 * ord], PetscBools[bdir])); 5459566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, i)); 546dec27d64SStefano Zampini } else if (test == ord) { 547b03ebc13SStefano Zampini if (order == 1 || (!order && ii[i + 1] - ii[i] == 1)) { 5483ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, "ENDPOINT %" PetscInt_FMT "\n", i)); 5499566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, i)); 550a13144ffSStefano Zampini } else { 5513ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, "CORNER CANDIDATE %" PetscInt_FMT "\n", i)); 5529566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btvcand, i)); 553a13144ffSStefano Zampini } 554a13144ffSStefano Zampini } 555a13144ffSStefano Zampini } 5569566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(el2g, NULL, &ecount, &eneighs)); 5579566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(vl2g, NULL, &vcount, &vneighs)); 5589566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btbd)); 559b03ebc13SStefano Zampini 560b03ebc13SStefano Zampini /* a candidate is valid if it is connected to another candidate via a non-primal edge dof */ 561b03ebc13SStefano Zampini if (order != 1) { 5623ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, "INSPECTING CANDIDATES\n")); 5639566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGe, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 564b03ebc13SStefano Zampini for (i = 0; i < nv; i++) { 565b03ebc13SStefano Zampini if (PetscBTLookup(btvcand, i)) { 566b03ebc13SStefano Zampini PetscBool found = PETSC_FALSE; 567b03ebc13SStefano Zampini for (j = ii[i]; j < ii[i + 1] && !found; j++) { 568b03ebc13SStefano Zampini PetscInt k, e = jj[j]; 569b03ebc13SStefano Zampini if (PetscBTLookup(bte, e)) continue; 570b03ebc13SStefano Zampini for (k = iit[e]; k < iit[e + 1]; k++) { 571b03ebc13SStefano Zampini PetscInt v = jjt[k]; 572b03ebc13SStefano Zampini if (v != i && PetscBTLookup(btvcand, v)) { 573b03ebc13SStefano Zampini found = PETSC_TRUE; 574b03ebc13SStefano Zampini break; 575b03ebc13SStefano Zampini } 576b03ebc13SStefano Zampini } 577b03ebc13SStefano Zampini } 578b03ebc13SStefano Zampini if (!found) { 5793ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " CANDIDATE %" PetscInt_FMT " CLEARED\n", i)); 5809566063dSJacob Faibussowitsch PetscCall(PetscBTClear(btvcand, i)); 581b03ebc13SStefano Zampini } else { 5823ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " CANDIDATE %" PetscInt_FMT " ACCEPTED\n", i)); 583b03ebc13SStefano Zampini } 584b03ebc13SStefano Zampini } 585b03ebc13SStefano Zampini } 5869566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGe, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 587b03ebc13SStefano Zampini } 5889566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(lGt, &vals)); 5899566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 5909566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGe)); 591a13144ffSStefano Zampini 592a13144ffSStefano Zampini /* Get the local G^T explicitly */ 5939566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGt)); 5949566063dSJacob Faibussowitsch PetscCall(MatTranspose(lG, MAT_INITIAL_MATRIX, &lGt)); 5959566063dSJacob Faibussowitsch PetscCall(MatSetOption(lGt, MAT_KEEP_NONZERO_PATTERN, PETSC_FALSE)); 596a13144ffSStefano Zampini 5974e64d54eSstefano_zampini /* Mark interior nodal dofs */ 5989566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetInfo(vl2g, &n_neigh, &neigh, &n_shared, &shared)); 5999566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(nv, &btvi)); 600a13144ffSStefano Zampini for (i = 1; i < n_neigh; i++) { 60148a46eb9SPierre Jolivet for (j = 0; j < n_shared[i]; j++) PetscCall(PetscBTSet(btvi, shared[i][j])); 602a13144ffSStefano Zampini } 6039566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreInfo(vl2g, &n_neigh, &neigh, &n_shared, &shared)); 604a13144ffSStefano Zampini 605a13144ffSStefano Zampini /* communicate corners and splitpoints */ 6069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nv, &vmarks)); 6079566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(sfvleaves, nv)); 6089566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(sfvroots, Lv)); 6099371c9d4SSatish Balay for (i = 0; i < nv; i++) 6109371c9d4SSatish Balay if (PetscUnlikely(PetscBTLookup(btv, i))) sfvleaves[i] = 1; 611a13144ffSStefano Zampini 612a13144ffSStefano Zampini if (print) { 613a13144ffSStefano Zampini IS tbz; 614a13144ffSStefano Zampini 615a13144ffSStefano Zampini cum = 0; 616a13144ffSStefano Zampini for (i = 0; i < nv; i++) 6179371c9d4SSatish Balay if (sfvleaves[i]) vmarks[cum++] = i; 618a13144ffSStefano Zampini 6199566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cum, vmarks, PETSC_COPY_VALUES, &tbz)); 6209566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)tbz, "corners_to_be_zeroed_local")); 6219566063dSJacob Faibussowitsch PetscCall(ISView(tbz, NULL)); 6229566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tbz)); 623a13144ffSStefano Zampini } 624a13144ffSStefano Zampini 6259566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(sfv, MPIU_INT, sfvleaves, sfvroots, MPI_SUM)); 6269566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(sfv, MPIU_INT, sfvleaves, sfvroots, MPI_SUM)); 6279566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfv, MPIU_INT, sfvroots, sfvleaves, MPI_REPLACE)); 6289566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfv, MPIU_INT, sfvroots, sfvleaves, MPI_REPLACE)); 629a13144ffSStefano Zampini 6304e64d54eSstefano_zampini /* Zero rows of lGt corresponding to identified corners 6314e64d54eSstefano_zampini and interior nodal dofs */ 632a13144ffSStefano Zampini cum = 0; 633a13144ffSStefano Zampini for (i = 0; i < nv; i++) { 634a13144ffSStefano Zampini if (sfvleaves[i]) { 635a13144ffSStefano Zampini vmarks[cum++] = i; 6369566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, i)); 637a13144ffSStefano Zampini } 6384e64d54eSstefano_zampini if (!PetscBTLookup(btvi, i)) vmarks[cum++] = i; 639a13144ffSStefano Zampini } 6409566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btvi)); 641a13144ffSStefano Zampini if (print) { 642a13144ffSStefano Zampini IS tbz; 643a13144ffSStefano Zampini 6449566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cum, vmarks, PETSC_COPY_VALUES, &tbz)); 6459566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)tbz, "corners_to_be_zeroed_with_interior")); 6469566063dSJacob Faibussowitsch PetscCall(ISView(tbz, NULL)); 6479566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tbz)); 648a13144ffSStefano Zampini } 6499566063dSJacob Faibussowitsch PetscCall(MatZeroRows(lGt, cum, vmarks, 0., NULL, NULL)); 6509566063dSJacob Faibussowitsch PetscCall(PetscFree(vmarks)); 6519566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfv)); 6529566063dSJacob Faibussowitsch PetscCall(PetscFree2(sfvleaves, sfvroots)); 653a13144ffSStefano Zampini 654a13144ffSStefano Zampini /* Recompute G */ 6559566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lG)); 6569566063dSJacob Faibussowitsch PetscCall(MatTranspose(lGt, MAT_INITIAL_MATRIX, &lG)); 657a13144ffSStefano Zampini if (print) { 6589566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)lG, "used_lG")); 6599566063dSJacob Faibussowitsch PetscCall(MatView(lG, NULL)); 6609566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)lGt, "used_lGt")); 6619566063dSJacob Faibussowitsch PetscCall(MatView(lGt, NULL)); 662a13144ffSStefano Zampini } 663a13144ffSStefano Zampini 664a13144ffSStefano Zampini /* Get primal dofs (if any) */ 665a13144ffSStefano Zampini cum = 0; 666a13144ffSStefano Zampini for (i = 0; i < ne; i++) { 667a13144ffSStefano Zampini if (PetscUnlikely(PetscBTLookup(bte, i))) marks[cum++] = i; 668a13144ffSStefano Zampini } 6691baa6e33SBarry Smith if (fl2g) PetscCall(ISLocalToGlobalMappingApply(fl2g, cum, marks, marks)); 6709566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, cum, marks, PETSC_COPY_VALUES, &primals)); 671a13144ffSStefano Zampini if (print) { 6729566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)primals, "prescribed_primal_dofs")); 6739566063dSJacob Faibussowitsch PetscCall(ISView(primals, NULL)); 674a13144ffSStefano Zampini } 6759566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&bte)); 676c2151214SStefano Zampini /* TODO: what if the user passed in some of them ? */ 6779566063dSJacob Faibussowitsch PetscCall(PCBDDCSetPrimalVerticesLocalIS(pc, primals)); 6789566063dSJacob Faibussowitsch PetscCall(ISDestroy(&primals)); 679a13144ffSStefano Zampini 680a13144ffSStefano Zampini /* Compute edge connectivity */ 6819566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)lG, "econn_")); 6824222ddf1SHong Zhang 6834222ddf1SHong Zhang /* Symbolic conn = lG*lGt */ 6849566063dSJacob Faibussowitsch PetscCall(MatProductCreate(lG, lGt, NULL, &conn)); 6859566063dSJacob Faibussowitsch PetscCall(MatProductSetType(conn, MATPRODUCT_AB)); 6869566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(conn, "default")); 6879566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(conn, PETSC_DEFAULT)); 6889566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)conn, "econn_")); 6899566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(conn)); 6909566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(conn)); 6914222ddf1SHong Zhang 6929566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 693c2151214SStefano Zampini if (fl2g) { 694c2151214SStefano Zampini PetscBT btf; 695c2151214SStefano Zampini PetscInt *iia, *jja, *iiu, *jju; 696c2151214SStefano Zampini PetscBool rest = PETSC_FALSE, free = PETSC_FALSE; 697c2151214SStefano Zampini 698c2151214SStefano Zampini /* create CSR for all local dofs */ 6999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n + 1, &iia)); 700c2151214SStefano Zampini if (pcbddc->mat_graph->nvtxs_csr) { /* the user has passed in a CSR graph */ 70163a3b9bcSJacob 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); 702c2151214SStefano Zampini iiu = pcbddc->mat_graph->xadj; 703c2151214SStefano Zampini jju = pcbddc->mat_graph->adjncy; 704c2151214SStefano Zampini } else if (pcbddc->use_local_adj) { 705c2151214SStefano Zampini rest = PETSC_TRUE; 7069566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(matis->A, 0, PETSC_TRUE, PETSC_FALSE, &i, (const PetscInt **)&iiu, (const PetscInt **)&jju, &done)); 707c2151214SStefano Zampini } else { 708c2151214SStefano Zampini free = PETSC_TRUE; 7099566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n + 1, &iiu, n, &jju)); 710c2151214SStefano Zampini iiu[0] = 0; 711c2151214SStefano Zampini for (i = 0; i < n; i++) { 712c2151214SStefano Zampini iiu[i + 1] = i + 1; 713c2151214SStefano Zampini jju[i] = -1; 714d904f53bSStefano Zampini } 715c2151214SStefano Zampini } 716c2151214SStefano Zampini 717c2151214SStefano Zampini /* import sizes of CSR */ 718c2151214SStefano Zampini iia[0] = 0; 719c2151214SStefano Zampini for (i = 0; i < n; i++) iia[i + 1] = iiu[i + 1] - iiu[i]; 720c2151214SStefano Zampini 721c2151214SStefano Zampini /* overwrite entries corresponding to the Nedelec field */ 7229566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(n, &btf)); 7239566063dSJacob Faibussowitsch PetscCall(ISGetIndices(nedfieldlocal, &idxs)); 724c2151214SStefano Zampini for (i = 0; i < ne; i++) { 7259566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btf, idxs[i])); 726c2151214SStefano Zampini iia[idxs[i] + 1] = ii[i + 1] - ii[i]; 727c2151214SStefano Zampini } 728c2151214SStefano Zampini 729c2151214SStefano Zampini /* iia in CSR */ 730c2151214SStefano Zampini for (i = 0; i < n; i++) iia[i + 1] += iia[i]; 731c2151214SStefano Zampini 732c2151214SStefano Zampini /* jja in CSR */ 7339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(iia[n], &jja)); 734c2151214SStefano Zampini for (i = 0; i < n; i++) 735c2151214SStefano Zampini if (!PetscBTLookup(btf, i)) 7369371c9d4SSatish Balay for (j = 0; j < iiu[i + 1] - iiu[i]; j++) jja[iia[i] + j] = jju[iiu[i] + j]; 737c2151214SStefano Zampini 738c2151214SStefano Zampini /* map edge dofs connectivity */ 7391e0482f5SStefano Zampini if (jj) { 7409566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(fl2g, ii[ne], jj, (PetscInt *)jj)); 741c2151214SStefano Zampini for (i = 0; i < ne; i++) { 742c2151214SStefano Zampini PetscInt e = idxs[i]; 743c2151214SStefano Zampini for (j = 0; j < ii[i + 1] - ii[i]; j++) jja[iia[e] + j] = jj[ii[i] + j]; 744c2151214SStefano Zampini } 7451e0482f5SStefano Zampini } 7469566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(nedfieldlocal, &idxs)); 7479566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLocalAdjacencyGraph(pc, n, iia, jja, PETSC_OWN_POINTER)); 74848a46eb9SPierre Jolivet if (rest) PetscCall(MatRestoreRowIJ(matis->A, 0, PETSC_TRUE, PETSC_FALSE, &i, (const PetscInt **)&iiu, (const PetscInt **)&jju, &done)); 7491baa6e33SBarry Smith if (free) PetscCall(PetscFree2(iiu, jju)); 7509566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btf)); 751c2151214SStefano Zampini } else { 7529566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLocalAdjacencyGraph(pc, n, ii, jj, PETSC_USE_POINTER)); 753c2151214SStefano Zampini } 754c2151214SStefano Zampini 755a13144ffSStefano Zampini /* Analyze interface for edge dofs */ 7569566063dSJacob Faibussowitsch PetscCall(PCBDDCAnalyzeInterface(pc)); 757213b8bfaSStefano Zampini pcbddc->mat_graph->twodim = PETSC_FALSE; 758a13144ffSStefano Zampini 759a13144ffSStefano Zampini /* Get coarse edges in the edge space */ 7609566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, NULL, NULL, &nee, &alleedges, &allprimals)); 7619566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(conn, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 762a13144ffSStefano Zampini 763c2151214SStefano Zampini if (fl2g) { 7649566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(fl2g, IS_GTOLM_DROP, allprimals, &primals)); 7659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nee, &eedges)); 76648a46eb9SPierre Jolivet for (i = 0; i < nee; i++) PetscCall(ISGlobalToLocalMappingApplyIS(fl2g, IS_GTOLM_DROP, alleedges[i], &eedges[i])); 767c2151214SStefano Zampini } else { 768c2151214SStefano Zampini eedges = alleedges; 769c2151214SStefano Zampini primals = allprimals; 770c2151214SStefano Zampini } 771c2151214SStefano Zampini 772a13144ffSStefano Zampini /* Mark fine edge dofs with their coarse edge id */ 7739566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(marks, ne)); 7749566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(primals, &cum)); 7759566063dSJacob Faibussowitsch PetscCall(ISGetIndices(primals, &idxs)); 776c2151214SStefano Zampini for (i = 0; i < cum; i++) marks[idxs[i]] = nee + 1; 7779566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(primals, &idxs)); 778c2151214SStefano Zampini if (print) { 7799566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)primals, "obtained_primal_dofs")); 7809566063dSJacob Faibussowitsch PetscCall(ISView(primals, NULL)); 781c2151214SStefano Zampini } 782c2151214SStefano Zampini 783c2151214SStefano Zampini maxsize = 0; 784a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 785a13144ffSStefano Zampini PetscInt size, mark = i + 1; 786a13144ffSStefano Zampini 7879566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 7889566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 789a13144ffSStefano Zampini for (j = 0; j < size; j++) marks[idxs[j]] = mark; 7909566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 791a13144ffSStefano Zampini maxsize = PetscMax(maxsize, size); 792a13144ffSStefano Zampini } 793a13144ffSStefano Zampini 794a13144ffSStefano Zampini /* Find coarse edge endpoints */ 7959566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lG, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 7969566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 797a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 798a13144ffSStefano Zampini PetscInt mark = i + 1, size; 799a13144ffSStefano Zampini 8009566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 8011e0482f5SStefano Zampini if (!size && nedfieldlocal) continue; 80263a3b9bcSJacob Faibussowitsch PetscCheck(size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected zero sized edge %" PetscInt_FMT, i); 8039566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 804a13144ffSStefano Zampini if (print) { 80563a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "ENDPOINTS ANALYSIS EDGE %" PetscInt_FMT "\n", i)); 8069566063dSJacob Faibussowitsch PetscCall(ISView(eedges[i], NULL)); 807a13144ffSStefano Zampini } 808a13144ffSStefano Zampini for (j = 0; j < size; j++) { 809a13144ffSStefano Zampini PetscInt k, ee = idxs[j]; 8103ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " idx %" PetscInt_FMT "\n", ee)); 811a13144ffSStefano Zampini for (k = ii[ee]; k < ii[ee + 1]; k++) { 8123ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " inspect %" PetscInt_FMT "\n", jj[k])); 813a13144ffSStefano Zampini if (PetscBTLookup(btv, jj[k])) { 8143ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " corner found (already set) %" PetscInt_FMT "\n", jj[k])); 815a13144ffSStefano Zampini } else if (PetscBTLookup(btvcand, jj[k])) { /* is it ok? */ 816a13144ffSStefano Zampini PetscInt k2; 817a13144ffSStefano Zampini PetscBool corner = PETSC_FALSE; 818a13144ffSStefano Zampini for (k2 = iit[jj[k]]; k2 < iit[jj[k] + 1]; k2++) { 8193ba16761SJacob 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]))); 820c2151214SStefano Zampini /* it's a corner if either is connected with an edge dof belonging to a different cc or 821c2151214SStefano Zampini if the edge dof lie on the natural part of the boundary */ 822c2151214SStefano Zampini if ((marks[jjt[k2]] && marks[jjt[k2]] != mark) || (!marks[jjt[k2]] && PetscBTLookup(btb, jjt[k2]))) { 823a13144ffSStefano Zampini corner = PETSC_TRUE; 824a13144ffSStefano Zampini break; 825a13144ffSStefano Zampini } 826a13144ffSStefano Zampini } 827a13144ffSStefano Zampini if (corner) { /* found the nodal dof corresponding to the endpoint of the edge */ 8283ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " corner found %" PetscInt_FMT "\n", jj[k])); 8299566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, jj[k])); 830a13144ffSStefano Zampini } else { 8313ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " no corners found\n")); 832a13144ffSStefano Zampini } 833a13144ffSStefano Zampini } 834a13144ffSStefano Zampini } 835a13144ffSStefano Zampini } 8369566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 837a13144ffSStefano Zampini } 8389566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 8399566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lG, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 8409566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btb)); 841a13144ffSStefano Zampini 842a13144ffSStefano Zampini /* Reset marked primal dofs */ 8439566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(primals, &cum)); 8449566063dSJacob Faibussowitsch PetscCall(ISGetIndices(primals, &idxs)); 845a13144ffSStefano Zampini for (i = 0; i < cum; i++) marks[idxs[i]] = 0; 8469566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(primals, &idxs)); 847a13144ffSStefano Zampini 8480569b399SStefano Zampini /* Now use the initial lG */ 8499566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lG)); 8509566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGt)); 8510569b399SStefano Zampini lG = lGinit; 8529566063dSJacob Faibussowitsch PetscCall(MatTranspose(lG, MAT_INITIAL_MATRIX, &lGt)); 8530569b399SStefano Zampini 854a13144ffSStefano Zampini /* Compute extended cols indices */ 8559566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(nv, &btvc)); 8569566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(nee, &bter)); 8579566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lG, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 8589566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetMaxRowNonzeros(lG, &i)); 859a13144ffSStefano Zampini i *= maxsize; 8609566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nee, &extcols)); 8619566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(i, &extrow, i, &gidxs)); 862a13144ffSStefano Zampini eerr = PETSC_FALSE; 863a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 864b03ebc13SStefano Zampini PetscInt size, found = 0; 865a13144ffSStefano Zampini 866a13144ffSStefano Zampini cum = 0; 8679566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 8681e0482f5SStefano Zampini if (!size && nedfieldlocal) continue; 86963a3b9bcSJacob Faibussowitsch PetscCheck(size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected zero sized edge %" PetscInt_FMT, i); 8709566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 8719566063dSJacob Faibussowitsch PetscCall(PetscBTMemzero(nv, btvc)); 872a13144ffSStefano Zampini for (j = 0; j < size; j++) { 873a13144ffSStefano Zampini PetscInt k, ee = idxs[j]; 874b03ebc13SStefano Zampini for (k = ii[ee]; k < ii[ee + 1]; k++) { 875b03ebc13SStefano Zampini PetscInt vv = jj[k]; 876b03ebc13SStefano Zampini if (!PetscBTLookup(btv, vv)) extrow[cum++] = vv; 877b03ebc13SStefano Zampini else if (!PetscBTLookupSet(btvc, vv)) found++; 878b03ebc13SStefano Zampini } 879a13144ffSStefano Zampini } 8809566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 8819566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&cum, extrow)); 8829566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(vl2g, cum, extrow, gidxs)); 8839566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(cum, gidxs, extrow)); 8849566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cum, extrow, PETSC_COPY_VALUES, &extcols[i])); 885a13144ffSStefano Zampini /* it may happen that endpoints are not defined at this point 886a13144ffSStefano Zampini if it is the case, mark this edge for a second pass */ 887b03ebc13SStefano Zampini if (cum != size - 1 || found != 2) { 8889566063dSJacob Faibussowitsch PetscCall(PetscBTSet(bter, i)); 889a13144ffSStefano Zampini if (print) { 8909566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)eedges[i], "error_edge")); 8919566063dSJacob Faibussowitsch PetscCall(ISView(eedges[i], NULL)); 8929566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)extcols[i], "error_extcol")); 8939566063dSJacob Faibussowitsch PetscCall(ISView(extcols[i], NULL)); 894a13144ffSStefano Zampini } 895a13144ffSStefano Zampini eerr = PETSC_TRUE; 896a13144ffSStefano Zampini } 897a13144ffSStefano Zampini } 89828b400f6SJacob Faibussowitsch /* PetscCheck(!eerr,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected SIZE OF EDGE > EXTCOL FIRST PASS"); */ 8991c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&eerr, &done, 1, MPIU_BOOL, MPI_LOR, comm)); 900a13144ffSStefano Zampini if (done) { 901a13144ffSStefano Zampini PetscInt *newprimals; 902a13144ffSStefano Zampini 9039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ne, &newprimals)); 9049566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(primals, &cum)); 9059566063dSJacob Faibussowitsch PetscCall(ISGetIndices(primals, &idxs)); 9069566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(newprimals, idxs, cum)); 9079566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(primals, &idxs)); 9089566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 9093ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, "DOING SECOND PASS (eerr %s)\n", PetscBools[eerr])); 910a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 911b03ebc13SStefano Zampini PetscBool has_candidates = PETSC_FALSE; 912b03ebc13SStefano Zampini if (PetscBTLookup(bter, i)) { 913a13144ffSStefano Zampini PetscInt size, mark = i + 1; 914a13144ffSStefano Zampini 9159566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 9169566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 917c2151214SStefano Zampini /* for (j=0;j<size;j++) newprimals[cum++] = idxs[j]; */ 918a13144ffSStefano Zampini for (j = 0; j < size; j++) { 919a13144ffSStefano Zampini PetscInt k, ee = idxs[j]; 9203ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, "Inspecting edge dof %" PetscInt_FMT " [%" PetscInt_FMT " %" PetscInt_FMT ")\n", ee, ii[ee], ii[ee + 1])); 921a13144ffSStefano Zampini for (k = ii[ee]; k < ii[ee + 1]; k++) { 922a13144ffSStefano Zampini /* set all candidates located on the edge as corners */ 923a13144ffSStefano Zampini if (PetscBTLookup(btvcand, jj[k])) { 924a13144ffSStefano Zampini PetscInt k2, vv = jj[k]; 925b03ebc13SStefano Zampini has_candidates = PETSC_TRUE; 9263ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Candidate set to vertex %" PetscInt_FMT "\n", vv)); 9279566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, vv)); 928a13144ffSStefano Zampini /* set all edge dofs connected to candidate as primals */ 929a13144ffSStefano Zampini for (k2 = iit[vv]; k2 < iit[vv + 1]; k2++) { 930a13144ffSStefano Zampini if (marks[jjt[k2]] == mark) { 931a13144ffSStefano Zampini PetscInt k3, ee2 = jjt[k2]; 9323ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Connected edge dof set to primal %" PetscInt_FMT "\n", ee2)); 933a13144ffSStefano Zampini newprimals[cum++] = ee2; 934a13144ffSStefano Zampini /* finally set the new corners */ 935a13144ffSStefano Zampini for (k3 = ii[ee2]; k3 < ii[ee2 + 1]; k3++) { 9363ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Connected nodal dof set to vertex %" PetscInt_FMT "\n", jj[k3])); 9379566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, jj[k3])); 938a13144ffSStefano Zampini } 939a13144ffSStefano Zampini } 940a13144ffSStefano Zampini } 941b03ebc13SStefano Zampini } else { 9423ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Not a candidate vertex %" PetscInt_FMT "\n", jj[k])); 943a13144ffSStefano Zampini } 944a13144ffSStefano Zampini } 945a13144ffSStefano Zampini } 946b03ebc13SStefano Zampini if (!has_candidates) { /* circular edge */ 947b03ebc13SStefano Zampini PetscInt k, ee = idxs[0], *tmarks; 948b03ebc13SStefano Zampini 9499566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(ne, &tmarks)); 9503ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Circular edge %" PetscInt_FMT "\n", i)); 951b03ebc13SStefano Zampini for (k = ii[ee]; k < ii[ee + 1]; k++) { 952b03ebc13SStefano Zampini PetscInt k2; 9533ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Set to corner %" PetscInt_FMT "\n", jj[k])); 9549566063dSJacob Faibussowitsch PetscCall(PetscBTSet(btv, jj[k])); 955b03ebc13SStefano Zampini for (k2 = iit[jj[k]]; k2 < iit[jj[k] + 1]; k2++) tmarks[jjt[k2]]++; 956b03ebc13SStefano Zampini } 957b03ebc13SStefano Zampini for (j = 0; j < size; j++) { 958b03ebc13SStefano Zampini if (tmarks[idxs[j]] > 1) { 9593ba16761SJacob Faibussowitsch if (print) PetscCall(PetscPrintf(PETSC_COMM_SELF, " Edge dof set to primal %" PetscInt_FMT "\n", idxs[j])); 960b03ebc13SStefano Zampini newprimals[cum++] = idxs[j]; 961b03ebc13SStefano Zampini } 962b03ebc13SStefano Zampini } 9639566063dSJacob Faibussowitsch PetscCall(PetscFree(tmarks)); 964b03ebc13SStefano Zampini } 9659566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 966a13144ffSStefano Zampini } 9679566063dSJacob Faibussowitsch PetscCall(ISDestroy(&extcols[i])); 968a13144ffSStefano Zampini } 9699566063dSJacob Faibussowitsch PetscCall(PetscFree(extcols)); 9709566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &iit, &jjt, &done)); 9719566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&cum, newprimals)); 972c2151214SStefano Zampini if (fl2g) { 9739566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(fl2g, cum, newprimals, newprimals)); 9749566063dSJacob Faibussowitsch PetscCall(ISDestroy(&primals)); 97548a46eb9SPierre Jolivet for (i = 0; i < nee; i++) PetscCall(ISDestroy(&eedges[i])); 9769566063dSJacob Faibussowitsch PetscCall(PetscFree(eedges)); 977c2151214SStefano Zampini } 9789566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, NULL, NULL, &nee, &alleedges, &allprimals)); 9799566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, cum, newprimals, PETSC_COPY_VALUES, &primals)); 9809566063dSJacob Faibussowitsch PetscCall(PetscFree(newprimals)); 9819566063dSJacob Faibussowitsch PetscCall(PCBDDCSetPrimalVerticesLocalIS(pc, primals)); 9829566063dSJacob Faibussowitsch PetscCall(ISDestroy(&primals)); 9839566063dSJacob Faibussowitsch PetscCall(PCBDDCAnalyzeInterface(pc)); 984213b8bfaSStefano Zampini pcbddc->mat_graph->twodim = PETSC_FALSE; 9859566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, NULL, NULL, &nee, &alleedges, &allprimals)); 986c2151214SStefano Zampini if (fl2g) { 9879566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(fl2g, IS_GTOLM_DROP, allprimals, &primals)); 9889566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nee, &eedges)); 98948a46eb9SPierre Jolivet for (i = 0; i < nee; i++) PetscCall(ISGlobalToLocalMappingApplyIS(fl2g, IS_GTOLM_DROP, alleedges[i], &eedges[i])); 990c2151214SStefano Zampini } else { 991c2151214SStefano Zampini eedges = alleedges; 992c2151214SStefano Zampini primals = allprimals; 993c2151214SStefano Zampini } 9949566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nee, &extcols)); 995a13144ffSStefano Zampini 996a13144ffSStefano Zampini /* Mark again */ 9979566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(marks, ne)); 998a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 999a13144ffSStefano Zampini PetscInt size, mark = i + 1; 1000a13144ffSStefano Zampini 10019566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 10029566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 1003a13144ffSStefano Zampini for (j = 0; j < size; j++) marks[idxs[j]] = mark; 10049566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 1005a13144ffSStefano Zampini } 1006a13144ffSStefano Zampini if (print) { 10079566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)primals, "obtained_primal_dofs_secondpass")); 10089566063dSJacob Faibussowitsch PetscCall(ISView(primals, NULL)); 1009a13144ffSStefano Zampini } 1010a13144ffSStefano Zampini 1011a13144ffSStefano Zampini /* Recompute extended cols */ 1012a13144ffSStefano Zampini eerr = PETSC_FALSE; 1013a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 1014a13144ffSStefano Zampini PetscInt size; 1015a13144ffSStefano Zampini 1016a13144ffSStefano Zampini cum = 0; 10179566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 10181e0482f5SStefano Zampini if (!size && nedfieldlocal) continue; 101963a3b9bcSJacob Faibussowitsch PetscCheck(size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected zero sized edge %" PetscInt_FMT, i); 10209566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 1021a13144ffSStefano Zampini for (j = 0; j < size; j++) { 1022a13144ffSStefano Zampini PetscInt k, ee = idxs[j]; 10239371c9d4SSatish Balay for (k = ii[ee]; k < ii[ee + 1]; k++) 10249371c9d4SSatish Balay if (!PetscBTLookup(btv, jj[k])) extrow[cum++] = jj[k]; 1025a13144ffSStefano Zampini } 10269566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 10279566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&cum, extrow)); 10289566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(vl2g, cum, extrow, gidxs)); 10299566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(cum, gidxs, extrow)); 10309566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, cum, extrow, PETSC_COPY_VALUES, &extcols[i])); 1031a13144ffSStefano Zampini if (cum != size - 1) { 1032a13144ffSStefano Zampini if (print) { 10339566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)eedges[i], "error_edge_secondpass")); 10349566063dSJacob Faibussowitsch PetscCall(ISView(eedges[i], NULL)); 10359566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)extcols[i], "error_extcol_secondpass")); 10369566063dSJacob Faibussowitsch PetscCall(ISView(extcols[i], NULL)); 1037a13144ffSStefano Zampini } 1038a13144ffSStefano Zampini eerr = PETSC_TRUE; 1039a13144ffSStefano Zampini } 1040a13144ffSStefano Zampini } 1041a13144ffSStefano Zampini } 10429566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lG, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 10439566063dSJacob Faibussowitsch PetscCall(PetscFree2(extrow, gidxs)); 10449566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&bter)); 10459566063dSJacob Faibussowitsch if (print) PetscCall(PCBDDCGraphASCIIView(pcbddc->mat_graph, 5, PETSC_VIEWER_STDOUT_SELF)); 1046a13144ffSStefano Zampini /* an error should not occur at this point */ 104728b400f6SJacob Faibussowitsch PetscCheck(!eerr, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected SIZE OF EDGE > EXTCOL SECOND PASS"); 1048a13144ffSStefano Zampini 10494e64d54eSstefano_zampini /* Check the number of endpoints */ 10509566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lG, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 10519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2 * nee, &corners)); 10529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nee, &cedges)); 10534e64d54eSstefano_zampini for (i = 0; i < nee; i++) { 1054b03ebc13SStefano Zampini PetscInt size, found = 0, gc[2]; 10554e64d54eSstefano_zampini 1056b03ebc13SStefano Zampini /* init with defaults */ 1057b03ebc13SStefano Zampini cedges[i] = corners[i * 2] = corners[i * 2 + 1] = -1; 10589566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(eedges[i], &size)); 10591e0482f5SStefano Zampini if (!size && nedfieldlocal) continue; 106063a3b9bcSJacob Faibussowitsch PetscCheck(size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected zero sized edge %" PetscInt_FMT, i); 10619566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &idxs)); 10629566063dSJacob Faibussowitsch PetscCall(PetscBTMemzero(nv, btvc)); 10634e64d54eSstefano_zampini for (j = 0; j < size; j++) { 10644e64d54eSstefano_zampini PetscInt k, ee = idxs[j]; 10654e64d54eSstefano_zampini for (k = ii[ee]; k < ii[ee + 1]; k++) { 10664e64d54eSstefano_zampini PetscInt vv = jj[k]; 10674e64d54eSstefano_zampini if (PetscBTLookup(btv, vv) && !PetscBTLookupSet(btvc, vv)) { 1068467446fbSPierre Jolivet PetscCheck(found != 2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Found more than two corners for edge %" PetscInt_FMT, i); 1069b03ebc13SStefano Zampini corners[i * 2 + found++] = vv; 10704e64d54eSstefano_zampini } 10714e64d54eSstefano_zampini } 10724e64d54eSstefano_zampini } 1073b03ebc13SStefano Zampini if (found != 2) { 1074b03ebc13SStefano Zampini PetscInt e; 1075b03ebc13SStefano Zampini if (fl2g) { 10769566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(fl2g, 1, idxs, &e)); 1077b03ebc13SStefano Zampini } else { 1078b03ebc13SStefano Zampini e = idxs[0]; 1079b03ebc13SStefano Zampini } 108063a3b9bcSJacob 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]); 1081b03ebc13SStefano Zampini } 1082eee23b56SStefano Zampini 1083eee23b56SStefano Zampini /* get primal dof index on this coarse edge */ 10849566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(vl2g, 2, corners + 2 * i, gc)); 1085b03ebc13SStefano Zampini if (gc[0] > gc[1]) { 1086b03ebc13SStefano Zampini PetscInt swap = corners[2 * i]; 1087b03ebc13SStefano Zampini corners[2 * i] = corners[2 * i + 1]; 1088b03ebc13SStefano Zampini corners[2 * i + 1] = swap; 1089b03ebc13SStefano Zampini } 1090eee23b56SStefano Zampini cedges[i] = idxs[size - 1]; 10919566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &idxs)); 10923ba16761SJacob 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])); 10934e64d54eSstefano_zampini } 10949566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lG, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 10959566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btvc)); 10964e64d54eSstefano_zampini 109776bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 1098a13144ffSStefano Zampini /* Inspects columns of lG (rows of lGt) and make sure the change of basis will 1099a13144ffSStefano Zampini not interfere with neighbouring coarse edges */ 11009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nee + 1, &emarks)); 11019566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 1102a13144ffSStefano Zampini for (i = 0; i < nv; i++) { 1103a13144ffSStefano Zampini PetscInt emax = 0, eemax = 0; 1104a13144ffSStefano Zampini 1105a13144ffSStefano Zampini if (ii[i + 1] == ii[i] || PetscBTLookup(btv, i)) continue; 11069566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(emarks, nee + 1)); 1107a13144ffSStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) emarks[marks[jj[j]]]++; 1108a13144ffSStefano Zampini for (j = 1; j < nee + 1; j++) { 1109a13144ffSStefano Zampini if (emax < emarks[j]) { 1110a13144ffSStefano Zampini emax = emarks[j]; 1111a13144ffSStefano Zampini eemax = j; 1112a13144ffSStefano Zampini } 1113a13144ffSStefano Zampini } 1114a13144ffSStefano Zampini /* not relevant for edges */ 1115a13144ffSStefano Zampini if (!eemax) continue; 1116a13144ffSStefano Zampini 1117a13144ffSStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 11187a46b595SBarry 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]); 1119a13144ffSStefano Zampini } 1120a13144ffSStefano Zampini } 11219566063dSJacob Faibussowitsch PetscCall(PetscFree(emarks)); 11229566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 112376bd3646SJed Brown } 1124a13144ffSStefano Zampini 1125a13144ffSStefano Zampini /* Compute extended rows indices for edge blocks of the change of basis */ 11269566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 11279566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetMaxRowNonzeros(lGt, &extmem)); 1128a13144ffSStefano Zampini extmem *= maxsize; 11299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(extmem * nee, &extrow)); 11309566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nee, &extrows)); 11319566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nee, &extrowcum)); 1132a13144ffSStefano Zampini for (i = 0; i < nv; i++) { 1133a13144ffSStefano Zampini PetscInt mark = 0, size, start; 1134213b8bfaSStefano Zampini 1135a13144ffSStefano Zampini if (ii[i + 1] == ii[i] || PetscBTLookup(btv, i)) continue; 1136a13144ffSStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) 11379371c9d4SSatish Balay if (marks[jj[j]] && !mark) mark = marks[jj[j]]; 1138a13144ffSStefano Zampini 1139a13144ffSStefano Zampini /* not relevant */ 1140a13144ffSStefano Zampini if (!mark) continue; 1141a13144ffSStefano Zampini 1142a13144ffSStefano Zampini /* import extended row */ 1143a13144ffSStefano Zampini mark--; 1144a13144ffSStefano Zampini start = mark * extmem + extrowcum[mark]; 1145a13144ffSStefano Zampini size = ii[i + 1] - ii[i]; 114663a3b9bcSJacob Faibussowitsch PetscCheck(extrowcum[mark] + size <= extmem, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Not enough memory allocated %" PetscInt_FMT " > %" PetscInt_FMT, extrowcum[mark] + size, extmem); 11479566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(extrow + start, jj + ii[i], size)); 1148a13144ffSStefano Zampini extrowcum[mark] += size; 1149a13144ffSStefano Zampini } 11509566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(lGt, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &done)); 11519566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lGt)); 11529566063dSJacob Faibussowitsch PetscCall(PetscFree(marks)); 1153213b8bfaSStefano Zampini 1154213b8bfaSStefano Zampini /* Compress extrows */ 1155a13144ffSStefano Zampini cum = 0; 1156a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 1157a13144ffSStefano Zampini PetscInt size = extrowcum[i], *start = extrow + i * extmem; 11589566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&size, start)); 11599566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, size, start, PETSC_USE_POINTER, &extrows[i])); 1160a13144ffSStefano Zampini cum = PetscMax(cum, size); 1161a13144ffSStefano Zampini } 11629566063dSJacob Faibussowitsch PetscCall(PetscFree(extrowcum)); 11639566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btv)); 11649566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btvcand)); 1165a13144ffSStefano Zampini 1166a13144ffSStefano Zampini /* Workspace for lapack inner calls and VecSetValues */ 11679566063dSJacob Faibussowitsch PetscCall(PetscMalloc2((5 + cum + maxsize) * maxsize, &work, maxsize, &rwork)); 1168a13144ffSStefano Zampini 1169a13144ffSStefano Zampini /* Create change of basis matrix (preallocation can be improved) */ 11709566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &T)); 1171d0609cedSBarry Smith PetscCall(MatSetSizes(T, pc->pmat->rmap->n, pc->pmat->rmap->n, pc->pmat->rmap->N, pc->pmat->rmap->N)); 11729566063dSJacob Faibussowitsch PetscCall(MatSetType(T, MATAIJ)); 11739566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(T, 10, NULL)); 11749566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(T, 10, NULL, 10, NULL)); 11759566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(T, al2g, al2g)); 11769566063dSJacob Faibussowitsch PetscCall(MatSetOption(T, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 11779566063dSJacob Faibussowitsch PetscCall(MatSetOption(T, MAT_ROW_ORIENTED, PETSC_FALSE)); 11789566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&al2g)); 1179a13144ffSStefano Zampini 1180a13144ffSStefano Zampini /* Defaults to identity */ 11819566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(pc->pmat, &tvec, NULL)); 11829566063dSJacob Faibussowitsch PetscCall(VecSet(tvec, 1.0)); 11839566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(T, tvec, INSERT_VALUES)); 11849566063dSJacob Faibussowitsch PetscCall(VecDestroy(&tvec)); 1185a13144ffSStefano Zampini 11861e0482f5SStefano Zampini /* Create discrete gradient for the coarser level if needed */ 11879566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->nedcG)); 11889566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->nedclocal)); 11891e0482f5SStefano Zampini if (pcbddc->current_level < pcbddc->max_levels) { 11901e0482f5SStefano Zampini ISLocalToGlobalMapping cel2g, cvl2g; 11911e0482f5SStefano Zampini IS wis, gwis; 11921e0482f5SStefano Zampini PetscInt cnv, cne; 11931e0482f5SStefano Zampini 11949566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, nee, cedges, PETSC_COPY_VALUES, &wis)); 11951e0482f5SStefano Zampini if (fl2g) { 11969566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(fl2g, wis, &pcbddc->nedclocal)); 11971e0482f5SStefano Zampini } else { 11989566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)wis)); 11991e0482f5SStefano Zampini pcbddc->nedclocal = wis; 12001e0482f5SStefano Zampini } 12019566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(el2g, wis, &gwis)); 12029566063dSJacob Faibussowitsch PetscCall(ISDestroy(&wis)); 12039566063dSJacob Faibussowitsch PetscCall(ISRenumber(gwis, NULL, &cne, &wis)); 12049566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(wis, &cel2g)); 12059566063dSJacob Faibussowitsch PetscCall(ISDestroy(&wis)); 12069566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gwis)); 12071e0482f5SStefano Zampini 12089566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, 2 * nee, corners, PETSC_USE_POINTER, &wis)); 12099566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(vl2g, wis, &gwis)); 12109566063dSJacob Faibussowitsch PetscCall(ISDestroy(&wis)); 12119566063dSJacob Faibussowitsch PetscCall(ISRenumber(gwis, NULL, &cnv, &wis)); 12129566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(wis, &cvl2g)); 12139566063dSJacob Faibussowitsch PetscCall(ISDestroy(&wis)); 12149566063dSJacob Faibussowitsch PetscCall(ISDestroy(&gwis)); 12151e0482f5SStefano Zampini 12169566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &pcbddc->nedcG)); 12179566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->nedcG, PETSC_DECIDE, PETSC_DECIDE, cne, cnv)); 12189566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->nedcG, MATAIJ)); 12199566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(pcbddc->nedcG, 2, NULL)); 12209566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(pcbddc->nedcG, 2, NULL, 2, NULL)); 12219566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(pcbddc->nedcG, cel2g, cvl2g)); 12229566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cel2g)); 12239566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cvl2g)); 12241e0482f5SStefano Zampini } 12259566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&vl2g)); 12261e0482f5SStefano Zampini 12271e0482f5SStefano Zampini #if defined(PRINT_GDET) 12281e0482f5SStefano Zampini inc = 0; 12291e0482f5SStefano Zampini lev = pcbddc->current_level; 12301e0482f5SStefano Zampini #endif 1231213b8bfaSStefano Zampini 1232213b8bfaSStefano Zampini /* Insert values in the change of basis matrix */ 1233a13144ffSStefano Zampini for (i = 0; i < nee; i++) { 1234a13144ffSStefano Zampini Mat Gins = NULL, GKins = NULL; 12351e0482f5SStefano Zampini IS cornersis = NULL; 12361e0482f5SStefano Zampini PetscScalar cvals[2]; 1237a13144ffSStefano Zampini 123848a46eb9SPierre Jolivet if (pcbddc->nedcG) PetscCall(ISCreateGeneral(PETSC_COMM_SELF, 2, corners + 2 * i, PETSC_USE_POINTER, &cornersis)); 12399566063dSJacob Faibussowitsch PetscCall(PCBDDCComputeNedelecChangeEdge(lG, eedges[i], extrows[i], extcols[i], cornersis, &Gins, &GKins, cvals, work, rwork)); 1240a13144ffSStefano Zampini if (Gins && GKins) { 12411683a169SBarry Smith const PetscScalar *data; 1242a13144ffSStefano Zampini const PetscInt *rows, *cols; 1243a13144ffSStefano Zampini PetscInt nrh, nch, nrc, ncc; 1244a13144ffSStefano Zampini 12459566063dSJacob Faibussowitsch PetscCall(ISGetIndices(eedges[i], &cols)); 1246a13144ffSStefano Zampini /* H1 */ 12479566063dSJacob Faibussowitsch PetscCall(ISGetIndices(extrows[i], &rows)); 12489566063dSJacob Faibussowitsch PetscCall(MatGetSize(Gins, &nrh, &nch)); 12499566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(Gins, &data)); 12509566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(T, nrh, rows, nch, cols, data, INSERT_VALUES)); 12519566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(Gins, &data)); 12529566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(extrows[i], &rows)); 1253a13144ffSStefano Zampini /* complement */ 12549566063dSJacob Faibussowitsch PetscCall(MatGetSize(GKins, &nrc, &ncc)); 125563a3b9bcSJacob Faibussowitsch PetscCheck(ncc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Constant function has not been generated for coarse edge %" PetscInt_FMT, i); 125663a3b9bcSJacob 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); 125763a3b9bcSJacob 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); 12589566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(GKins, &data)); 12599566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(T, nrc, cols, ncc, cols + nch, data, INSERT_VALUES)); 12609566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(GKins, &data)); 12611e0482f5SStefano Zampini 12621e0482f5SStefano Zampini /* coarse discrete gradient */ 12631e0482f5SStefano Zampini if (pcbddc->nedcG) { 12641e0482f5SStefano Zampini PetscInt cols[2]; 12651e0482f5SStefano Zampini 12661e0482f5SStefano Zampini cols[0] = 2 * i; 12671e0482f5SStefano Zampini cols[1] = 2 * i + 1; 12689566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(pcbddc->nedcG, 1, &i, 2, cols, cvals, INSERT_VALUES)); 12691e0482f5SStefano Zampini } 12709566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(eedges[i], &cols)); 1271a13144ffSStefano Zampini } 12729566063dSJacob Faibussowitsch PetscCall(ISDestroy(&extrows[i])); 12739566063dSJacob Faibussowitsch PetscCall(ISDestroy(&extcols[i])); 12749566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cornersis)); 12759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Gins)); 12769566063dSJacob Faibussowitsch PetscCall(MatDestroy(&GKins)); 1277a13144ffSStefano Zampini } 12789566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&el2g)); 1279a13144ffSStefano Zampini 1280a13144ffSStefano Zampini /* Start assembling */ 12819566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(T, MAT_FINAL_ASSEMBLY)); 12821baa6e33SBarry Smith if (pcbddc->nedcG) PetscCall(MatAssemblyBegin(pcbddc->nedcG, MAT_FINAL_ASSEMBLY)); 1283a13144ffSStefano Zampini 1284a13144ffSStefano Zampini /* Free */ 1285c2151214SStefano Zampini if (fl2g) { 12869566063dSJacob Faibussowitsch PetscCall(ISDestroy(&primals)); 128748a46eb9SPierre Jolivet for (i = 0; i < nee; i++) PetscCall(ISDestroy(&eedges[i])); 12889566063dSJacob Faibussowitsch PetscCall(PetscFree(eedges)); 1289c2151214SStefano Zampini } 1290eee23b56SStefano Zampini 1291eee23b56SStefano Zampini /* hack mat_graph with primal dofs on the coarse edges */ 1292eee23b56SStefano Zampini { 1293eee23b56SStefano Zampini PCBDDCGraph graph = pcbddc->mat_graph; 1294eee23b56SStefano Zampini PetscInt *oqueue = graph->queue; 1295eee23b56SStefano Zampini PetscInt *ocptr = graph->cptr; 1296eee23b56SStefano Zampini PetscInt ncc, *idxs; 1297eee23b56SStefano Zampini 1298eee23b56SStefano Zampini /* find first primal edge */ 1299eee23b56SStefano Zampini if (pcbddc->nedclocal) { 13009566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->nedclocal, (const PetscInt **)&idxs)); 1301eee23b56SStefano Zampini } else { 13021baa6e33SBarry Smith if (fl2g) PetscCall(ISLocalToGlobalMappingApply(fl2g, nee, cedges, cedges)); 1303eee23b56SStefano Zampini idxs = cedges; 1304eee23b56SStefano Zampini } 1305eee23b56SStefano Zampini cum = 0; 1306eee23b56SStefano Zampini while (cum < nee && cedges[cum] < 0) cum++; 1307eee23b56SStefano Zampini 1308eee23b56SStefano Zampini /* adapt connected components */ 13099566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(graph->nvtxs + 1, &graph->cptr, ocptr[graph->ncc], &graph->queue)); 1310eee23b56SStefano Zampini graph->cptr[0] = 0; 1311eee23b56SStefano Zampini for (i = 0, ncc = 0; i < graph->ncc; i++) { 1312eee23b56SStefano Zampini PetscInt lc = ocptr[i + 1] - ocptr[i]; 1313eee23b56SStefano Zampini if (cum != nee && oqueue[ocptr[i + 1] - 1] == cedges[cum]) { /* this cc has a primal dof */ 1314eee23b56SStefano Zampini graph->cptr[ncc + 1] = graph->cptr[ncc] + 1; 1315eee23b56SStefano Zampini graph->queue[graph->cptr[ncc]] = cedges[cum]; 1316eee23b56SStefano Zampini ncc++; 1317eee23b56SStefano Zampini lc--; 1318eee23b56SStefano Zampini cum++; 1319eee23b56SStefano Zampini while (cum < nee && cedges[cum] < 0) cum++; 1320eee23b56SStefano Zampini } 1321eee23b56SStefano Zampini graph->cptr[ncc + 1] = graph->cptr[ncc] + lc; 1322eee23b56SStefano Zampini for (j = 0; j < lc; j++) graph->queue[graph->cptr[ncc] + j] = oqueue[ocptr[i] + j]; 1323eee23b56SStefano Zampini ncc++; 1324eee23b56SStefano Zampini } 1325eee23b56SStefano Zampini graph->ncc = ncc; 132648a46eb9SPierre Jolivet if (pcbddc->nedclocal) PetscCall(ISRestoreIndices(pcbddc->nedclocal, (const PetscInt **)&idxs)); 13279566063dSJacob Faibussowitsch PetscCall(PetscFree2(ocptr, oqueue)); 1328eee23b56SStefano Zampini } 13299566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&fl2g)); 13309566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, NULL, NULL, &nee, &alleedges, &allprimals)); 13319566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphResetCSR(pcbddc->mat_graph)); 13329566063dSJacob Faibussowitsch PetscCall(MatDestroy(&conn)); 1333eee23b56SStefano Zampini 13349566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nedfieldlocal)); 13359566063dSJacob Faibussowitsch PetscCall(PetscFree(extrow)); 13369566063dSJacob Faibussowitsch PetscCall(PetscFree2(work, rwork)); 13379566063dSJacob Faibussowitsch PetscCall(PetscFree(corners)); 13389566063dSJacob Faibussowitsch PetscCall(PetscFree(cedges)); 13399566063dSJacob Faibussowitsch PetscCall(PetscFree(extrows)); 13409566063dSJacob Faibussowitsch PetscCall(PetscFree(extcols)); 13419566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lG)); 1342a13144ffSStefano Zampini 1343a13144ffSStefano Zampini /* Complete assembling */ 13449566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(T, MAT_FINAL_ASSEMBLY)); 13451e0482f5SStefano Zampini if (pcbddc->nedcG) { 13469566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->nedcG, MAT_FINAL_ASSEMBLY)); 13471e0482f5SStefano Zampini #if 0 13489566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)pcbddc->nedcG,"coarse_G")); 13499566063dSJacob Faibussowitsch PetscCall(MatView(pcbddc->nedcG,NULL)); 13501e0482f5SStefano Zampini #endif 13511e0482f5SStefano Zampini } 1352a13144ffSStefano Zampini 1353a13144ffSStefano Zampini /* set change of basis */ 13549566063dSJacob Faibussowitsch PetscCall(PCBDDCSetChangeOfBasisMat(pc, T, singular)); 13559566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 13563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1357a13144ffSStefano Zampini } 1358a13144ffSStefano Zampini 1359d8203eabSStefano Zampini /* the near-null space of BDDC carries information on quadrature weights, 1360d8203eabSStefano Zampini and these can be collinear -> so cheat with MatNullSpaceCreate 1361d8203eabSStefano Zampini and create a suitable set of basis vectors first */ 1362d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCNullSpaceCreate(MPI_Comm comm, PetscBool has_const, PetscInt nvecs, Vec quad_vecs[], MatNullSpace *nnsp) 1363d71ae5a4SJacob Faibussowitsch { 1364d8203eabSStefano Zampini PetscInt i; 1365d8203eabSStefano Zampini 1366d8203eabSStefano Zampini PetscFunctionBegin; 1367d8203eabSStefano Zampini for (i = 0; i < nvecs; i++) { 1368d8203eabSStefano Zampini PetscInt first, last; 1369d8203eabSStefano Zampini 13709566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(quad_vecs[i], &first, &last)); 13717827d75bSBarry Smith PetscCheck(last - first >= 2 * nvecs || !has_const, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented"); 1372d8203eabSStefano Zampini if (i >= first && i < last) { 1373d8203eabSStefano Zampini PetscScalar *data; 13749566063dSJacob Faibussowitsch PetscCall(VecGetArray(quad_vecs[i], &data)); 1375d8203eabSStefano Zampini if (!has_const) { 1376d8203eabSStefano Zampini data[i - first] = 1.; 1377d8203eabSStefano Zampini } else { 137886fa73c5SStefano Zampini data[2 * i - first] = 1. / PetscSqrtReal(2.); 137986fa73c5SStefano Zampini data[2 * i - first + 1] = -1. / PetscSqrtReal(2.); 1380d8203eabSStefano Zampini } 13819566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(quad_vecs[i], &data)); 1382d8203eabSStefano Zampini } 13839566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)quad_vecs[i])); 1384d8203eabSStefano Zampini } 13859566063dSJacob Faibussowitsch PetscCall(MatNullSpaceCreate(comm, has_const, nvecs, quad_vecs, nnsp)); 1386d8203eabSStefano Zampini for (i = 0; i < nvecs; i++) { /* reset vectors */ 1387d8203eabSStefano Zampini PetscInt first, last; 13889566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(quad_vecs[i])); 13899566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(quad_vecs[i], &first, &last)); 1390d8203eabSStefano Zampini if (i >= first && i < last) { 1391d8203eabSStefano Zampini PetscScalar *data; 13929566063dSJacob Faibussowitsch PetscCall(VecGetArray(quad_vecs[i], &data)); 1393d8203eabSStefano Zampini if (!has_const) { 1394d8203eabSStefano Zampini data[i - first] = 0.; 1395d8203eabSStefano Zampini } else { 139686fa73c5SStefano Zampini data[2 * i - first] = 0.; 139786fa73c5SStefano Zampini data[2 * i - first + 1] = 0.; 1398d8203eabSStefano Zampini } 13999566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(quad_vecs[i], &data)); 1400d8203eabSStefano Zampini } 14019566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)quad_vecs[i])); 14029566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(quad_vecs[i])); 1403d8203eabSStefano Zampini } 14043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1405d8203eabSStefano Zampini } 1406d8203eabSStefano Zampini 1407d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCComputeNoNetFlux(Mat A, Mat divudotp, PetscBool transpose, IS vl2l, PCBDDCGraph graph, MatNullSpace *nnsp) 1408d71ae5a4SJacob Faibussowitsch { 1409a198735bSStefano Zampini Mat loc_divudotp; 1410fa23a32eSStefano Zampini Vec p, v, vins, quad_vec, *quad_vecs; 14118ae0ca82SStefano Zampini ISLocalToGlobalMapping map; 1412669cc0f4SStefano Zampini PetscScalar *vals; 1413669cc0f4SStefano Zampini const PetscScalar *array; 14140f04eeffSStefano Zampini PetscInt i, maxneighs = 0, maxsize, *gidxs; 1415a040e873SStefano Zampini PetscInt n_neigh, *neigh, *n_shared, **shared; 14161ae86dd6SStefano Zampini PetscMPIInt rank; 1417669cc0f4SStefano Zampini 1418669cc0f4SStefano Zampini PetscFunctionBegin; 14199566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetInfo(graph->l2gmap, &n_neigh, &neigh, &n_shared, &shared)); 14200f04eeffSStefano Zampini for (i = 0; i < n_neigh; i++) maxneighs = PetscMax(graph->count[shared[i][0]] + 1, maxneighs); 14211c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(MPI_IN_PLACE, &maxneighs, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)A))); 14228037d520SStefano Zampini if (!maxneighs) { 14239566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreInfo(graph->l2gmap, &n_neigh, &neigh, &n_shared, &shared)); 14248037d520SStefano Zampini *nnsp = NULL; 14253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1426669cc0f4SStefano Zampini } 1427669cc0f4SStefano Zampini maxsize = 0; 1428a040e873SStefano Zampini for (i = 0; i < n_neigh; i++) maxsize = PetscMax(n_shared[i], maxsize); 14299566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(maxsize, &gidxs, maxsize, &vals)); 1430669cc0f4SStefano Zampini /* create vectors to hold quadrature weights */ 14319566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, &quad_vec, NULL)); 14328ae0ca82SStefano Zampini if (!transpose) { 14339566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(A, &map, NULL)); 14348ae0ca82SStefano Zampini } else { 14359566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(A, NULL, &map)); 14368ae0ca82SStefano Zampini } 14379566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(quad_vec, maxneighs, &quad_vecs)); 14389566063dSJacob Faibussowitsch PetscCall(VecDestroy(&quad_vec)); 14399566063dSJacob Faibussowitsch PetscCall(PCBDDCNullSpaceCreate(PetscObjectComm((PetscObject)A), PETSC_FALSE, maxneighs, quad_vecs, nnsp)); 144048a46eb9SPierre Jolivet for (i = 0; i < maxneighs; i++) PetscCall(VecLockReadPop(quad_vecs[i])); 1441d8203eabSStefano Zampini 1442669cc0f4SStefano Zampini /* compute local quad vec */ 14439566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(divudotp, &loc_divudotp)); 14448ae0ca82SStefano Zampini if (!transpose) { 14459566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(loc_divudotp, &v, &p)); 14468ae0ca82SStefano Zampini } else { 14479566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(loc_divudotp, &p, &v)); 14488ae0ca82SStefano Zampini } 14499566063dSJacob Faibussowitsch PetscCall(VecSet(p, 1.)); 14508ae0ca82SStefano Zampini if (!transpose) { 14519566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(loc_divudotp, p, v)); 14528ae0ca82SStefano Zampini } else { 14539566063dSJacob Faibussowitsch PetscCall(MatMult(loc_divudotp, p, v)); 14548ae0ca82SStefano Zampini } 1455fa23a32eSStefano Zampini if (vl2l) { 1456187c917aSStefano Zampini Mat lA; 1457187c917aSStefano Zampini VecScatter sc; 1458187c917aSStefano Zampini 14599566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A, &lA)); 14609566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(lA, &vins, NULL)); 14619566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(v, NULL, vins, vl2l, &sc)); 14629566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sc, v, vins, INSERT_VALUES, SCATTER_FORWARD)); 14639566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sc, v, vins, INSERT_VALUES, SCATTER_FORWARD)); 14649566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sc)); 1465fa23a32eSStefano Zampini } else { 1466fa23a32eSStefano Zampini vins = v; 1467fa23a32eSStefano Zampini } 14689566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vins, &array)); 14699566063dSJacob Faibussowitsch PetscCall(VecDestroy(&p)); 14709a962809SStefano Zampini 14711ae86dd6SStefano Zampini /* insert in global quadrature vecs */ 14729566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank)); 14730f04eeffSStefano Zampini for (i = 1; i < n_neigh; i++) { 1474669cc0f4SStefano Zampini const PetscInt *idxs; 1475669cc0f4SStefano Zampini PetscInt idx, nn, j; 1476669cc0f4SStefano Zampini 1477a040e873SStefano Zampini idxs = shared[i]; 1478a040e873SStefano Zampini nn = n_shared[i]; 1479669cc0f4SStefano Zampini for (j = 0; j < nn; j++) vals[j] = array[idxs[j]]; 14809566063dSJacob Faibussowitsch PetscCall(PetscFindInt(rank, graph->count[idxs[0]], graph->neighbours_set[idxs[0]], &idx)); 1481669cc0f4SStefano Zampini idx = -(idx + 1); 148263a3b9bcSJacob Faibussowitsch PetscCheck(idx >= 0 && idx < maxneighs, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid index %" PetscInt_FMT " not in [0,%" PetscInt_FMT ")", idx, maxneighs); 14839566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(map, nn, idxs, gidxs)); 14849566063dSJacob Faibussowitsch PetscCall(VecSetValues(quad_vecs[idx], nn, gidxs, vals, INSERT_VALUES)); 1485669cc0f4SStefano Zampini } 14869566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreInfo(graph->l2gmap, &n_neigh, &neigh, &n_shared, &shared)); 14879566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vins, &array)); 148848a46eb9SPierre Jolivet if (vl2l) PetscCall(VecDestroy(&vins)); 14899566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 14909566063dSJacob Faibussowitsch PetscCall(PetscFree2(gidxs, vals)); 1491669cc0f4SStefano Zampini 1492669cc0f4SStefano Zampini /* assemble near null space */ 149348a46eb9SPierre Jolivet for (i = 0; i < maxneighs; i++) PetscCall(VecAssemblyBegin(quad_vecs[i])); 1494669cc0f4SStefano Zampini for (i = 0; i < maxneighs; i++) { 14959566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(quad_vecs[i])); 14969566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(quad_vecs[i], NULL, "-pc_bddc_quad_vecs_view")); 14979566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(quad_vecs[i])); 1498669cc0f4SStefano Zampini } 14999566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(maxneighs, &quad_vecs)); 15003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1501669cc0f4SStefano Zampini } 1502669cc0f4SStefano Zampini 1503d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCAddPrimalVerticesLocalIS(PC pc, IS primalv) 1504d71ae5a4SJacob Faibussowitsch { 15057620a527SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 15067620a527SStefano Zampini 15077620a527SStefano Zampini PetscFunctionBegin; 15087620a527SStefano Zampini if (primalv) { 15097620a527SStefano Zampini if (pcbddc->user_primal_vertices_local) { 15107620a527SStefano Zampini IS list[2], newp; 15117620a527SStefano Zampini 15127620a527SStefano Zampini list[0] = primalv; 15137620a527SStefano Zampini list[1] = pcbddc->user_primal_vertices_local; 15149566063dSJacob Faibussowitsch PetscCall(ISConcatenate(PetscObjectComm((PetscObject)pc), 2, list, &newp)); 15159566063dSJacob Faibussowitsch PetscCall(ISSortRemoveDups(newp)); 15169566063dSJacob Faibussowitsch PetscCall(ISDestroy(&list[1])); 15177620a527SStefano Zampini pcbddc->user_primal_vertices_local = newp; 15187620a527SStefano Zampini } else { 15199566063dSJacob Faibussowitsch PetscCall(PCBDDCSetPrimalVerticesLocalIS(pc, primalv)); 15207620a527SStefano Zampini } 15217620a527SStefano Zampini } 15223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15237620a527SStefano Zampini } 1524669cc0f4SStefano Zampini 1525d71ae5a4SJacob Faibussowitsch static PetscErrorCode func_coords_private(PetscInt dim, PetscReal t, const PetscReal X[], PetscInt Nf, PetscScalar *out, void *ctx) 1526d71ae5a4SJacob Faibussowitsch { 15271c7a958bSStefano Zampini PetscInt f, *comp = (PetscInt *)ctx; 15281c7a958bSStefano Zampini 15291c7a958bSStefano Zampini PetscFunctionBegin; 15301c7a958bSStefano Zampini for (f = 0; f < Nf; f++) out[f] = X[*comp]; 15313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15321c7a958bSStefano Zampini } 1533674ae819SStefano Zampini 1534d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCComputeLocalTopologyInfo(PC pc) 1535d71ae5a4SJacob Faibussowitsch { 15361f4df5f7SStefano Zampini Vec local, global; 15371f4df5f7SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 15381f4df5f7SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 15395c5e10d6SStefano Zampini PetscBool monolithic = PETSC_FALSE; 15401f4df5f7SStefano Zampini 15411f4df5f7SStefano Zampini PetscFunctionBegin; 1542d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)pc), ((PetscObject)pc)->prefix, "BDDC topology options", "PC"); 15439566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_monolithic", "Discard any information on dofs splitting", NULL, monolithic, &monolithic, NULL)); 1544d0609cedSBarry Smith PetscOptionsEnd(); 15451f4df5f7SStefano Zampini /* need to convert from global to local topology information and remove references to information in global ordering */ 15469566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(pc->pmat, &global, NULL)); 15479566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(matis->A, &local, NULL)); 15489566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(global, PETSC_TRUE)); 15499566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(local, PETSC_TRUE)); 15506a8fc67bSStefano Zampini if (monolithic) { /* just get block size to properly compute vertices */ 155148a46eb9SPierre Jolivet if (pcbddc->vertex_size == 1) PetscCall(MatGetBlockSize(pc->pmat, &pcbddc->vertex_size)); 15526a8fc67bSStefano Zampini goto boundary; 15536a8fc67bSStefano Zampini } 15545c5e10d6SStefano Zampini 15551f4df5f7SStefano Zampini if (pcbddc->user_provided_isfordofs) { 15561f4df5f7SStefano Zampini if (pcbddc->n_ISForDofs) { 15571f4df5f7SStefano Zampini PetscInt i; 15580c85b387SStefano Zampini 15599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->n_ISForDofs, &pcbddc->ISForDofsLocal)); 15601f4df5f7SStefano Zampini for (i = 0; i < pcbddc->n_ISForDofs; i++) { 15610c85b387SStefano Zampini PetscInt bs; 15620c85b387SStefano Zampini 15639566063dSJacob Faibussowitsch PetscCall(PCBDDCGlobalToLocal(matis->rctx, global, local, pcbddc->ISForDofs[i], &pcbddc->ISForDofsLocal[i])); 15649566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(pcbddc->ISForDofs[i], &bs)); 15659566063dSJacob Faibussowitsch PetscCall(ISSetBlockSize(pcbddc->ISForDofsLocal[i], bs)); 15669566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->ISForDofs[i])); 15671f4df5f7SStefano Zampini } 15681f4df5f7SStefano Zampini pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs; 15691f4df5f7SStefano Zampini pcbddc->n_ISForDofs = 0; 15709566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->ISForDofs)); 15711f4df5f7SStefano Zampini } 15721f4df5f7SStefano Zampini } else { 157321ef3d20SStefano Zampini if (!pcbddc->n_ISForDofsLocal) { /* field split not present */ 157421ef3d20SStefano Zampini DM dm; 157521ef3d20SStefano Zampini 15769566063dSJacob Faibussowitsch PetscCall(MatGetDM(pc->pmat, &dm)); 157748a46eb9SPierre Jolivet if (!dm) PetscCall(PCGetDM(pc, &dm)); 157821ef3d20SStefano Zampini if (dm) { 157921ef3d20SStefano Zampini IS *fields; 158021ef3d20SStefano Zampini PetscInt nf, i; 15810c85b387SStefano Zampini 15829566063dSJacob Faibussowitsch PetscCall(DMCreateFieldDecomposition(dm, &nf, NULL, &fields, NULL)); 15839566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nf, &pcbddc->ISForDofsLocal)); 158421ef3d20SStefano Zampini for (i = 0; i < nf; i++) { 15850c85b387SStefano Zampini PetscInt bs; 15860c85b387SStefano Zampini 15879566063dSJacob Faibussowitsch PetscCall(PCBDDCGlobalToLocal(matis->rctx, global, local, fields[i], &pcbddc->ISForDofsLocal[i])); 15889566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(fields[i], &bs)); 15899566063dSJacob Faibussowitsch PetscCall(ISSetBlockSize(pcbddc->ISForDofsLocal[i], bs)); 15909566063dSJacob Faibussowitsch PetscCall(ISDestroy(&fields[i])); 159121ef3d20SStefano Zampini } 15929566063dSJacob Faibussowitsch PetscCall(PetscFree(fields)); 159321ef3d20SStefano Zampini pcbddc->n_ISForDofsLocal = nf; 159421ef3d20SStefano Zampini } else { /* See if MATIS has fields attached by the conversion from MatNest */ 159521ef3d20SStefano Zampini PetscContainer c; 159621ef3d20SStefano Zampini 15979566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc->pmat, "_convert_nest_lfields", (PetscObject *)&c)); 159821ef3d20SStefano Zampini if (c) { 159921ef3d20SStefano Zampini MatISLocalFields lf; 16009566063dSJacob Faibussowitsch PetscCall(PetscContainerGetPointer(c, (void **)&lf)); 16019566063dSJacob Faibussowitsch PetscCall(PCBDDCSetDofsSplittingLocal(pc, lf->nr, lf->rf)); 160221ef3d20SStefano Zampini } else { /* fallback, create the default fields if bs > 1 */ 16031f4df5f7SStefano Zampini PetscInt i, n = matis->A->rmap->n; 16049566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(pc->pmat, &i)); 160521ef3d20SStefano Zampini if (i > 1) { 1606986cdee1SStefano Zampini pcbddc->n_ISForDofsLocal = i; 16079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->n_ISForDofsLocal, &pcbddc->ISForDofsLocal)); 160848a46eb9SPierre 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])); 16091f4df5f7SStefano Zampini } 161021ef3d20SStefano Zampini } 161121ef3d20SStefano Zampini } 16127a0e7b2cSstefano_zampini } else { 16137a0e7b2cSstefano_zampini PetscInt i; 161448a46eb9SPierre Jolivet for (i = 0; i < pcbddc->n_ISForDofsLocal; i++) PetscCall(PCBDDCConsistencyCheckIS(pc, MPI_LAND, &pcbddc->ISForDofsLocal[i])); 16151f4df5f7SStefano Zampini } 1616986cdee1SStefano Zampini } 16171f4df5f7SStefano Zampini 16185c5e10d6SStefano Zampini boundary: 16191f4df5f7SStefano Zampini if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) { 16209566063dSJacob Faibussowitsch PetscCall(PCBDDCGlobalToLocal(matis->rctx, global, local, pcbddc->DirichletBoundaries, &pcbddc->DirichletBoundariesLocal)); 16217a0e7b2cSstefano_zampini } else if (pcbddc->DirichletBoundariesLocal) { 16229566063dSJacob Faibussowitsch PetscCall(PCBDDCConsistencyCheckIS(pc, MPI_LAND, &pcbddc->DirichletBoundariesLocal)); 16231f4df5f7SStefano Zampini } 16241f4df5f7SStefano Zampini if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) { 16259566063dSJacob Faibussowitsch PetscCall(PCBDDCGlobalToLocal(matis->rctx, global, local, pcbddc->NeumannBoundaries, &pcbddc->NeumannBoundariesLocal)); 16267a0e7b2cSstefano_zampini } else if (pcbddc->NeumannBoundariesLocal) { 16279566063dSJacob Faibussowitsch PetscCall(PCBDDCConsistencyCheckIS(pc, MPI_LOR, &pcbddc->NeumannBoundariesLocal)); 16281f4df5f7SStefano Zampini } 162948a46eb9SPierre 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)); 16309566063dSJacob Faibussowitsch PetscCall(VecDestroy(&global)); 16319566063dSJacob Faibussowitsch PetscCall(VecDestroy(&local)); 16327620a527SStefano Zampini /* detect local disconnected subdomains if requested (use matis->A) */ 16337620a527SStefano Zampini if (pcbddc->detect_disconnected) { 16347620a527SStefano Zampini IS primalv = NULL; 16357620a527SStefano Zampini PetscInt i; 16368361f951SStefano Zampini PetscBool filter = pcbddc->detect_disconnected_filter; 16377a0e7b2cSstefano_zampini 163848a46eb9SPierre Jolivet for (i = 0; i < pcbddc->n_local_subs; i++) PetscCall(ISDestroy(&pcbddc->local_subs[i])); 16399566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->local_subs)); 16409566063dSJacob Faibussowitsch PetscCall(PCBDDCDetectDisconnectedComponents(pc, filter, &pcbddc->n_local_subs, &pcbddc->local_subs, &primalv)); 16419566063dSJacob Faibussowitsch PetscCall(PCBDDCAddPrimalVerticesLocalIS(pc, primalv)); 16429566063dSJacob Faibussowitsch PetscCall(ISDestroy(&primalv)); 16437620a527SStefano Zampini } 16447620a527SStefano Zampini /* early stage corner detection */ 16457620a527SStefano Zampini { 16467620a527SStefano Zampini DM dm; 16477620a527SStefano Zampini 16489566063dSJacob Faibussowitsch PetscCall(MatGetDM(pc->pmat, &dm)); 164948a46eb9SPierre Jolivet if (!dm) PetscCall(PCGetDM(pc, &dm)); 16507620a527SStefano Zampini if (dm) { 16517620a527SStefano Zampini PetscBool isda; 16527620a527SStefano Zampini 16539566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMDA, &isda)); 16547620a527SStefano Zampini if (isda) { 16557620a527SStefano Zampini ISLocalToGlobalMapping l2l; 16567620a527SStefano Zampini IS corners; 16577620a527SStefano Zampini Mat lA; 16584f819b78SStefano Zampini PetscBool gl, lo; 16597620a527SStefano Zampini 16604f819b78SStefano Zampini { 16614f819b78SStefano Zampini Vec cvec; 16624f819b78SStefano Zampini const PetscScalar *coords; 16634f819b78SStefano Zampini PetscInt dof, n, cdim; 16644f819b78SStefano Zampini PetscBool memc = PETSC_TRUE; 16654f819b78SStefano Zampini 16669566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL)); 16679566063dSJacob Faibussowitsch PetscCall(DMGetCoordinates(dm, &cvec)); 16689566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(cvec, &n)); 16699566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(cvec, &cdim)); 16704f819b78SStefano Zampini n /= cdim; 16719566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->mat_graph->coords)); 16729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dof * n * cdim, &pcbddc->mat_graph->coords)); 16739566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(cvec, &coords)); 16744f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX) 16754f819b78SStefano Zampini memc = PETSC_FALSE; 16764f819b78SStefano Zampini #endif 16774f819b78SStefano Zampini if (dof != 1) memc = PETSC_FALSE; 16784f819b78SStefano Zampini if (memc) { 16799566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pcbddc->mat_graph->coords, coords, cdim * n * dof)); 16804f819b78SStefano Zampini } else { /* BDDC graph does not use any blocked information, we need to replicate the data */ 16814f819b78SStefano Zampini PetscReal *bcoords = pcbddc->mat_graph->coords; 16824f819b78SStefano Zampini PetscInt i, b, d; 16834f819b78SStefano Zampini 16844f819b78SStefano Zampini for (i = 0; i < n; i++) { 16854f819b78SStefano Zampini for (b = 0; b < dof; b++) { 1686ad540459SPierre Jolivet for (d = 0; d < cdim; d++) bcoords[i * dof * cdim + b * cdim + d] = PetscRealPart(coords[i * cdim + d]); 16874f819b78SStefano Zampini } 16884f819b78SStefano Zampini } 16894f819b78SStefano Zampini } 16909566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(cvec, &coords)); 16914f819b78SStefano Zampini pcbddc->mat_graph->cdim = cdim; 16924f819b78SStefano Zampini pcbddc->mat_graph->cnloc = dof * n; 16934f819b78SStefano Zampini pcbddc->mat_graph->cloc = PETSC_FALSE; 16944f819b78SStefano Zampini } 16959566063dSJacob Faibussowitsch PetscCall(DMDAGetSubdomainCornersIS(dm, &corners)); 16969566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->pmat, &lA)); 16979566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(lA, &l2l, NULL)); 16989566063dSJacob Faibussowitsch PetscCall(MatISRestoreLocalMat(pc->pmat, &lA)); 16994f819b78SStefano Zampini lo = (PetscBool)(l2l && corners); 17001c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&lo, &gl, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)pc))); 17014f819b78SStefano Zampini if (gl) { /* From PETSc's DMDA */ 17027620a527SStefano Zampini const PetscInt *idx; 170372ed36d8SStefano Zampini PetscInt dof, bs, *idxout, n; 17047620a527SStefano Zampini 17059566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(dm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL)); 17069566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(l2l, &bs)); 17079566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(corners, &n)); 17089566063dSJacob Faibussowitsch PetscCall(ISGetIndices(corners, &idx)); 170972ed36d8SStefano Zampini if (bs == dof) { 17109566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &idxout)); 17119566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(l2l, n, idx, idxout)); 171272ed36d8SStefano Zampini } else { /* the original DMDA local-to-local map have been modified */ 171372ed36d8SStefano Zampini PetscInt i, d; 171472ed36d8SStefano Zampini 17159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dof * n, &idxout)); 17169371c9d4SSatish Balay for (i = 0; i < n; i++) 17179371c9d4SSatish Balay for (d = 0; d < dof; d++) idxout[dof * i + d] = dof * idx[i] + d; 17189566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(l2l, dof * n, idxout, idxout)); 171972ed36d8SStefano Zampini 172072ed36d8SStefano Zampini bs = 1; 172172ed36d8SStefano Zampini n *= dof; 172272ed36d8SStefano Zampini } 17239566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(corners, &idx)); 17249566063dSJacob Faibussowitsch PetscCall(DMDARestoreSubdomainCornersIS(dm, &corners)); 17259566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)pc), bs, n, idxout, PETSC_OWN_POINTER, &corners)); 17269566063dSJacob Faibussowitsch PetscCall(PCBDDCAddPrimalVerticesLocalIS(pc, corners)); 17279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&corners)); 17281c7a958bSStefano Zampini pcbddc->corner_selected = PETSC_TRUE; 17294f819b78SStefano Zampini pcbddc->corner_selection = PETSC_TRUE; 17304f819b78SStefano Zampini } 173148a46eb9SPierre Jolivet if (corners) PetscCall(DMDARestoreSubdomainCornersIS(dm, &corners)); 17327620a527SStefano Zampini } 17337620a527SStefano Zampini } 17347620a527SStefano Zampini } 17351c7a958bSStefano Zampini if (pcbddc->corner_selection && !pcbddc->mat_graph->cdim) { 17361c7a958bSStefano Zampini DM dm; 17371c7a958bSStefano Zampini 17389566063dSJacob Faibussowitsch PetscCall(MatGetDM(pc->pmat, &dm)); 173948a46eb9SPierre Jolivet if (!dm) PetscCall(PCGetDM(pc, &dm)); 17404f819b78SStefano Zampini if (dm) { /* this can get very expensive, I need to find a faster alternative */ 17411c7a958bSStefano Zampini Vec vcoords; 17421c7a958bSStefano Zampini PetscSection section; 17431c7a958bSStefano Zampini PetscReal *coords; 17441c7a958bSStefano Zampini PetscInt d, cdim, nl, nf, **ctxs; 17451c7a958bSStefano Zampini PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal *, PetscInt, PetscScalar *, void *); 174651ab8ad6SStefano Zampini /* debug coordinates */ 174751ab8ad6SStefano Zampini PetscViewer viewer; 174851ab8ad6SStefano Zampini PetscBool flg; 174951ab8ad6SStefano Zampini PetscViewerFormat format; 175051ab8ad6SStefano Zampini const char *prefix; 17511c7a958bSStefano Zampini 17529566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 17539566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, §ion)); 17549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(section, &nf)); 17559566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dm, &vcoords)); 17569566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vcoords, &nl)); 17579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl * cdim, &coords)); 17589566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nf, &funcs, nf, &ctxs)); 17599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nf, &ctxs[0])); 17601c7a958bSStefano Zampini for (d = 0; d < nf; d++) funcs[d] = func_coords_private; 17611c7a958bSStefano Zampini for (d = 1; d < nf; d++) ctxs[d] = ctxs[d - 1] + 1; 176251ab8ad6SStefano Zampini 176351ab8ad6SStefano Zampini /* debug coordinates */ 176451ab8ad6SStefano Zampini PetscCall(PCGetOptionsPrefix(pc, &prefix)); 176551ab8ad6SStefano Zampini PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)vcoords), ((PetscObject)vcoords)->options, prefix, "-pc_bddc_coords_vec_view", &viewer, &format, &flg)); 176651ab8ad6SStefano Zampini if (flg) PetscCall(PetscViewerPushFormat(viewer, format)); 17671c7a958bSStefano Zampini for (d = 0; d < cdim; d++) { 17681c7a958bSStefano Zampini PetscInt i; 17691c7a958bSStefano Zampini const PetscScalar *v; 177051ab8ad6SStefano Zampini char name[16]; 17711c7a958bSStefano Zampini 17721c7a958bSStefano Zampini for (i = 0; i < nf; i++) ctxs[i][0] = d; 177351ab8ad6SStefano Zampini PetscCall(PetscSNPrintf(name, sizeof(name), "bddc_coords_%d", (int)d)); 177451ab8ad6SStefano Zampini PetscCall(PetscObjectSetName((PetscObject)vcoords, name)); 17759566063dSJacob Faibussowitsch PetscCall(DMProjectFunction(dm, 0.0, funcs, (void **)ctxs, INSERT_VALUES, vcoords)); 177651ab8ad6SStefano Zampini if (flg) PetscCall(VecView(vcoords, viewer)); 17779566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vcoords, &v)); 17781c7a958bSStefano Zampini for (i = 0; i < nl; i++) coords[i * cdim + d] = PetscRealPart(v[i]); 17799566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vcoords, &v)); 17801c7a958bSStefano Zampini } 17819566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vcoords)); 17829566063dSJacob Faibussowitsch PetscCall(PCSetCoordinates(pc, cdim, nl, coords)); 17839566063dSJacob Faibussowitsch PetscCall(PetscFree(coords)); 17849566063dSJacob Faibussowitsch PetscCall(PetscFree(ctxs[0])); 17859566063dSJacob Faibussowitsch PetscCall(PetscFree2(funcs, ctxs)); 178651ab8ad6SStefano Zampini if (flg) { 178751ab8ad6SStefano Zampini PetscCall(PetscViewerPopFormat(viewer)); 1788cd791dc2SBarry Smith PetscCall(PetscOptionsRestoreViewer(&viewer)); 178951ab8ad6SStefano Zampini } 17901c7a958bSStefano Zampini } 17911c7a958bSStefano Zampini } 17923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17937a0e7b2cSstefano_zampini } 17947a0e7b2cSstefano_zampini 1795d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCConsistencyCheckIS(PC pc, MPI_Op mop, IS *is) 1796d71ae5a4SJacob Faibussowitsch { 1797*f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)pc->pmat->data; 17987a0e7b2cSstefano_zampini IS nis; 17997a0e7b2cSstefano_zampini const PetscInt *idxs; 18007a0e7b2cSstefano_zampini PetscInt i, nd, n = matis->A->rmap->n, *nidxs, nnd; 18017a0e7b2cSstefano_zampini 18027a0e7b2cSstefano_zampini PetscFunctionBegin; 18037827d75bSBarry Smith PetscCheck(mop == MPI_LAND || mop == MPI_LOR, PetscObjectComm((PetscObject)(pc)), PETSC_ERR_SUP, "Supported are MPI_LAND and MPI_LOR"); 18047a0e7b2cSstefano_zampini if (mop == MPI_LAND) { 18057a0e7b2cSstefano_zampini /* init rootdata with true */ 18061bd50df1SStefano Zampini for (i = 0; i < pc->pmat->rmap->n; i++) matis->sf_rootdata[i] = 1; 18077a0e7b2cSstefano_zampini } else { 18089566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_rootdata, pc->pmat->rmap->n)); 18097a0e7b2cSstefano_zampini } 18109566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_leafdata, n)); 18119566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(*is, &nd)); 18129566063dSJacob Faibussowitsch PetscCall(ISGetIndices(*is, &idxs)); 18137a0e7b2cSstefano_zampini for (i = 0; i < nd; i++) 18149371c9d4SSatish Balay if (-1 < idxs[i] && idxs[i] < n) matis->sf_leafdata[idxs[i]] = 1; 18159566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(*is, &idxs)); 18169566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, matis->sf_leafdata, matis->sf_rootdata, mop)); 18179566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, matis->sf_leafdata, matis->sf_rootdata, mop)); 18189566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 18199566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 18207a0e7b2cSstefano_zampini if (mop == MPI_LAND) { 18219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nd, &nidxs)); 18227a0e7b2cSstefano_zampini } else { 18239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &nidxs)); 18247a0e7b2cSstefano_zampini } 18257a0e7b2cSstefano_zampini for (i = 0, nnd = 0; i < n; i++) 18269371c9d4SSatish Balay if (matis->sf_leafdata[i]) nidxs[nnd++] = i; 1827*f4f49eeaSPierre Jolivet PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)*is), nnd, nidxs, PETSC_OWN_POINTER, &nis)); 18289566063dSJacob Faibussowitsch PetscCall(ISDestroy(is)); 18297a0e7b2cSstefano_zampini *is = nis; 18303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18311f4df5f7SStefano Zampini } 18321f4df5f7SStefano Zampini 1833d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignRemoveInterior(PC pc, Vec r, Vec z) 1834d71ae5a4SJacob Faibussowitsch { 1835*f4f49eeaSPierre Jolivet PC_IS *pcis = (PC_IS *)pc->data; 1836*f4f49eeaSPierre Jolivet PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 18373e589ea0SStefano Zampini 18383e589ea0SStefano Zampini PetscFunctionBegin; 18393ba16761SJacob Faibussowitsch if (!pcbddc->benign_have_null) PetscFunctionReturn(PETSC_SUCCESS); 18403e589ea0SStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 18413e589ea0SStefano Zampini Vec swap; 18423e589ea0SStefano Zampini 18439566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, r, pcbddc->work_change)); 18443e589ea0SStefano Zampini swap = pcbddc->work_change; 18453e589ea0SStefano Zampini pcbddc->work_change = r; 18463e589ea0SStefano Zampini r = swap; 18473e589ea0SStefano Zampini } 18489566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 18499566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 18509566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 18519566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D)); 18529566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 18539566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D)); 18549566063dSJacob Faibussowitsch PetscCall(VecSet(z, 0.)); 18559566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE)); 18569566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE)); 18573e589ea0SStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 1858f913dca9SStefano Zampini pcbddc->work_change = r; 18599566063dSJacob Faibussowitsch PetscCall(VecCopy(z, pcbddc->work_change)); 18609566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcbddc->work_change, z)); 18613e589ea0SStefano Zampini } 18623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18633e589ea0SStefano Zampini } 18643e589ea0SStefano Zampini 1865ba38deedSJacob Faibussowitsch static PetscErrorCode PCBDDCBenignMatMult_Private_Private(Mat A, Vec x, Vec y, PetscBool transpose) 1866d71ae5a4SJacob Faibussowitsch { 1867a3df083aSStefano Zampini PCBDDCBenignMatMult_ctx ctx; 1868a3df083aSStefano Zampini PetscBool apply_right, apply_left, reset_x; 1869a3df083aSStefano Zampini 1870a3df083aSStefano Zampini PetscFunctionBegin; 18719566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(A, &ctx)); 1872a3df083aSStefano Zampini if (transpose) { 1873a3df083aSStefano Zampini apply_right = ctx->apply_left; 1874a3df083aSStefano Zampini apply_left = ctx->apply_right; 1875a3df083aSStefano Zampini } else { 1876a3df083aSStefano Zampini apply_right = ctx->apply_right; 1877a3df083aSStefano Zampini apply_left = ctx->apply_left; 1878a3df083aSStefano Zampini } 1879a3df083aSStefano Zampini reset_x = PETSC_FALSE; 1880a3df083aSStefano Zampini if (apply_right) { 1881a3df083aSStefano Zampini const PetscScalar *ax; 1882a3df083aSStefano Zampini PetscInt nl, i; 1883a3df083aSStefano Zampini 18849566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(x, &nl)); 18859566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &ax)); 18869566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(ctx->work, ax, nl)); 18879566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &ax)); 1888a3df083aSStefano Zampini for (i = 0; i < ctx->benign_n; i++) { 1889a3df083aSStefano Zampini PetscScalar sum, val; 1890a3df083aSStefano Zampini const PetscInt *idxs; 1891a3df083aSStefano Zampini PetscInt nz, j; 18929566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(ctx->benign_zerodiag_subs[i], &nz)); 18939566063dSJacob Faibussowitsch PetscCall(ISGetIndices(ctx->benign_zerodiag_subs[i], &idxs)); 1894a3df083aSStefano Zampini sum = 0.; 1895a3df083aSStefano Zampini if (ctx->apply_p0) { 1896a3df083aSStefano Zampini val = ctx->work[idxs[nz - 1]]; 1897a3df083aSStefano Zampini for (j = 0; j < nz - 1; j++) { 1898a3df083aSStefano Zampini sum += ctx->work[idxs[j]]; 1899a3df083aSStefano Zampini ctx->work[idxs[j]] += val; 1900a3df083aSStefano Zampini } 1901a3df083aSStefano Zampini } else { 1902ad540459SPierre Jolivet for (j = 0; j < nz - 1; j++) sum += ctx->work[idxs[j]]; 1903a3df083aSStefano Zampini } 1904a3df083aSStefano Zampini ctx->work[idxs[nz - 1]] -= sum; 19059566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(ctx->benign_zerodiag_subs[i], &idxs)); 1906a3df083aSStefano Zampini } 19079566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(x, ctx->work)); 1908a3df083aSStefano Zampini reset_x = PETSC_TRUE; 1909a3df083aSStefano Zampini } 1910a3df083aSStefano Zampini if (transpose) { 19119566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(ctx->A, x, y)); 1912a3df083aSStefano Zampini } else { 19139566063dSJacob Faibussowitsch PetscCall(MatMult(ctx->A, x, y)); 1914a3df083aSStefano Zampini } 19151baa6e33SBarry Smith if (reset_x) PetscCall(VecResetArray(x)); 1916a3df083aSStefano Zampini if (apply_left) { 1917a3df083aSStefano Zampini PetscScalar *ay; 1918a3df083aSStefano Zampini PetscInt i; 1919a3df083aSStefano Zampini 19209566063dSJacob Faibussowitsch PetscCall(VecGetArray(y, &ay)); 1921a3df083aSStefano Zampini for (i = 0; i < ctx->benign_n; i++) { 1922a3df083aSStefano Zampini PetscScalar sum, val; 1923a3df083aSStefano Zampini const PetscInt *idxs; 1924a3df083aSStefano Zampini PetscInt nz, j; 19259566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(ctx->benign_zerodiag_subs[i], &nz)); 19269566063dSJacob Faibussowitsch PetscCall(ISGetIndices(ctx->benign_zerodiag_subs[i], &idxs)); 1927a3df083aSStefano Zampini val = -ay[idxs[nz - 1]]; 1928a3df083aSStefano Zampini if (ctx->apply_p0) { 1929a3df083aSStefano Zampini sum = 0.; 1930a3df083aSStefano Zampini for (j = 0; j < nz - 1; j++) { 1931a3df083aSStefano Zampini sum += ay[idxs[j]]; 1932a3df083aSStefano Zampini ay[idxs[j]] += val; 1933a3df083aSStefano Zampini } 1934a3df083aSStefano Zampini ay[idxs[nz - 1]] += sum; 1935a3df083aSStefano Zampini } else { 1936ad540459SPierre Jolivet for (j = 0; j < nz - 1; j++) ay[idxs[j]] += val; 1937a3df083aSStefano Zampini ay[idxs[nz - 1]] = 0.; 1938a3df083aSStefano Zampini } 19399566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(ctx->benign_zerodiag_subs[i], &idxs)); 1940a3df083aSStefano Zampini } 19419566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(y, &ay)); 1942a3df083aSStefano Zampini } 19433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1944a3df083aSStefano Zampini } 1945a3df083aSStefano Zampini 1946ba38deedSJacob Faibussowitsch static PetscErrorCode PCBDDCBenignMatMultTranspose_Private(Mat A, Vec x, Vec y) 1947d71ae5a4SJacob Faibussowitsch { 1948a3df083aSStefano Zampini PetscFunctionBegin; 19499566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignMatMult_Private_Private(A, x, y, PETSC_TRUE)); 19503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1951a3df083aSStefano Zampini } 1952a3df083aSStefano Zampini 1953ba38deedSJacob Faibussowitsch static PetscErrorCode PCBDDCBenignMatMult_Private(Mat A, Vec x, Vec y) 1954d71ae5a4SJacob Faibussowitsch { 1955a3df083aSStefano Zampini PetscFunctionBegin; 19569566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignMatMult_Private_Private(A, x, y, PETSC_FALSE)); 19573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1958a3df083aSStefano Zampini } 1959a3df083aSStefano Zampini 1960d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignShellMat(PC pc, PetscBool restore) 1961d71ae5a4SJacob Faibussowitsch { 1962a3df083aSStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 1963a3df083aSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 1964a3df083aSStefano Zampini PCBDDCBenignMatMult_ctx ctx; 1965a3df083aSStefano Zampini 1966a3df083aSStefano Zampini PetscFunctionBegin; 1967a3df083aSStefano Zampini if (!restore) { 19681dd7afcfSStefano Zampini Mat A_IB, A_BI; 1969a3df083aSStefano Zampini PetscScalar *work; 1970b334f244SStefano Zampini PCBDDCReuseSolvers reuse = pcbddc->sub_schurs ? pcbddc->sub_schurs->reuse_solver : NULL; 1971a3df083aSStefano Zampini 197228b400f6SJacob Faibussowitsch PetscCheck(!pcbddc->benign_original_mat, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Benign original mat has not been restored"); 19733ba16761SJacob Faibussowitsch if (!pcbddc->benign_change || !pcbddc->benign_n || pcbddc->benign_change_explicit) PetscFunctionReturn(PETSC_SUCCESS); 19749566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n, &work)); 19759566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &A_IB)); 19769566063dSJacob Faibussowitsch PetscCall(MatSetSizes(A_IB, pcis->n - pcis->n_B, pcis->n_B, PETSC_DECIDE, PETSC_DECIDE)); 19779566063dSJacob Faibussowitsch PetscCall(MatSetType(A_IB, MATSHELL)); 19789566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(A_IB, MATOP_MULT, (void (*)(void))PCBDDCBenignMatMult_Private)); 19799566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(A_IB, MATOP_MULT_TRANSPOSE, (void (*)(void))PCBDDCBenignMatMultTranspose_Private)); 19809566063dSJacob Faibussowitsch PetscCall(PetscNew(&ctx)); 19819566063dSJacob Faibussowitsch PetscCall(MatShellSetContext(A_IB, ctx)); 1982a3df083aSStefano Zampini ctx->apply_left = PETSC_TRUE; 1983a3df083aSStefano Zampini ctx->apply_right = PETSC_FALSE; 1984a3df083aSStefano Zampini ctx->apply_p0 = PETSC_FALSE; 1985a3df083aSStefano Zampini ctx->benign_n = pcbddc->benign_n; 1986059032f7SStefano Zampini if (reuse) { 1987a3df083aSStefano Zampini ctx->benign_zerodiag_subs = reuse->benign_zerodiag_subs; 19881dd7afcfSStefano Zampini ctx->free = PETSC_FALSE; 1989059032f7SStefano Zampini } else { /* TODO: could be optimized for successive solves */ 1990059032f7SStefano Zampini ISLocalToGlobalMapping N_to_D; 1991059032f7SStefano Zampini PetscInt i; 1992059032f7SStefano Zampini 19939566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(pcis->is_I_local, &N_to_D)); 19949566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->benign_n, &ctx->benign_zerodiag_subs)); 199548a46eb9SPierre 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])); 19969566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&N_to_D)); 19971dd7afcfSStefano Zampini ctx->free = PETSC_TRUE; 1998059032f7SStefano Zampini } 1999a3df083aSStefano Zampini ctx->A = pcis->A_IB; 2000a3df083aSStefano Zampini ctx->work = work; 20019566063dSJacob Faibussowitsch PetscCall(MatSetUp(A_IB)); 20029566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A_IB, MAT_FINAL_ASSEMBLY)); 20039566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A_IB, MAT_FINAL_ASSEMBLY)); 2004a3df083aSStefano Zampini pcis->A_IB = A_IB; 2005a3df083aSStefano Zampini 2006a3df083aSStefano Zampini /* A_BI as A_IB^T */ 20079566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(A_IB, &A_BI)); 2008a3df083aSStefano Zampini pcbddc->benign_original_mat = pcis->A_BI; 2009a3df083aSStefano Zampini pcis->A_BI = A_BI; 2010a3df083aSStefano Zampini } else { 20113ba16761SJacob Faibussowitsch if (!pcbddc->benign_original_mat) PetscFunctionReturn(PETSC_SUCCESS); 20129566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(pcis->A_IB, &ctx)); 20139566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_IB)); 2014a3df083aSStefano Zampini pcis->A_IB = ctx->A; 20151dd7afcfSStefano Zampini ctx->A = NULL; 20169566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_BI)); 20171dd7afcfSStefano Zampini pcis->A_BI = pcbddc->benign_original_mat; 20181dd7afcfSStefano Zampini pcbddc->benign_original_mat = NULL; 20191dd7afcfSStefano Zampini if (ctx->free) { 2020059032f7SStefano Zampini PetscInt i; 202148a46eb9SPierre Jolivet for (i = 0; i < ctx->benign_n; i++) PetscCall(ISDestroy(&ctx->benign_zerodiag_subs[i])); 20229566063dSJacob Faibussowitsch PetscCall(PetscFree(ctx->benign_zerodiag_subs)); 2023059032f7SStefano Zampini } 20249566063dSJacob Faibussowitsch PetscCall(PetscFree(ctx->work)); 20259566063dSJacob Faibussowitsch PetscCall(PetscFree(ctx)); 2026a3df083aSStefano Zampini } 20273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2028a3df083aSStefano Zampini } 2029a3df083aSStefano Zampini 2030a3df083aSStefano Zampini /* used just in bddc debug mode */ 2031ba38deedSJacob Faibussowitsch static PetscErrorCode PCBDDCBenignProject(PC pc, IS is1, IS is2, Mat *B) 2032d71ae5a4SJacob Faibussowitsch { 2033a3df083aSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 2034a3df083aSStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 2035a3df083aSStefano Zampini Mat An; 2036a3df083aSStefano Zampini 2037a3df083aSStefano Zampini PetscFunctionBegin; 20389566063dSJacob Faibussowitsch PetscCall(MatPtAP(matis->A, pcbddc->benign_change, MAT_INITIAL_MATRIX, 2.0, &An)); 20399566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns(An, pcbddc->benign_n, pcbddc->benign_p0_lidx, 1.0, NULL, NULL)); 2040a3df083aSStefano Zampini if (is1) { 20419566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(An, is1, is2, MAT_INITIAL_MATRIX, B)); 20429566063dSJacob Faibussowitsch PetscCall(MatDestroy(&An)); 2043a3df083aSStefano Zampini } else { 2044a3df083aSStefano Zampini *B = An; 2045a3df083aSStefano Zampini } 20463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2047a3df083aSStefano Zampini } 2048a3df083aSStefano Zampini 20491cf9b237SStefano Zampini /* TODO: add reuse flag */ 2050d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSeqAIJCompress(Mat A, Mat *B) 2051d71ae5a4SJacob Faibussowitsch { 20521cf9b237SStefano Zampini Mat Bt; 20531cf9b237SStefano Zampini PetscScalar *a, *bdata; 20541cf9b237SStefano Zampini const PetscInt *ii, *ij; 20551cf9b237SStefano Zampini PetscInt m, n, i, nnz, *bii, *bij; 20561cf9b237SStefano Zampini PetscBool flg_row; 20571cf9b237SStefano Zampini 20581cf9b237SStefano Zampini PetscFunctionBegin; 20599566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &n, &m)); 20609566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &ij, &flg_row)); 20619566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A, &a)); 20621cf9b237SStefano Zampini nnz = n; 20631cf9b237SStefano Zampini for (i = 0; i < ii[n]; i++) { 20641cf9b237SStefano Zampini if (PetscLikely(PetscAbsScalar(a[i]) > PETSC_SMALL)) nnz++; 20651cf9b237SStefano Zampini } 20669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n + 1, &bii)); 20679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &bij)); 20689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &bdata)); 20691cf9b237SStefano Zampini nnz = 0; 20701cf9b237SStefano Zampini bii[0] = 0; 20711cf9b237SStefano Zampini for (i = 0; i < n; i++) { 20721cf9b237SStefano Zampini PetscInt j; 20731cf9b237SStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 20741cf9b237SStefano Zampini PetscScalar entry = a[j]; 20753272d46bSStefano Zampini if (PetscLikely(PetscAbsScalar(entry) > PETSC_SMALL) || (n == m && ij[j] == i)) { 20761cf9b237SStefano Zampini bij[nnz] = ij[j]; 20771cf9b237SStefano Zampini bdata[nnz] = entry; 20781cf9b237SStefano Zampini nnz++; 20791cf9b237SStefano Zampini } 20801cf9b237SStefano Zampini } 20811cf9b237SStefano Zampini bii[i + 1] = nnz; 20821cf9b237SStefano Zampini } 20839566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(A, &a)); 20849566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A), n, m, bii, bij, bdata, &Bt)); 20859566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &ij, &flg_row)); 20861cf9b237SStefano Zampini { 2087*f4f49eeaSPierre Jolivet Mat_SeqAIJ *b = (Mat_SeqAIJ *)Bt->data; 20881cf9b237SStefano Zampini b->free_a = PETSC_TRUE; 20891cf9b237SStefano Zampini b->free_ij = PETSC_TRUE; 20901cf9b237SStefano Zampini } 209148a46eb9SPierre Jolivet if (*B == A) PetscCall(MatDestroy(&A)); 20921cf9b237SStefano Zampini *B = Bt; 20933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20941cf9b237SStefano Zampini } 20951cf9b237SStefano Zampini 2096d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCDetectDisconnectedComponents(PC pc, PetscBool filter, PetscInt *ncc, IS *cc[], IS *primalv) 2097d71ae5a4SJacob Faibussowitsch { 2098c80a6c00SStefano Zampini Mat B = NULL; 2099c80a6c00SStefano Zampini DM dm; 21004f1b2e48SStefano Zampini IS is_dummy, *cc_n; 21014f1b2e48SStefano Zampini ISLocalToGlobalMapping l2gmap_dummy; 21024f1b2e48SStefano Zampini PCBDDCGraph graph; 2103c80a6c00SStefano Zampini PetscInt *xadj_filtered = NULL, *adjncy_filtered = NULL; 21044f1b2e48SStefano Zampini PetscInt i, n; 21054f1b2e48SStefano Zampini PetscInt *xadj, *adjncy; 2106c80a6c00SStefano Zampini PetscBool isplex = PETSC_FALSE; 21074f1b2e48SStefano Zampini 21084f1b2e48SStefano Zampini PetscFunctionBegin; 2109a2eca866SStefano Zampini if (ncc) *ncc = 0; 2110a2eca866SStefano Zampini if (cc) *cc = NULL; 2111a2eca866SStefano Zampini if (primalv) *primalv = NULL; 21129566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphCreate(&graph)); 21139566063dSJacob Faibussowitsch PetscCall(MatGetDM(pc->pmat, &dm)); 211448a46eb9SPierre Jolivet if (!dm) PetscCall(PCGetDM(pc, &dm)); 2115f9635d15SStefano Zampini if (dm) PetscCall(PetscObjectTypeCompareAny((PetscObject)dm, &isplex, DMPLEX, DMP4EST, DMP8EST, "")); 21168361f951SStefano Zampini if (filter) isplex = PETSC_FALSE; 21178361f951SStefano Zampini 2118c80a6c00SStefano Zampini if (isplex) { /* this code has been modified from plexpartition.c */ 2119c80a6c00SStefano Zampini PetscInt p, pStart, pEnd, a, adjSize, idx, size, nroots; 2120c80a6c00SStefano Zampini PetscInt *adj = NULL; 2121c80a6c00SStefano Zampini IS cellNumbering; 2122c80a6c00SStefano Zampini const PetscInt *cellNum; 2123c80a6c00SStefano Zampini PetscBool useCone, useClosure; 2124c80a6c00SStefano Zampini PetscSection section; 2125c80a6c00SStefano Zampini PetscSegBuffer adjBuffer; 2126c80a6c00SStefano Zampini PetscSF sfPoint; 2127c80a6c00SStefano Zampini 2128f9635d15SStefano Zampini PetscCall(DMConvert(dm, DMPLEX, &dm)); 21299566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd)); 21309566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 21319566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL)); 2132c80a6c00SStefano Zampini /* Build adjacency graph via a section/segbuffer */ 21339566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 21349566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(section, pStart, pEnd)); 21359566063dSJacob Faibussowitsch PetscCall(PetscSegBufferCreate(sizeof(PetscInt), 1000, &adjBuffer)); 2136c80a6c00SStefano Zampini /* Always use FVM adjacency to create partitioner graph */ 21379566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 21389566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dm, PETSC_TRUE, PETSC_FALSE)); 21399566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellNumbering(dm, &cellNumbering)); 21409566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cellNumbering, &cellNum)); 2141c80a6c00SStefano Zampini for (n = 0, p = pStart; p < pEnd; p++) { 2142c80a6c00SStefano Zampini /* Skip non-owned cells in parallel (ParMetis expects no overlap) */ 21439371c9d4SSatish Balay if (nroots > 0) { 21449371c9d4SSatish Balay if (cellNum[p] < 0) continue; 21459371c9d4SSatish Balay } 2146c80a6c00SStefano Zampini adjSize = PETSC_DETERMINE; 21479566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dm, p, &adjSize, &adj)); 2148c80a6c00SStefano Zampini for (a = 0; a < adjSize; ++a) { 2149c80a6c00SStefano Zampini const PetscInt point = adj[a]; 21505cef3d0dSStefano Zampini if (pStart <= point && point < pEnd) { 2151c80a6c00SStefano Zampini PetscInt *PETSC_RESTRICT pBuf; 21529566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(section, p, 1)); 21539566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGetInts(adjBuffer, 1, &pBuf)); 2154c80a6c00SStefano Zampini *pBuf = point; 2155c80a6c00SStefano Zampini } 2156c80a6c00SStefano Zampini } 2157c80a6c00SStefano Zampini n++; 2158c80a6c00SStefano Zampini } 21599566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(dm, useCone, useClosure)); 2160c80a6c00SStefano Zampini /* Derive CSR graph from section/segbuffer */ 21619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(section)); 21629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(section, &size)); 21639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n + 1, &xadj)); 2164c80a6c00SStefano Zampini for (idx = 0, p = pStart; p < pEnd; p++) { 21659371c9d4SSatish Balay if (nroots > 0) { 21669371c9d4SSatish Balay if (cellNum[p] < 0) continue; 21679371c9d4SSatish Balay } 2168*f4f49eeaSPierre Jolivet PetscCall(PetscSectionGetOffset(section, p, &xadj[idx++])); 2169c80a6c00SStefano Zampini } 2170c80a6c00SStefano Zampini xadj[n] = size; 21719566063dSJacob Faibussowitsch PetscCall(PetscSegBufferExtractAlloc(adjBuffer, &adjncy)); 2172c80a6c00SStefano Zampini /* Clean up */ 21739566063dSJacob Faibussowitsch PetscCall(PetscSegBufferDestroy(&adjBuffer)); 21749566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 21759566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 2176c80a6c00SStefano Zampini graph->xadj = xadj; 2177c80a6c00SStefano Zampini graph->adjncy = adjncy; 2178c80a6c00SStefano Zampini } else { 2179c80a6c00SStefano Zampini Mat A; 21808361f951SStefano Zampini PetscBool isseqaij, flg_row; 2181c80a6c00SStefano Zampini 21829566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->pmat, &A)); 218363c961adSStefano Zampini if (!A->rmap->N || !A->cmap->N) { 21849566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphDestroy(&graph)); 21853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 218663c961adSStefano Zampini } 21879566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isseqaij)); 21884f1b2e48SStefano Zampini if (!isseqaij && filter) { 21891cf9b237SStefano Zampini PetscBool isseqdense; 21901cf9b237SStefano Zampini 21919566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATSEQDENSE, &isseqdense)); 21921cf9b237SStefano Zampini if (!isseqdense) { 21939566063dSJacob Faibussowitsch PetscCall(MatConvert(A, MATSEQAIJ, MAT_INITIAL_MATRIX, &B)); 21941cf9b237SStefano Zampini } else { /* TODO: rectangular case and LDA */ 21951cf9b237SStefano Zampini PetscScalar *array; 21961cf9b237SStefano Zampini PetscReal chop = 1.e-6; 21971cf9b237SStefano Zampini 21989566063dSJacob Faibussowitsch PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &B)); 21999566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(B, &array)); 22009566063dSJacob Faibussowitsch PetscCall(MatGetSize(B, &n, NULL)); 22011cf9b237SStefano Zampini for (i = 0; i < n; i++) { 22021cf9b237SStefano Zampini PetscInt j; 22031cf9b237SStefano Zampini for (j = i + 1; j < n; j++) { 22041cf9b237SStefano Zampini PetscReal thresh = chop * (PetscAbsScalar(array[i * (n + 1)]) + PetscAbsScalar(array[j * (n + 1)])); 22051cf9b237SStefano Zampini if (PetscAbsScalar(array[i * n + j]) < thresh) array[i * n + j] = 0.; 22061cf9b237SStefano Zampini if (PetscAbsScalar(array[j * n + i]) < thresh) array[j * n + i] = 0.; 22071cf9b237SStefano Zampini } 22081cf9b237SStefano Zampini } 22099566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(B, &array)); 22109566063dSJacob Faibussowitsch PetscCall(MatConvert(B, MATSEQAIJ, MAT_INPLACE_MATRIX, &B)); 22111cf9b237SStefano Zampini } 22124f1b2e48SStefano Zampini } else { 22139566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 22144f1b2e48SStefano Zampini B = A; 22154f1b2e48SStefano Zampini } 22169566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(B, 0, PETSC_TRUE, PETSC_FALSE, &n, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &flg_row)); 22174f1b2e48SStefano Zampini 22184f1b2e48SStefano Zampini /* if filter is true, then removes entries lower than PETSC_SMALL in magnitude */ 22194f1b2e48SStefano Zampini if (filter) { 22204f1b2e48SStefano Zampini PetscScalar *data; 22214f1b2e48SStefano Zampini PetscInt j, cum; 22224f1b2e48SStefano Zampini 22239566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(n + 1, &xadj_filtered, xadj[n], &adjncy_filtered)); 22249566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(B, &data)); 22254f1b2e48SStefano Zampini cum = 0; 22264f1b2e48SStefano Zampini for (i = 0; i < n; i++) { 22274f1b2e48SStefano Zampini PetscInt t; 22284f1b2e48SStefano Zampini 22294f1b2e48SStefano Zampini for (j = xadj[i]; j < xadj[i + 1]; j++) { 2230ad540459SPierre Jolivet if (PetscUnlikely(PetscAbsScalar(data[j]) < PETSC_SMALL)) continue; 22314f1b2e48SStefano Zampini adjncy_filtered[cum + xadj_filtered[i]++] = adjncy[j]; 22324f1b2e48SStefano Zampini } 22334f1b2e48SStefano Zampini t = xadj_filtered[i]; 22344f1b2e48SStefano Zampini xadj_filtered[i] = cum; 22354f1b2e48SStefano Zampini cum += t; 22364f1b2e48SStefano Zampini } 22379566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(B, &data)); 22384f1b2e48SStefano Zampini graph->xadj = xadj_filtered; 22394f1b2e48SStefano Zampini graph->adjncy = adjncy_filtered; 22404f1b2e48SStefano Zampini } else { 22414f1b2e48SStefano Zampini graph->xadj = xadj; 22424f1b2e48SStefano Zampini graph->adjncy = adjncy; 22434f1b2e48SStefano Zampini } 2244c80a6c00SStefano Zampini } 2245c80a6c00SStefano Zampini /* compute local connected components using PCBDDCGraph */ 22469566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, n, 0, 1, &is_dummy)); 22479566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is_dummy, &l2gmap_dummy)); 22489566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_dummy)); 22499566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphInit(graph, l2gmap_dummy, n, PETSC_MAX_INT)); 22509566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&l2gmap_dummy)); 22519566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphSetUp(graph, 1, NULL, NULL, 0, NULL, NULL)); 22529566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphComputeConnectedComponents(graph)); 2253c80a6c00SStefano Zampini 22544f1b2e48SStefano Zampini /* partial clean up */ 22559566063dSJacob Faibussowitsch PetscCall(PetscFree2(xadj_filtered, adjncy_filtered)); 2256c80a6c00SStefano Zampini if (B) { 2257c80a6c00SStefano Zampini PetscBool flg_row; 22589566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(B, 0, PETSC_TRUE, PETSC_FALSE, &n, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &flg_row)); 22599566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 22604f1b2e48SStefano Zampini } 2261c80a6c00SStefano Zampini if (isplex) { 22629566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 22639566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 2264c80a6c00SStefano Zampini } 22654f1b2e48SStefano Zampini 22664f1b2e48SStefano Zampini /* get back data */ 2267c80a6c00SStefano Zampini if (isplex) { 2268c80a6c00SStefano Zampini if (ncc) *ncc = graph->ncc; 2269c80a6c00SStefano Zampini if (cc || primalv) { 2270c80a6c00SStefano Zampini Mat A; 2271f9635d15SStefano Zampini PetscBT btv, btvt, btvc; 2272c80a6c00SStefano Zampini PetscSection subSection; 2273c80a6c00SStefano Zampini PetscInt *ids, cum, cump, *cids, *pids; 2274f9635d15SStefano Zampini PetscInt dim, cStart, cEnd, fStart, fEnd, vStart, vEnd, pStart, pEnd; 2275c80a6c00SStefano Zampini 2276f9635d15SStefano Zampini PetscCall(DMGetDimension(dm, &dim)); 22779566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubdomainSection(dm, &subSection)); 2278f9635d15SStefano Zampini PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 2279f9635d15SStefano Zampini PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 2280f9635d15SStefano Zampini PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 2281f9635d15SStefano Zampini PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 22829566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->pmat, &A)); 22839566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(A->rmap->n, &ids, graph->ncc + 1, &cids, A->rmap->n, &pids)); 22849566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(A->rmap->n, &btv)); 22859566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(A->rmap->n, &btvt)); 2286f9635d15SStefano Zampini PetscCall(PetscBTCreate(pEnd - pStart, &btvc)); 2287f9635d15SStefano Zampini 2288f9635d15SStefano Zampini /* First see if we find corners for the subdomains, i.e. a vertex 2289f9635d15SStefano Zampini shared by at least dim subdomain boundary faces. This does not 2290f9635d15SStefano Zampini cover all the possible cases with simplices but it is enough 2291f9635d15SStefano Zampini for tensor cells */ 2292f9635d15SStefano Zampini if (vStart != fStart && dim <= 3) { 2293f9635d15SStefano Zampini for (PetscInt c = cStart; c < cEnd; c++) { 2294f9635d15SStefano Zampini PetscInt nf, cnt = 0, mcnt = dim, *cfaces; 2295f9635d15SStefano Zampini const PetscInt *faces; 2296f9635d15SStefano Zampini 2297f9635d15SStefano Zampini PetscCall(DMPlexGetConeSize(dm, c, &nf)); 2298f9635d15SStefano Zampini PetscCall(DMGetWorkArray(dm, nf, MPIU_INT, &cfaces)); 2299f9635d15SStefano Zampini PetscCall(DMPlexGetCone(dm, c, &faces)); 2300f9635d15SStefano Zampini for (PetscInt f = 0; f < nf; f++) { 2301f9635d15SStefano Zampini PetscInt nc, ff; 2302f9635d15SStefano Zampini 2303f9635d15SStefano Zampini PetscCall(DMPlexGetSupportSize(dm, faces[f], &nc)); 2304f9635d15SStefano Zampini PetscCall(DMPlexGetTreeParent(dm, faces[f], &ff, NULL)); 2305f9635d15SStefano Zampini if (nc == 1 && faces[f] == ff) cfaces[cnt++] = faces[f]; 2306f9635d15SStefano Zampini } 2307f9635d15SStefano Zampini if (cnt >= mcnt) { 2308f9635d15SStefano Zampini PetscInt size, *closure = NULL; 2309f9635d15SStefano Zampini 2310f9635d15SStefano Zampini PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &size, &closure)); 2311f9635d15SStefano Zampini for (PetscInt k = 0; k < 2 * size; k += 2) { 2312f9635d15SStefano Zampini PetscInt v = closure[k]; 2313f9635d15SStefano Zampini if (v >= vStart && v < vEnd) { 2314f9635d15SStefano Zampini PetscInt vsize, *vclosure = NULL; 2315f9635d15SStefano Zampini 2316f9635d15SStefano Zampini cnt = 0; 2317f9635d15SStefano Zampini PetscCall(DMPlexGetTransitiveClosure(dm, v, PETSC_FALSE, &vsize, &vclosure)); 2318f9635d15SStefano Zampini for (PetscInt vk = 0; vk < 2 * vsize; vk += 2) { 2319f9635d15SStefano Zampini PetscInt f = vclosure[vk]; 2320f9635d15SStefano Zampini if (f >= fStart && f < fEnd) { 2321f9635d15SStefano Zampini PetscInt nc, ff; 2322f9635d15SStefano Zampini PetscBool valid = PETSC_FALSE; 2323f9635d15SStefano Zampini 2324f9635d15SStefano Zampini for (PetscInt fk = 0; fk < nf; fk++) 2325f9635d15SStefano Zampini if (f == cfaces[fk]) valid = PETSC_TRUE; 2326f9635d15SStefano Zampini if (!valid) continue; 2327f9635d15SStefano Zampini PetscCall(DMPlexGetSupportSize(dm, f, &nc)); 2328f9635d15SStefano Zampini PetscCall(DMPlexGetTreeParent(dm, f, &ff, NULL)); 2329f9635d15SStefano Zampini if (nc == 1 && f == ff) cnt++; 2330f9635d15SStefano Zampini } 2331f9635d15SStefano Zampini } 2332f9635d15SStefano Zampini if (cnt >= mcnt) PetscCall(PetscBTSet(btvc, v - pStart)); 2333f9635d15SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure(dm, v, PETSC_FALSE, &vsize, &vclosure)); 2334f9635d15SStefano Zampini } 2335f9635d15SStefano Zampini } 2336f9635d15SStefano Zampini PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &size, &closure)); 2337f9635d15SStefano Zampini } 2338f9635d15SStefano Zampini PetscCall(DMRestoreWorkArray(dm, nf, MPIU_INT, &cfaces)); 2339f9635d15SStefano Zampini } 2340f9635d15SStefano Zampini } 2341c80a6c00SStefano Zampini 2342c80a6c00SStefano Zampini cids[0] = 0; 2343c80a6c00SStefano Zampini for (i = 0, cump = 0, cum = 0; i < graph->ncc; i++) { 2344c80a6c00SStefano Zampini PetscInt j; 2345c80a6c00SStefano Zampini 23469566063dSJacob Faibussowitsch PetscCall(PetscBTMemzero(A->rmap->n, btvt)); 2347c80a6c00SStefano Zampini for (j = graph->cptr[i]; j < graph->cptr[i + 1]; j++) { 2348c80a6c00SStefano Zampini PetscInt k, size, *closure = NULL, cell = graph->queue[j]; 2349c80a6c00SStefano Zampini 23509566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &size, &closure)); 2351c80a6c00SStefano Zampini for (k = 0; k < 2 * size; k += 2) { 235220c3699dSStefano Zampini PetscInt s, pp, p = closure[k], off, dof, cdof; 2353c80a6c00SStefano Zampini 23549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(subSection, p, &cdof)); 23559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(subSection, p, &off)); 23569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subSection, p, &dof)); 2357c80a6c00SStefano Zampini for (s = 0; s < dof - cdof; s++) { 2358c80a6c00SStefano Zampini if (PetscBTLookupSet(btvt, off + s)) continue; 2359f9635d15SStefano Zampini if (PetscBTLookup(btvc, p - pStart)) pids[cump++] = off + s; /* subdomain corner */ 2360f9635d15SStefano Zampini else if (!PetscBTLookup(btv, off + s)) ids[cum++] = off + s; 2361e432b41dSStefano Zampini else pids[cump++] = off + s; /* cross-vertex */ 2362c80a6c00SStefano Zampini } 23639566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL)); 236420c3699dSStefano Zampini if (pp != p) { 23659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(subSection, pp, &cdof)); 23669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(subSection, pp, &off)); 23679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subSection, pp, &dof)); 236820c3699dSStefano Zampini for (s = 0; s < dof - cdof; s++) { 236920c3699dSStefano Zampini if (PetscBTLookupSet(btvt, off + s)) continue; 2370f9635d15SStefano Zampini if (PetscBTLookup(btvc, pp - pStart)) pids[cump++] = off + s; /* subdomain corner */ 2371f9635d15SStefano Zampini else if (!PetscBTLookup(btv, off + s)) ids[cum++] = off + s; 2372e432b41dSStefano Zampini else pids[cump++] = off + s; /* cross-vertex */ 237320c3699dSStefano Zampini } 237420c3699dSStefano Zampini } 2375c80a6c00SStefano Zampini } 23769566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &size, &closure)); 2377c80a6c00SStefano Zampini } 2378c80a6c00SStefano Zampini cids[i + 1] = cum; 2379c80a6c00SStefano Zampini /* mark dofs as already assigned */ 238048a46eb9SPierre Jolivet for (j = cids[i]; j < cids[i + 1]; j++) PetscCall(PetscBTSet(btv, ids[j])); 2381c80a6c00SStefano Zampini } 2382c80a6c00SStefano Zampini if (cc) { 23839566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(graph->ncc, &cc_n)); 238448a46eb9SPierre 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])); 2385c80a6c00SStefano Zampini *cc = cc_n; 2386c80a6c00SStefano Zampini } 23871baa6e33SBarry Smith if (primalv) PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), cump, pids, PETSC_COPY_VALUES, primalv)); 23889566063dSJacob Faibussowitsch PetscCall(PetscFree3(ids, cids, pids)); 23899566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btv)); 23909566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&btvt)); 2391f9635d15SStefano Zampini PetscCall(PetscBTDestroy(&btvc)); 2392f9635d15SStefano Zampini PetscCall(DMDestroy(&dm)); 2393c80a6c00SStefano Zampini } 2394c80a6c00SStefano Zampini } else { 23951cf9b237SStefano Zampini if (ncc) *ncc = graph->ncc; 23961cf9b237SStefano Zampini if (cc) { 23979566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(graph->ncc, &cc_n)); 239848a46eb9SPierre 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])); 23994f1b2e48SStefano Zampini *cc = cc_n; 24001cf9b237SStefano Zampini } 2401c80a6c00SStefano Zampini } 24024f1b2e48SStefano Zampini /* clean up graph */ 24030a545947SLisandro Dalcin graph->xadj = NULL; 24040a545947SLisandro Dalcin graph->adjncy = NULL; 24059566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphDestroy(&graph)); 24063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24074f1b2e48SStefano Zampini } 24084f1b2e48SStefano Zampini 2409d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignCheck(PC pc, IS zerodiag) 2410d71ae5a4SJacob Faibussowitsch { 24115408967cSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 2412*f4f49eeaSPierre Jolivet PC_IS *pcis = (PC_IS *)pc->data; 2413dee84bffSStefano Zampini IS dirIS = NULL; 24144f1b2e48SStefano Zampini PetscInt i; 24155408967cSStefano Zampini 24165408967cSStefano Zampini PetscFunctionBegin; 24179566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph, &dirIS)); 24185408967cSStefano Zampini if (zerodiag) { 24195408967cSStefano Zampini Mat A; 24205408967cSStefano Zampini Vec vec3_N; 24215408967cSStefano Zampini PetscScalar *vals; 24225408967cSStefano Zampini const PetscInt *idxs; 2423d12d3064SStefano Zampini PetscInt nz, *count; 24245408967cSStefano Zampini 24255408967cSStefano Zampini /* p0 */ 24269566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_N, 0.)); 24279566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n, &vals)); 24289566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zerodiag, &nz)); 24299566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zerodiag, &idxs)); 24304f1b2e48SStefano Zampini for (i = 0; i < nz; i++) vals[i] = 1.; 24319566063dSJacob Faibussowitsch PetscCall(VecSetValues(pcis->vec1_N, nz, idxs, vals, INSERT_VALUES)); 24329566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(pcis->vec1_N)); 24339566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(pcis->vec1_N)); 24345408967cSStefano Zampini /* v_I */ 24359566063dSJacob Faibussowitsch PetscCall(VecSetRandom(pcis->vec2_N, NULL)); 24365408967cSStefano Zampini for (i = 0; i < nz; i++) vals[i] = 0.; 24379566063dSJacob Faibussowitsch PetscCall(VecSetValues(pcis->vec2_N, nz, idxs, vals, INSERT_VALUES)); 24389566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zerodiag, &idxs)); 24399566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_B_local, &idxs)); 24405408967cSStefano Zampini for (i = 0; i < pcis->n_B; i++) vals[i] = 0.; 24419566063dSJacob Faibussowitsch PetscCall(VecSetValues(pcis->vec2_N, pcis->n_B, idxs, vals, INSERT_VALUES)); 24429566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_B_local, &idxs)); 24435408967cSStefano Zampini if (dirIS) { 24445408967cSStefano Zampini PetscInt n; 24455408967cSStefano Zampini 24469566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(dirIS, &n)); 24479566063dSJacob Faibussowitsch PetscCall(ISGetIndices(dirIS, &idxs)); 24485408967cSStefano Zampini for (i = 0; i < n; i++) vals[i] = 0.; 24499566063dSJacob Faibussowitsch PetscCall(VecSetValues(pcis->vec2_N, n, idxs, vals, INSERT_VALUES)); 24509566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(dirIS, &idxs)); 24515408967cSStefano Zampini } 24529566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(pcis->vec2_N)); 24539566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(pcis->vec2_N)); 24549566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_N, &vec3_N)); 24559566063dSJacob Faibussowitsch PetscCall(VecSet(vec3_N, 0.)); 24569566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->pmat, &A)); 24579566063dSJacob Faibussowitsch PetscCall(MatMult(A, pcis->vec1_N, vec3_N)); 24589566063dSJacob Faibussowitsch PetscCall(VecDot(vec3_N, pcis->vec2_N, &vals[0])); 24597827d75bSBarry 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])); 24609566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 24619566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vec3_N)); 2462d12d3064SStefano Zampini 2463d12d3064SStefano Zampini /* there should not be any pressure dofs lying on the interface */ 24649566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pcis->n, &count)); 24659566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_B_local, &idxs)); 2466d12d3064SStefano Zampini for (i = 0; i < pcis->n_B; i++) count[idxs[i]]++; 24679566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_B_local, &idxs)); 24689566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zerodiag, &idxs)); 246963a3b9bcSJacob 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]); 24709566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zerodiag, &idxs)); 24719566063dSJacob Faibussowitsch PetscCall(PetscFree(count)); 24725408967cSStefano Zampini } 24739566063dSJacob Faibussowitsch PetscCall(ISDestroy(&dirIS)); 24745408967cSStefano Zampini 24755408967cSStefano Zampini /* check PCBDDCBenignGetOrSetP0 */ 24769566063dSJacob Faibussowitsch PetscCall(VecSetRandom(pcis->vec1_global, NULL)); 24774f1b2e48SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) pcbddc->benign_p0[i] = -PetscGlobalRank - i; 24789566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc, pcis->vec1_global, PETSC_FALSE)); 24794f1b2e48SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) pcbddc->benign_p0[i] = 1; 24809566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc, pcis->vec1_global, PETSC_TRUE)); 2481f2a566d8SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) { 2482f2a566d8SStefano Zampini PetscInt val = PetscRealPart(pcbddc->benign_p0[i]); 248363a3b9bcSJacob 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)); 2484f2a566d8SStefano Zampini } 24853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24865408967cSStefano Zampini } 24875408967cSStefano Zampini 2488d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignDetectSaddlePoint(PC pc, PetscBool reuse, IS *zerodiaglocal) 2489d71ae5a4SJacob Faibussowitsch { 2490339f8db1SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 2491*f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)pc->pmat->data; 24923b03f7bbSStefano Zampini IS pressures = NULL, zerodiag = NULL, *bzerodiag = NULL, zerodiag_save, *zerodiag_subs; 24933b03f7bbSStefano Zampini PetscInt nz, n, benign_n, bsp = 1; 24944edc6404Sstefano_zampini PetscInt *interior_dofs, n_interior_dofs, nneu; 24954edc6404Sstefano_zampini PetscBool sorted, have_null, has_null_pressures, recompute_zerodiag, checkb; 2496339f8db1SStefano Zampini 2497339f8db1SStefano Zampini PetscFunctionBegin; 24983b03f7bbSStefano Zampini if (reuse) goto project_b0; 24999566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pcbddc->benign_sf)); 25009566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->benign_B0)); 250148a46eb9SPierre Jolivet for (n = 0; n < pcbddc->benign_n; n++) PetscCall(ISDestroy(&pcbddc->benign_zerodiag_subs[n])); 25029566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->benign_zerodiag_subs)); 25033b03f7bbSStefano Zampini has_null_pressures = PETSC_TRUE; 25043b03f7bbSStefano Zampini have_null = PETSC_TRUE; 25053b03f7bbSStefano Zampini /* if a local information on dofs is present, gets pressure dofs from command line (uses the last field is not provided) 25063b03f7bbSStefano Zampini Without local information, it uses only the zerodiagonal dofs (ok if the pressure block is all zero and it is a scalar field) 25074f1b2e48SStefano Zampini Checks if all the pressure dofs in each subdomain have a zero diagonal 25084f1b2e48SStefano Zampini If not, a change of basis on pressures is not needed 25091ae86dd6SStefano Zampini since the local Schur complements are already SPD 25104f1b2e48SStefano Zampini */ 251140fa8d13SStefano Zampini if (pcbddc->n_ISForDofsLocal) { 25127fbe2174Sstefano_zampini IS iP = NULL; 25133b03f7bbSStefano Zampini PetscInt p, *pp; 25143b03f7bbSStefano Zampini PetscBool flg; 25154f1b2e48SStefano Zampini 25169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->n_ISForDofsLocal, &pp)); 25173b03f7bbSStefano Zampini n = pcbddc->n_ISForDofsLocal; 2518d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)pc), ((PetscObject)pc)->prefix, "BDDC benign options", "PC"); 25199566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-pc_bddc_pressure_field", "Field id for pressures", NULL, pp, &n, &flg)); 2520d0609cedSBarry Smith PetscOptionsEnd(); 25213b03f7bbSStefano Zampini if (!flg) { 25223b03f7bbSStefano Zampini n = 1; 25233b03f7bbSStefano Zampini pp[0] = pcbddc->n_ISForDofsLocal - 1; 25243b03f7bbSStefano Zampini } 25253b03f7bbSStefano Zampini 25263b03f7bbSStefano Zampini bsp = 0; 25273b03f7bbSStefano Zampini for (p = 0; p < n; p++) { 25283b03f7bbSStefano Zampini PetscInt bs; 25293b03f7bbSStefano Zampini 253063a3b9bcSJacob 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]); 25319566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(pcbddc->ISForDofsLocal[pp[p]], &bs)); 25323b03f7bbSStefano Zampini bsp += bs; 25333b03f7bbSStefano Zampini } 25349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bsp, &bzerodiag)); 25353b03f7bbSStefano Zampini bsp = 0; 25363b03f7bbSStefano Zampini for (p = 0; p < n; p++) { 25373b03f7bbSStefano Zampini const PetscInt *idxs; 25383b03f7bbSStefano Zampini PetscInt b, bs, npl, *bidxs; 25393b03f7bbSStefano Zampini 25409566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(pcbddc->ISForDofsLocal[pp[p]], &bs)); 25419566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->ISForDofsLocal[pp[p]], &npl)); 25429566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->ISForDofsLocal[pp[p]], &idxs)); 25439566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(npl / bs, &bidxs)); 25443b03f7bbSStefano Zampini for (b = 0; b < bs; b++) { 25453b03f7bbSStefano Zampini PetscInt i; 25463b03f7bbSStefano Zampini 25473b03f7bbSStefano Zampini for (i = 0; i < npl / bs; i++) bidxs[i] = idxs[bs * i + b]; 25489566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, npl / bs, bidxs, PETSC_COPY_VALUES, &bzerodiag[bsp])); 25493b03f7bbSStefano Zampini bsp++; 25503b03f7bbSStefano Zampini } 25519566063dSJacob Faibussowitsch PetscCall(PetscFree(bidxs)); 25529566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->ISForDofsLocal[pp[p]], &idxs)); 25533b03f7bbSStefano Zampini } 25549566063dSJacob Faibussowitsch PetscCall(ISConcatenate(PETSC_COMM_SELF, bsp, bzerodiag, &pressures)); 25553b03f7bbSStefano Zampini 25567fbe2174Sstefano_zampini /* remove zeroed out pressures if we are setting up a BDDC solver for a saddle-point FETI-DP */ 25579566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lP", (PetscObject *)&iP)); 25587fbe2174Sstefano_zampini if (iP) { 25597fbe2174Sstefano_zampini IS newpressures; 25607fbe2174Sstefano_zampini 25619566063dSJacob Faibussowitsch PetscCall(ISDifference(pressures, iP, &newpressures)); 25629566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pressures)); 25637fbe2174Sstefano_zampini pressures = newpressures; 25647fbe2174Sstefano_zampini } 25659566063dSJacob Faibussowitsch PetscCall(ISSorted(pressures, &sorted)); 256648a46eb9SPierre Jolivet if (!sorted) PetscCall(ISSort(pressures)); 25679566063dSJacob Faibussowitsch PetscCall(PetscFree(pp)); 256840fa8d13SStefano Zampini } 25693b03f7bbSStefano Zampini 257097d764eeSStefano Zampini /* pcis has not been setup yet, so get the local size from the subdomain matrix */ 25719566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pcbddc->local_mat, &n, NULL)); 257227b6a85dSStefano Zampini if (!n) pcbddc->benign_change_explicit = PETSC_TRUE; 25739566063dSJacob Faibussowitsch PetscCall(MatFindZeroDiagonals(pcbddc->local_mat, &zerodiag)); 25749566063dSJacob Faibussowitsch PetscCall(ISSorted(zerodiag, &sorted)); 257548a46eb9SPierre Jolivet if (!sorted) PetscCall(ISSort(zerodiag)); 25769566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)zerodiag)); 25774edc6404Sstefano_zampini zerodiag_save = zerodiag; 25789566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zerodiag, &nz)); 25794f1b2e48SStefano Zampini if (!nz) { 25804f1b2e48SStefano Zampini if (n) have_null = PETSC_FALSE; 25814f1b2e48SStefano Zampini has_null_pressures = PETSC_FALSE; 25829566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zerodiag)); 258340fa8d13SStefano Zampini } 25844f1b2e48SStefano Zampini recompute_zerodiag = PETSC_FALSE; 25853b03f7bbSStefano Zampini 25864f1b2e48SStefano Zampini /* in case disconnected subdomains info is present, split the pressures accordingly (otherwise the benign trick could fail) */ 25874f1b2e48SStefano Zampini zerodiag_subs = NULL; 25883b03f7bbSStefano Zampini benign_n = 0; 25891f4df5f7SStefano Zampini n_interior_dofs = 0; 25901f4df5f7SStefano Zampini interior_dofs = NULL; 25914edc6404Sstefano_zampini nneu = 0; 259248a46eb9SPierre Jolivet if (pcbddc->NeumannBoundariesLocal) PetscCall(ISGetLocalSize(pcbddc->NeumannBoundariesLocal, &nneu)); 25933369cb78Sstefano_zampini checkb = (PetscBool)(!pcbddc->NeumannBoundariesLocal || pcbddc->current_level); 25944edc6404Sstefano_zampini if (checkb) { /* need to compute interior nodes */ 25951f4df5f7SStefano Zampini PetscInt n, i, j; 25961f4df5f7SStefano Zampini PetscInt n_neigh, *neigh, *n_shared, **shared; 25971f4df5f7SStefano Zampini PetscInt *iwork; 25981f4df5f7SStefano Zampini 25999566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->rmapping, &n)); 26009566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetInfo(matis->rmapping, &n_neigh, &neigh, &n_shared, &shared)); 26019566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(n, &iwork)); 26029566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &interior_dofs)); 260390648384SStefano Zampini for (i = 1; i < n_neigh; i++) 26049371c9d4SSatish Balay for (j = 0; j < n_shared[i]; j++) iwork[shared[i][j]] += 1; 26051f4df5f7SStefano Zampini for (i = 0; i < n; i++) 26069371c9d4SSatish Balay if (!iwork[i]) interior_dofs[n_interior_dofs++] = i; 26079566063dSJacob Faibussowitsch PetscCall(PetscFree(iwork)); 26089566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreInfo(matis->rmapping, &n_neigh, &neigh, &n_shared, &shared)); 26091f4df5f7SStefano Zampini } 26104f1b2e48SStefano Zampini if (has_null_pressures) { 26114f1b2e48SStefano Zampini IS *subs; 26124edc6404Sstefano_zampini PetscInt nsubs, i, j, nl; 26131f4df5f7SStefano Zampini const PetscInt *idxs; 26141f4df5f7SStefano Zampini PetscScalar *array; 26151f4df5f7SStefano Zampini Vec *work; 26164f1b2e48SStefano Zampini 26174f1b2e48SStefano Zampini subs = pcbddc->local_subs; 26184f1b2e48SStefano Zampini nsubs = pcbddc->n_local_subs; 26191f4df5f7SStefano 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) */ 26204edc6404Sstefano_zampini if (checkb) { 26219566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(matis->y, 2, &work)); 26229566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zerodiag, &nl)); 26239566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zerodiag, &idxs)); 26241f4df5f7SStefano Zampini /* work[0] = 1_p */ 26259566063dSJacob Faibussowitsch PetscCall(VecSet(work[0], 0.)); 26269566063dSJacob Faibussowitsch PetscCall(VecGetArray(work[0], &array)); 26271f4df5f7SStefano Zampini for (j = 0; j < nl; j++) array[idxs[j]] = 1.; 26289566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(work[0], &array)); 26291f4df5f7SStefano Zampini /* work[0] = 1_v */ 26309566063dSJacob Faibussowitsch PetscCall(VecSet(work[1], 1.)); 26319566063dSJacob Faibussowitsch PetscCall(VecGetArray(work[1], &array)); 26321f4df5f7SStefano Zampini for (j = 0; j < nl; j++) array[idxs[j]] = 0.; 26339566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(work[1], &array)); 26349566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zerodiag, &idxs)); 26351f4df5f7SStefano Zampini } 26363b03f7bbSStefano Zampini 26373b03f7bbSStefano Zampini if (nsubs > 1 || bsp > 1) { 26383b03f7bbSStefano Zampini IS *is; 26393b03f7bbSStefano Zampini PetscInt b, totb; 26403b03f7bbSStefano Zampini 26413b03f7bbSStefano Zampini totb = bsp; 26423b03f7bbSStefano Zampini is = bsp > 1 ? bzerodiag : &zerodiag; 26433b03f7bbSStefano Zampini nsubs = PetscMax(nsubs, 1); 26449566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nsubs * totb, &zerodiag_subs)); 26453b03f7bbSStefano Zampini for (b = 0; b < totb; b++) { 26464f1b2e48SStefano Zampini for (i = 0; i < nsubs; i++) { 26474f1b2e48SStefano Zampini ISLocalToGlobalMapping l2g; 26484f1b2e48SStefano Zampini IS t_zerodiag_subs; 26494f1b2e48SStefano Zampini PetscInt nl; 26504f1b2e48SStefano Zampini 26513b03f7bbSStefano Zampini if (subs) { 26529566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(subs[i], &l2g)); 26533b03f7bbSStefano Zampini } else { 26543b03f7bbSStefano Zampini IS tis; 26553b03f7bbSStefano Zampini 26569566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pcbddc->local_mat, &nl, NULL)); 26579566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, nl, 0, 1, &tis)); 26589566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(tis, &l2g)); 26599566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tis)); 26603b03f7bbSStefano Zampini } 26619566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(l2g, IS_GTOLM_DROP, is[b], &t_zerodiag_subs)); 26629566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(t_zerodiag_subs, &nl)); 26634f1b2e48SStefano Zampini if (nl) { 26644f1b2e48SStefano Zampini PetscBool valid = PETSC_TRUE; 26654f1b2e48SStefano Zampini 26664edc6404Sstefano_zampini if (checkb) { 26679566063dSJacob Faibussowitsch PetscCall(VecSet(matis->x, 0)); 26689566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(subs[i], &nl)); 26699566063dSJacob Faibussowitsch PetscCall(ISGetIndices(subs[i], &idxs)); 26709566063dSJacob Faibussowitsch PetscCall(VecGetArray(matis->x, &array)); 26711f4df5f7SStefano Zampini for (j = 0; j < nl; j++) array[idxs[j]] = 1.; 26729566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(matis->x, &array)); 26739566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(subs[i], &idxs)); 26749566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(matis->x, work[0], matis->x)); 26759566063dSJacob Faibussowitsch PetscCall(MatMult(matis->A, matis->x, matis->y)); 26769566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(matis->y, work[1], matis->y)); 26779566063dSJacob Faibussowitsch PetscCall(VecGetArray(matis->y, &array)); 26781f4df5f7SStefano Zampini for (j = 0; j < n_interior_dofs; j++) { 26791f4df5f7SStefano Zampini if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) { 26801f4df5f7SStefano Zampini valid = PETSC_FALSE; 26811f4df5f7SStefano Zampini break; 26821f4df5f7SStefano Zampini } 26831f4df5f7SStefano Zampini } 26849566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(matis->y, &array)); 26851f4df5f7SStefano Zampini } 26866632bad2Sstefano_zampini if (valid && nneu) { 26876632bad2Sstefano_zampini const PetscInt *idxs; 26881f4df5f7SStefano Zampini PetscInt nzb; 26891f4df5f7SStefano Zampini 26909566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->NeumannBoundariesLocal, &idxs)); 26919566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(l2g, IS_GTOLM_DROP, nneu, idxs, &nzb, NULL)); 26929566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->NeumannBoundariesLocal, &idxs)); 26931f4df5f7SStefano Zampini if (nzb) valid = PETSC_FALSE; 26941f4df5f7SStefano Zampini } 26951f4df5f7SStefano Zampini if (valid && pressures) { 26963b03f7bbSStefano Zampini IS t_pressure_subs, tmp; 26973b03f7bbSStefano Zampini PetscInt i1, i2; 26983b03f7bbSStefano Zampini 26999566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(l2g, IS_GTOLM_DROP, pressures, &t_pressure_subs)); 27009566063dSJacob Faibussowitsch PetscCall(ISEmbed(t_zerodiag_subs, t_pressure_subs, PETSC_TRUE, &tmp)); 27019566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(tmp, &i1)); 27029566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(t_zerodiag_subs, &i2)); 27033b03f7bbSStefano Zampini if (i2 != i1) valid = PETSC_FALSE; 27049566063dSJacob Faibussowitsch PetscCall(ISDestroy(&t_pressure_subs)); 27059566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tmp)); 27064f1b2e48SStefano Zampini } 27074f1b2e48SStefano Zampini if (valid) { 27089566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(l2g, t_zerodiag_subs, &zerodiag_subs[benign_n])); 27093b03f7bbSStefano Zampini benign_n++; 27103b03f7bbSStefano Zampini } else recompute_zerodiag = PETSC_TRUE; 27114f1b2e48SStefano Zampini } 27129566063dSJacob Faibussowitsch PetscCall(ISDestroy(&t_zerodiag_subs)); 27139566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&l2g)); 27144f1b2e48SStefano Zampini } 27153b03f7bbSStefano Zampini } 27164f1b2e48SStefano Zampini } else { /* there's just one subdomain (or zero if they have not been detected */ 27174f1b2e48SStefano Zampini PetscBool valid = PETSC_TRUE; 27181f4df5f7SStefano Zampini 27196632bad2Sstefano_zampini if (nneu) valid = PETSC_FALSE; 272048a46eb9SPierre Jolivet if (valid && pressures) PetscCall(ISEqual(pressures, zerodiag, &valid)); 27214edc6404Sstefano_zampini if (valid && checkb) { 27229566063dSJacob Faibussowitsch PetscCall(MatMult(matis->A, work[0], matis->x)); 27239566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(matis->x, work[1], matis->x)); 27249566063dSJacob Faibussowitsch PetscCall(VecGetArray(matis->x, &array)); 27251f4df5f7SStefano Zampini for (j = 0; j < n_interior_dofs; j++) { 27261f4df5f7SStefano Zampini if (PetscAbsScalar(array[interior_dofs[j]]) > PETSC_SMALL) { 27271f4df5f7SStefano Zampini valid = PETSC_FALSE; 27281f4df5f7SStefano Zampini break; 27291f4df5f7SStefano Zampini } 27301f4df5f7SStefano Zampini } 27319566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(matis->x, &array)); 27321f4df5f7SStefano Zampini } 27334f1b2e48SStefano Zampini if (valid) { 27343b03f7bbSStefano Zampini benign_n = 1; 27359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(benign_n, &zerodiag_subs)); 27369566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)zerodiag)); 27374f1b2e48SStefano Zampini zerodiag_subs[0] = zerodiag; 27384f1b2e48SStefano Zampini } 27394f1b2e48SStefano Zampini } 274048a46eb9SPierre Jolivet if (checkb) PetscCall(VecDestroyVecs(2, &work)); 27411f4df5f7SStefano Zampini } 27429566063dSJacob Faibussowitsch PetscCall(PetscFree(interior_dofs)); 27434f1b2e48SStefano Zampini 27443b03f7bbSStefano Zampini if (!benign_n) { 2745b9b0e38cSStefano Zampini PetscInt n; 2746b9b0e38cSStefano Zampini 27479566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zerodiag)); 27484f1b2e48SStefano Zampini recompute_zerodiag = PETSC_FALSE; 27499566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pcbddc->local_mat, &n, NULL)); 275076a58201SStefano Zampini if (n) have_null = PETSC_FALSE; 2751b9b0e38cSStefano Zampini } 27524f1b2e48SStefano Zampini 27534f1b2e48SStefano Zampini /* final check for null pressures */ 275448a46eb9SPierre Jolivet if (zerodiag && pressures) PetscCall(ISEqual(pressures, zerodiag, &have_null)); 27554f1b2e48SStefano Zampini 27564f1b2e48SStefano Zampini if (recompute_zerodiag) { 27579566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zerodiag)); 27583b03f7bbSStefano Zampini if (benign_n == 1) { 27599566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)zerodiag_subs[0])); 27604f1b2e48SStefano Zampini zerodiag = zerodiag_subs[0]; 27614f1b2e48SStefano Zampini } else { 27624f1b2e48SStefano Zampini PetscInt i, nzn, *new_idxs; 27634f1b2e48SStefano Zampini 27644f1b2e48SStefano Zampini nzn = 0; 27653b03f7bbSStefano Zampini for (i = 0; i < benign_n; i++) { 27664f1b2e48SStefano Zampini PetscInt ns; 27679566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zerodiag_subs[i], &ns)); 27684f1b2e48SStefano Zampini nzn += ns; 27694f1b2e48SStefano Zampini } 27709566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nzn, &new_idxs)); 27714f1b2e48SStefano Zampini nzn = 0; 27723b03f7bbSStefano Zampini for (i = 0; i < benign_n; i++) { 27734f1b2e48SStefano Zampini PetscInt ns, *idxs; 27749566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zerodiag_subs[i], &ns)); 27759566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zerodiag_subs[i], (const PetscInt **)&idxs)); 27769566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(new_idxs + nzn, idxs, ns)); 27779566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zerodiag_subs[i], (const PetscInt **)&idxs)); 27784f1b2e48SStefano Zampini nzn += ns; 27794f1b2e48SStefano Zampini } 27809566063dSJacob Faibussowitsch PetscCall(PetscSortInt(nzn, new_idxs)); 27819566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nzn, new_idxs, PETSC_OWN_POINTER, &zerodiag)); 27824f1b2e48SStefano Zampini } 27834f1b2e48SStefano Zampini have_null = PETSC_FALSE; 27844f1b2e48SStefano Zampini } 27854f1b2e48SStefano Zampini 27863b03f7bbSStefano Zampini /* determines if the coarse solver will be singular or not */ 27871c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&have_null, &pcbddc->benign_null, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)pc))); 27883b03f7bbSStefano Zampini 2789669cc0f4SStefano Zampini /* Prepare matrix to compute no-net-flux */ 2790a198735bSStefano Zampini if (pcbddc->compute_nonetflux && !pcbddc->divudotp) { 2791a198735bSStefano Zampini Mat A, loc_divudotp; 2792a198735bSStefano Zampini ISLocalToGlobalMapping rl2g, cl2g, l2gmap; 2793a198735bSStefano Zampini IS row, col, isused = NULL; 2794a198735bSStefano Zampini PetscInt M, N, n, st, n_isused; 2795a198735bSStefano Zampini 27961f4df5f7SStefano Zampini if (pressures) { 27971f4df5f7SStefano Zampini isused = pressures; 27981f4df5f7SStefano Zampini } else { 27994edc6404Sstefano_zampini isused = zerodiag_save; 28001f4df5f7SStefano Zampini } 28019566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(pc->pmat, &l2gmap, NULL)); 28029566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pc->pmat, &A)); 28039566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &n, NULL)); 28047827d75bSBarry 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"); 2805a198735bSStefano Zampini n_isused = 0; 280648a46eb9SPierre Jolivet if (isused) PetscCall(ISGetLocalSize(isused, &n_isused)); 28079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Scan(&n_isused, &st, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)pc))); 2808a198735bSStefano Zampini st = st - n_isused; 28091ae86dd6SStefano Zampini if (n) { 2810a198735bSStefano Zampini const PetscInt *gidxs; 2811a198735bSStefano Zampini 28129566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, isused, NULL, MAT_INITIAL_MATRIX, &loc_divudotp)); 28139566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(l2gmap, &gidxs)); 2814a198735bSStefano Zampini /* TODO: extend ISCreateStride with st = PETSC_DECIDE */ 28159566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)pc), n_isused, st, 1, &row)); 28169566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), n, gidxs, PETSC_COPY_VALUES, &col)); 28179566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(l2gmap, &gidxs)); 28181ae86dd6SStefano Zampini } else { 28199566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, 0, 0, 1, NULL, &loc_divudotp)); 28209566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)pc), n_isused, st, 1, &row)); 28219566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), 0, NULL, PETSC_COPY_VALUES, &col)); 2822a198735bSStefano Zampini } 28239566063dSJacob Faibussowitsch PetscCall(MatGetSize(pc->pmat, NULL, &N)); 28249566063dSJacob Faibussowitsch PetscCall(ISGetSize(row, &M)); 28259566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(row, &rl2g)); 28269566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(col, &cl2g)); 28279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&row)); 28289566063dSJacob Faibussowitsch PetscCall(ISDestroy(&col)); 28299566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)pc), &pcbddc->divudotp)); 28309566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->divudotp, MATIS)); 28319566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->divudotp, PETSC_DECIDE, PETSC_DECIDE, M, N)); 28329566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(pcbddc->divudotp, rl2g, cl2g)); 28339566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 28349566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 28359566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(pcbddc->divudotp, loc_divudotp)); 28369566063dSJacob Faibussowitsch PetscCall(MatDestroy(&loc_divudotp)); 28379566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pcbddc->divudotp, MAT_FINAL_ASSEMBLY)); 28389566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->divudotp, MAT_FINAL_ASSEMBLY)); 28391ae86dd6SStefano Zampini } 28409566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zerodiag_save)); 28419566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pressures)); 28423b03f7bbSStefano Zampini if (bzerodiag) { 28433b03f7bbSStefano Zampini PetscInt i; 2844b3afcdbeSStefano Zampini 284548a46eb9SPierre Jolivet for (i = 0; i < bsp; i++) PetscCall(ISDestroy(&bzerodiag[i])); 28469566063dSJacob Faibussowitsch PetscCall(PetscFree(bzerodiag)); 28473b03f7bbSStefano Zampini } 28483b03f7bbSStefano Zampini pcbddc->benign_n = benign_n; 28493b03f7bbSStefano Zampini pcbddc->benign_zerodiag_subs = zerodiag_subs; 28503b03f7bbSStefano Zampini 28513b03f7bbSStefano Zampini /* determines if the problem has subdomains with 0 pressure block */ 28523b03f7bbSStefano Zampini have_null = (PetscBool)(!!pcbddc->benign_n); 28531c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&have_null, &pcbddc->benign_have_null, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 28543b03f7bbSStefano Zampini 28553b03f7bbSStefano Zampini project_b0: 28569566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pcbddc->local_mat, &n, NULL)); 2857b3afcdbeSStefano Zampini /* change of basis and p0 dofs */ 28583b03f7bbSStefano Zampini if (pcbddc->benign_n) { 28594f1b2e48SStefano Zampini PetscInt i, s, *nnz; 28604f1b2e48SStefano Zampini 2861339f8db1SStefano Zampini /* local change of basis for pressures */ 28629566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->benign_change)); 28639566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat), &pcbddc->benign_change)); 28649566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->benign_change, MATAIJ)); 28659566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->benign_change, n, n, PETSC_DECIDE, PETSC_DECIDE)); 28669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &nnz)); 2867aa0d93e9SStefano Zampini for (i = 0; i < n; i++) nnz[i] = 1; /* defaults to identity */ 28684f1b2e48SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) { 2869aa0d93e9SStefano Zampini const PetscInt *idxs; 28704f1b2e48SStefano Zampini PetscInt nzs, j; 28714f1b2e48SStefano Zampini 28729566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[i], &nzs)); 28739566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->benign_zerodiag_subs[i], &idxs)); 28744f1b2e48SStefano Zampini for (j = 0; j < nzs - 1; j++) nnz[idxs[j]] = 2; /* change on pressures */ 28754f1b2e48SStefano Zampini nnz[idxs[nzs - 1]] = nzs; /* last local pressure dof in subdomain */ 28769566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->benign_zerodiag_subs[i], &idxs)); 28774f1b2e48SStefano Zampini } 28789566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(pcbddc->benign_change, 0, nnz)); 28799566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->benign_change, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 28809566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 2881aa0d93e9SStefano Zampini /* set identity by default */ 288248a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall(MatSetValue(pcbddc->benign_change, i, i, 1., INSERT_VALUES)); 28839566063dSJacob Faibussowitsch PetscCall(PetscFree3(pcbddc->benign_p0_lidx, pcbddc->benign_p0_gidx, pcbddc->benign_p0)); 28849566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(pcbddc->benign_n, &pcbddc->benign_p0_lidx, pcbddc->benign_n, &pcbddc->benign_p0_gidx, pcbddc->benign_n, &pcbddc->benign_p0)); 2885339f8db1SStefano Zampini /* set change on pressures */ 28864f1b2e48SStefano Zampini for (s = 0; s < pcbddc->benign_n; s++) { 28874f1b2e48SStefano Zampini PetscScalar *array; 2888aa0d93e9SStefano Zampini const PetscInt *idxs; 28894f1b2e48SStefano Zampini PetscInt nzs; 28904f1b2e48SStefano Zampini 28919566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[s], &nzs)); 28929566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->benign_zerodiag_subs[s], &idxs)); 28934f1b2e48SStefano Zampini for (i = 0; i < nzs - 1; i++) { 2894339f8db1SStefano Zampini PetscScalar vals[2]; 2895339f8db1SStefano Zampini PetscInt cols[2]; 2896339f8db1SStefano Zampini 2897339f8db1SStefano Zampini cols[0] = idxs[i]; 28984f1b2e48SStefano Zampini cols[1] = idxs[nzs - 1]; 2899339f8db1SStefano Zampini vals[0] = 1.; 2900b0f5fe93SStefano Zampini vals[1] = 1.; 29019566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->benign_change, 1, cols, 2, cols, vals, INSERT_VALUES)); 2902339f8db1SStefano Zampini } 29039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nzs, &array)); 29044f1b2e48SStefano Zampini for (i = 0; i < nzs - 1; i++) array[i] = -1.; 29054f1b2e48SStefano Zampini array[nzs - 1] = 1.; 29069566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->benign_change, 1, idxs + nzs - 1, nzs, idxs, array, INSERT_VALUES)); 29074f1b2e48SStefano Zampini /* store local idxs for p0 */ 29084f1b2e48SStefano Zampini pcbddc->benign_p0_lidx[s] = idxs[nzs - 1]; 29099566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->benign_zerodiag_subs[s], &idxs)); 29109566063dSJacob Faibussowitsch PetscCall(PetscFree(array)); 29114f1b2e48SStefano Zampini } 29129566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pcbddc->benign_change, MAT_FINAL_ASSEMBLY)); 29139566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->benign_change, MAT_FINAL_ASSEMBLY)); 29143b03f7bbSStefano Zampini 2915a3df083aSStefano Zampini /* project if needed */ 2916a3df083aSStefano Zampini if (pcbddc->benign_change_explicit) { 29171dd7afcfSStefano Zampini Mat M; 29181dd7afcfSStefano Zampini 29199566063dSJacob Faibussowitsch PetscCall(MatPtAP(pcbddc->local_mat, pcbddc->benign_change, MAT_INITIAL_MATRIX, 2.0, &M)); 29209566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 29219566063dSJacob Faibussowitsch PetscCall(MatSeqAIJCompress(M, &pcbddc->local_mat)); 29229566063dSJacob Faibussowitsch PetscCall(MatDestroy(&M)); 2923a3df083aSStefano Zampini } 29244f1b2e48SStefano Zampini /* store global idxs for p0 */ 29259566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(matis->rmapping, pcbddc->benign_n, pcbddc->benign_p0_lidx, pcbddc->benign_p0_gidx)); 2926339f8db1SStefano Zampini } 2927339f8db1SStefano Zampini *zerodiaglocal = zerodiag; 29283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2929339f8db1SStefano Zampini } 2930339f8db1SStefano Zampini 2931d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignGetOrSetP0(PC pc, Vec v, PetscBool get) 2932d71ae5a4SJacob Faibussowitsch { 2933efc2fbd9SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 2934de9d7bd0SStefano Zampini PetscScalar *array; 2935efc2fbd9SStefano Zampini 2936efc2fbd9SStefano Zampini PetscFunctionBegin; 2937efc2fbd9SStefano Zampini if (!pcbddc->benign_sf) { 29389566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)pc), &pcbddc->benign_sf)); 29399566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(pcbddc->benign_sf, pc->pmat->rmap, pcbddc->benign_n, NULL, PETSC_OWN_POINTER, pcbddc->benign_p0_gidx)); 2940efc2fbd9SStefano Zampini } 2941de9d7bd0SStefano Zampini if (get) { 29429566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, (const PetscScalar **)&array)); 29439566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(pcbddc->benign_sf, MPIU_SCALAR, array, pcbddc->benign_p0, MPI_REPLACE)); 29449566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(pcbddc->benign_sf, MPIU_SCALAR, array, pcbddc->benign_p0, MPI_REPLACE)); 29459566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, (const PetscScalar **)&array)); 2946de9d7bd0SStefano Zampini } else { 29479566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &array)); 29489566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(pcbddc->benign_sf, MPIU_SCALAR, pcbddc->benign_p0, array, MPI_REPLACE)); 29499566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(pcbddc->benign_sf, MPIU_SCALAR, pcbddc->benign_p0, array, MPI_REPLACE)); 29509566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &array)); 2951efc2fbd9SStefano Zampini } 29523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2953efc2fbd9SStefano Zampini } 2954efc2fbd9SStefano Zampini 2955d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCBenignPopOrPushB0(PC pc, PetscBool pop) 2956d71ae5a4SJacob Faibussowitsch { 2957c263805aSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 2958c263805aSStefano Zampini 2959c263805aSStefano Zampini PetscFunctionBegin; 2960c263805aSStefano Zampini /* TODO: add error checking 2961c263805aSStefano Zampini - avoid nested pop (or push) calls. 2962c263805aSStefano Zampini - cannot push before pop. 29631c604dc7SStefano Zampini - cannot call this if pcbddc->local_mat is NULL 2964c263805aSStefano Zampini */ 29653ba16761SJacob Faibussowitsch if (!pcbddc->benign_n) PetscFunctionReturn(PETSC_SUCCESS); 2966c263805aSStefano Zampini if (pop) { 2967a3df083aSStefano Zampini if (pcbddc->benign_change_explicit) { 29684f1b2e48SStefano Zampini IS is_p0; 29694f1b2e48SStefano Zampini MatReuse reuse; 2970c263805aSStefano Zampini 2971c263805aSStefano Zampini /* extract B_0 */ 29724f1b2e48SStefano Zampini reuse = MAT_INITIAL_MATRIX; 2973ad540459SPierre Jolivet if (pcbddc->benign_B0) reuse = MAT_REUSE_MATRIX; 29749566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, pcbddc->benign_n, pcbddc->benign_p0_lidx, PETSC_COPY_VALUES, &is_p0)); 29759566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, is_p0, NULL, reuse, &pcbddc->benign_B0)); 2976c263805aSStefano Zampini /* remove rows and cols from local problem */ 29779566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->local_mat, MAT_KEEP_NONZERO_PATTERN, PETSC_TRUE)); 29789566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->local_mat, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_FALSE)); 29799566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumnsIS(pcbddc->local_mat, is_p0, 1.0, NULL, NULL)); 29809566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_p0)); 2981a3df083aSStefano Zampini } else { 2982a3df083aSStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 2983a3df083aSStefano Zampini PetscScalar *vals; 2984a3df083aSStefano Zampini PetscInt i, n, *idxs_ins; 2985a3df083aSStefano Zampini 29869566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(matis->y, &n)); 29879566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n, &idxs_ins, n, &vals)); 2988a3df083aSStefano Zampini if (!pcbddc->benign_B0) { 29890b5adadeSStefano Zampini PetscInt *nnz; 29909566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)pcbddc->local_mat), &pcbddc->benign_B0)); 29919566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->benign_B0, MATAIJ)); 29929566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->benign_B0, pcbddc->benign_n, n, PETSC_DECIDE, PETSC_DECIDE)); 29939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->benign_n, &nnz)); 2994331e053bSStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) { 29959566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[i], &nnz[i])); 2996331e053bSStefano Zampini nnz[i] = n - nnz[i]; 2997331e053bSStefano Zampini } 29989566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(pcbddc->benign_B0, 0, nnz)); 29999566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->benign_B0, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 30009566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 3001331e053bSStefano Zampini } 3002a3df083aSStefano Zampini 3003a3df083aSStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) { 3004a3df083aSStefano Zampini PetscScalar *array; 3005a3df083aSStefano Zampini PetscInt *idxs, j, nz, cum; 3006a3df083aSStefano Zampini 30079566063dSJacob Faibussowitsch PetscCall(VecSet(matis->x, 0.)); 30089566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->benign_zerodiag_subs[i], &nz)); 30099566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->benign_zerodiag_subs[i], (const PetscInt **)&idxs)); 3010a3df083aSStefano Zampini for (j = 0; j < nz; j++) vals[j] = 1.; 30119566063dSJacob Faibussowitsch PetscCall(VecSetValues(matis->x, nz, idxs, vals, INSERT_VALUES)); 30129566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(matis->x)); 30139566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(matis->x)); 30149566063dSJacob Faibussowitsch PetscCall(VecSet(matis->y, 0.)); 30159566063dSJacob Faibussowitsch PetscCall(MatMult(matis->A, matis->x, matis->y)); 30169566063dSJacob Faibussowitsch PetscCall(VecGetArray(matis->y, &array)); 3017a3df083aSStefano Zampini cum = 0; 3018a3df083aSStefano Zampini for (j = 0; j < n; j++) { 301922db5ddcSStefano Zampini if (PetscUnlikely(PetscAbsScalar(array[j]) > PETSC_SMALL)) { 3020a3df083aSStefano Zampini vals[cum] = array[j]; 3021a3df083aSStefano Zampini idxs_ins[cum] = j; 3022a3df083aSStefano Zampini cum++; 3023a3df083aSStefano Zampini } 3024a3df083aSStefano Zampini } 30259566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->benign_B0, 1, &i, cum, idxs_ins, vals, INSERT_VALUES)); 30269566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(matis->y, &array)); 30279566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->benign_zerodiag_subs[i], (const PetscInt **)&idxs)); 3028a3df083aSStefano Zampini } 30299566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pcbddc->benign_B0, MAT_FINAL_ASSEMBLY)); 30309566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->benign_B0, MAT_FINAL_ASSEMBLY)); 30319566063dSJacob Faibussowitsch PetscCall(PetscFree2(idxs_ins, vals)); 3032a3df083aSStefano Zampini } 3033c263805aSStefano Zampini } else { /* push */ 30344f1b2e48SStefano Zampini 30350fdf79fbSJacob Faibussowitsch PetscCheck(pcbddc->benign_change_explicit, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Cannot push B0!"); 30360fdf79fbSJacob Faibussowitsch for (PetscInt i = 0; i < pcbddc->benign_n; i++) { 30374f1b2e48SStefano Zampini PetscScalar *B0_vals; 30384f1b2e48SStefano Zampini PetscInt *B0_cols, B0_ncol; 30394f1b2e48SStefano Zampini 30409566063dSJacob Faibussowitsch PetscCall(MatGetRow(pcbddc->benign_B0, i, &B0_ncol, (const PetscInt **)&B0_cols, (const PetscScalar **)&B0_vals)); 30419566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->local_mat, 1, pcbddc->benign_p0_lidx + i, B0_ncol, B0_cols, B0_vals, INSERT_VALUES)); 30429566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->local_mat, B0_ncol, B0_cols, 1, pcbddc->benign_p0_lidx + i, B0_vals, INSERT_VALUES)); 30439566063dSJacob Faibussowitsch PetscCall(MatSetValue(pcbddc->local_mat, pcbddc->benign_p0_lidx[i], pcbddc->benign_p0_lidx[i], 0.0, INSERT_VALUES)); 30449566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(pcbddc->benign_B0, i, &B0_ncol, (const PetscInt **)&B0_cols, (const PetscScalar **)&B0_vals)); 30454f1b2e48SStefano Zampini } 30469566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pcbddc->local_mat, MAT_FINAL_ASSEMBLY)); 30479566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->local_mat, MAT_FINAL_ASSEMBLY)); 3048c263805aSStefano Zampini } 30493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3050c263805aSStefano Zampini } 3051c263805aSStefano Zampini 3052d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCAdaptiveSelection(PC pc) 3053d71ae5a4SJacob Faibussowitsch { 3054b1b3d7a2SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 305508122e43SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 305608122e43SStefano Zampini PetscBLASInt B_dummyint, B_neigs, B_ierr, B_lwork; 305708122e43SStefano Zampini PetscBLASInt *B_iwork, *B_ifail; 305808122e43SStefano Zampini PetscScalar *work, lwork; 305908122e43SStefano Zampini PetscScalar *St, *S, *eigv; 306008122e43SStefano Zampini PetscScalar *Sarray, *Starray; 3061bd2a564bSStefano Zampini PetscReal *eigs, thresh, lthresh, uthresh; 30621b968477SStefano Zampini PetscInt i, nmax, nmin, nv, cum, mss, cum2, cumarray, maxneigs; 306332fe681dSStefano Zampini PetscBool allocated_S_St, upart; 306408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 306508122e43SStefano Zampini PetscReal *rwork; 306608122e43SStefano Zampini #endif 3067b1b3d7a2SStefano Zampini 3068b1b3d7a2SStefano Zampini PetscFunctionBegin; 30693ba16761SJacob Faibussowitsch if (!pcbddc->adaptive_selection) PetscFunctionReturn(PETSC_SUCCESS); 307028b400f6SJacob Faibussowitsch PetscCheck(sub_schurs, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Adaptive selection of constraints requires SubSchurs data"); 307132fe681dSStefano 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"); 30729371c9d4SSatish 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, 30739371c9d4SSatish Balay sub_schurs->is_posdef); 30749566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_AdaptiveSetUp[pcbddc->current_level], pc, 0, 0, 0)); 307506a4e24aSStefano Zampini 3076fd14bc51SStefano Zampini if (pcbddc->dbg_flag) { 307732fe681dSStefano Zampini if (!pcbddc->dbg_viewer) pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc)); 30789566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 30799566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 30809566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Check adaptive selection of constraints\n")); 30819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 3082fd14bc51SStefano Zampini } 3083fd14bc51SStefano Zampini 308448a46eb9SPierre 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)); 3085e496cd5dSStefano Zampini 308608122e43SStefano Zampini /* max size of subsets */ 308708122e43SStefano Zampini mss = 0; 308808122e43SStefano Zampini for (i = 0; i < sub_schurs->n_subs; i++) { 308908122e43SStefano Zampini PetscInt subset_size; 3090862806e4SStefano Zampini 30919566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->is_subs[i], &subset_size)); 309208122e43SStefano Zampini mss = PetscMax(mss, subset_size); 309308122e43SStefano Zampini } 309408122e43SStefano Zampini 309508122e43SStefano Zampini /* min/max and threshold */ 309608122e43SStefano Zampini nmax = pcbddc->adaptive_nmax > 0 ? pcbddc->adaptive_nmax : mss; 3097f6f667cfSStefano Zampini nmin = pcbddc->adaptive_nmin > 0 ? pcbddc->adaptive_nmin : 0; 309808122e43SStefano Zampini nmax = PetscMax(nmin, nmax); 3099f6f667cfSStefano Zampini allocated_S_St = PETSC_FALSE; 3100bd2a564bSStefano Zampini if (nmin || !sub_schurs->is_posdef) { /* XXX */ 3101f6f667cfSStefano Zampini allocated_S_St = PETSC_TRUE; 3102f6f667cfSStefano Zampini } 310308122e43SStefano Zampini 310408122e43SStefano Zampini /* allocate lapack workspace */ 310508122e43SStefano Zampini cum = cum2 = 0; 310608122e43SStefano Zampini maxneigs = 0; 310708122e43SStefano Zampini for (i = 0; i < sub_schurs->n_subs; i++) { 310808122e43SStefano Zampini PetscInt n, subset_size; 3109f6f667cfSStefano Zampini 31109566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->is_subs[i], &subset_size)); 311108122e43SStefano Zampini n = PetscMin(subset_size, nmax); 31129162d606SStefano Zampini cum += subset_size; 31139162d606SStefano Zampini cum2 += subset_size * n; 311408122e43SStefano Zampini maxneigs = PetscMax(maxneigs, n); 311508122e43SStefano Zampini } 31167ebab0bbSStefano Zampini lwork = 0; 311708122e43SStefano Zampini if (mss) { 31187ebab0bbSStefano Zampini PetscScalar sdummy = 0.; 311908122e43SStefano Zampini PetscBLASInt B_itype = 1; 31207ebab0bbSStefano Zampini PetscBLASInt B_N = mss, idummy = 0; 31217ebab0bbSStefano Zampini PetscReal rdummy = 0., zero = 0.0; 31224c6709b3SStefano Zampini PetscReal eps = 0.0; /* dlamch? */ 312308122e43SStefano Zampini 31240fdf79fbSJacob Faibussowitsch PetscCheck(sub_schurs->is_symmetric, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not yet implemented"); 312508122e43SStefano Zampini B_lwork = -1; 31267ebab0bbSStefano Zampini /* some implementations may complain about NULL pointers, even if we are querying */ 31277ebab0bbSStefano Zampini S = &sdummy; 31287ebab0bbSStefano Zampini St = &sdummy; 31297ebab0bbSStefano Zampini eigs = &rdummy; 31307ebab0bbSStefano Zampini eigv = &sdummy; 31317ebab0bbSStefano Zampini B_iwork = &idummy; 31327ebab0bbSStefano Zampini B_ifail = &idummy; 3133d1710679SStefano Zampini #if defined(PETSC_USE_COMPLEX) 31347ebab0bbSStefano Zampini rwork = &rdummy; 3135d1710679SStefano Zampini #endif 31368bec7fa6SStefano Zampini thresh = 1.0; 31379566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 313808122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 3139792fecdfSBarry Smith PetscCallBLAS("LAPACKsygvx", LAPACKsygvx_(&B_itype, "V", "V", "L", &B_N, St, &B_N, S, &B_N, &zero, &thresh, &B_dummyint, &B_dummyint, &eps, &B_neigs, eigs, eigv, &B_N, &lwork, &B_lwork, rwork, B_iwork, B_ifail, &B_ierr)); 314008122e43SStefano Zampini #else 3141792fecdfSBarry Smith PetscCallBLAS("LAPACKsygvx", LAPACKsygvx_(&B_itype, "V", "V", "L", &B_N, St, &B_N, S, &B_N, &zero, &thresh, &B_dummyint, &B_dummyint, &eps, &B_neigs, eigs, eigv, &B_N, &lwork, &B_lwork, B_iwork, B_ifail, &B_ierr)); 314208122e43SStefano Zampini #endif 314308401ef6SPierre Jolivet PetscCheck(B_ierr == 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in query to SYGVX Lapack routine %d", (int)B_ierr); 31449566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 314508122e43SStefano Zampini } 314608122e43SStefano Zampini 314708122e43SStefano Zampini nv = 0; 3148d62866d3SStefano 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) */ 31499566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->is_vertices, &nv)); 315008122e43SStefano Zampini } 31519566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(lwork), &B_lwork)); 315248a46eb9SPierre Jolivet if (allocated_S_St) PetscCall(PetscMalloc2(mss * mss, &S, mss * mss, &St)); 31539566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(mss * mss, &eigv, mss, &eigs, B_lwork, &work, 5 * mss, &B_iwork, mss, &B_ifail)); 315408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 31559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(7 * mss, &rwork)); 315608122e43SStefano Zampini #endif 31579371c9d4SSatish 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, 31589371c9d4SSatish Balay &pcbddc->adaptive_constraints_data)); 31599566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(pcbddc->adaptive_constraints_n, nv + sub_schurs->n_subs)); 316008122e43SStefano Zampini 316108122e43SStefano Zampini maxneigs = 0; 316272b8c272SStefano Zampini cum = cumarray = 0; 31639162d606SStefano Zampini pcbddc->adaptive_constraints_idxs_ptr[0] = 0; 31649162d606SStefano Zampini pcbddc->adaptive_constraints_data_ptr[0] = 0; 3165d62866d3SStefano Zampini if (sub_schurs->is_vertices && pcbddc->use_vertices) { 316608122e43SStefano Zampini const PetscInt *idxs; 316708122e43SStefano Zampini 31689566063dSJacob Faibussowitsch PetscCall(ISGetIndices(sub_schurs->is_vertices, &idxs)); 316908122e43SStefano Zampini for (cum = 0; cum < nv; cum++) { 317008122e43SStefano Zampini pcbddc->adaptive_constraints_n[cum] = 1; 317108122e43SStefano Zampini pcbddc->adaptive_constraints_idxs[cum] = idxs[cum]; 317208122e43SStefano Zampini pcbddc->adaptive_constraints_data[cum] = 1.0; 31739162d606SStefano Zampini pcbddc->adaptive_constraints_idxs_ptr[cum + 1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + 1; 31749162d606SStefano Zampini pcbddc->adaptive_constraints_data_ptr[cum + 1] = pcbddc->adaptive_constraints_data_ptr[cum] + 1; 317508122e43SStefano Zampini } 31769566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(sub_schurs->is_vertices, &idxs)); 317708122e43SStefano Zampini } 317808122e43SStefano Zampini 317908122e43SStefano Zampini if (mss) { /* multilevel */ 318032fe681dSStefano Zampini if (sub_schurs->gdsw) { 318132fe681dSStefano Zampini PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_all, &Sarray)); 318232fe681dSStefano Zampini PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all, &Starray)); 318332fe681dSStefano Zampini } else { 31849566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_inv_all, &Sarray)); 31859566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all, &Starray)); 318608122e43SStefano Zampini } 318732fe681dSStefano Zampini } 318808122e43SStefano Zampini 3189bd2a564bSStefano Zampini lthresh = pcbddc->adaptive_threshold[0]; 3190bd2a564bSStefano Zampini uthresh = pcbddc->adaptive_threshold[1]; 319132fe681dSStefano Zampini upart = pcbddc->use_deluxe_scaling; 319208122e43SStefano Zampini for (i = 0; i < sub_schurs->n_subs; i++) { 319308122e43SStefano Zampini const PetscInt *idxs; 31949d54b7f4SStefano Zampini PetscReal upper, lower; 3195862806e4SStefano Zampini PetscInt j, subset_size, eigs_start = 0; 319608122e43SStefano Zampini PetscBLASInt B_N; 3197aff50787SStefano Zampini PetscBool same_data = PETSC_FALSE; 3198bd2a564bSStefano Zampini PetscBool scal = PETSC_FALSE; 319908122e43SStefano Zampini 320032fe681dSStefano Zampini if (upart) { 32019d54b7f4SStefano Zampini upper = PETSC_MAX_REAL; 3202bd2a564bSStefano Zampini lower = uthresh; 32039d54b7f4SStefano Zampini } else { 320432fe681dSStefano Zampini if (sub_schurs->gdsw) { 320532fe681dSStefano Zampini upper = uthresh; 320632fe681dSStefano Zampini lower = PETSC_MIN_REAL; 320732fe681dSStefano Zampini } else { 320828b400f6SJacob Faibussowitsch PetscCheck(sub_schurs->is_posdef, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not yet implemented without deluxe scaling"); 3209bd2a564bSStefano Zampini upper = 1. / uthresh; 32109d54b7f4SStefano Zampini lower = 0.; 32119d54b7f4SStefano Zampini } 321232fe681dSStefano Zampini } 32139566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->is_subs[i], &subset_size)); 32149566063dSJacob Faibussowitsch PetscCall(ISGetIndices(sub_schurs->is_subs[i], &idxs)); 32159566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(subset_size, &B_N)); 3216bd2a564bSStefano Zampini /* this is experimental: we assume the dofs have been properly grouped to have 3217bd2a564bSStefano Zampini the diagonal blocks Schur complements either positive or negative definite (true for Stokes) */ 3218bd2a564bSStefano Zampini if (!sub_schurs->is_posdef) { 3219bd2a564bSStefano Zampini Mat T; 3220bd2a564bSStefano Zampini 3221bd2a564bSStefano Zampini for (j = 0; j < subset_size; j++) { 3222bd2a564bSStefano Zampini if (PetscRealPart(*(Sarray + cumarray + j * (subset_size + 1))) < 0.0) { 32239566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, subset_size, subset_size, Sarray + cumarray, &T)); 32249566063dSJacob Faibussowitsch PetscCall(MatScale(T, -1.0)); 32259566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 32269566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, subset_size, subset_size, Starray + cumarray, &T)); 32279566063dSJacob Faibussowitsch PetscCall(MatScale(T, -1.0)); 32289566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 3229bd2a564bSStefano Zampini if (sub_schurs->change_primal_sub) { 3230bd2a564bSStefano Zampini PetscInt nz, k; 3231bd2a564bSStefano Zampini const PetscInt *idxs; 3232bd2a564bSStefano Zampini 32339566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->change_primal_sub[i], &nz)); 32349566063dSJacob Faibussowitsch PetscCall(ISGetIndices(sub_schurs->change_primal_sub[i], &idxs)); 3235bd2a564bSStefano Zampini for (k = 0; k < nz; k++) { 3236bd2a564bSStefano Zampini *(Sarray + cumarray + idxs[k] * (subset_size + 1)) *= -1.0; 3237bd2a564bSStefano Zampini *(Starray + cumarray + idxs[k] * (subset_size + 1)) = 0.0; 3238bd2a564bSStefano Zampini } 32399566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(sub_schurs->change_primal_sub[i], &idxs)); 3240bd2a564bSStefano Zampini } 3241bd2a564bSStefano Zampini scal = PETSC_TRUE; 3242bd2a564bSStefano Zampini break; 3243bd2a564bSStefano Zampini } 3244bd2a564bSStefano Zampini } 3245bd2a564bSStefano Zampini } 3246bd2a564bSStefano Zampini 3247f6f667cfSStefano Zampini if (allocated_S_St) { /* S and S_t should be copied since we could need them later */ 3248bd2a564bSStefano Zampini if (sub_schurs->is_symmetric) { 3249aff50787SStefano Zampini PetscInt j, k; 3250580bdb30SBarry Smith if (sub_schurs->n_subs == 1) { /* zeroing memory to use PetscArraycmp() later */ 32519566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(S, subset_size * subset_size)); 32529566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(St, subset_size * subset_size)); 325308122e43SStefano Zampini } 325408122e43SStefano Zampini for (j = 0; j < subset_size; j++) { 3255aff50787SStefano Zampini for (k = j; k < subset_size; k++) { 3256aff50787SStefano Zampini S[j * subset_size + k] = Sarray[cumarray + j * subset_size + k]; 3257aff50787SStefano Zampini St[j * subset_size + k] = Starray[cumarray + j * subset_size + k]; 3258aff50787SStefano Zampini } 325908122e43SStefano Zampini } 326008122e43SStefano Zampini } else { 32619566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 32629566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 326308122e43SStefano Zampini } 32648bec7fa6SStefano Zampini } else { 3265f6f667cfSStefano Zampini S = Sarray + cumarray; 3266f6f667cfSStefano Zampini St = Starray + cumarray; 32678bec7fa6SStefano Zampini } 3268aff50787SStefano Zampini /* see if we can save some work */ 326948a46eb9SPierre Jolivet if (sub_schurs->n_subs == 1 && pcbddc->use_deluxe_scaling) PetscCall(PetscArraycmp(S, St, subset_size * subset_size, &same_data)); 3270aff50787SStefano Zampini 3271b7ab4a40SStefano Zampini if (same_data && !sub_schurs->change) { /* there's no need of constraints here */ 3272aff50787SStefano Zampini B_neigs = 0; 3273aff50787SStefano Zampini } else { 327408122e43SStefano Zampini PetscBLASInt B_itype = 1; 3275f6f667cfSStefano Zampini PetscBLASInt B_IL, B_IU; 32764c6709b3SStefano Zampini PetscReal eps = -1.0; /* dlamch? */ 32779552c7c7SStefano Zampini PetscInt nmin_s; 3278bd2a564bSStefano Zampini PetscBool compute_range; 3279bd2a564bSStefano Zampini 32800fdf79fbSJacob Faibussowitsch PetscCheck(sub_schurs->is_symmetric, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not yet implemented"); 32819036ceccSStefano Zampini B_neigs = 0; 3282bd2a564bSStefano Zampini compute_range = (PetscBool)!same_data; 3283bd2a564bSStefano Zampini if (nmin >= subset_size) compute_range = PETSC_FALSE; 328408122e43SStefano Zampini 3285fd14bc51SStefano Zampini if (pcbddc->dbg_flag) { 32869036ceccSStefano Zampini PetscInt nc = 0; 3287d16cbb6bSStefano Zampini 328848a46eb9SPierre Jolivet if (sub_schurs->change_primal_sub) PetscCall(ISGetLocalSize(sub_schurs->change_primal_sub[i], &nc)); 32899371c9d4SSatish Balay PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Computing for sub %" PetscInt_FMT "/%" PetscInt_FMT " size %" PetscInt_FMT " count %" PetscInt_FMT " fid %" PetscInt_FMT " (range %d) (change %" PetscInt_FMT ").\n", i, 32909371c9d4SSatish Balay sub_schurs->n_subs, subset_size, pcbddc->mat_graph->count[idxs[0]] + 1, pcbddc->mat_graph->which_dof[idxs[0]], compute_range, nc)); 3291b7ab4a40SStefano Zampini } 3292b7ab4a40SStefano Zampini 32939566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 3294b7ab4a40SStefano Zampini if (compute_range) { 3295d16cbb6bSStefano Zampini /* ask for eigenvalues larger than thresh */ 3296bd2a564bSStefano Zampini if (sub_schurs->is_posdef) { 329708122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 3298792fecdfSBarry 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)); 329908122e43SStefano Zampini #else 3300792fecdfSBarry 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)); 330108122e43SStefano Zampini #endif 33029566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 3303bd2a564bSStefano Zampini } else { /* no theory so far, but it works nicely */ 33049036ceccSStefano Zampini PetscInt recipe = 0, recipe_m = 1; 3305bd2a564bSStefano Zampini PetscReal bb[2]; 3306bd2a564bSStefano Zampini 33079566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)pc)->prefix, "-pc_bddc_adaptive_recipe", &recipe, NULL)); 3308bd2a564bSStefano Zampini switch (recipe) { 3309bd2a564bSStefano Zampini case 0: 33109371c9d4SSatish Balay if (scal) { 33119371c9d4SSatish Balay bb[0] = PETSC_MIN_REAL; 33129371c9d4SSatish Balay bb[1] = lthresh; 33139371c9d4SSatish Balay } else { 33149371c9d4SSatish Balay bb[0] = uthresh; 33159371c9d4SSatish Balay bb[1] = PETSC_MAX_REAL; 33169371c9d4SSatish Balay } 3317bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3318792fecdfSBarry 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)); 3319bd2a564bSStefano Zampini #else 3320792fecdfSBarry 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)); 3321bd2a564bSStefano Zampini #endif 33229566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 3323bd2a564bSStefano Zampini break; 3324d71ae5a4SJacob Faibussowitsch case 1: 3325d71ae5a4SJacob Faibussowitsch bb[0] = PETSC_MIN_REAL; 3326d71ae5a4SJacob Faibussowitsch bb[1] = lthresh * lthresh; 3327bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3328792fecdfSBarry 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)); 3329bd2a564bSStefano Zampini #else 3330792fecdfSBarry 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)); 3331bd2a564bSStefano Zampini #endif 33329566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 3333bd2a564bSStefano Zampini if (!scal) { 33349036ceccSStefano Zampini PetscBLASInt B_neigs2 = 0; 3335bd2a564bSStefano Zampini 33369371c9d4SSatish Balay bb[0] = PetscMax(lthresh * lthresh, uthresh); 33379371c9d4SSatish Balay bb[1] = PETSC_MAX_REAL; 33389566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 33399566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 3340bd2a564bSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3341792fecdfSBarry 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)); 3342bd2a564bSStefano Zampini #else 3343792fecdfSBarry 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)); 3344bd2a564bSStefano Zampini #endif 33459566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 3346bd2a564bSStefano Zampini B_neigs += B_neigs2; 3347bd2a564bSStefano Zampini } 3348bd2a564bSStefano Zampini break; 33499036ceccSStefano Zampini case 2: 33509036ceccSStefano Zampini if (scal) { 33519036ceccSStefano Zampini bb[0] = PETSC_MIN_REAL; 33529036ceccSStefano Zampini bb[1] = 0; 33539036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3354792fecdfSBarry 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)); 33559036ceccSStefano Zampini #else 3356792fecdfSBarry 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)); 33579036ceccSStefano Zampini #endif 33589566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 33599036ceccSStefano Zampini } else { 33609036ceccSStefano Zampini PetscBLASInt B_neigs2 = 0; 336113bcc0bdSJacob Faibussowitsch PetscBool do_copy = PETSC_FALSE; 33629036ceccSStefano Zampini 33639036ceccSStefano Zampini lthresh = PetscMax(lthresh, 0.0); 33649036ceccSStefano Zampini if (lthresh > 0.0) { 33659036ceccSStefano Zampini bb[0] = PETSC_MIN_REAL; 33669036ceccSStefano Zampini bb[1] = lthresh * lthresh; 33679036ceccSStefano Zampini 336813bcc0bdSJacob Faibussowitsch do_copy = PETSC_TRUE; 33699036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3370792fecdfSBarry 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)); 33719036ceccSStefano Zampini #else 3372792fecdfSBarry 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)); 33739036ceccSStefano Zampini #endif 33749566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 33759036ceccSStefano Zampini } 33769036ceccSStefano Zampini bb[0] = PetscMax(lthresh * lthresh, uthresh); 33779036ceccSStefano Zampini bb[1] = PETSC_MAX_REAL; 337813bcc0bdSJacob Faibussowitsch if (do_copy) { 33799566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 33809566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 33819036ceccSStefano Zampini } 33829036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3383792fecdfSBarry 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)); 33849036ceccSStefano Zampini #else 3385792fecdfSBarry 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)); 33869036ceccSStefano Zampini #endif 33879566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 33889036ceccSStefano Zampini B_neigs += B_neigs2; 33899036ceccSStefano Zampini } 33909036ceccSStefano Zampini break; 33919036ceccSStefano Zampini case 3: 33929036ceccSStefano Zampini if (scal) { 33939566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)pc)->prefix, "-pc_bddc_adaptive_recipe3_min_scal", &recipe_m, NULL)); 33949036ceccSStefano Zampini } else { 33959566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, ((PetscObject)pc)->prefix, "-pc_bddc_adaptive_recipe3_min", &recipe_m, NULL)); 33969036ceccSStefano Zampini } 33979036ceccSStefano Zampini if (!scal) { 33989036ceccSStefano Zampini bb[0] = uthresh; 33999036ceccSStefano Zampini bb[1] = PETSC_MAX_REAL; 34009036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3401792fecdfSBarry 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)); 34029036ceccSStefano Zampini #else 3403792fecdfSBarry 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)); 34049036ceccSStefano Zampini #endif 34059566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 34069036ceccSStefano Zampini } 34079036ceccSStefano Zampini if (recipe_m > 0 && B_N - B_neigs > 0) { 34089036ceccSStefano Zampini PetscBLASInt B_neigs2 = 0; 34099036ceccSStefano Zampini 34109036ceccSStefano Zampini B_IL = 1; 34119566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(PetscMin(recipe_m, B_N - B_neigs), &B_IU)); 34129566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 34139566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 34149036ceccSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3415792fecdfSBarry 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)); 34169036ceccSStefano Zampini #else 3417792fecdfSBarry 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)); 34189036ceccSStefano Zampini #endif 34199566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 34209036ceccSStefano Zampini B_neigs += B_neigs2; 34219036ceccSStefano Zampini } 34229036ceccSStefano Zampini break; 3423d71ae5a4SJacob Faibussowitsch case 4: 3424d71ae5a4SJacob Faibussowitsch bb[0] = PETSC_MIN_REAL; 3425d71ae5a4SJacob Faibussowitsch bb[1] = lthresh; 342648cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX) 3427792fecdfSBarry 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)); 342848cebe81SStefano Zampini #else 3429792fecdfSBarry 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)); 343048cebe81SStefano Zampini #endif 34319566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 343248cebe81SStefano Zampini { 343348cebe81SStefano Zampini PetscBLASInt B_neigs2 = 0; 343448cebe81SStefano Zampini 34359371c9d4SSatish Balay bb[0] = PetscMax(lthresh + PETSC_SMALL, uthresh); 34369371c9d4SSatish Balay bb[1] = PETSC_MAX_REAL; 34379566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 34389566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 343948cebe81SStefano Zampini #if defined(PETSC_USE_COMPLEX) 3440792fecdfSBarry 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)); 344148cebe81SStefano Zampini #else 3442792fecdfSBarry 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)); 344348cebe81SStefano Zampini #endif 34449566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 344548cebe81SStefano Zampini B_neigs += B_neigs2; 344648cebe81SStefano Zampini } 344748cebe81SStefano Zampini break; 344880db8efeSStefano Zampini case 5: /* same as before: first compute all eigenvalues, then filter */ 344980db8efeSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3450792fecdfSBarry 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)); 345180db8efeSStefano Zampini #else 3452792fecdfSBarry 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)); 345380db8efeSStefano Zampini #endif 34549566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 345580db8efeSStefano Zampini { 345680db8efeSStefano Zampini PetscInt e, k, ne; 345780db8efeSStefano Zampini for (e = 0, ne = 0; e < B_neigs; e++) { 345880db8efeSStefano Zampini if (eigs[e] < lthresh || eigs[e] > uthresh) { 345980db8efeSStefano Zampini for (k = 0; k < B_N; k++) S[ne * B_N + k] = eigv[e * B_N + k]; 346080db8efeSStefano Zampini eigs[ne] = eigs[e]; 346180db8efeSStefano Zampini ne++; 346280db8efeSStefano Zampini } 346380db8efeSStefano Zampini } 34649566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(eigv, S, B_N * ne)); 346580db8efeSStefano Zampini B_neigs = ne; 346680db8efeSStefano Zampini } 346780db8efeSStefano Zampini break; 3468d71ae5a4SJacob Faibussowitsch default: 3469d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Unknown recipe %" PetscInt_FMT, recipe); 3470bd2a564bSStefano Zampini } 3471bd2a564bSStefano Zampini } 3472bd2a564bSStefano Zampini } else if (!same_data) { /* this is just to see all the eigenvalues */ 3473d16cbb6bSStefano Zampini B_IU = PetscMax(1, PetscMin(B_N, nmax)); 3474d16cbb6bSStefano Zampini B_IL = 1; 3475d16cbb6bSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3476792fecdfSBarry 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)); 3477d16cbb6bSStefano Zampini #else 3478792fecdfSBarry 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)); 3479d16cbb6bSStefano Zampini #endif 34809566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 3481b03ebc13SStefano Zampini } else { /* same_data is true, so just get the adaptive functional requested by the user */ 3482b7ab4a40SStefano Zampini PetscInt k; 348328b400f6SJacob Faibussowitsch PetscCheck(sub_schurs->change_primal_sub, PETSC_COMM_SELF, PETSC_ERR_PLIB, "This should not happen"); 34849566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->change_primal_sub[i], &nmax)); 34859566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(nmax, &B_neigs)); 3486b7ab4a40SStefano Zampini nmin = nmax; 34879566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(eigv, subset_size * nmax)); 3488b7ab4a40SStefano Zampini for (k = 0; k < nmax; k++) { 3489b7ab4a40SStefano Zampini eigs[k] = 1. / PETSC_SMALL; 3490b7ab4a40SStefano Zampini eigv[k * (subset_size + 1)] = 1.0; 3491b7ab4a40SStefano Zampini } 3492d16cbb6bSStefano Zampini } 34939566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 349408122e43SStefano Zampini if (B_ierr) { 349563a3b9bcSJacob Faibussowitsch PetscCheck(B_ierr >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in SYGVX Lapack routine: illegal value for argument %" PetscBLASInt_FMT, -B_ierr); 349663a3b9bcSJacob 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); 349763a3b9bcSJacob 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); 349808122e43SStefano Zampini } 349908122e43SStefano Zampini 350008122e43SStefano Zampini if (B_neigs > nmax) { 350148a46eb9SPierre Jolivet if (pcbddc->dbg_flag) PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " found %" PetscBLASInt_FMT " eigs, more than maximum required %" PetscInt_FMT ".\n", B_neigs, nmax)); 350232fe681dSStefano Zampini if (upart) eigs_start = scal ? 0 : B_neigs - nmax; 350308122e43SStefano Zampini B_neigs = nmax; 350408122e43SStefano Zampini } 350508122e43SStefano Zampini 35069552c7c7SStefano Zampini nmin_s = PetscMin(nmin, B_N); 35079552c7c7SStefano Zampini if (B_neigs < nmin_s) { 35089036ceccSStefano Zampini PetscBLASInt B_neigs2 = 0; 350908122e43SStefano Zampini 351032fe681dSStefano Zampini if (upart) { 3511bd2a564bSStefano Zampini if (scal) { 3512bd2a564bSStefano Zampini B_IU = nmin_s; 3513bd2a564bSStefano Zampini B_IL = B_neigs + 1; 3514bd2a564bSStefano Zampini } else { 3515f6f667cfSStefano Zampini B_IL = B_N - nmin_s + 1; 35169d54b7f4SStefano Zampini B_IU = B_N - B_neigs; 3517bd2a564bSStefano Zampini } 35189d54b7f4SStefano Zampini } else { 35199d54b7f4SStefano Zampini B_IL = B_neigs + 1; 35209d54b7f4SStefano Zampini B_IU = nmin_s; 35219d54b7f4SStefano Zampini } 3522fd14bc51SStefano Zampini if (pcbddc->dbg_flag) { 352363a3b9bcSJacob 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)); 3524fd14bc51SStefano Zampini } 3525bd2a564bSStefano Zampini if (sub_schurs->is_symmetric) { 35261ae86dd6SStefano Zampini PetscInt j, k; 352708122e43SStefano Zampini for (j = 0; j < subset_size; j++) { 35281ae86dd6SStefano Zampini for (k = j; k < subset_size; k++) { 35291ae86dd6SStefano Zampini S[j * subset_size + k] = Sarray[cumarray + j * subset_size + k]; 35301ae86dd6SStefano Zampini St[j * subset_size + k] = Starray[cumarray + j * subset_size + k]; 353108122e43SStefano Zampini } 353208122e43SStefano Zampini } 353308122e43SStefano Zampini } else { 35349566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(S, Sarray + cumarray, subset_size * subset_size)); 35359566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(St, Starray + cumarray, subset_size * subset_size)); 353608122e43SStefano Zampini } 35379566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 353808122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 3539792fecdfSBarry 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)); 354008122e43SStefano Zampini #else 3541792fecdfSBarry 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)); 354208122e43SStefano Zampini #endif 35439566063dSJacob Faibussowitsch PetscCall(PetscLogFlops((4.0 * subset_size * subset_size * subset_size) / 3.0)); 35449566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 354508122e43SStefano Zampini B_neigs += B_neigs2; 354608122e43SStefano Zampini } 354708122e43SStefano Zampini if (B_ierr) { 354863a3b9bcSJacob Faibussowitsch PetscCheck(B_ierr >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in SYGVX Lapack routine: illegal value for argument %" PetscBLASInt_FMT, -B_ierr); 354963a3b9bcSJacob 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); 355063a3b9bcSJacob 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); 355108122e43SStefano Zampini } 3552fd14bc51SStefano Zampini if (pcbddc->dbg_flag) { 355363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " -> Got %" PetscBLASInt_FMT " eigs\n", B_neigs)); 355408122e43SStefano Zampini for (j = 0; j < B_neigs; j++) { 355532fe681dSStefano Zampini if (!sub_schurs->gdsw) { 355608122e43SStefano Zampini if (eigs[j] == 0.0) { 35579566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " Inf\n")); 355808122e43SStefano Zampini } else { 355932fe681dSStefano Zampini if (upart) { 356063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.6e\n", (double)eigs[j + eigs_start])); 35619d54b7f4SStefano Zampini } else { 356263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.6e\n", (double)(1. / eigs[j + eigs_start]))); 35639d54b7f4SStefano Zampini } 3564fd14bc51SStefano Zampini } 356532fe681dSStefano Zampini } else { 356632fe681dSStefano Zampini double pg = (double)eigs[j + eigs_start]; 356732fe681dSStefano Zampini if (pg < 2 * PETSC_SMALL) pg = 0.0; 356832fe681dSStefano Zampini PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.6e\n", pg)); 356932fe681dSStefano Zampini } 357008122e43SStefano Zampini } 357108122e43SStefano Zampini } 3572aff50787SStefano Zampini } 35736c3e6151SStefano Zampini /* change the basis back to the original one */ 35746c3e6151SStefano Zampini if (sub_schurs->change) { 357572b8c272SStefano Zampini Mat change, phi, phit; 35766c3e6151SStefano Zampini 357703dfb2d7SStefano Zampini if (pcbddc->dbg_flag > 2) { 35786c3e6151SStefano Zampini PetscInt ii; 35796c3e6151SStefano Zampini for (ii = 0; ii < B_neigs; ii++) { 358063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " -> Eigenvector (old basis) %" PetscInt_FMT "/%" PetscBLASInt_FMT " (%" PetscBLASInt_FMT ")\n", ii, B_neigs, B_N)); 35816c3e6151SStefano Zampini for (j = 0; j < B_N; j++) { 3582684229deSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3583684229deSStefano Zampini PetscReal r = PetscRealPart(eigv[(ii + eigs_start) * subset_size + j]); 3584684229deSStefano Zampini PetscReal c = PetscImaginaryPart(eigv[(ii + eigs_start) * subset_size + j]); 358563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.4e + %1.4e i\n", (double)r, (double)c)); 3586684229deSStefano Zampini #else 358763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.4e\n", (double)(eigv[(ii + eigs_start) * subset_size + j]))); 3588684229deSStefano Zampini #endif 35896c3e6151SStefano Zampini } 35906c3e6151SStefano Zampini } 35916c3e6151SStefano Zampini } 35929566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(sub_schurs->change[i], &change, NULL)); 35939566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, subset_size, B_neigs, eigv + eigs_start * subset_size, &phit)); 35949566063dSJacob Faibussowitsch PetscCall(MatMatMult(change, phit, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &phi)); 35959566063dSJacob Faibussowitsch PetscCall(MatCopy(phi, phit, SAME_NONZERO_PATTERN)); 35969566063dSJacob Faibussowitsch PetscCall(MatDestroy(&phit)); 35979566063dSJacob Faibussowitsch PetscCall(MatDestroy(&phi)); 35986c3e6151SStefano Zampini } 35998bec7fa6SStefano Zampini maxneigs = PetscMax(B_neigs, maxneigs); 36008bec7fa6SStefano Zampini pcbddc->adaptive_constraints_n[i + nv] = B_neigs; 36019162d606SStefano Zampini if (B_neigs) { 36029566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pcbddc->adaptive_constraints_data + pcbddc->adaptive_constraints_data_ptr[cum], eigv + eigs_start * subset_size, B_neigs * subset_size)); 3603fd14bc51SStefano Zampini 3604fd14bc51SStefano Zampini if (pcbddc->dbg_flag > 1) { 36059552c7c7SStefano Zampini PetscInt ii; 36069552c7c7SStefano Zampini for (ii = 0; ii < B_neigs; ii++) { 360763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " -> Eigenvector %" PetscInt_FMT "/%" PetscBLASInt_FMT " (%" PetscBLASInt_FMT ")\n", ii, B_neigs, B_N)); 36089552c7c7SStefano Zampini for (j = 0; j < B_N; j++) { 3609ac47001eSStefano Zampini #if defined(PETSC_USE_COMPLEX) 3610ac47001eSStefano Zampini PetscReal r = PetscRealPart(pcbddc->adaptive_constraints_data[ii * subset_size + j + pcbddc->adaptive_constraints_data_ptr[cum]]); 3611ac47001eSStefano Zampini PetscReal c = PetscImaginaryPart(pcbddc->adaptive_constraints_data[ii * subset_size + j + pcbddc->adaptive_constraints_data_ptr[cum]]); 361263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, " %1.4e + %1.4e i\n", (double)r, (double)c)); 3613ac47001eSStefano Zampini #else 361463a3b9bcSJacob 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]]))); 3615ac47001eSStefano Zampini #endif 36169552c7c7SStefano Zampini } 36179552c7c7SStefano Zampini } 3618fd14bc51SStefano Zampini } 36199566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pcbddc->adaptive_constraints_idxs + pcbddc->adaptive_constraints_idxs_ptr[cum], idxs, subset_size)); 36209162d606SStefano Zampini pcbddc->adaptive_constraints_idxs_ptr[cum + 1] = pcbddc->adaptive_constraints_idxs_ptr[cum] + subset_size; 36219162d606SStefano Zampini pcbddc->adaptive_constraints_data_ptr[cum + 1] = pcbddc->adaptive_constraints_data_ptr[cum] + subset_size * B_neigs; 36229162d606SStefano Zampini cum++; 362308122e43SStefano Zampini } 36249566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(sub_schurs->is_subs[i], &idxs)); 362508122e43SStefano Zampini /* shift for next computation */ 362608122e43SStefano Zampini cumarray += subset_size * subset_size; 362708122e43SStefano Zampini } 36281baa6e33SBarry Smith if (pcbddc->dbg_flag) PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 362908122e43SStefano Zampini 363008122e43SStefano Zampini if (mss) { 363132fe681dSStefano Zampini if (sub_schurs->gdsw) { 363232fe681dSStefano Zampini PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_all, &Sarray)); 363332fe681dSStefano Zampini PetscCall(MatSeqAIJGetArray(sub_schurs->sum_S_Ej_tilda_all, &Starray)); 363432fe681dSStefano Zampini } else { 36359566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_inv_all, &Sarray)); 36369566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(sub_schurs->sum_S_Ej_tilda_all, &Starray)); 3637f6f667cfSStefano Zampini /* destroy matrices (junk) */ 36389566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sub_schurs->sum_S_Ej_inv_all)); 36399566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sub_schurs->sum_S_Ej_tilda_all)); 364008122e43SStefano Zampini } 364132fe681dSStefano Zampini } 36421baa6e33SBarry Smith if (allocated_S_St) PetscCall(PetscFree2(S, St)); 36439566063dSJacob Faibussowitsch PetscCall(PetscFree5(eigv, eigs, work, B_iwork, B_ifail)); 364408122e43SStefano Zampini #if defined(PETSC_USE_COMPLEX) 36459566063dSJacob Faibussowitsch PetscCall(PetscFree(rwork)); 364608122e43SStefano Zampini #endif 364708122e43SStefano Zampini if (pcbddc->dbg_flag) { 36481b968477SStefano Zampini PetscInt maxneigs_r; 36491c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&maxneigs, &maxneigs_r, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)pc))); 365063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Maximum number of constraints per cc %" PetscInt_FMT "\n", maxneigs_r)); 365108122e43SStefano Zampini } 36529566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_AdaptiveSetUp[pcbddc->current_level], pc, 0, 0, 0)); 36533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 365408122e43SStefano Zampini } 3655b1b3d7a2SStefano Zampini 3656d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpSolvers(PC pc) 3657d71ae5a4SJacob Faibussowitsch { 36588629588bSStefano Zampini PetscScalar *coarse_submat_vals; 3659c8587f34SStefano Zampini 3660c8587f34SStefano Zampini PetscFunctionBegin; 3661f4ddd8eeSStefano Zampini /* Setup local scatters R_to_B and (optionally) R_to_D */ 36625e8657edSStefano Zampini /* PCBDDCSetUpLocalWorkVectors should be called first! */ 36639566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpLocalScatters(pc)); 3664c8587f34SStefano Zampini 3665684f6988SStefano Zampini /* Setup local neumann solver ksp_R */ 36660fccc4e9SStefano Zampini /* PCBDDCSetUpLocalScatters should be called first! */ 36679566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpLocalSolvers(pc, PETSC_FALSE, PETSC_TRUE)); 3668c8587f34SStefano Zampini 36698629588bSStefano Zampini /* 36708629588bSStefano Zampini Setup local correction and local part of coarse basis. 36718629588bSStefano Zampini Gives back the dense local part of the coarse matrix in column major ordering 36728629588bSStefano Zampini */ 36739566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpCorrection(pc, &coarse_submat_vals)); 36748629588bSStefano Zampini 36758629588bSStefano Zampini /* Compute total number of coarse nodes and setup coarse solver */ 36769566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpCoarseSolver(pc, coarse_submat_vals)); 36778629588bSStefano Zampini 36788629588bSStefano Zampini /* free */ 36799566063dSJacob Faibussowitsch PetscCall(PetscFree(coarse_submat_vals)); 36803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3681c8587f34SStefano Zampini } 3682c8587f34SStefano Zampini 3683d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCResetCustomization(PC pc) 3684d71ae5a4SJacob Faibussowitsch { 3685674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 3686674ae819SStefano Zampini 3687674ae819SStefano Zampini PetscFunctionBegin; 36889566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices)); 36899566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local)); 36909566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundaries)); 36919566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal)); 36929566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundaries)); 36939566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&pcbddc->onearnullspace)); 36949566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->onearnullvecs_state)); 36959566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal)); 36969566063dSJacob Faibussowitsch PetscCall(PCBDDCSetDofsSplitting(pc, 0, NULL)); 36979566063dSJacob Faibussowitsch PetscCall(PCBDDCSetDofsSplittingLocal(pc, 0, NULL)); 36983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3699674ae819SStefano Zampini } 3700674ae819SStefano Zampini 3701d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCResetTopography(PC pc) 3702d71ae5a4SJacob Faibussowitsch { 3703674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 37044f1b2e48SStefano Zampini PetscInt i; 3705674ae819SStefano Zampini 3706674ae819SStefano Zampini PetscFunctionBegin; 37079566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->nedcG)); 37089566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->nedclocal)); 37099566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->discretegradient)); 37109566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->user_ChangeOfBasisMatrix)); 37119566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->ChangeOfBasisMatrix)); 37129566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->switch_static_change)); 37139566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->work_change)); 37149566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->ConstraintMatrix)); 37159566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->divudotp)); 37169566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->divudotp_vl2l)); 37179566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphDestroy(&pcbddc->mat_graph)); 371848a46eb9SPierre Jolivet for (i = 0; i < pcbddc->n_local_subs; i++) PetscCall(ISDestroy(&pcbddc->local_subs[i])); 3719e68a0315Sstefano_zampini pcbddc->n_local_subs = 0; 37209566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->local_subs)); 37219566063dSJacob Faibussowitsch PetscCall(PCBDDCSubSchursDestroy(&pcbddc->sub_schurs)); 3722c703fcc7SStefano Zampini pcbddc->graphanalyzed = PETSC_FALSE; 37238af8fcf9SStefano Zampini pcbddc->recompute_topography = PETSC_TRUE; 37241c7a958bSStefano Zampini pcbddc->corner_selected = PETSC_FALSE; 37253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3726674ae819SStefano Zampini } 3727674ae819SStefano Zampini 3728d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCResetSolvers(PC pc) 3729d71ae5a4SJacob Faibussowitsch { 3730674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 3731674ae819SStefano Zampini 3732674ae819SStefano Zampini PetscFunctionBegin; 37339566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->coarse_vec)); 373458da7f69SStefano Zampini if (pcbddc->coarse_phi_B) { 3735ca92afb2SStefano Zampini PetscScalar *array; 37369566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(pcbddc->coarse_phi_B, &array)); 37379566063dSJacob Faibussowitsch PetscCall(PetscFree(array)); 373858da7f69SStefano Zampini } 37399566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_phi_B)); 37409566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_phi_D)); 37419566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_psi_B)); 37429566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_psi_D)); 37439566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_P)); 37449566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_C)); 37459566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_auxmat2)); 37469566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_auxmat1)); 37479566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_R)); 37489566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec2_R)); 37499566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->is_R_local)); 37509566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->R_to_B)); 37519566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->R_to_D)); 37529566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->coarse_loc_to_glob)); 37539566063dSJacob Faibussowitsch PetscCall(KSPReset(pcbddc->ksp_D)); 37549566063dSJacob Faibussowitsch PetscCall(KSPReset(pcbddc->ksp_R)); 37559566063dSJacob Faibussowitsch PetscCall(KSPReset(pcbddc->coarse_ksp)); 37569566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 37579566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->primal_indices_local_idxs)); 37589566063dSJacob Faibussowitsch PetscCall(PetscFree2(pcbddc->local_primal_ref_node, pcbddc->local_primal_ref_mult)); 37599566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->global_primal_indices)); 37609566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->coarse_subassembling)); 37619566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->benign_change)); 37629566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->benign_vec)); 37639566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignShellMat(pc, PETSC_TRUE)); 37649566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->benign_B0)); 37659566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&pcbddc->benign_sf)); 3766ca92afb2SStefano Zampini if (pcbddc->benign_zerodiag_subs) { 3767ca92afb2SStefano Zampini PetscInt i; 376848a46eb9SPierre Jolivet for (i = 0; i < pcbddc->benign_n; i++) PetscCall(ISDestroy(&pcbddc->benign_zerodiag_subs[i])); 37699566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->benign_zerodiag_subs)); 3770ca92afb2SStefano Zampini } 37719566063dSJacob Faibussowitsch PetscCall(PetscFree3(pcbddc->benign_p0_lidx, pcbddc->benign_p0_gidx, pcbddc->benign_p0)); 37723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3773674ae819SStefano Zampini } 3774674ae819SStefano Zampini 3775d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc) 3776d71ae5a4SJacob Faibussowitsch { 37776bfb1811SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 37786bfb1811SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 37796bfb1811SStefano Zampini VecType impVecType; 37804f1b2e48SStefano Zampini PetscInt n_constraints, n_R, old_size; 37816bfb1811SStefano Zampini 37826bfb1811SStefano Zampini PetscFunctionBegin; 37834f1b2e48SStefano Zampini n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - pcbddc->n_vertices; 3784b371cd4fSStefano Zampini n_R = pcis->n - pcbddc->n_vertices; 37859566063dSJacob Faibussowitsch PetscCall(VecGetType(pcis->vec1_N, &impVecType)); 3786e7b262bdSStefano Zampini /* local work vectors (try to avoid unneeded work)*/ 3787e7b262bdSStefano Zampini /* R nodes */ 3788e7b262bdSStefano Zampini old_size = -1; 378948a46eb9SPierre Jolivet if (pcbddc->vec1_R) PetscCall(VecGetSize(pcbddc->vec1_R, &old_size)); 3790e7b262bdSStefano Zampini if (n_R != old_size) { 37919566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_R)); 37929566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec2_R)); 37939566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N), &pcbddc->vec1_R)); 37949566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pcbddc->vec1_R, PETSC_DECIDE, n_R)); 37959566063dSJacob Faibussowitsch PetscCall(VecSetType(pcbddc->vec1_R, impVecType)); 37969566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcbddc->vec1_R, &pcbddc->vec2_R)); 3797e7b262bdSStefano Zampini } 3798e7b262bdSStefano Zampini /* local primal dofs */ 3799e7b262bdSStefano Zampini old_size = -1; 380048a46eb9SPierre Jolivet if (pcbddc->vec1_P) PetscCall(VecGetSize(pcbddc->vec1_P, &old_size)); 3801e9189074SStefano Zampini if (pcbddc->local_primal_size != old_size) { 38029566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_P)); 38039566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N), &pcbddc->vec1_P)); 38049566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pcbddc->vec1_P, PETSC_DECIDE, pcbddc->local_primal_size)); 38059566063dSJacob Faibussowitsch PetscCall(VecSetType(pcbddc->vec1_P, impVecType)); 3806e7b262bdSStefano Zampini } 3807e7b262bdSStefano Zampini /* local explicit constraints */ 3808e7b262bdSStefano Zampini old_size = -1; 380948a46eb9SPierre Jolivet if (pcbddc->vec1_C) PetscCall(VecGetSize(pcbddc->vec1_C, &old_size)); 3810e7b262bdSStefano Zampini if (n_constraints && n_constraints != old_size) { 38119566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->vec1_C)); 38129566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N), &pcbddc->vec1_C)); 38139566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pcbddc->vec1_C, PETSC_DECIDE, n_constraints)); 38149566063dSJacob Faibussowitsch PetscCall(VecSetType(pcbddc->vec1_C, impVecType)); 381583b7ccabSStefano Zampini } 38163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 38176bfb1811SStefano Zampini } 38186bfb1811SStefano Zampini 3819d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n) 3820d71ae5a4SJacob Faibussowitsch { 382125084f0cSStefano Zampini /* pointers to pcis and pcbddc */ 382288ebb749SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 382388ebb749SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 3824d62866d3SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 382525084f0cSStefano Zampini /* submatrices of local problem */ 382680677318SStefano Zampini Mat A_RV, A_VR, A_VV, local_auxmat2_R; 382706656605SStefano Zampini /* submatrices of local coarse problem */ 382806656605SStefano Zampini Mat S_VV, S_CV, S_VC, S_CC; 382925084f0cSStefano Zampini /* working matrices */ 383006656605SStefano Zampini Mat C_CR; 383125084f0cSStefano Zampini /* additional working stuff */ 383206656605SStefano Zampini PC pc_R; 3833c58f9fdbSStefano Zampini Mat F, Brhs = NULL; 38345cbda25cSStefano Zampini Vec dummy_vec; 38357ebab0bbSStefano Zampini PetscBool isLU, isCHOL, need_benign_correction, sparserhs; 383625084f0cSStefano Zampini PetscScalar *coarse_submat_vals; /* TODO: use a PETSc matrix */ 383706656605SStefano Zampini PetscScalar *work; 383806656605SStefano Zampini PetscInt *idx_V_B; 3839ffd830a3SStefano Zampini PetscInt lda_rhs, n, n_vertices, n_constraints, *p0_lidx_I; 384006656605SStefano Zampini PetscInt i, n_R, n_D, n_B; 384106656605SStefano Zampini PetscScalar one = 1.0, m_one = -1.0; 384288ebb749SStefano Zampini 384388ebb749SStefano Zampini PetscFunctionBegin; 38447827d75bSBarry 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"); 38459566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_CorrectionSetUp[pcbddc->current_level], pc, 0, 0, 0)); 3846ffd830a3SStefano Zampini 3847ffd830a3SStefano Zampini /* Set Non-overlapping dimensions */ 3848b371cd4fSStefano Zampini n_vertices = pcbddc->n_vertices; 38494f1b2e48SStefano Zampini n_constraints = pcbddc->local_primal_size - pcbddc->benign_n - n_vertices; 3850b371cd4fSStefano Zampini n_B = pcis->n_B; 3851b371cd4fSStefano Zampini n_D = pcis->n - n_B; 385288ebb749SStefano Zampini n_R = pcis->n - n_vertices; 385388ebb749SStefano Zampini 385488ebb749SStefano Zampini /* vertices in boundary numbering */ 38559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_vertices, &idx_V_B)); 38569566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(pcis->BtoNmap, IS_GTOLM_DROP, n_vertices, pcbddc->local_primal_ref_node, &i, idx_V_B)); 385763a3b9bcSJacob 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); 385888ebb749SStefano Zampini 385906656605SStefano Zampini /* Subdomain contribution (Non-overlapping) to coarse matrix */ 38609566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(pcbddc->local_primal_size * pcbddc->local_primal_size, &coarse_submat_vals)); 38619566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_vertices, n_vertices, coarse_submat_vals, &S_VV)); 38629566063dSJacob Faibussowitsch PetscCall(MatDenseSetLDA(S_VV, pcbddc->local_primal_size)); 38638e3a54c0SPierre Jolivet PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_constraints, n_vertices, PetscSafePointerPlusOffset(coarse_submat_vals, n_vertices), &S_CV)); 38649566063dSJacob Faibussowitsch PetscCall(MatDenseSetLDA(S_CV, pcbddc->local_primal_size)); 38658e3a54c0SPierre Jolivet PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_vertices, n_constraints, PetscSafePointerPlusOffset(coarse_submat_vals, pcbddc->local_primal_size * n_vertices), &S_VC)); 38669566063dSJacob Faibussowitsch PetscCall(MatDenseSetLDA(S_VC, pcbddc->local_primal_size)); 38678e3a54c0SPierre Jolivet PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_constraints, n_constraints, PetscSafePointerPlusOffset(coarse_submat_vals, (pcbddc->local_primal_size + 1) * n_vertices), &S_CC)); 38689566063dSJacob Faibussowitsch PetscCall(MatDenseSetLDA(S_CC, pcbddc->local_primal_size)); 386906656605SStefano Zampini 387006656605SStefano Zampini /* determine if can use MatSolve routines instead of calling KSPSolve on ksp_R */ 38719566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_R, &pc_R)); 38729566063dSJacob Faibussowitsch PetscCall(PCSetUp(pc_R)); 38739566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_R, PCLU, &isLU)); 38749566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_R, PCCHOLESKY, &isCHOL)); 3875ffd830a3SStefano Zampini lda_rhs = n_R; 3876a3df083aSStefano Zampini need_benign_correction = PETSC_FALSE; 38777ebab0bbSStefano Zampini if (isLU || isCHOL) { 38789566063dSJacob Faibussowitsch PetscCall(PCFactorGetMatrix(pc_R, &F)); 3879b334f244SStefano Zampini } else if (sub_schurs && sub_schurs->reuse_solver) { 3880df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 3881d62866d3SStefano Zampini MatFactorType type; 3882d62866d3SStefano Zampini 3883df4d28bfSStefano Zampini F = reuse_solver->F; 38849566063dSJacob Faibussowitsch PetscCall(MatGetFactorType(F, &type)); 3885d62866d3SStefano Zampini if (type == MAT_FACTOR_CHOLESKY) isCHOL = PETSC_TRUE; 38867ebab0bbSStefano Zampini if (type == MAT_FACTOR_LU) isLU = PETSC_TRUE; 38879566063dSJacob Faibussowitsch PetscCall(MatGetSize(F, &lda_rhs, NULL)); 388822db5ddcSStefano Zampini need_benign_correction = (PetscBool)(!!reuse_solver->benign_n); 38897ebab0bbSStefano Zampini } else F = NULL; 389006656605SStefano Zampini 3891c58f9fdbSStefano Zampini /* determine if we can use a sparse right-hand side */ 3892c58f9fdbSStefano Zampini sparserhs = PETSC_FALSE; 3893c58f9fdbSStefano Zampini if (F) { 3894ea799195SBarry Smith MatSolverType solver; 3895c58f9fdbSStefano Zampini 38969566063dSJacob Faibussowitsch PetscCall(MatFactorGetSolverType(F, &solver)); 38979566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(solver, MATSOLVERMUMPS, &sparserhs)); 3898c58f9fdbSStefano Zampini } 3899c58f9fdbSStefano Zampini 3900ffd830a3SStefano Zampini /* allocate workspace */ 3901ffd830a3SStefano Zampini n = 0; 3902ad540459SPierre Jolivet if (n_constraints) n += lda_rhs * n_constraints; 3903ffd830a3SStefano Zampini if (n_vertices) { 3904ffd830a3SStefano Zampini n = PetscMax(2 * lda_rhs * n_vertices, n); 3905ffd830a3SStefano Zampini n = PetscMax((lda_rhs + n_B) * n_vertices, n); 3906ffd830a3SStefano Zampini } 3907ad540459SPierre Jolivet if (!pcbddc->symmetric_primal) n = PetscMax(2 * lda_rhs * pcbddc->local_primal_size, n); 39089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &work)); 3909ffd830a3SStefano Zampini 39105cbda25cSStefano Zampini /* create dummy vector to modify rhs and sol of MatMatSolve (work array will never be used) */ 39115cbda25cSStefano Zampini dummy_vec = NULL; 39125cbda25cSStefano Zampini if (need_benign_correction && lda_rhs != n_R && F) { 39139566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N), &dummy_vec)); 39149566063dSJacob Faibussowitsch PetscCall(VecSetSizes(dummy_vec, lda_rhs, PETSC_DECIDE)); 39159566063dSJacob Faibussowitsch PetscCall(VecSetType(dummy_vec, ((PetscObject)pcis->vec1_N)->type_name)); 39165cbda25cSStefano Zampini } 39175cbda25cSStefano Zampini 39189566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_auxmat1)); 39199566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_auxmat2)); 39207ebab0bbSStefano Zampini 392188ebb749SStefano Zampini /* Precompute stuffs needed for preprocessing and application of BDDC*/ 392288ebb749SStefano Zampini if (n_constraints) { 3923837cedc9SStefano Zampini Mat M3, C_B; 392406656605SStefano Zampini IS is_aux; 392506656605SStefano Zampini 392625084f0cSStefano Zampini /* Extract constraints on R nodes: C_{CR} */ 39279566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, n_constraints, n_vertices, 1, &is_aux)); 39289566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->ConstraintMatrix, is_aux, pcbddc->is_R_local, MAT_INITIAL_MATRIX, &C_CR)); 39299566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->ConstraintMatrix, is_aux, pcis->is_B_local, MAT_INITIAL_MATRIX, &C_B)); 393088ebb749SStefano Zampini 393180677318SStefano Zampini /* Assemble local_auxmat2_R = (- A_{RR}^{-1} C^T_{CR}) needed by BDDC setup */ 393280677318SStefano Zampini /* Assemble pcbddc->local_auxmat2 = R_to_B (- A_{RR}^{-1} C^T_{CR}) needed by BDDC application */ 3933c58f9fdbSStefano Zampini if (!sparserhs) { 39349566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(work, lda_rhs * n_constraints)); 393588ebb749SStefano Zampini for (i = 0; i < n_constraints; i++) { 393606656605SStefano Zampini const PetscScalar *row_cmat_values; 393706656605SStefano Zampini const PetscInt *row_cmat_indices; 393806656605SStefano Zampini PetscInt size_of_constraint, j; 393988ebb749SStefano Zampini 39409566063dSJacob Faibussowitsch PetscCall(MatGetRow(C_CR, i, &size_of_constraint, &row_cmat_indices, &row_cmat_values)); 3941ad540459SPierre Jolivet for (j = 0; j < size_of_constraint; j++) work[row_cmat_indices[j] + i * lda_rhs] = -row_cmat_values[j]; 39429566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(C_CR, i, &size_of_constraint, &row_cmat_indices, &row_cmat_values)); 394306656605SStefano Zampini } 39449566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, lda_rhs, n_constraints, work, &Brhs)); 3945c58f9fdbSStefano Zampini } else { 3946c58f9fdbSStefano Zampini Mat tC_CR; 3947c58f9fdbSStefano Zampini 39489566063dSJacob Faibussowitsch PetscCall(MatScale(C_CR, -1.0)); 3949c58f9fdbSStefano Zampini if (lda_rhs != n_R) { 3950c58f9fdbSStefano Zampini PetscScalar *aa; 3951c58f9fdbSStefano Zampini PetscInt r, *ii, *jj; 3952c58f9fdbSStefano Zampini PetscBool done; 3953c58f9fdbSStefano Zampini 39549566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(C_CR, 0, PETSC_FALSE, PETSC_FALSE, &r, (const PetscInt **)&ii, (const PetscInt **)&jj, &done)); 395528b400f6SJacob Faibussowitsch PetscCheck(done, PETSC_COMM_SELF, PETSC_ERR_PLIB, "GetRowIJ failed"); 39569566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(C_CR, &aa)); 39579566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, n_constraints, lda_rhs, ii, jj, aa, &tC_CR)); 39589566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(C_CR, 0, PETSC_FALSE, PETSC_FALSE, &r, (const PetscInt **)&ii, (const PetscInt **)&jj, &done)); 395928b400f6SJacob Faibussowitsch PetscCheck(done, PETSC_COMM_SELF, PETSC_ERR_PLIB, "RestoreRowIJ failed"); 3960c58f9fdbSStefano Zampini } else { 39619566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)C_CR)); 3962c58f9fdbSStefano Zampini tC_CR = C_CR; 3963c58f9fdbSStefano Zampini } 39649566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(tC_CR, &Brhs)); 39659566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tC_CR)); 3966c58f9fdbSStefano Zampini } 39679566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, lda_rhs, n_constraints, NULL, &local_auxmat2_R)); 396806656605SStefano Zampini if (F) { 3969a3df083aSStefano Zampini if (need_benign_correction) { 3970df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 3971a3df083aSStefano Zampini 397272b8c272SStefano Zampini /* rhs is already zero on interior dofs, no need to change the rhs */ 39739566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(reuse_solver->benign_save_vals, pcbddc->benign_n)); 3974a3df083aSStefano Zampini } 39759566063dSJacob Faibussowitsch PetscCall(MatMatSolve(F, Brhs, local_auxmat2_R)); 3976a3df083aSStefano Zampini if (need_benign_correction) { 3977a3df083aSStefano Zampini PetscScalar *marr; 3978df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 3979a3df083aSStefano Zampini 39809566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(local_auxmat2_R, &marr)); 39815cbda25cSStefano Zampini if (lda_rhs != n_R) { 39825cbda25cSStefano Zampini for (i = 0; i < n_constraints; i++) { 39839566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dummy_vec, marr + i * lda_rhs)); 39849566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, dummy_vec, NULL, PETSC_TRUE, PETSC_TRUE)); 39859566063dSJacob Faibussowitsch PetscCall(VecResetArray(dummy_vec)); 39865cbda25cSStefano Zampini } 39875cbda25cSStefano Zampini } else { 3988a3df083aSStefano Zampini for (i = 0; i < n_constraints; i++) { 39899566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, marr + i * lda_rhs)); 39909566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, pcbddc->vec1_R, NULL, PETSC_TRUE, PETSC_TRUE)); 39919566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 3992a3df083aSStefano Zampini } 39935cbda25cSStefano Zampini } 39949566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(local_auxmat2_R, &marr)); 3995a3df083aSStefano Zampini } 399606656605SStefano Zampini } else { 399780677318SStefano Zampini PetscScalar *marr; 399880677318SStefano Zampini 39999566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(local_auxmat2_R, &marr)); 400006656605SStefano Zampini for (i = 0; i < n_constraints; i++) { 40019566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, work + i * lda_rhs)); 40029566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec2_R, marr + i * lda_rhs)); 40039566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec2_R)); 40049566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec2_R)); 40059566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 40069566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec2_R)); 400706656605SStefano Zampini } 40089566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(local_auxmat2_R, &marr)); 400906656605SStefano Zampini } 40101baa6e33SBarry Smith if (sparserhs) PetscCall(MatScale(C_CR, -1.0)); 40119566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Brhs)); 401280677318SStefano Zampini if (!pcbddc->switch_static) { 40139566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_B, n_constraints, NULL, &pcbddc->local_auxmat2)); 401480677318SStefano Zampini for (i = 0; i < n_constraints; i++) { 4015ab2d12f3SJunchao Zhang Vec r, b; 40169566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVecRead(local_auxmat2_R, i, &r)); 40179566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVec(pcbddc->local_auxmat2, i, &b)); 40189566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, r, b, INSERT_VALUES, SCATTER_FORWARD)); 40199566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, r, b, INSERT_VALUES, SCATTER_FORWARD)); 40209566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVec(pcbddc->local_auxmat2, i, &b)); 40219566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVecRead(local_auxmat2_R, i, &r)); 402280677318SStefano Zampini } 40239566063dSJacob Faibussowitsch PetscCall(MatMatMult(C_B, pcbddc->local_auxmat2, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &M3)); 402480677318SStefano Zampini } else { 4025ffd830a3SStefano Zampini if (lda_rhs != n_R) { 4026ffd830a3SStefano Zampini IS dummy; 4027ffd830a3SStefano Zampini 40289566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, n_R, 0, 1, &dummy)); 40299566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(local_auxmat2_R, dummy, NULL, MAT_INITIAL_MATRIX, &pcbddc->local_auxmat2)); 40309566063dSJacob Faibussowitsch PetscCall(ISDestroy(&dummy)); 4031ffd830a3SStefano Zampini } else { 40329566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)local_auxmat2_R)); 403380677318SStefano Zampini pcbddc->local_auxmat2 = local_auxmat2_R; 4034ffd830a3SStefano Zampini } 40359566063dSJacob Faibussowitsch PetscCall(MatMatMult(C_CR, pcbddc->local_auxmat2, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &M3)); 403680677318SStefano Zampini } 40379566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_aux)); 403880677318SStefano Zampini /* Assemble explicitly S_CC = ( C_{CR} A_{RR}^{-1} C^T_{CR})^{-1} */ 40399566063dSJacob Faibussowitsch PetscCall(MatScale(M3, m_one)); 404080677318SStefano Zampini if (isCHOL) { 40419566063dSJacob Faibussowitsch PetscCall(MatCholeskyFactor(M3, NULL, NULL)); 404280677318SStefano Zampini } else { 40439566063dSJacob Faibussowitsch PetscCall(MatLUFactor(M3, NULL, NULL, NULL)); 404480677318SStefano Zampini } 40459566063dSJacob Faibussowitsch PetscCall(MatSeqDenseInvertFactors_Private(M3)); 404680677318SStefano Zampini /* Assemble local_auxmat1 = S_CC*C_{CB} needed by BDDC application in KSP and in preproc */ 40479566063dSJacob Faibussowitsch PetscCall(MatMatMult(M3, C_B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &pcbddc->local_auxmat1)); 40489566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C_B)); 40499566063dSJacob Faibussowitsch PetscCall(MatCopy(M3, S_CC, SAME_NONZERO_PATTERN)); /* S_CC can have a different LDA, MatMatSolve doesn't support it */ 40509566063dSJacob Faibussowitsch PetscCall(MatDestroy(&M3)); 4051f4ddd8eeSStefano Zampini } 4052fc227af8SStefano Zampini 4053fc227af8SStefano Zampini /* Get submatrices from subdomain matrix */ 405488ebb749SStefano Zampini if (n_vertices) { 40557ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 40567ebab0bbSStefano Zampini PetscBool oldpin; 40577ebab0bbSStefano Zampini #endif 40587ebab0bbSStefano Zampini PetscBool isaij; 405906656605SStefano Zampini IS is_aux; 40603a50541eSStefano Zampini 4061b334f244SStefano Zampini if (sub_schurs && sub_schurs->reuse_solver) { /* is_R_local is not sorted, ISComplement doesn't like it */ 40626816873aSStefano Zampini IS tis; 40636816873aSStefano Zampini 40649566063dSJacob Faibussowitsch PetscCall(ISDuplicate(pcbddc->is_R_local, &tis)); 40659566063dSJacob Faibussowitsch PetscCall(ISSort(tis)); 40669566063dSJacob Faibussowitsch PetscCall(ISComplement(tis, 0, pcis->n, &is_aux)); 40679566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tis)); 40686816873aSStefano Zampini } else { 40699566063dSJacob Faibussowitsch PetscCall(ISComplement(pcbddc->is_R_local, 0, pcis->n, &is_aux)); 40706816873aSStefano Zampini } 40717ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 4072b470e4b4SRichard Tran Mills oldpin = pcbddc->local_mat->boundtocpu; 40737ebab0bbSStefano Zampini #endif 40749566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(pcbddc->local_mat, PETSC_TRUE)); 40759566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcbddc->is_R_local, is_aux, MAT_INITIAL_MATRIX, &A_RV)); 40769566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, is_aux, pcbddc->is_R_local, MAT_INITIAL_MATRIX, &A_VR)); 40779566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A_VR, MATSEQAIJ, &isaij)); 40787ebab0bbSStefano Zampini if (!isaij) { /* TODO REMOVE: MatMatMult(A_VR,A_RRmA_RV) below may raise an error */ 40799566063dSJacob Faibussowitsch PetscCall(MatConvert(A_VR, MATSEQAIJ, MAT_INPLACE_MATRIX, &A_VR)); 40807ebab0bbSStefano Zampini } 40819566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, is_aux, is_aux, MAT_INITIAL_MATRIX, &A_VV)); 40827ebab0bbSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 40839566063dSJacob Faibussowitsch PetscCall(MatBindToCPU(pcbddc->local_mat, oldpin)); 40847ebab0bbSStefano Zampini #endif 40859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_aux)); 408688ebb749SStefano Zampini } 408788ebb749SStefano Zampini 408888ebb749SStefano Zampini /* Matrix of coarse basis functions (local) */ 4089f4ddd8eeSStefano Zampini if (pcbddc->coarse_phi_B) { 409006656605SStefano Zampini PetscInt on_B, on_primal, on_D = n_D; 409148a46eb9SPierre Jolivet if (pcbddc->coarse_phi_D) PetscCall(MatGetSize(pcbddc->coarse_phi_D, &on_D, NULL)); 40929566063dSJacob Faibussowitsch PetscCall(MatGetSize(pcbddc->coarse_phi_B, &on_B, &on_primal)); 409306656605SStefano Zampini if (on_B != n_B || on_primal != pcbddc->local_primal_size || on_D != n_D) { 409406656605SStefano Zampini PetscScalar *marray; 409506656605SStefano Zampini 40969566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(pcbddc->coarse_phi_B, &marray)); 40979566063dSJacob Faibussowitsch PetscCall(PetscFree(marray)); 40989566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_phi_B)); 40999566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_psi_B)); 41009566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_phi_D)); 41019566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->coarse_psi_D)); 4102f4ddd8eeSStefano Zampini } 4103f4ddd8eeSStefano Zampini } 410406656605SStefano Zampini 4105f4ddd8eeSStefano Zampini if (!pcbddc->coarse_phi_B) { 4106a6e023c1Sstefano_zampini PetscScalar *marr; 410788ebb749SStefano Zampini 4108a6e023c1Sstefano_zampini /* memory size */ 410906656605SStefano Zampini n = n_B * pcbddc->local_primal_size; 4110a6e023c1Sstefano_zampini if (pcbddc->switch_static || pcbddc->dbg_flag) n += n_D * pcbddc->local_primal_size; 4111a6e023c1Sstefano_zampini if (!pcbddc->symmetric_primal) n *= 2; 41129566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(n, &marr)); 41139566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_B, pcbddc->local_primal_size, marr, &pcbddc->coarse_phi_B)); 41148e3a54c0SPierre Jolivet marr = PetscSafePointerPlusOffset(marr, n_B * pcbddc->local_primal_size); 41158eeda7d8SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 41169566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_D, pcbddc->local_primal_size, marr, &pcbddc->coarse_phi_D)); 4117a6e023c1Sstefano_zampini marr += n_D * pcbddc->local_primal_size; 411888ebb749SStefano Zampini } 41193301b35fSStefano Zampini if (!pcbddc->symmetric_primal) { 41209566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_B, pcbddc->local_primal_size, marr, &pcbddc->coarse_psi_B)); 4121a6e023c1Sstefano_zampini marr += n_B * pcbddc->local_primal_size; 412248a46eb9SPierre Jolivet if (pcbddc->switch_static || pcbddc->dbg_flag) PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_D, pcbddc->local_primal_size, marr, &pcbddc->coarse_psi_D)); 412388ebb749SStefano Zampini } else { 41249566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->coarse_phi_B)); 4125c0553b1fSStefano Zampini pcbddc->coarse_psi_B = pcbddc->coarse_phi_B; 41261b968477SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 41279566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->coarse_phi_D)); 4128c0553b1fSStefano Zampini pcbddc->coarse_psi_D = pcbddc->coarse_phi_D; 4129c0553b1fSStefano Zampini } 413088ebb749SStefano Zampini } 413106656605SStefano Zampini } 4132019a44ceSStefano Zampini 413306656605SStefano Zampini /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */ 41344f1b2e48SStefano Zampini p0_lidx_I = NULL; 41354f1b2e48SStefano Zampini if (pcbddc->benign_n && (pcbddc->switch_static || pcbddc->dbg_flag)) { 4136d12edf2fSStefano Zampini const PetscInt *idxs; 4137d12edf2fSStefano Zampini 41389566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_I_local, &idxs)); 41399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->benign_n, &p0_lidx_I)); 414048a46eb9SPierre 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])); 41419566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_I_local, &idxs)); 4142d12edf2fSStefano Zampini } 4143d16cbb6bSStefano Zampini 414406656605SStefano Zampini /* vertices */ 414506656605SStefano Zampini if (n_vertices) { 4146c58f9fdbSStefano Zampini PetscBool restoreavr = PETSC_FALSE; 414716f15bc4SStefano Zampini 41489566063dSJacob Faibussowitsch PetscCall(MatConvert(A_VV, MATDENSE, MAT_INPLACE_MATRIX, &A_VV)); 414904708bb6SStefano Zampini 415016f15bc4SStefano Zampini if (n_R) { 415114393ed6SStefano Zampini Mat A_RRmA_RV, A_RV_bcorr = NULL, S_VVt; /* S_VVt with LDA=N */ 415206656605SStefano Zampini PetscBLASInt B_N, B_one = 1; 41531683a169SBarry Smith const PetscScalar *x; 41541683a169SBarry Smith PetscScalar *y; 415506656605SStefano Zampini 41569566063dSJacob Faibussowitsch PetscCall(MatScale(A_RV, m_one)); 415714393ed6SStefano Zampini if (need_benign_correction) { 415814393ed6SStefano Zampini ISLocalToGlobalMapping RtoN; 415914393ed6SStefano Zampini IS is_p0; 416014393ed6SStefano Zampini PetscInt *idxs_p0, n; 416114393ed6SStefano Zampini 41629566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->benign_n, &idxs_p0)); 41639566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(pcbddc->is_R_local, &RtoN)); 41649566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(RtoN, IS_GTOLM_DROP, pcbddc->benign_n, pcbddc->benign_p0_lidx, &n, idxs_p0)); 416563a3b9bcSJacob 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); 41669566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&RtoN)); 41679566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, n, idxs_p0, PETSC_OWN_POINTER, &is_p0)); 41689566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A_RV, is_p0, NULL, MAT_INITIAL_MATRIX, &A_RV_bcorr)); 41699566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_p0)); 417014393ed6SStefano Zampini } 417114393ed6SStefano Zampini 41729566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, lda_rhs, n_vertices, work, &A_RRmA_RV)); 4173c58f9fdbSStefano Zampini if (!sparserhs || need_benign_correction) { 4174ffd830a3SStefano Zampini if (lda_rhs == n_R) { 41759566063dSJacob Faibussowitsch PetscCall(MatConvert(A_RV, MATDENSE, MAT_INPLACE_MATRIX, &A_RV)); 4176ffd830a3SStefano Zampini } else { 4177ca92afb2SStefano Zampini PetscScalar *av, *array; 4178ca92afb2SStefano Zampini const PetscInt *xadj, *adjncy; 4179ca92afb2SStefano Zampini PetscInt n; 4180ca92afb2SStefano Zampini PetscBool flg_row; 4181ffd830a3SStefano Zampini 4182ca92afb2SStefano Zampini array = work + lda_rhs * n_vertices; 41839566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(array, lda_rhs * n_vertices)); 41849566063dSJacob Faibussowitsch PetscCall(MatConvert(A_RV, MATSEQAIJ, MAT_INPLACE_MATRIX, &A_RV)); 41859566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A_RV, 0, PETSC_FALSE, PETSC_FALSE, &n, &xadj, &adjncy, &flg_row)); 41869566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A_RV, &av)); 4187ca92afb2SStefano Zampini for (i = 0; i < n; i++) { 4188ca92afb2SStefano Zampini PetscInt j; 4189ca92afb2SStefano Zampini for (j = xadj[i]; j < xadj[i + 1]; j++) array[lda_rhs * adjncy[j] + i] = av[j]; 4190ffd830a3SStefano Zampini } 41919566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A_RV, 0, PETSC_FALSE, PETSC_FALSE, &n, &xadj, &adjncy, &flg_row)); 41929566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RV)); 41939566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, lda_rhs, n_vertices, array, &A_RV)); 4194ffd830a3SStefano Zampini } 4195a3df083aSStefano Zampini if (need_benign_correction) { 4196df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 4197a3df083aSStefano Zampini PetscScalar *marr; 4198a3df083aSStefano Zampini 41999566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(A_RV, &marr)); 420014393ed6SStefano Zampini /* need \Phi^T A_RV = (I+L)A_RV, L given by 420114393ed6SStefano Zampini 420214393ed6SStefano Zampini | 0 0 0 | (V) 420314393ed6SStefano Zampini L = | 0 0 -1 | (P-p0) 420414393ed6SStefano Zampini | 0 0 -1 | (p0) 420514393ed6SStefano Zampini 420614393ed6SStefano Zampini */ 4207df4d28bfSStefano Zampini for (i = 0; i < reuse_solver->benign_n; i++) { 420814393ed6SStefano Zampini const PetscScalar *vals; 420914393ed6SStefano Zampini const PetscInt *idxs, *idxs_zero; 421014393ed6SStefano Zampini PetscInt n, j, nz; 421114393ed6SStefano Zampini 42129566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i], &nz)); 42139566063dSJacob Faibussowitsch PetscCall(ISGetIndices(reuse_solver->benign_zerodiag_subs[i], &idxs_zero)); 42149566063dSJacob Faibussowitsch PetscCall(MatGetRow(A_RV_bcorr, i, &n, &idxs, &vals)); 421514393ed6SStefano Zampini for (j = 0; j < n; j++) { 421614393ed6SStefano Zampini PetscScalar val = vals[j]; 421714393ed6SStefano Zampini PetscInt k, col = idxs[j]; 421814393ed6SStefano Zampini for (k = 0; k < nz; k++) marr[idxs_zero[k] + lda_rhs * col] -= val; 421914393ed6SStefano Zampini } 42209566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(A_RV_bcorr, i, &n, &idxs, &vals)); 42219566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i], &idxs_zero)); 422214393ed6SStefano Zampini } 42239566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(A_RV, &marr)); 422472b8c272SStefano Zampini } 42259566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A_RV)); 4226c58f9fdbSStefano Zampini Brhs = A_RV; 4227c58f9fdbSStefano Zampini } else { 4228c58f9fdbSStefano Zampini Mat tA_RVT, A_RVT; 4229c58f9fdbSStefano Zampini 4230c58f9fdbSStefano Zampini if (!pcbddc->symmetric_primal) { 4231fb6280fbSStefano Zampini /* A_RV already scaled by -1 */ 42329566063dSJacob Faibussowitsch PetscCall(MatTranspose(A_RV, MAT_INITIAL_MATRIX, &A_RVT)); 4233c58f9fdbSStefano Zampini } else { 4234c58f9fdbSStefano Zampini restoreavr = PETSC_TRUE; 42359566063dSJacob Faibussowitsch PetscCall(MatScale(A_VR, -1.0)); 42369566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A_VR)); 4237c58f9fdbSStefano Zampini A_RVT = A_VR; 4238c58f9fdbSStefano Zampini } 4239c58f9fdbSStefano Zampini if (lda_rhs != n_R) { 4240c58f9fdbSStefano Zampini PetscScalar *aa; 4241c58f9fdbSStefano Zampini PetscInt r, *ii, *jj; 4242c58f9fdbSStefano Zampini PetscBool done; 4243c58f9fdbSStefano Zampini 42449566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A_RVT, 0, PETSC_FALSE, PETSC_FALSE, &r, (const PetscInt **)&ii, (const PetscInt **)&jj, &done)); 424528b400f6SJacob Faibussowitsch PetscCheck(done, PETSC_COMM_SELF, PETSC_ERR_PLIB, "GetRowIJ failed"); 42469566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A_RVT, &aa)); 42479566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, n_vertices, lda_rhs, ii, jj, aa, &tA_RVT)); 42489566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A_RVT, 0, PETSC_FALSE, PETSC_FALSE, &r, (const PetscInt **)&ii, (const PetscInt **)&jj, &done)); 424928b400f6SJacob Faibussowitsch PetscCheck(done, PETSC_COMM_SELF, PETSC_ERR_PLIB, "RestoreRowIJ failed"); 4250c58f9fdbSStefano Zampini } else { 42519566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A_RVT)); 4252c58f9fdbSStefano Zampini tA_RVT = A_RVT; 4253c58f9fdbSStefano Zampini } 42549566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(tA_RVT, &Brhs)); 42559566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tA_RVT)); 42569566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RVT)); 4257c58f9fdbSStefano Zampini } 425872b8c272SStefano Zampini if (F) { 425914393ed6SStefano Zampini /* need to correct the rhs */ 426072b8c272SStefano Zampini if (need_benign_correction) { 426172b8c272SStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 426272b8c272SStefano Zampini PetscScalar *marr; 426372b8c272SStefano Zampini 42649566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(Brhs, &marr)); 42655cbda25cSStefano Zampini if (lda_rhs != n_R) { 42665cbda25cSStefano Zampini for (i = 0; i < n_vertices; i++) { 42679566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dummy_vec, marr + i * lda_rhs)); 42689566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, dummy_vec, NULL, PETSC_FALSE, PETSC_TRUE)); 42699566063dSJacob Faibussowitsch PetscCall(VecResetArray(dummy_vec)); 42705cbda25cSStefano Zampini } 42715cbda25cSStefano Zampini } else { 4272a3df083aSStefano Zampini for (i = 0; i < n_vertices; i++) { 42739566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, marr + i * lda_rhs)); 42749566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, pcbddc->vec1_R, NULL, PETSC_FALSE, PETSC_TRUE)); 42759566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 4276a3df083aSStefano Zampini } 42775cbda25cSStefano Zampini } 42789566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(Brhs, &marr)); 4279a3df083aSStefano Zampini } 42809566063dSJacob Faibussowitsch PetscCall(MatMatSolve(F, Brhs, A_RRmA_RV)); 42811baa6e33SBarry Smith if (restoreavr) PetscCall(MatScale(A_VR, -1.0)); 428214393ed6SStefano Zampini /* need to correct the solution */ 4283a3df083aSStefano Zampini if (need_benign_correction) { 4284df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 4285a3df083aSStefano Zampini PetscScalar *marr; 4286a3df083aSStefano Zampini 42879566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(A_RRmA_RV, &marr)); 42885cbda25cSStefano Zampini if (lda_rhs != n_R) { 42895cbda25cSStefano Zampini for (i = 0; i < n_vertices; i++) { 42909566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(dummy_vec, marr + i * lda_rhs)); 42919566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, dummy_vec, NULL, PETSC_TRUE, PETSC_TRUE)); 42929566063dSJacob Faibussowitsch PetscCall(VecResetArray(dummy_vec)); 42935cbda25cSStefano Zampini } 42945cbda25cSStefano Zampini } else { 4295a3df083aSStefano Zampini for (i = 0; i < n_vertices; i++) { 42969566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, marr + i * lda_rhs)); 42979566063dSJacob Faibussowitsch PetscCall(PCBDDCReuseSolversBenignAdapt(reuse_solver, pcbddc->vec1_R, NULL, PETSC_TRUE, PETSC_TRUE)); 42989566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 4299a3df083aSStefano Zampini } 43005cbda25cSStefano Zampini } 43019566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(A_RRmA_RV, &marr)); 4302a3df083aSStefano Zampini } 430306656605SStefano Zampini } else { 43049566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(Brhs, &y)); 430506656605SStefano Zampini for (i = 0; i < n_vertices; i++) { 43069566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, y + i * lda_rhs)); 43079566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec2_R, work + i * lda_rhs)); 43089566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec2_R)); 43099566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec2_R)); 43109566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 43119566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec2_R)); 431206656605SStefano Zampini } 43139566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(Brhs, &y)); 431406656605SStefano Zampini } 43159566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RV)); 43169566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Brhs)); 4317ffd830a3SStefano Zampini /* S_VV and S_CV */ 431806656605SStefano Zampini if (n_constraints) { 431906656605SStefano Zampini Mat B; 432080677318SStefano Zampini 43219566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(work + lda_rhs * n_vertices, n_B * n_vertices)); 432280677318SStefano Zampini for (i = 0; i < n_vertices; i++) { 43239566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, work + i * lda_rhs)); 43249566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcis->vec1_B, work + lda_rhs * n_vertices + i * n_B)); 43259566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, pcbddc->vec1_R, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 43269566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, pcbddc->vec1_R, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 43279566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcis->vec1_B)); 43289566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 432980677318SStefano Zampini } 43309566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_B, n_vertices, work + lda_rhs * n_vertices, &B)); 43314222ddf1SHong Zhang /* Reuse dense S_C = pcbddc->local_auxmat1 * B */ 43329566063dSJacob Faibussowitsch PetscCall(MatProductCreateWithMat(pcbddc->local_auxmat1, B, NULL, S_CV)); 43339566063dSJacob Faibussowitsch PetscCall(MatProductSetType(S_CV, MATPRODUCT_AB)); 43349566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(S_CV)); 43359566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(S_CV)); 43369566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(S_CV)); 43379566063dSJacob Faibussowitsch PetscCall(MatProductClear(S_CV)); 43384222ddf1SHong Zhang 43399566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 43409566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, lda_rhs, n_vertices, work + lda_rhs * n_vertices, &B)); 43414222ddf1SHong Zhang /* Reuse B = local_auxmat2_R * S_CV */ 43429566063dSJacob Faibussowitsch PetscCall(MatProductCreateWithMat(local_auxmat2_R, S_CV, NULL, B)); 43439566063dSJacob Faibussowitsch PetscCall(MatProductSetType(B, MATPRODUCT_AB)); 43449566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(B)); 43459566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(B)); 43469566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(B)); 43474222ddf1SHong Zhang 43489566063dSJacob Faibussowitsch PetscCall(MatScale(S_CV, m_one)); 43499566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(lda_rhs * n_vertices, &B_N)); 4350792fecdfSBarry Smith PetscCallBLAS("BLASaxpy", BLASaxpy_(&B_N, &one, work + lda_rhs * n_vertices, &B_one, work, &B_one)); 43519566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 435206656605SStefano Zampini } 4353ffd830a3SStefano Zampini if (lda_rhs != n_R) { 43549566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RRmA_RV)); 43559566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_R, n_vertices, work, &A_RRmA_RV)); 43569566063dSJacob Faibussowitsch PetscCall(MatDenseSetLDA(A_RRmA_RV, lda_rhs)); 4357ffd830a3SStefano Zampini } 43589566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_VR, A_RRmA_RV, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &S_VVt)); 435914393ed6SStefano Zampini /* need A_VR * \Phi * A_RRmA_RV = A_VR * (I+L)^T * A_RRmA_RV, L given as before */ 436014393ed6SStefano Zampini if (need_benign_correction) { 4361df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 436214393ed6SStefano Zampini PetscScalar *marr, *sums; 436314393ed6SStefano Zampini 43649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_vertices, &sums)); 43659566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(S_VVt, &marr)); 4366df4d28bfSStefano Zampini for (i = 0; i < reuse_solver->benign_n; i++) { 436714393ed6SStefano Zampini const PetscScalar *vals; 436814393ed6SStefano Zampini const PetscInt *idxs, *idxs_zero; 436914393ed6SStefano Zampini PetscInt n, j, nz; 437014393ed6SStefano Zampini 43719566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(reuse_solver->benign_zerodiag_subs[i], &nz)); 43729566063dSJacob Faibussowitsch PetscCall(ISGetIndices(reuse_solver->benign_zerodiag_subs[i], &idxs_zero)); 437314393ed6SStefano Zampini for (j = 0; j < n_vertices; j++) { 437414393ed6SStefano Zampini PetscInt k; 437514393ed6SStefano Zampini sums[j] = 0.; 437614393ed6SStefano Zampini for (k = 0; k < nz; k++) sums[j] += work[idxs_zero[k] + j * lda_rhs]; 437714393ed6SStefano Zampini } 43789566063dSJacob Faibussowitsch PetscCall(MatGetRow(A_RV_bcorr, i, &n, &idxs, &vals)); 437914393ed6SStefano Zampini for (j = 0; j < n; j++) { 438014393ed6SStefano Zampini PetscScalar val = vals[j]; 438114393ed6SStefano Zampini PetscInt k; 4382ad540459SPierre Jolivet for (k = 0; k < n_vertices; k++) marr[idxs[j] + k * n_vertices] += val * sums[k]; 438314393ed6SStefano Zampini } 43849566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(A_RV_bcorr, i, &n, &idxs, &vals)); 43859566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(reuse_solver->benign_zerodiag_subs[i], &idxs_zero)); 438614393ed6SStefano Zampini } 43879566063dSJacob Faibussowitsch PetscCall(PetscFree(sums)); 43889566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(S_VVt, &marr)); 43899566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RV_bcorr)); 439014393ed6SStefano Zampini } 43919566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RRmA_RV)); 43929566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(n_vertices * n_vertices, &B_N)); 43939566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(A_VV, &x)); 43949566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(S_VVt, &y)); 4395792fecdfSBarry Smith PetscCallBLAS("BLASaxpy", BLASaxpy_(&B_N, &one, x, &B_one, y, &B_one)); 43969566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(A_VV, &x)); 43979566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(S_VVt, &y)); 43989566063dSJacob Faibussowitsch PetscCall(MatCopy(S_VVt, S_VV, SAME_NONZERO_PATTERN)); 43999566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_VVt)); 4400019a44ceSStefano Zampini } else { 44019566063dSJacob Faibussowitsch PetscCall(MatCopy(A_VV, S_VV, SAME_NONZERO_PATTERN)); 4402d16cbb6bSStefano Zampini } 44039566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_VV)); 4404d16cbb6bSStefano Zampini 440506656605SStefano Zampini /* coarse basis functions */ 440606656605SStefano Zampini for (i = 0; i < n_vertices; i++) { 4407ab2d12f3SJunchao Zhang Vec v; 4408ab2d12f3SJunchao Zhang PetscScalar one = 1.0, zero = 0.0; 440916f15bc4SStefano Zampini 44109566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, work + lda_rhs * i)); 44119566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVec(pcbddc->coarse_phi_B, i, &v)); 44129566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 44139566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 4414ab2d12f3SJunchao Zhang if (PetscDefined(USE_DEBUG)) { /* The following VecSetValues() expects a sequential matrix */ 4415ab2d12f3SJunchao Zhang PetscMPIInt rank; 44169566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pcbddc->coarse_phi_B), &rank)); 441708401ef6SPierre Jolivet PetscCheck(rank <= 1, PetscObjectComm((PetscObject)pcbddc->coarse_phi_B), PETSC_ERR_PLIB, "Expected a sequential dense matrix"); 4418ab2d12f3SJunchao Zhang } 44199566063dSJacob Faibussowitsch PetscCall(VecSetValues(v, 1, &idx_V_B[i], &one, INSERT_VALUES)); 44209566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(v)); /* If v is on device, hope VecSetValues() eventually implemented by a host to device memcopy */ 44219566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(v)); 44229566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_phi_B, i, &v)); 442306656605SStefano Zampini 442406656605SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 44254f1b2e48SStefano Zampini PetscInt j; 44264f1b2e48SStefano Zampini 44279566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVec(pcbddc->coarse_phi_D, i, &v)); 44289566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_D, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 44299566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_D, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 4430ab2d12f3SJunchao Zhang if (PetscDefined(USE_DEBUG)) { /* The following VecSetValues() expects a sequential matrix */ 4431ab2d12f3SJunchao Zhang PetscMPIInt rank; 44329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pcbddc->coarse_phi_D), &rank)); 443308401ef6SPierre Jolivet PetscCheck(rank <= 1, PetscObjectComm((PetscObject)pcbddc->coarse_phi_D), PETSC_ERR_PLIB, "Expected a sequential dense matrix"); 4434ab2d12f3SJunchao Zhang } 44359566063dSJacob Faibussowitsch for (j = 0; j < pcbddc->benign_n; j++) PetscCall(VecSetValues(v, 1, &p0_lidx_I[j], &zero, INSERT_VALUES)); 44369566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(v)); 44379566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(v)); 44389566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_phi_D, i, &v)); 443906656605SStefano Zampini } 44409566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 444106656605SStefano Zampini } 444204708bb6SStefano Zampini /* if n_R == 0 the object is not destroyed */ 44439566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RV)); 444406656605SStefano Zampini } 44459566063dSJacob Faibussowitsch PetscCall(VecDestroy(&dummy_vec)); 444606656605SStefano Zampini 444706656605SStefano Zampini if (n_constraints) { 444806656605SStefano Zampini Mat B; 444906656605SStefano Zampini 44509566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, lda_rhs, n_constraints, work, &B)); 44519566063dSJacob Faibussowitsch PetscCall(MatScale(S_CC, m_one)); 44529566063dSJacob Faibussowitsch PetscCall(MatProductCreateWithMat(local_auxmat2_R, S_CC, NULL, B)); 44539566063dSJacob Faibussowitsch PetscCall(MatProductSetType(B, MATPRODUCT_AB)); 44549566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(B)); 44559566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(B)); 44569566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(B)); 4457a961b312SStefano Zampini 44589566063dSJacob Faibussowitsch PetscCall(MatScale(S_CC, m_one)); 445906656605SStefano Zampini if (n_vertices) { 446003dfb2d7SStefano Zampini if (isCHOL || need_benign_correction) { /* if we can solve the interior problem with cholesky, we should also be fine with transposing here */ 44617fb60732SBarry Smith PetscCall(MatTransposeSetPrecursor(S_CV, S_VC)); 44629566063dSJacob Faibussowitsch PetscCall(MatTranspose(S_CV, MAT_REUSE_MATRIX, &S_VC)); 446380677318SStefano Zampini } else { 446480677318SStefano Zampini Mat S_VCt; 446580677318SStefano Zampini 4466ffd830a3SStefano Zampini if (lda_rhs != n_R) { 44679566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 44689566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_R, n_constraints, work, &B)); 44699566063dSJacob Faibussowitsch PetscCall(MatDenseSetLDA(B, lda_rhs)); 4470ffd830a3SStefano Zampini } 44719566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_VR, B, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &S_VCt)); 44729566063dSJacob Faibussowitsch PetscCall(MatCopy(S_VCt, S_VC, SAME_NONZERO_PATTERN)); 44739566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_VCt)); 447480677318SStefano Zampini } 447506656605SStefano Zampini } 44769566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 447706656605SStefano Zampini /* coarse basis functions */ 447806656605SStefano Zampini for (i = 0; i < n_constraints; i++) { 4479ab2d12f3SJunchao Zhang Vec v; 448006656605SStefano Zampini 44819566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, work + lda_rhs * i)); 44829566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVec(pcbddc->coarse_phi_B, i + n_vertices, &v)); 44839566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 44849566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 44859566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_phi_B, i + n_vertices, &v)); 448606656605SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 44874f1b2e48SStefano Zampini PetscInt j; 4488ab2d12f3SJunchao Zhang PetscScalar zero = 0.0; 44899566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVec(pcbddc->coarse_phi_D, i + n_vertices, &v)); 44909566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_D, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 44919566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_D, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 44929566063dSJacob Faibussowitsch for (j = 0; j < pcbddc->benign_n; j++) PetscCall(VecSetValues(v, 1, &p0_lidx_I[j], &zero, INSERT_VALUES)); 44939566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(v)); 44949566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(v)); 44959566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_phi_D, i + n_vertices, &v)); 449606656605SStefano Zampini } 44979566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 449806656605SStefano Zampini } 449906656605SStefano Zampini } 450048a46eb9SPierre Jolivet if (n_constraints) PetscCall(MatDestroy(&local_auxmat2_R)); 45019566063dSJacob Faibussowitsch PetscCall(PetscFree(p0_lidx_I)); 450272b8c272SStefano Zampini 450372b8c272SStefano Zampini /* coarse matrix entries relative to B_0 */ 450472b8c272SStefano Zampini if (pcbddc->benign_n) { 450572b8c272SStefano Zampini Mat B0_B, B0_BPHI; 450672b8c272SStefano Zampini IS is_dummy; 45071683a169SBarry Smith const PetscScalar *data; 450872b8c272SStefano Zampini PetscInt j; 450972b8c272SStefano Zampini 45109566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pcbddc->benign_n, 0, 1, &is_dummy)); 45119566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->benign_B0, is_dummy, pcis->is_B_local, MAT_INITIAL_MATRIX, &B0_B)); 45129566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_dummy)); 45139566063dSJacob Faibussowitsch PetscCall(MatMatMult(B0_B, pcbddc->coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &B0_BPHI)); 45149566063dSJacob Faibussowitsch PetscCall(MatConvert(B0_BPHI, MATSEQDENSE, MAT_INPLACE_MATRIX, &B0_BPHI)); 45159566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(B0_BPHI, &data)); 451672b8c272SStefano Zampini for (j = 0; j < pcbddc->benign_n; j++) { 451772b8c272SStefano Zampini PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j; 451872b8c272SStefano Zampini for (i = 0; i < pcbddc->local_primal_size; i++) { 451972b8c272SStefano Zampini coarse_submat_vals[primal_idx * pcbddc->local_primal_size + i] = data[i * pcbddc->benign_n + j]; 452072b8c272SStefano Zampini coarse_submat_vals[i * pcbddc->local_primal_size + primal_idx] = data[i * pcbddc->benign_n + j]; 452172b8c272SStefano Zampini } 452272b8c272SStefano Zampini } 45239566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(B0_BPHI, &data)); 45249566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B0_B)); 45259566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B0_BPHI)); 452672b8c272SStefano Zampini } 4527019a44ceSStefano Zampini 452806656605SStefano Zampini /* compute other basis functions for non-symmetric problems */ 45293301b35fSStefano Zampini if (!pcbddc->symmetric_primal) { 4530ffd830a3SStefano Zampini Mat B_V = NULL, B_C = NULL; 4531ffd830a3SStefano Zampini PetscScalar *marray; 453206656605SStefano Zampini 453306656605SStefano Zampini if (n_constraints) { 4534ffd830a3SStefano Zampini Mat S_CCT, C_CRT; 453506656605SStefano Zampini 45369566063dSJacob Faibussowitsch PetscCall(MatTranspose(C_CR, MAT_INITIAL_MATRIX, &C_CRT)); 45379566063dSJacob Faibussowitsch PetscCall(MatTranspose(S_CC, MAT_INITIAL_MATRIX, &S_CCT)); 45389566063dSJacob Faibussowitsch PetscCall(MatMatMult(C_CRT, S_CCT, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &B_C)); 45399566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_CCT)); 454006656605SStefano Zampini if (n_vertices) { 4541ffd830a3SStefano Zampini Mat S_VCT; 454206656605SStefano Zampini 45439566063dSJacob Faibussowitsch PetscCall(MatTranspose(S_VC, MAT_INITIAL_MATRIX, &S_VCT)); 45449566063dSJacob Faibussowitsch PetscCall(MatMatMult(C_CRT, S_VCT, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &B_V)); 45459566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_VCT)); 454606656605SStefano Zampini } 45479566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C_CRT)); 45485b782168SStefano Zampini } else { 45499566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, n_R, n_vertices, NULL, &B_V)); 455006656605SStefano Zampini } 455116f15bc4SStefano Zampini if (n_vertices && n_R) { 4552ffd830a3SStefano Zampini PetscScalar *av, *marray; 4553ffd830a3SStefano Zampini const PetscInt *xadj, *adjncy; 4554ffd830a3SStefano Zampini PetscInt n; 4555ffd830a3SStefano Zampini PetscBool flg_row; 455606656605SStefano Zampini 4557ffd830a3SStefano Zampini /* B_V = B_V - A_VR^T */ 45589566063dSJacob Faibussowitsch PetscCall(MatConvert(A_VR, MATSEQAIJ, MAT_INPLACE_MATRIX, &A_VR)); 45599566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A_VR, 0, PETSC_FALSE, PETSC_FALSE, &n, &xadj, &adjncy, &flg_row)); 45609566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(A_VR, &av)); 45619566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(B_V, &marray)); 4562ffd830a3SStefano Zampini for (i = 0; i < n; i++) { 4563ffd830a3SStefano Zampini PetscInt j; 4564ffd830a3SStefano Zampini for (j = xadj[i]; j < xadj[i + 1]; j++) marray[i * n_R + adjncy[j]] -= av[j]; 4565ffd830a3SStefano Zampini } 45669566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(B_V, &marray)); 45679566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A_VR, 0, PETSC_FALSE, PETSC_FALSE, &n, &xadj, &adjncy, &flg_row)); 45689566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_VR)); 456906656605SStefano Zampini } 457006656605SStefano Zampini 4571ffd830a3SStefano Zampini /* currently there's no support for MatTransposeMatSolve(F,B,X) */ 4572abc8f43dSstefano_zampini if (n_vertices) { 45739566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(B_V, &marray)); 4574ffd830a3SStefano Zampini for (i = 0; i < n_vertices; i++) { 45759566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, marray + i * n_R)); 45769566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec2_R, work + i * n_R)); 45779566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec2_R)); 45789566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec2_R)); 45799566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 45809566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec2_R)); 458106656605SStefano Zampini } 45829566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(B_V, &marray)); 4583abc8f43dSstefano_zampini } 45845b782168SStefano Zampini if (B_C) { 45859566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(B_C, &marray)); 4586ffd830a3SStefano Zampini for (i = n_vertices; i < n_constraints + n_vertices; i++) { 45879566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, marray + (i - n_vertices) * n_R)); 45889566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec2_R, work + i * n_R)); 45899566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec2_R)); 45909566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec2_R)); 45919566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 45929566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec2_R)); 459306656605SStefano Zampini } 45949566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(B_C, &marray)); 45955b782168SStefano Zampini } 459606656605SStefano Zampini /* coarse basis functions */ 459706656605SStefano Zampini for (i = 0; i < pcbddc->local_primal_size; i++) { 4598ab2d12f3SJunchao Zhang Vec v; 459906656605SStefano Zampini 46009566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_R, work + i * n_R)); 46019566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVec(pcbddc->coarse_psi_B, i, &v)); 46029566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 46039566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 460406656605SStefano Zampini if (i < n_vertices) { 4605ab2d12f3SJunchao Zhang PetscScalar one = 1.0; 46069566063dSJacob Faibussowitsch PetscCall(VecSetValues(v, 1, &idx_V_B[i], &one, INSERT_VALUES)); 46079566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(v)); 46089566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(v)); 460906656605SStefano Zampini } 46109566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_psi_B, i, &v)); 461106656605SStefano Zampini 461206656605SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 46139566063dSJacob Faibussowitsch PetscCall(MatDenseGetColumnVec(pcbddc->coarse_psi_D, i, &v)); 46149566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_D, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 46159566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_D, pcbddc->vec1_R, v, INSERT_VALUES, SCATTER_FORWARD)); 46169566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreColumnVec(pcbddc->coarse_psi_D, i, &v)); 461706656605SStefano Zampini } 46189566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_R)); 461906656605SStefano Zampini } 46209566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B_V)); 46219566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B_C)); 462206656605SStefano Zampini } 4623a6e023c1Sstefano_zampini 4624d62866d3SStefano Zampini /* free memory */ 46259566063dSJacob Faibussowitsch PetscCall(PetscFree(idx_V_B)); 46269566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_VV)); 46279566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_CV)); 46289566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_VC)); 46299566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_CC)); 46309566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 463148a46eb9SPierre Jolivet if (n_vertices) PetscCall(MatDestroy(&A_VR)); 463248a46eb9SPierre Jolivet if (n_constraints) PetscCall(MatDestroy(&C_CR)); 46339566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_CorrectionSetUp[pcbddc->current_level], pc, 0, 0, 0)); 46348ead10e4SStefano Zampini 4635da81f932SPierre Jolivet /* Checking coarse_sub_mat and coarse basis functions */ 463688ebb749SStefano Zampini /* Symmetric case : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */ 463788ebb749SStefano Zampini /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */ 4638d12edf2fSStefano Zampini if (pcbddc->dbg_flag) { 463988ebb749SStefano Zampini Mat coarse_sub_mat; 464025084f0cSStefano Zampini Mat AUXMAT, TM1, TM2, TM3, TM4; 464188ebb749SStefano Zampini Mat coarse_phi_D, coarse_phi_B; 464288ebb749SStefano Zampini Mat coarse_psi_D, coarse_psi_B; 464388ebb749SStefano Zampini Mat A_II, A_BB, A_IB, A_BI; 46448bec7fa6SStefano Zampini Mat C_B, CPHI; 46458bec7fa6SStefano Zampini IS is_dummy; 46468bec7fa6SStefano Zampini Vec mones; 464788ebb749SStefano Zampini MatType checkmattype = MATSEQAIJ; 464888ebb749SStefano Zampini PetscReal real_value; 464988ebb749SStefano Zampini 4650a3df083aSStefano Zampini if (pcbddc->benign_n && !pcbddc->benign_change_explicit) { 4651a3df083aSStefano Zampini Mat A; 46529566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignProject(pc, NULL, NULL, &A)); 46539566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, pcis->is_I_local, pcis->is_I_local, MAT_INITIAL_MATRIX, &A_II)); 46549566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, pcis->is_I_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &A_IB)); 46559566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, pcis->is_B_local, pcis->is_I_local, MAT_INITIAL_MATRIX, &A_BI)); 46569566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, pcis->is_B_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &A_BB)); 46579566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 4658a3df083aSStefano Zampini } else { 46599566063dSJacob Faibussowitsch PetscCall(MatConvert(pcis->A_II, checkmattype, MAT_INITIAL_MATRIX, &A_II)); 46609566063dSJacob Faibussowitsch PetscCall(MatConvert(pcis->A_IB, checkmattype, MAT_INITIAL_MATRIX, &A_IB)); 46619566063dSJacob Faibussowitsch PetscCall(MatConvert(pcis->A_BI, checkmattype, MAT_INITIAL_MATRIX, &A_BI)); 46629566063dSJacob Faibussowitsch PetscCall(MatConvert(pcis->A_BB, checkmattype, MAT_INITIAL_MATRIX, &A_BB)); 4663a3df083aSStefano Zampini } 46649566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->coarse_phi_D, checkmattype, MAT_INITIAL_MATRIX, &coarse_phi_D)); 46659566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->coarse_phi_B, checkmattype, MAT_INITIAL_MATRIX, &coarse_phi_B)); 4666ffd830a3SStefano Zampini if (!pcbddc->symmetric_primal) { 46679566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->coarse_psi_D, checkmattype, MAT_INITIAL_MATRIX, &coarse_psi_D)); 46689566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->coarse_psi_B, checkmattype, MAT_INITIAL_MATRIX, &coarse_psi_B)); 466988ebb749SStefano Zampini } 46709566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, pcbddc->local_primal_size, pcbddc->local_primal_size, coarse_submat_vals, &coarse_sub_mat)); 467188ebb749SStefano Zampini 46729566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 46739566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Check coarse sub mat computation (symmetric %d)\n", pcbddc->symmetric_primal)); 46749566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 4675ffd830a3SStefano Zampini if (!pcbddc->symmetric_primal) { 46769566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_II, coarse_phi_D, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 46779566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_psi_D, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM1)); 46789566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 46799566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_BB, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 46809566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_psi_B, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM2)); 46819566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 46829566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_IB, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 46839566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_psi_D, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM3)); 46849566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 46859566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_BI, coarse_phi_D, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 46869566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_psi_B, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM4)); 46879566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 468888ebb749SStefano Zampini } else { 46899566063dSJacob Faibussowitsch PetscCall(MatPtAP(A_II, coarse_phi_D, MAT_INITIAL_MATRIX, 1.0, &TM1)); 46909566063dSJacob Faibussowitsch PetscCall(MatPtAP(A_BB, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &TM2)); 46919566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_IB, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 46929566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_phi_D, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM3)); 46939566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 46949566063dSJacob Faibussowitsch PetscCall(MatMatMult(A_BI, coarse_phi_D, MAT_INITIAL_MATRIX, 1.0, &AUXMAT)); 46959566063dSJacob Faibussowitsch PetscCall(MatTransposeMatMult(coarse_phi_B, AUXMAT, MAT_INITIAL_MATRIX, 1.0, &TM4)); 46969566063dSJacob Faibussowitsch PetscCall(MatDestroy(&AUXMAT)); 469788ebb749SStefano Zampini } 46989566063dSJacob Faibussowitsch PetscCall(MatAXPY(TM1, one, TM2, DIFFERENT_NONZERO_PATTERN)); 46999566063dSJacob Faibussowitsch PetscCall(MatAXPY(TM1, one, TM3, DIFFERENT_NONZERO_PATTERN)); 47009566063dSJacob Faibussowitsch PetscCall(MatAXPY(TM1, one, TM4, DIFFERENT_NONZERO_PATTERN)); 47019566063dSJacob Faibussowitsch PetscCall(MatConvert(TM1, MATSEQDENSE, MAT_INPLACE_MATRIX, &TM1)); 47024f1b2e48SStefano Zampini if (pcbddc->benign_n) { 4703fc227af8SStefano Zampini Mat B0_B, B0_BPHI; 47041683a169SBarry Smith const PetscScalar *data2; 47051683a169SBarry Smith PetscScalar *data; 47064f1b2e48SStefano Zampini PetscInt j; 4707d12edf2fSStefano Zampini 47089566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pcbddc->benign_n, 0, 1, &is_dummy)); 47099566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->benign_B0, is_dummy, pcis->is_B_local, MAT_INITIAL_MATRIX, &B0_B)); 47109566063dSJacob Faibussowitsch PetscCall(MatMatMult(B0_B, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &B0_BPHI)); 47119566063dSJacob Faibussowitsch PetscCall(MatConvert(B0_BPHI, MATSEQDENSE, MAT_INPLACE_MATRIX, &B0_BPHI)); 47129566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(TM1, &data)); 47139566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(B0_BPHI, &data2)); 47144f1b2e48SStefano Zampini for (j = 0; j < pcbddc->benign_n; j++) { 47154f1b2e48SStefano Zampini PetscInt primal_idx = pcbddc->local_primal_size - pcbddc->benign_n + j; 4716d12edf2fSStefano Zampini for (i = 0; i < pcbddc->local_primal_size; i++) { 47174f1b2e48SStefano Zampini data[primal_idx * pcbddc->local_primal_size + i] += data2[i * pcbddc->benign_n + j]; 47184f1b2e48SStefano Zampini data[i * pcbddc->local_primal_size + primal_idx] += data2[i * pcbddc->benign_n + j]; 47194f1b2e48SStefano Zampini } 4720d12edf2fSStefano Zampini } 47219566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(TM1, &data)); 47229566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(B0_BPHI, &data2)); 47239566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B0_B)); 47249566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_dummy)); 47259566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B0_BPHI)); 4726d12edf2fSStefano Zampini } 4727d12edf2fSStefano Zampini #if 0 4728d12edf2fSStefano Zampini { 4729d12edf2fSStefano Zampini PetscViewer viewer; 4730d12edf2fSStefano Zampini char filename[256]; 4731a364092eSJacob Faibussowitsch PetscCall(PetscSNPrintf(filename, PETSC_STATIC_ARRAY_LENGTH(filename), "details_local_coarse_mat%d_level%d.m",PetscGlobalRank,pcbddc->current_level)); 47329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer)); 47339566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB)); 47349566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coarse_sub_mat,"computed")); 47359566063dSJacob Faibussowitsch PetscCall(MatView(coarse_sub_mat,viewer)); 47369566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)TM1,"projected")); 47379566063dSJacob Faibussowitsch PetscCall(MatView(TM1,viewer)); 4738a7414863SStefano Zampini if (pcbddc->coarse_phi_B) { 47399566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_phi_B,"phi_B")); 47409566063dSJacob Faibussowitsch PetscCall(MatView(pcbddc->coarse_phi_B,viewer)); 474172b8c272SStefano Zampini } 4742ffd830a3SStefano Zampini if (pcbddc->coarse_phi_D) { 47439566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_phi_D,"phi_D")); 47449566063dSJacob Faibussowitsch PetscCall(MatView(pcbddc->coarse_phi_D,viewer)); 4745ffd830a3SStefano Zampini } 4746ffd830a3SStefano Zampini if (pcbddc->coarse_psi_B) { 47479566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_psi_B,"psi_B")); 47489566063dSJacob Faibussowitsch PetscCall(MatView(pcbddc->coarse_psi_B,viewer)); 4749ffd830a3SStefano Zampini } 475072b8c272SStefano Zampini if (pcbddc->coarse_psi_D) { 47519566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)pcbddc->coarse_psi_D,"psi_D")); 47529566063dSJacob Faibussowitsch PetscCall(MatView(pcbddc->coarse_psi_D,viewer)); 4753ffd830a3SStefano Zampini } 47549566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)pcbddc->local_mat,"A")); 47559566063dSJacob Faibussowitsch PetscCall(MatView(pcbddc->local_mat,viewer)); 47569566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)pcbddc->ConstraintMatrix,"C")); 47579566063dSJacob Faibussowitsch PetscCall(MatView(pcbddc->ConstraintMatrix,viewer)); 47589566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)pcis->is_I_local,"I")); 47599566063dSJacob Faibussowitsch PetscCall(ISView(pcis->is_I_local,viewer)); 47609566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)pcis->is_B_local,"B")); 47619566063dSJacob Faibussowitsch PetscCall(ISView(pcis->is_B_local,viewer)); 47629566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)pcbddc->is_R_local,"R")); 47639566063dSJacob Faibussowitsch PetscCall(ISView(pcbddc->is_R_local,viewer)); 4764cd791dc2SBarry Smith PetscCall(PetscOptionsRestoreViewer(&viewer)); 4765d12edf2fSStefano Zampini } 4766d12edf2fSStefano Zampini #endif 47679566063dSJacob Faibussowitsch PetscCall(MatAXPY(TM1, m_one, coarse_sub_mat, DIFFERENT_NONZERO_PATTERN)); 47689566063dSJacob Faibussowitsch PetscCall(MatNorm(TM1, NORM_FROBENIUS, &real_value)); 47699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 477063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d matrix error % 1.14e\n", PetscGlobalRank, (double)real_value)); 47718bec7fa6SStefano Zampini 47728bec7fa6SStefano Zampini /* check constraints */ 47739566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pcbddc->local_primal_size - pcbddc->benign_n, 0, 1, &is_dummy)); 47749566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->ConstraintMatrix, is_dummy, pcis->is_B_local, MAT_INITIAL_MATRIX, &C_B)); 47754f1b2e48SStefano Zampini if (!pcbddc->benign_n) { /* TODO: add benign case */ 47769566063dSJacob Faibussowitsch PetscCall(MatMatMult(C_B, coarse_phi_B, MAT_INITIAL_MATRIX, 1.0, &CPHI)); 4777a00504b5SStefano Zampini } else { 4778a00504b5SStefano Zampini PetscScalar *data; 4779a00504b5SStefano Zampini Mat tmat; 47809566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(pcbddc->coarse_phi_B, &data)); 47819566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, pcis->n_B, pcbddc->local_primal_size - pcbddc->benign_n, data, &tmat)); 47829566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(pcbddc->coarse_phi_B, &data)); 47839566063dSJacob Faibussowitsch PetscCall(MatMatMult(C_B, tmat, MAT_INITIAL_MATRIX, 1.0, &CPHI)); 47849566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tmat)); 4785a00504b5SStefano Zampini } 47869566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(CPHI, &mones, NULL)); 47879566063dSJacob Faibussowitsch PetscCall(VecSet(mones, -1.0)); 47889566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(CPHI, mones, ADD_VALUES)); 47899566063dSJacob Faibussowitsch PetscCall(MatNorm(CPHI, NORM_FROBENIUS, &real_value)); 479063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d phi constraints error % 1.14e\n", PetscGlobalRank, (double)real_value)); 4791ffd830a3SStefano Zampini if (!pcbddc->symmetric_primal) { 47929566063dSJacob Faibussowitsch PetscCall(MatMatMult(C_B, coarse_psi_B, MAT_REUSE_MATRIX, 1.0, &CPHI)); 47939566063dSJacob Faibussowitsch PetscCall(VecSet(mones, -1.0)); 47949566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(CPHI, mones, ADD_VALUES)); 47959566063dSJacob Faibussowitsch PetscCall(MatNorm(CPHI, NORM_FROBENIUS, &real_value)); 479663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d psi constraints error % 1.14e\n", PetscGlobalRank, (double)real_value)); 479788ebb749SStefano Zampini } 47989566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C_B)); 47999566063dSJacob Faibussowitsch PetscCall(MatDestroy(&CPHI)); 48009566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_dummy)); 48019566063dSJacob Faibussowitsch PetscCall(VecDestroy(&mones)); 48029566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 48039566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_II)); 48049566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_BB)); 48059566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_IB)); 48069566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_BI)); 48079566063dSJacob Faibussowitsch PetscCall(MatDestroy(&TM1)); 48089566063dSJacob Faibussowitsch PetscCall(MatDestroy(&TM2)); 48099566063dSJacob Faibussowitsch PetscCall(MatDestroy(&TM3)); 48109566063dSJacob Faibussowitsch PetscCall(MatDestroy(&TM4)); 48119566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_phi_D)); 48129566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_phi_B)); 4813ffd830a3SStefano Zampini if (!pcbddc->symmetric_primal) { 48149566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_psi_D)); 48159566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_psi_B)); 481688ebb749SStefano Zampini } 48179566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_sub_mat)); 481888ebb749SStefano Zampini } 48197ebab0bbSStefano Zampini /* FINAL CUDA support (we cannot currently mix viennacl and cuda vectors */ 48207ebab0bbSStefano Zampini { 48217ebab0bbSStefano Zampini PetscBool gpu; 48227ebab0bbSStefano Zampini 48239566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pcis->vec1_N, VECSEQCUDA, &gpu)); 48247ebab0bbSStefano Zampini if (gpu) { 482548a46eb9SPierre Jolivet if (pcbddc->local_auxmat1) PetscCall(MatConvert(pcbddc->local_auxmat1, MATSEQDENSECUDA, MAT_INPLACE_MATRIX, &pcbddc->local_auxmat1)); 482648a46eb9SPierre Jolivet if (pcbddc->local_auxmat2) PetscCall(MatConvert(pcbddc->local_auxmat2, MATSEQDENSECUDA, MAT_INPLACE_MATRIX, &pcbddc->local_auxmat2)); 482748a46eb9SPierre Jolivet if (pcbddc->coarse_phi_B) PetscCall(MatConvert(pcbddc->coarse_phi_B, MATSEQDENSECUDA, MAT_INPLACE_MATRIX, &pcbddc->coarse_phi_B)); 482848a46eb9SPierre Jolivet if (pcbddc->coarse_phi_D) PetscCall(MatConvert(pcbddc->coarse_phi_D, MATSEQDENSECUDA, MAT_INPLACE_MATRIX, &pcbddc->coarse_phi_D)); 482948a46eb9SPierre Jolivet if (pcbddc->coarse_psi_B) PetscCall(MatConvert(pcbddc->coarse_psi_B, MATSEQDENSECUDA, MAT_INPLACE_MATRIX, &pcbddc->coarse_psi_B)); 483048a46eb9SPierre Jolivet if (pcbddc->coarse_psi_D) PetscCall(MatConvert(pcbddc->coarse_psi_D, MATSEQDENSECUDA, MAT_INPLACE_MATRIX, &pcbddc->coarse_psi_D)); 48317ebab0bbSStefano Zampini } 48327ebab0bbSStefano Zampini } 48338629588bSStefano Zampini /* get back data */ 48348629588bSStefano Zampini *coarse_submat_vals_n = coarse_submat_vals; 48353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 483688ebb749SStefano Zampini } 483788ebb749SStefano Zampini 4838d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat *B) 4839d71ae5a4SJacob Faibussowitsch { 4840d65f70fdSStefano Zampini Mat *work_mat; 4841d65f70fdSStefano Zampini IS isrow_s, iscol_s; 4842d65f70fdSStefano Zampini PetscBool rsorted, csorted; 4843c43ebad9SStefano Zampini PetscInt rsize, *idxs_perm_r = NULL, csize, *idxs_perm_c = NULL; 4844aa0d41d4SStefano Zampini 4845aa0d41d4SStefano Zampini PetscFunctionBegin; 48469566063dSJacob Faibussowitsch PetscCall(ISSorted(isrow, &rsorted)); 48479566063dSJacob Faibussowitsch PetscCall(ISSorted(iscol, &csorted)); 48489566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isrow, &rsize)); 48499566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(iscol, &csize)); 4850aa0d41d4SStefano Zampini 4851d65f70fdSStefano Zampini if (!rsorted) { 4852906d46d4SStefano Zampini const PetscInt *idxs; 4853906d46d4SStefano Zampini PetscInt *idxs_sorted, i; 4854aa0d41d4SStefano Zampini 48559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rsize, &idxs_perm_r)); 48569566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rsize, &idxs_sorted)); 4857ad540459SPierre Jolivet for (i = 0; i < rsize; i++) idxs_perm_r[i] = i; 48589566063dSJacob Faibussowitsch PetscCall(ISGetIndices(isrow, &idxs)); 48599566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithPermutation(rsize, idxs, idxs_perm_r)); 4860ad540459SPierre Jolivet for (i = 0; i < rsize; i++) idxs_sorted[i] = idxs[idxs_perm_r[i]]; 48619566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(isrow, &idxs)); 48629566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, rsize, idxs_sorted, PETSC_OWN_POINTER, &isrow_s)); 4863d65f70fdSStefano Zampini } else { 48649566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)isrow)); 4865d65f70fdSStefano Zampini isrow_s = isrow; 4866aa0d41d4SStefano Zampini } 4867906d46d4SStefano Zampini 4868d65f70fdSStefano Zampini if (!csorted) { 4869d65f70fdSStefano Zampini if (isrow == iscol) { 48709566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)isrow_s)); 4871d65f70fdSStefano Zampini iscol_s = isrow_s; 4872d65f70fdSStefano Zampini } else { 4873d65f70fdSStefano Zampini const PetscInt *idxs; 4874d65f70fdSStefano Zampini PetscInt *idxs_sorted, i; 4875906d46d4SStefano Zampini 48769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(csize, &idxs_perm_c)); 48779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(csize, &idxs_sorted)); 4878ad540459SPierre Jolivet for (i = 0; i < csize; i++) idxs_perm_c[i] = i; 48799566063dSJacob Faibussowitsch PetscCall(ISGetIndices(iscol, &idxs)); 48809566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithPermutation(csize, idxs, idxs_perm_c)); 4881ad540459SPierre Jolivet for (i = 0; i < csize; i++) idxs_sorted[i] = idxs[idxs_perm_c[i]]; 48829566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(iscol, &idxs)); 48839566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, csize, idxs_sorted, PETSC_OWN_POINTER, &iscol_s)); 4884d65f70fdSStefano Zampini } 4885d65f70fdSStefano Zampini } else { 48869566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)iscol)); 4887d65f70fdSStefano Zampini iscol_s = iscol; 4888d65f70fdSStefano Zampini } 4889d65f70fdSStefano Zampini 48909566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(A, 1, &isrow_s, &iscol_s, MAT_INITIAL_MATRIX, &work_mat)); 4891d65f70fdSStefano Zampini 4892d65f70fdSStefano Zampini if (!rsorted || !csorted) { 4893906d46d4SStefano Zampini Mat new_mat; 4894d65f70fdSStefano Zampini IS is_perm_r, is_perm_c; 4895906d46d4SStefano Zampini 4896d65f70fdSStefano Zampini if (!rsorted) { 4897d65f70fdSStefano Zampini PetscInt *idxs_r, i; 48989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rsize, &idxs_r)); 4899ad540459SPierre Jolivet for (i = 0; i < rsize; i++) idxs_r[idxs_perm_r[i]] = i; 49009566063dSJacob Faibussowitsch PetscCall(PetscFree(idxs_perm_r)); 49019566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, rsize, idxs_r, PETSC_OWN_POINTER, &is_perm_r)); 4902d65f70fdSStefano Zampini } else { 49039566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, rsize, 0, 1, &is_perm_r)); 4904906d46d4SStefano Zampini } 49059566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(is_perm_r)); 4906d65f70fdSStefano Zampini 4907d65f70fdSStefano Zampini if (!csorted) { 4908d65f70fdSStefano Zampini if (isrow_s == iscol_s) { 49099566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is_perm_r)); 4910d65f70fdSStefano Zampini is_perm_c = is_perm_r; 4911d65f70fdSStefano Zampini } else { 4912d65f70fdSStefano Zampini PetscInt *idxs_c, i; 491328b400f6SJacob Faibussowitsch PetscCheck(idxs_perm_c, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Permutation array not present"); 49149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(csize, &idxs_c)); 4915ad540459SPierre Jolivet for (i = 0; i < csize; i++) idxs_c[idxs_perm_c[i]] = i; 49169566063dSJacob Faibussowitsch PetscCall(PetscFree(idxs_perm_c)); 49179566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, csize, idxs_c, PETSC_OWN_POINTER, &is_perm_c)); 4918d65f70fdSStefano Zampini } 4919d65f70fdSStefano Zampini } else { 49209566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, csize, 0, 1, &is_perm_c)); 4921d65f70fdSStefano Zampini } 49229566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(is_perm_c)); 4923d65f70fdSStefano Zampini 49249566063dSJacob Faibussowitsch PetscCall(MatPermute(work_mat[0], is_perm_r, is_perm_c, &new_mat)); 49259566063dSJacob Faibussowitsch PetscCall(MatDestroy(&work_mat[0])); 4926d65f70fdSStefano Zampini work_mat[0] = new_mat; 49279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_perm_r)); 49289566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_perm_c)); 4929d65f70fdSStefano Zampini } 4930d65f70fdSStefano Zampini 49319566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)work_mat[0])); 4932d65f70fdSStefano Zampini *B = work_mat[0]; 49339566063dSJacob Faibussowitsch PetscCall(MatDestroyMatrices(1, &work_mat)); 49349566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isrow_s)); 49359566063dSJacob Faibussowitsch PetscCall(ISDestroy(&iscol_s)); 49363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4937d65f70fdSStefano Zampini } 4938d65f70fdSStefano Zampini 4939d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix) 4940d71ae5a4SJacob Faibussowitsch { 4941aa0d41d4SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 49425e8657edSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 4943022d8d2bSstefano_zampini Mat new_mat, lA; 49445e8657edSStefano Zampini IS is_local, is_global; 4945d65f70fdSStefano Zampini PetscInt local_size; 4946b94d7dedSBarry Smith PetscBool isseqaij, issym, isset; 4947aa0d41d4SStefano Zampini 4948aa0d41d4SStefano Zampini PetscFunctionBegin; 49499566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 49509566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A, &local_size, NULL)); 49519566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)matis->A), local_size, 0, 1, &is_local)); 49529566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(matis->rmapping, is_local, &is_global)); 49539566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_local)); 49549566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrixUnsorted(ChangeOfBasisMatrix, is_global, is_global, &new_mat)); 49559566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_global)); 4956906d46d4SStefano Zampini 4957906d46d4SStefano Zampini if (pcbddc->dbg_flag) { 4958906d46d4SStefano Zampini Vec x, x_change; 4959906d46d4SStefano Zampini PetscReal error; 4960906d46d4SStefano Zampini 49619566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(ChangeOfBasisMatrix, &x, &x_change)); 49629566063dSJacob Faibussowitsch PetscCall(VecSetRandom(x, NULL)); 49639566063dSJacob Faibussowitsch PetscCall(MatMult(ChangeOfBasisMatrix, x, x_change)); 49649566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->cctx, x, matis->x, INSERT_VALUES, SCATTER_FORWARD)); 49659566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->cctx, x, matis->x, INSERT_VALUES, SCATTER_FORWARD)); 49669566063dSJacob Faibussowitsch PetscCall(MatMult(new_mat, matis->x, matis->y)); 496788428137SStefano Zampini if (!pcbddc->change_interior) { 496888428137SStefano Zampini const PetscScalar *x, *y, *v; 496988428137SStefano Zampini PetscReal lerror = 0.; 497088428137SStefano Zampini PetscInt i; 497188428137SStefano Zampini 49729566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(matis->x, &x)); 49739566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(matis->y, &y)); 49749566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(matis->counter, &v)); 497588428137SStefano Zampini for (i = 0; i < local_size; i++) 49769371c9d4SSatish Balay if (PetscRealPart(v[i]) < 1.5 && PetscAbsScalar(x[i] - y[i]) > lerror) lerror = PetscAbsScalar(x[i] - y[i]); 49779566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(matis->x, &x)); 49789566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(matis->y, &y)); 49799566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(matis->counter, &v)); 49801c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&lerror, &error, 1, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)pc))); 4981637e8532SStefano Zampini if (error > PETSC_SMALL) { 4982637e8532SStefano Zampini if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) { 498363a3b9bcSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_PLIB, "Error global vs local change on I: %1.6e", (double)error); 4984637e8532SStefano Zampini } else { 498563a3b9bcSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "Error global vs local change on I: %1.6e", (double)error); 4986637e8532SStefano Zampini } 4987637e8532SStefano Zampini } 498888428137SStefano Zampini } 49899566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, matis->y, x, INSERT_VALUES, SCATTER_REVERSE)); 49909566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, matis->y, x, INSERT_VALUES, SCATTER_REVERSE)); 49919566063dSJacob Faibussowitsch PetscCall(VecAXPY(x, -1.0, x_change)); 49929566063dSJacob Faibussowitsch PetscCall(VecNorm(x, NORM_INFINITY, &error)); 4993637e8532SStefano Zampini if (error > PETSC_SMALL) { 4994637e8532SStefano Zampini if (!pcbddc->user_ChangeOfBasisMatrix || pcbddc->current_level) { 499563a3b9bcSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_PLIB, "Error global vs local change on N: %1.6e", (double)error); 4996637e8532SStefano Zampini } else { 499763a3b9bcSJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "Error global vs local change on N: %1.6e", (double)error); 4998637e8532SStefano Zampini } 4999637e8532SStefano Zampini } 50009566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 50019566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x_change)); 5002906d46d4SStefano Zampini } 5003906d46d4SStefano Zampini 5004022d8d2bSstefano_zampini /* lA is present if we are setting up an inner BDDC for a saddle point FETI-DP */ 50059566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lA", (PetscObject *)&lA)); 5006022d8d2bSstefano_zampini 500722d5777bSStefano Zampini /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */ 50089566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQAIJ, &isseqaij)); 500922d5777bSStefano Zampini if (isseqaij) { 50109566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 50119566063dSJacob Faibussowitsch PetscCall(MatPtAP(matis->A, new_mat, MAT_INITIAL_MATRIX, 2.0, &pcbddc->local_mat)); 5012022d8d2bSstefano_zampini if (lA) { 5013022d8d2bSstefano_zampini Mat work; 50149566063dSJacob Faibussowitsch PetscCall(MatPtAP(lA, new_mat, MAT_INITIAL_MATRIX, 2.0, &work)); 50159566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_lA", (PetscObject)work)); 50169566063dSJacob Faibussowitsch PetscCall(MatDestroy(&work)); 5017022d8d2bSstefano_zampini } 5018aa0d41d4SStefano Zampini } else { 5019a00504b5SStefano Zampini Mat work_mat; 50201cf9b237SStefano Zampini 50219566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 50229566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &work_mat)); 50239566063dSJacob Faibussowitsch PetscCall(MatPtAP(work_mat, new_mat, MAT_INITIAL_MATRIX, 2.0, &pcbddc->local_mat)); 50249566063dSJacob Faibussowitsch PetscCall(MatDestroy(&work_mat)); 5025022d8d2bSstefano_zampini if (lA) { 5026022d8d2bSstefano_zampini Mat work; 50279566063dSJacob Faibussowitsch PetscCall(MatConvert(lA, MATSEQAIJ, MAT_INITIAL_MATRIX, &work_mat)); 50289566063dSJacob Faibussowitsch PetscCall(MatPtAP(work_mat, new_mat, MAT_INITIAL_MATRIX, 2.0, &work)); 50299566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_lA", (PetscObject)work)); 50309566063dSJacob Faibussowitsch PetscCall(MatDestroy(&work)); 5031022d8d2bSstefano_zampini } 5032aa0d41d4SStefano Zampini } 5033b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(matis->A, &isset, &issym)); 5034b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(pcbddc->local_mat, MAT_SYMMETRIC, issym)); 50359566063dSJacob Faibussowitsch PetscCall(MatDestroy(&new_mat)); 50363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5037aa0d41d4SStefano Zampini } 5038aa0d41d4SStefano Zampini 5039d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpLocalScatters(PC pc) 5040d71ae5a4SJacob Faibussowitsch { 5041*f4f49eeaSPierre Jolivet PC_IS *pcis = (PC_IS *)pc->data; 5042a64d13efSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 5043d62866d3SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 504453892102SStefano Zampini PetscInt *idx_R_local = NULL; 50453a50541eSStefano Zampini PetscInt n_vertices, i, j, n_R, n_D, n_B; 50463a50541eSStefano Zampini PetscInt vbs, bs; 50476816873aSStefano Zampini PetscBT bitmask = NULL; 5048a64d13efSStefano Zampini 5049a64d13efSStefano Zampini PetscFunctionBegin; 5050b23d619eSStefano Zampini /* 5051b23d619eSStefano Zampini No need to setup local scatters if 5052b23d619eSStefano Zampini - primal space is unchanged 5053b23d619eSStefano Zampini AND 5054b23d619eSStefano Zampini - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains) 5055b23d619eSStefano Zampini AND 5056b23d619eSStefano Zampini - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine 5057b23d619eSStefano Zampini */ 50583ba16761SJacob Faibussowitsch if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) PetscFunctionReturn(PETSC_SUCCESS); 5059f4ddd8eeSStefano Zampini /* destroy old objects */ 50609566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->is_R_local)); 50619566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->R_to_B)); 50629566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->R_to_D)); 5063a64d13efSStefano Zampini /* Set Non-overlapping dimensions */ 5064b371cd4fSStefano Zampini n_B = pcis->n_B; 5065b371cd4fSStefano Zampini n_D = pcis->n - n_B; 5066b371cd4fSStefano Zampini n_vertices = pcbddc->n_vertices; 50673a50541eSStefano Zampini 5068e602f447SPierre Jolivet /* Dohrmann's notation: dofs split in R (Remaining: all dofs but the vertices) and V (Vertices) */ 50696816873aSStefano Zampini 507053892102SStefano Zampini /* create auxiliary bitmask and allocate workspace */ 5071b334f244SStefano Zampini if (!sub_schurs || !sub_schurs->reuse_solver) { 50729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n - n_vertices, &idx_R_local)); 50739566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(pcis->n, &bitmask)); 507448a46eb9SPierre Jolivet for (i = 0; i < n_vertices; i++) PetscCall(PetscBTSet(bitmask, pcbddc->local_primal_ref_node[i])); 50754641a718SStefano Zampini 5076a64d13efSStefano Zampini for (i = 0, n_R = 0; i < pcis->n; i++) { 5077ad540459SPierre Jolivet if (!PetscBTLookup(bitmask, i)) idx_R_local[n_R++] = i; 5078a64d13efSStefano Zampini } 5079df4d28bfSStefano Zampini } else { /* A different ordering (already computed) is present if we are reusing the Schur solver */ 5080df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 50816816873aSStefano Zampini 50829566063dSJacob Faibussowitsch PetscCall(ISGetIndices(reuse_solver->is_R, (const PetscInt **)&idx_R_local)); 50839566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(reuse_solver->is_R, &n_R)); 50846816873aSStefano Zampini } 50853a50541eSStefano Zampini 50863a50541eSStefano Zampini /* Block code */ 50873a50541eSStefano Zampini vbs = 1; 50889566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(pcbddc->local_mat, &bs)); 50893a50541eSStefano Zampini if (bs > 1 && !(n_vertices % bs)) { 50903a50541eSStefano Zampini PetscBool is_blocked = PETSC_TRUE; 50913a50541eSStefano Zampini PetscInt *vary; 5092b334f244SStefano Zampini if (!sub_schurs || !sub_schurs->reuse_solver) { 50939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n / bs, &vary)); 50949566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(vary, pcis->n / bs)); 5095d3df7717SStefano Zampini /* Verify that the vertex indices correspond to each element in a block (code taken from sbaij2.c) */ 5096d3df7717SStefano 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 */ 50970e6343abSStefano Zampini for (i = 0; i < n_vertices; i++) vary[pcbddc->local_primal_ref_node[i] / bs]++; 5098d3df7717SStefano Zampini for (i = 0; i < pcis->n / bs; i++) { 50993a50541eSStefano Zampini if (vary[i] != 0 && vary[i] != bs) { 51003a50541eSStefano Zampini is_blocked = PETSC_FALSE; 51013a50541eSStefano Zampini break; 51023a50541eSStefano Zampini } 51033a50541eSStefano Zampini } 51049566063dSJacob Faibussowitsch PetscCall(PetscFree(vary)); 5105d3df7717SStefano Zampini } else { 5106d3df7717SStefano Zampini /* Verify directly the R set */ 5107d3df7717SStefano Zampini for (i = 0; i < n_R / bs; i++) { 5108d3df7717SStefano Zampini PetscInt j, node = idx_R_local[bs * i]; 5109d3df7717SStefano Zampini for (j = 1; j < bs; j++) { 5110d3df7717SStefano Zampini if (node != idx_R_local[bs * i + j] - j) { 5111d3df7717SStefano Zampini is_blocked = PETSC_FALSE; 5112d3df7717SStefano Zampini break; 5113d3df7717SStefano Zampini } 5114d3df7717SStefano Zampini } 5115d3df7717SStefano Zampini } 5116d3df7717SStefano Zampini } 51173a50541eSStefano Zampini if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */ 51183a50541eSStefano Zampini vbs = bs; 5119ad540459SPierre Jolivet for (i = 0; i < n_R / vbs; i++) idx_R_local[i] = idx_R_local[vbs * i] / vbs; 51203a50541eSStefano Zampini } 51213a50541eSStefano Zampini } 51229566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF, vbs, n_R / vbs, idx_R_local, PETSC_COPY_VALUES, &pcbddc->is_R_local)); 5123b334f244SStefano Zampini if (sub_schurs && sub_schurs->reuse_solver) { 5124df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 512553892102SStefano Zampini 51269566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(reuse_solver->is_R, (const PetscInt **)&idx_R_local)); 51279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&reuse_solver->is_R)); 51289566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->is_R_local)); 5129df4d28bfSStefano Zampini reuse_solver->is_R = pcbddc->is_R_local; 513053892102SStefano Zampini } else { 51319566063dSJacob Faibussowitsch PetscCall(PetscFree(idx_R_local)); 513253892102SStefano Zampini } 5133a64d13efSStefano Zampini 5134a64d13efSStefano Zampini /* print some info if requested */ 5135a64d13efSStefano Zampini if (pcbddc->dbg_flag) { 51369566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 51379566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 51389566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 51399566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d local dimensions\n", PetscGlobalRank)); 514063a3b9bcSJacob 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)); 51419371c9d4SSatish 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, 51429371c9d4SSatish Balay pcbddc->local_primal_size - n_vertices - pcbddc->benign_n, pcbddc->local_primal_size)); 51439566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 5144a64d13efSStefano Zampini } 5145a64d13efSStefano Zampini 5146a64d13efSStefano Zampini /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */ 5147b334f244SStefano Zampini if (!sub_schurs || !sub_schurs->reuse_solver) { 51486816873aSStefano Zampini IS is_aux1, is_aux2; 51496816873aSStefano Zampini PetscInt *aux_array1, *aux_array2, *is_indices, *idx_R_local; 51506816873aSStefano Zampini 51519566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->is_R_local, (const PetscInt **)&idx_R_local)); 51529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n_B - n_vertices, &aux_array1)); 51539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n_B - n_vertices, &aux_array2)); 51549566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_I_local, (const PetscInt **)&is_indices)); 515548a46eb9SPierre Jolivet for (i = 0; i < n_D; i++) PetscCall(PetscBTSet(bitmask, is_indices[i])); 51569566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_I_local, (const PetscInt **)&is_indices)); 5157a64d13efSStefano Zampini for (i = 0, j = 0; i < n_R; i++) { 5158ad540459SPierre Jolivet if (!PetscBTLookup(bitmask, idx_R_local[i])) aux_array1[j++] = i; 5159a64d13efSStefano Zampini } 51609566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, aux_array1, PETSC_OWN_POINTER, &is_aux1)); 51619566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_B_local, (const PetscInt **)&is_indices)); 5162a64d13efSStefano Zampini for (i = 0, j = 0; i < n_B; i++) { 5163ad540459SPierre Jolivet if (!PetscBTLookup(bitmask, is_indices[i])) aux_array2[j++] = i; 5164a64d13efSStefano Zampini } 51659566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_B_local, (const PetscInt **)&is_indices)); 51669566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, aux_array2, PETSC_OWN_POINTER, &is_aux2)); 51679566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(pcbddc->vec1_R, is_aux1, pcis->vec1_B, is_aux2, &pcbddc->R_to_B)); 51689566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_aux1)); 51699566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_aux2)); 5170a64d13efSStefano Zampini 51718eeda7d8SStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 51729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_D, &aux_array1)); 5173a64d13efSStefano Zampini for (i = 0, j = 0; i < n_R; i++) { 5174ad540459SPierre Jolivet if (PetscBTLookup(bitmask, idx_R_local[i])) aux_array1[j++] = i; 5175a64d13efSStefano Zampini } 51769566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, j, aux_array1, PETSC_OWN_POINTER, &is_aux1)); 51779566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(pcbddc->vec1_R, is_aux1, pcis->vec1_D, (IS)0, &pcbddc->R_to_D)); 51789566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_aux1)); 5179a64d13efSStefano Zampini } 51809566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&bitmask)); 51819566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->is_R_local, (const PetscInt **)&idx_R_local)); 5182d62866d3SStefano Zampini } else { 5183df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 51846816873aSStefano Zampini IS tis; 51856816873aSStefano Zampini PetscInt schur_size; 51866816873aSStefano Zampini 51879566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(reuse_solver->is_B, &schur_size)); 51889566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, schur_size, n_D, 1, &tis)); 51899566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(pcbddc->vec1_R, tis, pcis->vec1_B, reuse_solver->is_B, &pcbddc->R_to_B)); 51909566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tis)); 51916816873aSStefano Zampini if (pcbddc->switch_static || pcbddc->dbg_flag) { 51929566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, n_D, 0, 1, &tis)); 51939566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(pcbddc->vec1_R, tis, pcis->vec1_D, (IS)0, &pcbddc->R_to_D)); 51949566063dSJacob Faibussowitsch PetscCall(ISDestroy(&tis)); 5195d62866d3SStefano Zampini } 5196d62866d3SStefano Zampini } 51973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5198a64d13efSStefano Zampini } 5199a64d13efSStefano Zampini 5200d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatNullSpacePropagateAny_Private(Mat A, IS is, Mat B) 5201d71ae5a4SJacob Faibussowitsch { 520292cccca0SStefano Zampini MatNullSpace NullSpace; 520392cccca0SStefano Zampini Mat dmat; 520492cccca0SStefano Zampini const Vec *nullvecs; 520592cccca0SStefano Zampini Vec v, v2, *nullvecs2; 52066d9e27e4SStefano Zampini VecScatter sct = NULL; 5207eb06acf8SStefano Zampini PetscContainer c; 5208eb06acf8SStefano Zampini PetscScalar *ddata; 5209295df10fSStefano Zampini PetscInt k, nnsp_size, bsiz, bsiz2, n, N, bs; 521092cccca0SStefano Zampini PetscBool nnsp_has_cnst; 521192cccca0SStefano Zampini 521292cccca0SStefano Zampini PetscFunctionBegin; 52136d9e27e4SStefano Zampini if (!is && !B) { /* MATIS */ 52146d9e27e4SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 52156d9e27e4SStefano Zampini 521648a46eb9SPierre Jolivet if (!B) PetscCall(MatISGetLocalMat(A, &B)); 52176d9e27e4SStefano Zampini sct = matis->cctx; 52189566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)sct)); 52196d9e27e4SStefano Zampini } else { 52209566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(B, &NullSpace)); 522148a46eb9SPierre Jolivet if (!NullSpace) PetscCall(MatGetNearNullSpace(B, &NullSpace)); 52223ba16761SJacob Faibussowitsch if (NullSpace) PetscFunctionReturn(PETSC_SUCCESS); 52236d9e27e4SStefano Zampini } 52249566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(A, &NullSpace)); 522548a46eb9SPierre Jolivet if (!NullSpace) PetscCall(MatGetNearNullSpace(A, &NullSpace)); 52263ba16761SJacob Faibussowitsch if (!NullSpace) PetscFunctionReturn(PETSC_SUCCESS); 52276d9e27e4SStefano Zampini 52289566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, &v, NULL)); 52299566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(B, &v2, NULL)); 523048a46eb9SPierre Jolivet if (!sct) PetscCall(VecScatterCreate(v, is, v2, NULL, &sct)); 52319566063dSJacob Faibussowitsch PetscCall(MatNullSpaceGetVecs(NullSpace, &nnsp_has_cnst, &nnsp_size, (const Vec **)&nullvecs)); 5232295df10fSStefano Zampini bsiz = bsiz2 = nnsp_size + !!nnsp_has_cnst; 52339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bsiz, &nullvecs2)); 52349566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(v2, &bs)); 52359566063dSJacob Faibussowitsch PetscCall(VecGetSize(v2, &N)); 52369566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v2, &n)); 52379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n * bsiz, &ddata)); 523892cccca0SStefano Zampini for (k = 0; k < nnsp_size; k++) { 52399566063dSJacob Faibussowitsch PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)B), bs, n, N, ddata + n * k, &nullvecs2[k])); 52409566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(sct, nullvecs[k], nullvecs2[k], INSERT_VALUES, SCATTER_FORWARD)); 52419566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(sct, nullvecs[k], nullvecs2[k], INSERT_VALUES, SCATTER_FORWARD)); 524292cccca0SStefano Zampini } 524392cccca0SStefano Zampini if (nnsp_has_cnst) { 52449566063dSJacob Faibussowitsch PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)B), bs, n, N, ddata + n * nnsp_size, &nullvecs2[nnsp_size])); 52459566063dSJacob Faibussowitsch PetscCall(VecSet(nullvecs2[nnsp_size], 1.0)); 524692cccca0SStefano Zampini } 52479566063dSJacob Faibussowitsch PetscCall(PCBDDCOrthonormalizeVecs(&bsiz2, nullvecs2)); 52489566063dSJacob Faibussowitsch PetscCall(MatNullSpaceCreate(PetscObjectComm((PetscObject)B), PETSC_FALSE, bsiz2, nullvecs2, &NullSpace)); 5249295df10fSStefano Zampini 52509566063dSJacob Faibussowitsch PetscCall(MatCreateDense(PetscObjectComm((PetscObject)B), n, PETSC_DECIDE, N, bsiz2, ddata, &dmat)); 52519566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &c)); 52529566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(c, ddata)); 52539566063dSJacob Faibussowitsch PetscCall(PetscContainerSetUserDestroy(c, PetscContainerUserDestroyDefault)); 52549566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)dmat, "_PBDDC_Null_dmat_arr", (PetscObject)c)); 52559566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&c)); 52569566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)NullSpace, "_PBDDC_Null_dmat", (PetscObject)dmat)); 52579566063dSJacob Faibussowitsch PetscCall(MatDestroy(&dmat)); 5258eb06acf8SStefano Zampini 525948a46eb9SPierre Jolivet for (k = 0; k < bsiz; k++) PetscCall(VecDestroy(&nullvecs2[k])); 52609566063dSJacob Faibussowitsch PetscCall(PetscFree(nullvecs2)); 52619566063dSJacob Faibussowitsch PetscCall(MatSetNearNullSpace(B, NullSpace)); 52629566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&NullSpace)); 52639566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 52649566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v2)); 52659566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&sct)); 52663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 526792cccca0SStefano Zampini } 5268304d26faSStefano Zampini 5269d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann) 5270d71ae5a4SJacob Faibussowitsch { 5271304d26faSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 5272304d26faSStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 5273304d26faSStefano Zampini PC pc_temp; 5274304d26faSStefano Zampini Mat A_RR; 527592cccca0SStefano Zampini MatNullSpace nnsp; 5276f4ddd8eeSStefano Zampini MatReuse reuse; 5277304d26faSStefano Zampini PetscScalar m_one = -1.0; 5278304d26faSStefano Zampini PetscReal value; 527904708bb6SStefano Zampini PetscInt n_D, n_R; 5280b94d7dedSBarry Smith PetscBool issbaij, opts, isset, issym; 52810a545947SLisandro Dalcin void (*f)(void) = NULL; 5282312be037SStefano Zampini char dir_prefix[256], neu_prefix[256], str_level[16]; 5283e604994aSStefano Zampini size_t len; 5284304d26faSStefano Zampini 5285304d26faSStefano Zampini PetscFunctionBegin; 52869566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_LocalSolvers[pcbddc->current_level], pc, 0, 0, 0)); 52876d9e27e4SStefano Zampini /* approximate solver, propagate NearNullSpace if needed */ 52886d9e27e4SStefano Zampini if (!pc->setupcalled && (pcbddc->NullSpace_corr[0] || pcbddc->NullSpace_corr[2])) { 52896d9e27e4SStefano Zampini MatNullSpace gnnsp1, gnnsp2; 52906d9e27e4SStefano Zampini PetscBool lhas, ghas; 52916d9e27e4SStefano Zampini 52929566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pcbddc->local_mat, &nnsp)); 52939566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pc->pmat, &gnnsp1)); 52949566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(pc->pmat, &gnnsp2)); 52956d9e27e4SStefano Zampini lhas = nnsp ? PETSC_TRUE : PETSC_FALSE; 52961c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&lhas, &ghas, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 529748a46eb9SPierre Jolivet if (!ghas && (gnnsp1 || gnnsp2)) PetscCall(MatNullSpacePropagateAny_Private(pc->pmat, NULL, NULL)); 52986d9e27e4SStefano Zampini } 52996d9e27e4SStefano Zampini 5300e604994aSStefano Zampini /* compute prefixes */ 5301c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(dir_prefix, "", sizeof(dir_prefix))); 5302c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(neu_prefix, "", sizeof(neu_prefix))); 5303e604994aSStefano Zampini if (!pcbddc->current_level) { 53049566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(dir_prefix, ((PetscObject)pc)->prefix, sizeof(dir_prefix))); 53059566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(neu_prefix, ((PetscObject)pc)->prefix, sizeof(neu_prefix))); 53069566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(dir_prefix, "pc_bddc_dirichlet_", sizeof(dir_prefix))); 53079566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(neu_prefix, "pc_bddc_neumann_", sizeof(neu_prefix))); 5308e604994aSStefano Zampini } else { 5309*f4f49eeaSPierre Jolivet PetscCall(PetscSNPrintf(str_level, sizeof(str_level), "l%d_", (int)pcbddc->current_level)); 53109566063dSJacob Faibussowitsch PetscCall(PetscStrlen(((PetscObject)pc)->prefix, &len)); 5311e604994aSStefano Zampini len -= 15; /* remove "pc_bddc_coarse_" */ 5312312be037SStefano Zampini if (pcbddc->current_level > 1) len -= 3; /* remove "lX_" with X level number */ 5313312be037SStefano Zampini if (pcbddc->current_level > 10) len -= 1; /* remove another char from level number */ 5314a126751eSBarry Smith /* Nonstandard use of PetscStrncpy() to only copy a portion of the input string */ 53159566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(dir_prefix, ((PetscObject)pc)->prefix, len + 1)); 53169566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(neu_prefix, ((PetscObject)pc)->prefix, len + 1)); 53179566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(dir_prefix, "pc_bddc_dirichlet_", sizeof(dir_prefix))); 53189566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(neu_prefix, "pc_bddc_neumann_", sizeof(neu_prefix))); 53199566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(dir_prefix, str_level, sizeof(dir_prefix))); 53209566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(neu_prefix, str_level, sizeof(neu_prefix))); 5321e604994aSStefano Zampini } 5322e604994aSStefano Zampini 5323304d26faSStefano Zampini /* DIRICHLET PROBLEM */ 5324684f6988SStefano Zampini if (dirichlet) { 5325d5574798SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 5326450f8f5eSStefano Zampini if (pcbddc->benign_n && !pcbddc->benign_change_explicit) { 53277827d75bSBarry Smith PetscCheck(sub_schurs && sub_schurs->reuse_solver, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not yet implemented"); 5328450f8f5eSStefano Zampini if (pcbddc->dbg_flag) { 5329a3df083aSStefano Zampini Mat A_IIn; 5330a3df083aSStefano Zampini 53319566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignProject(pc, pcis->is_I_local, pcis->is_I_local, &A_IIn)); 53329566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_II)); 5333a3df083aSStefano Zampini pcis->A_II = A_IIn; 5334a3df083aSStefano Zampini } 5335450f8f5eSStefano Zampini } 5336b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(pcbddc->local_mat, &isset, &issym)); 5337b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(pcis->A_II, MAT_SYMMETRIC, issym)); 5338b94d7dedSBarry Smith 5339ac78edfcSStefano Zampini /* Matrix for Dirichlet problem is pcis->A_II */ 5340964fefecSStefano Zampini n_D = pcis->n - pcis->n_B; 534192cccca0SStefano Zampini opts = PETSC_FALSE; 5342304d26faSStefano Zampini if (!pcbddc->ksp_D) { /* create object if not yet build */ 534392cccca0SStefano Zampini opts = PETSC_TRUE; 53449566063dSJacob Faibussowitsch PetscCall(KSPCreate(PETSC_COMM_SELF, &pcbddc->ksp_D)); 53453821be0aSBarry Smith PetscCall(KSPSetNestLevel(pcbddc->ksp_D, pc->kspnestlevel)); 53469566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D, (PetscObject)pc, 1)); 5347304d26faSStefano Zampini /* default */ 53489566063dSJacob Faibussowitsch PetscCall(KSPSetType(pcbddc->ksp_D, KSPPREONLY)); 53499566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(pcbddc->ksp_D, dir_prefix)); 53509566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pcis->pA_II, MATSEQSBAIJ, &issbaij)); 53519566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_D, &pc_temp)); 53529577ea80SStefano Zampini if (issbaij) { 53539566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCCHOLESKY)); 53549577ea80SStefano Zampini } else { 53559566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCLU)); 53569577ea80SStefano Zampini } 53579566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(pcbddc->ksp_D, pc->erroriffailure)); 535892cccca0SStefano Zampini } 53599566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(pcis->pA_II, ((PetscObject)pcbddc->ksp_D)->prefix)); 53609566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(pcbddc->ksp_D, pcis->A_II, pcis->pA_II)); 5361304d26faSStefano Zampini /* Allow user's customization */ 53621baa6e33SBarry Smith if (opts) PetscCall(KSPSetFromOptions(pcbddc->ksp_D)); 53639566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pcis->pA_II, &nnsp)); 53646d9e27e4SStefano Zampini if (pcbddc->NullSpace_corr[0] && !nnsp) { /* approximate solver, propagate NearNullSpace */ 53659566063dSJacob Faibussowitsch PetscCall(MatNullSpacePropagateAny_Private(pcbddc->local_mat, pcis->is_I_local, pcis->pA_II)); 536692cccca0SStefano Zampini } 53679566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pcis->pA_II, &nnsp)); 53689566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_D, &pc_temp)); 53699566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)pc_temp, "PCSetCoordinates_C", &f)); 537092cccca0SStefano Zampini if (f && pcbddc->mat_graph->cloc && !nnsp) { 5371cd18cfedSStefano Zampini PetscReal *coords = pcbddc->mat_graph->coords, *scoords; 5372cd18cfedSStefano Zampini const PetscInt *idxs; 5373cd18cfedSStefano Zampini PetscInt cdim = pcbddc->mat_graph->cdim, nl, i, d; 5374cd18cfedSStefano Zampini 53759566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcis->is_I_local, &nl)); 53769566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcis->is_I_local, &idxs)); 53779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl * cdim, &scoords)); 5378cd18cfedSStefano Zampini for (i = 0; i < nl; i++) { 5379ad540459SPierre Jolivet for (d = 0; d < cdim; d++) scoords[i * cdim + d] = coords[idxs[i] * cdim + d]; 5380cd18cfedSStefano Zampini } 53819566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcis->is_I_local, &idxs)); 53829566063dSJacob Faibussowitsch PetscCall(PCSetCoordinates(pc_temp, cdim, nl, scoords)); 53839566063dSJacob Faibussowitsch PetscCall(PetscFree(scoords)); 5384cd18cfedSStefano Zampini } 5385b334f244SStefano Zampini if (sub_schurs && sub_schurs->reuse_solver) { 5386df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 5387d62866d3SStefano Zampini 53889566063dSJacob Faibussowitsch PetscCall(KSPSetPC(pcbddc->ksp_D, reuse_solver->interior_solver)); 5389d5574798SStefano Zampini } 539092cccca0SStefano Zampini 5391304d26faSStefano Zampini /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */ 5392304d26faSStefano Zampini if (!n_D) { 53939566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_D, &pc_temp)); 53949566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCNONE)); 5395304d26faSStefano Zampini } 53969566063dSJacob Faibussowitsch PetscCall(KSPSetUp(pcbddc->ksp_D)); 5397304d26faSStefano Zampini /* set ksp_D into pcis data */ 53989566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->ksp_D)); 53999566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&pcis->ksp_D)); 5400304d26faSStefano Zampini pcis->ksp_D = pcbddc->ksp_D; 5401684f6988SStefano Zampini } 5402304d26faSStefano Zampini 5403304d26faSStefano Zampini /* NEUMANN PROBLEM */ 54040a545947SLisandro Dalcin A_RR = NULL; 5405684f6988SStefano Zampini if (neumann) { 5406d62866d3SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 540704708bb6SStefano Zampini PetscInt ibs, mbs; 5408b94d7dedSBarry Smith PetscBool issbaij, reuse_neumann_solver, isset, issym; 540904708bb6SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 54100aa714b2SStefano Zampini 54110aa714b2SStefano Zampini reuse_neumann_solver = PETSC_FALSE; 54120aa714b2SStefano Zampini if (sub_schurs && sub_schurs->reuse_solver) { 54130aa714b2SStefano Zampini IS iP; 54140aa714b2SStefano Zampini 54150aa714b2SStefano Zampini reuse_neumann_solver = PETSC_TRUE; 54169566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)sub_schurs->A, "__KSPFETIDP_iP", (PetscObject *)&iP)); 54170aa714b2SStefano Zampini if (iP) reuse_neumann_solver = PETSC_FALSE; 54180aa714b2SStefano Zampini } 5419f4ddd8eeSStefano Zampini /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */ 54209566063dSJacob Faibussowitsch PetscCall(ISGetSize(pcbddc->is_R_local, &n_R)); 5421f4ddd8eeSStefano Zampini if (pcbddc->ksp_R) { /* already created ksp */ 5422f4ddd8eeSStefano Zampini PetscInt nn_R; 54239566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(pcbddc->ksp_R, NULL, &A_RR)); 54249566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A_RR)); 54259566063dSJacob Faibussowitsch PetscCall(MatGetSize(A_RR, &nn_R, NULL)); 5426f4ddd8eeSStefano Zampini if (nn_R != n_R) { /* old ksp is not reusable, so reset it */ 54279566063dSJacob Faibussowitsch PetscCall(KSPReset(pcbddc->ksp_R)); 54289566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 5429f4ddd8eeSStefano Zampini reuse = MAT_INITIAL_MATRIX; 5430f4ddd8eeSStefano Zampini } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */ 5431727cdba6SStefano Zampini if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */ 54329566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 5433f4ddd8eeSStefano Zampini reuse = MAT_INITIAL_MATRIX; 5434f4ddd8eeSStefano Zampini } else { /* safe to reuse the matrix */ 5435f4ddd8eeSStefano Zampini reuse = MAT_REUSE_MATRIX; 5436f4ddd8eeSStefano Zampini } 5437f4ddd8eeSStefano Zampini } 5438f4ddd8eeSStefano Zampini /* last check */ 5439d1e9a80fSBarry Smith if (pc->flag == DIFFERENT_NONZERO_PATTERN) { 54409566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 5441f4ddd8eeSStefano Zampini reuse = MAT_INITIAL_MATRIX; 5442f4ddd8eeSStefano Zampini } 5443f4ddd8eeSStefano Zampini } else { /* first time, so we need to create the matrix */ 5444f4ddd8eeSStefano Zampini reuse = MAT_INITIAL_MATRIX; 5445f4ddd8eeSStefano Zampini } 5446365a3a41SStefano Zampini /* convert pcbddc->local_mat if needed later in PCBDDCSetUpCorrection 5447365a3a41SStefano Zampini TODO: Get Rid of these conversions */ 54489566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(pcbddc->local_mat, &mbs)); 54499566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(pcbddc->is_R_local, &ibs)); 54509566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pcbddc->local_mat, MATSEQSBAIJ, &issbaij)); 545104708bb6SStefano Zampini if (ibs != mbs) { /* need to convert to SEQAIJ to extract any submatrix with is_R_local */ 545204708bb6SStefano Zampini if (matis->A == pcbddc->local_mat) { 54539566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 54549566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &pcbddc->local_mat)); 5455af732b37SStefano Zampini } else { 54569566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->local_mat, MATSEQAIJ, MAT_INPLACE_MATRIX, &pcbddc->local_mat)); 54576816873aSStefano Zampini } 54584cf0e950SBarry Smith } else if (issbaij) { /* need to convert to BAIJ to get off-diagonal blocks */ 545904708bb6SStefano Zampini if (matis->A == pcbddc->local_mat) { 54609566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 54619566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, mbs > 1 ? MATSEQBAIJ : MATSEQAIJ, MAT_INITIAL_MATRIX, &pcbddc->local_mat)); 546204708bb6SStefano Zampini } else { 54639566063dSJacob Faibussowitsch PetscCall(MatConvert(pcbddc->local_mat, mbs > 1 ? MATSEQBAIJ : MATSEQAIJ, MAT_INPLACE_MATRIX, &pcbddc->local_mat)); 546404708bb6SStefano Zampini } 546504708bb6SStefano Zampini } 5466a00504b5SStefano Zampini /* extract A_RR */ 54670aa714b2SStefano Zampini if (reuse_neumann_solver) { 5468a00504b5SStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 5469a00504b5SStefano Zampini 5470a00504b5SStefano Zampini if (pcbddc->dbg_flag) { /* we need A_RR to test the solver later */ 54719566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 5472a00504b5SStefano Zampini if (reuse_solver->benign_n) { /* we are not using the explicit change of basis on the pressures */ 54739566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignProject(pc, pcbddc->is_R_local, pcbddc->is_R_local, &A_RR)); 547416e386b8SStefano Zampini } else { 54759566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcbddc->is_R_local, pcbddc->is_R_local, MAT_INITIAL_MATRIX, &A_RR)); 5476a00504b5SStefano Zampini } 5477a00504b5SStefano Zampini } else { 54789566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 54799566063dSJacob Faibussowitsch PetscCall(PCGetOperators(reuse_solver->correction_solver, &A_RR, NULL)); 54809566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A_RR)); 5481a00504b5SStefano Zampini } 5482a00504b5SStefano Zampini } else { /* we have to build the neumann solver, so we need to extract the relevant matrix */ 54839566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcbddc->is_R_local, pcbddc->is_R_local, reuse, &A_RR)); 548416e386b8SStefano Zampini } 5485b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(pcbddc->local_mat, &isset, &issym)); 5486b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(A_RR, MAT_SYMMETRIC, issym)); 548792cccca0SStefano Zampini opts = PETSC_FALSE; 5488f4ddd8eeSStefano Zampini if (!pcbddc->ksp_R) { /* create object if not present */ 548992cccca0SStefano Zampini opts = PETSC_TRUE; 54909566063dSJacob Faibussowitsch PetscCall(KSPCreate(PETSC_COMM_SELF, &pcbddc->ksp_R)); 54913821be0aSBarry Smith PetscCall(KSPSetNestLevel(pcbddc->ksp_R, pc->kspnestlevel)); 54929566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R, (PetscObject)pc, 1)); 5493304d26faSStefano Zampini /* default */ 54949566063dSJacob Faibussowitsch PetscCall(KSPSetType(pcbddc->ksp_R, KSPPREONLY)); 54959566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(pcbddc->ksp_R, neu_prefix)); 54969566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_R, &pc_temp)); 54979566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A_RR, MATSEQSBAIJ, &issbaij)); 54989577ea80SStefano Zampini if (issbaij) { 54999566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCCHOLESKY)); 55009577ea80SStefano Zampini } else { 55019566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCLU)); 55029577ea80SStefano Zampini } 55039566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(pcbddc->ksp_R, pc->erroriffailure)); 550492cccca0SStefano Zampini } 55059566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(pcbddc->ksp_R, A_RR, A_RR)); 55069566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(A_RR, ((PetscObject)pcbddc->ksp_R)->prefix)); 550792cccca0SStefano Zampini if (opts) { /* Allow user's customization once */ 55089566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(pcbddc->ksp_R)); 550992cccca0SStefano Zampini } 55109566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(A_RR, &nnsp)); 55116d9e27e4SStefano Zampini if (pcbddc->NullSpace_corr[2] && !nnsp) { /* approximate solver, propagate NearNullSpace */ 55129566063dSJacob Faibussowitsch PetscCall(MatNullSpacePropagateAny_Private(pcbddc->local_mat, pcbddc->is_R_local, A_RR)); 551392cccca0SStefano Zampini } 55149566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(A_RR, &nnsp)); 55159566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_R, &pc_temp)); 55169566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)pc_temp, "PCSetCoordinates_C", &f)); 551792cccca0SStefano Zampini if (f && pcbddc->mat_graph->cloc && !nnsp) { 5518cd18cfedSStefano Zampini PetscReal *coords = pcbddc->mat_graph->coords, *scoords; 5519cd18cfedSStefano Zampini const PetscInt *idxs; 5520cd18cfedSStefano Zampini PetscInt cdim = pcbddc->mat_graph->cdim, nl, i, d; 5521cd18cfedSStefano Zampini 55229566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->is_R_local, &nl)); 55239566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->is_R_local, &idxs)); 55249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl * cdim, &scoords)); 5525cd18cfedSStefano Zampini for (i = 0; i < nl; i++) { 5526ad540459SPierre Jolivet for (d = 0; d < cdim; d++) scoords[i * cdim + d] = coords[idxs[i] * cdim + d]; 5527cd18cfedSStefano Zampini } 55289566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->is_R_local, &idxs)); 55299566063dSJacob Faibussowitsch PetscCall(PCSetCoordinates(pc_temp, cdim, nl, scoords)); 55309566063dSJacob Faibussowitsch PetscCall(PetscFree(scoords)); 5531cd18cfedSStefano Zampini } 553292cccca0SStefano Zampini 5533304d26faSStefano Zampini /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */ 5534304d26faSStefano Zampini if (!n_R) { 55359566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->ksp_R, &pc_temp)); 55369566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCNONE)); 5537304d26faSStefano Zampini } 5538df4d28bfSStefano Zampini /* Reuse solver if it is present */ 55390aa714b2SStefano Zampini if (reuse_neumann_solver) { 5540df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 5541d62866d3SStefano Zampini 55429566063dSJacob Faibussowitsch PetscCall(KSPSetPC(pcbddc->ksp_R, reuse_solver->correction_solver)); 5543d62866d3SStefano Zampini } 55449566063dSJacob Faibussowitsch PetscCall(KSPSetUp(pcbddc->ksp_R)); 5545684f6988SStefano Zampini } 5546304d26faSStefano Zampini 5547684f6988SStefano Zampini if (pcbddc->dbg_flag) { 55489566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 55499566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 55509566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 5551684f6988SStefano Zampini } 55529566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_LocalSolvers[pcbddc->current_level], pc, 0, 0, 0)); 5553c7017625SStefano Zampini 5554c7017625SStefano Zampini /* adapt Dirichlet and Neumann solvers if a nullspace correction has been requested */ 555548a46eb9SPierre Jolivet if (pcbddc->NullSpace_corr[0]) PetscCall(PCBDDCSetUseExactDirichlet(pc, PETSC_FALSE)); 555648a46eb9SPierre Jolivet if (dirichlet && pcbddc->NullSpace_corr[0] && !pcbddc->switch_static) PetscCall(PCBDDCNullSpaceAssembleCorrection(pc, PETSC_TRUE, pcbddc->NullSpace_corr[1])); 555748a46eb9SPierre Jolivet if (neumann && pcbddc->NullSpace_corr[2]) PetscCall(PCBDDCNullSpaceAssembleCorrection(pc, PETSC_FALSE, pcbddc->NullSpace_corr[3])); 5558c7017625SStefano Zampini /* check Dirichlet and Neumann solvers */ 5559c7017625SStefano Zampini if (pcbddc->dbg_flag) { 5560684f6988SStefano Zampini if (dirichlet) { /* Dirichlet */ 55619566063dSJacob Faibussowitsch PetscCall(VecSetRandom(pcis->vec1_D, NULL)); 55629566063dSJacob Faibussowitsch PetscCall(MatMult(pcis->A_II, pcis->vec1_D, pcis->vec2_D)); 55639566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec2_D, pcis->vec2_D)); 55649566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D)); 55659566063dSJacob Faibussowitsch PetscCall(VecAXPY(pcis->vec1_D, m_one, pcis->vec2_D)); 55669566063dSJacob Faibussowitsch PetscCall(VecNorm(pcis->vec1_D, NORM_INFINITY, &value)); 5567*f4f49eeaSPierre 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)); 55689566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 5569304d26faSStefano Zampini } 5570684f6988SStefano Zampini if (neumann) { /* Neumann */ 55719566063dSJacob Faibussowitsch PetscCall(VecSetRandom(pcbddc->vec1_R, NULL)); 55729566063dSJacob Faibussowitsch PetscCall(MatMult(A_RR, pcbddc->vec1_R, pcbddc->vec2_R)); 55739566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_R, pcbddc->vec2_R, pcbddc->vec2_R)); 55749566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec2_R)); 55759566063dSJacob Faibussowitsch PetscCall(VecAXPY(pcbddc->vec1_R, m_one, pcbddc->vec2_R)); 55769566063dSJacob Faibussowitsch PetscCall(VecNorm(pcbddc->vec1_R, NORM_INFINITY, &value)); 5577*f4f49eeaSPierre 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)); 55789566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 5579304d26faSStefano Zampini } 5580684f6988SStefano Zampini } 55815cbda25cSStefano Zampini /* free Neumann problem's matrix */ 55829566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A_RR)); 55833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5584304d26faSStefano Zampini } 5585304d26faSStefano Zampini 5586d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSolveSubstructureCorrection(PC pc, Vec inout_B, Vec inout_D, PetscBool applytranspose) 5587d71ae5a4SJacob Faibussowitsch { 5588*f4f49eeaSPierre Jolivet PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 5589be83ff47SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 5590b334f244SStefano Zampini PetscBool reuse_solver = sub_schurs ? (sub_schurs->reuse_solver ? PETSC_TRUE : PETSC_FALSE) : PETSC_FALSE; 5591674ae819SStefano Zampini 5592674ae819SStefano Zampini PetscFunctionBegin; 559348a46eb9SPierre Jolivet if (!reuse_solver) PetscCall(VecSet(pcbddc->vec1_R, 0.)); 559480677318SStefano Zampini if (!pcbddc->switch_static) { 559580677318SStefano Zampini if (applytranspose && pcbddc->local_auxmat1) { 55969566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->local_auxmat2, inout_B, pcbddc->vec1_C)); 55979566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(pcbddc->local_auxmat1, pcbddc->vec1_C, inout_B, inout_B)); 559820c7b377SStefano Zampini } 5599b334f244SStefano Zampini if (!reuse_solver) { 56009566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 56019566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 560220c7b377SStefano Zampini } else { 5603df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 5604be83ff47SStefano Zampini 56059566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(reuse_solver->correction_scatter_B, inout_B, reuse_solver->rhs_B, INSERT_VALUES, SCATTER_FORWARD)); 56069566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(reuse_solver->correction_scatter_B, inout_B, reuse_solver->rhs_B, INSERT_VALUES, SCATTER_FORWARD)); 560720c7b377SStefano Zampini } 5608be83ff47SStefano Zampini } else { 56099566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 56109566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 56119566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_D, inout_D, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 56129566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_D, inout_D, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 561380677318SStefano Zampini if (applytranspose && pcbddc->local_auxmat1) { 56149566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->local_auxmat2, pcbddc->vec1_R, pcbddc->vec1_C)); 56159566063dSJacob Faibussowitsch PetscCall(MatMultTransposeAdd(pcbddc->local_auxmat1, pcbddc->vec1_C, inout_B, inout_B)); 56169566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 56179566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, inout_B, pcbddc->vec1_R, INSERT_VALUES, SCATTER_REVERSE)); 5618674ae819SStefano Zampini } 5619674ae819SStefano Zampini } 56209566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][1], pc, 0, 0, 0)); 5621b334f244SStefano Zampini if (!reuse_solver || pcbddc->switch_static) { 562280677318SStefano Zampini if (applytranspose) { 56239566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec1_R)); 562480677318SStefano Zampini } else { 56259566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_R, pcbddc->vec1_R, pcbddc->vec1_R)); 562680677318SStefano Zampini } 56279566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_R, pc, pcbddc->vec1_R)); 5628be83ff47SStefano Zampini } else { 5629df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 5630be83ff47SStefano Zampini 5631be83ff47SStefano Zampini if (applytranspose) { 56329566063dSJacob Faibussowitsch PetscCall(MatFactorSolveSchurComplementTranspose(reuse_solver->F, reuse_solver->rhs_B, reuse_solver->sol_B)); 5633be83ff47SStefano Zampini } else { 56349566063dSJacob Faibussowitsch PetscCall(MatFactorSolveSchurComplement(reuse_solver->F, reuse_solver->rhs_B, reuse_solver->sol_B)); 5635be83ff47SStefano Zampini } 5636be83ff47SStefano Zampini } 56379566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][1], pc, 0, 0, 0)); 56389566063dSJacob Faibussowitsch PetscCall(VecSet(inout_B, 0.)); 563980677318SStefano Zampini if (!pcbddc->switch_static) { 5640b334f244SStefano Zampini if (!reuse_solver) { 56419566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 56429566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 5643be83ff47SStefano Zampini } else { 5644df4d28bfSStefano Zampini PCBDDCReuseSolvers reuse_solver = sub_schurs->reuse_solver; 5645be83ff47SStefano Zampini 56469566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(reuse_solver->correction_scatter_B, reuse_solver->sol_B, inout_B, INSERT_VALUES, SCATTER_REVERSE)); 56479566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(reuse_solver->correction_scatter_B, reuse_solver->sol_B, inout_B, INSERT_VALUES, SCATTER_REVERSE)); 5648be83ff47SStefano Zampini } 564980677318SStefano Zampini if (!applytranspose && pcbddc->local_auxmat1) { 56509566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->local_auxmat1, inout_B, pcbddc->vec1_C)); 56519566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pcbddc->local_auxmat2, pcbddc->vec1_C, inout_B, inout_B)); 565280677318SStefano Zampini } 565380677318SStefano Zampini } else { 56549566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 56559566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 56569566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_D, pcbddc->vec1_R, inout_D, INSERT_VALUES, SCATTER_FORWARD)); 56579566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_D, pcbddc->vec1_R, inout_D, INSERT_VALUES, SCATTER_FORWARD)); 565880677318SStefano Zampini if (!applytranspose && pcbddc->local_auxmat1) { 56599566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->local_auxmat1, inout_B, pcbddc->vec1_C)); 56609566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pcbddc->local_auxmat2, pcbddc->vec1_C, pcbddc->vec1_R, pcbddc->vec1_R)); 566180677318SStefano Zampini } 56629566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 56639566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_B, pcbddc->vec1_R, inout_B, INSERT_VALUES, SCATTER_FORWARD)); 56649566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->R_to_D, pcbddc->vec1_R, inout_D, INSERT_VALUES, SCATTER_FORWARD)); 56659566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->R_to_D, pcbddc->vec1_R, inout_D, INSERT_VALUES, SCATTER_FORWARD)); 5666674ae819SStefano Zampini } 56673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5668674ae819SStefano Zampini } 5669674ae819SStefano Zampini 5670dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */ 5671d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose) 5672d71ae5a4SJacob Faibussowitsch { 5673*f4f49eeaSPierre Jolivet PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 5674*f4f49eeaSPierre Jolivet PC_IS *pcis = (PC_IS *)pc->data; 5675674ae819SStefano Zampini const PetscScalar zero = 0.0; 5676674ae819SStefano Zampini 5677674ae819SStefano Zampini PetscFunctionBegin; 5678dc359a40SStefano Zampini /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */ 56794fee134fSStefano Zampini if (!pcbddc->benign_apply_coarse_only) { 5680dc359a40SStefano Zampini if (applytranspose) { 56819566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->coarse_phi_B, pcis->vec1_B, pcbddc->vec1_P)); 56829566063dSJacob Faibussowitsch if (pcbddc->switch_static) PetscCall(MatMultTransposeAdd(pcbddc->coarse_phi_D, pcis->vec1_D, pcbddc->vec1_P, pcbddc->vec1_P)); 5683dc359a40SStefano Zampini } else { 56849566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->coarse_psi_B, pcis->vec1_B, pcbddc->vec1_P)); 56859566063dSJacob Faibussowitsch if (pcbddc->switch_static) PetscCall(MatMultTransposeAdd(pcbddc->coarse_psi_D, pcis->vec1_D, pcbddc->vec1_P, pcbddc->vec1_P)); 568615aaf578SStefano Zampini } 56874fee134fSStefano Zampini } else { 56889566063dSJacob Faibussowitsch PetscCall(VecSet(pcbddc->vec1_P, zero)); 56894fee134fSStefano Zampini } 5690efc2fbd9SStefano Zampini 5691efc2fbd9SStefano Zampini /* add p0 to the last value of vec1_P holding the coarse dof relative to p0 */ 56924f1b2e48SStefano Zampini if (pcbddc->benign_n) { 5693efc2fbd9SStefano Zampini PetscScalar *array; 56944f1b2e48SStefano Zampini PetscInt j; 5695efc2fbd9SStefano Zampini 56969566063dSJacob Faibussowitsch PetscCall(VecGetArray(pcbddc->vec1_P, &array)); 56974f1b2e48SStefano Zampini for (j = 0; j < pcbddc->benign_n; j++) array[pcbddc->local_primal_size - pcbddc->benign_n + j] += pcbddc->benign_p0[j]; 56989566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pcbddc->vec1_P, &array)); 5699efc2fbd9SStefano Zampini } 5700efc2fbd9SStefano Zampini 570112edc857SStefano Zampini /* start communications from local primal nodes to rhs of coarse solver */ 57029566063dSJacob Faibussowitsch PetscCall(VecSet(pcbddc->coarse_vec, zero)); 57039566063dSJacob Faibussowitsch PetscCall(PCBDDCScatterCoarseDataBegin(pc, ADD_VALUES, SCATTER_FORWARD)); 57049566063dSJacob Faibussowitsch PetscCall(PCBDDCScatterCoarseDataEnd(pc, ADD_VALUES, SCATTER_FORWARD)); 570512edc857SStefano Zampini 57069f00e9b4SStefano Zampini /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */ 5707a1cb837bSStefano Zampini PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][2], pc, 0, 0, 0)); 570812edc857SStefano Zampini if (pcbddc->coarse_ksp) { 570951694757SStefano Zampini Mat coarse_mat; 5710964fefecSStefano Zampini Vec rhs, sol; 571151694757SStefano Zampini MatNullSpace nullsp; 571227b6a85dSStefano Zampini PetscBool isbddc = PETSC_FALSE; 5713964fefecSStefano Zampini 571427b6a85dSStefano Zampini if (pcbddc->benign_have_null) { 571527b6a85dSStefano Zampini PC coarse_pc; 571627b6a85dSStefano Zampini 57179566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &coarse_pc)); 57189566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)coarse_pc, PCBDDC, &isbddc)); 571927b6a85dSStefano Zampini /* we need to propagate to coarser levels the need for a possible benign correction */ 572027b6a85dSStefano Zampini if (isbddc && pcbddc->benign_apply_coarse_only && !pcbddc->benign_skip_correction) { 5721*f4f49eeaSPierre Jolivet PC_BDDC *coarsepcbddc = (PC_BDDC *)coarse_pc->data; 572227b6a85dSStefano Zampini coarsepcbddc->benign_skip_correction = PETSC_FALSE; 57233bca92a6SStefano Zampini coarsepcbddc->benign_apply_coarse_only = PETSC_TRUE; 572427b6a85dSStefano Zampini } 572527b6a85dSStefano Zampini } 57269566063dSJacob Faibussowitsch PetscCall(KSPGetRhs(pcbddc->coarse_ksp, &rhs)); 57279566063dSJacob Faibussowitsch PetscCall(KSPGetSolution(pcbddc->coarse_ksp, &sol)); 57289566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(pcbddc->coarse_ksp, &coarse_mat, NULL)); 572912edc857SStefano Zampini if (applytranspose) { 573028b400f6SJacob Faibussowitsch PetscCheck(!pcbddc->benign_apply_coarse_only, PetscObjectComm((PetscObject)pcbddc->coarse_ksp), PETSC_ERR_SUP, "Not yet implemented"); 57319566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->coarse_ksp, rhs, sol)); 57329566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->coarse_ksp, pc, sol)); 57339566063dSJacob Faibussowitsch PetscCall(MatGetTransposeNullSpace(coarse_mat, &nullsp)); 57341baa6e33SBarry Smith if (nullsp) PetscCall(MatNullSpaceRemove(nullsp, sol)); 57352701bc32SStefano Zampini } else { 57369566063dSJacob Faibussowitsch PetscCall(MatGetNullSpace(coarse_mat, &nullsp)); 57371f4df5f7SStefano Zampini if (pcbddc->benign_apply_coarse_only && isbddc) { /* need just to apply the coarse preconditioner during presolve */ 57382701bc32SStefano Zampini PC coarse_pc; 57392701bc32SStefano Zampini 57401baa6e33SBarry Smith if (nullsp) PetscCall(MatNullSpaceRemove(nullsp, rhs)); 57419566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &coarse_pc)); 57429566063dSJacob Faibussowitsch PetscCall(PCPreSolve(coarse_pc, pcbddc->coarse_ksp)); 57439566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignRemoveInterior(coarse_pc, rhs, sol)); 57449566063dSJacob Faibussowitsch PetscCall(PCPostSolve(coarse_pc, pcbddc->coarse_ksp)); 574512edc857SStefano Zampini } else { 57469566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->coarse_ksp, rhs, sol)); 57479566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->coarse_ksp, pc, sol)); 57481baa6e33SBarry Smith if (nullsp) PetscCall(MatNullSpaceRemove(nullsp, sol)); 574912edc857SStefano Zampini } 57502701bc32SStefano Zampini } 57511d82a3b6SStefano Zampini /* we don't need the benign correction at coarser levels anymore */ 575227b6a85dSStefano Zampini if (pcbddc->benign_have_null && isbddc) { 575327b6a85dSStefano Zampini PC coarse_pc; 575427b6a85dSStefano Zampini PC_BDDC *coarsepcbddc; 575527b6a85dSStefano Zampini 57569566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &coarse_pc)); 5757*f4f49eeaSPierre Jolivet coarsepcbddc = (PC_BDDC *)coarse_pc->data; 575827b6a85dSStefano Zampini coarsepcbddc->benign_skip_correction = PETSC_TRUE; 57593bca92a6SStefano Zampini coarsepcbddc->benign_apply_coarse_only = PETSC_FALSE; 576027b6a85dSStefano Zampini } 576112edc857SStefano Zampini } 5762a1cb837bSStefano Zampini PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][2], pc, 0, 0, 0)); 5763674ae819SStefano Zampini 5764674ae819SStefano Zampini /* Local solution on R nodes */ 5765a1cb837bSStefano Zampini if (!pcbddc->benign_apply_coarse_only) PetscCall(PCBDDCSolveSubstructureCorrection(pc, pcis->vec1_B, pcis->vec1_D, applytranspose)); 57669f00e9b4SStefano Zampini /* communications from coarse sol to local primal nodes */ 57679566063dSJacob Faibussowitsch PetscCall(PCBDDCScatterCoarseDataBegin(pc, INSERT_VALUES, SCATTER_REVERSE)); 57689566063dSJacob Faibussowitsch PetscCall(PCBDDCScatterCoarseDataEnd(pc, INSERT_VALUES, SCATTER_REVERSE)); 5769674ae819SStefano Zampini 57704fee134fSStefano Zampini /* Sum contributions from the two levels */ 57714fee134fSStefano Zampini if (!pcbddc->benign_apply_coarse_only) { 5772dc359a40SStefano Zampini if (applytranspose) { 57739566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pcbddc->coarse_psi_B, pcbddc->vec1_P, pcis->vec1_B, pcis->vec1_B)); 57749566063dSJacob Faibussowitsch if (pcbddc->switch_static) PetscCall(MatMultAdd(pcbddc->coarse_psi_D, pcbddc->vec1_P, pcis->vec1_D, pcis->vec1_D)); 5775dc359a40SStefano Zampini } else { 57769566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pcbddc->coarse_phi_B, pcbddc->vec1_P, pcis->vec1_B, pcis->vec1_B)); 57779566063dSJacob Faibussowitsch if (pcbddc->switch_static) PetscCall(MatMultAdd(pcbddc->coarse_phi_D, pcbddc->vec1_P, pcis->vec1_D, pcis->vec1_D)); 5778dc359a40SStefano Zampini } 5779efc2fbd9SStefano Zampini /* store p0 */ 57804f1b2e48SStefano Zampini if (pcbddc->benign_n) { 5781efc2fbd9SStefano Zampini PetscScalar *array; 57824f1b2e48SStefano Zampini PetscInt j; 5783efc2fbd9SStefano Zampini 57849566063dSJacob Faibussowitsch PetscCall(VecGetArray(pcbddc->vec1_P, &array)); 57854f1b2e48SStefano Zampini for (j = 0; j < pcbddc->benign_n; j++) pcbddc->benign_p0[j] = array[pcbddc->local_primal_size - pcbddc->benign_n + j]; 57869566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pcbddc->vec1_P, &array)); 5787efc2fbd9SStefano Zampini } 57884fee134fSStefano Zampini } else { /* expand the coarse solution */ 57894fee134fSStefano Zampini if (applytranspose) { 57909566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->coarse_psi_B, pcbddc->vec1_P, pcis->vec1_B)); 57914fee134fSStefano Zampini } else { 57929566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->coarse_phi_B, pcbddc->vec1_P, pcis->vec1_B)); 57934fee134fSStefano Zampini } 57944fee134fSStefano Zampini } 57953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5796674ae819SStefano Zampini } 5797674ae819SStefano Zampini 5798d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc, InsertMode imode, ScatterMode smode) 5799d71ae5a4SJacob Faibussowitsch { 5800*f4f49eeaSPierre Jolivet PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 580112edc857SStefano Zampini Vec from, to; 58027ebab0bbSStefano Zampini const PetscScalar *array; 5803674ae819SStefano Zampini 5804674ae819SStefano Zampini PetscFunctionBegin; 580512edc857SStefano Zampini if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */ 580612edc857SStefano Zampini from = pcbddc->coarse_vec; 580712edc857SStefano Zampini to = pcbddc->vec1_P; 580812edc857SStefano Zampini if (pcbddc->coarse_ksp) { /* get array from coarse processes */ 580912edc857SStefano Zampini Vec tvec; 581058da7f69SStefano Zampini 58119566063dSJacob Faibussowitsch PetscCall(KSPGetRhs(pcbddc->coarse_ksp, &tvec)); 58129566063dSJacob Faibussowitsch PetscCall(VecResetArray(tvec)); 58139566063dSJacob Faibussowitsch PetscCall(KSPGetSolution(pcbddc->coarse_ksp, &tvec)); 58149566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(tvec, &array)); 58159566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(from, array)); 58169566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(tvec, &array)); 581712edc857SStefano Zampini } 581812edc857SStefano Zampini } else { /* from local to global -> put data in coarse right hand side */ 581912edc857SStefano Zampini from = pcbddc->vec1_P; 582012edc857SStefano Zampini to = pcbddc->coarse_vec; 582112edc857SStefano Zampini } 58229566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob, from, to, imode, smode)); 58233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5824674ae819SStefano Zampini } 5825674ae819SStefano Zampini 5826d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode) 5827d71ae5a4SJacob Faibussowitsch { 5828*f4f49eeaSPierre Jolivet PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 582912edc857SStefano Zampini Vec from, to; 58307ebab0bbSStefano Zampini const PetscScalar *array; 5831674ae819SStefano Zampini 5832674ae819SStefano Zampini PetscFunctionBegin; 583312edc857SStefano Zampini if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */ 583412edc857SStefano Zampini from = pcbddc->coarse_vec; 583512edc857SStefano Zampini to = pcbddc->vec1_P; 583612edc857SStefano Zampini } else { /* from local to global -> put data in coarse right hand side */ 583712edc857SStefano Zampini from = pcbddc->vec1_P; 583812edc857SStefano Zampini to = pcbddc->coarse_vec; 583912edc857SStefano Zampini } 58409566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob, from, to, imode, smode)); 584112edc857SStefano Zampini if (smode == SCATTER_FORWARD) { 584212edc857SStefano Zampini if (pcbddc->coarse_ksp) { /* get array from coarse processes */ 584312edc857SStefano Zampini Vec tvec; 584458da7f69SStefano Zampini 58459566063dSJacob Faibussowitsch PetscCall(KSPGetRhs(pcbddc->coarse_ksp, &tvec)); 58469566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(to, &array)); 58479566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(tvec, array)); 58489566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(to, &array)); 584958da7f69SStefano Zampini } 585058da7f69SStefano Zampini } else { 585158da7f69SStefano Zampini if (pcbddc->coarse_ksp) { /* restore array of pcbddc->coarse_vec */ 58529566063dSJacob Faibussowitsch PetscCall(VecResetArray(from)); 585312edc857SStefano Zampini } 585412edc857SStefano Zampini } 58553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5856674ae819SStefano Zampini } 5857674ae819SStefano Zampini 5858d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCConstraintsSetUp(PC pc) 5859d71ae5a4SJacob Faibussowitsch { 5860*f4f49eeaSPierre Jolivet PC_IS *pcis = (PC_IS *)pc->data; 5861674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 5862674ae819SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 5863984c4197SStefano Zampini /* one and zero */ 5864984c4197SStefano Zampini PetscScalar one = 1.0, zero = 0.0; 5865984c4197SStefano Zampini /* space to store constraints and their local indices */ 58669162d606SStefano Zampini PetscScalar *constraints_data; 58679162d606SStefano Zampini PetscInt *constraints_idxs, *constraints_idxs_B; 58689162d606SStefano Zampini PetscInt *constraints_idxs_ptr, *constraints_data_ptr; 58699162d606SStefano Zampini PetscInt *constraints_n; 5870984c4197SStefano Zampini /* iterators */ 5871b3d85658SStefano Zampini PetscInt i, j, k, total_counts, total_counts_cc, cum; 5872984c4197SStefano Zampini /* BLAS integers */ 5873e310c8b4SStefano Zampini PetscBLASInt lwork, lierr; 5874e310c8b4SStefano Zampini PetscBLASInt Blas_N, Blas_M, Blas_K, Blas_one = 1; 5875c4303822SStefano Zampini PetscBLASInt Blas_LDA, Blas_LDB, Blas_LDC; 5876727cdba6SStefano Zampini /* reuse */ 58770e6343abSStefano Zampini PetscInt olocal_primal_size, olocal_primal_size_cc; 58780e6343abSStefano Zampini PetscInt *olocal_primal_ref_node, *olocal_primal_ref_mult; 5879984c4197SStefano Zampini /* change of basis */ 5880b3d85658SStefano Zampini PetscBool qr_needed; 58819162d606SStefano Zampini PetscBT change_basis, qr_needed_idx; 5882984c4197SStefano Zampini /* auxiliary stuff */ 588364efe560SStefano Zampini PetscInt *nnz, *is_indices; 58848a0068c3SStefano Zampini PetscInt ncc; 5885984c4197SStefano Zampini /* some quantities */ 588645a1bb75SStefano Zampini PetscInt n_vertices, total_primal_vertices, valid_constraints; 5887a58a30b4SStefano Zampini PetscInt size_of_constraint, max_size_of_constraint = 0, max_constraints, temp_constraints; 588857715f18SStefano Zampini PetscReal tol; /* tolerance for retaining eigenmodes */ 5889984c4197SStefano Zampini 5890674ae819SStefano Zampini PetscFunctionBegin; 589157715f18SStefano Zampini tol = PetscSqrtReal(PETSC_SMALL); 58928e61c736SStefano Zampini /* Destroy Mat objects computed previously */ 58939566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->ChangeOfBasisMatrix)); 58949566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->ConstraintMatrix)); 58959566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->switch_static_change)); 5896088faed8SStefano Zampini /* save info on constraints from previous setup (if any) */ 5897088faed8SStefano Zampini olocal_primal_size = pcbddc->local_primal_size; 58980e6343abSStefano Zampini olocal_primal_size_cc = pcbddc->local_primal_size_cc; 58999566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(olocal_primal_size_cc, &olocal_primal_ref_node, olocal_primal_size_cc, &olocal_primal_ref_mult)); 59009566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(olocal_primal_ref_node, pcbddc->local_primal_ref_node, olocal_primal_size_cc)); 59019566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(olocal_primal_ref_mult, pcbddc->local_primal_ref_mult, olocal_primal_size_cc)); 59029566063dSJacob Faibussowitsch PetscCall(PetscFree2(pcbddc->local_primal_ref_node, pcbddc->local_primal_ref_mult)); 59039566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->primal_indices_local_idxs)); 5904cf5a6209SStefano Zampini 5905cf5a6209SStefano Zampini if (!pcbddc->adaptive_selection) { 59069162d606SStefano Zampini IS ISForVertices, *ISForFaces, *ISForEdges; 5907cf5a6209SStefano Zampini MatNullSpace nearnullsp; 5908cf5a6209SStefano Zampini const Vec *nearnullvecs; 5909cf5a6209SStefano Zampini Vec *localnearnullsp; 5910cf5a6209SStefano Zampini PetscScalar *array; 591132fe681dSStefano Zampini PetscInt n_ISForFaces, n_ISForEdges, nnsp_size, o_nf, o_ne; 5912cf5a6209SStefano Zampini PetscBool nnsp_has_cnst; 5913674ae819SStefano Zampini /* LAPACK working arrays for SVD or POD */ 5914b3d85658SStefano Zampini PetscBool skip_lapack, boolforchange; 5915674ae819SStefano Zampini PetscScalar *work; 5916674ae819SStefano Zampini PetscReal *singular_vals; 5917674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX) 5918674ae819SStefano Zampini PetscReal *rwork; 5919674ae819SStefano Zampini #endif 592055080a34SStefano Zampini PetscScalar *temp_basis = NULL, *correlation_mat = NULL; 5921964fefecSStefano Zampini PetscBLASInt dummy_int = 1; 5922964fefecSStefano Zampini PetscScalar dummy_scalar = 1.; 592355080a34SStefano Zampini PetscBool use_pod = PETSC_FALSE; 5924674ae819SStefano Zampini 592555080a34SStefano Zampini /* MKL SVD with same input gives different results on different processes! */ 5926b88df2e7SBarry Smith #if defined(PETSC_MISSING_LAPACK_GESVD) || defined(PETSC_HAVE_MKL_LIBS) 592755080a34SStefano Zampini use_pod = PETSC_TRUE; 592855080a34SStefano Zampini #endif 5929674ae819SStefano Zampini /* Get index sets for faces, edges and vertices from graph */ 59309566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, &n_ISForFaces, &ISForFaces, &n_ISForEdges, &ISForEdges, &ISForVertices)); 593132fe681dSStefano Zampini o_nf = n_ISForFaces; 593232fe681dSStefano Zampini o_ne = n_ISForEdges; 593332fe681dSStefano Zampini n_vertices = 0; 593432fe681dSStefano Zampini if (ISForVertices) PetscCall(ISGetSize(ISForVertices, &n_vertices)); 5935e4d548c7SStefano Zampini /* print some info */ 59365c643e28SStefano Zampini if (pcbddc->dbg_flag && (!pcbddc->sub_schurs || pcbddc->sub_schurs_rebuild)) { 593732fe681dSStefano Zampini if (!pcbddc->dbg_viewer) pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc)); 59389566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphASCIIView(pcbddc->mat_graph, pcbddc->dbg_flag, pcbddc->dbg_viewer)); 59399566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 59409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "--------------------------------------------------------------\n")); 594132fe681dSStefano Zampini PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate vertices (%d)\n", PetscGlobalRank, n_vertices, pcbddc->use_vertices)); 594263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate edges (%d)\n", PetscGlobalRank, n_ISForEdges, pcbddc->use_edges)); 594363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate faces (%d)\n", PetscGlobalRank, n_ISForFaces, pcbddc->use_faces)); 59449566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 59459566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer)); 5946e4d548c7SStefano Zampini } 5947e4d548c7SStefano Zampini 594832fe681dSStefano Zampini if (!pcbddc->use_vertices) n_vertices = 0; 594932fe681dSStefano Zampini if (!pcbddc->use_edges) n_ISForEdges = 0; 595032fe681dSStefano Zampini if (!pcbddc->use_faces) n_ISForFaces = 0; 595170022509SStefano Zampini 5952674ae819SStefano Zampini /* check if near null space is attached to global mat */ 59536d9e27e4SStefano Zampini if (pcbddc->use_nnsp) { 59549566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pc->pmat, &nearnullsp)); 59556d9e27e4SStefano Zampini } else nearnullsp = NULL; 59566d9e27e4SStefano Zampini 5957674ae819SStefano Zampini if (nearnullsp) { 59589566063dSJacob Faibussowitsch PetscCall(MatNullSpaceGetVecs(nearnullsp, &nnsp_has_cnst, &nnsp_size, &nearnullvecs)); 5959f4ddd8eeSStefano Zampini /* remove any stored info */ 59609566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&pcbddc->onearnullspace)); 59619566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->onearnullvecs_state)); 5962f4ddd8eeSStefano Zampini /* store information for BDDC solver reuse */ 59639566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)nearnullsp)); 5964f4ddd8eeSStefano Zampini pcbddc->onearnullspace = nearnullsp; 59659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnsp_size, &pcbddc->onearnullvecs_state)); 596648a46eb9SPierre Jolivet for (i = 0; i < nnsp_size; i++) PetscCall(PetscObjectStateGet((PetscObject)nearnullvecs[i], &pcbddc->onearnullvecs_state[i])); 5967984c4197SStefano Zampini } else { /* if near null space is not provided BDDC uses constants by default */ 5968984c4197SStefano Zampini nnsp_size = 0; 5969674ae819SStefano Zampini nnsp_has_cnst = PETSC_TRUE; 5970674ae819SStefano Zampini } 5971984c4197SStefano Zampini /* get max number of constraints on a single cc */ 5972984c4197SStefano Zampini max_constraints = nnsp_size; 5973984c4197SStefano Zampini if (nnsp_has_cnst) max_constraints++; 5974984c4197SStefano Zampini 5975674ae819SStefano Zampini /* 5976674ae819SStefano Zampini Evaluate maximum storage size needed by the procedure 59779162d606SStefano Zampini - Indices for connected component i stored at "constraints_idxs + constraints_idxs_ptr[i]" 59789162d606SStefano Zampini - Values for constraints on connected component i stored at "constraints_data + constraints_data_ptr[i]" 59799162d606SStefano Zampini There can be multiple constraints per connected component 5980674ae819SStefano Zampini */ 59819162d606SStefano Zampini ncc = n_vertices + n_ISForFaces + n_ISForEdges; 59829566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(ncc + 1, &constraints_idxs_ptr, ncc + 1, &constraints_data_ptr, ncc, &constraints_n)); 59839162d606SStefano Zampini 59849162d606SStefano Zampini total_counts = n_ISForFaces + n_ISForEdges; 59859162d606SStefano Zampini total_counts *= max_constraints; 5986674ae819SStefano Zampini total_counts += n_vertices; 59879566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(total_counts, &change_basis)); 59889162d606SStefano Zampini 5989674ae819SStefano Zampini total_counts = 0; 5990674ae819SStefano Zampini max_size_of_constraint = 0; 5991674ae819SStefano Zampini for (i = 0; i < n_ISForEdges + n_ISForFaces; i++) { 59929162d606SStefano Zampini IS used_is; 5993674ae819SStefano Zampini if (i < n_ISForEdges) { 59949162d606SStefano Zampini used_is = ISForEdges[i]; 5995674ae819SStefano Zampini } else { 59969162d606SStefano Zampini used_is = ISForFaces[i - n_ISForEdges]; 5997674ae819SStefano Zampini } 59989566063dSJacob Faibussowitsch PetscCall(ISGetSize(used_is, &j)); 5999674ae819SStefano Zampini total_counts += j; 6000674ae819SStefano Zampini max_size_of_constraint = PetscMax(j, max_size_of_constraint); 6001674ae819SStefano Zampini } 60029566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(total_counts * max_constraints + n_vertices, &constraints_data, total_counts + n_vertices, &constraints_idxs, total_counts + n_vertices, &constraints_idxs_B)); 60039162d606SStefano Zampini 6004984c4197SStefano Zampini /* get local part of global near null space vectors */ 60059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnsp_size, &localnearnullsp)); 6006984c4197SStefano Zampini for (k = 0; k < nnsp_size; k++) { 60079566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_N, &localnearnullsp[k])); 60089566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, nearnullvecs[k], localnearnullsp[k], INSERT_VALUES, SCATTER_FORWARD)); 60099566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, nearnullvecs[k], localnearnullsp[k], INSERT_VALUES, SCATTER_FORWARD)); 6010984c4197SStefano Zampini } 6011674ae819SStefano Zampini 6012242a89d7SStefano Zampini /* whether or not to skip lapack calls */ 6013242a89d7SStefano Zampini skip_lapack = PETSC_TRUE; 6014a773dcb8SStefano Zampini if (n_ISForFaces + n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE; 6015242a89d7SStefano Zampini 6016984c4197SStefano Zampini /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */ 6017a773dcb8SStefano Zampini if (!skip_lapack) { 6018674ae819SStefano Zampini PetscScalar temp_work; 6019911cabfeSStefano Zampini 602055080a34SStefano Zampini if (use_pod) { 6021984c4197SStefano Zampini /* Proper Orthogonal Decomposition (POD) using the snapshot method */ 60229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_constraints * max_constraints, &correlation_mat)); 60239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_constraints, &singular_vals)); 60249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_size_of_constraint * max_constraints, &temp_basis)); 6025674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX) 60269566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(3 * max_constraints, &rwork)); 6027674ae819SStefano Zampini #endif 6028674ae819SStefano Zampini /* now we evaluate the optimal workspace using query with lwork=-1 */ 60299566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_constraints, &Blas_N)); 60309566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_constraints, &Blas_LDA)); 6031674ae819SStefano Zampini lwork = -1; 60329566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6033674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX) 6034792fecdfSBarry Smith PetscCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &Blas_N, correlation_mat, &Blas_LDA, singular_vals, &temp_work, &lwork, &lierr)); 6035674ae819SStefano Zampini #else 6036792fecdfSBarry Smith PetscCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &Blas_N, correlation_mat, &Blas_LDA, singular_vals, &temp_work, &lwork, rwork, &lierr)); 6037674ae819SStefano Zampini #endif 60389566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 603928b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in query to SYEV Lapack routine %d", (int)lierr); 604055080a34SStefano Zampini } else { 604155080a34SStefano Zampini #if !defined(PETSC_MISSING_LAPACK_GESVD) 6042674ae819SStefano Zampini /* SVD */ 6043674ae819SStefano Zampini PetscInt max_n, min_n; 6044674ae819SStefano Zampini max_n = max_size_of_constraint; 6045984c4197SStefano Zampini min_n = max_constraints; 6046984c4197SStefano Zampini if (max_size_of_constraint < max_constraints) { 6047674ae819SStefano Zampini min_n = max_size_of_constraint; 6048984c4197SStefano Zampini max_n = max_constraints; 6049674ae819SStefano Zampini } 60509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(min_n, &singular_vals)); 6051674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX) 60529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(5 * min_n, &rwork)); 6053674ae819SStefano Zampini #endif 6054674ae819SStefano Zampini /* now we evaluate the optimal workspace using query with lwork=-1 */ 6055674ae819SStefano Zampini lwork = -1; 60569566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_n, &Blas_M)); 60579566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(min_n, &Blas_N)); 60589566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_n, &Blas_LDA)); 60599566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6060674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX) 6061792fecdfSBarry 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)); 6062674ae819SStefano Zampini #else 6063792fecdfSBarry 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)); 6064674ae819SStefano Zampini #endif 60659566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 606628b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in query to GESVD Lapack routine %d", (int)lierr); 606755080a34SStefano Zampini #else 606855080a34SStefano Zampini SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "This should not happen"); 6069984c4197SStefano Zampini #endif /* on missing GESVD */ 607055080a34SStefano Zampini } 6071674ae819SStefano Zampini /* Allocate optimal workspace */ 60729566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(temp_work), &lwork)); 60739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(lwork, &work)); 6074674ae819SStefano Zampini } 6075674ae819SStefano Zampini /* Now we can loop on constraining sets */ 6076674ae819SStefano Zampini total_counts = 0; 60779162d606SStefano Zampini constraints_idxs_ptr[0] = 0; 60789162d606SStefano Zampini constraints_data_ptr[0] = 0; 6079674ae819SStefano Zampini /* vertices */ 60809162d606SStefano Zampini if (n_vertices) { 60819566063dSJacob Faibussowitsch PetscCall(ISGetIndices(ISForVertices, (const PetscInt **)&is_indices)); 60829566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(constraints_idxs, is_indices, n_vertices)); 6083674ae819SStefano Zampini for (i = 0; i < n_vertices; i++) { 60849162d606SStefano Zampini constraints_n[total_counts] = 1; 60859162d606SStefano Zampini constraints_data[total_counts] = 1.0; 60869162d606SStefano Zampini constraints_idxs_ptr[total_counts + 1] = constraints_idxs_ptr[total_counts] + 1; 60879162d606SStefano Zampini constraints_data_ptr[total_counts + 1] = constraints_data_ptr[total_counts] + 1; 6088674ae819SStefano Zampini total_counts++; 6089674ae819SStefano Zampini } 60909566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(ISForVertices, (const PetscInt **)&is_indices)); 6091674ae819SStefano Zampini } 6092984c4197SStefano Zampini 6093674ae819SStefano Zampini /* edges and faces */ 60949162d606SStefano Zampini total_counts_cc = total_counts; 6095911cabfeSStefano Zampini for (ncc = 0; ncc < n_ISForEdges + n_ISForFaces; ncc++) { 60969162d606SStefano Zampini IS used_is; 60979162d606SStefano Zampini PetscBool idxs_copied = PETSC_FALSE; 60989162d606SStefano Zampini 6099911cabfeSStefano Zampini if (ncc < n_ISForEdges) { 61009162d606SStefano Zampini used_is = ISForEdges[ncc]; 6101984c4197SStefano Zampini boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */ 6102674ae819SStefano Zampini } else { 61039162d606SStefano Zampini used_is = ISForFaces[ncc - n_ISForEdges]; 6104984c4197SStefano Zampini boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */ 6105674ae819SStefano Zampini } 6106674ae819SStefano Zampini temp_constraints = 0; /* zero the number of constraints I have on this conn comp */ 61079162d606SStefano Zampini 61089566063dSJacob Faibussowitsch PetscCall(ISGetSize(used_is, &size_of_constraint)); 610932fe681dSStefano Zampini if (!size_of_constraint) continue; 61109566063dSJacob Faibussowitsch PetscCall(ISGetIndices(used_is, (const PetscInt **)&is_indices)); 6111984c4197SStefano Zampini /* change of basis should not be performed on local periodic nodes */ 6112984c4197SStefano Zampini if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE; 6113674ae819SStefano Zampini if (nnsp_has_cnst) { 61145b08dc53SStefano Zampini PetscScalar quad_value; 61159162d606SStefano Zampini 61169566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc], is_indices, size_of_constraint)); 61179162d606SStefano Zampini idxs_copied = PETSC_TRUE; 61189162d606SStefano Zampini 6119a773dcb8SStefano Zampini if (!pcbddc->use_nnsp_true) { 6120674ae819SStefano Zampini quad_value = (PetscScalar)(1.0 / PetscSqrtReal((PetscReal)size_of_constraint)); 6121a773dcb8SStefano Zampini } else { 6122a773dcb8SStefano Zampini quad_value = 1.0; 6123a773dcb8SStefano Zampini } 6124ad540459SPierre Jolivet for (j = 0; j < size_of_constraint; j++) constraints_data[constraints_data_ptr[total_counts_cc] + j] = quad_value; 61259162d606SStefano Zampini temp_constraints++; 6126674ae819SStefano Zampini total_counts++; 6127674ae819SStefano Zampini } 6128674ae819SStefano Zampini for (k = 0; k < nnsp_size; k++) { 6129984c4197SStefano Zampini PetscReal real_value; 61309162d606SStefano Zampini PetscScalar *ptr_to_data; 61319162d606SStefano Zampini 61329566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(localnearnullsp[k], (const PetscScalar **)&array)); 61339162d606SStefano Zampini ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc] + temp_constraints * size_of_constraint]; 6134ad540459SPierre Jolivet for (j = 0; j < size_of_constraint; j++) ptr_to_data[j] = array[is_indices[j]]; 61359566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(localnearnullsp[k], (const PetscScalar **)&array)); 6136984c4197SStefano Zampini /* check if array is null on the connected component */ 61379566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 6138792fecdfSBarry Smith PetscCallBLAS("BLASasum", real_value = BLASasum_(&Blas_N, ptr_to_data, &Blas_one)); 613957715f18SStefano Zampini if (real_value > tol * size_of_constraint) { /* keep indices and values */ 6140674ae819SStefano Zampini temp_constraints++; 6141674ae819SStefano Zampini total_counts++; 61429162d606SStefano Zampini if (!idxs_copied) { 61439566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(constraints_idxs + constraints_idxs_ptr[total_counts_cc], is_indices, size_of_constraint)); 61449162d606SStefano Zampini idxs_copied = PETSC_TRUE; 6145674ae819SStefano Zampini } 6146674ae819SStefano Zampini } 61479162d606SStefano Zampini } 61489566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(used_is, (const PetscInt **)&is_indices)); 614945a1bb75SStefano Zampini valid_constraints = temp_constraints; 6150eb97c9d2SStefano Zampini if (!pcbddc->use_nnsp_true && temp_constraints) { 6151a773dcb8SStefano Zampini if (temp_constraints == 1) { /* just normalize the constraint */ 61529162d606SStefano Zampini PetscScalar norm, *ptr_to_data; 61539162d606SStefano Zampini 61549162d606SStefano Zampini ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]]; 61559566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 6156792fecdfSBarry Smith PetscCallBLAS("BLASdot", norm = BLASdot_(&Blas_N, ptr_to_data, &Blas_one, ptr_to_data, &Blas_one)); 6157a773dcb8SStefano Zampini norm = 1.0 / PetscSqrtReal(PetscRealPart(norm)); 6158792fecdfSBarry Smith PetscCallBLAS("BLASscal", BLASscal_(&Blas_N, &norm, ptr_to_data, &Blas_one)); 6159a773dcb8SStefano Zampini } else { /* perform SVD */ 61609162d606SStefano Zampini PetscScalar *ptr_to_data = &constraints_data[constraints_data_ptr[total_counts_cc]]; 6161674ae819SStefano Zampini 616255080a34SStefano Zampini if (use_pod) { 6163984c4197SStefano Zampini /* SVD: Y = U*S*V^H -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag 6164984c4197SStefano Zampini POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2) 6165984c4197SStefano Zampini -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined 6166984c4197SStefano Zampini the constraints basis will differ (by a complex factor with absolute value equal to 1) 6167984c4197SStefano Zampini from that computed using LAPACKgesvd 6168984c4197SStefano Zampini -> This is due to a different computation of eigenvectors in LAPACKheev 6169984c4197SStefano Zampini -> The quality of the POD-computed basis will be the same */ 61709566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(correlation_mat, temp_constraints * temp_constraints)); 6171674ae819SStefano Zampini /* Store upper triangular part of correlation matrix */ 61729566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 61739566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6174674ae819SStefano Zampini for (j = 0; j < temp_constraints; j++) { 617548a46eb9SPierre 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)); 6176674ae819SStefano Zampini } 6177e310c8b4SStefano Zampini /* compute eigenvalues and eigenvectors of correlation matrix */ 61789566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_N)); 61799566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_LDA)); 6180674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX) 6181792fecdfSBarry Smith PetscCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &Blas_N, correlation_mat, &Blas_LDA, singular_vals, work, &lwork, &lierr)); 6182674ae819SStefano Zampini #else 6183792fecdfSBarry Smith PetscCallBLAS("LAPACKsyev", LAPACKsyev_("V", "U", &Blas_N, correlation_mat, &Blas_LDA, singular_vals, work, &lwork, rwork, &lierr)); 6184674ae819SStefano Zampini #endif 61859566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 618628b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in SYEV Lapack routine %d", (int)lierr); 6187984c4197SStefano Zampini /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */ 6188674ae819SStefano Zampini j = 0; 618987b3baaaSStefano Zampini while (j < temp_constraints && singular_vals[j] / singular_vals[temp_constraints - 1] < tol) j++; 6190674ae819SStefano Zampini total_counts = total_counts - j; 619145a1bb75SStefano Zampini valid_constraints = temp_constraints - j; 6192e310c8b4SStefano Zampini /* scale and copy POD basis into used quadrature memory */ 61939566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_M)); 61949566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_N)); 61959566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_K)); 61969566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 61979566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_LDB)); 61989566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDC)); 6199674ae819SStefano Zampini if (j < temp_constraints) { 6200984c4197SStefano Zampini PetscInt ii; 6201984c4197SStefano Zampini for (k = j; k < temp_constraints; k++) singular_vals[k] = 1.0 / PetscSqrtReal(singular_vals[k]); 62029566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6203792fecdfSBarry 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)); 62049566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 6205984c4197SStefano Zampini for (k = 0; k < temp_constraints - j; k++) { 6206ad540459SPierre 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]; 6207674ae819SStefano Zampini } 6208674ae819SStefano Zampini } 620955080a34SStefano Zampini } else { 621055080a34SStefano Zampini #if !defined(PETSC_MISSING_LAPACK_GESVD) 62119566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_M)); 62129566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(temp_constraints, &Blas_N)); 62139566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 62149566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6215674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX) 6216792fecdfSBarry 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)); 6217674ae819SStefano Zampini #else 6218792fecdfSBarry 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)); 6219674ae819SStefano Zampini #endif 622028b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in GESVD Lapack routine %d", (int)lierr); 62219566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 6222984c4197SStefano Zampini /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */ 6223e310c8b4SStefano Zampini k = temp_constraints; 6224e310c8b4SStefano Zampini if (k > size_of_constraint) k = size_of_constraint; 6225674ae819SStefano Zampini j = 0; 622687b3baaaSStefano Zampini while (j < k && singular_vals[k - j - 1] / singular_vals[0] < tol) j++; 622745a1bb75SStefano Zampini valid_constraints = k - j; 6228911cabfeSStefano Zampini total_counts = total_counts - temp_constraints + valid_constraints; 622955080a34SStefano Zampini #else 623055080a34SStefano Zampini SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "This should not happen"); 6231984c4197SStefano Zampini #endif /* on missing GESVD */ 6232674ae819SStefano Zampini } 6233a773dcb8SStefano Zampini } 623455080a34SStefano Zampini } 62359162d606SStefano Zampini /* update pointers information */ 62369162d606SStefano Zampini if (valid_constraints) { 62379162d606SStefano Zampini constraints_n[total_counts_cc] = valid_constraints; 62389162d606SStefano Zampini constraints_idxs_ptr[total_counts_cc + 1] = constraints_idxs_ptr[total_counts_cc] + size_of_constraint; 62399162d606SStefano Zampini constraints_data_ptr[total_counts_cc + 1] = constraints_data_ptr[total_counts_cc] + size_of_constraint * valid_constraints; 62409162d606SStefano Zampini /* set change_of_basis flag */ 62413ba16761SJacob Faibussowitsch if (boolforchange) PetscCall(PetscBTSet(change_basis, total_counts_cc)); 6242b3d85658SStefano Zampini total_counts_cc++; 624345a1bb75SStefano Zampini } 624445a1bb75SStefano Zampini } 6245984c4197SStefano Zampini /* free workspace */ 62468f1c130eSStefano Zampini if (!skip_lapack) { 62479566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 6248984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX) 62499566063dSJacob Faibussowitsch PetscCall(PetscFree(rwork)); 6250984c4197SStefano Zampini #endif 62519566063dSJacob Faibussowitsch PetscCall(PetscFree(singular_vals)); 62529566063dSJacob Faibussowitsch PetscCall(PetscFree(correlation_mat)); 62539566063dSJacob Faibussowitsch PetscCall(PetscFree(temp_basis)); 6254984c4197SStefano Zampini } 625548a46eb9SPierre Jolivet for (k = 0; k < nnsp_size; k++) PetscCall(VecDestroy(&localnearnullsp[k])); 62569566063dSJacob Faibussowitsch PetscCall(PetscFree(localnearnullsp)); 6257cf5a6209SStefano Zampini /* free index sets of faces, edges and vertices */ 625832fe681dSStefano Zampini PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, &o_nf, &ISForFaces, &o_ne, &ISForEdges, &ISForVertices)); 625908122e43SStefano Zampini } else { 626008122e43SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 6261984c4197SStefano Zampini 626208122e43SStefano Zampini total_counts = 0; 626308122e43SStefano Zampini n_vertices = 0; 626448a46eb9SPierre Jolivet if (sub_schurs->is_vertices && pcbddc->use_vertices) PetscCall(ISGetLocalSize(sub_schurs->is_vertices, &n_vertices)); 626508122e43SStefano Zampini max_constraints = 0; 62669162d606SStefano Zampini total_counts_cc = 0; 626708122e43SStefano Zampini for (i = 0; i < sub_schurs->n_subs + n_vertices; i++) { 626808122e43SStefano Zampini total_counts += pcbddc->adaptive_constraints_n[i]; 62699162d606SStefano Zampini if (pcbddc->adaptive_constraints_n[i]) total_counts_cc++; 627008122e43SStefano Zampini max_constraints = PetscMax(max_constraints, pcbddc->adaptive_constraints_n[i]); 627108122e43SStefano Zampini } 62729162d606SStefano Zampini constraints_idxs_ptr = pcbddc->adaptive_constraints_idxs_ptr; 62739162d606SStefano Zampini constraints_data_ptr = pcbddc->adaptive_constraints_data_ptr; 62749162d606SStefano Zampini constraints_idxs = pcbddc->adaptive_constraints_idxs; 62759162d606SStefano Zampini constraints_data = pcbddc->adaptive_constraints_data; 627674d5cdf7SStefano Zampini /* constraints_n differs from pcbddc->adaptive_constraints_n */ 62779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(total_counts_cc, &constraints_n)); 62789162d606SStefano Zampini total_counts_cc = 0; 62799162d606SStefano Zampini for (i = 0; i < sub_schurs->n_subs + n_vertices; i++) { 6280ad540459SPierre Jolivet if (pcbddc->adaptive_constraints_n[i]) constraints_n[total_counts_cc++] = pcbddc->adaptive_constraints_n[i]; 628108122e43SStefano Zampini } 628208122e43SStefano Zampini 62838bec7fa6SStefano Zampini max_size_of_constraint = 0; 62849162d606SStefano 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]); 62859566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(constraints_idxs_ptr[total_counts_cc], &constraints_idxs_B)); 628608122e43SStefano Zampini /* Change of basis */ 62879566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(total_counts_cc, &change_basis)); 628808122e43SStefano Zampini if (pcbddc->use_change_of_basis) { 628908122e43SStefano Zampini for (i = 0; i < sub_schurs->n_subs; i++) { 629048a46eb9SPierre Jolivet if (PetscBTLookup(sub_schurs->is_edge, i) || pcbddc->use_change_on_faces) PetscCall(PetscBTSet(change_basis, i + n_vertices)); 629108122e43SStefano Zampini } 629208122e43SStefano Zampini } 629308122e43SStefano Zampini } 6294984c4197SStefano Zampini pcbddc->local_primal_size = total_counts; 62959566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->local_primal_size + pcbddc->benign_n, &pcbddc->primal_indices_local_idxs)); 629608122e43SStefano Zampini 62979162d606SStefano Zampini /* map constraints_idxs in boundary numbering */ 629832fe681dSStefano Zampini if (pcbddc->use_change_of_basis) { 62999566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(pcis->BtoNmap, IS_GTOLM_DROP, constraints_idxs_ptr[total_counts_cc], constraints_idxs, &i, constraints_idxs_B)); 630063a3b9bcSJacob 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); 630132fe681dSStefano Zampini } 6302674ae819SStefano Zampini 6303674ae819SStefano Zampini /* Create constraint matrix */ 63049566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &pcbddc->ConstraintMatrix)); 63059566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->ConstraintMatrix, MATAIJ)); 63069566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->ConstraintMatrix, pcbddc->local_primal_size, pcis->n, pcbddc->local_primal_size, pcis->n)); 6307984c4197SStefano Zampini 6308984c4197SStefano Zampini /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */ 6309a717540cSStefano Zampini /* determine if a QR strategy is needed for change of basis */ 63105a52fde0SStefano Zampini qr_needed = pcbddc->use_qr_single; 63119566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(total_counts_cc, &qr_needed_idx)); 6312984c4197SStefano Zampini total_primal_vertices = 0; 6313b3d85658SStefano Zampini pcbddc->local_primal_size_cc = 0; 63149162d606SStefano Zampini for (i = 0; i < total_counts_cc; i++) { 63159162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[i + 1] - constraints_idxs_ptr[i]; 631672b8c272SStefano Zampini if (size_of_constraint == 1 && pcbddc->mat_graph->custom_minimal_size) { 63179162d606SStefano Zampini pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i]]; 6318b3d85658SStefano Zampini pcbddc->local_primal_size_cc += 1; 631964efe560SStefano Zampini } else if (PetscBTLookup(change_basis, i)) { 6320ad540459SPierre Jolivet for (k = 0; k < constraints_n[i]; k++) pcbddc->primal_indices_local_idxs[total_primal_vertices++] = constraints_idxs[constraints_idxs_ptr[i] + k]; 6321b3d85658SStefano Zampini pcbddc->local_primal_size_cc += constraints_n[i]; 632291af6908SStefano Zampini if (constraints_n[i] > 1 || pcbddc->use_qr_single) { 63233ba16761SJacob Faibussowitsch PetscCall(PetscBTSet(qr_needed_idx, i)); 6324a717540cSStefano Zampini qr_needed = PETSC_TRUE; 6325a717540cSStefano Zampini } 6326fa434743SStefano Zampini } else { 6327b3d85658SStefano Zampini pcbddc->local_primal_size_cc += 1; 6328fa434743SStefano Zampini } 6329a717540cSStefano Zampini } 6330b371cd4fSStefano Zampini /* note that the local variable n_vertices used below stores the number of pointwise constraints */ 6331b371cd4fSStefano Zampini pcbddc->n_vertices = total_primal_vertices; 6332674ae819SStefano Zampini /* permute indices in order to have a sorted set of vertices */ 63339566063dSJacob Faibussowitsch PetscCall(PetscSortInt(total_primal_vertices, pcbddc->primal_indices_local_idxs)); 63349566063dSJacob 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)); 63359566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(pcbddc->local_primal_ref_node, pcbddc->primal_indices_local_idxs, total_primal_vertices)); 63360e6343abSStefano Zampini for (i = 0; i < total_primal_vertices; i++) pcbddc->local_primal_ref_mult[i] = 1; 6337984c4197SStefano Zampini 6338984c4197SStefano Zampini /* nonzero structure of constraint matrix */ 633974d5cdf7SStefano Zampini /* and get reference dof for local constraints */ 63409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->local_primal_size, &nnz)); 6341984c4197SStefano Zampini for (i = 0; i < total_primal_vertices; i++) nnz[i] = 1; 634274d5cdf7SStefano Zampini 6343984c4197SStefano Zampini j = total_primal_vertices; 634474d5cdf7SStefano Zampini total_counts = total_primal_vertices; 6345b3d85658SStefano Zampini cum = total_primal_vertices; 63469162d606SStefano Zampini for (i = n_vertices; i < total_counts_cc; i++) { 63474641a718SStefano Zampini if (!PetscBTLookup(change_basis, i)) { 6348b3d85658SStefano Zampini pcbddc->local_primal_ref_node[cum] = constraints_idxs[constraints_idxs_ptr[i]]; 6349b3d85658SStefano Zampini pcbddc->local_primal_ref_mult[cum] = constraints_n[i]; 6350b3d85658SStefano Zampini cum++; 63519162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[i + 1] - constraints_idxs_ptr[i]; 635274d5cdf7SStefano Zampini for (k = 0; k < constraints_n[i]; k++) { 635374d5cdf7SStefano Zampini pcbddc->primal_indices_local_idxs[total_counts++] = constraints_idxs[constraints_idxs_ptr[i] + k]; 635474d5cdf7SStefano Zampini nnz[j + k] = size_of_constraint; 635574d5cdf7SStefano Zampini } 63569162d606SStefano Zampini j += constraints_n[i]; 6357674ae819SStefano Zampini } 6358674ae819SStefano Zampini } 63599566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix, 0, nnz)); 63609566063dSJacob Faibussowitsch PetscCall(MatSetOption(pcbddc->ConstraintMatrix, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 63619566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 6362088faed8SStefano Zampini 6363674ae819SStefano Zampini /* set values in constraint matrix */ 636448a46eb9SPierre Jolivet for (i = 0; i < total_primal_vertices; i++) PetscCall(MatSetValue(pcbddc->ConstraintMatrix, i, pcbddc->local_primal_ref_node[i], 1.0, INSERT_VALUES)); 6365984c4197SStefano Zampini total_counts = total_primal_vertices; 63669162d606SStefano Zampini for (i = n_vertices; i < total_counts_cc; i++) { 63674641a718SStefano Zampini if (!PetscBTLookup(change_basis, i)) { 63689162d606SStefano Zampini PetscInt *cols; 63699162d606SStefano Zampini 63709162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[i + 1] - constraints_idxs_ptr[i]; 63719162d606SStefano Zampini cols = constraints_idxs + constraints_idxs_ptr[i]; 63729162d606SStefano Zampini for (k = 0; k < constraints_n[i]; k++) { 63739162d606SStefano Zampini PetscInt row = total_counts + k; 63749162d606SStefano Zampini PetscScalar *vals; 63759162d606SStefano Zampini 63769162d606SStefano Zampini vals = constraints_data + constraints_data_ptr[i] + k * size_of_constraint; 63779566063dSJacob Faibussowitsch PetscCall(MatSetValues(pcbddc->ConstraintMatrix, 1, &row, size_of_constraint, cols, vals, INSERT_VALUES)); 63789162d606SStefano Zampini } 63799162d606SStefano Zampini total_counts += constraints_n[i]; 6380674ae819SStefano Zampini } 6381674ae819SStefano Zampini } 6382674ae819SStefano Zampini /* assembling */ 63839566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(pcbddc->ConstraintMatrix, MAT_FINAL_ASSEMBLY)); 63849566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(pcbddc->ConstraintMatrix, MAT_FINAL_ASSEMBLY)); 63859566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(pcbddc->ConstraintMatrix, (PetscObject)pc, "-pc_bddc_constraint_mat_view")); 6386088faed8SStefano Zampini 6387674ae819SStefano Zampini /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */ 6388674ae819SStefano Zampini if (pcbddc->use_change_of_basis) { 6389026de310SStefano Zampini /* dual and primal dofs on a single cc */ 6390984c4197SStefano Zampini PetscInt dual_dofs, primal_dofs; 6391984c4197SStefano Zampini /* working stuff for GEQRF */ 63925a52fde0SStefano Zampini PetscScalar *qr_basis = NULL, *qr_tau = NULL, *qr_work = NULL, lqr_work_t; 6393984c4197SStefano Zampini PetscBLASInt lqr_work; 6394984c4197SStefano Zampini /* working stuff for UNGQR */ 63953c377650SSatish Balay PetscScalar *gqr_work = NULL, lgqr_work_t = 0.0; 6396984c4197SStefano Zampini PetscBLASInt lgqr_work; 6397984c4197SStefano Zampini /* working stuff for TRTRS */ 63985a52fde0SStefano Zampini PetscScalar *trs_rhs = NULL; 63993f08241aSStefano Zampini PetscBLASInt Blas_NRHS; 6400984c4197SStefano Zampini /* pointers for values insertion into change of basis matrix */ 6401984c4197SStefano Zampini PetscInt *start_rows, *start_cols; 6402984c4197SStefano Zampini PetscScalar *start_vals; 6403984c4197SStefano Zampini /* working stuff for values insertion */ 64044641a718SStefano Zampini PetscBT is_primal; 640564efe560SStefano Zampini PetscInt *aux_primal_numbering_B; 6406906d46d4SStefano Zampini /* matrix sizes */ 6407906d46d4SStefano Zampini PetscInt global_size, local_size; 6408906d46d4SStefano Zampini /* temporary change of basis */ 6409906d46d4SStefano Zampini Mat localChangeOfBasisMatrix; 6410cf5a6209SStefano Zampini /* extra space for debugging */ 64115a52fde0SStefano Zampini PetscScalar *dbg_work = NULL; 6412984c4197SStefano Zampini 64139566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &localChangeOfBasisMatrix)); 64149566063dSJacob Faibussowitsch PetscCall(MatSetType(localChangeOfBasisMatrix, MATAIJ)); 64159566063dSJacob Faibussowitsch PetscCall(MatSetSizes(localChangeOfBasisMatrix, pcis->n, pcis->n, pcis->n, pcis->n)); 6416906d46d4SStefano Zampini /* nonzeros for local mat */ 64179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcis->n, &nnz)); 64181dd7afcfSStefano Zampini if (!pcbddc->benign_change || pcbddc->fake_change) { 6419bbb9e6c6SStefano Zampini for (i = 0; i < pcis->n; i++) nnz[i] = 1; 64201dd7afcfSStefano Zampini } else { 64211dd7afcfSStefano Zampini const PetscInt *ii; 64221dd7afcfSStefano Zampini PetscInt n; 64231dd7afcfSStefano Zampini PetscBool flg_row; 64249566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(pcbddc->benign_change, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, NULL, &flg_row)); 64251dd7afcfSStefano Zampini for (i = 0; i < n; i++) nnz[i] = ii[i + 1] - ii[i]; 64269566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(pcbddc->benign_change, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, NULL, &flg_row)); 64271dd7afcfSStefano Zampini } 64289162d606SStefano Zampini for (i = n_vertices; i < total_counts_cc; i++) { 6429a717540cSStefano Zampini if (PetscBTLookup(change_basis, i)) { 64309162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[i + 1] - constraints_idxs_ptr[i]; 6431a717540cSStefano Zampini if (PetscBTLookup(qr_needed_idx, i)) { 64329162d606SStefano Zampini for (j = 0; j < size_of_constraint; j++) nnz[constraints_idxs[constraints_idxs_ptr[i] + j]] = size_of_constraint; 6433a717540cSStefano Zampini } else { 64349162d606SStefano Zampini nnz[constraints_idxs[constraints_idxs_ptr[i]]] = size_of_constraint; 64359162d606SStefano Zampini for (j = 1; j < size_of_constraint; j++) nnz[constraints_idxs[constraints_idxs_ptr[i] + j]] = 2; 6436a717540cSStefano Zampini } 6437a717540cSStefano Zampini } 6438a717540cSStefano Zampini } 64399566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(localChangeOfBasisMatrix, 0, nnz)); 64409566063dSJacob Faibussowitsch PetscCall(MatSetOption(localChangeOfBasisMatrix, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 64419566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz)); 64421dd7afcfSStefano Zampini /* Set interior change in the matrix */ 64431dd7afcfSStefano Zampini if (!pcbddc->benign_change || pcbddc->fake_change) { 644448a46eb9SPierre Jolivet for (i = 0; i < pcis->n; i++) PetscCall(MatSetValue(localChangeOfBasisMatrix, i, i, 1.0, INSERT_VALUES)); 64451dd7afcfSStefano Zampini } else { 64461dd7afcfSStefano Zampini const PetscInt *ii, *jj; 64471dd7afcfSStefano Zampini PetscScalar *aa; 64481dd7afcfSStefano Zampini PetscInt n; 64491dd7afcfSStefano Zampini PetscBool flg_row; 64509566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(pcbddc->benign_change, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &flg_row)); 64519566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(pcbddc->benign_change, &aa)); 645248a46eb9SPierre 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)); 64539566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(pcbddc->benign_change, &aa)); 64549566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(pcbddc->benign_change, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &flg_row)); 64551dd7afcfSStefano Zampini } 6456a717540cSStefano Zampini 6457a717540cSStefano Zampini if (pcbddc->dbg_flag) { 64589566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "--------------------------------------------------------------\n")); 64599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Checking change of basis computation for subdomain %04d\n", PetscGlobalRank)); 6460a717540cSStefano Zampini } 6461a717540cSStefano Zampini 6462a717540cSStefano Zampini /* Now we loop on the constraints which need a change of basis */ 6463a717540cSStefano Zampini /* 6464a717540cSStefano Zampini Change of basis matrix is evaluated similarly to the FIRST APPROACH in 6465a717540cSStefano Zampini Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1) 6466a717540cSStefano Zampini 64677c625d9fSStefano Zampini Basic blocks of change of basis matrix T computed: 6468a717540cSStefano Zampini 64697c625d9fSStefano 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) 6470a6b551f4SStefano Zampini 6471a6b551f4SStefano Zampini | 1 0 ... 0 s_1/S | 6472a6b551f4SStefano Zampini | 0 1 ... 0 s_2/S | 6473a717540cSStefano Zampini | ... | 6474a6b551f4SStefano Zampini | 0 ... 1 s_{n-1}/S | 6475a6b551f4SStefano Zampini | -s_1/s_n ... -s_{n-1}/s_n s_n/S | 6476a717540cSStefano Zampini 6477a6b551f4SStefano Zampini with S = \sum_{i=1}^n s_i^2 6478a6b551f4SStefano Zampini NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering 6479a6b551f4SStefano Zampini in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering 6480a6b551f4SStefano Zampini 6481a6b551f4SStefano Zampini - QR decomposition of constraints otherwise 6482a717540cSStefano Zampini */ 64835a52fde0SStefano Zampini if (qr_needed && max_size_of_constraint) { 6484984c4197SStefano Zampini /* space to store Q */ 64859566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_size_of_constraint * max_size_of_constraint, &qr_basis)); 64864e64d54eSstefano_zampini /* array to store scaling factors for reflectors */ 64879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_constraints, &qr_tau)); 6488984c4197SStefano Zampini /* first we issue queries for optimal work */ 64899566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_size_of_constraint, &Blas_M)); 64909566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_constraints, &Blas_N)); 64919566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_size_of_constraint, &Blas_LDA)); 6492984c4197SStefano Zampini lqr_work = -1; 6493792fecdfSBarry Smith PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&Blas_M, &Blas_N, qr_basis, &Blas_LDA, qr_tau, &lqr_work_t, &lqr_work, &lierr)); 649428b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in query to GEQRF Lapack routine %d", (int)lierr); 64959566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t), &lqr_work)); 649659b05608SBarry Smith PetscCall(PetscMalloc1(lqr_work, &qr_work)); 6497984c4197SStefano Zampini lgqr_work = -1; 64989566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_size_of_constraint, &Blas_M)); 64999566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_size_of_constraint, &Blas_N)); 65009566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_constraints, &Blas_K)); 65019566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(max_size_of_constraint, &Blas_LDA)); 65023f08241aSStefano Zampini if (Blas_K > Blas_M) Blas_K = Blas_M; /* adjust just for computing optimal work */ 6503792fecdfSBarry Smith PetscCallBLAS("LAPACKorgqr", LAPACKorgqr_(&Blas_M, &Blas_N, &Blas_K, qr_basis, &Blas_LDA, qr_tau, &lgqr_work_t, &lgqr_work, &lierr)); 650428b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in query to ORGQR/UNGQR Lapack routine %d", (int)lierr); 65059566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t), &lgqr_work)); 650659b05608SBarry Smith PetscCall(PetscMalloc1(lgqr_work, &gqr_work)); 6507984c4197SStefano Zampini /* array to store rhs and solution of triangular solver */ 65089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(max_constraints * max_constraints, &trs_rhs)); 6509a717540cSStefano Zampini /* allocating workspace for check */ 651048a46eb9SPierre Jolivet if (pcbddc->dbg_flag) PetscCall(PetscMalloc1(max_size_of_constraint * (max_constraints + max_size_of_constraint), &dbg_work)); 6511a717540cSStefano Zampini } 6512984c4197SStefano Zampini /* array to store whether a node is primal or not */ 65139566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(pcis->n_B, &is_primal)); 65149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(total_primal_vertices, &aux_primal_numbering_B)); 65159566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(pcis->BtoNmap, IS_GTOLM_DROP, total_primal_vertices, pcbddc->local_primal_ref_node, &i, aux_primal_numbering_B)); 651663a3b9bcSJacob 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); 651748a46eb9SPierre Jolivet for (i = 0; i < total_primal_vertices; i++) PetscCall(PetscBTSet(is_primal, aux_primal_numbering_B[i])); 65189566063dSJacob Faibussowitsch PetscCall(PetscFree(aux_primal_numbering_B)); 6519984c4197SStefano Zampini 6520a717540cSStefano Zampini /* loop on constraints and see whether or not they need a change of basis and compute it */ 65219162d606SStefano Zampini for (total_counts = n_vertices; total_counts < total_counts_cc; total_counts++) { 65229162d606SStefano Zampini size_of_constraint = constraints_idxs_ptr[total_counts + 1] - constraints_idxs_ptr[total_counts]; 65234641a718SStefano Zampini if (PetscBTLookup(change_basis, total_counts)) { 6524984c4197SStefano Zampini /* get constraint info */ 65259162d606SStefano Zampini primal_dofs = constraints_n[total_counts]; 6526984c4197SStefano Zampini dual_dofs = size_of_constraint - primal_dofs; 6527984c4197SStefano Zampini 652848a46eb9SPierre 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)); 6529984c4197SStefano Zampini 6530fa434743SStefano Zampini if (PetscBTLookup(qr_needed_idx, total_counts)) { /* QR */ 6531a717540cSStefano Zampini 6532a717540cSStefano Zampini /* copy quadrature constraints for change of basis check */ 653348a46eb9SPierre Jolivet if (pcbddc->dbg_flag) PetscCall(PetscArraycpy(dbg_work, &constraints_data[constraints_data_ptr[total_counts]], size_of_constraint * primal_dofs)); 6534984c4197SStefano Zampini /* copy temporary constraints into larger work vector (in order to store all columns of Q) */ 65359566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(qr_basis, &constraints_data[constraints_data_ptr[total_counts]], size_of_constraint * primal_dofs)); 6536984c4197SStefano Zampini 6537984c4197SStefano Zampini /* compute QR decomposition of constraints */ 65389566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_M)); 65399566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_N)); 65409566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 65419566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6542792fecdfSBarry Smith PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&Blas_M, &Blas_N, qr_basis, &Blas_LDA, qr_tau, qr_work, &lqr_work, &lierr)); 654328b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in GEQRF Lapack routine %d", (int)lierr); 65449566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 6545984c4197SStefano Zampini 6546a5b23f4aSJose E. Roman /* explicitly compute R^-T */ 65479566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(trs_rhs, primal_dofs * primal_dofs)); 6548984c4197SStefano Zampini for (j = 0; j < primal_dofs; j++) trs_rhs[j * (primal_dofs + 1)] = 1.0; 65499566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_N)); 65509566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_NRHS)); 65519566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 65529566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_LDB)); 65539566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6554792fecdfSBarry Smith PetscCallBLAS("LAPACKtrtrs", LAPACKtrtrs_("U", "T", "N", &Blas_N, &Blas_NRHS, qr_basis, &Blas_LDA, trs_rhs, &Blas_LDB, &lierr)); 655528b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in TRTRS Lapack routine %d", (int)lierr); 65569566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 6557984c4197SStefano Zampini 6558a717540cSStefano Zampini /* explicitly compute all columns of Q (Q = [Q1 | Q2]) overwriting QR factorization in qr_basis */ 65599566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_M)); 65609566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 65619566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_K)); 65629566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 65639566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6564792fecdfSBarry Smith PetscCallBLAS("LAPACKorgqr", LAPACKorgqr_(&Blas_M, &Blas_N, &Blas_K, qr_basis, &Blas_LDA, qr_tau, gqr_work, &lgqr_work, &lierr)); 656528b400f6SJacob Faibussowitsch PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ORGQR/UNGQR Lapack routine %d", (int)lierr); 65669566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 6567984c4197SStefano Zampini 6568984c4197SStefano Zampini /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints 6569984c4197SStefano Zampini i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below) 6570984c4197SStefano Zampini where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */ 65719566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_M)); 65729566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_N)); 65739566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_K)); 65749566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 65759566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_LDB)); 65769566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDC)); 65779566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6578792fecdfSBarry 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)); 65799566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 65809566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(qr_basis, &constraints_data[constraints_data_ptr[total_counts]], size_of_constraint * primal_dofs)); 6581984c4197SStefano Zampini 6582984c4197SStefano Zampini /* insert values in change of basis matrix respecting global ordering of new primal dofs */ 65839162d606SStefano Zampini start_rows = &constraints_idxs[constraints_idxs_ptr[total_counts]]; 6584984c4197SStefano Zampini /* insert cols for primal dofs */ 6585984c4197SStefano Zampini for (j = 0; j < primal_dofs; j++) { 6586984c4197SStefano Zampini start_vals = &qr_basis[j * size_of_constraint]; 65879162d606SStefano Zampini start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts] + j]; 65889566063dSJacob Faibussowitsch PetscCall(MatSetValues(localChangeOfBasisMatrix, size_of_constraint, start_rows, 1, start_cols, start_vals, INSERT_VALUES)); 6589984c4197SStefano Zampini } 6590984c4197SStefano Zampini /* insert cols for dual dofs */ 6591984c4197SStefano Zampini for (j = 0, k = 0; j < dual_dofs; k++) { 65929162d606SStefano Zampini if (!PetscBTLookup(is_primal, constraints_idxs_B[constraints_idxs_ptr[total_counts] + k])) { 6593984c4197SStefano Zampini start_vals = &qr_basis[(primal_dofs + j) * size_of_constraint]; 65949162d606SStefano Zampini start_cols = &constraints_idxs[constraints_idxs_ptr[total_counts] + k]; 65959566063dSJacob Faibussowitsch PetscCall(MatSetValues(localChangeOfBasisMatrix, size_of_constraint, start_rows, 1, start_cols, start_vals, INSERT_VALUES)); 6596984c4197SStefano Zampini j++; 6597674ae819SStefano Zampini } 6598674ae819SStefano Zampini } 6599984c4197SStefano Zampini 6600984c4197SStefano Zampini /* check change of basis */ 6601984c4197SStefano Zampini if (pcbddc->dbg_flag) { 6602984c4197SStefano Zampini PetscInt ii, jj; 6603984c4197SStefano Zampini PetscBool valid_qr = PETSC_TRUE; 66049566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_M)); 66059566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 66069566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_K)); 66079566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDA)); 66089566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_LDB)); 66099566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(primal_dofs, &Blas_LDC)); 66109566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 6611792fecdfSBarry 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)); 66129566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 6613984c4197SStefano Zampini for (jj = 0; jj < size_of_constraint; jj++) { 6614984c4197SStefano Zampini for (ii = 0; ii < primal_dofs; ii++) { 6615cf5a6209SStefano Zampini if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint * primal_dofs + jj * primal_dofs + ii]) > 1.e-12) valid_qr = PETSC_FALSE; 6616c068d9bbSLisandro 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; 6617674ae819SStefano Zampini } 6618674ae819SStefano Zampini } 6619984c4197SStefano Zampini if (!valid_qr) { 66209566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "\t-> wrong change of basis!\n")); 6621984c4197SStefano Zampini for (jj = 0; jj < size_of_constraint; jj++) { 6622984c4197SStefano Zampini for (ii = 0; ii < primal_dofs; ii++) { 6623cf5a6209SStefano Zampini if (ii != jj && PetscAbsScalar(dbg_work[size_of_constraint * primal_dofs + jj * primal_dofs + ii]) > 1.e-12) { 662463a3b9bcSJacob 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]))); 6625674ae819SStefano Zampini } 6626c068d9bbSLisandro Dalcin if (ii == jj && PetscAbsScalar(dbg_work[size_of_constraint * primal_dofs + jj * primal_dofs + ii] - (PetscReal)1) > 1.e-12) { 662763a3b9bcSJacob 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]))); 6628984c4197SStefano Zampini } 6629984c4197SStefano Zampini } 6630984c4197SStefano Zampini } 6631674ae819SStefano Zampini } else { 66329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "\t-> right change of basis!\n")); 6633674ae819SStefano Zampini } 6634674ae819SStefano Zampini } 6635a717540cSStefano Zampini } else { /* simple transformation block */ 6636a717540cSStefano Zampini PetscInt row, col; 6637a6b551f4SStefano Zampini PetscScalar val, norm; 6638a6b551f4SStefano Zampini 66399566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(size_of_constraint, &Blas_N)); 6640792fecdfSBarry 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)); 6641a717540cSStefano Zampini for (j = 0; j < size_of_constraint; j++) { 66429162d606SStefano Zampini PetscInt row_B = constraints_idxs_B[constraints_idxs_ptr[total_counts] + j]; 66439162d606SStefano Zampini row = constraints_idxs[constraints_idxs_ptr[total_counts] + j]; 6644bbb9e6c6SStefano Zampini if (!PetscBTLookup(is_primal, row_B)) { 66459162d606SStefano Zampini col = constraints_idxs[constraints_idxs_ptr[total_counts]]; 66469566063dSJacob Faibussowitsch PetscCall(MatSetValue(localChangeOfBasisMatrix, row, row, 1.0, INSERT_VALUES)); 66479566063dSJacob Faibussowitsch PetscCall(MatSetValue(localChangeOfBasisMatrix, row, col, constraints_data[constraints_data_ptr[total_counts] + j] / norm, INSERT_VALUES)); 6648a717540cSStefano Zampini } else { 6649a717540cSStefano Zampini for (k = 0; k < size_of_constraint; k++) { 66509162d606SStefano Zampini col = constraints_idxs[constraints_idxs_ptr[total_counts] + k]; 6651a717540cSStefano Zampini if (row != col) { 66529162d606SStefano Zampini val = -constraints_data[constraints_data_ptr[total_counts] + k] / constraints_data[constraints_data_ptr[total_counts]]; 6653a717540cSStefano Zampini } else { 66549162d606SStefano Zampini val = constraints_data[constraints_data_ptr[total_counts]] / norm; 6655a717540cSStefano Zampini } 66569566063dSJacob Faibussowitsch PetscCall(MatSetValue(localChangeOfBasisMatrix, row, col, val, INSERT_VALUES)); 6657a717540cSStefano Zampini } 6658a717540cSStefano Zampini } 6659a717540cSStefano Zampini } 666048a46eb9SPierre Jolivet if (pcbddc->dbg_flag) PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "\t-> using standard change of basis\n")); 6661a717540cSStefano Zampini } 6662984c4197SStefano Zampini } else { 666348a46eb9SPierre 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)); 6664674ae819SStefano Zampini } 6665674ae819SStefano Zampini } 6666a717540cSStefano Zampini 6667a717540cSStefano Zampini /* free workspace */ 6668a717540cSStefano Zampini if (qr_needed) { 66691baa6e33SBarry Smith if (pcbddc->dbg_flag) PetscCall(PetscFree(dbg_work)); 66709566063dSJacob Faibussowitsch PetscCall(PetscFree(trs_rhs)); 66719566063dSJacob Faibussowitsch PetscCall(PetscFree(qr_tau)); 66729566063dSJacob Faibussowitsch PetscCall(PetscFree(qr_work)); 66739566063dSJacob Faibussowitsch PetscCall(PetscFree(gqr_work)); 66749566063dSJacob Faibussowitsch PetscCall(PetscFree(qr_basis)); 6675674ae819SStefano Zampini } 66769566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&is_primal)); 66779566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(localChangeOfBasisMatrix, MAT_FINAL_ASSEMBLY)); 66789566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(localChangeOfBasisMatrix, MAT_FINAL_ASSEMBLY)); 6679906d46d4SStefano Zampini 6680906d46d4SStefano Zampini /* assembling of global change of variable */ 668188c03ad3SStefano Zampini if (!pcbddc->fake_change) { 6682bbb9e6c6SStefano Zampini Mat tmat; 668316f15bc4SStefano Zampini PetscInt bs; 668416f15bc4SStefano Zampini 66859566063dSJacob Faibussowitsch PetscCall(VecGetSize(pcis->vec1_global, &global_size)); 66869566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(pcis->vec1_global, &local_size)); 66879566063dSJacob Faibussowitsch PetscCall(MatDuplicate(pc->pmat, MAT_DO_NOT_COPY_VALUES, &tmat)); 66889566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(tmat, localChangeOfBasisMatrix)); 66899566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(tmat, MAT_FINAL_ASSEMBLY)); 66909566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(tmat, MAT_FINAL_ASSEMBLY)); 66919566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)pc), &pcbddc->ChangeOfBasisMatrix)); 66929566063dSJacob Faibussowitsch PetscCall(MatSetType(pcbddc->ChangeOfBasisMatrix, MATAIJ)); 66939566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(pc->pmat, &bs)); 66949566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(pcbddc->ChangeOfBasisMatrix, bs)); 66959566063dSJacob Faibussowitsch PetscCall(MatSetSizes(pcbddc->ChangeOfBasisMatrix, local_size, local_size, global_size, global_size)); 66969566063dSJacob Faibussowitsch PetscCall(MatISSetMPIXAIJPreallocation_Private(tmat, pcbddc->ChangeOfBasisMatrix, PETSC_TRUE)); 66979566063dSJacob Faibussowitsch PetscCall(MatConvert(tmat, MATAIJ, MAT_REUSE_MATRIX, &pcbddc->ChangeOfBasisMatrix)); 66989566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tmat)); 66999566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_global, 0.0)); 67009566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_N, 1.0)); 67019566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_N, pcis->vec1_global, ADD_VALUES, SCATTER_REVERSE)); 67029566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_N, pcis->vec1_global, ADD_VALUES, SCATTER_REVERSE)); 67039566063dSJacob Faibussowitsch PetscCall(VecReciprocal(pcis->vec1_global)); 67049566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(pcbddc->ChangeOfBasisMatrix, pcis->vec1_global, NULL)); 670588c03ad3SStefano Zampini 6706906d46d4SStefano Zampini /* check */ 6707906d46d4SStefano Zampini if (pcbddc->dbg_flag) { 6708906d46d4SStefano Zampini PetscReal error; 6709906d46d4SStefano Zampini Vec x, x_change; 6710906d46d4SStefano Zampini 67119566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_global, &x)); 67129566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_global, &x_change)); 67139566063dSJacob Faibussowitsch PetscCall(VecSetRandom(x, NULL)); 67149566063dSJacob Faibussowitsch PetscCall(VecCopy(x, pcis->vec1_global)); 67159566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, x, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD)); 67169566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, x, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD)); 67179566063dSJacob Faibussowitsch PetscCall(MatMult(localChangeOfBasisMatrix, pcis->vec1_N, pcis->vec2_N)); 67189566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, pcis->vec2_N, x, INSERT_VALUES, SCATTER_REVERSE)); 67199566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, pcis->vec2_N, x, INSERT_VALUES, SCATTER_REVERSE)); 67209566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcis->vec1_global, x_change)); 67219566063dSJacob Faibussowitsch PetscCall(VecAXPY(x, -1.0, x_change)); 67229566063dSJacob Faibussowitsch PetscCall(VecNorm(x, NORM_INFINITY, &error)); 6723049d1499SBarry Smith PetscCheck(error <= PETSC_SMALL, PetscObjectComm((PetscObject)pc), PETSC_ERR_PLIB, "Error global vs local change on N: %1.6e", (double)error); 67249566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 67259566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x_change)); 6726906d46d4SStefano Zampini } 6727b96c3477SStefano Zampini /* adapt sub_schurs computed (if any) */ 6728b96c3477SStefano Zampini if (pcbddc->use_deluxe_scaling) { 6729b96c3477SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 6730bf3a8328SStefano Zampini 673108401ef6SPierre 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"); 6732b334f244SStefano Zampini if (sub_schurs && sub_schurs->S_Ej_all) { 6733ac632422SStefano Zampini Mat S_new, tmat; 6734bf3a8328SStefano Zampini IS is_all_N, is_V_Sall = NULL; 6735bbb9e6c6SStefano Zampini 67369566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(pcis->BtoNmap, sub_schurs->is_Ej_all, &is_all_N)); 67379566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(localChangeOfBasisMatrix, is_all_N, is_all_N, MAT_INITIAL_MATRIX, &tmat)); 6738bf3a8328SStefano Zampini if (pcbddc->deluxe_zerorows) { 6739bf3a8328SStefano Zampini ISLocalToGlobalMapping NtoSall; 6740bf3a8328SStefano Zampini IS is_V; 67419566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, pcbddc->n_vertices, pcbddc->local_primal_ref_node, PETSC_COPY_VALUES, &is_V)); 67429566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is_all_N, &NtoSall)); 67439566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyIS(NtoSall, IS_GTOLM_DROP, is_V, &is_V_Sall)); 67449566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&NtoSall)); 67459566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_V)); 6746bf3a8328SStefano Zampini } 67479566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_all_N)); 67489566063dSJacob Faibussowitsch PetscCall(MatPtAP(sub_schurs->S_Ej_all, tmat, MAT_INITIAL_MATRIX, 1.0, &S_new)); 67499566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sub_schurs->S_Ej_all)); 67509566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)S_new)); 6751bf3a8328SStefano Zampini if (pcbddc->deluxe_zerorows) { 6752bf3a8328SStefano Zampini const PetscScalar *array; 6753bf3a8328SStefano Zampini const PetscInt *idxs_V, *idxs_all; 6754bf3a8328SStefano Zampini PetscInt i, n_V; 6755bf3a8328SStefano Zampini 67569566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumnsIS(S_new, is_V_Sall, 1., NULL, NULL)); 67579566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is_V_Sall, &n_V)); 67589566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is_V_Sall, &idxs_V)); 67599566063dSJacob Faibussowitsch PetscCall(ISGetIndices(sub_schurs->is_Ej_all, &idxs_all)); 67609566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(pcis->D, &array)); 6761b087196eSStefano Zampini for (i = 0; i < n_V; i++) { 6762b087196eSStefano Zampini PetscScalar val; 6763b087196eSStefano Zampini PetscInt idx; 6764b087196eSStefano Zampini 6765b087196eSStefano Zampini idx = idxs_V[i]; 6766b087196eSStefano Zampini val = array[idxs_all[idxs_V[i]]]; 67679566063dSJacob Faibussowitsch PetscCall(MatSetValue(S_new, idx, idx, val, INSERT_VALUES)); 6768b087196eSStefano Zampini } 67699566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(S_new, MAT_FINAL_ASSEMBLY)); 67709566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(S_new, MAT_FINAL_ASSEMBLY)); 67719566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(pcis->D, &array)); 67729566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(sub_schurs->is_Ej_all, &idxs_all)); 67739566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is_V_Sall, &idxs_V)); 6774bf3a8328SStefano Zampini } 6775ac632422SStefano Zampini sub_schurs->S_Ej_all = S_new; 67769566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_new)); 6777ac632422SStefano Zampini if (sub_schurs->sum_S_Ej_all) { 67789566063dSJacob Faibussowitsch PetscCall(MatPtAP(sub_schurs->sum_S_Ej_all, tmat, MAT_INITIAL_MATRIX, 1.0, &S_new)); 67799566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sub_schurs->sum_S_Ej_all)); 67809566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)S_new)); 67811baa6e33SBarry Smith if (pcbddc->deluxe_zerorows) PetscCall(MatZeroRowsColumnsIS(S_new, is_V_Sall, 1., NULL, NULL)); 6782ac632422SStefano Zampini sub_schurs->sum_S_Ej_all = S_new; 67839566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_new)); 6784ac632422SStefano Zampini } 67859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_V_Sall)); 67869566063dSJacob Faibussowitsch PetscCall(MatDestroy(&tmat)); 6787b96c3477SStefano Zampini } 6788c9db6a07SStefano Zampini /* destroy any change of basis context in sub_schurs */ 6789b334f244SStefano Zampini if (sub_schurs && sub_schurs->change) { 6790c9db6a07SStefano Zampini PetscInt i; 6791c9db6a07SStefano Zampini 679248a46eb9SPierre Jolivet for (i = 0; i < sub_schurs->n_subs; i++) PetscCall(KSPDestroy(&sub_schurs->change[i])); 67939566063dSJacob Faibussowitsch PetscCall(PetscFree(sub_schurs->change)); 6794c9db6a07SStefano Zampini } 6795b96c3477SStefano Zampini } 679616909a7fSStefano Zampini if (pcbddc->switch_static) { /* need to save the local change */ 679716909a7fSStefano Zampini pcbddc->switch_static_change = localChangeOfBasisMatrix; 679816909a7fSStefano Zampini } else { 67999566063dSJacob Faibussowitsch PetscCall(MatDestroy(&localChangeOfBasisMatrix)); 680016909a7fSStefano Zampini } 68011dd7afcfSStefano Zampini /* determine if any process has changed the pressures locally */ 680227b6a85dSStefano Zampini pcbddc->change_interior = pcbddc->benign_have_null; 680372b8c272SStefano Zampini } else { /* fake change (get back change of basis into ConstraintMatrix and info on qr) */ 68049566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->ConstraintMatrix)); 680572b8c272SStefano Zampini pcbddc->ConstraintMatrix = localChangeOfBasisMatrix; 680672b8c272SStefano Zampini pcbddc->use_qr_single = qr_needed; 680772b8c272SStefano Zampini } 68081dd7afcfSStefano Zampini } else if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->benign_saddle_point) { 680927b6a85dSStefano Zampini if (!pcbddc->benign_have_null && pcbddc->user_ChangeOfBasisMatrix) { 68109566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix)); 6811b9b85e73SStefano Zampini pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix; 6812906d46d4SStefano Zampini } else { 68131dd7afcfSStefano Zampini Mat benign_global = NULL; 681427b6a85dSStefano Zampini if (pcbddc->benign_have_null) { 68151dd7afcfSStefano Zampini Mat M; 68161dd7afcfSStefano Zampini 68179e9b7b1fSStefano Zampini pcbddc->change_interior = PETSC_TRUE; 68189566063dSJacob Faibussowitsch PetscCall(VecCopy(matis->counter, pcis->vec1_N)); 68199566063dSJacob Faibussowitsch PetscCall(VecReciprocal(pcis->vec1_N)); 68209566063dSJacob Faibussowitsch PetscCall(MatDuplicate(pc->pmat, MAT_DO_NOT_COPY_VALUES, &benign_global)); 68219e9b7b1fSStefano Zampini if (pcbddc->benign_change) { 68229566063dSJacob Faibussowitsch PetscCall(MatDuplicate(pcbddc->benign_change, MAT_COPY_VALUES, &M)); 68239566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(M, pcis->vec1_N, NULL)); 6824906d46d4SStefano Zampini } else { 68259566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, pcis->n, pcis->n, 1, NULL, &M)); 68269566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(M, pcis->vec1_N, INSERT_VALUES)); 6827906d46d4SStefano Zampini } 68289566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(benign_global, M)); 68299566063dSJacob Faibussowitsch PetscCall(MatDestroy(&M)); 68309566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(benign_global, MAT_FINAL_ASSEMBLY)); 68319566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(benign_global, MAT_FINAL_ASSEMBLY)); 68321dd7afcfSStefano Zampini } 68331dd7afcfSStefano Zampini if (pcbddc->user_ChangeOfBasisMatrix) { 68349566063dSJacob Faibussowitsch PetscCall(MatMatMult(pcbddc->user_ChangeOfBasisMatrix, benign_global, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &pcbddc->ChangeOfBasisMatrix)); 68359566063dSJacob Faibussowitsch PetscCall(MatDestroy(&benign_global)); 683627b6a85dSStefano Zampini } else if (pcbddc->benign_have_null) { 68371dd7afcfSStefano Zampini pcbddc->ChangeOfBasisMatrix = benign_global; 68381dd7afcfSStefano Zampini } 68391dd7afcfSStefano Zampini } 684016909a7fSStefano Zampini if (pcbddc->switch_static && pcbddc->ChangeOfBasisMatrix) { /* need to save the local change */ 684116909a7fSStefano Zampini IS is_global; 684216909a7fSStefano Zampini const PetscInt *gidxs; 684316909a7fSStefano Zampini 68449566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->rmapping, &gidxs)); 68459566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), pcis->n, gidxs, PETSC_COPY_VALUES, &is_global)); 68469566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->rmapping, &gidxs)); 68479566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrixUnsorted(pcbddc->ChangeOfBasisMatrix, is_global, is_global, &pcbddc->switch_static_change)); 68489566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_global)); 684916909a7fSStefano Zampini } 68501dd7afcfSStefano Zampini } 685148a46eb9SPierre Jolivet if (!pcbddc->fake_change && pcbddc->ChangeOfBasisMatrix && !pcbddc->work_change) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->work_change)); 6852a717540cSStefano Zampini 685372b8c272SStefano Zampini if (!pcbddc->fake_change) { 68544f1b2e48SStefano Zampini /* add pressure dofs to set of primal nodes for numbering purposes */ 68554f1b2e48SStefano Zampini for (i = 0; i < pcbddc->benign_n; i++) { 68564f1b2e48SStefano Zampini pcbddc->local_primal_ref_node[pcbddc->local_primal_size_cc] = pcbddc->benign_p0_lidx[i]; 68574f1b2e48SStefano Zampini pcbddc->primal_indices_local_idxs[pcbddc->local_primal_size] = pcbddc->benign_p0_lidx[i]; 6858019a44ceSStefano Zampini pcbddc->local_primal_ref_mult[pcbddc->local_primal_size_cc] = 1; 6859019a44ceSStefano Zampini pcbddc->local_primal_size_cc++; 6860019a44ceSStefano Zampini pcbddc->local_primal_size++; 6861019a44ceSStefano Zampini } 6862019a44ceSStefano Zampini 6863019a44ceSStefano Zampini /* check if a new primal space has been introduced (also take into account benign trick) */ 6864727cdba6SStefano Zampini pcbddc->new_primal_space_local = PETSC_TRUE; 6865727cdba6SStefano Zampini if (olocal_primal_size == pcbddc->local_primal_size) { 68669566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(pcbddc->local_primal_ref_node, olocal_primal_ref_node, olocal_primal_size_cc, &pcbddc->new_primal_space_local)); 6867c1c8e736SStefano Zampini pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local); 68680e6343abSStefano Zampini if (!pcbddc->new_primal_space_local) { 68699566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(pcbddc->local_primal_ref_mult, olocal_primal_ref_mult, olocal_primal_size_cc, &pcbddc->new_primal_space_local)); 6870727cdba6SStefano Zampini pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local); 6871727cdba6SStefano Zampini } 68720e6343abSStefano Zampini } 6873727cdba6SStefano Zampini /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */ 68741c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&pcbddc->new_primal_space_local, &pcbddc->new_primal_space, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 687572b8c272SStefano Zampini } 68769566063dSJacob Faibussowitsch PetscCall(PetscFree2(olocal_primal_ref_node, olocal_primal_ref_mult)); 6877727cdba6SStefano Zampini 6878a717540cSStefano Zampini /* flush dbg viewer */ 68791baa6e33SBarry Smith if (pcbddc->dbg_flag) PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 6880a717540cSStefano Zampini 6881e310c8b4SStefano Zampini /* free workspace */ 68829566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&qr_needed_idx)); 68839566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&change_basis)); 688408122e43SStefano Zampini if (!pcbddc->adaptive_selection) { 68859566063dSJacob Faibussowitsch PetscCall(PetscFree3(constraints_idxs_ptr, constraints_data_ptr, constraints_n)); 68869566063dSJacob Faibussowitsch PetscCall(PetscFree3(constraints_data, constraints_idxs, constraints_idxs_B)); 688708122e43SStefano Zampini } else { 6888d0609cedSBarry 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)); 68899566063dSJacob Faibussowitsch PetscCall(PetscFree(constraints_n)); 68909566063dSJacob Faibussowitsch PetscCall(PetscFree(constraints_idxs_B)); 689108122e43SStefano Zampini } 68923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6893674ae819SStefano Zampini } 6894674ae819SStefano Zampini 6895d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCAnalyzeInterface(PC pc) 6896d71ae5a4SJacob Faibussowitsch { 689771582508SStefano Zampini ISLocalToGlobalMapping map; 6898674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 6899674ae819SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 690066da6bd7Sstefano_zampini PetscInt i, N; 690166da6bd7Sstefano_zampini PetscBool rcsr = PETSC_FALSE; 6902674ae819SStefano Zampini 6903674ae819SStefano Zampini PetscFunctionBegin; 69048af8fcf9SStefano Zampini if (pcbddc->recompute_topography) { 6905b03ebc13SStefano Zampini pcbddc->graphanalyzed = PETSC_FALSE; 69068e61c736SStefano Zampini /* Reset previously computed graph */ 69079566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphReset(pcbddc->mat_graph)); 6908674ae819SStefano Zampini /* Init local Graph struct */ 69099566063dSJacob Faibussowitsch PetscCall(MatGetSize(pc->pmat, &N, NULL)); 69109566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(pc->pmat, &map, NULL)); 69119566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphInit(pcbddc->mat_graph, map, N, pcbddc->graphmaxcount)); 6912674ae819SStefano Zampini 691348a46eb9SPierre Jolivet if (pcbddc->user_primal_vertices_local && !pcbddc->user_primal_vertices) PetscCall(PCBDDCConsistencyCheckIS(pc, MPI_LOR, &pcbddc->user_primal_vertices_local)); 6914575ad6abSStefano Zampini /* Check validity of the csr graph passed in by the user */ 69159371c9d4SSatish 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, 69169371c9d4SSatish Balay pcbddc->mat_graph->nvtxs); 69179577ea80SStefano Zampini 6918674ae819SStefano Zampini /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */ 691966da6bd7Sstefano_zampini if (!pcbddc->mat_graph->xadj && pcbddc->use_local_adj) { 69204d379d7bSStefano Zampini PetscInt *xadj, *adjncy; 69214d379d7bSStefano Zampini PetscInt nvtxs; 6922e496cd5dSStefano Zampini PetscBool flg_row = PETSC_FALSE; 6923674ae819SStefano Zampini 69249566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(matis->A, 0, PETSC_TRUE, PETSC_FALSE, &nvtxs, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &flg_row)); 69252fffb893SStefano Zampini if (flg_row) { 69269566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLocalAdjacencyGraph(pc, nvtxs, xadj, adjncy, PETSC_COPY_VALUES)); 6927b96c3477SStefano Zampini pcbddc->computed_rowadj = PETSC_TRUE; 69282fffb893SStefano Zampini } 69299566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(matis->A, 0, PETSC_TRUE, PETSC_FALSE, &nvtxs, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &flg_row)); 693066da6bd7Sstefano_zampini rcsr = PETSC_TRUE; 6931674ae819SStefano Zampini } 69321baa6e33SBarry Smith if (pcbddc->dbg_flag) PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 6933674ae819SStefano Zampini 6934ab8c8b98SStefano Zampini if (pcbddc->mat_graph->cdim && !pcbddc->mat_graph->cloc) { 6935ab8c8b98SStefano Zampini PetscReal *lcoords; 6936ab8c8b98SStefano Zampini PetscInt n; 6937ab8c8b98SStefano Zampini MPI_Datatype dimrealtype; 6938ab8c8b98SStefano Zampini 69394f819b78SStefano Zampini /* TODO: support for blocked */ 694063a3b9bcSJacob 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); 69419566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(matis->A, &n, NULL)); 69429566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->mat_graph->cdim * n, &lcoords)); 69439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(pcbddc->mat_graph->cdim, MPIU_REAL, &dimrealtype)); 69449566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&dimrealtype)); 69459566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, dimrealtype, pcbddc->mat_graph->coords, lcoords, MPI_REPLACE)); 69469566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, dimrealtype, pcbddc->mat_graph->coords, lcoords, MPI_REPLACE)); 69479566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&dimrealtype)); 69489566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->mat_graph->coords)); 6949ab8c8b98SStefano Zampini 6950ab8c8b98SStefano Zampini pcbddc->mat_graph->coords = lcoords; 6951ab8c8b98SStefano Zampini pcbddc->mat_graph->cloc = PETSC_TRUE; 6952ab8c8b98SStefano Zampini pcbddc->mat_graph->cnloc = n; 6953ab8c8b98SStefano Zampini } 69549371c9d4SSatish 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, 69559371c9d4SSatish Balay pcbddc->mat_graph->nvtxs); 6956625961bdSStefano Zampini pcbddc->mat_graph->active_coords = (PetscBool)(pcbddc->corner_selection && pcbddc->mat_graph->cdim && !pcbddc->corner_selected); 6957ab8c8b98SStefano Zampini 6958674ae819SStefano Zampini /* Setup of Graph */ 69594b2aedd3SStefano Zampini pcbddc->mat_graph->commsizelimit = 0; /* don't use the COMM_SELF variant of the graph */ 69609566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphSetUp(pcbddc->mat_graph, pcbddc->vertex_size, pcbddc->NeumannBoundariesLocal, pcbddc->DirichletBoundariesLocal, pcbddc->n_ISForDofsLocal, pcbddc->ISForDofsLocal, pcbddc->user_primal_vertices_local)); 6961674ae819SStefano Zampini 69624f1b2e48SStefano Zampini /* attach info on disconnected subdomains if present */ 69634f1b2e48SStefano Zampini if (pcbddc->n_local_subs) { 696420c3699dSStefano Zampini PetscInt *local_subs, n, totn; 69654f1b2e48SStefano Zampini 69669566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(matis->A, &n, NULL)); 69679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &local_subs)); 696820c3699dSStefano Zampini for (i = 0; i < n; i++) local_subs[i] = pcbddc->n_local_subs; 69694f1b2e48SStefano Zampini for (i = 0; i < pcbddc->n_local_subs; i++) { 69704f1b2e48SStefano Zampini const PetscInt *idxs; 69714f1b2e48SStefano Zampini PetscInt nl, j; 69724f1b2e48SStefano Zampini 69739566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->local_subs[i], &nl)); 69749566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->local_subs[i], &idxs)); 697571582508SStefano Zampini for (j = 0; j < nl; j++) local_subs[idxs[j]] = i; 69769566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->local_subs[i], &idxs)); 69774f1b2e48SStefano Zampini } 697820c3699dSStefano Zampini for (i = 0, totn = 0; i < n; i++) totn = PetscMax(totn, local_subs[i]); 697920c3699dSStefano Zampini pcbddc->mat_graph->n_local_subs = totn + 1; 69804f1b2e48SStefano Zampini pcbddc->mat_graph->local_subs = local_subs; 69814f1b2e48SStefano Zampini } 69828af8fcf9SStefano Zampini } 69834f1b2e48SStefano Zampini 6984cac5312eSStefano Zampini if (!pcbddc->graphanalyzed) { 6985674ae819SStefano Zampini /* Graph's connected components analysis */ 69869566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph)); 698771582508SStefano Zampini pcbddc->graphanalyzed = PETSC_TRUE; 69884f819b78SStefano Zampini pcbddc->corner_selected = pcbddc->corner_selection; 69898af8fcf9SStefano Zampini } 699066da6bd7Sstefano_zampini if (rcsr) pcbddc->mat_graph->nvtxs_csr = 0; 69913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6992674ae819SStefano Zampini } 6993674ae819SStefano Zampini 6994d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt *nio, Vec vecs[]) 6995d71ae5a4SJacob Faibussowitsch { 6996295df10fSStefano Zampini PetscInt i, j, n; 69979a7d3425SStefano Zampini PetscScalar *alphas; 6998295df10fSStefano Zampini PetscReal norm, *onorms; 69999a7d3425SStefano Zampini 70009a7d3425SStefano Zampini PetscFunctionBegin; 7001295df10fSStefano Zampini n = *nio; 70023ba16761SJacob Faibussowitsch if (!n) PetscFunctionReturn(PETSC_SUCCESS); 70039566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n, &alphas, n, &onorms)); 70049566063dSJacob Faibussowitsch PetscCall(VecNormalize(vecs[0], &norm)); 700592cccca0SStefano Zampini if (norm < PETSC_SMALL) { 7006295df10fSStefano Zampini onorms[0] = 0.0; 70079566063dSJacob Faibussowitsch PetscCall(VecSet(vecs[0], 0.0)); 7008295df10fSStefano Zampini } else { 7009295df10fSStefano Zampini onorms[0] = norm; 701092cccca0SStefano Zampini } 7011295df10fSStefano Zampini 70128c0031efSStefano Zampini for (i = 1; i < n; i++) { 70139566063dSJacob Faibussowitsch PetscCall(VecMDot(vecs[i], i, vecs, alphas)); 70148c0031efSStefano Zampini for (j = 0; j < i; j++) alphas[j] = PetscConj(-alphas[j]); 70159566063dSJacob Faibussowitsch PetscCall(VecMAXPY(vecs[i], i, alphas, vecs)); 70169566063dSJacob Faibussowitsch PetscCall(VecNormalize(vecs[i], &norm)); 701792cccca0SStefano Zampini if (norm < PETSC_SMALL) { 7018295df10fSStefano Zampini onorms[i] = 0.0; 70199566063dSJacob Faibussowitsch PetscCall(VecSet(vecs[i], 0.0)); 7020295df10fSStefano Zampini } else { 7021295df10fSStefano Zampini onorms[i] = norm; 702292cccca0SStefano Zampini } 70239a7d3425SStefano Zampini } 7024295df10fSStefano Zampini /* push nonzero vectors at the beginning */ 7025295df10fSStefano Zampini for (i = 0; i < n; i++) { 7026295df10fSStefano Zampini if (onorms[i] == 0.0) { 7027295df10fSStefano Zampini for (j = i + 1; j < n; j++) { 7028295df10fSStefano Zampini if (onorms[j] != 0.0) { 70299566063dSJacob Faibussowitsch PetscCall(VecCopy(vecs[j], vecs[i])); 7030295df10fSStefano Zampini onorms[j] = 0.0; 7031295df10fSStefano Zampini } 7032295df10fSStefano Zampini } 7033295df10fSStefano Zampini } 7034295df10fSStefano Zampini } 7035295df10fSStefano Zampini for (i = 0, *nio = 0; i < n; i++) *nio += onorms[i] != 0.0 ? 1 : 0; 70369566063dSJacob Faibussowitsch PetscCall(PetscFree2(alphas, onorms)); 70373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 70389a7d3425SStefano Zampini } 70399a7d3425SStefano Zampini 7040ba38deedSJacob Faibussowitsch static PetscErrorCode PCBDDCMatISGetSubassemblingPattern(Mat mat, PetscInt *n_subdomains, PetscInt redprocs, IS *is_sends, PetscBool *have_void) 7041d71ae5a4SJacob Faibussowitsch { 7042e432b41dSStefano Zampini ISLocalToGlobalMapping mapping; 704357de7509SStefano Zampini Mat A; 7044e7931f94SStefano Zampini PetscInt n_neighs, *neighs, *n_shared, **shared; 7045e7931f94SStefano Zampini PetscMPIInt size, rank, color; 704652e5ac9dSStefano Zampini PetscInt *xadj, *adjncy; 704752e5ac9dSStefano Zampini PetscInt *adjncy_wgt, *v_wgt, *ranks_send_to_idx; 7048bb360cb4SStefano Zampini PetscInt im_active, active_procs, N, n, i, j, threshold = 2; 704957de7509SStefano Zampini PetscInt void_procs, *procs_candidates = NULL; 705027b6a85dSStefano Zampini PetscInt xadj_count, *count; 705127b6a85dSStefano Zampini PetscBool ismatis, use_vwgt = PETSC_FALSE; 705227b6a85dSStefano Zampini PetscSubcomm psubcomm; 705327b6a85dSStefano Zampini MPI_Comm subcomm; 7054a57a6d2fSStefano Zampini 7055e7931f94SStefano Zampini PetscFunctionBegin; 705657de7509SStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 70579566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)mat, MATIS, &ismatis)); 705828b400f6SJacob 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); 705957de7509SStefano Zampini PetscValidLogicalCollectiveInt(mat, *n_subdomains, 2); 706057de7509SStefano Zampini PetscValidLogicalCollectiveInt(mat, redprocs, 3); 706163a3b9bcSJacob Faibussowitsch PetscCheck(*n_subdomains > 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Invalid number of subdomains requested %" PetscInt_FMT, *n_subdomains); 706257de7509SStefano Zampini 706357de7509SStefano Zampini if (have_void) *have_void = PETSC_FALSE; 70649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 70659566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)mat), &rank)); 70669566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(mat, &A)); 70679566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &n, NULL)); 7068bb360cb4SStefano Zampini im_active = !!n; 70691c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&im_active, &active_procs, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 707057de7509SStefano Zampini void_procs = size - active_procs; 707115229ffcSPierre Jolivet /* get ranks of non-active processes in mat communicator */ 707257de7509SStefano Zampini if (void_procs) { 707357de7509SStefano Zampini PetscInt ncand; 707457de7509SStefano Zampini 707557de7509SStefano Zampini if (have_void) *have_void = PETSC_TRUE; 70769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &procs_candidates)); 70779566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allgather(&im_active, 1, MPIU_INT, procs_candidates, 1, MPIU_INT, PetscObjectComm((PetscObject)mat))); 707857de7509SStefano Zampini for (i = 0, ncand = 0; i < size; i++) { 7079ad540459SPierre Jolivet if (!procs_candidates[i]) procs_candidates[ncand++] = i; 708057de7509SStefano Zampini } 708157de7509SStefano Zampini /* force n_subdomains to be not greater that the number of non-active processes */ 708257de7509SStefano Zampini *n_subdomains = PetscMin(void_procs, *n_subdomains); 708357de7509SStefano Zampini } 708457de7509SStefano Zampini 7085bb360cb4SStefano Zampini /* number of subdomains requested greater than active processes or matrix size -> just shift the matrix 70869dddd249SSatish Balay number of subdomains requested 1 -> send to rank-0 or first candidate in voids */ 70879566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &N, NULL)); 7088bb360cb4SStefano Zampini if (active_procs < *n_subdomains || *n_subdomains == 1 || N <= *n_subdomains) { 708914f0bfb9SStefano Zampini PetscInt issize, isidx, dest; 709014f0bfb9SStefano Zampini if (*n_subdomains == 1) dest = 0; 709114f0bfb9SStefano Zampini else dest = rank; 709257de7509SStefano Zampini if (im_active) { 709357de7509SStefano Zampini issize = 1; 709457de7509SStefano Zampini if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */ 709514f0bfb9SStefano Zampini isidx = procs_candidates[dest]; 709657de7509SStefano Zampini } else { 709714f0bfb9SStefano Zampini isidx = dest; 709857de7509SStefano Zampini } 709957de7509SStefano Zampini } else { 710057de7509SStefano Zampini issize = 0; 710157de7509SStefano Zampini isidx = -1; 710257de7509SStefano Zampini } 7103bb360cb4SStefano Zampini if (*n_subdomains != 1) *n_subdomains = active_procs; 71049566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), issize, &isidx, PETSC_COPY_VALUES, is_sends)); 71059566063dSJacob Faibussowitsch PetscCall(PetscFree(procs_candidates)); 71063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 710757de7509SStefano Zampini } 71089566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-matis_partitioning_use_vwgt", &use_vwgt, NULL)); 71099566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, NULL, "-matis_partitioning_threshold", &threshold, NULL)); 711027b6a85dSStefano Zampini threshold = PetscMax(threshold, 2); 7111e7931f94SStefano Zampini 7112e7931f94SStefano Zampini /* Get info on mapping */ 71139566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(mat, &mapping, NULL)); 71149566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetInfo(mapping, &n_neighs, &neighs, &n_shared, &shared)); 7115e7931f94SStefano Zampini 7116e7931f94SStefano Zampini /* build local CSR graph of subdomains' connectivity */ 71179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2, &xadj)); 7118e7931f94SStefano Zampini xadj[0] = 0; 7119e7931f94SStefano Zampini xadj[1] = PetscMax(n_neighs - 1, 0); 71209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(xadj[1], &adjncy)); 71219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(xadj[1], &adjncy_wgt)); 71229566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(n, &count)); 712327b6a85dSStefano Zampini for (i = 1; i < n_neighs; i++) 71249371c9d4SSatish Balay for (j = 0; j < n_shared[i]; j++) count[shared[i][j]] += 1; 7125e7931f94SStefano Zampini 712627b6a85dSStefano Zampini xadj_count = 0; 71272b510759SStefano Zampini for (i = 1; i < n_neighs; i++) { 712827b6a85dSStefano Zampini for (j = 0; j < n_shared[i]; j++) { 712927b6a85dSStefano Zampini if (count[shared[i][j]] < threshold) { 7130d023bfaeSStefano Zampini adjncy[xadj_count] = neighs[i]; 7131d023bfaeSStefano Zampini adjncy_wgt[xadj_count] = n_shared[i]; 7132d023bfaeSStefano Zampini xadj_count++; 713327b6a85dSStefano Zampini break; 713427b6a85dSStefano Zampini } 7135e7931f94SStefano Zampini } 7136e7931f94SStefano Zampini } 7137d023bfaeSStefano Zampini xadj[1] = xadj_count; 71389566063dSJacob Faibussowitsch PetscCall(PetscFree(count)); 71399566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreInfo(mapping, &n_neighs, &neighs, &n_shared, &shared)); 71409566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(xadj[1], adjncy, adjncy_wgt)); 7141e7931f94SStefano Zampini 71429566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &ranks_send_to_idx)); 7143e7931f94SStefano Zampini 714427b6a85dSStefano Zampini /* Restrict work on active processes only */ 71459566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(im_active, &color)); 714627b6a85dSStefano Zampini if (void_procs) { 71479566063dSJacob Faibussowitsch PetscCall(PetscSubcommCreate(PetscObjectComm((PetscObject)mat), &psubcomm)); 71489566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetNumber(psubcomm, 2)); /* 2 groups, active process and not active processes */ 71499566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetTypeGeneral(psubcomm, color, rank)); 715027b6a85dSStefano Zampini subcomm = PetscSubcommChild(psubcomm); 715127b6a85dSStefano Zampini } else { 715227b6a85dSStefano Zampini psubcomm = NULL; 715327b6a85dSStefano Zampini subcomm = PetscObjectComm((PetscObject)mat); 715427b6a85dSStefano Zampini } 715527b6a85dSStefano Zampini 715627b6a85dSStefano Zampini v_wgt = NULL; 715727b6a85dSStefano Zampini if (!color) { 71589566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 71599566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 71609566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy_wgt)); 7161c8587f34SStefano Zampini } else { 716252e5ac9dSStefano Zampini Mat subdomain_adj; 716352e5ac9dSStefano Zampini IS new_ranks, new_ranks_contig; 716452e5ac9dSStefano Zampini MatPartitioning partitioner; 716527b6a85dSStefano Zampini PetscInt rstart = 0, rend = 0; 716652e5ac9dSStefano Zampini PetscInt *is_indices, *oldranks; 716757de7509SStefano Zampini PetscMPIInt size; 7168b0c7d250SStefano Zampini PetscBool aggregate; 7169b0c7d250SStefano Zampini 71709566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(subcomm, &size)); 717127b6a85dSStefano Zampini if (void_procs) { 717227b6a85dSStefano Zampini PetscInt prank = rank; 71739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &oldranks)); 71749566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allgather(&prank, 1, MPIU_INT, oldranks, 1, MPIU_INT, subcomm)); 717548a46eb9SPierre Jolivet for (i = 0; i < xadj[1]; i++) PetscCall(PetscFindInt(adjncy[i], size, oldranks, &adjncy[i])); 71769566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithArray(xadj[1], adjncy, adjncy_wgt)); 717727b6a85dSStefano Zampini } else { 717827b6a85dSStefano Zampini oldranks = NULL; 717927b6a85dSStefano Zampini } 7180b0c7d250SStefano Zampini aggregate = ((redprocs > 0 && redprocs < size) ? PETSC_TRUE : PETSC_FALSE); 718127b6a85dSStefano Zampini if (aggregate) { /* TODO: all this part could be made more efficient */ 7182b0c7d250SStefano Zampini PetscInt lrows, row, ncols, *cols; 7183b0c7d250SStefano Zampini PetscMPIInt nrank; 7184b0c7d250SStefano Zampini PetscScalar *vals; 7185b0c7d250SStefano Zampini 71869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(subcomm, &nrank)); 7187b0c7d250SStefano Zampini lrows = 0; 7188b0c7d250SStefano Zampini if (nrank < redprocs) { 7189b0c7d250SStefano Zampini lrows = size / redprocs; 7190b0c7d250SStefano Zampini if (nrank < size % redprocs) lrows++; 7191b0c7d250SStefano Zampini } 71929566063dSJacob Faibussowitsch PetscCall(MatCreateAIJ(subcomm, lrows, lrows, size, size, 50, NULL, 50, NULL, &subdomain_adj)); 71939566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(subdomain_adj, &rstart, &rend)); 71949566063dSJacob Faibussowitsch PetscCall(MatSetOption(subdomain_adj, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_FALSE)); 71959566063dSJacob Faibussowitsch PetscCall(MatSetOption(subdomain_adj, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 7196b0c7d250SStefano Zampini row = nrank; 7197b0c7d250SStefano Zampini ncols = xadj[1] - xadj[0]; 7198b0c7d250SStefano Zampini cols = adjncy; 71999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncols, &vals)); 7200b0c7d250SStefano Zampini for (i = 0; i < ncols; i++) vals[i] = adjncy_wgt[i]; 72019566063dSJacob Faibussowitsch PetscCall(MatSetValues(subdomain_adj, 1, &row, ncols, cols, vals, INSERT_VALUES)); 72029566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(subdomain_adj, MAT_FINAL_ASSEMBLY)); 72039566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(subdomain_adj, MAT_FINAL_ASSEMBLY)); 72049566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 72059566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 72069566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy_wgt)); 72079566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 720827b6a85dSStefano Zampini if (use_vwgt) { 720927b6a85dSStefano Zampini Vec v; 721027b6a85dSStefano Zampini const PetscScalar *array; 721127b6a85dSStefano Zampini PetscInt nl; 721227b6a85dSStefano Zampini 72139566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(subdomain_adj, &v, NULL)); 72149566063dSJacob Faibussowitsch PetscCall(VecSetValue(v, row, (PetscScalar)n, INSERT_VALUES)); 72159566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(v)); 72169566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(v)); 72179566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &nl)); 72189566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &array)); 72199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl, &v_wgt)); 722022db5ddcSStefano Zampini for (i = 0; i < nl; i++) v_wgt[i] = (PetscInt)PetscRealPart(array[i]); 72219566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &array)); 72229566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 722327b6a85dSStefano Zampini } 7224b0c7d250SStefano Zampini } else { 72259566063dSJacob Faibussowitsch PetscCall(MatCreateMPIAdj(subcomm, 1, (PetscInt)size, xadj, adjncy, adjncy_wgt, &subdomain_adj)); 722627b6a85dSStefano Zampini if (use_vwgt) { 72279566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &v_wgt)); 7228bb360cb4SStefano Zampini v_wgt[0] = n; 722927b6a85dSStefano Zampini } 7230b0c7d250SStefano Zampini } 72319566063dSJacob Faibussowitsch /* PetscCall(MatView(subdomain_adj,0)); */ 7232e7931f94SStefano Zampini 7233e7931f94SStefano Zampini /* Partition */ 72349566063dSJacob Faibussowitsch PetscCall(MatPartitioningCreate(subcomm, &partitioner)); 7235ce64c636SStefano Zampini #if defined(PETSC_HAVE_PTSCOTCH) 72369566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetType(partitioner, MATPARTITIONINGPTSCOTCH)); 7237ce64c636SStefano Zampini #elif defined(PETSC_HAVE_PARMETIS) 72389566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetType(partitioner, MATPARTITIONINGPARMETIS)); 7239ce64c636SStefano Zampini #else 72409566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetType(partitioner, MATPARTITIONINGAVERAGE)); 7241ce64c636SStefano Zampini #endif 72429566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetAdjacency(partitioner, subdomain_adj)); 72431baa6e33SBarry Smith if (v_wgt) PetscCall(MatPartitioningSetVertexWeights(partitioner, v_wgt)); 724457de7509SStefano Zampini *n_subdomains = PetscMin((PetscInt)size, *n_subdomains); 72459566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetNParts(partitioner, *n_subdomains)); 72469566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetFromOptions(partitioner)); 72479566063dSJacob Faibussowitsch PetscCall(MatPartitioningApply(partitioner, &new_ranks)); 72489566063dSJacob Faibussowitsch /* PetscCall(MatPartitioningView(partitioner,0)); */ 7249e7931f94SStefano Zampini 725052e5ac9dSStefano Zampini /* renumber new_ranks to avoid "holes" in new set of processors */ 72519566063dSJacob Faibussowitsch PetscCall(ISRenumber(new_ranks, NULL, NULL, &new_ranks_contig)); 72529566063dSJacob Faibussowitsch PetscCall(ISDestroy(&new_ranks)); 72539566063dSJacob Faibussowitsch PetscCall(ISGetIndices(new_ranks_contig, (const PetscInt **)&is_indices)); 725457de7509SStefano Zampini if (!aggregate) { 725557de7509SStefano Zampini if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */ 72566bdcaf15SBarry Smith PetscAssert(oldranks, PETSC_COMM_SELF, PETSC_ERR_PLIB, "This should not happen"); 725757de7509SStefano Zampini ranks_send_to_idx[0] = procs_candidates[oldranks[is_indices[0]]]; 725827b6a85dSStefano Zampini } else if (oldranks) { 7259b0c7d250SStefano Zampini ranks_send_to_idx[0] = oldranks[is_indices[0]]; 726027b6a85dSStefano Zampini } else { 726127b6a85dSStefano Zampini ranks_send_to_idx[0] = is_indices[0]; 726257de7509SStefano Zampini } 726328143c3dSStefano Zampini } else { 72647fb8a5e4SKarl Rupp PetscInt idx = 0; 7265b0c7d250SStefano Zampini PetscMPIInt tag; 7266b0c7d250SStefano Zampini MPI_Request *reqs; 7267b0c7d250SStefano Zampini 72689566063dSJacob Faibussowitsch PetscCall(PetscObjectGetNewTag((PetscObject)subdomain_adj, &tag)); 72699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rend - rstart, &reqs)); 727048a46eb9SPierre Jolivet for (i = rstart; i < rend; i++) PetscCallMPI(MPI_Isend(is_indices + i - rstart, 1, MPIU_INT, i, tag, subcomm, &reqs[i - rstart])); 72719566063dSJacob Faibussowitsch PetscCallMPI(MPI_Recv(&idx, 1, MPIU_INT, MPI_ANY_SOURCE, tag, subcomm, MPI_STATUS_IGNORE)); 72729566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(rend - rstart, reqs, MPI_STATUSES_IGNORE)); 72739566063dSJacob Faibussowitsch PetscCall(PetscFree(reqs)); 727457de7509SStefano Zampini if (procs_candidates) { /* shift the pattern on non-active candidates (if any) */ 72756bdcaf15SBarry Smith PetscAssert(oldranks, PETSC_COMM_SELF, PETSC_ERR_PLIB, "This should not happen"); 72767fb8a5e4SKarl Rupp ranks_send_to_idx[0] = procs_candidates[oldranks[idx]]; 727727b6a85dSStefano Zampini } else if (oldranks) { 72787fb8a5e4SKarl Rupp ranks_send_to_idx[0] = oldranks[idx]; 727927b6a85dSStefano Zampini } else { 72807fb8a5e4SKarl Rupp ranks_send_to_idx[0] = idx; 728128143c3dSStefano Zampini } 728257de7509SStefano Zampini } 72839566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(new_ranks_contig, (const PetscInt **)&is_indices)); 7284e7931f94SStefano Zampini /* clean up */ 72859566063dSJacob Faibussowitsch PetscCall(PetscFree(oldranks)); 72869566063dSJacob Faibussowitsch PetscCall(ISDestroy(&new_ranks_contig)); 72879566063dSJacob Faibussowitsch PetscCall(MatDestroy(&subdomain_adj)); 72889566063dSJacob Faibussowitsch PetscCall(MatPartitioningDestroy(&partitioner)); 7289e7931f94SStefano Zampini } 72909566063dSJacob Faibussowitsch PetscCall(PetscSubcommDestroy(&psubcomm)); 72919566063dSJacob Faibussowitsch PetscCall(PetscFree(procs_candidates)); 7292e7931f94SStefano Zampini 7293e7931f94SStefano Zampini /* assemble parallel IS for sends */ 7294e7931f94SStefano Zampini i = 1; 729527b6a85dSStefano Zampini if (!color) i = 0; 72969566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), i, ranks_send_to_idx, PETSC_OWN_POINTER, is_sends)); 72973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7298e7931f94SStefano Zampini } 7299e7931f94SStefano Zampini 73009371c9d4SSatish Balay typedef enum { 73019371c9d4SSatish Balay MATDENSE_PRIVATE = 0, 73029371c9d4SSatish Balay MATAIJ_PRIVATE, 73039371c9d4SSatish Balay MATBAIJ_PRIVATE, 73049371c9d4SSatish Balay MATSBAIJ_PRIVATE 73059371c9d4SSatish Balay } MatTypePrivate; 7306e7931f94SStefano Zampini 7307ba38deedSJacob 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[]) 7308d71ae5a4SJacob Faibussowitsch { 730970cf5478SStefano Zampini Mat local_mat; 7310e7931f94SStefano Zampini IS is_sends_internal; 73119d30be91SStefano Zampini PetscInt rows, cols, new_local_rows; 73121ae86dd6SStefano Zampini PetscInt i, bs, buf_size_idxs, buf_size_idxs_is, buf_size_vals, buf_size_vecs; 73139d30be91SStefano Zampini PetscBool ismatis, isdense, newisdense, destroy_mat; 7314e7931f94SStefano Zampini ISLocalToGlobalMapping l2gmap; 7315e7931f94SStefano Zampini PetscInt *l2gmap_indices; 7316e7931f94SStefano Zampini const PetscInt *is_indices; 7317e7931f94SStefano Zampini MatType new_local_type; 7318e7931f94SStefano Zampini /* buffers */ 7319e7931f94SStefano Zampini PetscInt *ptr_idxs, *send_buffer_idxs, *recv_buffer_idxs; 732028143c3dSStefano Zampini PetscInt *ptr_idxs_is, *send_buffer_idxs_is, *recv_buffer_idxs_is; 73219d30be91SStefano Zampini PetscInt *recv_buffer_idxs_local; 73221683a169SBarry Smith PetscScalar *ptr_vals, *recv_buffer_vals; 73231683a169SBarry Smith const PetscScalar *send_buffer_vals; 73241ae86dd6SStefano Zampini PetscScalar *ptr_vecs, *send_buffer_vecs, *recv_buffer_vecs; 7325e7931f94SStefano Zampini /* MPI */ 732628143c3dSStefano Zampini MPI_Comm comm, comm_n; 732728143c3dSStefano Zampini PetscSubcomm subcomm; 7328e569e4e1SStefano Zampini PetscMPIInt n_sends, n_recvs, size; 732928143c3dSStefano Zampini PetscMPIInt *iflags, *ilengths_idxs, *ilengths_vals, *ilengths_idxs_is; 733028143c3dSStefano Zampini PetscMPIInt *onodes, *onodes_is, *olengths_idxs, *olengths_idxs_is, *olengths_vals; 73311ae86dd6SStefano Zampini PetscMPIInt len, tag_idxs, tag_idxs_is, tag_vals, tag_vecs, source_dest; 73321ae86dd6SStefano Zampini MPI_Request *send_req_idxs, *send_req_idxs_is, *send_req_vals, *send_req_vecs; 73331ae86dd6SStefano Zampini MPI_Request *recv_req_idxs, *recv_req_idxs_is, *recv_req_vals, *recv_req_vecs; 7334e7931f94SStefano Zampini 7335e7931f94SStefano Zampini PetscFunctionBegin; 733657de7509SStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 73379566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)mat, MATIS, &ismatis)); 73385f80ce2aSJacob 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); 733957de7509SStefano Zampini PetscValidLogicalCollectiveInt(mat, n_subdomains, 3); 734057de7509SStefano Zampini PetscValidLogicalCollectiveBool(mat, restrict_comm, 4); 734157de7509SStefano Zampini PetscValidLogicalCollectiveBool(mat, restrict_full, 5); 734257de7509SStefano Zampini PetscValidLogicalCollectiveBool(mat, reuse, 6); 734357de7509SStefano Zampini PetscValidLogicalCollectiveInt(mat, nis, 8); 73441ae86dd6SStefano Zampini PetscValidLogicalCollectiveInt(mat, nvecs, 10); 73451ae86dd6SStefano Zampini if (nvecs) { 734608401ef6SPierre Jolivet PetscCheck(nvecs <= 1, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Just 1 vector supported"); 73471ae86dd6SStefano Zampini PetscValidHeaderSpecific(nnsp_vec[0], VEC_CLASSID, 11); 73481ae86dd6SStefano Zampini } 734957de7509SStefano Zampini /* further checks */ 73509566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(mat, &local_mat)); 73519566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)local_mat, MATSEQDENSE, &isdense)); 73525f80ce2aSJacob Faibussowitsch PetscCheck(isdense, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE"); 73539566063dSJacob Faibussowitsch PetscCall(MatGetSize(local_mat, &rows, &cols)); 73545f80ce2aSJacob Faibussowitsch PetscCheck(rows == cols, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Local MATIS matrices should be square"); 735557de7509SStefano Zampini if (reuse && *mat_n) { 735670cf5478SStefano Zampini PetscInt mrows, mcols, mnrows, mncols; 735757de7509SStefano Zampini PetscValidHeaderSpecific(*mat_n, MAT_CLASSID, 7); 73589566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)*mat_n, MATIS, &ismatis)); 73595f80ce2aSJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)*mat_n), PETSC_ERR_SUP, "Cannot reuse a matrix which is not of type MATIS"); 73609566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &mrows, &mcols)); 73619566063dSJacob Faibussowitsch PetscCall(MatGetSize(*mat_n, &mnrows, &mncols)); 736263a3b9bcSJacob Faibussowitsch PetscCheck(mrows == mnrows, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix! Wrong number of rows %" PetscInt_FMT " != %" PetscInt_FMT, mrows, mnrows); 736363a3b9bcSJacob Faibussowitsch PetscCheck(mcols == mncols, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix! Wrong number of cols %" PetscInt_FMT " != %" PetscInt_FMT, mcols, mncols); 736470cf5478SStefano Zampini } 73659566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(local_mat, &bs)); 7366064a246eSJacob Faibussowitsch PetscValidLogicalCollectiveInt(mat, bs, 1); 736757de7509SStefano Zampini 7368e7931f94SStefano Zampini /* prepare IS for sending if not provided */ 7369e7931f94SStefano Zampini if (!is_sends) { 73705f80ce2aSJacob Faibussowitsch PetscCheck(n_subdomains, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "You should specify either an IS or a target number of subdomains"); 73719566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISGetSubassemblingPattern(mat, &n_subdomains, 0, &is_sends_internal, NULL)); 7372c8587f34SStefano Zampini } else { 73739566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is_sends)); 7374e7931f94SStefano Zampini is_sends_internal = is_sends; 7375c8587f34SStefano Zampini } 7376e7931f94SStefano Zampini 7377e7931f94SStefano Zampini /* get comm */ 73789566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7379e7931f94SStefano Zampini 7380e7931f94SStefano Zampini /* compute number of sends */ 73819566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is_sends_internal, &i)); 73829566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(i, &n_sends)); 7383e7931f94SStefano Zampini 7384e7931f94SStefano Zampini /* compute number of receives */ 73859566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 73869566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &iflags)); 73879566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(iflags, size)); 73889566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is_sends_internal, &is_indices)); 7389e7931f94SStefano Zampini for (i = 0; i < n_sends; i++) iflags[is_indices[i]] = 1; 73909566063dSJacob Faibussowitsch PetscCall(PetscGatherNumberOfMessages(comm, iflags, NULL, &n_recvs)); 73919566063dSJacob Faibussowitsch PetscCall(PetscFree(iflags)); 7392e7931f94SStefano Zampini 739328143c3dSStefano Zampini /* restrict comm if requested */ 73940a545947SLisandro Dalcin subcomm = NULL; 739528143c3dSStefano Zampini destroy_mat = PETSC_FALSE; 739628143c3dSStefano Zampini if (restrict_comm) { 7397779c1cceSStefano Zampini PetscMPIInt color, subcommsize; 7398779c1cceSStefano Zampini 739928143c3dSStefano Zampini color = 0; 740053a05cb3SStefano Zampini if (restrict_full) { 74016aad120cSJose E. Roman if (!n_recvs) color = 1; /* processes not receiving anything will not participate in new comm (full restriction) */ 740253a05cb3SStefano Zampini } else { 74036aad120cSJose 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 */ 740453a05cb3SStefano Zampini } 74051c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&color, &subcommsize, 1, MPI_INT, MPI_SUM, comm)); 7406e569e4e1SStefano Zampini subcommsize = size - subcommsize; 740728143c3dSStefano Zampini /* check if reuse has been requested */ 740857de7509SStefano Zampini if (reuse) { 740928143c3dSStefano Zampini if (*mat_n) { 741028143c3dSStefano Zampini PetscMPIInt subcommsize2; 74119566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n), &subcommsize2)); 74125f80ce2aSJacob Faibussowitsch PetscCheck(subcommsize == subcommsize2, PetscObjectComm((PetscObject)*mat_n), PETSC_ERR_PLIB, "Cannot reuse matrix! wrong subcomm size %d != %d", subcommsize, subcommsize2); 741328143c3dSStefano Zampini comm_n = PetscObjectComm((PetscObject)*mat_n); 741428143c3dSStefano Zampini } else { 741528143c3dSStefano Zampini comm_n = PETSC_COMM_SELF; 741628143c3dSStefano Zampini } 741728143c3dSStefano Zampini } else { /* MAT_INITIAL_MATRIX */ 7418779c1cceSStefano Zampini PetscMPIInt rank; 7419779c1cceSStefano Zampini 74209566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 74219566063dSJacob Faibussowitsch PetscCall(PetscSubcommCreate(comm, &subcomm)); 74229566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetNumber(subcomm, 2)); 74239566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetTypeGeneral(subcomm, color, rank)); 7424306c2d5bSBarry Smith comm_n = PetscSubcommChild(subcomm); 742528143c3dSStefano Zampini } 742628143c3dSStefano Zampini /* flag to destroy *mat_n if not significative */ 742728143c3dSStefano Zampini if (color) destroy_mat = PETSC_TRUE; 742828143c3dSStefano Zampini } else { 742928143c3dSStefano Zampini comm_n = comm; 743028143c3dSStefano Zampini } 743128143c3dSStefano Zampini 7432e7931f94SStefano Zampini /* prepare send/receive buffers */ 74339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &ilengths_idxs)); 74349566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(ilengths_idxs, size)); 74359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(size, &ilengths_vals)); 74369566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(ilengths_vals, size)); 743748a46eb9SPierre Jolivet if (nis) PetscCall(PetscCalloc1(size, &ilengths_idxs_is)); 7438e7931f94SStefano Zampini 743928143c3dSStefano Zampini /* Get data from local matrices */ 7440e432b41dSStefano Zampini PetscCheck(isdense, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Subassembling of AIJ local matrices not yet implemented"); 7441e7931f94SStefano Zampini /* TODO: See below some guidelines on how to prepare the local buffers */ 7442e7931f94SStefano Zampini /* 7443e7931f94SStefano Zampini send_buffer_vals should contain the raw values of the local matrix 7444e7931f94SStefano Zampini send_buffer_idxs should contain: 7445e7931f94SStefano Zampini - MatType_PRIVATE type 7446e7931f94SStefano Zampini - PetscInt size_of_l2gmap 7447e7931f94SStefano Zampini - PetscInt global_row_indices[size_of_l2gmap] 7448e7931f94SStefano Zampini - PetscInt all_other_info_which_is_needed_to_compute_preallocation_and_set_values 7449e7931f94SStefano Zampini */ 7450e432b41dSStefano Zampini { 7451e432b41dSStefano Zampini ISLocalToGlobalMapping mapping; 7452e432b41dSStefano Zampini 74539566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(mat, &mapping, NULL)); 74549566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(local_mat, &send_buffer_vals)); 74559566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(mapping, &i)); 74569566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(i + 2, &send_buffer_idxs)); 7457e7931f94SStefano Zampini send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE; 7458e7931f94SStefano Zampini send_buffer_idxs[1] = i; 74599566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(mapping, (const PetscInt **)&ptr_idxs)); 74609566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&send_buffer_idxs[2], ptr_idxs, i)); 74619566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(mapping, (const PetscInt **)&ptr_idxs)); 74629566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(i, &len)); 7463e7931f94SStefano Zampini for (i = 0; i < n_sends; i++) { 7464e7931f94SStefano Zampini ilengths_vals[is_indices[i]] = len * len; 7465e7931f94SStefano Zampini ilengths_idxs[is_indices[i]] = len + 2; 7466c8587f34SStefano Zampini } 7467c8587f34SStefano Zampini } 74689566063dSJacob Faibussowitsch PetscCall(PetscGatherMessageLengths2(comm, n_sends, n_recvs, ilengths_idxs, ilengths_vals, &onodes, &olengths_idxs, &olengths_vals)); 746928143c3dSStefano Zampini /* additional is (if any) */ 747028143c3dSStefano Zampini if (nis) { 747128143c3dSStefano Zampini PetscMPIInt psum; 747228143c3dSStefano Zampini PetscInt j; 747328143c3dSStefano Zampini for (j = 0, psum = 0; j < nis; j++) { 747428143c3dSStefano Zampini PetscInt plen; 74759566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isarray[j], &plen)); 74769566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(plen, &len)); 74776aad120cSJose E. Roman psum += len + 1; /* indices + length */ 747828143c3dSStefano Zampini } 74799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(psum, &send_buffer_idxs_is)); 748028143c3dSStefano Zampini for (j = 0, psum = 0; j < nis; j++) { 748128143c3dSStefano Zampini PetscInt plen; 748228143c3dSStefano Zampini const PetscInt *is_array_idxs; 74839566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isarray[j], &plen)); 748428143c3dSStefano Zampini send_buffer_idxs_is[psum] = plen; 74859566063dSJacob Faibussowitsch PetscCall(ISGetIndices(isarray[j], &is_array_idxs)); 74869566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&send_buffer_idxs_is[psum + 1], is_array_idxs, plen)); 74879566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(isarray[j], &is_array_idxs)); 74886aad120cSJose E. Roman psum += plen + 1; /* indices + length */ 748928143c3dSStefano Zampini } 7490ad540459SPierre Jolivet for (i = 0; i < n_sends; i++) ilengths_idxs_is[is_indices[i]] = psum; 74919566063dSJacob Faibussowitsch PetscCall(PetscGatherMessageLengths(comm, n_sends, n_recvs, ilengths_idxs_is, &onodes_is, &olengths_idxs_is)); 749228143c3dSStefano Zampini } 74939566063dSJacob Faibussowitsch PetscCall(MatISRestoreLocalMat(mat, &local_mat)); 749428143c3dSStefano Zampini 7495e7931f94SStefano Zampini buf_size_idxs = 0; 7496e7931f94SStefano Zampini buf_size_vals = 0; 749728143c3dSStefano Zampini buf_size_idxs_is = 0; 74981ae86dd6SStefano Zampini buf_size_vecs = 0; 7499e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 7500e7931f94SStefano Zampini buf_size_idxs += (PetscInt)olengths_idxs[i]; 7501e7931f94SStefano Zampini buf_size_vals += (PetscInt)olengths_vals[i]; 750228143c3dSStefano Zampini if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i]; 75031ae86dd6SStefano Zampini if (nvecs) buf_size_vecs += (PetscInt)olengths_idxs[i]; 7504e7931f94SStefano Zampini } 75059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(buf_size_idxs, &recv_buffer_idxs)); 75069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(buf_size_vals, &recv_buffer_vals)); 75079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(buf_size_idxs_is, &recv_buffer_idxs_is)); 75089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(buf_size_vecs, &recv_buffer_vecs)); 7509e7931f94SStefano Zampini 7510e7931f94SStefano Zampini /* get new tags for clean communications */ 75119566063dSJacob Faibussowitsch PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag_idxs)); 75129566063dSJacob Faibussowitsch PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag_vals)); 75139566063dSJacob Faibussowitsch PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag_idxs_is)); 75149566063dSJacob Faibussowitsch PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag_vecs)); 7515e7931f94SStefano Zampini 7516e7931f94SStefano Zampini /* allocate for requests */ 75179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_sends, &send_req_idxs)); 75189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_sends, &send_req_vals)); 75199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_sends, &send_req_idxs_is)); 75209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_sends, &send_req_vecs)); 75219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_recvs, &recv_req_idxs)); 75229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_recvs, &recv_req_vals)); 75239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_recvs, &recv_req_idxs_is)); 75249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_recvs, &recv_req_vecs)); 7525e7931f94SStefano Zampini 7526e7931f94SStefano Zampini /* communications */ 7527e7931f94SStefano Zampini ptr_idxs = recv_buffer_idxs; 7528e7931f94SStefano Zampini ptr_vals = recv_buffer_vals; 752928143c3dSStefano Zampini ptr_idxs_is = recv_buffer_idxs_is; 75301ae86dd6SStefano Zampini ptr_vecs = recv_buffer_vecs; 7531e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 7532e7931f94SStefano Zampini source_dest = onodes[i]; 75339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Irecv(ptr_idxs, olengths_idxs[i], MPIU_INT, source_dest, tag_idxs, comm, &recv_req_idxs[i])); 75349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Irecv(ptr_vals, olengths_vals[i], MPIU_SCALAR, source_dest, tag_vals, comm, &recv_req_vals[i])); 7535e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 7536e7931f94SStefano Zampini ptr_vals += olengths_vals[i]; 753728143c3dSStefano Zampini if (nis) { 753857de7509SStefano Zampini source_dest = onodes_is[i]; 75399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Irecv(ptr_idxs_is, olengths_idxs_is[i], MPIU_INT, source_dest, tag_idxs_is, comm, &recv_req_idxs_is[i])); 754028143c3dSStefano Zampini ptr_idxs_is += olengths_idxs_is[i]; 754128143c3dSStefano Zampini } 75421ae86dd6SStefano Zampini if (nvecs) { 75431ae86dd6SStefano Zampini source_dest = onodes[i]; 75449566063dSJacob Faibussowitsch PetscCallMPI(MPI_Irecv(ptr_vecs, olengths_idxs[i] - 2, MPIU_SCALAR, source_dest, tag_vecs, comm, &recv_req_vecs[i])); 75451ae86dd6SStefano Zampini ptr_vecs += olengths_idxs[i] - 2; 75461ae86dd6SStefano Zampini } 7547e7931f94SStefano Zampini } 7548e7931f94SStefano Zampini for (i = 0; i < n_sends; i++) { 75499566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(is_indices[i], &source_dest)); 75509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Isend(send_buffer_idxs, ilengths_idxs[source_dest], MPIU_INT, source_dest, tag_idxs, comm, &send_req_idxs[i])); 75519566063dSJacob Faibussowitsch PetscCallMPI(MPI_Isend((PetscScalar *)send_buffer_vals, ilengths_vals[source_dest], MPIU_SCALAR, source_dest, tag_vals, comm, &send_req_vals[i])); 755248a46eb9SPierre Jolivet if (nis) PetscCallMPI(MPI_Isend(send_buffer_idxs_is, ilengths_idxs_is[source_dest], MPIU_INT, source_dest, tag_idxs_is, comm, &send_req_idxs_is[i])); 75531ae86dd6SStefano Zampini if (nvecs) { 75549566063dSJacob Faibussowitsch PetscCall(VecGetArray(nnsp_vec[0], &send_buffer_vecs)); 75559566063dSJacob Faibussowitsch PetscCallMPI(MPI_Isend(send_buffer_vecs, ilengths_idxs[source_dest] - 2, MPIU_SCALAR, source_dest, tag_vecs, comm, &send_req_vecs[i])); 75561ae86dd6SStefano Zampini } 7557e7931f94SStefano Zampini } 75589566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is_sends_internal, &is_indices)); 75599566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_sends_internal)); 7560e7931f94SStefano Zampini 7561e7931f94SStefano Zampini /* assemble new l2g map */ 75629566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_recvs, recv_req_idxs, MPI_STATUSES_IGNORE)); 7563e7931f94SStefano Zampini ptr_idxs = recv_buffer_idxs; 75649d30be91SStefano Zampini new_local_rows = 0; 7565e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 75669d30be91SStefano Zampini new_local_rows += *(ptr_idxs + 1); /* second element is the local size of the l2gmap */ 7567e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 7568e7931f94SStefano Zampini } 75699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(new_local_rows, &l2gmap_indices)); 7570e7931f94SStefano Zampini ptr_idxs = recv_buffer_idxs; 75719d30be91SStefano Zampini new_local_rows = 0; 7572e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 75739566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&l2gmap_indices[new_local_rows], ptr_idxs + 2, *(ptr_idxs + 1))); 75749d30be91SStefano Zampini new_local_rows += *(ptr_idxs + 1); /* second element is the local size of the l2gmap */ 7575e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 7576e7931f94SStefano Zampini } 75779566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&new_local_rows, l2gmap_indices)); 75789566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(comm_n, 1, new_local_rows, l2gmap_indices, PETSC_COPY_VALUES, &l2gmap)); 75799566063dSJacob Faibussowitsch PetscCall(PetscFree(l2gmap_indices)); 7580e7931f94SStefano Zampini 7581e7931f94SStefano Zampini /* infer new local matrix type from received local matrices type */ 7582e7931f94SStefano Zampini /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */ 7583e7931f94SStefano 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) */ 7584e7931f94SStefano Zampini if (n_recvs) { 758528143c3dSStefano Zampini MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0]; 7586e7931f94SStefano Zampini ptr_idxs = recv_buffer_idxs; 7587e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 7588e7931f94SStefano Zampini if ((PetscInt)new_local_type_private != *ptr_idxs) { 7589e7931f94SStefano Zampini new_local_type_private = MATAIJ_PRIVATE; 7590e7931f94SStefano Zampini break; 7591e7931f94SStefano Zampini } 7592e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 7593e7931f94SStefano Zampini } 7594e7931f94SStefano Zampini switch (new_local_type_private) { 759528143c3dSStefano Zampini case MATDENSE_PRIVATE: 7596e7931f94SStefano Zampini new_local_type = MATSEQAIJ; 7597e7931f94SStefano Zampini bs = 1; 7598e7931f94SStefano Zampini break; 7599e7931f94SStefano Zampini case MATAIJ_PRIVATE: 7600e7931f94SStefano Zampini new_local_type = MATSEQAIJ; 7601e7931f94SStefano Zampini bs = 1; 7602e7931f94SStefano Zampini break; 7603d71ae5a4SJacob Faibussowitsch case MATBAIJ_PRIVATE: 7604d71ae5a4SJacob Faibussowitsch new_local_type = MATSEQBAIJ; 7605d71ae5a4SJacob Faibussowitsch break; 7606d71ae5a4SJacob Faibussowitsch case MATSBAIJ_PRIVATE: 7607d71ae5a4SJacob Faibussowitsch new_local_type = MATSEQSBAIJ; 7608d71ae5a4SJacob Faibussowitsch break; 7609d71ae5a4SJacob Faibussowitsch default: 7610d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_SUP, "Unsupported private type %d in %s", new_local_type_private, PETSC_FUNCTION_NAME); 7611e7931f94SStefano Zampini } 7612ed8ed4edSstefano_zampini } else { /* by default, new_local_type is seqaij */ 7613ed8ed4edSstefano_zampini new_local_type = MATSEQAIJ; 761428143c3dSStefano Zampini bs = 1; 7615e7931f94SStefano Zampini } 7616e7931f94SStefano Zampini 761770cf5478SStefano Zampini /* create MATIS object if needed */ 761857de7509SStefano Zampini if (!reuse) { 76199566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &rows, &cols)); 76209566063dSJacob Faibussowitsch PetscCall(MatCreateIS(comm_n, bs, PETSC_DECIDE, PETSC_DECIDE, rows, cols, l2gmap, l2gmap, mat_n)); 762170cf5478SStefano Zampini } else { 762270cf5478SStefano Zampini /* it also destroys the local matrices */ 762357de7509SStefano Zampini if (*mat_n) { 76249566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*mat_n, l2gmap, l2gmap)); 762557de7509SStefano Zampini } else { /* this is a fake object */ 76269566063dSJacob Faibussowitsch PetscCall(MatCreateIS(comm_n, bs, PETSC_DECIDE, PETSC_DECIDE, rows, cols, l2gmap, l2gmap, mat_n)); 762757de7509SStefano Zampini } 762870cf5478SStefano Zampini } 76299566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*mat_n, &local_mat)); 76309566063dSJacob Faibussowitsch PetscCall(MatSetType(local_mat, new_local_type)); 76319d30be91SStefano Zampini 76329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_recvs, recv_req_vals, MPI_STATUSES_IGNORE)); 76339d30be91SStefano Zampini 76349d30be91SStefano Zampini /* Global to local map of received indices */ 76359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(buf_size_idxs, &recv_buffer_idxs_local)); /* needed for values insertion */ 76369566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(l2gmap, IS_GTOLM_MASK, buf_size_idxs, recv_buffer_idxs, &i, recv_buffer_idxs_local)); 76379566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&l2gmap)); 76389d30be91SStefano Zampini 76399d30be91SStefano Zampini /* restore attributes -> type of incoming data and its size */ 76409d30be91SStefano Zampini buf_size_idxs = 0; 76419d30be91SStefano Zampini for (i = 0; i < n_recvs; i++) { 76429d30be91SStefano Zampini recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs]; 76439d30be91SStefano Zampini recv_buffer_idxs_local[buf_size_idxs + 1] = recv_buffer_idxs[buf_size_idxs + 1]; 76449d30be91SStefano Zampini buf_size_idxs += (PetscInt)olengths_idxs[i]; 76459d30be91SStefano Zampini } 76469566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_buffer_idxs)); 76479d30be91SStefano Zampini 76489d30be91SStefano Zampini /* set preallocation */ 76499566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)local_mat, MATSEQDENSE, &newisdense)); 76509d30be91SStefano Zampini if (!newisdense) { 76510a545947SLisandro Dalcin PetscInt *new_local_nnz = NULL; 76529d30be91SStefano Zampini 76539d30be91SStefano Zampini ptr_idxs = recv_buffer_idxs_local; 765448a46eb9SPierre Jolivet if (n_recvs) PetscCall(PetscCalloc1(new_local_rows, &new_local_nnz)); 76559d30be91SStefano Zampini for (i = 0; i < n_recvs; i++) { 76569d30be91SStefano Zampini PetscInt j; 76579d30be91SStefano Zampini if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */ 7658ad540459SPierre Jolivet for (j = 0; j < *(ptr_idxs + 1); j++) new_local_nnz[*(ptr_idxs + 2 + j)] += *(ptr_idxs + 1); 76599d30be91SStefano Zampini } else { 76609d30be91SStefano Zampini /* TODO */ 76619d30be91SStefano Zampini } 76629d30be91SStefano Zampini ptr_idxs += olengths_idxs[i]; 76639d30be91SStefano Zampini } 76649d30be91SStefano Zampini if (new_local_nnz) { 76659d30be91SStefano Zampini for (i = 0; i < new_local_rows; i++) new_local_nnz[i] = PetscMin(new_local_nnz[i], new_local_rows); 76669566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(local_mat, 0, new_local_nnz)); 76679d30be91SStefano Zampini for (i = 0; i < new_local_rows; i++) new_local_nnz[i] /= bs; 76689566063dSJacob Faibussowitsch PetscCall(MatSeqBAIJSetPreallocation(local_mat, bs, 0, new_local_nnz)); 76699d30be91SStefano Zampini for (i = 0; i < new_local_rows; i++) new_local_nnz[i] = PetscMax(new_local_nnz[i] - i, 0); 76709566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(local_mat, bs, 0, new_local_nnz)); 76719d30be91SStefano Zampini } else { 76729566063dSJacob Faibussowitsch PetscCall(MatSetUp(local_mat)); 76739d30be91SStefano Zampini } 76749566063dSJacob Faibussowitsch PetscCall(PetscFree(new_local_nnz)); 76759d30be91SStefano Zampini } else { 76769566063dSJacob Faibussowitsch PetscCall(MatSetUp(local_mat)); 76779d30be91SStefano Zampini } 7678e7931f94SStefano Zampini 7679e7931f94SStefano Zampini /* set values */ 7680e7931f94SStefano Zampini ptr_vals = recv_buffer_vals; 76819d30be91SStefano Zampini ptr_idxs = recv_buffer_idxs_local; 7682e7931f94SStefano Zampini for (i = 0; i < n_recvs; i++) { 7683e7931f94SStefano Zampini if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */ 76849566063dSJacob Faibussowitsch PetscCall(MatSetOption(local_mat, MAT_ROW_ORIENTED, PETSC_FALSE)); 76859566063dSJacob Faibussowitsch PetscCall(MatSetValues(local_mat, *(ptr_idxs + 1), ptr_idxs + 2, *(ptr_idxs + 1), ptr_idxs + 2, ptr_vals, ADD_VALUES)); 76869566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(local_mat, MAT_FLUSH_ASSEMBLY)); 76879566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(local_mat, MAT_FLUSH_ASSEMBLY)); 76889566063dSJacob Faibussowitsch PetscCall(MatSetOption(local_mat, MAT_ROW_ORIENTED, PETSC_TRUE)); 768928143c3dSStefano Zampini } else { 769028143c3dSStefano Zampini /* TODO */ 7691e7931f94SStefano Zampini } 7692e7931f94SStefano Zampini ptr_idxs += olengths_idxs[i]; 7693e7931f94SStefano Zampini ptr_vals += olengths_vals[i]; 7694e7931f94SStefano Zampini } 76959566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(local_mat, MAT_FINAL_ASSEMBLY)); 76969566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(local_mat, MAT_FINAL_ASSEMBLY)); 76979566063dSJacob Faibussowitsch PetscCall(MatISRestoreLocalMat(*mat_n, &local_mat)); 76989566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat_n, MAT_FINAL_ASSEMBLY)); 76999566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat_n, MAT_FINAL_ASSEMBLY)); 77009566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_buffer_vals)); 7701e7931f94SStefano Zampini 7702dfd14d43SStefano Zampini #if 0 770328143c3dSStefano Zampini if (!restrict_comm) { /* check */ 7704e7931f94SStefano Zampini Vec lvec,rvec; 7705e7931f94SStefano Zampini PetscReal infty_error; 7706e7931f94SStefano Zampini 77079566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(mat,&rvec,&lvec)); 77089566063dSJacob Faibussowitsch PetscCall(VecSetRandom(rvec,NULL)); 77099566063dSJacob Faibussowitsch PetscCall(MatMult(mat,rvec,lvec)); 77109566063dSJacob Faibussowitsch PetscCall(VecScale(lvec,-1.0)); 77119566063dSJacob Faibussowitsch PetscCall(MatMultAdd(*mat_n,rvec,lvec,lvec)); 77129566063dSJacob Faibussowitsch PetscCall(VecNorm(lvec,NORM_INFINITY,&infty_error)); 77139566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error)); 77149566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rvec)); 77159566063dSJacob Faibussowitsch PetscCall(VecDestroy(&lvec)); 7716e7931f94SStefano Zampini } 771728143c3dSStefano Zampini #endif 7718e7931f94SStefano Zampini 771928143c3dSStefano Zampini /* assemble new additional is (if any) */ 772028143c3dSStefano Zampini if (nis) { 772128143c3dSStefano Zampini PetscInt **temp_idxs, *count_is, j, psum; 772228143c3dSStefano Zampini 77239566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_recvs, recv_req_idxs_is, MPI_STATUSES_IGNORE)); 77249566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nis, &count_is)); 772528143c3dSStefano Zampini ptr_idxs = recv_buffer_idxs_is; 772628143c3dSStefano Zampini psum = 0; 772728143c3dSStefano Zampini for (i = 0; i < n_recvs; i++) { 772828143c3dSStefano Zampini for (j = 0; j < nis; j++) { 772928143c3dSStefano Zampini PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */ 773028143c3dSStefano Zampini count_is[j] += plen; /* increment counting of buffer for j-th IS */ 773128143c3dSStefano Zampini psum += plen; 773228143c3dSStefano Zampini ptr_idxs += plen + 1; /* shift pointer to received data */ 773328143c3dSStefano Zampini } 773428143c3dSStefano Zampini } 77359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nis, &temp_idxs)); 77369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(psum, &temp_idxs[0])); 77378e3a54c0SPierre Jolivet for (i = 1; i < nis; i++) temp_idxs[i] = PetscSafePointerPlusOffset(temp_idxs[i - 1], count_is[i - 1]); 77389566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(count_is, nis)); 773928143c3dSStefano Zampini ptr_idxs = recv_buffer_idxs_is; 774028143c3dSStefano Zampini for (i = 0; i < n_recvs; i++) { 774128143c3dSStefano Zampini for (j = 0; j < nis; j++) { 774228143c3dSStefano Zampini PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */ 77439566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(&temp_idxs[j][count_is[j]], ptr_idxs + 1, plen)); 774428143c3dSStefano Zampini count_is[j] += plen; /* increment starting point of buffer for j-th IS */ 774528143c3dSStefano Zampini ptr_idxs += plen + 1; /* shift pointer to received data */ 774628143c3dSStefano Zampini } 774728143c3dSStefano Zampini } 774828143c3dSStefano Zampini for (i = 0; i < nis; i++) { 77499566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isarray[i])); 77509566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsInt(&count_is[i], temp_idxs[i])); 77519566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm_n, count_is[i], temp_idxs[i], PETSC_COPY_VALUES, &isarray[i])); 775228143c3dSStefano Zampini } 77539566063dSJacob Faibussowitsch PetscCall(PetscFree(count_is)); 77549566063dSJacob Faibussowitsch PetscCall(PetscFree(temp_idxs[0])); 77559566063dSJacob Faibussowitsch PetscCall(PetscFree(temp_idxs)); 775628143c3dSStefano Zampini } 7757e7931f94SStefano Zampini /* free workspace */ 77589566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_buffer_idxs_is)); 77599566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_sends, send_req_idxs, MPI_STATUSES_IGNORE)); 77609566063dSJacob Faibussowitsch PetscCall(PetscFree(send_buffer_idxs)); 77619566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_sends, send_req_vals, MPI_STATUSES_IGNORE)); 7762e7931f94SStefano Zampini if (isdense) { 77639566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(mat, &local_mat)); 77649566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(local_mat, &send_buffer_vals)); 77659566063dSJacob Faibussowitsch PetscCall(MatISRestoreLocalMat(mat, &local_mat)); 7766e7931f94SStefano Zampini } else { 77679566063dSJacob Faibussowitsch /* PetscCall(PetscFree(send_buffer_vals)); */ 7768e7931f94SStefano Zampini } 776928143c3dSStefano Zampini if (nis) { 77709566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_sends, send_req_idxs_is, MPI_STATUSES_IGNORE)); 77719566063dSJacob Faibussowitsch PetscCall(PetscFree(send_buffer_idxs_is)); 777228143c3dSStefano Zampini } 77731ae86dd6SStefano Zampini 77741ae86dd6SStefano Zampini if (nvecs) { 77759566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_recvs, recv_req_vecs, MPI_STATUSES_IGNORE)); 77769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(n_sends, send_req_vecs, MPI_STATUSES_IGNORE)); 77779566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(nnsp_vec[0], &send_buffer_vecs)); 77789566063dSJacob Faibussowitsch PetscCall(VecDestroy(&nnsp_vec[0])); 77799566063dSJacob Faibussowitsch PetscCall(VecCreate(comm_n, &nnsp_vec[0])); 77809566063dSJacob Faibussowitsch PetscCall(VecSetSizes(nnsp_vec[0], new_local_rows, PETSC_DECIDE)); 77819566063dSJacob Faibussowitsch PetscCall(VecSetType(nnsp_vec[0], VECSTANDARD)); 77821ae86dd6SStefano Zampini /* set values */ 77831ae86dd6SStefano Zampini ptr_vals = recv_buffer_vecs; 77841ae86dd6SStefano Zampini ptr_idxs = recv_buffer_idxs_local; 77859566063dSJacob Faibussowitsch PetscCall(VecGetArray(nnsp_vec[0], &send_buffer_vecs)); 77861ae86dd6SStefano Zampini for (i = 0; i < n_recvs; i++) { 77871ae86dd6SStefano Zampini PetscInt j; 7788ad540459SPierre Jolivet for (j = 0; j < *(ptr_idxs + 1); j++) send_buffer_vecs[*(ptr_idxs + 2 + j)] += *(ptr_vals + j); 77891ae86dd6SStefano Zampini ptr_idxs += olengths_idxs[i]; 77901ae86dd6SStefano Zampini ptr_vals += olengths_idxs[i] - 2; 77911ae86dd6SStefano Zampini } 77929566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(nnsp_vec[0], &send_buffer_vecs)); 77939566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(nnsp_vec[0])); 77949566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(nnsp_vec[0])); 77951ae86dd6SStefano Zampini } 77961ae86dd6SStefano Zampini 77979566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_buffer_vecs)); 77989566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_buffer_idxs_local)); 77999566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_req_idxs)); 78009566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_req_vals)); 78019566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_req_vecs)); 78029566063dSJacob Faibussowitsch PetscCall(PetscFree(recv_req_idxs_is)); 78039566063dSJacob Faibussowitsch PetscCall(PetscFree(send_req_idxs)); 78049566063dSJacob Faibussowitsch PetscCall(PetscFree(send_req_vals)); 78059566063dSJacob Faibussowitsch PetscCall(PetscFree(send_req_vecs)); 78069566063dSJacob Faibussowitsch PetscCall(PetscFree(send_req_idxs_is)); 78079566063dSJacob Faibussowitsch PetscCall(PetscFree(ilengths_vals)); 78089566063dSJacob Faibussowitsch PetscCall(PetscFree(ilengths_idxs)); 78099566063dSJacob Faibussowitsch PetscCall(PetscFree(olengths_vals)); 78109566063dSJacob Faibussowitsch PetscCall(PetscFree(olengths_idxs)); 78119566063dSJacob Faibussowitsch PetscCall(PetscFree(onodes)); 781228143c3dSStefano Zampini if (nis) { 78139566063dSJacob Faibussowitsch PetscCall(PetscFree(ilengths_idxs_is)); 78149566063dSJacob Faibussowitsch PetscCall(PetscFree(olengths_idxs_is)); 78159566063dSJacob Faibussowitsch PetscCall(PetscFree(onodes_is)); 781628143c3dSStefano Zampini } 78179566063dSJacob Faibussowitsch PetscCall(PetscSubcommDestroy(&subcomm)); 78186aad120cSJose E. Roman if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not participate */ 78199566063dSJacob Faibussowitsch PetscCall(MatDestroy(mat_n)); 782048a46eb9SPierre Jolivet for (i = 0; i < nis; i++) PetscCall(ISDestroy(&isarray[i])); 78211ae86dd6SStefano Zampini if (nvecs) { /* need to match VecDestroy nnsp_vec called in the other code path */ 78229566063dSJacob Faibussowitsch PetscCall(VecDestroy(&nnsp_vec[0])); 78231ae86dd6SStefano Zampini } 782453a05cb3SStefano Zampini *mat_n = NULL; 782528143c3dSStefano Zampini } 78263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7827e7931f94SStefano Zampini } 7828a57a6d2fSStefano Zampini 782912edc857SStefano Zampini /* temporary hack into ksp private data structure */ 7830af0996ceSBarry Smith #include <petsc/private/kspimpl.h> 783112edc857SStefano Zampini 7832d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc, PetscScalar *coarse_submat_vals) 7833d71ae5a4SJacob Faibussowitsch { 7834c8587f34SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 7835c8587f34SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 783620a2ab83SStefano Zampini Mat coarse_mat, coarse_mat_is, coarse_submat_dense; 78371ae86dd6SStefano Zampini Mat coarsedivudotp = NULL; 78381e0482f5SStefano Zampini Mat coarseG, t_coarse_mat_is; 78399881197aSStefano Zampini MatNullSpace CoarseNullSpace = NULL; 784020a2ab83SStefano Zampini ISLocalToGlobalMapping coarse_islg; 78414f819b78SStefano Zampini IS coarse_is, *isarray, corners; 78426e683305SStefano Zampini PetscInt i, im_active = -1, active_procs = -1; 784330368db7SStefano Zampini PetscInt nis, nisdofs, nisneu, nisvert; 7844e569e4e1SStefano Zampini PetscInt coarse_eqs_per_proc; 7845f9eb5b7dSStefano Zampini PC pc_temp; 7846c8587f34SStefano Zampini PCType coarse_pc_type; 7847c8587f34SStefano Zampini KSPType coarse_ksp_type; 7848f9eb5b7dSStefano Zampini PetscBool multilevel_requested, multilevel_allowed; 78497274672aSStefano Zampini PetscBool coarse_reuse; 78501e0482f5SStefano Zampini PetscInt ncoarse, nedcfield; 785168457ee5SStefano Zampini PetscBool compute_vecs = PETSC_FALSE; 785222bc73bbSStefano Zampini PetscScalar *array; 785357de7509SStefano Zampini MatReuse coarse_mat_reuse; 785457de7509SStefano Zampini PetscBool restr, full_restr, have_void; 7855e569e4e1SStefano Zampini PetscMPIInt size; 7856fdc09c96SStefano Zampini 7857c8587f34SStefano Zampini PetscFunctionBegin; 78589566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_CoarseSetUp[pcbddc->current_level], pc, 0, 0, 0)); 7859c8587f34SStefano Zampini /* Assign global numbering to coarse dofs */ 786068457ee5SStefano 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 */ 7861fa7f1dd8SStefano Zampini PetscInt ocoarse_size; 78625a75c04eSSatish Balay compute_vecs = PETSC_TRUE; 78637de4f681Sstefano_zampini 78647de4f681Sstefano_zampini pcbddc->new_primal_space = PETSC_TRUE; 7865fa7f1dd8SStefano Zampini ocoarse_size = pcbddc->coarse_size; 78669566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->global_primal_indices)); 78679566063dSJacob Faibussowitsch PetscCall(PCBDDCComputePrimalNumbering(pc, &pcbddc->coarse_size, &pcbddc->global_primal_indices)); 7868f4ddd8eeSStefano Zampini /* see if we can avoid some work */ 7869fa7f1dd8SStefano Zampini if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */ 787051bea450SStefano Zampini /* if the coarse size is different or we are using adaptive selection, better to not reuse the coarse matrix */ 787151bea450SStefano Zampini if (ocoarse_size != pcbddc->coarse_size || pcbddc->adaptive_selection) { 78729566063dSJacob Faibussowitsch PetscCall(KSPReset(pcbddc->coarse_ksp)); 7873fa7f1dd8SStefano Zampini coarse_reuse = PETSC_FALSE; 7874fa7f1dd8SStefano Zampini } else { /* we can safely reuse already computed coarse matrix */ 7875fa7f1dd8SStefano Zampini coarse_reuse = PETSC_TRUE; 7876f4ddd8eeSStefano Zampini } 7877fa7f1dd8SStefano Zampini } else { /* there's no coarse ksp, so we need to create the coarse matrix too */ 7878fa7f1dd8SStefano Zampini coarse_reuse = PETSC_FALSE; 7879f4ddd8eeSStefano Zampini } 788070cf5478SStefano Zampini /* reset any subassembling information */ 788148a46eb9SPierre Jolivet if (!coarse_reuse || pcbddc->recompute_topography) PetscCall(ISDestroy(&pcbddc->coarse_subassembling)); 78826e683305SStefano Zampini } else { /* primal space is unchanged, so we can reuse coarse matrix */ 7883fa7f1dd8SStefano Zampini coarse_reuse = PETSC_TRUE; 7884f4ddd8eeSStefano Zampini } 788557de7509SStefano Zampini if (coarse_reuse && pcbddc->coarse_ksp) { 78869566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(pcbddc->coarse_ksp, &coarse_mat, NULL)); 78879566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coarse_mat)); 788857de7509SStefano Zampini coarse_mat_reuse = MAT_REUSE_MATRIX; 788918a45a71SStefano Zampini } else { 789057de7509SStefano Zampini coarse_mat = NULL; 789157de7509SStefano Zampini coarse_mat_reuse = MAT_INITIAL_MATRIX; 78926e683305SStefano Zampini } 7893e7931f94SStefano Zampini 7894abbbba34SStefano Zampini /* creates temporary l2gmap and IS for coarse indexes */ 78959566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), pcbddc->local_primal_size, pcbddc->global_primal_indices, PETSC_COPY_VALUES, &coarse_is)); 78969566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(coarse_is, &coarse_islg)); 7897abbbba34SStefano Zampini 7898abbbba34SStefano Zampini /* creates temporary MATIS object for coarse matrix */ 78999566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, pcbddc->local_primal_size, pcbddc->local_primal_size, coarse_submat_vals, &coarse_submat_dense)); 79009566063dSJacob Faibussowitsch PetscCall(MatCreateIS(PetscObjectComm((PetscObject)pc), 1, PETSC_DECIDE, PETSC_DECIDE, pcbddc->coarse_size, pcbddc->coarse_size, coarse_islg, coarse_islg, &t_coarse_mat_is)); 79019566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(t_coarse_mat_is, coarse_submat_dense)); 79029566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(t_coarse_mat_is, MAT_FINAL_ASSEMBLY)); 79039566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(t_coarse_mat_is, MAT_FINAL_ASSEMBLY)); 79049566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_submat_dense)); 7905abbbba34SStefano Zampini 790657de7509SStefano Zampini /* count "active" (i.e. with positive local size) and "void" processes */ 7907*f4f49eeaSPierre Jolivet im_active = !!pcis->n; 79081c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&im_active, &active_procs, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)pc))); 790957de7509SStefano Zampini 791014f0bfb9SStefano Zampini /* determine number of processes partecipating to coarse solver and compute subassembling pattern */ 791128d58a37SPierre Jolivet /* restr : whether we want to exclude senders (which are not receivers) from the subassembling pattern */ 791257de7509SStefano Zampini /* full_restr : just use the receivers from the subassembling pattern */ 79139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size)); 791457de7509SStefano Zampini coarse_mat_is = NULL; 791557de7509SStefano Zampini multilevel_allowed = PETSC_FALSE; 791657de7509SStefano Zampini multilevel_requested = PETSC_FALSE; 7917e569e4e1SStefano Zampini coarse_eqs_per_proc = PetscMin(PetscMax(pcbddc->coarse_size, 1), pcbddc->coarse_eqs_per_proc); 7918ce64c636SStefano Zampini if (coarse_eqs_per_proc < 0) coarse_eqs_per_proc = pcbddc->coarse_size; 791957de7509SStefano Zampini if (pcbddc->current_level < pcbddc->max_levels) multilevel_requested = PETSC_TRUE; 7920e569e4e1SStefano Zampini if (pcbddc->coarse_size <= pcbddc->coarse_eqs_limit) multilevel_requested = PETSC_FALSE; 792157de7509SStefano Zampini if (multilevel_requested) { 792257de7509SStefano Zampini ncoarse = active_procs / pcbddc->coarsening_ratio; 792357de7509SStefano Zampini restr = PETSC_FALSE; 792457de7509SStefano Zampini full_restr = PETSC_FALSE; 792557de7509SStefano Zampini } else { 7926e569e4e1SStefano Zampini ncoarse = pcbddc->coarse_size / coarse_eqs_per_proc + !!(pcbddc->coarse_size % coarse_eqs_per_proc); 792757de7509SStefano Zampini restr = PETSC_TRUE; 792857de7509SStefano Zampini full_restr = PETSC_TRUE; 792957de7509SStefano Zampini } 7930e569e4e1SStefano Zampini if (!pcbddc->coarse_size || size == 1) multilevel_allowed = multilevel_requested = restr = full_restr = PETSC_FALSE; 793157de7509SStefano Zampini ncoarse = PetscMax(1, ncoarse); 793257de7509SStefano Zampini if (!pcbddc->coarse_subassembling) { 7933a198735bSStefano Zampini if (pcbddc->coarsening_ratio > 1) { 7934bb360cb4SStefano Zampini if (multilevel_requested) { 79359566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISGetSubassemblingPattern(pc->pmat, &ncoarse, pcbddc->coarse_adj_red, &pcbddc->coarse_subassembling, &have_void)); 7936bb360cb4SStefano Zampini } else { 79379566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISGetSubassemblingPattern(t_coarse_mat_is, &ncoarse, pcbddc->coarse_adj_red, &pcbddc->coarse_subassembling, &have_void)); 7938bb360cb4SStefano Zampini } 7939a198735bSStefano Zampini } else { 79407de4f681Sstefano_zampini PetscMPIInt rank; 794128d58a37SPierre Jolivet 79429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc), &rank)); 7943e569e4e1SStefano Zampini have_void = (active_procs == (PetscInt)size) ? PETSC_FALSE : PETSC_TRUE; 79449566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)pc), 1, rank, 1, &pcbddc->coarse_subassembling)); 7945a198735bSStefano Zampini } 794657de7509SStefano Zampini } else { /* if a subassembling pattern exists, then we can reuse the coarse ksp and compute the number of process involved */ 794757de7509SStefano Zampini PetscInt psum; 794857de7509SStefano Zampini if (pcbddc->coarse_ksp) psum = 1; 794957de7509SStefano Zampini else psum = 0; 79501c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&psum, &ncoarse, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)pc))); 7951075e25bcSStefano Zampini have_void = ncoarse < size ? PETSC_TRUE : PETSC_FALSE; 795257de7509SStefano Zampini } 795357de7509SStefano Zampini /* determine if we can go multilevel */ 795457de7509SStefano Zampini if (multilevel_requested) { 795557de7509SStefano Zampini if (ncoarse > 1) multilevel_allowed = PETSC_TRUE; /* found enough processes */ 795657de7509SStefano Zampini else restr = full_restr = PETSC_TRUE; /* 1 subdomain, use a direct solver */ 795757de7509SStefano Zampini } 795857de7509SStefano Zampini if (multilevel_allowed && have_void) restr = PETSC_TRUE; 795957de7509SStefano Zampini 7960e4d548c7SStefano Zampini /* dump subassembling pattern */ 796148a46eb9SPierre Jolivet if (pcbddc->dbg_flag && multilevel_allowed) PetscCall(ISView(pcbddc->coarse_subassembling, pcbddc->dbg_viewer)); 79626e683305SStefano Zampini /* compute dofs splitting and neumann boundaries for coarse dofs */ 79631e0482f5SStefano Zampini nedcfield = -1; 79644f819b78SStefano Zampini corners = NULL; 79658966356dSPierre Jolivet if (multilevel_allowed && !coarse_reuse && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal || pcbddc->nedclocal || pcbddc->corner_selected)) { /* protects from unneeded computations */ 79666e683305SStefano Zampini PetscInt *tidxs, *tidxs2, nout, tsize, i; 79676e683305SStefano Zampini const PetscInt *idxs; 79686e683305SStefano Zampini ISLocalToGlobalMapping tmap; 79696e683305SStefano Zampini 79706e683305SStefano Zampini /* create map between primal indices (in local representative ordering) and local primal numbering */ 79719566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PETSC_COMM_SELF, 1, pcbddc->local_primal_size, pcbddc->primal_indices_local_idxs, PETSC_COPY_VALUES, &tmap)); 79726e683305SStefano Zampini /* allocate space for temporary storage */ 79739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->local_primal_size, &tidxs)); 79749566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->local_primal_size, &tidxs2)); 79756e683305SStefano Zampini /* allocate for IS array */ 79766e683305SStefano Zampini nisdofs = pcbddc->n_ISForDofsLocal; 79771e0482f5SStefano Zampini if (pcbddc->nedclocal) { 79781e0482f5SStefano Zampini if (pcbddc->nedfield > -1) { 79791e0482f5SStefano Zampini nedcfield = pcbddc->nedfield; 79801e0482f5SStefano Zampini } else { 79811e0482f5SStefano Zampini nedcfield = 0; 798263a3b9bcSJacob Faibussowitsch PetscCheck(!nisdofs, PetscObjectComm((PetscObject)pc), PETSC_ERR_PLIB, "This should not happen (%" PetscInt_FMT ")", nisdofs); 79831e0482f5SStefano Zampini nisdofs = 1; 79841e0482f5SStefano Zampini } 79851e0482f5SStefano Zampini } 79866e683305SStefano Zampini nisneu = !!pcbddc->NeumannBoundariesLocal; 798727b6a85dSStefano Zampini nisvert = 0; /* nisvert is not used */ 798830368db7SStefano Zampini nis = nisdofs + nisneu + nisvert; 79899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nis, &isarray)); 79906e683305SStefano Zampini /* dofs splitting */ 79916e683305SStefano Zampini for (i = 0; i < nisdofs; i++) { 79929566063dSJacob Faibussowitsch /* PetscCall(ISView(pcbddc->ISForDofsLocal[i],0)); */ 79931e0482f5SStefano Zampini if (nedcfield != i) { 79949566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->ISForDofsLocal[i], &tsize)); 79959566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->ISForDofsLocal[i], &idxs)); 79969566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(tmap, IS_GTOLM_DROP, tsize, idxs, &nout, tidxs)); 79979566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->ISForDofsLocal[i], &idxs)); 79981e0482f5SStefano Zampini } else { 79999566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->nedclocal, &tsize)); 80009566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->nedclocal, &idxs)); 80019566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(tmap, IS_GTOLM_DROP, tsize, idxs, &nout, tidxs)); 800263a3b9bcSJacob Faibussowitsch PetscCheck(tsize == nout, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Failed when mapping coarse nedelec field! %" PetscInt_FMT " != %" PetscInt_FMT, tsize, nout); 80039566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->nedclocal, &idxs)); 80041e0482f5SStefano Zampini } 80059566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(coarse_islg, nout, tidxs, tidxs2)); 80069566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), nout, tidxs2, PETSC_COPY_VALUES, &isarray[i])); 80079566063dSJacob Faibussowitsch /* PetscCall(ISView(isarray[i],0)); */ 80086e683305SStefano Zampini } 80096e683305SStefano Zampini /* neumann boundaries */ 80106e683305SStefano Zampini if (pcbddc->NeumannBoundariesLocal) { 80119566063dSJacob Faibussowitsch /* PetscCall(ISView(pcbddc->NeumannBoundariesLocal,0)); */ 80129566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pcbddc->NeumannBoundariesLocal, &tsize)); 80139566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pcbddc->NeumannBoundariesLocal, &idxs)); 80149566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(tmap, IS_GTOLM_DROP, tsize, idxs, &nout, tidxs)); 80159566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pcbddc->NeumannBoundariesLocal, &idxs)); 80169566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(coarse_islg, nout, tidxs, tidxs2)); 80179566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), nout, tidxs2, PETSC_COPY_VALUES, &isarray[nisdofs])); 80189566063dSJacob Faibussowitsch /* PetscCall(ISView(isarray[nisdofs],0)); */ 80196e683305SStefano Zampini } 80204f819b78SStefano Zampini /* coordinates */ 80214f819b78SStefano Zampini if (pcbddc->corner_selected) { 80229566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &corners)); 80239566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(corners, &tsize)); 80249566063dSJacob Faibussowitsch PetscCall(ISGetIndices(corners, &idxs)); 80259566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(tmap, IS_GTOLM_DROP, tsize, idxs, &nout, tidxs)); 802663a3b9bcSJacob Faibussowitsch PetscCheck(tsize == nout, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Failed when mapping corners! %" PetscInt_FMT " != %" PetscInt_FMT, tsize, nout); 80279566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(corners, &idxs)); 80289566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &corners)); 80299566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(coarse_islg, nout, tidxs, tidxs2)); 80309566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), nout, tidxs2, PETSC_COPY_VALUES, &corners)); 80314f819b78SStefano Zampini } 80329566063dSJacob Faibussowitsch PetscCall(PetscFree(tidxs)); 80339566063dSJacob Faibussowitsch PetscCall(PetscFree(tidxs2)); 80349566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&tmap)); 80356e683305SStefano Zampini } else { 80366e683305SStefano Zampini nis = 0; 80376e683305SStefano Zampini nisdofs = 0; 80386e683305SStefano Zampini nisneu = 0; 803930368db7SStefano Zampini nisvert = 0; 80406e683305SStefano Zampini isarray = NULL; 80416e683305SStefano Zampini } 80426e683305SStefano Zampini /* destroy no longer needed map */ 80439566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&coarse_islg)); 80446e683305SStefano Zampini 804557de7509SStefano Zampini /* subassemble */ 804657de7509SStefano Zampini if (multilevel_allowed) { 80471ae86dd6SStefano Zampini Vec vp[1]; 80481ae86dd6SStefano Zampini PetscInt nvecs = 0; 804957de7509SStefano Zampini PetscBool reuse, reuser; 80501ae86dd6SStefano Zampini 805157de7509SStefano Zampini if (coarse_mat) reuse = PETSC_TRUE; 805257de7509SStefano Zampini else reuse = PETSC_FALSE; 80531c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&reuse, &reuser, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 80541ae86dd6SStefano Zampini vp[0] = NULL; 80551ae86dd6SStefano Zampini if (pcbddc->benign_have_null) { /* propagate no-net-flux quadrature to coarser level */ 80569566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pc), &vp[0])); 80579566063dSJacob Faibussowitsch PetscCall(VecSetSizes(vp[0], pcbddc->local_primal_size, PETSC_DECIDE)); 80589566063dSJacob Faibussowitsch PetscCall(VecSetType(vp[0], VECSTANDARD)); 80591ae86dd6SStefano Zampini nvecs = 1; 80601ae86dd6SStefano Zampini 80611ae86dd6SStefano Zampini if (pcbddc->divudotp) { 8062a198735bSStefano Zampini Mat B, loc_divudotp; 80631ae86dd6SStefano Zampini Vec v, p; 80641ae86dd6SStefano Zampini IS dummy; 80651ae86dd6SStefano Zampini PetscInt np; 80661ae86dd6SStefano Zampini 80679566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(pcbddc->divudotp, &loc_divudotp)); 80689566063dSJacob Faibussowitsch PetscCall(MatGetSize(loc_divudotp, &np, NULL)); 80699566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, np, 0, 1, &dummy)); 80709566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(loc_divudotp, dummy, pcis->is_B_local, MAT_INITIAL_MATRIX, &B)); 80719566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(B, &v, &p)); 80729566063dSJacob Faibussowitsch PetscCall(VecSet(p, 1.)); 80739566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(B, p, v)); 80749566063dSJacob Faibussowitsch PetscCall(VecDestroy(&p)); 80759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 80769566063dSJacob Faibussowitsch PetscCall(VecGetArray(vp[0], &array)); 80779566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(pcbddc->vec1_P, array)); 80789566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->coarse_phi_B, v, pcbddc->vec1_P)); 80799566063dSJacob Faibussowitsch PetscCall(VecResetArray(pcbddc->vec1_P)); 80809566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(vp[0], &array)); 80819566063dSJacob Faibussowitsch PetscCall(ISDestroy(&dummy)); 80829566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 808374e2c79eSStefano Zampini } 80841ae86dd6SStefano Zampini } 80851ae86dd6SStefano Zampini if (reuser) { 80869566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISSubassemble(t_coarse_mat_is, pcbddc->coarse_subassembling, 0, restr, full_restr, PETSC_TRUE, &coarse_mat, nis, isarray, nvecs, vp)); 808774e2c79eSStefano Zampini } else { 80889566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISSubassemble(t_coarse_mat_is, pcbddc->coarse_subassembling, 0, restr, full_restr, PETSC_FALSE, &coarse_mat_is, nis, isarray, nvecs, vp)); 80891ae86dd6SStefano Zampini } 80901ae86dd6SStefano Zampini if (vp[0]) { /* vp[0] could have been placed on a different set of processes */ 80911683a169SBarry Smith PetscScalar *arraym; 80921683a169SBarry Smith const PetscScalar *arrayv; 80931ae86dd6SStefano Zampini PetscInt nl; 80949566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(vp[0], &nl)); 80959566063dSJacob Faibussowitsch PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, 1, nl, NULL, &coarsedivudotp)); 80969566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(coarsedivudotp, &arraym)); 80979566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vp[0], &arrayv)); 80989566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(arraym, arrayv, nl)); 80999566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vp[0], &arrayv)); 81009566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(coarsedivudotp, &arraym)); 81019566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vp[0])); 8102a198735bSStefano Zampini } else { 81039566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, 0, 0, 1, NULL, &coarsedivudotp)); 81041ae86dd6SStefano Zampini } 81051ae86dd6SStefano Zampini } else { 81069566063dSJacob Faibussowitsch PetscCall(PCBDDCMatISSubassemble(t_coarse_mat_is, pcbddc->coarse_subassembling, 0, restr, full_restr, PETSC_FALSE, &coarse_mat_is, 0, NULL, 0, NULL)); 81076e683305SStefano Zampini } 810857de7509SStefano Zampini if (coarse_mat_is || coarse_mat) { 810957de7509SStefano Zampini if (!multilevel_allowed) { 81109566063dSJacob Faibussowitsch PetscCall(MatConvert(coarse_mat_is, MATAIJ, coarse_mat_reuse, &coarse_mat)); 81116e683305SStefano Zampini } else { 811257de7509SStefano Zampini /* if this matrix is present, it means we are not reusing the coarse matrix */ 811357de7509SStefano Zampini if (coarse_mat_is) { 811428b400f6SJacob Faibussowitsch PetscCheck(!coarse_mat, PetscObjectComm((PetscObject)coarse_mat_is), PETSC_ERR_PLIB, "This should not happen"); 81159566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coarse_mat_is)); 811657de7509SStefano Zampini coarse_mat = coarse_mat_is; 811757de7509SStefano Zampini } 8118779c1cceSStefano Zampini } 8119779c1cceSStefano Zampini } 81209566063dSJacob Faibussowitsch PetscCall(MatDestroy(&t_coarse_mat_is)); 81219566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_mat_is)); 81226e683305SStefano Zampini 81236e683305SStefano Zampini /* create local to global scatters for coarse problem */ 812468457ee5SStefano Zampini if (compute_vecs) { 81256e683305SStefano Zampini PetscInt lrows; 81269566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->coarse_vec)); 812757de7509SStefano Zampini if (coarse_mat) { 81289566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(coarse_mat, &lrows, NULL)); 81296e683305SStefano Zampini } else { 81306e683305SStefano Zampini lrows = 0; 81316e683305SStefano Zampini } 81329566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pc), &pcbddc->coarse_vec)); 81339566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pcbddc->coarse_vec, lrows, PETSC_DECIDE)); 81349566063dSJacob Faibussowitsch PetscCall(VecSetType(pcbddc->coarse_vec, coarse_mat ? coarse_mat->defaultvectype : VECSTANDARD)); 81359566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&pcbddc->coarse_loc_to_glob)); 81369566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(pcbddc->vec1_P, NULL, pcbddc->coarse_vec, coarse_is, &pcbddc->coarse_loc_to_glob)); 81376e683305SStefano Zampini } 81389566063dSJacob Faibussowitsch PetscCall(ISDestroy(&coarse_is)); 8139c8587f34SStefano Zampini 8140f9eb5b7dSStefano Zampini /* set defaults for coarse KSP and PC */ 8141f9eb5b7dSStefano Zampini if (multilevel_allowed) { 8142f9eb5b7dSStefano Zampini coarse_ksp_type = KSPRICHARDSON; 8143f9eb5b7dSStefano Zampini coarse_pc_type = PCBDDC; 8144f9eb5b7dSStefano Zampini } else { 8145f9eb5b7dSStefano Zampini coarse_ksp_type = KSPPREONLY; 8146f9eb5b7dSStefano Zampini coarse_pc_type = PCREDUNDANT; 8147c8587f34SStefano Zampini } 8148c8587f34SStefano Zampini 81496e683305SStefano Zampini /* print some info if requested */ 81506e683305SStefano Zampini if (pcbddc->dbg_flag) { 81516e683305SStefano Zampini if (!multilevel_allowed) { 81529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 81536e683305SStefano Zampini if (multilevel_requested) { 815463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Not enough active processes on level %" PetscInt_FMT " (active processes %" PetscInt_FMT ", coarsening ratio %" PetscInt_FMT ")\n", pcbddc->current_level, active_procs, pcbddc->coarsening_ratio)); 81556e683305SStefano Zampini } else if (pcbddc->max_levels) { 815663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Maximum number of requested levels reached (%" PetscInt_FMT ")\n", pcbddc->max_levels)); 81576e683305SStefano Zampini } 81589566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 81596e683305SStefano Zampini } 81606e683305SStefano Zampini } 81616e683305SStefano Zampini 81621e0482f5SStefano Zampini /* communicate coarse discrete gradient */ 81631e0482f5SStefano Zampini coarseG = NULL; 81641e0482f5SStefano Zampini if (pcbddc->nedcG && multilevel_allowed) { 81651e0482f5SStefano Zampini MPI_Comm ccomm; 81661e0482f5SStefano Zampini if (coarse_mat) { 81671e0482f5SStefano Zampini ccomm = PetscObjectComm((PetscObject)coarse_mat); 81681e0482f5SStefano Zampini } else { 81691e0482f5SStefano Zampini ccomm = MPI_COMM_NULL; 81701e0482f5SStefano Zampini } 81719566063dSJacob Faibussowitsch PetscCall(MatMPIAIJRestrict(pcbddc->nedcG, ccomm, &coarseG)); 81721e0482f5SStefano Zampini } 81731e0482f5SStefano Zampini 8174f9eb5b7dSStefano Zampini /* create the coarse KSP object only once with defaults */ 817557de7509SStefano Zampini if (coarse_mat) { 817628d58a37SPierre Jolivet PetscBool isredundant, isbddc, force, valid; 81776a1308c2SStefano Zampini PetscViewer dbg_viewer = NULL; 8178b94d7dedSBarry Smith PetscBool isset, issym, isher, isspd; 81797274672aSStefano Zampini 81806e683305SStefano Zampini if (pcbddc->dbg_flag) { 818157de7509SStefano Zampini dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat)); 81829566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIAddTab(dbg_viewer, 2 * pcbddc->current_level)); 81836e683305SStefano Zampini } 8184f9eb5b7dSStefano Zampini if (!pcbddc->coarse_ksp) { 8185312be037SStefano Zampini char prefix[256], str_level[16]; 8186e604994aSStefano Zampini size_t len; 81871e0482f5SStefano Zampini 81889566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)coarse_mat), &pcbddc->coarse_ksp)); 81893821be0aSBarry Smith PetscCall(KSPSetNestLevel(pcbddc->coarse_ksp, pc->kspnestlevel)); 81909566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(pcbddc->coarse_ksp, pc->erroriffailure)); 81919566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp, (PetscObject)pc, 1)); 81929566063dSJacob Faibussowitsch PetscCall(KSPSetTolerances(pcbddc->coarse_ksp, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, 1)); 81939566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(pcbddc->coarse_ksp, coarse_mat, coarse_mat)); 81949566063dSJacob Faibussowitsch PetscCall(KSPSetType(pcbddc->coarse_ksp, coarse_ksp_type)); 81959566063dSJacob Faibussowitsch PetscCall(KSPSetNormType(pcbddc->coarse_ksp, KSP_NORM_NONE)); 81969566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &pc_temp)); 81971e0482f5SStefano Zampini /* TODO is this logic correct? should check for coarse_mat type */ 81989566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, coarse_pc_type)); 8199e604994aSStefano Zampini /* prefix */ 8200c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(prefix, "", sizeof(prefix))); 8201c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(str_level, "", sizeof(str_level))); 8202e604994aSStefano Zampini if (!pcbddc->current_level) { 82039566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(prefix, ((PetscObject)pc)->prefix, sizeof(prefix))); 82049566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, "pc_bddc_coarse_", sizeof(prefix))); 8205c8587f34SStefano Zampini } else { 82069566063dSJacob Faibussowitsch PetscCall(PetscStrlen(((PetscObject)pc)->prefix, &len)); 8207312be037SStefano Zampini if (pcbddc->current_level > 1) len -= 3; /* remove "lX_" with X level number */ 8208312be037SStefano Zampini if (pcbddc->current_level > 10) len -= 1; /* remove another char from level number */ 8209a126751eSBarry Smith /* Nonstandard use of PetscStrncpy() to copy only a portion of the string */ 82109566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(prefix, ((PetscObject)pc)->prefix, len + 1)); 8211*f4f49eeaSPierre Jolivet PetscCall(PetscSNPrintf(str_level, sizeof(str_level), "l%d_", (int)pcbddc->current_level)); 82129566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(prefix, str_level, sizeof(prefix))); 8213e604994aSStefano Zampini } 82149566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(pcbddc->coarse_ksp, prefix)); 82153e3c6dadSStefano Zampini /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */ 82169566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLevel(pc_temp, pcbddc->current_level + 1)); 82179566063dSJacob Faibussowitsch PetscCall(PCBDDCSetCoarseningRatio(pc_temp, pcbddc->coarsening_ratio)); 82189566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLevels(pc_temp, pcbddc->max_levels)); 8219f9eb5b7dSStefano Zampini /* allow user customization */ 82209566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(pcbddc->coarse_ksp)); 8221e569e4e1SStefano Zampini /* get some info after set from options */ 82229566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &pc_temp)); 822328d58a37SPierre Jolivet /* multilevel cannot be done with coarse PC different from BDDC, NN, HPDDM, unless forced to */ 822428d58a37SPierre Jolivet force = PETSC_FALSE; 82259566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)pc_temp)->prefix, "-pc_type_forced", &force, NULL)); 82269566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)pc_temp, &valid, PCBDDC, PCNN, PCHPDDM, "")); 82279566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp, PCBDDC, &isbddc)); 822828d58a37SPierre Jolivet if (multilevel_allowed && !force && !valid) { 8229e569e4e1SStefano Zampini isbddc = PETSC_TRUE; 82309566063dSJacob Faibussowitsch PetscCall(PCSetType(pc_temp, PCBDDC)); 82319566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLevel(pc_temp, pcbddc->current_level + 1)); 82329566063dSJacob Faibussowitsch PetscCall(PCBDDCSetCoarseningRatio(pc_temp, pcbddc->coarsening_ratio)); 82339566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLevels(pc_temp, pcbddc->max_levels)); 82344f819b78SStefano Zampini if (pc_temp->ops->setfromoptions) { /* need to setfromoptions again, skipping the pc_type */ 8235d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)pc_temp); 8236dbbe0bcdSBarry Smith PetscCall((*pc_temp->ops->setfromoptions)(pc_temp, PetscOptionsObject)); 8237dbbe0bcdSBarry Smith PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)pc_temp, PetscOptionsObject)); 8238d0609cedSBarry Smith PetscOptionsEnd(); 82394f819b78SStefano Zampini pc_temp->setfromoptionscalled++; 82404f819b78SStefano Zampini } 8241e569e4e1SStefano Zampini } 82423e3c6dadSStefano Zampini } 82433e3c6dadSStefano Zampini /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */ 82449566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &pc_temp)); 82453e3c6dadSStefano Zampini if (nisdofs) { 82469566063dSJacob Faibussowitsch PetscCall(PCBDDCSetDofsSplitting(pc_temp, nisdofs, isarray)); 824748a46eb9SPierre Jolivet for (i = 0; i < nisdofs; i++) PetscCall(ISDestroy(&isarray[i])); 82483e3c6dadSStefano Zampini } 82493e3c6dadSStefano Zampini if (nisneu) { 82509566063dSJacob Faibussowitsch PetscCall(PCBDDCSetNeumannBoundaries(pc_temp, isarray[nisdofs])); 82519566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isarray[nisdofs])); 8252312be037SStefano Zampini } 825330368db7SStefano Zampini if (nisvert) { 82549566063dSJacob Faibussowitsch PetscCall(PCBDDCSetPrimalVerticesIS(pc_temp, isarray[nis - 1])); 82559566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isarray[nis - 1])); 825630368db7SStefano Zampini } 82571baa6e33SBarry Smith if (coarseG) PetscCall(PCBDDCSetDiscreteGradient(pc_temp, coarseG, 1, nedcfield, PETSC_FALSE, PETSC_TRUE)); 8258f9eb5b7dSStefano Zampini 8259f9eb5b7dSStefano Zampini /* get some info after set from options */ 82609566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp, PCBDDC, &isbddc)); 82614f819b78SStefano Zampini 8262b76f3995Sstefano_zampini /* multilevel can only be requested via -pc_bddc_levels or PCBDDCSetLevels */ 826348a46eb9SPierre Jolivet if (isbddc && !multilevel_allowed) PetscCall(PCSetType(pc_temp, coarse_pc_type)); 826428d58a37SPierre Jolivet /* multilevel cannot be done with coarse PC different from BDDC, NN, HPDDM, unless forced to */ 826528d58a37SPierre Jolivet force = PETSC_FALSE; 82669566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)pc_temp)->prefix, "-pc_type_forced", &force, NULL)); 82679566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)pc_temp, &valid, PCBDDC, PCNN, PCHPDDM, "")); 826848a46eb9SPierre Jolivet if (multilevel_requested && multilevel_allowed && !valid && !force) PetscCall(PCSetType(pc_temp, PCBDDC)); 82699566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp, PCREDUNDANT, &isredundant)); 82704f3a063dSStefano Zampini if (isredundant) { 82714f3a063dSStefano Zampini KSP inner_ksp; 82724f3a063dSStefano Zampini PC inner_pc; 82739326c5c6Sstefano_zampini 82749566063dSJacob Faibussowitsch PetscCall(PCRedundantGetKSP(pc_temp, &inner_ksp)); 82759566063dSJacob Faibussowitsch PetscCall(KSPGetPC(inner_ksp, &inner_pc)); 82764f3a063dSStefano Zampini } 8277f9eb5b7dSStefano Zampini 827857de7509SStefano Zampini /* parameters which miss an API */ 82799566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc_temp, PCBDDC, &isbddc)); 828057de7509SStefano Zampini if (isbddc) { 8281720d30f9SStefano Zampini PC_BDDC *pcbddc_coarse = (PC_BDDC *)pc_temp->data; 82827274672aSStefano Zampini 8283720d30f9SStefano Zampini pcbddc_coarse->detect_disconnected = PETSC_TRUE; 828457de7509SStefano Zampini pcbddc_coarse->coarse_eqs_per_proc = pcbddc->coarse_eqs_per_proc; 8285e569e4e1SStefano Zampini pcbddc_coarse->coarse_eqs_limit = pcbddc->coarse_eqs_limit; 828627b6a85dSStefano Zampini pcbddc_coarse->benign_saddle_point = pcbddc->benign_have_null; 828727b6a85dSStefano Zampini if (pcbddc_coarse->benign_saddle_point) { 8288a198735bSStefano Zampini Mat coarsedivudotp_is; 8289a198735bSStefano Zampini ISLocalToGlobalMapping l2gmap, rl2g, cl2g; 8290a198735bSStefano Zampini IS row, col; 8291a198735bSStefano Zampini const PetscInt *gidxs; 8292a198735bSStefano Zampini PetscInt n, st, M, N; 8293a198735bSStefano Zampini 82949566063dSJacob Faibussowitsch PetscCall(MatGetSize(coarsedivudotp, &n, NULL)); 82959566063dSJacob Faibussowitsch PetscCallMPI(MPI_Scan(&n, &st, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)coarse_mat))); 8296a198735bSStefano Zampini st = st - n; 82979566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)coarse_mat), 1, st, 1, &row)); 82989566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(coarse_mat, &l2gmap, NULL)); 82999566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(l2gmap, &n)); 83009566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(l2gmap, &gidxs)); 83019566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)coarse_mat), n, gidxs, PETSC_COPY_VALUES, &col)); 83029566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(l2gmap, &gidxs)); 83039566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(row, &rl2g)); 83049566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(col, &cl2g)); 83059566063dSJacob Faibussowitsch PetscCall(ISGetSize(row, &M)); 83069566063dSJacob Faibussowitsch PetscCall(MatGetSize(coarse_mat, &N, NULL)); 83079566063dSJacob Faibussowitsch PetscCall(ISDestroy(&row)); 83089566063dSJacob Faibussowitsch PetscCall(ISDestroy(&col)); 83099566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)coarse_mat), &coarsedivudotp_is)); 83109566063dSJacob Faibussowitsch PetscCall(MatSetType(coarsedivudotp_is, MATIS)); 83119566063dSJacob Faibussowitsch PetscCall(MatSetSizes(coarsedivudotp_is, PETSC_DECIDE, PETSC_DECIDE, M, N)); 83129566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(coarsedivudotp_is, rl2g, cl2g)); 83139566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 83149566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 83159566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(coarsedivudotp_is, coarsedivudotp)); 83169566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarsedivudotp)); 83179566063dSJacob Faibussowitsch PetscCall(PCBDDCSetDivergenceMat(pc_temp, coarsedivudotp_is, PETSC_FALSE, NULL)); 83189566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarsedivudotp_is)); 8319720d30f9SStefano Zampini pcbddc_coarse->adaptive_userdefined = PETSC_TRUE; 8320bd2a564bSStefano Zampini if (pcbddc->adaptive_threshold[0] == 0.0) pcbddc_coarse->deluxe_zerorows = PETSC_TRUE; 8321720d30f9SStefano Zampini } 8322d4d8cf7bSStefano Zampini } 83239881197aSStefano Zampini 83243301b35fSStefano Zampini /* propagate symmetry info of coarse matrix */ 83259566063dSJacob Faibussowitsch PetscCall(MatSetOption(coarse_mat, MAT_STRUCTURALLY_SYMMETRIC, PETSC_TRUE)); 8326b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(pc->pmat, &isset, &issym)); 8327b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(coarse_mat, MAT_SYMMETRIC, issym)); 8328b94d7dedSBarry Smith PetscCall(MatIsHermitianKnown(pc->pmat, &isset, &isher)); 8329b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(coarse_mat, MAT_HERMITIAN, isher)); 8330b94d7dedSBarry Smith PetscCall(MatIsSPDKnown(pc->pmat, &isset, &isspd)); 8331b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(coarse_mat, MAT_SPD, isspd)); 8332b94d7dedSBarry Smith 833348a46eb9SPierre Jolivet if (pcbddc->benign_saddle_point && !pcbddc->benign_have_null) PetscCall(MatSetOption(coarse_mat, MAT_SPD, PETSC_TRUE)); 83346e683305SStefano Zampini /* set operators */ 83359566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(coarse_mat, (PetscObject)pc, "-pc_bddc_coarse_mat_view")); 83369566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(coarse_mat, ((PetscObject)pcbddc->coarse_ksp)->prefix)); 83379566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(pcbddc->coarse_ksp, coarse_mat, coarse_mat)); 83381baa6e33SBarry Smith if (pcbddc->dbg_flag) PetscCall(PetscViewerASCIISubtractTab(dbg_viewer, 2 * pcbddc->current_level)); 83396e683305SStefano Zampini } 83409566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarseG)); 83419566063dSJacob Faibussowitsch PetscCall(PetscFree(isarray)); 8342b1ecc7b1SStefano Zampini #if 0 8343b9b85e73SStefano Zampini { 8344b9b85e73SStefano Zampini PetscViewer viewer; 8345b9b85e73SStefano Zampini char filename[256]; 8346a364092eSJacob Faibussowitsch PetscCall(PetscSNPrintf(filename, PETSC_STATIC_ARRAY_LENGTH(filename), "coarse_mat_level%d.m",pcbddc->current_level)); 83479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIOpen(PetscObjectComm((PetscObject)coarse_mat),filename,&viewer)); 83489566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_MATLAB)); 83499566063dSJacob Faibussowitsch PetscCall(MatView(coarse_mat,viewer)); 83509566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 83519566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 8352b9b85e73SStefano Zampini } 8353b9b85e73SStefano Zampini #endif 8354f9eb5b7dSStefano Zampini 83554f819b78SStefano Zampini if (corners) { 83564f819b78SStefano Zampini Vec gv; 83574f819b78SStefano Zampini IS is; 83584f819b78SStefano Zampini const PetscInt *idxs; 83594f819b78SStefano Zampini PetscInt i, d, N, n, cdim = pcbddc->mat_graph->cdim; 83604f819b78SStefano Zampini PetscScalar *coords; 83614f819b78SStefano Zampini 836228b400f6SJacob Faibussowitsch PetscCheck(pcbddc->mat_graph->cloc, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing local coordinates"); 83639566063dSJacob Faibussowitsch PetscCall(VecGetSize(pcbddc->coarse_vec, &N)); 83649566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(pcbddc->coarse_vec, &n)); 83659566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)pcbddc->coarse_vec), &gv)); 83669566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(gv, cdim)); 83679566063dSJacob Faibussowitsch PetscCall(VecSetSizes(gv, n * cdim, N * cdim)); 83689566063dSJacob Faibussowitsch PetscCall(VecSetType(gv, VECSTANDARD)); 83699566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(gv)); 83709566063dSJacob Faibussowitsch PetscCall(VecSet(gv, PETSC_MAX_REAL)); /* we only propagate coordinates from vertices constraints */ 83714f819b78SStefano Zampini 83729566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &is)); 83739566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &n)); 83749566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, &idxs)); 83759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n * cdim, &coords)); 83764f819b78SStefano Zampini for (i = 0; i < n; i++) { 8377ad540459SPierre Jolivet for (d = 0; d < cdim; d++) coords[cdim * i + d] = pcbddc->mat_graph->coords[cdim * idxs[i] + d]; 83784f819b78SStefano Zampini } 83799566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, &idxs)); 83809566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &is)); 83814f819b78SStefano Zampini 83829566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(corners, &n)); 83839566063dSJacob Faibussowitsch PetscCall(ISGetIndices(corners, &idxs)); 83849566063dSJacob Faibussowitsch PetscCall(VecSetValuesBlocked(gv, n, idxs, coords, INSERT_VALUES)); 83859566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(corners, &idxs)); 83869566063dSJacob Faibussowitsch PetscCall(PetscFree(coords)); 83879566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(gv)); 83889566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(gv)); 83899566063dSJacob Faibussowitsch PetscCall(VecGetArray(gv, &coords)); 83904f819b78SStefano Zampini if (pcbddc->coarse_ksp) { 83914f819b78SStefano Zampini PC coarse_pc; 83924f819b78SStefano Zampini PetscBool isbddc; 83934f819b78SStefano Zampini 83949566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &coarse_pc)); 83959566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)coarse_pc, PCBDDC, &isbddc)); 83964f819b78SStefano Zampini if (isbddc) { /* coarse coordinates have PETSC_MAX_REAL, specific for BDDC */ 83974f819b78SStefano Zampini PetscReal *realcoords; 83984f819b78SStefano Zampini 83999566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(gv, &n)); 84004f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX) 84019566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &realcoords)); 84024f819b78SStefano Zampini for (i = 0; i < n; i++) realcoords[i] = PetscRealPart(coords[i]); 84034f819b78SStefano Zampini #else 84044f819b78SStefano Zampini realcoords = coords; 84054f819b78SStefano Zampini #endif 84069566063dSJacob Faibussowitsch PetscCall(PCSetCoordinates(coarse_pc, cdim, n / cdim, realcoords)); 84074f819b78SStefano Zampini #if defined(PETSC_USE_COMPLEX) 84089566063dSJacob Faibussowitsch PetscCall(PetscFree(realcoords)); 84094f819b78SStefano Zampini #endif 84104f819b78SStefano Zampini } 84114f819b78SStefano Zampini } 84129566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(gv, &coords)); 84139566063dSJacob Faibussowitsch PetscCall(VecDestroy(&gv)); 84144f819b78SStefano Zampini } 84159566063dSJacob Faibussowitsch PetscCall(ISDestroy(&corners)); 84164f819b78SStefano Zampini 841798a51de6SStefano Zampini if (pcbddc->coarse_ksp) { 841898a51de6SStefano Zampini Vec crhs, csol; 841904708bb6SStefano Zampini 84209566063dSJacob Faibussowitsch PetscCall(KSPGetSolution(pcbddc->coarse_ksp, &csol)); 84219566063dSJacob Faibussowitsch PetscCall(KSPGetRhs(pcbddc->coarse_ksp, &crhs)); 8422*f4f49eeaSPierre Jolivet if (!csol) PetscCall(MatCreateVecs(coarse_mat, &pcbddc->coarse_ksp->vec_sol, NULL)); 8423*f4f49eeaSPierre Jolivet if (!crhs) PetscCall(MatCreateVecs(coarse_mat, NULL, &pcbddc->coarse_ksp->vec_rhs)); 8424b0f5fe93SStefano Zampini } 84259566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarsedivudotp)); 8426b0f5fe93SStefano Zampini 8427b0f5fe93SStefano Zampini /* compute null space for coarse solver if the benign trick has been requested */ 8428b0f5fe93SStefano Zampini if (pcbddc->benign_null) { 84299566063dSJacob Faibussowitsch PetscCall(VecSet(pcbddc->vec1_P, 0.)); 843048a46eb9SPierre 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)); 84319566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(pcbddc->vec1_P)); 84329566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(pcbddc->vec1_P)); 84339566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcbddc->coarse_loc_to_glob, pcbddc->vec1_P, pcbddc->coarse_vec, INSERT_VALUES, SCATTER_FORWARD)); 84349566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcbddc->coarse_loc_to_glob, pcbddc->vec1_P, pcbddc->coarse_vec, INSERT_VALUES, SCATTER_FORWARD)); 8435b0f5fe93SStefano Zampini if (coarse_mat) { 8436b0f5fe93SStefano Zampini Vec nullv; 8437b0f5fe93SStefano Zampini PetscScalar *array, *array2; 8438b0f5fe93SStefano Zampini PetscInt nl; 8439b0f5fe93SStefano Zampini 84409566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(coarse_mat, &nullv, NULL)); 84419566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(nullv, &nl)); 84429566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(pcbddc->coarse_vec, (const PetscScalar **)&array)); 84439566063dSJacob Faibussowitsch PetscCall(VecGetArray(nullv, &array2)); 84449566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(array2, array, nl)); 84459566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(nullv, &array2)); 84469566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(pcbddc->coarse_vec, (const PetscScalar **)&array)); 84479566063dSJacob Faibussowitsch PetscCall(VecNormalize(nullv, NULL)); 84489566063dSJacob Faibussowitsch PetscCall(MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat), PETSC_FALSE, 1, &nullv, &CoarseNullSpace)); 84499566063dSJacob Faibussowitsch PetscCall(VecDestroy(&nullv)); 8450b0f5fe93SStefano Zampini } 8451b0f5fe93SStefano Zampini } 84529566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_CoarseSetUp[pcbddc->current_level], pc, 0, 0, 0)); 8453b0f5fe93SStefano Zampini 84549566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_CoarseSolver[pcbddc->current_level], pc, 0, 0, 0)); 8455b0f5fe93SStefano Zampini if (pcbddc->coarse_ksp) { 8456b0f5fe93SStefano Zampini PetscBool ispreonly; 8457b0f5fe93SStefano Zampini 8458b0f5fe93SStefano Zampini if (CoarseNullSpace) { 8459b0f5fe93SStefano Zampini PetscBool isnull; 84607c625d9fSStefano Zampini 84619566063dSJacob Faibussowitsch PetscCall(MatNullSpaceTest(CoarseNullSpace, coarse_mat, &isnull)); 84621baa6e33SBarry Smith if (isnull) PetscCall(MatSetNullSpace(coarse_mat, CoarseNullSpace)); 8463bef83e63SStefano Zampini /* TODO: add local nullspaces (if any) */ 8464b0f5fe93SStefano Zampini } 8465b0f5fe93SStefano Zampini /* setup coarse ksp */ 84669566063dSJacob Faibussowitsch PetscCall(KSPSetUp(pcbddc->coarse_ksp)); 8467cbcc2c2aSStefano Zampini /* Check coarse problem if in debug mode or if solving with an iterative method */ 84689566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp, KSPPREONLY, &ispreonly)); 84696e683305SStefano Zampini if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates)) { 8470c8587f34SStefano Zampini KSP check_ksp; 84712b510759SStefano Zampini KSPType check_ksp_type; 8472c8587f34SStefano Zampini PC check_pc; 84736e683305SStefano Zampini Vec check_vec, coarse_vec; 84746a1308c2SStefano Zampini PetscReal abs_infty_error, infty_error, lambda_min = 1.0, lambda_max = 1.0; 84752b510759SStefano Zampini PetscInt its; 84766e683305SStefano Zampini PetscBool compute_eigs; 84776e683305SStefano Zampini PetscReal *eigs_r, *eigs_c; 84786e683305SStefano Zampini PetscInt neigs; 84798e185a42SStefano Zampini const char *prefix; 8480c8587f34SStefano Zampini 84812b510759SStefano Zampini /* Create ksp object suitable for estimation of extreme eigenvalues */ 84829566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp), &check_ksp)); 84833821be0aSBarry Smith PetscCall(KSPSetNestLevel(check_ksp, pc->kspnestlevel)); 84849566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)check_ksp, (PetscObject)pcbddc->coarse_ksp, 0)); 84859566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(pcbddc->coarse_ksp, PETSC_FALSE)); 84869566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(check_ksp, coarse_mat, coarse_mat)); 84879566063dSJacob Faibussowitsch PetscCall(KSPSetTolerances(check_ksp, 1.e-12, 1.e-12, PETSC_DEFAULT, pcbddc->coarse_size)); 8488e4d548c7SStefano Zampini /* prevent from setup unneeded object */ 84899566063dSJacob Faibussowitsch PetscCall(KSPGetPC(check_ksp, &check_pc)); 84909566063dSJacob Faibussowitsch PetscCall(PCSetType(check_pc, PCNONE)); 84912b510759SStefano Zampini if (ispreonly) { 84922b510759SStefano Zampini check_ksp_type = KSPPREONLY; 84936e683305SStefano Zampini compute_eigs = PETSC_FALSE; 84942b510759SStefano Zampini } else { 8495cbcc2c2aSStefano Zampini check_ksp_type = KSPGMRES; 84966e683305SStefano Zampini compute_eigs = PETSC_TRUE; 8497c8587f34SStefano Zampini } 84989566063dSJacob Faibussowitsch PetscCall(KSPSetType(check_ksp, check_ksp_type)); 84999566063dSJacob Faibussowitsch PetscCall(KSPSetComputeSingularValues(check_ksp, compute_eigs)); 85009566063dSJacob Faibussowitsch PetscCall(KSPSetComputeEigenvalues(check_ksp, compute_eigs)); 85019566063dSJacob Faibussowitsch PetscCall(KSPGMRESSetRestart(check_ksp, pcbddc->coarse_size + 1)); 85029566063dSJacob Faibussowitsch PetscCall(KSPGetOptionsPrefix(pcbddc->coarse_ksp, &prefix)); 85039566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(check_ksp, prefix)); 85049566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(check_ksp, "check_")); 85059566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(check_ksp)); 85069566063dSJacob Faibussowitsch PetscCall(KSPSetUp(check_ksp)); 85079566063dSJacob Faibussowitsch PetscCall(KSPGetPC(pcbddc->coarse_ksp, &check_pc)); 85089566063dSJacob Faibussowitsch PetscCall(KSPSetPC(check_ksp, check_pc)); 8509c8587f34SStefano Zampini /* create random vec */ 85109566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(coarse_mat, &coarse_vec, &check_vec)); 85119566063dSJacob Faibussowitsch PetscCall(VecSetRandom(check_vec, NULL)); 85129566063dSJacob Faibussowitsch PetscCall(MatMult(coarse_mat, check_vec, coarse_vec)); 8513c8587f34SStefano Zampini /* solve coarse problem */ 85149566063dSJacob Faibussowitsch PetscCall(KSPSolve(check_ksp, coarse_vec, coarse_vec)); 85159566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(check_ksp, pc, coarse_vec)); 8516cbcc2c2aSStefano Zampini /* set eigenvalue estimation if preonly has not been requested */ 85176e683305SStefano Zampini if (compute_eigs) { 85189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->coarse_size + 1, &eigs_r)); 85199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->coarse_size + 1, &eigs_c)); 85209566063dSJacob Faibussowitsch PetscCall(KSPComputeEigenvalues(check_ksp, pcbddc->coarse_size + 1, eigs_r, eigs_c, &neigs)); 85211ae86dd6SStefano Zampini if (neigs) { 85226e683305SStefano Zampini lambda_max = eigs_r[neigs - 1]; 85236e683305SStefano Zampini lambda_min = eigs_r[0]; 85246e683305SStefano Zampini if (pcbddc->use_coarse_estimates) { 85252701bc32SStefano Zampini if (lambda_max >= lambda_min) { /* using PETSC_SMALL since lambda_max == lambda_min is not allowed by KSPChebyshevSetEigenvalues */ 85269566063dSJacob Faibussowitsch PetscCall(KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp, lambda_max + PETSC_SMALL, lambda_min)); 85279566063dSJacob Faibussowitsch PetscCall(KSPRichardsonSetScale(pcbddc->coarse_ksp, 2.0 / (lambda_max + lambda_min))); 8528cbcc2c2aSStefano Zampini } 8529c8587f34SStefano Zampini } 8530c8587f34SStefano Zampini } 85311ae86dd6SStefano Zampini } 8532cbcc2c2aSStefano Zampini 8533c8587f34SStefano Zampini /* check coarse problem residual error */ 85346e683305SStefano Zampini if (pcbddc->dbg_flag) { 85356e683305SStefano Zampini PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp)); 85369566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIAddTab(dbg_viewer, 2 * (pcbddc->current_level + 1))); 85379566063dSJacob Faibussowitsch PetscCall(VecAXPY(check_vec, -1.0, coarse_vec)); 85389566063dSJacob Faibussowitsch PetscCall(VecNorm(check_vec, NORM_INFINITY, &infty_error)); 85399566063dSJacob Faibussowitsch PetscCall(MatMult(coarse_mat, check_vec, coarse_vec)); 85409566063dSJacob Faibussowitsch PetscCall(VecNorm(coarse_vec, NORM_INFINITY, &abs_infty_error)); 85419566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(dbg_viewer, "Coarse problem details (use estimates %d)\n", pcbddc->use_coarse_estimates)); 8542*f4f49eeaSPierre Jolivet PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)pcbddc->coarse_ksp, dbg_viewer)); 85439566063dSJacob Faibussowitsch PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc), dbg_viewer)); 854463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(dbg_viewer, "Coarse problem exact infty_error : %1.6e\n", (double)infty_error)); 854563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(dbg_viewer, "Coarse problem residual infty_error: %1.6e\n", (double)abs_infty_error)); 854648a46eb9SPierre Jolivet if (CoarseNullSpace) PetscCall(PetscViewerASCIIPrintf(dbg_viewer, "Coarse problem is singular\n")); 85476e683305SStefano Zampini if (compute_eigs) { 85486e683305SStefano Zampini PetscReal lambda_max_s, lambda_min_s; 8549b03ebc13SStefano Zampini KSPConvergedReason reason; 85509566063dSJacob Faibussowitsch PetscCall(KSPGetType(check_ksp, &check_ksp_type)); 85519566063dSJacob Faibussowitsch PetscCall(KSPGetIterationNumber(check_ksp, &its)); 85529566063dSJacob Faibussowitsch PetscCall(KSPGetConvergedReason(check_ksp, &reason)); 85539566063dSJacob Faibussowitsch PetscCall(KSPComputeExtremeSingularValues(check_ksp, &lambda_max_s, &lambda_min_s)); 855463a3b9bcSJacob 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)); 855548a46eb9SPierre Jolivet for (i = 0; i < neigs; i++) PetscCall(PetscViewerASCIIPrintf(dbg_viewer, "%1.6e %1.6ei\n", (double)eigs_r[i], (double)eigs_c[i])); 85566e683305SStefano Zampini } 85579566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(dbg_viewer)); 85589566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISubtractTab(dbg_viewer, 2 * (pcbddc->current_level + 1))); 85596e683305SStefano Zampini } 85609566063dSJacob Faibussowitsch PetscCall(VecDestroy(&check_vec)); 85619566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coarse_vec)); 85629566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&check_ksp)); 85636e683305SStefano Zampini if (compute_eigs) { 85649566063dSJacob Faibussowitsch PetscCall(PetscFree(eigs_r)); 85659566063dSJacob Faibussowitsch PetscCall(PetscFree(eigs_c)); 8566c8587f34SStefano Zampini } 85676e683305SStefano Zampini } 85686e683305SStefano Zampini } 85699566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&CoarseNullSpace)); 8570cbcc2c2aSStefano Zampini /* print additional info */ 8571cbcc2c2aSStefano Zampini if (pcbddc->dbg_flag) { 85726e683305SStefano Zampini /* waits until all processes reaches this point */ 85739566063dSJacob Faibussowitsch PetscCall(PetscBarrier((PetscObject)pc)); 857463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Coarse solver setup completed at level %" PetscInt_FMT "\n", pcbddc->current_level)); 85759566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 8576cbcc2c2aSStefano Zampini } 8577cbcc2c2aSStefano Zampini 85782b510759SStefano Zampini /* free memory */ 85799566063dSJacob Faibussowitsch PetscCall(MatDestroy(&coarse_mat)); 85809566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_CoarseSolver[pcbddc->current_level], pc, 0, 0, 0)); 85813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8582c8587f34SStefano Zampini } 8583674ae819SStefano Zampini 8584d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCComputePrimalNumbering(PC pc, PetscInt *coarse_size_n, PetscInt **local_primal_indices_n) 8585d71ae5a4SJacob Faibussowitsch { 8586f34684f1SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 8587f34684f1SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 8588f34684f1SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 8589dc456d91SStefano Zampini IS subset, subset_mult, subset_n; 8590dc456d91SStefano Zampini PetscInt local_size, coarse_size = 0; 859173be2a3aSStefano Zampini PetscInt *local_primal_indices = NULL; 8592dc456d91SStefano Zampini const PetscInt *t_local_primal_indices; 8593f34684f1SStefano Zampini 8594f34684f1SStefano Zampini PetscFunctionBegin; 8595f34684f1SStefano Zampini /* Compute global number of coarse dofs */ 859608401ef6SPierre Jolivet PetscCheck(!pcbddc->local_primal_size || pcbddc->local_primal_ref_node, PETSC_COMM_SELF, PETSC_ERR_PLIB, "BDDC ConstraintsSetUp should be called first"); 8597*f4f49eeaSPierre Jolivet PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc->pmat), pcbddc->local_primal_size_cc, pcbddc->local_primal_ref_node, PETSC_COPY_VALUES, &subset_n)); 85989566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(pcis->mapping, subset_n, &subset)); 85999566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subset_n)); 8600*f4f49eeaSPierre Jolivet PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc->pmat), pcbddc->local_primal_size_cc, pcbddc->local_primal_ref_mult, PETSC_COPY_VALUES, &subset_mult)); 86019566063dSJacob Faibussowitsch PetscCall(ISRenumber(subset, subset_mult, &coarse_size, &subset_n)); 86029566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subset)); 86039566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subset_mult)); 86049566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(subset_n, &local_size)); 860563a3b9bcSJacob 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); 86069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(local_size, &local_primal_indices)); 86079566063dSJacob Faibussowitsch PetscCall(ISGetIndices(subset_n, &t_local_primal_indices)); 86089566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(local_primal_indices, t_local_primal_indices, local_size)); 86099566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(subset_n, &t_local_primal_indices)); 86109566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subset_n)); 8611f34684f1SStefano Zampini 8612f34684f1SStefano Zampini /* check numbering */ 8613f34684f1SStefano Zampini if (pcbddc->dbg_flag) { 8614019a44ceSStefano Zampini PetscScalar coarsesum, *array, *array2; 8615dc456d91SStefano Zampini PetscInt i; 8616b9b85e73SStefano Zampini PetscBool set_error = PETSC_FALSE, set_error_reduced = PETSC_FALSE; 8617f34684f1SStefano Zampini 86189566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 86199566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "--------------------------------------------------\n")); 86209566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Check coarse indices\n")); 86219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 8622019a44ceSStefano Zampini /* counter */ 86239566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_global, 0.0)); 86249566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_N, 1.0)); 86259566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_N, pcis->vec1_global, ADD_VALUES, SCATTER_REVERSE)); 86269566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_N, pcis->vec1_global, ADD_VALUES, SCATTER_REVERSE)); 86279566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_global, pcis->vec2_N, INSERT_VALUES, SCATTER_FORWARD)); 86289566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_global, pcis->vec2_N, INSERT_VALUES, SCATTER_FORWARD)); 86299566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_N, 0.0)); 863048a46eb9SPierre Jolivet for (i = 0; i < pcbddc->local_primal_size; i++) PetscCall(VecSetValue(pcis->vec1_N, pcbddc->primal_indices_local_idxs[i], 1.0, INSERT_VALUES)); 86319566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(pcis->vec1_N)); 86329566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(pcis->vec1_N)); 86339566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_global, 0.0)); 86349566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_N, pcis->vec1_global, ADD_VALUES, SCATTER_REVERSE)); 86359566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_N, pcis->vec1_global, ADD_VALUES, SCATTER_REVERSE)); 86369566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_global, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD)); 86379566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_global, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD)); 86389566063dSJacob Faibussowitsch PetscCall(VecGetArray(pcis->vec1_N, &array)); 86399566063dSJacob Faibussowitsch PetscCall(VecGetArray(pcis->vec2_N, &array2)); 8640f34684f1SStefano Zampini for (i = 0; i < pcis->n; i++) { 8641019a44ceSStefano Zampini if (array[i] != 0.0 && array[i] != array2[i]) { 86422c66d082SStefano Zampini PetscInt owned = (PetscInt)PetscRealPart(array[i]), gi; 864375c01103SStefano Zampini PetscInt neigh = (PetscInt)PetscRealPart(array2[i]); 8644b9b85e73SStefano Zampini set_error = PETSC_TRUE; 86459566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(pcis->mapping, 1, &i, &gi)); 864663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d: local index %" PetscInt_FMT " (gid %" PetscInt_FMT ") owned by %" PetscInt_FMT " processes instead of %" PetscInt_FMT "!\n", PetscGlobalRank, i, gi, owned, neigh)); 8647f34684f1SStefano Zampini } 8648f34684f1SStefano Zampini } 86499566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pcis->vec2_N, &array2)); 86501c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&set_error, &set_error_reduced, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 86519566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 8652f34684f1SStefano Zampini for (i = 0; i < pcis->n; i++) { 8653f34684f1SStefano Zampini if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0 / PetscRealPart(array[i]); 8654f34684f1SStefano Zampini } 86559566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pcis->vec1_N, &array)); 86569566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_global, 0.0)); 86579566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_N, pcis->vec1_global, ADD_VALUES, SCATTER_REVERSE)); 86589566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_N, pcis->vec1_global, ADD_VALUES, SCATTER_REVERSE)); 86599566063dSJacob Faibussowitsch PetscCall(VecSum(pcis->vec1_global, &coarsesum)); 866063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Size of coarse problem is %" PetscInt_FMT " (%lf)\n", coarse_size, (double)PetscRealPart(coarsesum))); 8661b9b85e73SStefano Zampini if (pcbddc->dbg_flag > 1 || set_error_reduced) { 8662ca8b9ea9SStefano Zampini PetscInt *gidxs; 8663ca8b9ea9SStefano Zampini 86649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pcbddc->local_primal_size, &gidxs)); 86659566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(pcis->mapping, pcbddc->local_primal_size, pcbddc->primal_indices_local_idxs, gidxs)); 86669566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "Distribution of local primal indices\n")); 86679566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 86689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d\n", PetscGlobalRank)); 8669f34684f1SStefano Zampini for (i = 0; i < pcbddc->local_primal_size; i++) { 867063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "local_primal_indices[%" PetscInt_FMT "]=%" PetscInt_FMT " (%" PetscInt_FMT ",%" PetscInt_FMT ")\n", i, local_primal_indices[i], pcbddc->primal_indices_local_idxs[i], gidxs[i])); 8671f34684f1SStefano Zampini } 86729566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 86739566063dSJacob Faibussowitsch PetscCall(PetscFree(gidxs)); 8674f34684f1SStefano Zampini } 86759566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 86769566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 867728b400f6SJacob Faibussowitsch PetscCheck(!set_error_reduced, PetscObjectComm((PetscObject)pc), PETSC_ERR_PLIB, "BDDC Numbering of coarse dofs failed"); 8678f34684f1SStefano Zampini } 86796080607fSStefano Zampini 8680f34684f1SStefano Zampini /* get back data */ 8681f34684f1SStefano Zampini *coarse_size_n = coarse_size; 8682f34684f1SStefano Zampini *local_primal_indices_n = local_primal_indices; 86833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8684674ae819SStefano Zampini } 8685674ae819SStefano Zampini 8686d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx, Vec gwork, Vec lwork, IS globalis, IS *localis) 8687d71ae5a4SJacob Faibussowitsch { 8688e456f2a8SStefano Zampini IS localis_t; 8689a7dc3881SStefano Zampini PetscInt i, lsize, *idxs, n; 8690e456f2a8SStefano Zampini PetscScalar *vals; 8691e456f2a8SStefano Zampini 8692e456f2a8SStefano Zampini PetscFunctionBegin; 8693a7dc3881SStefano Zampini /* get indices in local ordering exploiting local to global map */ 86949566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(globalis, &lsize)); 86959566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(lsize, &vals)); 8696e456f2a8SStefano Zampini for (i = 0; i < lsize; i++) vals[i] = 1.0; 86979566063dSJacob Faibussowitsch PetscCall(ISGetIndices(globalis, (const PetscInt **)&idxs)); 86989566063dSJacob Faibussowitsch PetscCall(VecSet(gwork, 0.0)); 86999566063dSJacob Faibussowitsch PetscCall(VecSet(lwork, 0.0)); 87001035eff8SStefano Zampini if (idxs) { /* multilevel guard */ 87019566063dSJacob Faibussowitsch PetscCall(VecSetOption(gwork, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE)); 87029566063dSJacob Faibussowitsch PetscCall(VecSetValues(gwork, lsize, idxs, vals, INSERT_VALUES)); 87031035eff8SStefano Zampini } 87049566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(gwork)); 87059566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(globalis, (const PetscInt **)&idxs)); 87069566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 87079566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(gwork)); 8708a7dc3881SStefano Zampini /* now compute set in local ordering */ 87099566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(g2l_ctx, gwork, lwork, INSERT_VALUES, SCATTER_FORWARD)); 87109566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(g2l_ctx, gwork, lwork, INSERT_VALUES, SCATTER_FORWARD)); 87119566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(lwork, (const PetscScalar **)&vals)); 87129566063dSJacob Faibussowitsch PetscCall(VecGetSize(lwork, &n)); 8713a7dc3881SStefano Zampini for (i = 0, lsize = 0; i < n; i++) { 8714ad540459SPierre Jolivet if (PetscRealPart(vals[i]) > 0.5) lsize++; 8715e456f2a8SStefano Zampini } 87169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(lsize, &idxs)); 8717a7dc3881SStefano Zampini for (i = 0, lsize = 0; i < n; i++) { 8718ad540459SPierre Jolivet if (PetscRealPart(vals[i]) > 0.5) idxs[lsize++] = i; 8719e456f2a8SStefano Zampini } 87209566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(lwork, (const PetscScalar **)&vals)); 87219566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)gwork), lsize, idxs, PETSC_OWN_POINTER, &localis_t)); 8722e456f2a8SStefano Zampini *localis = localis_t; 87233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8724e456f2a8SStefano Zampini } 8725906d46d4SStefano Zampini 8726d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCComputeFakeChange(PC pc, PetscBool constraints, PCBDDCGraph graph, PCBDDCSubSchurs schurs, Mat *change, IS *change_primal, IS *change_primal_mult, PetscBool *change_with_qr) 8727d71ae5a4SJacob Faibussowitsch { 87287c625d9fSStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 87297c625d9fSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 87307c625d9fSStefano Zampini PC_IS *pcisf; 87317c625d9fSStefano Zampini PC_BDDC *pcbddcf; 87327c625d9fSStefano Zampini PC pcf; 87337c625d9fSStefano Zampini 87347c625d9fSStefano Zampini PetscFunctionBegin; 87357c625d9fSStefano Zampini PetscCall(PCCreate(PetscObjectComm((PetscObject)pc), &pcf)); 87367c625d9fSStefano Zampini PetscCall(PCSetOperators(pcf, pc->mat, pc->pmat)); 87377c625d9fSStefano Zampini PetscCall(PCSetType(pcf, PCBDDC)); 87387c625d9fSStefano Zampini 87397c625d9fSStefano Zampini pcisf = (PC_IS *)pcf->data; 874032fe681dSStefano Zampini pcbddcf = (PC_BDDC *)pcf->data; 874132fe681dSStefano Zampini 87427c625d9fSStefano Zampini pcisf->is_B_local = pcis->is_B_local; 87437c625d9fSStefano Zampini pcisf->vec1_N = pcis->vec1_N; 87447c625d9fSStefano Zampini pcisf->BtoNmap = pcis->BtoNmap; 87457c625d9fSStefano Zampini pcisf->n = pcis->n; 87467c625d9fSStefano Zampini pcisf->n_B = pcis->n_B; 87477c625d9fSStefano Zampini 87487c625d9fSStefano Zampini PetscCall(PetscFree(pcbddcf->mat_graph)); 874932fe681dSStefano Zampini PetscCall(PetscFree(pcbddcf->sub_schurs)); 87507c625d9fSStefano Zampini pcbddcf->mat_graph = graph ? graph : pcbddc->mat_graph; 875132fe681dSStefano Zampini pcbddcf->sub_schurs = schurs; 875232fe681dSStefano Zampini pcbddcf->adaptive_selection = schurs ? PETSC_TRUE : PETSC_FALSE; 875332fe681dSStefano Zampini pcbddcf->adaptive_threshold[0] = pcbddc->adaptive_threshold[0]; 875432fe681dSStefano Zampini pcbddcf->adaptive_threshold[1] = pcbddc->adaptive_threshold[1]; 875532fe681dSStefano Zampini pcbddcf->adaptive_nmin = pcbddc->adaptive_nmin; 875632fe681dSStefano Zampini pcbddcf->adaptive_nmax = pcbddc->adaptive_nmax; 87577c625d9fSStefano Zampini pcbddcf->use_faces = PETSC_TRUE; 875832fe681dSStefano Zampini pcbddcf->use_change_of_basis = (PetscBool)!constraints; 875932fe681dSStefano Zampini pcbddcf->use_change_on_faces = (PetscBool)!constraints; 876032fe681dSStefano Zampini pcbddcf->use_qr_single = (PetscBool)!constraints; 87617c625d9fSStefano Zampini pcbddcf->fake_change = PETSC_TRUE; 876232fe681dSStefano Zampini pcbddcf->dbg_flag = pcbddc->dbg_flag; 876332fe681dSStefano Zampini 876432fe681dSStefano Zampini PetscCall(PCBDDCAdaptiveSelection(pcf)); 87657c625d9fSStefano Zampini PetscCall(PCBDDCConstraintsSetUp(pcf)); 87667c625d9fSStefano Zampini 87677c625d9fSStefano Zampini *change = pcbddcf->ConstraintMatrix; 87687c625d9fSStefano 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)); 87697c625d9fSStefano 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)); 87707c625d9fSStefano Zampini if (change_with_qr) *change_with_qr = pcbddcf->use_qr_single; 87717c625d9fSStefano Zampini 877232fe681dSStefano Zampini if (schurs) pcbddcf->sub_schurs = NULL; 87737c625d9fSStefano Zampini pcbddcf->ConstraintMatrix = NULL; 877432fe681dSStefano Zampini pcbddcf->mat_graph = NULL; 877532fe681dSStefano Zampini pcisf->is_B_local = NULL; 877632fe681dSStefano Zampini pcisf->vec1_N = NULL; 877732fe681dSStefano Zampini pcisf->BtoNmap = NULL; 87787c625d9fSStefano Zampini PetscCall(PCDestroy(&pcf)); 87793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 87807c625d9fSStefano Zampini } 87817c625d9fSStefano Zampini 8782d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUpSubSchurs(PC pc) 8783d71ae5a4SJacob Faibussowitsch { 8784a64f4aa4SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 8785b96c3477SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 8786b96c3477SStefano Zampini PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; 8787a64f4aa4SStefano Zampini Mat S_j; 8788b96c3477SStefano Zampini PetscInt *used_xadj, *used_adjncy; 8789b96c3477SStefano Zampini PetscBool free_used_adj; 8790b96c3477SStefano Zampini 8791b96c3477SStefano Zampini PetscFunctionBegin; 87929566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Schurs[pcbddc->current_level], pc, 0, 0, 0)); 8793b96c3477SStefano Zampini /* decide the adjacency to be used for determining internal problems for local schur on subsets */ 8794b96c3477SStefano Zampini free_used_adj = PETSC_FALSE; 879508122e43SStefano Zampini if (pcbddc->sub_schurs_layers == -1) { 8796b96c3477SStefano Zampini used_xadj = NULL; 8797b96c3477SStefano Zampini used_adjncy = NULL; 8798b96c3477SStefano Zampini } else { 879908122e43SStefano Zampini if (pcbddc->sub_schurs_use_useradj && pcbddc->mat_graph->xadj) { 880008122e43SStefano Zampini used_xadj = pcbddc->mat_graph->xadj; 880108122e43SStefano Zampini used_adjncy = pcbddc->mat_graph->adjncy; 880208122e43SStefano Zampini } else if (pcbddc->computed_rowadj) { 8803b96c3477SStefano Zampini used_xadj = pcbddc->mat_graph->xadj; 8804b96c3477SStefano Zampini used_adjncy = pcbddc->mat_graph->adjncy; 8805b96c3477SStefano Zampini } else { 88062fffb893SStefano Zampini PetscBool flg_row = PETSC_FALSE; 8807b96c3477SStefano Zampini const PetscInt *xadj, *adjncy; 8808b96c3477SStefano Zampini PetscInt nvtxs; 8809b96c3477SStefano Zampini 88109566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(pcbddc->local_mat, 0, PETSC_TRUE, PETSC_FALSE, &nvtxs, &xadj, &adjncy, &flg_row)); 88112fffb893SStefano Zampini if (flg_row) { 88129566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nvtxs + 1, &used_xadj, xadj[nvtxs], &used_adjncy)); 88139566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(used_xadj, xadj, nvtxs + 1)); 88149566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(used_adjncy, adjncy, xadj[nvtxs])); 8815b96c3477SStefano Zampini free_used_adj = PETSC_TRUE; 88162fffb893SStefano Zampini } else { 88172fffb893SStefano Zampini pcbddc->sub_schurs_layers = -1; 88182fffb893SStefano Zampini used_xadj = NULL; 88192fffb893SStefano Zampini used_adjncy = NULL; 88202fffb893SStefano Zampini } 88219566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(pcbddc->local_mat, 0, PETSC_TRUE, PETSC_FALSE, &nvtxs, &xadj, &adjncy, &flg_row)); 8822b96c3477SStefano Zampini } 8823b96c3477SStefano Zampini } 8824d5574798SStefano Zampini 8825d5574798SStefano Zampini /* setup sub_schurs data */ 88269566063dSJacob Faibussowitsch PetscCall(MatCreateSchurComplement(pcis->A_II, pcis->pA_II, pcis->A_IB, pcis->A_BI, pcis->A_BB, &S_j)); 8827df4d28bfSStefano Zampini if (!sub_schurs->schur_explicit) { 8828df4d28bfSStefano Zampini /* pcbddc->ksp_D up to date only if not using MatFactor with Schur complement support */ 88299566063dSJacob Faibussowitsch PetscCall(MatSchurComplementSetKSP(S_j, pcbddc->ksp_D)); 88309566063dSJacob 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)); 8831a64f4aa4SStefano Zampini } else { 883272b8c272SStefano Zampini Mat change = NULL; 88339d54b7f4SStefano Zampini Vec scaling = NULL; 8834111315fdSstefano_zampini IS change_primal = NULL, iP; 8835111315fdSstefano_zampini PetscInt benign_n; 8836111315fdSstefano_zampini PetscBool reuse_solvers = (PetscBool)!pcbddc->use_change_of_basis; 88377ebab0bbSStefano Zampini PetscBool need_change = PETSC_FALSE; 8838111315fdSstefano_zampini PetscBool discrete_harmonic = PETSC_FALSE; 8839a3df083aSStefano Zampini 88405feab87aSStefano Zampini if (!pcbddc->use_vertices && reuse_solvers) { 88415feab87aSStefano Zampini PetscInt n_vertices; 88425feab87aSStefano Zampini 88439566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(sub_schurs->is_vertices, &n_vertices)); 88442034aafcSStefano Zampini reuse_solvers = (PetscBool)!n_vertices; 88455feab87aSStefano Zampini } 8846a3df083aSStefano Zampini if (!pcbddc->benign_change_explicit) { 8847a3df083aSStefano Zampini benign_n = pcbddc->benign_n; 8848ca92afb2SStefano Zampini } else { 8849a3df083aSStefano Zampini benign_n = 0; 8850ca92afb2SStefano Zampini } 8851b7ab4a40SStefano Zampini /* sub_schurs->change is a local object; instead, PCBDDCConstraintsSetUp and the quantities used in the test below are logically collective on pc. 8852b7ab4a40SStefano Zampini We need a global reduction to avoid possible deadlocks. 8853b7ab4a40SStefano Zampini We assume that sub_schurs->change is created once, and then reused for different solves, unless the topography has been recomputed */ 885472b8c272SStefano Zampini if (pcbddc->adaptive_userdefined || (pcbddc->deluxe_zerorows && !pcbddc->use_change_of_basis)) { 885522db5ddcSStefano Zampini PetscBool have_loc_change = (PetscBool)(!!sub_schurs->change); 88561c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&have_loc_change, &need_change, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 885722db5ddcSStefano Zampini need_change = (PetscBool)(!need_change); 8858b7ab4a40SStefano Zampini } 88597c625d9fSStefano Zampini /* If the user defines additional constraints, we import them here */ 8860b7ab4a40SStefano Zampini if (need_change) { 886128b400f6SJacob Faibussowitsch PetscCheck(!pcbddc->sub_schurs_rebuild, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot compute change of basis with a different graph"); 886232fe681dSStefano Zampini PetscCall(PCBDDCComputeFakeChange(pc, PETSC_FALSE, NULL, NULL, &change, &change_primal, NULL, &sub_schurs->change_with_qr)); 886388c03ad3SStefano Zampini } 88649d54b7f4SStefano Zampini if (!pcbddc->use_deluxe_scaling) scaling = pcis->D; 8865111315fdSstefano_zampini 88669566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_iP", (PetscObject *)&iP)); 8867111315fdSstefano_zampini if (iP) { 8868d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)iP), sub_schurs->prefix, "BDDC sub_schurs options", "PC"); 88699566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-sub_schurs_discrete_harmonic", NULL, NULL, discrete_harmonic, &discrete_harmonic, NULL)); 8870d0609cedSBarry Smith PetscOptionsEnd(); 8871111315fdSstefano_zampini } 8872111315fdSstefano_zampini if (discrete_harmonic) { 8873111315fdSstefano_zampini Mat A; 88749566063dSJacob Faibussowitsch PetscCall(MatDuplicate(pcbddc->local_mat, MAT_COPY_VALUES, &A)); 88759566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumnsIS(A, iP, 1.0, NULL, NULL)); 88769566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)A, "__KSPFETIDP_iP", (PetscObject)iP)); 88779371c9d4SSatish 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, 88789371c9d4SSatish Balay pcbddc->benign_zerodiag_subs, change, change_primal)); 88799566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 8880111315fdSstefano_zampini } else { 88819371c9d4SSatish 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, 88829371c9d4SSatish Balay pcbddc->benign_p0_lidx, pcbddc->benign_zerodiag_subs, change, change_primal)); 8883111315fdSstefano_zampini } 88849566063dSJacob Faibussowitsch PetscCall(MatDestroy(&change)); 88859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&change_primal)); 8886ca92afb2SStefano Zampini } 88879566063dSJacob Faibussowitsch PetscCall(MatDestroy(&S_j)); 8888b96c3477SStefano Zampini 8889b96c3477SStefano Zampini /* free adjacency */ 88901baa6e33SBarry Smith if (free_used_adj) PetscCall(PetscFree2(used_xadj, used_adjncy)); 88919566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Schurs[pcbddc->current_level], pc, 0, 0, 0)); 88923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8893b96c3477SStefano Zampini } 8894b96c3477SStefano Zampini 8895d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCInitSubSchurs(PC pc) 8896d71ae5a4SJacob Faibussowitsch { 8897b96c3477SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 8898b96c3477SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 8899b96c3477SStefano Zampini PCBDDCGraph graph; 8900b96c3477SStefano Zampini 8901b96c3477SStefano Zampini PetscFunctionBegin; 8902b96c3477SStefano Zampini /* attach interface graph for determining subsets */ 890308122e43SStefano Zampini if (pcbddc->sub_schurs_rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */ 89043301b35fSStefano Zampini IS verticesIS, verticescomm; 89053301b35fSStefano Zampini PetscInt vsize, *idxs; 8906b96c3477SStefano Zampini 89079566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &verticesIS)); 89089566063dSJacob Faibussowitsch PetscCall(ISGetSize(verticesIS, &vsize)); 89099566063dSJacob Faibussowitsch PetscCall(ISGetIndices(verticesIS, (const PetscInt **)&idxs)); 89109566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), vsize, idxs, PETSC_COPY_VALUES, &verticescomm)); 89119566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(verticesIS, (const PetscInt **)&idxs)); 89129566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(pcbddc->mat_graph, NULL, NULL, NULL, NULL, &verticesIS)); 89139566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphCreate(&graph)); 89149566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphInit(graph, pcbddc->mat_graph->l2gmap, pcbddc->mat_graph->nvtxs_global, pcbddc->graphmaxcount)); 89159566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphSetUp(graph, pcbddc->mat_graph->custom_minimal_size, NULL, pcbddc->DirichletBoundariesLocal, 0, NULL, verticescomm)); 89169566063dSJacob Faibussowitsch PetscCall(ISDestroy(&verticescomm)); 89179566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphComputeConnectedComponents(graph)); 8918b96c3477SStefano Zampini } else { 8919b96c3477SStefano Zampini graph = pcbddc->mat_graph; 8920b96c3477SStefano Zampini } 8921e4d548c7SStefano Zampini /* print some info */ 89225c643e28SStefano Zampini if (pcbddc->dbg_flag && !pcbddc->sub_schurs_rebuild) { 8923e4d548c7SStefano Zampini IS vertices; 8924e4d548c7SStefano Zampini PetscInt nv, nedges, nfaces; 89259566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphASCIIView(graph, pcbddc->dbg_flag, pcbddc->dbg_viewer)); 89269566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetCandidatesIS(graph, &nfaces, NULL, &nedges, NULL, &vertices)); 89279566063dSJacob Faibussowitsch PetscCall(ISGetSize(vertices, &nv)); 89289566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 89299566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "--------------------------------------------------------------\n")); 893063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate vertices (%d)\n", PetscGlobalRank, nv, pcbddc->use_vertices)); 893163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate edges (%d)\n", PetscGlobalRank, nedges, pcbddc->use_edges)); 893263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer, "Subdomain %04d got %02" PetscInt_FMT " local candidate faces (%d)\n", PetscGlobalRank, nfaces, pcbddc->use_faces)); 89339566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 89349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer)); 89359566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphRestoreCandidatesIS(graph, &nfaces, NULL, &nedges, NULL, &vertices)); 8936e4d548c7SStefano Zampini } 8937b96c3477SStefano Zampini 8938b96c3477SStefano Zampini /* sub_schurs init */ 893948a46eb9SPierre Jolivet if (!pcbddc->sub_schurs) PetscCall(PCBDDCSubSchursCreate(&pcbddc->sub_schurs)); 894032fe681dSStefano 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)); 8941a64f4aa4SStefano Zampini 8942b96c3477SStefano Zampini /* free graph struct */ 894348a46eb9SPierre Jolivet if (pcbddc->sub_schurs_rebuild) PetscCall(PCBDDCGraphDestroy(&graph)); 89443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8945b96c3477SStefano Zampini } 8946fa34dd3eSStefano Zampini 89471e0482f5SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h> 8948ba38deedSJacob Faibussowitsch static PetscErrorCode MatMPIAIJRestrict(Mat A, MPI_Comm ccomm, Mat *B) 8949d71ae5a4SJacob Faibussowitsch { 89501e0482f5SStefano Zampini Mat At; 89511e0482f5SStefano Zampini IS rows; 89521e0482f5SStefano Zampini PetscInt rst, ren; 89531e0482f5SStefano Zampini PetscLayout rmap; 89541e0482f5SStefano Zampini 89551e0482f5SStefano Zampini PetscFunctionBegin; 89561e0482f5SStefano Zampini rst = ren = 0; 89571e0482f5SStefano Zampini if (ccomm != MPI_COMM_NULL) { 89589566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(ccomm, &rmap)); 89599566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetSize(rmap, A->rmap->N)); 89609566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(rmap, 1)); 89619566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rmap)); 89629566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rmap, &rst, &ren)); 89631e0482f5SStefano Zampini } 89649566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), ren - rst, rst, 1, &rows)); 89659566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(A, rows, NULL, MAT_INITIAL_MATRIX, &At)); 89669566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rows)); 89671e0482f5SStefano Zampini 89681e0482f5SStefano Zampini if (ccomm != MPI_COMM_NULL) { 89691e0482f5SStefano Zampini Mat_MPIAIJ *a, *b; 89701e0482f5SStefano Zampini IS from, to; 89711e0482f5SStefano Zampini Vec gvec; 89721e0482f5SStefano Zampini PetscInt lsize; 89731e0482f5SStefano Zampini 89749566063dSJacob Faibussowitsch PetscCall(MatCreate(ccomm, B)); 89759566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B, ren - rst, PETSC_DECIDE, PETSC_DECIDE, At->cmap->N)); 89769566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, MATAIJ)); 89779566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&((*B)->rmap))); 89789566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp((*B)->cmap)); 89791e0482f5SStefano Zampini a = (Mat_MPIAIJ *)At->data; 89801e0482f5SStefano Zampini b = (Mat_MPIAIJ *)(*B)->data; 89819566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(ccomm, &b->size)); 89829566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(ccomm, &b->rank)); 89839566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)a->A)); 89849566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)a->B)); 89851e0482f5SStefano Zampini b->A = a->A; 89861e0482f5SStefano Zampini b->B = a->B; 89871e0482f5SStefano Zampini 89881e0482f5SStefano Zampini b->donotstash = a->donotstash; 89891e0482f5SStefano Zampini b->roworiented = a->roworiented; 89900a545947SLisandro Dalcin b->rowindices = NULL; 89910a545947SLisandro Dalcin b->rowvalues = NULL; 89921e0482f5SStefano Zampini b->getrowactive = PETSC_FALSE; 89931e0482f5SStefano Zampini 89941e0482f5SStefano Zampini (*B)->rmap = rmap; 89951e0482f5SStefano Zampini (*B)->factortype = A->factortype; 89961e0482f5SStefano Zampini (*B)->assembled = PETSC_TRUE; 89971e0482f5SStefano Zampini (*B)->insertmode = NOT_SET_VALUES; 89981e0482f5SStefano Zampini (*B)->preallocated = PETSC_TRUE; 89991e0482f5SStefano Zampini 90001e0482f5SStefano Zampini if (a->colmap) { 90011e0482f5SStefano Zampini #if defined(PETSC_USE_CTABLE) 9002eec179cfSJacob Faibussowitsch PetscCall(PetscHMapIDuplicate(a->colmap, &b->colmap)); 90031e0482f5SStefano Zampini #else 90049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(At->cmap->N, &b->colmap)); 90059566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(b->colmap, a->colmap, At->cmap->N)); 90061e0482f5SStefano Zampini #endif 90070a545947SLisandro Dalcin } else b->colmap = NULL; 90081e0482f5SStefano Zampini if (a->garray) { 90091e0482f5SStefano Zampini PetscInt len; 90101e0482f5SStefano Zampini len = a->B->cmap->n; 90119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(len + 1, &b->garray)); 90129566063dSJacob Faibussowitsch if (len) PetscCall(PetscArraycpy(b->garray, a->garray, len)); 90130a545947SLisandro Dalcin } else b->garray = NULL; 90141e0482f5SStefano Zampini 90159566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)a->lvec)); 90161e0482f5SStefano Zampini b->lvec = a->lvec; 90171e0482f5SStefano Zampini 90181e0482f5SStefano Zampini /* cannot use VecScatterCopy */ 90199566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(b->lvec, &lsize)); 90209566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(ccomm, lsize, b->garray, PETSC_USE_POINTER, &from)); 90219566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, lsize, 0, 1, &to)); 90229566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(*B, &gvec, NULL)); 90239566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(gvec, from, b->lvec, to, &b->Mvctx)); 90249566063dSJacob Faibussowitsch PetscCall(ISDestroy(&from)); 90259566063dSJacob Faibussowitsch PetscCall(ISDestroy(&to)); 90269566063dSJacob Faibussowitsch PetscCall(VecDestroy(&gvec)); 90271e0482f5SStefano Zampini } 90289566063dSJacob Faibussowitsch PetscCall(MatDestroy(&At)); 90293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 90301e0482f5SStefano Zampini } 9031