14bbf5ea8SMatthew G. Knepley #include <petsc/private/pcpatchimpl.h> /*I "petscpc.h" I*/ 254ab768cSLawrence Mitchell #include <petsc/private/kspimpl.h> /* For ksp->setfromoptionscalled */ 39d4fc724SLawrence Mitchell #include <petsc/private/vecimpl.h> /* For vec->map */ 45f824522SMatthew G. Knepley #include <petsc/private/dmpleximpl.h> /* For DMPlexComputeJacobian_Patch_Internal() */ 54bbf5ea8SMatthew G. Knepley #include <petscsf.h> 64bbf5ea8SMatthew G. Knepley #include <petscbt.h> 75f824522SMatthew G. Knepley #include <petscds.h> 8c73d2cf6SLawrence Mitchell #include <../src/mat/impls/dense/seq/dense.h> /*I "petscmat.h" I*/ 94bbf5ea8SMatthew G. Knepley 109d4fc724SLawrence Mitchell PetscLogEvent PC_Patch_CreatePatches, PC_Patch_ComputeOp, PC_Patch_Solve, PC_Patch_Apply, PC_Patch_Prealloc; 114bbf5ea8SMatthew G. Knepley 129371c9d4SSatish Balay static inline PetscErrorCode ObjectView(PetscObject obj, PetscViewer viewer, PetscViewerFormat format) { 139566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, format)); 149566063dSJacob Faibussowitsch PetscCall(PetscObjectView(obj, viewer)); 159566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 167974b488SMatthew G. Knepley return (0); 175f824522SMatthew G. Knepley } 185f824522SMatthew G. Knepley 199371c9d4SSatish Balay static PetscErrorCode PCPatchConstruct_Star(void *vpatch, DM dm, PetscInt point, PetscHSetI ht) { 204bbf5ea8SMatthew G. Knepley PetscInt starSize; 214bbf5ea8SMatthew G. Knepley PetscInt *star = NULL, si; 224bbf5ea8SMatthew G. Knepley 234bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 249566063dSJacob Faibussowitsch PetscCall(PetscHSetIClear(ht)); 254bbf5ea8SMatthew G. Knepley /* To start with, add the point we care about */ 269566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, point)); 274bbf5ea8SMatthew G. Knepley /* Loop over all the points that this point connects to */ 289566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_FALSE, &starSize, &star)); 299566063dSJacob Faibussowitsch for (si = 0; si < starSize * 2; si += 2) PetscCall(PetscHSetIAdd(ht, star[si])); 309566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_FALSE, &starSize, &star)); 314bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 324bbf5ea8SMatthew G. Knepley } 334bbf5ea8SMatthew G. Knepley 349371c9d4SSatish Balay static PetscErrorCode PCPatchConstruct_Vanka(void *vpatch, DM dm, PetscInt point, PetscHSetI ht) { 354bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)vpatch; 364bbf5ea8SMatthew G. Knepley PetscInt starSize; 374bbf5ea8SMatthew G. Knepley PetscInt *star = NULL; 384bbf5ea8SMatthew G. Knepley PetscBool shouldIgnore = PETSC_FALSE; 394bbf5ea8SMatthew G. Knepley PetscInt cStart, cEnd, iStart, iEnd, si; 404bbf5ea8SMatthew G. Knepley 414bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 429566063dSJacob Faibussowitsch PetscCall(PetscHSetIClear(ht)); 434bbf5ea8SMatthew G. Knepley /* To start with, add the point we care about */ 449566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, point)); 454bbf5ea8SMatthew G. Knepley /* Should we ignore any points of a certain dimension? */ 464bbf5ea8SMatthew G. Knepley if (patch->vankadim >= 0) { 474bbf5ea8SMatthew G. Knepley shouldIgnore = PETSC_TRUE; 489566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, patch->vankadim, &iStart, &iEnd)); 494bbf5ea8SMatthew G. Knepley } 509566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 514bbf5ea8SMatthew G. Knepley /* Loop over all the cells that this point connects to */ 529566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_FALSE, &starSize, &star)); 535f824522SMatthew G. Knepley for (si = 0; si < starSize * 2; si += 2) { 544bbf5ea8SMatthew G. Knepley const PetscInt cell = star[si]; 554bbf5ea8SMatthew G. Knepley PetscInt closureSize; 564bbf5ea8SMatthew G. Knepley PetscInt *closure = NULL, ci; 574bbf5ea8SMatthew G. Knepley 584bbf5ea8SMatthew G. Knepley if (cell < cStart || cell >= cEnd) continue; 594bbf5ea8SMatthew G. Knepley /* now loop over all entities in the closure of that cell */ 609566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure)); 615f824522SMatthew G. Knepley for (ci = 0; ci < closureSize * 2; ci += 2) { 624bbf5ea8SMatthew G. Knepley const PetscInt newpoint = closure[ci]; 634bbf5ea8SMatthew G. Knepley 644bbf5ea8SMatthew G. Knepley /* We've been told to ignore entities of this type.*/ 654bbf5ea8SMatthew G. Knepley if (shouldIgnore && newpoint >= iStart && newpoint < iEnd) continue; 669566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, newpoint)); 674bbf5ea8SMatthew G. Knepley } 689566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure)); 694bbf5ea8SMatthew G. Knepley } 709566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_FALSE, &starSize, &star)); 714bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 724bbf5ea8SMatthew G. Knepley } 734bbf5ea8SMatthew G. Knepley 749371c9d4SSatish Balay static PetscErrorCode PCPatchConstruct_Pardecomp(void *vpatch, DM dm, PetscInt point, PetscHSetI ht) { 75b525f888SPatrick Farrell PC_PATCH *patch = (PC_PATCH *)vpatch; 760a390943SPatrick Farrell DMLabel ghost = NULL; 770a390943SPatrick Farrell const PetscInt *leaves; 780a390943SPatrick Farrell PetscInt nleaves, pStart, pEnd, loc; 790a390943SPatrick Farrell PetscBool isFiredrake; 800a390943SPatrick Farrell PetscBool flg; 81b525f888SPatrick Farrell PetscInt starSize; 82b525f888SPatrick Farrell PetscInt *star = NULL; 8325fd193aSPatrick Farrell PetscInt opoint, overlapi; 840a390943SPatrick Farrell 850a390943SPatrick Farrell PetscFunctionBegin; 869566063dSJacob Faibussowitsch PetscCall(PetscHSetIClear(ht)); 870a390943SPatrick Farrell 889566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 890a390943SPatrick Farrell 909566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, "pyop2_ghost", &isFiredrake)); 910a390943SPatrick Farrell if (isFiredrake) { 929566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "pyop2_ghost", &ghost)); 939566063dSJacob Faibussowitsch PetscCall(DMLabelCreateIndex(ghost, pStart, pEnd)); 940a390943SPatrick Farrell } else { 950a390943SPatrick Farrell PetscSF sf; 969566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 979566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, &nleaves, &leaves, NULL)); 980a390943SPatrick Farrell nleaves = PetscMax(nleaves, 0); 990a390943SPatrick Farrell } 1000a390943SPatrick Farrell 10125fd193aSPatrick Farrell for (opoint = pStart; opoint < pEnd; ++opoint) { 1029566063dSJacob Faibussowitsch if (ghost) PetscCall(DMLabelHasPoint(ghost, opoint, &flg)); 1039371c9d4SSatish Balay else { 1049371c9d4SSatish Balay PetscCall(PetscFindInt(opoint, nleaves, leaves, &loc)); 1059371c9d4SSatish Balay flg = loc >= 0 ? PETSC_TRUE : PETSC_FALSE; 1069371c9d4SSatish Balay } 1070a390943SPatrick Farrell /* Not an owned entity, don't make a cell patch. */ 1080a390943SPatrick Farrell if (flg) continue; 1099566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, opoint)); 1100a390943SPatrick Farrell } 1110a390943SPatrick Farrell 112b525f888SPatrick Farrell /* Now build the overlap for the patch */ 11325fd193aSPatrick Farrell for (overlapi = 0; overlapi < patch->pardecomp_overlap; ++overlapi) { 114b525f888SPatrick Farrell PetscInt index = 0; 115b525f888SPatrick Farrell PetscInt *htpoints = NULL; 116b525f888SPatrick Farrell PetscInt htsize; 11725fd193aSPatrick Farrell PetscInt i; 118b525f888SPatrick Farrell 1199566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(ht, &htsize)); 1209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(htsize, &htpoints)); 1219566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(ht, &index, htpoints)); 122b525f888SPatrick Farrell 12325fd193aSPatrick Farrell for (i = 0; i < htsize; ++i) { 12425fd193aSPatrick Farrell PetscInt hpoint = htpoints[i]; 12525fd193aSPatrick Farrell PetscInt si; 126b525f888SPatrick Farrell 1279566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, hpoint, PETSC_FALSE, &starSize, &star)); 12825fd193aSPatrick Farrell for (si = 0; si < starSize * 2; si += 2) { 129b525f888SPatrick Farrell const PetscInt starp = star[si]; 130b525f888SPatrick Farrell PetscInt closureSize; 131b525f888SPatrick Farrell PetscInt *closure = NULL, ci; 132b525f888SPatrick Farrell 133b525f888SPatrick Farrell /* now loop over all entities in the closure of starp */ 1349566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, starp, PETSC_TRUE, &closureSize, &closure)); 13525fd193aSPatrick Farrell for (ci = 0; ci < closureSize * 2; ci += 2) { 136b525f888SPatrick Farrell const PetscInt closstarp = closure[ci]; 1379566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, closstarp)); 138b525f888SPatrick Farrell } 1399566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, starp, PETSC_TRUE, &closureSize, &closure)); 140b525f888SPatrick Farrell } 1419566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, hpoint, PETSC_FALSE, &starSize, &star)); 142b525f888SPatrick Farrell } 1439566063dSJacob Faibussowitsch PetscCall(PetscFree(htpoints)); 144b525f888SPatrick Farrell } 145b525f888SPatrick Farrell 1460a390943SPatrick Farrell PetscFunctionReturn(0); 1470a390943SPatrick Farrell } 1480a390943SPatrick Farrell 1494bbf5ea8SMatthew G. Knepley /* The user's already set the patches in patch->userIS. Build the hash tables */ 1509371c9d4SSatish Balay static PetscErrorCode PCPatchConstruct_User(void *vpatch, DM dm, PetscInt point, PetscHSetI ht) { 1514bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)vpatch; 1524bbf5ea8SMatthew G. Knepley IS patchis = patch->userIS[point]; 1534bbf5ea8SMatthew G. Knepley PetscInt n; 1544bbf5ea8SMatthew G. Knepley const PetscInt *patchdata; 1554bbf5ea8SMatthew G. Knepley PetscInt pStart, pEnd, i; 1564bbf5ea8SMatthew G. Knepley 1574bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 1589566063dSJacob Faibussowitsch PetscCall(PetscHSetIClear(ht)); 1599566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 1609566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(patchis, &n)); 1619566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patchis, &patchdata)); 1624bbf5ea8SMatthew G. Knepley for (i = 0; i < n; ++i) { 1634bbf5ea8SMatthew G. Knepley const PetscInt ownedpoint = patchdata[i]; 1644bbf5ea8SMatthew G. Knepley 1657a46b595SBarry Smith PetscCheck(ownedpoint >= pStart && ownedpoint < pEnd, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " was not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", ownedpoint, pStart, pEnd); 1669566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(ht, ownedpoint)); 1674bbf5ea8SMatthew G. Knepley } 1689566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patchis, &patchdata)); 1694bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 1704bbf5ea8SMatthew G. Knepley } 1714bbf5ea8SMatthew G. Knepley 1729371c9d4SSatish Balay static PetscErrorCode PCPatchCreateDefaultSF_Private(PC pc, PetscInt n, const PetscSF *sf, const PetscInt *bs) { 1734bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 1744bbf5ea8SMatthew G. Knepley PetscInt i; 1754bbf5ea8SMatthew G. Knepley 1764bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 1774bbf5ea8SMatthew G. Knepley if (n == 1 && bs[0] == 1) { 1781bb6d2a8SBarry Smith patch->sectionSF = sf[0]; 1799566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)patch->sectionSF)); 1804bbf5ea8SMatthew G. Knepley } else { 1814bbf5ea8SMatthew G. Knepley PetscInt allRoots = 0, allLeaves = 0; 1824bbf5ea8SMatthew G. Knepley PetscInt leafOffset = 0; 1834bbf5ea8SMatthew G. Knepley PetscInt *ilocal = NULL; 1844bbf5ea8SMatthew G. Knepley PetscSFNode *iremote = NULL; 1854bbf5ea8SMatthew G. Knepley PetscInt *remoteOffsets = NULL; 1864bbf5ea8SMatthew G. Knepley PetscInt index = 0; 1871b68eb51SMatthew G. Knepley PetscHMapI rankToIndex; 1884bbf5ea8SMatthew G. Knepley PetscInt numRanks = 0; 1894bbf5ea8SMatthew G. Knepley PetscSFNode *remote = NULL; 1904bbf5ea8SMatthew G. Knepley PetscSF rankSF; 1914bbf5ea8SMatthew G. Knepley PetscInt *ranks = NULL; 1924bbf5ea8SMatthew G. Knepley PetscInt *offsets = NULL; 1934bbf5ea8SMatthew G. Knepley MPI_Datatype contig; 1941b68eb51SMatthew G. Knepley PetscHSetI ranksUniq; 1954bbf5ea8SMatthew G. Knepley 1964bbf5ea8SMatthew G. Knepley /* First figure out how many dofs there are in the concatenated numbering. 197*f1580f4eSBarry Smith allRoots: number of owned global dofs; 198*f1580f4eSBarry Smith allLeaves: number of visible dofs (global + ghosted). 1994bbf5ea8SMatthew G. Knepley */ 2004bbf5ea8SMatthew G. Knepley for (i = 0; i < n; ++i) { 2014bbf5ea8SMatthew G. Knepley PetscInt nroots, nleaves; 2024bbf5ea8SMatthew G. Knepley 2039566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf[i], &nroots, &nleaves, NULL, NULL)); 2044bbf5ea8SMatthew G. Knepley allRoots += nroots * bs[i]; 2054bbf5ea8SMatthew G. Knepley allLeaves += nleaves * bs[i]; 2064bbf5ea8SMatthew G. Knepley } 2079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(allLeaves, &ilocal)); 2089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(allLeaves, &iremote)); 2094bbf5ea8SMatthew G. Knepley /* Now build an SF that just contains process connectivity. */ 2109566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&ranksUniq)); 2114bbf5ea8SMatthew G. Knepley for (i = 0; i < n; ++i) { 2124bbf5ea8SMatthew G. Knepley const PetscMPIInt *ranks = NULL; 2134bbf5ea8SMatthew G. Knepley PetscInt nranks, j; 2144bbf5ea8SMatthew G. Knepley 2159566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf[i])); 2169566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf[i], &nranks, &ranks, NULL, NULL, NULL)); 2174bbf5ea8SMatthew G. Knepley /* These are all the ranks who communicate with me. */ 21848a46eb9SPierre Jolivet for (j = 0; j < nranks; ++j) PetscCall(PetscHSetIAdd(ranksUniq, (PetscInt)ranks[j])); 2194bbf5ea8SMatthew G. Knepley } 2209566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(ranksUniq, &numRanks)); 2219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRanks, &remote)); 2229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRanks, &ranks)); 2239566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(ranksUniq, &index, ranks)); 2244bbf5ea8SMatthew G. Knepley 2259566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&rankToIndex)); 2264bbf5ea8SMatthew G. Knepley for (i = 0; i < numRanks; ++i) { 2274bbf5ea8SMatthew G. Knepley remote[i].rank = ranks[i]; 2284bbf5ea8SMatthew G. Knepley remote[i].index = 0; 2299566063dSJacob Faibussowitsch PetscCall(PetscHMapISet(rankToIndex, ranks[i], i)); 2304bbf5ea8SMatthew G. Knepley } 2319566063dSJacob Faibussowitsch PetscCall(PetscFree(ranks)); 2329566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&ranksUniq)); 2339566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)pc), &rankSF)); 2349566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(rankSF, 1, numRanks, NULL, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER)); 2359566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(rankSF)); 236*f1580f4eSBarry Smith /* OK, use it to communicate the root offset on the remote processes for each subspace. */ 2379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &offsets)); 2389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n * numRanks, &remoteOffsets)); 2394bbf5ea8SMatthew G. Knepley 2404bbf5ea8SMatthew G. Knepley offsets[0] = 0; 2414bbf5ea8SMatthew G. Knepley for (i = 1; i < n; ++i) { 2424bbf5ea8SMatthew G. Knepley PetscInt nroots; 2434bbf5ea8SMatthew G. Knepley 2449566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf[i - 1], &nroots, NULL, NULL, NULL)); 2454bbf5ea8SMatthew G. Knepley offsets[i] = offsets[i - 1] + nroots * bs[i - 1]; 2464bbf5ea8SMatthew G. Knepley } 247*f1580f4eSBarry Smith /* Offsets are the offsets on the current process of the global dof numbering for the subspaces. */ 2489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(n, MPIU_INT, &contig)); 2499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&contig)); 2504bbf5ea8SMatthew G. Knepley 2519566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(rankSF, contig, offsets, remoteOffsets, MPI_REPLACE)); 2529566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(rankSF, contig, offsets, remoteOffsets, MPI_REPLACE)); 2539566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&contig)); 2549566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 2559566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&rankSF)); 2564bbf5ea8SMatthew G. Knepley /* Now remoteOffsets contains the offsets on the remote 257*f1580f4eSBarry Smith processes who communicate with me. So now we can 258*f1580f4eSBarry Smith concatenate the list of SFs into a single one. */ 2594bbf5ea8SMatthew G. Knepley index = 0; 2604bbf5ea8SMatthew G. Knepley for (i = 0; i < n; ++i) { 2614bbf5ea8SMatthew G. Knepley const PetscSFNode *remote = NULL; 2624bbf5ea8SMatthew G. Knepley const PetscInt *local = NULL; 2634bbf5ea8SMatthew G. Knepley PetscInt nroots, nleaves, j; 2644bbf5ea8SMatthew G. Knepley 2659566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf[i], &nroots, &nleaves, &local, &remote)); 2664bbf5ea8SMatthew G. Knepley for (j = 0; j < nleaves; ++j) { 2674bbf5ea8SMatthew G. Knepley PetscInt rank = remote[j].rank; 2684bbf5ea8SMatthew G. Knepley PetscInt idx, rootOffset, k; 2694bbf5ea8SMatthew G. Knepley 2709566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(rankToIndex, rank, &idx)); 27108401ef6SPierre Jolivet PetscCheck(idx != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Didn't find rank, huh?"); 2724bbf5ea8SMatthew G. Knepley /* Offset on given rank for ith subspace */ 2734bbf5ea8SMatthew G. Knepley rootOffset = remoteOffsets[n * idx + i]; 2744bbf5ea8SMatthew G. Knepley for (k = 0; k < bs[i]; ++k) { 27573ec7555SLawrence Mitchell ilocal[index] = (local ? local[j] : j) * bs[i] + k + leafOffset; 2764bbf5ea8SMatthew G. Knepley iremote[index].rank = remote[j].rank; 2774bbf5ea8SMatthew G. Knepley iremote[index].index = remote[j].index * bs[i] + k + rootOffset; 2784bbf5ea8SMatthew G. Knepley ++index; 2794bbf5ea8SMatthew G. Knepley } 2804bbf5ea8SMatthew G. Knepley } 2814bbf5ea8SMatthew G. Knepley leafOffset += nleaves * bs[i]; 2824bbf5ea8SMatthew G. Knepley } 2839566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&rankToIndex)); 2849566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 2859566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)pc), &patch->sectionSF)); 2869566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(patch->sectionSF, allRoots, allLeaves, ilocal, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER)); 2874bbf5ea8SMatthew G. Knepley } 2884bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 2894bbf5ea8SMatthew G. Knepley } 2904bbf5ea8SMatthew G. Knepley 2919371c9d4SSatish Balay PetscErrorCode PCPatchSetDenseInverse(PC pc, PetscBool flg) { 292c73d2cf6SLawrence Mitchell PC_PATCH *patch = (PC_PATCH *)pc->data; 293c73d2cf6SLawrence Mitchell PetscFunctionBegin; 294c73d2cf6SLawrence Mitchell patch->denseinverse = flg; 295c73d2cf6SLawrence Mitchell PetscFunctionReturn(0); 296c73d2cf6SLawrence Mitchell } 297c73d2cf6SLawrence Mitchell 2989371c9d4SSatish Balay PetscErrorCode PCPatchGetDenseInverse(PC pc, PetscBool *flg) { 299c73d2cf6SLawrence Mitchell PC_PATCH *patch = (PC_PATCH *)pc->data; 300c73d2cf6SLawrence Mitchell PetscFunctionBegin; 301c73d2cf6SLawrence Mitchell *flg = patch->denseinverse; 302c73d2cf6SLawrence Mitchell PetscFunctionReturn(0); 303c73d2cf6SLawrence Mitchell } 304c73d2cf6SLawrence Mitchell 3054bbf5ea8SMatthew G. Knepley /* TODO: Docs */ 3069371c9d4SSatish Balay PetscErrorCode PCPatchSetIgnoreDim(PC pc, PetscInt dim) { 3075f824522SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 3085f824522SMatthew G. Knepley PetscFunctionBegin; 3095f824522SMatthew G. Knepley patch->ignoredim = dim; 3105f824522SMatthew G. Knepley PetscFunctionReturn(0); 3115f824522SMatthew G. Knepley } 3125f824522SMatthew G. Knepley 3135f824522SMatthew G. Knepley /* TODO: Docs */ 3149371c9d4SSatish Balay PetscErrorCode PCPatchGetIgnoreDim(PC pc, PetscInt *dim) { 3155f824522SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 3165f824522SMatthew G. Knepley PetscFunctionBegin; 3175f824522SMatthew G. Knepley *dim = patch->ignoredim; 3185f824522SMatthew G. Knepley PetscFunctionReturn(0); 3195f824522SMatthew G. Knepley } 3205f824522SMatthew G. Knepley 3215f824522SMatthew G. Knepley /* TODO: Docs */ 3229371c9d4SSatish Balay PetscErrorCode PCPatchSetSaveOperators(PC pc, PetscBool flg) { 3234bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 3244bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 3254bbf5ea8SMatthew G. Knepley patch->save_operators = flg; 3264bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 3274bbf5ea8SMatthew G. Knepley } 3284bbf5ea8SMatthew G. Knepley 3294bbf5ea8SMatthew G. Knepley /* TODO: Docs */ 3309371c9d4SSatish Balay PetscErrorCode PCPatchGetSaveOperators(PC pc, PetscBool *flg) { 3314bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 3324bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 3334bbf5ea8SMatthew G. Knepley *flg = patch->save_operators; 3344bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 3354bbf5ea8SMatthew G. Knepley } 3364bbf5ea8SMatthew G. Knepley 3374bbf5ea8SMatthew G. Knepley /* TODO: Docs */ 3389371c9d4SSatish Balay PetscErrorCode PCPatchSetPrecomputeElementTensors(PC pc, PetscBool flg) { 339fa84ea4cSLawrence Mitchell PC_PATCH *patch = (PC_PATCH *)pc->data; 340fa84ea4cSLawrence Mitchell PetscFunctionBegin; 341fa84ea4cSLawrence Mitchell patch->precomputeElementTensors = flg; 342fa84ea4cSLawrence Mitchell PetscFunctionReturn(0); 343fa84ea4cSLawrence Mitchell } 344fa84ea4cSLawrence Mitchell 345fa84ea4cSLawrence Mitchell /* TODO: Docs */ 3469371c9d4SSatish Balay PetscErrorCode PCPatchGetPrecomputeElementTensors(PC pc, PetscBool *flg) { 347fa84ea4cSLawrence Mitchell PC_PATCH *patch = (PC_PATCH *)pc->data; 348fa84ea4cSLawrence Mitchell PetscFunctionBegin; 349fa84ea4cSLawrence Mitchell *flg = patch->precomputeElementTensors; 350fa84ea4cSLawrence Mitchell PetscFunctionReturn(0); 351fa84ea4cSLawrence Mitchell } 352fa84ea4cSLawrence Mitchell 353fa84ea4cSLawrence Mitchell /* TODO: Docs */ 3549371c9d4SSatish Balay PetscErrorCode PCPatchSetPartitionOfUnity(PC pc, PetscBool flg) { 3554bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 3564bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 3574bbf5ea8SMatthew G. Knepley patch->partition_of_unity = flg; 3584bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 3594bbf5ea8SMatthew G. Knepley } 3604bbf5ea8SMatthew G. Knepley 3614bbf5ea8SMatthew G. Knepley /* TODO: Docs */ 3629371c9d4SSatish Balay PetscErrorCode PCPatchGetPartitionOfUnity(PC pc, PetscBool *flg) { 3634bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 3644bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 3654bbf5ea8SMatthew G. Knepley *flg = patch->partition_of_unity; 3664bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 3674bbf5ea8SMatthew G. Knepley } 3684bbf5ea8SMatthew G. Knepley 3694bbf5ea8SMatthew G. Knepley /* TODO: Docs */ 3709371c9d4SSatish Balay PetscErrorCode PCPatchSetLocalComposition(PC pc, PCCompositeType type) { 371c2e6f3c0SFlorian Wechsung PC_PATCH *patch = (PC_PATCH *)pc->data; 372c2e6f3c0SFlorian Wechsung PetscFunctionBegin; 3732472a847SBarry Smith PetscCheck(type == PC_COMPOSITE_ADDITIVE || type == PC_COMPOSITE_MULTIPLICATIVE, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Only supports additive or multiplicative as the local type"); 37461c4b389SFlorian Wechsung patch->local_composition_type = type; 375c2e6f3c0SFlorian Wechsung PetscFunctionReturn(0); 376c2e6f3c0SFlorian Wechsung } 377c2e6f3c0SFlorian Wechsung 378c2e6f3c0SFlorian Wechsung /* TODO: Docs */ 3799371c9d4SSatish Balay PetscErrorCode PCPatchGetLocalComposition(PC pc, PCCompositeType *type) { 380c2e6f3c0SFlorian Wechsung PC_PATCH *patch = (PC_PATCH *)pc->data; 381c2e6f3c0SFlorian Wechsung PetscFunctionBegin; 38261c4b389SFlorian Wechsung *type = patch->local_composition_type; 383c2e6f3c0SFlorian Wechsung PetscFunctionReturn(0); 384c2e6f3c0SFlorian Wechsung } 385c2e6f3c0SFlorian Wechsung 386c2e6f3c0SFlorian Wechsung /* TODO: Docs */ 3879371c9d4SSatish Balay PetscErrorCode PCPatchSetSubMatType(PC pc, MatType sub_mat_type) { 3884bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 3894bbf5ea8SMatthew G. Knepley 3904bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 3919566063dSJacob Faibussowitsch if (patch->sub_mat_type) PetscCall(PetscFree(patch->sub_mat_type)); 3929566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(sub_mat_type, (char **)&patch->sub_mat_type)); 3934bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 3944bbf5ea8SMatthew G. Knepley } 3954bbf5ea8SMatthew G. Knepley 3964bbf5ea8SMatthew G. Knepley /* TODO: Docs */ 3979371c9d4SSatish Balay PetscErrorCode PCPatchGetSubMatType(PC pc, MatType *sub_mat_type) { 3984bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 3994bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 4004bbf5ea8SMatthew G. Knepley *sub_mat_type = patch->sub_mat_type; 4014bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 4024bbf5ea8SMatthew G. Knepley } 4034bbf5ea8SMatthew G. Knepley 4044bbf5ea8SMatthew G. Knepley /* TODO: Docs */ 4059371c9d4SSatish Balay PetscErrorCode PCPatchSetCellNumbering(PC pc, PetscSection cellNumbering) { 4064bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 4074bbf5ea8SMatthew G. Knepley 4084bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 4094bbf5ea8SMatthew G. Knepley patch->cellNumbering = cellNumbering; 4109566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)cellNumbering)); 4114bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 4124bbf5ea8SMatthew G. Knepley } 4134bbf5ea8SMatthew G. Knepley 4144bbf5ea8SMatthew G. Knepley /* TODO: Docs */ 4159371c9d4SSatish Balay PetscErrorCode PCPatchGetCellNumbering(PC pc, PetscSection *cellNumbering) { 4164bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 4174bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 4184bbf5ea8SMatthew G. Knepley *cellNumbering = patch->cellNumbering; 4194bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 4204bbf5ea8SMatthew G. Knepley } 4214bbf5ea8SMatthew G. Knepley 4224bbf5ea8SMatthew G. Knepley /* TODO: Docs */ 4239371c9d4SSatish Balay PetscErrorCode PCPatchSetConstructType(PC pc, PCPatchConstructType ctype, PetscErrorCode (*func)(PC, PetscInt *, IS **, IS *, void *), void *ctx) { 4244bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 4254bbf5ea8SMatthew G. Knepley 4264bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 4274bbf5ea8SMatthew G. Knepley patch->ctype = ctype; 4284bbf5ea8SMatthew G. Knepley switch (ctype) { 4294bbf5ea8SMatthew G. Knepley case PC_PATCH_STAR: 43040c17a03SPatrick Farrell patch->user_patches = PETSC_FALSE; 4314bbf5ea8SMatthew G. Knepley patch->patchconstructop = PCPatchConstruct_Star; 4324bbf5ea8SMatthew G. Knepley break; 4334bbf5ea8SMatthew G. Knepley case PC_PATCH_VANKA: 43440c17a03SPatrick Farrell patch->user_patches = PETSC_FALSE; 4354bbf5ea8SMatthew G. Knepley patch->patchconstructop = PCPatchConstruct_Vanka; 4364bbf5ea8SMatthew G. Knepley break; 437e5b9877fSPatrick Farrell case PC_PATCH_PARDECOMP: 4380a390943SPatrick Farrell patch->user_patches = PETSC_FALSE; 439e5b9877fSPatrick Farrell patch->patchconstructop = PCPatchConstruct_Pardecomp; 4400a390943SPatrick Farrell break; 4414bbf5ea8SMatthew G. Knepley case PC_PATCH_USER: 4424bbf5ea8SMatthew G. Knepley case PC_PATCH_PYTHON: 4434bbf5ea8SMatthew G. Knepley patch->user_patches = PETSC_TRUE; 4444bbf5ea8SMatthew G. Knepley patch->patchconstructop = PCPatchConstruct_User; 445bdd9e0cdSPatrick Farrell if (func) { 4464bbf5ea8SMatthew G. Knepley patch->userpatchconstructionop = func; 4474bbf5ea8SMatthew G. Knepley patch->userpatchconstructctx = ctx; 448bdd9e0cdSPatrick Farrell } 4494bbf5ea8SMatthew G. Knepley break; 4509371c9d4SSatish Balay default: SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "Unknown patch construction type %" PetscInt_FMT, (PetscInt)patch->ctype); 4514bbf5ea8SMatthew G. Knepley } 4524bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 4534bbf5ea8SMatthew G. Knepley } 4544bbf5ea8SMatthew G. Knepley 4554bbf5ea8SMatthew G. Knepley /* TODO: Docs */ 4569371c9d4SSatish Balay PetscErrorCode PCPatchGetConstructType(PC pc, PCPatchConstructType *ctype, PetscErrorCode (**func)(PC, PetscInt *, IS **, IS *, void *), void **ctx) { 4574bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 4584bbf5ea8SMatthew G. Knepley 4594bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 4604bbf5ea8SMatthew G. Knepley *ctype = patch->ctype; 4614bbf5ea8SMatthew G. Knepley switch (patch->ctype) { 4624bbf5ea8SMatthew G. Knepley case PC_PATCH_STAR: 4634bbf5ea8SMatthew G. Knepley case PC_PATCH_VANKA: 4649371c9d4SSatish Balay case PC_PATCH_PARDECOMP: break; 4654bbf5ea8SMatthew G. Knepley case PC_PATCH_USER: 4664bbf5ea8SMatthew G. Knepley case PC_PATCH_PYTHON: 4674bbf5ea8SMatthew G. Knepley *func = patch->userpatchconstructionop; 4684bbf5ea8SMatthew G. Knepley *ctx = patch->userpatchconstructctx; 4694bbf5ea8SMatthew G. Knepley break; 4709371c9d4SSatish Balay default: SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "Unknown patch construction type %" PetscInt_FMT, (PetscInt)patch->ctype); 4714bbf5ea8SMatthew G. Knepley } 4724bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 4734bbf5ea8SMatthew G. Knepley } 4744bbf5ea8SMatthew G. Knepley 4754bbf5ea8SMatthew G. Knepley /* TODO: Docs */ 4769371c9d4SSatish Balay PetscErrorCode PCPatchSetDiscretisationInfo(PC pc, PetscInt nsubspaces, DM *dms, PetscInt *bs, PetscInt *nodesPerCell, const PetscInt **cellNodeMap, const PetscInt *subspaceOffsets, PetscInt numGhostBcs, const PetscInt *ghostBcNodes, PetscInt numGlobalBcs, const PetscInt *globalBcNodes) { 4774bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 478b6bb21d1SLawrence Mitchell DM dm, plex; 4794bbf5ea8SMatthew G. Knepley PetscSF *sfs; 4805f824522SMatthew G. Knepley PetscInt cStart, cEnd, i, j; 4814bbf5ea8SMatthew G. Knepley 4824bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 4839566063dSJacob Faibussowitsch PetscCall(PCGetDM(pc, &dm)); 4849566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 485b6bb21d1SLawrence Mitchell dm = plex; 4869566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 4879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nsubspaces, &sfs)); 4889566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nsubspaces, &patch->dofSection)); 4899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nsubspaces, &patch->bs)); 4909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nsubspaces, &patch->nodesPerCell)); 4919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nsubspaces, &patch->cellNodeMap)); 4929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nsubspaces + 1, &patch->subspaceOffsets)); 4934bbf5ea8SMatthew G. Knepley 4944bbf5ea8SMatthew G. Knepley patch->nsubspaces = nsubspaces; 4954bbf5ea8SMatthew G. Knepley patch->totalDofsPerCell = 0; 4964bbf5ea8SMatthew G. Knepley for (i = 0; i < nsubspaces; ++i) { 4979566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dms[i], &patch->dofSection[i])); 4989566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)patch->dofSection[i])); 4999566063dSJacob Faibussowitsch PetscCall(DMGetSectionSF(dms[i], &sfs[i])); 5004bbf5ea8SMatthew G. Knepley patch->bs[i] = bs[i]; 5014bbf5ea8SMatthew G. Knepley patch->nodesPerCell[i] = nodesPerCell[i]; 5024bbf5ea8SMatthew G. Knepley patch->totalDofsPerCell += nodesPerCell[i] * bs[i]; 5039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((cEnd - cStart) * nodesPerCell[i], &patch->cellNodeMap[i])); 50480e8a965SFlorian Wechsung for (j = 0; j < (cEnd - cStart) * nodesPerCell[i]; ++j) patch->cellNodeMap[i][j] = cellNodeMap[i][j]; 5054bbf5ea8SMatthew G. Knepley patch->subspaceOffsets[i] = subspaceOffsets[i]; 5064bbf5ea8SMatthew G. Knepley } 5079566063dSJacob Faibussowitsch PetscCall(PCPatchCreateDefaultSF_Private(pc, nsubspaces, sfs, patch->bs)); 5089566063dSJacob Faibussowitsch PetscCall(PetscFree(sfs)); 5094bbf5ea8SMatthew G. Knepley 5104bbf5ea8SMatthew G. Knepley patch->subspaceOffsets[nsubspaces] = subspaceOffsets[nsubspaces]; 5119566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numGhostBcs, ghostBcNodes, PETSC_COPY_VALUES, &patch->ghostBcNodes)); 5129566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numGlobalBcs, globalBcNodes, PETSC_COPY_VALUES, &patch->globalBcNodes)); 5139566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dm)); 5144bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 5154bbf5ea8SMatthew G. Knepley } 5164bbf5ea8SMatthew G. Knepley 5174bbf5ea8SMatthew G. Knepley /* TODO: Docs */ 5189371c9d4SSatish Balay PetscErrorCode PCPatchSetDiscretisationInfoCombined(PC pc, DM dm, PetscInt *nodesPerCell, const PetscInt **cellNodeMap, PetscInt numGhostBcs, const PetscInt *ghostBcNodes, PetscInt numGlobalBcs, const PetscInt *globalBcNodes) { 5195f824522SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 5205f824522SMatthew G. Knepley PetscInt cStart, cEnd, i, j; 5215f824522SMatthew G. Knepley 5225f824522SMatthew G. Knepley PetscFunctionBegin; 5235f824522SMatthew G. Knepley patch->combined = PETSC_TRUE; 5249566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 5259566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &patch->nsubspaces)); 5269566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(patch->nsubspaces, &patch->dofSection)); 5279566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(patch->nsubspaces, &patch->bs)); 5289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(patch->nsubspaces, &patch->nodesPerCell)); 5299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(patch->nsubspaces, &patch->cellNodeMap)); 5309566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(patch->nsubspaces + 1, &patch->subspaceOffsets)); 5319566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, &patch->dofSection[0])); 5329566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)patch->dofSection[0])); 5339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(patch->dofSection[0], &patch->subspaceOffsets[patch->nsubspaces])); 5345f824522SMatthew G. Knepley patch->totalDofsPerCell = 0; 5355f824522SMatthew G. Knepley for (i = 0; i < patch->nsubspaces; ++i) { 5365f824522SMatthew G. Knepley patch->bs[i] = 1; 5375f824522SMatthew G. Knepley patch->nodesPerCell[i] = nodesPerCell[i]; 5385f824522SMatthew G. Knepley patch->totalDofsPerCell += nodesPerCell[i]; 5399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((cEnd - cStart) * nodesPerCell[i], &patch->cellNodeMap[i])); 5405f824522SMatthew G. Knepley for (j = 0; j < (cEnd - cStart) * nodesPerCell[i]; ++j) patch->cellNodeMap[i][j] = cellNodeMap[i][j]; 5415f824522SMatthew G. Knepley } 5429566063dSJacob Faibussowitsch PetscCall(DMGetSectionSF(dm, &patch->sectionSF)); 5439566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)patch->sectionSF)); 5449566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numGhostBcs, ghostBcNodes, PETSC_COPY_VALUES, &patch->ghostBcNodes)); 5459566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numGlobalBcs, globalBcNodes, PETSC_COPY_VALUES, &patch->globalBcNodes)); 5465f824522SMatthew G. Knepley PetscFunctionReturn(0); 5475f824522SMatthew G. Knepley } 5485f824522SMatthew G. Knepley 5495f824522SMatthew G. Knepley /*@C 5505f824522SMatthew G. Knepley 55192d50984SMatthew G. Knepley PCPatchSetComputeFunction - Set the callback used to compute patch residuals 55292d50984SMatthew G. Knepley 553*f1580f4eSBarry Smith Logically collective on pc 55499b7e5c6SPatrick Farrell 55592d50984SMatthew G. Knepley Input Parameters: 55692d50984SMatthew G. Knepley + pc - The PC 55792d50984SMatthew G. Knepley . func - The callback 55892d50984SMatthew G. Knepley - ctx - The user context 55992d50984SMatthew G. Knepley 5607a50e09dSPatrick Farrell Calling sequence of func: 5617a50e09dSPatrick Farrell $ func (PC pc,PetscInt point,Vec x,Vec f,IS cellIS,PetscInt n,const PetscInt* dofsArray,const PetscInt* dofsArrayWithAll,void* ctx) 5627a50e09dSPatrick Farrell 5637a50e09dSPatrick Farrell + pc - The PC 5647a50e09dSPatrick Farrell . point - The point 5657a50e09dSPatrick Farrell . x - The input solution (not used in linear problems) 5667a50e09dSPatrick Farrell . f - The patch residual vector 5677a50e09dSPatrick Farrell . cellIS - An array of the cell numbers 5687a50e09dSPatrick Farrell . n - The size of dofsArray 5697a50e09dSPatrick Farrell . dofsArray - The dofmap for the dofs to be solved for 5707a50e09dSPatrick Farrell . dofsArrayWithAll - The dofmap for all dofs on the patch 5717a50e09dSPatrick Farrell - ctx - The user context 5727a50e09dSPatrick Farrell 57392d50984SMatthew G. Knepley Level: advanced 57492d50984SMatthew G. Knepley 575*f1580f4eSBarry Smith Note: 57626dc5b63SLawrence Mitchell The entries of F (the output residual vector) have been set to zero before the call. 57792d50984SMatthew G. Knepley 578db781477SPatrick Sanan .seealso: `PCPatchSetComputeOperator()`, `PCPatchGetComputeOperator()`, `PCPatchSetDiscretisationInfo()`, `PCPatchSetComputeFunctionInteriorFacets()` 57992d50984SMatthew G. Knepley @*/ 5809371c9d4SSatish Balay PetscErrorCode PCPatchSetComputeFunction(PC pc, PetscErrorCode (*func)(PC, PetscInt, Vec, Vec, IS, PetscInt, const PetscInt *, const PetscInt *, void *), void *ctx) { 58192d50984SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 58292d50984SMatthew G. Knepley 58392d50984SMatthew G. Knepley PetscFunctionBegin; 58492d50984SMatthew G. Knepley patch->usercomputef = func; 58592d50984SMatthew G. Knepley patch->usercomputefctx = ctx; 58692d50984SMatthew G. Knepley PetscFunctionReturn(0); 58792d50984SMatthew G. Knepley } 58892d50984SMatthew G. Knepley 58992d50984SMatthew G. Knepley /*@C 59092d50984SMatthew G. Knepley 59159109abcSLawrence Mitchell PCPatchSetComputeFunctionInteriorFacets - Set the callback used to compute facet integrals for patch residuals 59259109abcSLawrence Mitchell 593*f1580f4eSBarry Smith Logically collective on pc 5947a50e09dSPatrick Farrell 59559109abcSLawrence Mitchell Input Parameters: 59659109abcSLawrence Mitchell + pc - The PC 59759109abcSLawrence Mitchell . func - The callback 59859109abcSLawrence Mitchell - ctx - The user context 59959109abcSLawrence Mitchell 6007a50e09dSPatrick Farrell Calling sequence of func: 6017a50e09dSPatrick Farrell $ func (PC pc,PetscInt point,Vec x,Vec f,IS facetIS,PetscInt n,const PetscInt* dofsArray,const PetscInt* dofsArrayWithAll,void* ctx) 6027a50e09dSPatrick Farrell 6037a50e09dSPatrick Farrell + pc - The PC 6047a50e09dSPatrick Farrell . point - The point 6057a50e09dSPatrick Farrell . x - The input solution (not used in linear problems) 6067a50e09dSPatrick Farrell . f - The patch residual vector 6077a50e09dSPatrick Farrell . facetIS - An array of the facet numbers 6087a50e09dSPatrick Farrell . n - The size of dofsArray 6097a50e09dSPatrick Farrell . dofsArray - The dofmap for the dofs to be solved for 6107a50e09dSPatrick Farrell . dofsArrayWithAll - The dofmap for all dofs on the patch 6117a50e09dSPatrick Farrell - ctx - The user context 6127a50e09dSPatrick Farrell 61359109abcSLawrence Mitchell Level: advanced 61459109abcSLawrence Mitchell 615*f1580f4eSBarry Smith Note: 61626dc5b63SLawrence Mitchell The entries of F (the output residual vector) have been set to zero before the call. 61759109abcSLawrence Mitchell 618db781477SPatrick Sanan .seealso: `PCPatchSetComputeOperator()`, `PCPatchGetComputeOperator()`, `PCPatchSetDiscretisationInfo()`, `PCPatchSetComputeFunction()` 61959109abcSLawrence Mitchell @*/ 6209371c9d4SSatish Balay PetscErrorCode PCPatchSetComputeFunctionInteriorFacets(PC pc, PetscErrorCode (*func)(PC, PetscInt, Vec, Vec, IS, PetscInt, const PetscInt *, const PetscInt *, void *), void *ctx) { 62159109abcSLawrence Mitchell PC_PATCH *patch = (PC_PATCH *)pc->data; 62259109abcSLawrence Mitchell 62359109abcSLawrence Mitchell PetscFunctionBegin; 62459109abcSLawrence Mitchell patch->usercomputefintfacet = func; 62559109abcSLawrence Mitchell patch->usercomputefintfacetctx = ctx; 62659109abcSLawrence Mitchell PetscFunctionReturn(0); 62759109abcSLawrence Mitchell } 62859109abcSLawrence Mitchell 62959109abcSLawrence Mitchell /*@C 63059109abcSLawrence Mitchell 6315f824522SMatthew G. Knepley PCPatchSetComputeOperator - Set the callback used to compute patch matrices 6325f824522SMatthew G. Knepley 633*f1580f4eSBarry Smith Logically collective on pc 6347a50e09dSPatrick Farrell 6355f824522SMatthew G. Knepley Input Parameters: 6365f824522SMatthew G. Knepley + pc - The PC 6375f824522SMatthew G. Knepley . func - The callback 6385f824522SMatthew G. Knepley - ctx - The user context 6395f824522SMatthew G. Knepley 6407a50e09dSPatrick Farrell Calling sequence of func: 6417a50e09dSPatrick Farrell $ func (PC pc,PetscInt point,Vec x,Mat mat,IS facetIS,PetscInt n,const PetscInt* dofsArray,const PetscInt* dofsArrayWithAll,void* ctx) 6427a50e09dSPatrick Farrell 6437a50e09dSPatrick Farrell + pc - The PC 6447a50e09dSPatrick Farrell . point - The point 6457a50e09dSPatrick Farrell . x - The input solution (not used in linear problems) 6467a50e09dSPatrick Farrell . mat - The patch matrix 6477a50e09dSPatrick Farrell . cellIS - An array of the cell numbers 6487a50e09dSPatrick Farrell . n - The size of dofsArray 6497a50e09dSPatrick Farrell . dofsArray - The dofmap for the dofs to be solved for 6507a50e09dSPatrick Farrell . dofsArrayWithAll - The dofmap for all dofs on the patch 6517a50e09dSPatrick Farrell - ctx - The user context 6527a50e09dSPatrick Farrell 6535f824522SMatthew G. Knepley Level: advanced 6545f824522SMatthew G. Knepley 655*f1580f4eSBarry Smith Note: 6567a50e09dSPatrick Farrell The matrix entries have been set to zero before the call. 6575f824522SMatthew G. Knepley 658db781477SPatrick Sanan .seealso: `PCPatchGetComputeOperator()`, `PCPatchSetComputeFunction()`, `PCPatchSetDiscretisationInfo()` 6595f824522SMatthew G. Knepley @*/ 6609371c9d4SSatish Balay PetscErrorCode PCPatchSetComputeOperator(PC pc, PetscErrorCode (*func)(PC, PetscInt, Vec, Mat, IS, PetscInt, const PetscInt *, const PetscInt *, void *), void *ctx) { 6614bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 6624bbf5ea8SMatthew G. Knepley 6634bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 6644bbf5ea8SMatthew G. Knepley patch->usercomputeop = func; 665723f9013SMatthew G. Knepley patch->usercomputeopctx = ctx; 6664bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 6674bbf5ea8SMatthew G. Knepley } 6684bbf5ea8SMatthew G. Knepley 66959109abcSLawrence Mitchell /*@C 67059109abcSLawrence Mitchell 6717a50e09dSPatrick Farrell PCPatchSetComputeOperatorInteriorFacets - Set the callback used to compute facet integrals for patch matrices 67259109abcSLawrence Mitchell 673*f1580f4eSBarry Smith Logically collective on pc 67499b7e5c6SPatrick Farrell 67559109abcSLawrence Mitchell Input Parameters: 67659109abcSLawrence Mitchell + pc - The PC 67759109abcSLawrence Mitchell . func - The callback 67859109abcSLawrence Mitchell - ctx - The user context 67959109abcSLawrence Mitchell 6807a50e09dSPatrick Farrell Calling sequence of func: 6817a50e09dSPatrick Farrell $ func (PC pc,PetscInt point,Vec x,Mat mat,IS facetIS,PetscInt n,const PetscInt* dofsArray,const PetscInt* dofsArrayWithAll,void* ctx) 6827a50e09dSPatrick Farrell 6837a50e09dSPatrick Farrell + pc - The PC 6847a50e09dSPatrick Farrell . point - The point 6857a50e09dSPatrick Farrell . x - The input solution (not used in linear problems) 6867a50e09dSPatrick Farrell . mat - The patch matrix 6877a50e09dSPatrick Farrell . facetIS - An array of the facet numbers 6887a50e09dSPatrick Farrell . n - The size of dofsArray 6897a50e09dSPatrick Farrell . dofsArray - The dofmap for the dofs to be solved for 6907a50e09dSPatrick Farrell . dofsArrayWithAll - The dofmap for all dofs on the patch 6917a50e09dSPatrick Farrell - ctx - The user context 6927a50e09dSPatrick Farrell 69359109abcSLawrence Mitchell Level: advanced 69459109abcSLawrence Mitchell 695*f1580f4eSBarry Smith Note: 6967a50e09dSPatrick Farrell The matrix entries have been set to zero before the call. 69759109abcSLawrence Mitchell 698db781477SPatrick Sanan .seealso: `PCPatchGetComputeOperator()`, `PCPatchSetComputeFunction()`, `PCPatchSetDiscretisationInfo()` 69959109abcSLawrence Mitchell @*/ 7009371c9d4SSatish Balay PetscErrorCode PCPatchSetComputeOperatorInteriorFacets(PC pc, PetscErrorCode (*func)(PC, PetscInt, Vec, Mat, IS, PetscInt, const PetscInt *, const PetscInt *, void *), void *ctx) { 70159109abcSLawrence Mitchell PC_PATCH *patch = (PC_PATCH *)pc->data; 70259109abcSLawrence Mitchell 70359109abcSLawrence Mitchell PetscFunctionBegin; 70459109abcSLawrence Mitchell patch->usercomputeopintfacet = func; 70559109abcSLawrence Mitchell patch->usercomputeopintfacetctx = ctx; 70659109abcSLawrence Mitchell PetscFunctionReturn(0); 70759109abcSLawrence Mitchell } 70859109abcSLawrence Mitchell 7094bbf5ea8SMatthew G. Knepley /* On entry, ht contains the topological entities whose dofs we are responsible for solving for; 7104bbf5ea8SMatthew G. Knepley on exit, cht contains all the topological entities we need to compute their residuals. 7114bbf5ea8SMatthew G. Knepley In full generality this should incorporate knowledge of the sparsity pattern of the matrix; 7124bbf5ea8SMatthew G. Knepley here we assume a standard FE sparsity pattern.*/ 7134bbf5ea8SMatthew G. Knepley /* TODO: Use DMPlexGetAdjacency() */ 7149371c9d4SSatish Balay static PetscErrorCode PCPatchCompleteCellPatch(PC pc, PetscHSetI ht, PetscHSetI cht) { 715b6bb21d1SLawrence Mitchell DM dm, plex; 716bc7fa33aSFlorian Wechsung PC_PATCH *patch = (PC_PATCH *)pc->data; 7171b68eb51SMatthew G. Knepley PetscHashIter hi; 7184bbf5ea8SMatthew G. Knepley PetscInt point; 7194bbf5ea8SMatthew G. Knepley PetscInt *star = NULL, *closure = NULL; 7204c954380SMatthew G. Knepley PetscInt ignoredim, iStart = 0, iEnd = -1, starSize, closureSize, si, ci; 721bc7fa33aSFlorian Wechsung PetscInt *fStar = NULL, *fClosure = NULL; 722bc7fa33aSFlorian Wechsung PetscInt fBegin, fEnd, fsi, fci, fStarSize, fClosureSize; 7234bbf5ea8SMatthew G. Knepley 7244bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 7259566063dSJacob Faibussowitsch PetscCall(PCGetDM(pc, &dm)); 7269566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 727b6bb21d1SLawrence Mitchell dm = plex; 7289566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fBegin, &fEnd)); 7299566063dSJacob Faibussowitsch PetscCall(PCPatchGetIgnoreDim(pc, &ignoredim)); 7309566063dSJacob Faibussowitsch if (ignoredim >= 0) PetscCall(DMPlexGetDepthStratum(dm, ignoredim, &iStart, &iEnd)); 7319566063dSJacob Faibussowitsch PetscCall(PetscHSetIClear(cht)); 7321b68eb51SMatthew G. Knepley PetscHashIterBegin(ht, hi); 7331b68eb51SMatthew G. Knepley while (!PetscHashIterAtEnd(ht, hi)) { 7341b68eb51SMatthew G. Knepley PetscHashIterGetKey(ht, hi, point); 7351b68eb51SMatthew G. Knepley PetscHashIterNext(ht, hi); 7364bbf5ea8SMatthew G. Knepley 7374bbf5ea8SMatthew G. Knepley /* Loop over all the cells that this point connects to */ 7389566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_FALSE, &starSize, &star)); 7395f824522SMatthew G. Knepley for (si = 0; si < starSize * 2; si += 2) { 7404c954380SMatthew G. Knepley const PetscInt ownedpoint = star[si]; 7415f824522SMatthew G. Knepley /* TODO Check for point in cht before running through closure again */ 7424bbf5ea8SMatthew G. Knepley /* now loop over all entities in the closure of that cell */ 7439566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, ownedpoint, PETSC_TRUE, &closureSize, &closure)); 7445f824522SMatthew G. Knepley for (ci = 0; ci < closureSize * 2; ci += 2) { 7454c954380SMatthew G. Knepley const PetscInt seenpoint = closure[ci]; 7465f824522SMatthew G. Knepley if (ignoredim >= 0 && seenpoint >= iStart && seenpoint < iEnd) continue; 7479566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(cht, seenpoint)); 748bc7fa33aSFlorian Wechsung /* Facet integrals couple dofs across facets, so in that case for each of 749*f1580f4eSBarry Smith the facets we need to add all dofs on the other side of the facet to 750*f1580f4eSBarry Smith the seen dofs. */ 751bc7fa33aSFlorian Wechsung if (patch->usercomputeopintfacet) { 752bc7fa33aSFlorian Wechsung if (fBegin <= seenpoint && seenpoint < fEnd) { 7539566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, seenpoint, PETSC_FALSE, &fStarSize, &fStar)); 754bc7fa33aSFlorian Wechsung for (fsi = 0; fsi < fStarSize * 2; fsi += 2) { 7559566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, fStar[fsi], PETSC_TRUE, &fClosureSize, &fClosure)); 75648a46eb9SPierre Jolivet for (fci = 0; fci < fClosureSize * 2; fci += 2) PetscCall(PetscHSetIAdd(cht, fClosure[fci])); 7579566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, fStar[fsi], PETSC_TRUE, NULL, &fClosure)); 758bc7fa33aSFlorian Wechsung } 7599566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, seenpoint, PETSC_FALSE, NULL, &fStar)); 760bc7fa33aSFlorian Wechsung } 761bc7fa33aSFlorian Wechsung } 7624bbf5ea8SMatthew G. Knepley } 7639566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, ownedpoint, PETSC_TRUE, NULL, &closure)); 7644bbf5ea8SMatthew G. Knepley } 7659566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_FALSE, NULL, &star)); 7664bbf5ea8SMatthew G. Knepley } 7679566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dm)); 7685f824522SMatthew G. Knepley PetscFunctionReturn(0); 7695f824522SMatthew G. Knepley } 7705f824522SMatthew G. Knepley 7719371c9d4SSatish Balay static PetscErrorCode PCPatchGetGlobalDofs(PC pc, PetscSection dofSection[], PetscInt f, PetscBool combined, PetscInt p, PetscInt *dof, PetscInt *off) { 7725f824522SMatthew G. Knepley PetscFunctionBegin; 7735f824522SMatthew G. Knepley if (combined) { 7745f824522SMatthew G. Knepley if (f < 0) { 7759566063dSJacob Faibussowitsch if (dof) PetscCall(PetscSectionGetDof(dofSection[0], p, dof)); 7769566063dSJacob Faibussowitsch if (off) PetscCall(PetscSectionGetOffset(dofSection[0], p, off)); 7775f824522SMatthew G. Knepley } else { 7789566063dSJacob Faibussowitsch if (dof) PetscCall(PetscSectionGetFieldDof(dofSection[0], p, f, dof)); 7799566063dSJacob Faibussowitsch if (off) PetscCall(PetscSectionGetFieldOffset(dofSection[0], p, f, off)); 7805f824522SMatthew G. Knepley } 7815f824522SMatthew G. Knepley } else { 7825f824522SMatthew G. Knepley if (f < 0) { 7835f824522SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 7845f824522SMatthew G. Knepley PetscInt fdof, g; 7855f824522SMatthew G. Knepley 7865f824522SMatthew G. Knepley if (dof) { 7875f824522SMatthew G. Knepley *dof = 0; 7885f824522SMatthew G. Knepley for (g = 0; g < patch->nsubspaces; ++g) { 7899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(dofSection[g], p, &fdof)); 7905f824522SMatthew G. Knepley *dof += fdof; 7915f824522SMatthew G. Knepley } 7925f824522SMatthew G. Knepley } 793624e31c3SLawrence Mitchell if (off) { 794624e31c3SLawrence Mitchell *off = 0; 795624e31c3SLawrence Mitchell for (g = 0; g < patch->nsubspaces; ++g) { 7969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(dofSection[g], p, &fdof)); 797624e31c3SLawrence Mitchell *off += fdof; 798624e31c3SLawrence Mitchell } 799624e31c3SLawrence Mitchell } 8005f824522SMatthew G. Knepley } else { 8019566063dSJacob Faibussowitsch if (dof) PetscCall(PetscSectionGetDof(dofSection[f], p, dof)); 8029566063dSJacob Faibussowitsch if (off) PetscCall(PetscSectionGetOffset(dofSection[f], p, off)); 8035f824522SMatthew G. Knepley } 8045f824522SMatthew G. Knepley } 8054bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 8064bbf5ea8SMatthew G. Knepley } 8074bbf5ea8SMatthew G. Knepley 8084bbf5ea8SMatthew G. Knepley /* Given a hash table with a set of topological entities (pts), compute the degrees of 8094bbf5ea8SMatthew G. Knepley freedom in global concatenated numbering on those entities. 8104bbf5ea8SMatthew G. Knepley For Vanka smoothing, this needs to do something special: ignore dofs of the 8114bbf5ea8SMatthew G. Knepley constraint subspace on entities that aren't the base entity we're building the patch 8124bbf5ea8SMatthew G. Knepley around. */ 8139371c9d4SSatish Balay static PetscErrorCode PCPatchGetPointDofs(PC pc, PetscHSetI pts, PetscHSetI dofs, PetscInt base, PetscHSetI *subspaces_to_exclude) { 8145f824522SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 8151b68eb51SMatthew G. Knepley PetscHashIter hi; 8164bbf5ea8SMatthew G. Knepley PetscInt ldof, loff; 8174bbf5ea8SMatthew G. Knepley PetscInt k, p; 8184bbf5ea8SMatthew G. Knepley 8194bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 8209566063dSJacob Faibussowitsch PetscCall(PetscHSetIClear(dofs)); 8214bbf5ea8SMatthew G. Knepley for (k = 0; k < patch->nsubspaces; ++k) { 8224bbf5ea8SMatthew G. Knepley PetscInt subspaceOffset = patch->subspaceOffsets[k]; 8234bbf5ea8SMatthew G. Knepley PetscInt bs = patch->bs[k]; 8244bbf5ea8SMatthew G. Knepley PetscInt j, l; 8254bbf5ea8SMatthew G. Knepley 826e4c66b91SPatrick Farrell if (subspaces_to_exclude != NULL) { 827e4c66b91SPatrick Farrell PetscBool should_exclude_k = PETSC_FALSE; 8289566063dSJacob Faibussowitsch PetscCall(PetscHSetIHas(*subspaces_to_exclude, k, &should_exclude_k)); 829e4c66b91SPatrick Farrell if (should_exclude_k) { 8304bbf5ea8SMatthew G. Knepley /* only get this subspace dofs at the base entity, not any others */ 8319566063dSJacob Faibussowitsch PetscCall(PCPatchGetGlobalDofs(pc, patch->dofSection, k, patch->combined, base, &ldof, &loff)); 8324bbf5ea8SMatthew G. Knepley if (0 == ldof) continue; 8334bbf5ea8SMatthew G. Knepley for (j = loff; j < ldof + loff; ++j) { 8344bbf5ea8SMatthew G. Knepley for (l = 0; l < bs; ++l) { 8354bbf5ea8SMatthew G. Knepley PetscInt dof = bs * j + l + subspaceOffset; 8369566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(dofs, dof)); 8374bbf5ea8SMatthew G. Knepley } 8384bbf5ea8SMatthew G. Knepley } 8394bbf5ea8SMatthew G. Knepley continue; /* skip the other dofs of this subspace */ 8404bbf5ea8SMatthew G. Knepley } 841e4c66b91SPatrick Farrell } 8424bbf5ea8SMatthew G. Knepley 8431b68eb51SMatthew G. Knepley PetscHashIterBegin(pts, hi); 8441b68eb51SMatthew G. Knepley while (!PetscHashIterAtEnd(pts, hi)) { 8451b68eb51SMatthew G. Knepley PetscHashIterGetKey(pts, hi, p); 8461b68eb51SMatthew G. Knepley PetscHashIterNext(pts, hi); 8479566063dSJacob Faibussowitsch PetscCall(PCPatchGetGlobalDofs(pc, patch->dofSection, k, patch->combined, p, &ldof, &loff)); 8484bbf5ea8SMatthew G. Knepley if (0 == ldof) continue; 8494bbf5ea8SMatthew G. Knepley for (j = loff; j < ldof + loff; ++j) { 8504bbf5ea8SMatthew G. Knepley for (l = 0; l < bs; ++l) { 8514bbf5ea8SMatthew G. Knepley PetscInt dof = bs * j + l + subspaceOffset; 8529566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(dofs, dof)); 8534bbf5ea8SMatthew G. Knepley } 8544bbf5ea8SMatthew G. Knepley } 8554bbf5ea8SMatthew G. Knepley } 8564bbf5ea8SMatthew G. Knepley } 8574bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 8584bbf5ea8SMatthew G. Knepley } 8594bbf5ea8SMatthew G. Knepley 8604bbf5ea8SMatthew G. Knepley /* Given two hash tables A and B, compute the keys in B that are not in A, and put them in C */ 8619371c9d4SSatish Balay static PetscErrorCode PCPatchComputeSetDifference_Private(PetscHSetI A, PetscHSetI B, PetscHSetI C) { 8621b68eb51SMatthew G. Knepley PetscHashIter hi; 8631b68eb51SMatthew G. Knepley PetscInt key; 8644bbf5ea8SMatthew G. Knepley PetscBool flg; 8654bbf5ea8SMatthew G. Knepley 8664bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 8679566063dSJacob Faibussowitsch PetscCall(PetscHSetIClear(C)); 8681b68eb51SMatthew G. Knepley PetscHashIterBegin(B, hi); 8691b68eb51SMatthew G. Knepley while (!PetscHashIterAtEnd(B, hi)) { 8701b68eb51SMatthew G. Knepley PetscHashIterGetKey(B, hi, key); 8711b68eb51SMatthew G. Knepley PetscHashIterNext(B, hi); 8729566063dSJacob Faibussowitsch PetscCall(PetscHSetIHas(A, key, &flg)); 8739566063dSJacob Faibussowitsch if (!flg) PetscCall(PetscHSetIAdd(C, key)); 8744bbf5ea8SMatthew G. Knepley } 8754bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 8764bbf5ea8SMatthew G. Knepley } 8774bbf5ea8SMatthew G. Knepley 8784bbf5ea8SMatthew G. Knepley /* 879*f1580f4eSBarry Smith PCPatchCreateCellPatches - create patches. 880*f1580f4eSBarry Smith 881*f1580f4eSBarry Smith Input Parameter: 882*f1580f4eSBarry Smith . dm - The DMPlex object defining the mesh 883*f1580f4eSBarry Smith 884*f1580f4eSBarry Smith Output Parameters: 885*f1580f4eSBarry Smith + cellCounts - Section with counts of cells around each vertex 886*f1580f4eSBarry Smith . cells - IS of the cell point indices of cells in each patch 887*f1580f4eSBarry Smith . pointCounts - Section with counts of cells around each vertex 888*f1580f4eSBarry Smith - point - IS of the cell point indices of cells in each patch 8894bbf5ea8SMatthew G. Knepley */ 8909371c9d4SSatish Balay static PetscErrorCode PCPatchCreateCellPatches(PC pc) { 8914bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 8925f824522SMatthew G. Knepley DMLabel ghost = NULL; 8934bbf5ea8SMatthew G. Knepley DM dm, plex; 89476ce8f1aSJose E. Roman PetscHSetI ht = NULL, cht = NULL; 8950e126c0bSLawrence Mitchell PetscSection cellCounts, pointCounts, intFacetCounts, extFacetCounts; 896eb62eeaaSLawrence Mitchell PetscInt *cellsArray, *pointsArray, *intFacetsArray, *extFacetsArray, *intFacetsToPatchCell; 8970e126c0bSLawrence Mitchell PetscInt numCells, numPoints, numIntFacets, numExtFacets; 8985f824522SMatthew G. Knepley const PetscInt *leaves; 89933cbca70SPatrick Farrell PetscInt nleaves, pStart, pEnd, cStart, cEnd, vStart, vEnd, fStart, fEnd, v; 9005f824522SMatthew G. Knepley PetscBool isFiredrake; 9014bbf5ea8SMatthew G. Knepley 9024bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 9034bbf5ea8SMatthew G. Knepley /* Used to keep track of the cells in the patch. */ 9049566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&ht)); 9059566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&cht)); 9064bbf5ea8SMatthew G. Knepley 9079566063dSJacob Faibussowitsch PetscCall(PCGetDM(pc, &dm)); 90828b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "DM not yet set on patch PC"); 9099566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 910b6bb21d1SLawrence Mitchell dm = plex; 9119566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 9129566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 9134bbf5ea8SMatthew G. Knepley 9144bbf5ea8SMatthew G. Knepley if (patch->user_patches) { 9159566063dSJacob Faibussowitsch PetscCall(patch->userpatchconstructionop(pc, &patch->npatch, &patch->userIS, &patch->iterationSet, patch->userpatchconstructctx)); 9169371c9d4SSatish Balay vStart = 0; 9179371c9d4SSatish Balay vEnd = patch->npatch; 918e5b9877fSPatrick Farrell } else if (patch->ctype == PC_PATCH_PARDECOMP) { 9199371c9d4SSatish Balay vStart = 0; 9209371c9d4SSatish Balay vEnd = 1; 9215f824522SMatthew G. Knepley } else if (patch->codim < 0) { 9229566063dSJacob Faibussowitsch if (patch->dim < 0) PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9239566063dSJacob Faibussowitsch else PetscCall(DMPlexGetDepthStratum(dm, patch->dim, &vStart, &vEnd)); 9249566063dSJacob Faibussowitsch } else PetscCall(DMPlexGetHeightStratum(dm, patch->codim, &vStart, &vEnd)); 9255f824522SMatthew G. Knepley patch->npatch = vEnd - vStart; 9264bbf5ea8SMatthew G. Knepley 9274bbf5ea8SMatthew G. Knepley /* These labels mark the owned points. We only create patches around points that this process owns. */ 9289566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, "pyop2_ghost", &isFiredrake)); 9295f824522SMatthew G. Knepley if (isFiredrake) { 9309566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "pyop2_ghost", &ghost)); 9319566063dSJacob Faibussowitsch PetscCall(DMLabelCreateIndex(ghost, pStart, pEnd)); 9325f824522SMatthew G. Knepley } else { 9335f824522SMatthew G. Knepley PetscSF sf; 9345f824522SMatthew G. Knepley 9359566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 9369566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, &nleaves, &leaves, NULL)); 9375f824522SMatthew G. Knepley nleaves = PetscMax(nleaves, 0); 9385f824522SMatthew G. Knepley } 9394bbf5ea8SMatthew G. Knepley 9409566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &patch->cellCounts)); 9419566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)patch->cellCounts, "Patch Cell Layout")); 9424bbf5ea8SMatthew G. Knepley cellCounts = patch->cellCounts; 9439566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(cellCounts, vStart, vEnd)); 9449566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &patch->pointCounts)); 9459566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)patch->pointCounts, "Patch Point Layout")); 9465f824522SMatthew G. Knepley pointCounts = patch->pointCounts; 9479566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(pointCounts, vStart, vEnd)); 9489566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &patch->extFacetCounts)); 9499566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)patch->extFacetCounts, "Patch Exterior Facet Layout")); 9500e126c0bSLawrence Mitchell extFacetCounts = patch->extFacetCounts; 9519566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(extFacetCounts, vStart, vEnd)); 9529566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &patch->intFacetCounts)); 9539566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)patch->intFacetCounts, "Patch Interior Facet Layout")); 9540e126c0bSLawrence Mitchell intFacetCounts = patch->intFacetCounts; 9559566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(intFacetCounts, vStart, vEnd)); 9565f824522SMatthew G. Knepley /* Count cells and points in the patch surrounding each entity */ 9579566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 9584bbf5ea8SMatthew G. Knepley for (v = vStart; v < vEnd; ++v) { 9591b68eb51SMatthew G. Knepley PetscHashIter hi; 9605f824522SMatthew G. Knepley PetscInt chtSize, loc = -1; 9615f824522SMatthew G. Knepley PetscBool flg; 9624bbf5ea8SMatthew G. Knepley 963b525f888SPatrick Farrell if (!patch->user_patches && patch->ctype != PC_PATCH_PARDECOMP) { 9649566063dSJacob Faibussowitsch if (ghost) PetscCall(DMLabelHasPoint(ghost, v, &flg)); 9659371c9d4SSatish Balay else { 9669371c9d4SSatish Balay PetscCall(PetscFindInt(v, nleaves, leaves, &loc)); 9679371c9d4SSatish Balay flg = loc >= 0 ? PETSC_TRUE : PETSC_FALSE; 9689371c9d4SSatish Balay } 9694bbf5ea8SMatthew G. Knepley /* Not an owned entity, don't make a cell patch. */ 9704bbf5ea8SMatthew G. Knepley if (flg) continue; 9714bbf5ea8SMatthew G. Knepley } 9724bbf5ea8SMatthew G. Knepley 9739566063dSJacob Faibussowitsch PetscCall(patch->patchconstructop((void *)patch, dm, v, ht)); 9749566063dSJacob Faibussowitsch PetscCall(PCPatchCompleteCellPatch(pc, ht, cht)); 9759566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(cht, &chtSize)); 9764bbf5ea8SMatthew G. Knepley /* empty patch, continue */ 9774bbf5ea8SMatthew G. Knepley if (chtSize == 0) continue; 9784bbf5ea8SMatthew G. Knepley 9794bbf5ea8SMatthew G. Knepley /* safe because size(cht) > 0 from above */ 9801b68eb51SMatthew G. Knepley PetscHashIterBegin(cht, hi); 9811b68eb51SMatthew G. Knepley while (!PetscHashIterAtEnd(cht, hi)) { 9825f824522SMatthew G. Knepley PetscInt point, pdof; 9834bbf5ea8SMatthew G. Knepley 9841b68eb51SMatthew G. Knepley PetscHashIterGetKey(cht, hi, point); 9850e126c0bSLawrence Mitchell if (fStart <= point && point < fEnd) { 9860e126c0bSLawrence Mitchell const PetscInt *support; 9870e126c0bSLawrence Mitchell PetscInt supportSize, p; 9880e126c0bSLawrence Mitchell PetscBool interior = PETSC_TRUE; 9899566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, point, &support)); 9909566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, point, &supportSize)); 9910e126c0bSLawrence Mitchell if (supportSize == 1) { 9920e126c0bSLawrence Mitchell interior = PETSC_FALSE; 9930e126c0bSLawrence Mitchell } else { 9940e126c0bSLawrence Mitchell for (p = 0; p < supportSize; p++) { 9950e126c0bSLawrence Mitchell PetscBool found; 9960e126c0bSLawrence Mitchell /* FIXME: can I do this while iterating over cht? */ 9979566063dSJacob Faibussowitsch PetscCall(PetscHSetIHas(cht, support[p], &found)); 9980e126c0bSLawrence Mitchell if (!found) { 9990e126c0bSLawrence Mitchell interior = PETSC_FALSE; 10000e126c0bSLawrence Mitchell break; 10010e126c0bSLawrence Mitchell } 10020e126c0bSLawrence Mitchell } 10030e126c0bSLawrence Mitchell } 10040e126c0bSLawrence Mitchell if (interior) { 10059566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(intFacetCounts, v, 1)); 10060e126c0bSLawrence Mitchell } else { 10079566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(extFacetCounts, v, 1)); 10080e126c0bSLawrence Mitchell } 10090e126c0bSLawrence Mitchell } 10109566063dSJacob Faibussowitsch PetscCall(PCPatchGetGlobalDofs(pc, patch->dofSection, -1, patch->combined, point, &pdof, NULL)); 10119566063dSJacob Faibussowitsch if (pdof) PetscCall(PetscSectionAddDof(pointCounts, v, 1)); 10129566063dSJacob Faibussowitsch if (point >= cStart && point < cEnd) PetscCall(PetscSectionAddDof(cellCounts, v, 1)); 10131b68eb51SMatthew G. Knepley PetscHashIterNext(cht, hi); 10144bbf5ea8SMatthew G. Knepley } 10154bbf5ea8SMatthew G. Knepley } 10169566063dSJacob Faibussowitsch if (isFiredrake) PetscCall(DMLabelDestroyIndex(ghost)); 10174bbf5ea8SMatthew G. Knepley 10189566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(cellCounts)); 10199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(cellCounts, &numCells)); 10209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numCells, &cellsArray)); 10219566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(pointCounts)); 10229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(pointCounts, &numPoints)); 10239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints, &pointsArray)); 10244bbf5ea8SMatthew G. Knepley 10259566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(intFacetCounts)); 10269566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(extFacetCounts)); 10279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(intFacetCounts, &numIntFacets)); 10289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(extFacetCounts, &numExtFacets)); 10299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numIntFacets, &intFacetsArray)); 10309566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numIntFacets * 2, &intFacetsToPatchCell)); 10319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numExtFacets, &extFacetsArray)); 10320e126c0bSLawrence Mitchell 10334bbf5ea8SMatthew G. Knepley /* Now that we know how much space we need, run through again and actually remember the cells. */ 10344bbf5ea8SMatthew G. Knepley for (v = vStart; v < vEnd; v++) { 10351b68eb51SMatthew G. Knepley PetscHashIter hi; 10360e126c0bSLawrence Mitchell PetscInt dof, off, cdof, coff, efdof, efoff, ifdof, ifoff, pdof, n = 0, cn = 0, ifn = 0, efn = 0; 10374bbf5ea8SMatthew G. Knepley 10389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(pointCounts, v, &dof)); 10399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(pointCounts, v, &off)); 10409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cellCounts, v, &cdof)); 10419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cellCounts, v, &coff)); 10429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(intFacetCounts, v, &ifdof)); 10439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(intFacetCounts, v, &ifoff)); 10449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(extFacetCounts, v, &efdof)); 10459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(extFacetCounts, v, &efoff)); 10465f824522SMatthew G. Knepley if (dof <= 0) continue; 10479566063dSJacob Faibussowitsch PetscCall(patch->patchconstructop((void *)patch, dm, v, ht)); 10489566063dSJacob Faibussowitsch PetscCall(PCPatchCompleteCellPatch(pc, ht, cht)); 10491b68eb51SMatthew G. Knepley PetscHashIterBegin(cht, hi); 10501b68eb51SMatthew G. Knepley while (!PetscHashIterAtEnd(cht, hi)) { 10514bbf5ea8SMatthew G. Knepley PetscInt point; 10524bbf5ea8SMatthew G. Knepley 10531b68eb51SMatthew G. Knepley PetscHashIterGetKey(cht, hi, point); 10540e126c0bSLawrence Mitchell if (fStart <= point && point < fEnd) { 10550e126c0bSLawrence Mitchell const PetscInt *support; 10560e126c0bSLawrence Mitchell PetscInt supportSize, p; 10570e126c0bSLawrence Mitchell PetscBool interior = PETSC_TRUE; 10589566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, point, &support)); 10599566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, point, &supportSize)); 10600e126c0bSLawrence Mitchell if (supportSize == 1) { 10610e126c0bSLawrence Mitchell interior = PETSC_FALSE; 10620e126c0bSLawrence Mitchell } else { 10630e126c0bSLawrence Mitchell for (p = 0; p < supportSize; p++) { 10640e126c0bSLawrence Mitchell PetscBool found; 10650e126c0bSLawrence Mitchell /* FIXME: can I do this while iterating over cht? */ 10669566063dSJacob Faibussowitsch PetscCall(PetscHSetIHas(cht, support[p], &found)); 10670e126c0bSLawrence Mitchell if (!found) { 10680e126c0bSLawrence Mitchell interior = PETSC_FALSE; 10690e126c0bSLawrence Mitchell break; 10700e126c0bSLawrence Mitchell } 10710e126c0bSLawrence Mitchell } 10720e126c0bSLawrence Mitchell } 10730e126c0bSLawrence Mitchell if (interior) { 107444b625f7SLawrence Mitchell intFacetsToPatchCell[2 * (ifoff + ifn)] = support[0]; 107544b625f7SLawrence Mitchell intFacetsToPatchCell[2 * (ifoff + ifn) + 1] = support[1]; 10760e126c0bSLawrence Mitchell intFacetsArray[ifoff + ifn++] = point; 10770e126c0bSLawrence Mitchell } else { 10780e126c0bSLawrence Mitchell extFacetsArray[efoff + efn++] = point; 10790e126c0bSLawrence Mitchell } 10800e126c0bSLawrence Mitchell } 10819566063dSJacob Faibussowitsch PetscCall(PCPatchGetGlobalDofs(pc, patch->dofSection, -1, patch->combined, point, &pdof, NULL)); 1082ad540459SPierre Jolivet if (pdof) pointsArray[off + n++] = point; 1083ad540459SPierre Jolivet if (point >= cStart && point < cEnd) cellsArray[coff + cn++] = point; 10841b68eb51SMatthew G. Knepley PetscHashIterNext(cht, hi); 10854bbf5ea8SMatthew G. Knepley } 108663a3b9bcSJacob Faibussowitsch PetscCheck(ifn == ifdof, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of interior facets in patch %" PetscInt_FMT " is %" PetscInt_FMT ", but should be %" PetscInt_FMT, v, ifn, ifdof); 108763a3b9bcSJacob Faibussowitsch PetscCheck(efn == efdof, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of exterior facets in patch %" PetscInt_FMT " is %" PetscInt_FMT ", but should be %" PetscInt_FMT, v, efn, efdof); 108863a3b9bcSJacob Faibussowitsch PetscCheck(cn == cdof, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of cells in patch %" PetscInt_FMT " is %" PetscInt_FMT ", but should be %" PetscInt_FMT, v, cn, cdof); 108963a3b9bcSJacob Faibussowitsch PetscCheck(n == dof, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of points in patch %" PetscInt_FMT " is %" PetscInt_FMT ", but should be %" PetscInt_FMT, v, n, dof); 1090eb62eeaaSLawrence Mitchell 1091eb62eeaaSLawrence Mitchell for (ifn = 0; ifn < ifdof; ifn++) { 109244b625f7SLawrence Mitchell PetscInt cell0 = intFacetsToPatchCell[2 * (ifoff + ifn)]; 109344b625f7SLawrence Mitchell PetscInt cell1 = intFacetsToPatchCell[2 * (ifoff + ifn) + 1]; 1094eb62eeaaSLawrence Mitchell PetscBool found0 = PETSC_FALSE, found1 = PETSC_FALSE; 1095eb62eeaaSLawrence Mitchell for (n = 0; n < cdof; n++) { 10967c54fef0SLawrence Mitchell if (!found0 && cell0 == cellsArray[coff + n]) { 1097c3faab33SLawrence Mitchell intFacetsToPatchCell[2 * (ifoff + ifn)] = n; 1098eb62eeaaSLawrence Mitchell found0 = PETSC_TRUE; 1099eb62eeaaSLawrence Mitchell } 11007c54fef0SLawrence Mitchell if (!found1 && cell1 == cellsArray[coff + n]) { 1101c3faab33SLawrence Mitchell intFacetsToPatchCell[2 * (ifoff + ifn) + 1] = n; 110280fc4459SLawrence Mitchell found1 = PETSC_TRUE; 1103eb62eeaaSLawrence Mitchell } 1104eb62eeaaSLawrence Mitchell if (found0 && found1) break; 1105eb62eeaaSLawrence Mitchell } 11067827d75bSBarry Smith PetscCheck(found0 && found1, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Didn't manage to find local point numbers for facet support"); 1107eb62eeaaSLawrence Mitchell } 11084bbf5ea8SMatthew G. Knepley } 11099566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&ht)); 11109566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&cht)); 11115f824522SMatthew G. Knepley 11129566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numCells, cellsArray, PETSC_OWN_POINTER, &patch->cells)); 11139566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)patch->cells, "Patch Cells")); 11145f824522SMatthew G. Knepley if (patch->viewCells) { 11159566063dSJacob Faibussowitsch PetscCall(ObjectView((PetscObject)patch->cellCounts, patch->viewerCells, patch->formatCells)); 11169566063dSJacob Faibussowitsch PetscCall(ObjectView((PetscObject)patch->cells, patch->viewerCells, patch->formatCells)); 11175f824522SMatthew G. Knepley } 11189566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numIntFacets, intFacetsArray, PETSC_OWN_POINTER, &patch->intFacets)); 11199566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)patch->intFacets, "Patch Interior Facets")); 11209566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, 2 * numIntFacets, intFacetsToPatchCell, PETSC_OWN_POINTER, &patch->intFacetsToPatchCell)); 11219566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)patch->intFacetsToPatchCell, "Patch Interior Facets local support")); 11220e126c0bSLawrence Mitchell if (patch->viewIntFacets) { 11239566063dSJacob Faibussowitsch PetscCall(ObjectView((PetscObject)patch->intFacetCounts, patch->viewerIntFacets, patch->formatIntFacets)); 11249566063dSJacob Faibussowitsch PetscCall(ObjectView((PetscObject)patch->intFacets, patch->viewerIntFacets, patch->formatIntFacets)); 11259566063dSJacob Faibussowitsch PetscCall(ObjectView((PetscObject)patch->intFacetsToPatchCell, patch->viewerIntFacets, patch->formatIntFacets)); 11260e126c0bSLawrence Mitchell } 11279566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numExtFacets, extFacetsArray, PETSC_OWN_POINTER, &patch->extFacets)); 11289566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)patch->extFacets, "Patch Exterior Facets")); 11290e126c0bSLawrence Mitchell if (patch->viewExtFacets) { 11309566063dSJacob Faibussowitsch PetscCall(ObjectView((PetscObject)patch->extFacetCounts, patch->viewerExtFacets, patch->formatExtFacets)); 11319566063dSJacob Faibussowitsch PetscCall(ObjectView((PetscObject)patch->extFacets, patch->viewerExtFacets, patch->formatExtFacets)); 11320e126c0bSLawrence Mitchell } 11339566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numPoints, pointsArray, PETSC_OWN_POINTER, &patch->points)); 11349566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)patch->points, "Patch Points")); 11355f824522SMatthew G. Knepley if (patch->viewPoints) { 11369566063dSJacob Faibussowitsch PetscCall(ObjectView((PetscObject)patch->pointCounts, patch->viewerPoints, patch->formatPoints)); 11379566063dSJacob Faibussowitsch PetscCall(ObjectView((PetscObject)patch->points, patch->viewerPoints, patch->formatPoints)); 11385f824522SMatthew G. Knepley } 11399566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dm)); 11404bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 11414bbf5ea8SMatthew G. Knepley } 11424bbf5ea8SMatthew G. Knepley 11434bbf5ea8SMatthew G. Knepley /* 1144*f1580f4eSBarry Smith PCPatchCreateCellPatchDiscretisationInfo - Build the dof maps for cell patches 1145*f1580f4eSBarry Smith 1146*f1580f4eSBarry Smith Input Parameters: 1147*f1580f4eSBarry Smith + dm - The DMPlex object defining the mesh 1148*f1580f4eSBarry Smith . cellCounts - Section with counts of cells around each vertex 1149*f1580f4eSBarry Smith . cells - IS of the cell point indices of cells in each patch 1150*f1580f4eSBarry Smith . cellNumbering - Section mapping plex cell points to Firedrake cell indices. 1151*f1580f4eSBarry Smith . nodesPerCell - number of nodes per cell. 1152*f1580f4eSBarry Smith - cellNodeMap - map from cells to node indices (nodesPerCell * numCells) 1153*f1580f4eSBarry Smith 1154*f1580f4eSBarry Smith Output Parameters: 1155*f1580f4eSBarry Smith + dofs - IS of local dof numbers of each cell in the patch, where local is a patch local numbering 1156*f1580f4eSBarry Smith . gtolCounts - Section with counts of dofs per cell patch 1157*f1580f4eSBarry Smith - gtol - IS mapping from global dofs to local dofs for each patch. 11584bbf5ea8SMatthew G. Knepley */ 11599371c9d4SSatish Balay static PetscErrorCode PCPatchCreateCellPatchDiscretisationInfo(PC pc) { 11604bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 11614bbf5ea8SMatthew G. Knepley PetscSection cellCounts = patch->cellCounts; 11625f824522SMatthew G. Knepley PetscSection pointCounts = patch->pointCounts; 11630904074fSPatrick Farrell PetscSection gtolCounts, gtolCountsWithArtificial = NULL, gtolCountsWithAll = NULL; 11644bbf5ea8SMatthew G. Knepley IS cells = patch->cells; 11655f824522SMatthew G. Knepley IS points = patch->points; 11664bbf5ea8SMatthew G. Knepley PetscSection cellNumbering = patch->cellNumbering; 11675f824522SMatthew G. Knepley PetscInt Nf = patch->nsubspaces; 11685f824522SMatthew G. Knepley PetscInt numCells, numPoints; 11694bbf5ea8SMatthew G. Knepley PetscInt numDofs; 11700904074fSPatrick Farrell PetscInt numGlobalDofs, numGlobalDofsWithArtificial, numGlobalDofsWithAll; 11714bbf5ea8SMatthew G. Knepley PetscInt totalDofsPerCell = patch->totalDofsPerCell; 11724bbf5ea8SMatthew G. Knepley PetscInt vStart, vEnd, v; 11735f824522SMatthew G. Knepley const PetscInt *cellsArray, *pointsArray; 11744bbf5ea8SMatthew G. Knepley PetscInt *newCellsArray = NULL; 11754bbf5ea8SMatthew G. Knepley PetscInt *dofsArray = NULL; 1176c2e6f3c0SFlorian Wechsung PetscInt *dofsArrayWithArtificial = NULL; 11770904074fSPatrick Farrell PetscInt *dofsArrayWithAll = NULL; 11785f824522SMatthew G. Knepley PetscInt *offsArray = NULL; 1179c2e6f3c0SFlorian Wechsung PetscInt *offsArrayWithArtificial = NULL; 11800904074fSPatrick Farrell PetscInt *offsArrayWithAll = NULL; 11814bbf5ea8SMatthew G. Knepley PetscInt *asmArray = NULL; 1182c2e6f3c0SFlorian Wechsung PetscInt *asmArrayWithArtificial = NULL; 11830904074fSPatrick Farrell PetscInt *asmArrayWithAll = NULL; 11844bbf5ea8SMatthew G. Knepley PetscInt *globalDofsArray = NULL; 1185c2e6f3c0SFlorian Wechsung PetscInt *globalDofsArrayWithArtificial = NULL; 11860904074fSPatrick Farrell PetscInt *globalDofsArrayWithAll = NULL; 11874bbf5ea8SMatthew G. Knepley PetscInt globalIndex = 0; 11884bbf5ea8SMatthew G. Knepley PetscInt key = 0; 11894bbf5ea8SMatthew G. Knepley PetscInt asmKey = 0; 1190b6bb21d1SLawrence Mitchell DM dm = NULL, plex; 1191557beb66SLawrence Mitchell const PetscInt *bcNodes = NULL; 11921b68eb51SMatthew G. Knepley PetscHMapI ht; 1193c2e6f3c0SFlorian Wechsung PetscHMapI htWithArtificial; 11940904074fSPatrick Farrell PetscHMapI htWithAll; 11951b68eb51SMatthew G. Knepley PetscHSetI globalBcs; 1196557beb66SLawrence Mitchell PetscInt numBcs; 11971b68eb51SMatthew G. Knepley PetscHSetI ownedpts, seenpts, owneddofs, seendofs, artificialbcs; 1198cda239d9SMatthew G. Knepley PetscInt pStart, pEnd, p, i; 119910534d48SPatrick Farrell char option[PETSC_MAX_PATH_LEN]; 120039fd2e8aSPatrick Farrell PetscBool isNonlinear; 12014bbf5ea8SMatthew G. Knepley 12024bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 1203557beb66SLawrence Mitchell 12049566063dSJacob Faibussowitsch PetscCall(PCGetDM(pc, &dm)); 12059566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 1206b6bb21d1SLawrence Mitchell dm = plex; 12074bbf5ea8SMatthew G. Knepley /* dofcounts section is cellcounts section * dofPerCell */ 12089566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(cellCounts, &numCells)); 12099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(patch->pointCounts, &numPoints)); 12104bbf5ea8SMatthew G. Knepley numDofs = numCells * totalDofsPerCell; 12119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numDofs, &dofsArray)); 12129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints * Nf, &offsArray)); 12139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numDofs, &asmArray)); 12149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numCells, &newCellsArray)); 12159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cellCounts, &vStart, &vEnd)); 12169566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &patch->gtolCounts)); 12174bbf5ea8SMatthew G. Knepley gtolCounts = patch->gtolCounts; 12189566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(gtolCounts, vStart, vEnd)); 12199566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)patch->gtolCounts, "Patch Global Index Section")); 12204bbf5ea8SMatthew G. Knepley 1221b6bb21d1SLawrence Mitchell if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) { 12229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints * Nf, &offsArrayWithArtificial)); 12239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numDofs, &asmArrayWithArtificial)); 12249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numDofs, &dofsArrayWithArtificial)); 12259566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &patch->gtolCountsWithArtificial)); 1226c2e6f3c0SFlorian Wechsung gtolCountsWithArtificial = patch->gtolCountsWithArtificial; 12279566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(gtolCountsWithArtificial, vStart, vEnd)); 12289566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)patch->gtolCountsWithArtificial, "Patch Global Index Section Including Artificial BCs")); 1229c2e6f3c0SFlorian Wechsung } 1230c2e6f3c0SFlorian Wechsung 12310904074fSPatrick Farrell isNonlinear = patch->isNonlinear; 1232b6bb21d1SLawrence Mitchell if (isNonlinear) { 12339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints * Nf, &offsArrayWithAll)); 12349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numDofs, &asmArrayWithAll)); 12359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numDofs, &dofsArrayWithAll)); 12369566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &patch->gtolCountsWithAll)); 12370904074fSPatrick Farrell gtolCountsWithAll = patch->gtolCountsWithAll; 12389566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(gtolCountsWithAll, vStart, vEnd)); 12399566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)patch->gtolCountsWithAll, "Patch Global Index Section Including All BCs")); 12400904074fSPatrick Farrell } 12410904074fSPatrick Farrell 1242557beb66SLawrence Mitchell /* Outside the patch loop, get the dofs that are globally-enforced Dirichlet 1243557beb66SLawrence Mitchell conditions */ 12449566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&globalBcs)); 12459566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->ghostBcNodes, &bcNodes)); 12469566063dSJacob Faibussowitsch PetscCall(ISGetSize(patch->ghostBcNodes, &numBcs)); 12479371c9d4SSatish Balay for (i = 0; i < numBcs; ++i) { PetscCall(PetscHSetIAdd(globalBcs, bcNodes[i])); /* these are already in concatenated numbering */ } 12489566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->ghostBcNodes, &bcNodes)); 12499566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->ghostBcNodes)); /* memory optimisation */ 1250557beb66SLawrence Mitchell 1251557beb66SLawrence Mitchell /* Hash tables for artificial BC construction */ 12529566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&ownedpts)); 12539566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&seenpts)); 12549566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&owneddofs)); 12559566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&seendofs)); 12569566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&artificialbcs)); 1257557beb66SLawrence Mitchell 12589566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cells, &cellsArray)); 12599566063dSJacob Faibussowitsch PetscCall(ISGetIndices(points, &pointsArray)); 12609566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&ht)); 12619566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&htWithArtificial)); 12629566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&htWithAll)); 12634bbf5ea8SMatthew G. Knepley for (v = vStart; v < vEnd; ++v) { 12644bbf5ea8SMatthew G. Knepley PetscInt localIndex = 0; 1265c2e6f3c0SFlorian Wechsung PetscInt localIndexWithArtificial = 0; 12660904074fSPatrick Farrell PetscInt localIndexWithAll = 0; 12674bbf5ea8SMatthew G. Knepley PetscInt dof, off, i, j, k, l; 12684bbf5ea8SMatthew G. Knepley 12699566063dSJacob Faibussowitsch PetscCall(PetscHMapIClear(ht)); 12709566063dSJacob Faibussowitsch PetscCall(PetscHMapIClear(htWithArtificial)); 12719566063dSJacob Faibussowitsch PetscCall(PetscHMapIClear(htWithAll)); 12729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cellCounts, v, &dof)); 12739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cellCounts, v, &off)); 12744bbf5ea8SMatthew G. Knepley if (dof <= 0) continue; 12754bbf5ea8SMatthew G. Knepley 1276557beb66SLawrence Mitchell /* Calculate the global numbers of the artificial BC dofs here first */ 12779566063dSJacob Faibussowitsch PetscCall(patch->patchconstructop((void *)patch, dm, v, ownedpts)); 12789566063dSJacob Faibussowitsch PetscCall(PCPatchCompleteCellPatch(pc, ownedpts, seenpts)); 12799566063dSJacob Faibussowitsch PetscCall(PCPatchGetPointDofs(pc, ownedpts, owneddofs, v, &patch->subspaces_to_exclude)); 12809566063dSJacob Faibussowitsch PetscCall(PCPatchGetPointDofs(pc, seenpts, seendofs, v, NULL)); 12819566063dSJacob Faibussowitsch PetscCall(PCPatchComputeSetDifference_Private(owneddofs, seendofs, artificialbcs)); 12828135ed82SLawrence Mitchell if (patch->viewPatches) { 12831b68eb51SMatthew G. Knepley PetscHSetI globalbcdofs; 12841b68eb51SMatthew G. Knepley PetscHashIter hi; 12858135ed82SLawrence Mitchell MPI_Comm comm = PetscObjectComm((PetscObject)pc); 12861b68eb51SMatthew G. Knepley 12879566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&globalbcdofs)); 128863a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "Patch %" PetscInt_FMT ": owned dofs:\n", v)); 12891b68eb51SMatthew G. Knepley PetscHashIterBegin(owneddofs, hi); 12901b68eb51SMatthew G. Knepley while (!PetscHashIterAtEnd(owneddofs, hi)) { 12918135ed82SLawrence Mitchell PetscInt globalDof; 12928135ed82SLawrence Mitchell 12931b68eb51SMatthew G. Knepley PetscHashIterGetKey(owneddofs, hi, globalDof); 12941b68eb51SMatthew G. Knepley PetscHashIterNext(owneddofs, hi); 129563a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "%" PetscInt_FMT " ", globalDof)); 12968135ed82SLawrence Mitchell } 12979566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "\n")); 129863a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "Patch %" PetscInt_FMT ": seen dofs:\n", v)); 12991b68eb51SMatthew G. Knepley PetscHashIterBegin(seendofs, hi); 13001b68eb51SMatthew G. Knepley while (!PetscHashIterAtEnd(seendofs, hi)) { 13018135ed82SLawrence Mitchell PetscInt globalDof; 13028135ed82SLawrence Mitchell PetscBool flg; 13038135ed82SLawrence Mitchell 13041b68eb51SMatthew G. Knepley PetscHashIterGetKey(seendofs, hi, globalDof); 13051b68eb51SMatthew G. Knepley PetscHashIterNext(seendofs, hi); 130663a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "%" PetscInt_FMT " ", globalDof)); 13078135ed82SLawrence Mitchell 13089566063dSJacob Faibussowitsch PetscCall(PetscHSetIHas(globalBcs, globalDof, &flg)); 13099566063dSJacob Faibussowitsch if (flg) PetscCall(PetscHSetIAdd(globalbcdofs, globalDof)); 13108135ed82SLawrence Mitchell } 13119566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "\n")); 131263a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "Patch %" PetscInt_FMT ": global BCs:\n", v)); 13139566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(globalbcdofs, &numBcs)); 13148135ed82SLawrence Mitchell if (numBcs > 0) { 13151b68eb51SMatthew G. Knepley PetscHashIterBegin(globalbcdofs, hi); 13161b68eb51SMatthew G. Knepley while (!PetscHashIterAtEnd(globalbcdofs, hi)) { 13178135ed82SLawrence Mitchell PetscInt globalDof; 13181b68eb51SMatthew G. Knepley PetscHashIterGetKey(globalbcdofs, hi, globalDof); 13191b68eb51SMatthew G. Knepley PetscHashIterNext(globalbcdofs, hi); 132063a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "%" PetscInt_FMT " ", globalDof)); 13218135ed82SLawrence Mitchell } 13228135ed82SLawrence Mitchell } 13239566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "\n")); 132463a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "Patch %" PetscInt_FMT ": artificial BCs:\n", v)); 13259566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(artificialbcs, &numBcs)); 13268135ed82SLawrence Mitchell if (numBcs > 0) { 13271b68eb51SMatthew G. Knepley PetscHashIterBegin(artificialbcs, hi); 13281b68eb51SMatthew G. Knepley while (!PetscHashIterAtEnd(artificialbcs, hi)) { 13298135ed82SLawrence Mitchell PetscInt globalDof; 13301b68eb51SMatthew G. Knepley PetscHashIterGetKey(artificialbcs, hi, globalDof); 13311b68eb51SMatthew G. Knepley PetscHashIterNext(artificialbcs, hi); 133263a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "%" PetscInt_FMT " ", globalDof)); 13338135ed82SLawrence Mitchell } 13348135ed82SLawrence Mitchell } 13359566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "\n\n")); 13369566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&globalbcdofs)); 13378135ed82SLawrence Mitchell } 13384bbf5ea8SMatthew G. Knepley for (k = 0; k < patch->nsubspaces; ++k) { 13394bbf5ea8SMatthew G. Knepley const PetscInt *cellNodeMap = patch->cellNodeMap[k]; 13404bbf5ea8SMatthew G. Knepley PetscInt nodesPerCell = patch->nodesPerCell[k]; 13414bbf5ea8SMatthew G. Knepley PetscInt subspaceOffset = patch->subspaceOffsets[k]; 13424bbf5ea8SMatthew G. Knepley PetscInt bs = patch->bs[k]; 13434bbf5ea8SMatthew G. Knepley 13444bbf5ea8SMatthew G. Knepley for (i = off; i < off + dof; ++i) { 13454bbf5ea8SMatthew G. Knepley /* Walk over the cells in this patch. */ 13464bbf5ea8SMatthew G. Knepley const PetscInt c = cellsArray[i]; 13475f824522SMatthew G. Knepley PetscInt cell = c; 13484bbf5ea8SMatthew G. Knepley 13495f824522SMatthew G. Knepley /* TODO Change this to an IS */ 13505f824522SMatthew G. Knepley if (cellNumbering) { 13519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cellNumbering, c, &cell)); 135263a3b9bcSJacob Faibussowitsch PetscCheck(cell > 0, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " doesn't appear in cell numbering map", c); 13539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cellNumbering, c, &cell)); 13545f824522SMatthew G. Knepley } 13554bbf5ea8SMatthew G. Knepley newCellsArray[i] = cell; 13564bbf5ea8SMatthew G. Knepley for (j = 0; j < nodesPerCell; ++j) { 13574bbf5ea8SMatthew G. Knepley /* For each global dof, map it into contiguous local storage. */ 13584bbf5ea8SMatthew G. Knepley const PetscInt globalDof = cellNodeMap[cell * nodesPerCell + j] * bs + subspaceOffset; 13594bbf5ea8SMatthew G. Knepley /* finally, loop over block size */ 13604bbf5ea8SMatthew G. Knepley for (l = 0; l < bs; ++l) { 13611b68eb51SMatthew G. Knepley PetscInt localDof; 13621b68eb51SMatthew G. Knepley PetscBool isGlobalBcDof, isArtificialBcDof; 13634bbf5ea8SMatthew G. Knepley 1364557beb66SLawrence Mitchell /* first, check if this is either a globally enforced or locally enforced BC dof */ 13659566063dSJacob Faibussowitsch PetscCall(PetscHSetIHas(globalBcs, globalDof + l, &isGlobalBcDof)); 13669566063dSJacob Faibussowitsch PetscCall(PetscHSetIHas(artificialbcs, globalDof + l, &isArtificialBcDof)); 1367557beb66SLawrence Mitchell 1368557beb66SLawrence Mitchell /* if it's either, don't ever give it a local dof number */ 13691b68eb51SMatthew G. Knepley if (isGlobalBcDof || isArtificialBcDof) { 1370c2e6f3c0SFlorian Wechsung dofsArray[globalIndex] = -1; /* don't use this in assembly in this patch */ 1371557beb66SLawrence Mitchell } else { 13729566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(ht, globalDof + l, &localDof)); 13734bbf5ea8SMatthew G. Knepley if (localDof == -1) { 13744bbf5ea8SMatthew G. Knepley localDof = localIndex++; 13759566063dSJacob Faibussowitsch PetscCall(PetscHMapISet(ht, globalDof + l, localDof)); 13764bbf5ea8SMatthew G. Knepley } 137763a3b9bcSJacob Faibussowitsch PetscCheck(globalIndex < numDofs, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Found more dofs %" PetscInt_FMT " than expected %" PetscInt_FMT, globalIndex + 1, numDofs); 13784bbf5ea8SMatthew G. Knepley /* And store. */ 1379c2e6f3c0SFlorian Wechsung dofsArray[globalIndex] = localDof; 13804bbf5ea8SMatthew G. Knepley } 1381c2e6f3c0SFlorian Wechsung 13820904074fSPatrick Farrell if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) { 1383c2e6f3c0SFlorian Wechsung if (isGlobalBcDof) { 1384e047a90bSFlorian Wechsung dofsArrayWithArtificial[globalIndex] = -1; /* don't use this in assembly in this patch */ 1385c2e6f3c0SFlorian Wechsung } else { 13869566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(htWithArtificial, globalDof + l, &localDof)); 1387c2e6f3c0SFlorian Wechsung if (localDof == -1) { 1388c2e6f3c0SFlorian Wechsung localDof = localIndexWithArtificial++; 13899566063dSJacob Faibussowitsch PetscCall(PetscHMapISet(htWithArtificial, globalDof + l, localDof)); 1390c2e6f3c0SFlorian Wechsung } 139163a3b9bcSJacob Faibussowitsch PetscCheck(globalIndex < numDofs, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Found more dofs %" PetscInt_FMT " than expected %" PetscInt_FMT, globalIndex + 1, numDofs); 1392c2e6f3c0SFlorian Wechsung /* And store.*/ 1393c2e6f3c0SFlorian Wechsung dofsArrayWithArtificial[globalIndex] = localDof; 1394c2e6f3c0SFlorian Wechsung } 1395c2e6f3c0SFlorian Wechsung } 13960904074fSPatrick Farrell 13970904074fSPatrick Farrell if (isNonlinear) { 13980904074fSPatrick Farrell /* Build the dofmap for the function space with _all_ dofs, 13990904074fSPatrick Farrell including those in any kind of boundary condition */ 14009566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(htWithAll, globalDof + l, &localDof)); 14010904074fSPatrick Farrell if (localDof == -1) { 14020904074fSPatrick Farrell localDof = localIndexWithAll++; 14039566063dSJacob Faibussowitsch PetscCall(PetscHMapISet(htWithAll, globalDof + l, localDof)); 14040904074fSPatrick Farrell } 140563a3b9bcSJacob Faibussowitsch PetscCheck(globalIndex < numDofs, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Found more dofs %" PetscInt_FMT " than expected %" PetscInt_FMT, globalIndex + 1, numDofs); 14060904074fSPatrick Farrell /* And store.*/ 14070904074fSPatrick Farrell dofsArrayWithAll[globalIndex] = localDof; 14080904074fSPatrick Farrell } 1409c2e6f3c0SFlorian Wechsung globalIndex++; 14104bbf5ea8SMatthew G. Knepley } 14114bbf5ea8SMatthew G. Knepley } 14124bbf5ea8SMatthew G. Knepley } 1413557beb66SLawrence Mitchell } 14144bbf5ea8SMatthew G. Knepley /*How many local dofs in this patch? */ 14150904074fSPatrick Farrell if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) { 14169566063dSJacob Faibussowitsch PetscCall(PetscHMapIGetSize(htWithArtificial, &dof)); 14179566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(gtolCountsWithArtificial, v, dof)); 1418c2e6f3c0SFlorian Wechsung } 14190904074fSPatrick Farrell if (isNonlinear) { 14209566063dSJacob Faibussowitsch PetscCall(PetscHMapIGetSize(htWithAll, &dof)); 14219566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(gtolCountsWithAll, v, dof)); 14220904074fSPatrick Farrell } 14239566063dSJacob Faibussowitsch PetscCall(PetscHMapIGetSize(ht, &dof)); 14249566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(gtolCounts, v, dof)); 14254bbf5ea8SMatthew G. Knepley } 1426b6bb21d1SLawrence Mitchell 14279566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dm)); 142863a3b9bcSJacob Faibussowitsch PetscCheck(globalIndex == numDofs, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Expected number of dofs (%" PetscInt_FMT ") doesn't match found number (%" PetscInt_FMT ")", numDofs, globalIndex); 14299566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(gtolCounts)); 14309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(gtolCounts, &numGlobalDofs)); 14319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numGlobalDofs, &globalDofsArray)); 14324bbf5ea8SMatthew G. Knepley 14330904074fSPatrick Farrell if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) { 14349566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(gtolCountsWithArtificial)); 14359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(gtolCountsWithArtificial, &numGlobalDofsWithArtificial)); 14369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numGlobalDofsWithArtificial, &globalDofsArrayWithArtificial)); 1437c2e6f3c0SFlorian Wechsung } 14380904074fSPatrick Farrell if (isNonlinear) { 14399566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(gtolCountsWithAll)); 14409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(gtolCountsWithAll, &numGlobalDofsWithAll)); 14419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numGlobalDofsWithAll, &globalDofsArrayWithAll)); 14420904074fSPatrick Farrell } 14434bbf5ea8SMatthew G. Knepley /* Now populate the global to local map. This could be merged into the above loop if we were willing to deal with reallocs. */ 14444bbf5ea8SMatthew G. Knepley for (v = vStart; v < vEnd; ++v) { 14451b68eb51SMatthew G. Knepley PetscHashIter hi; 14465f824522SMatthew G. Knepley PetscInt dof, off, Np, ooff, i, j, k, l; 14474bbf5ea8SMatthew G. Knepley 14489566063dSJacob Faibussowitsch PetscCall(PetscHMapIClear(ht)); 14499566063dSJacob Faibussowitsch PetscCall(PetscHMapIClear(htWithArtificial)); 14509566063dSJacob Faibussowitsch PetscCall(PetscHMapIClear(htWithAll)); 14519566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cellCounts, v, &dof)); 14529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cellCounts, v, &off)); 14539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(pointCounts, v, &Np)); 14549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(pointCounts, v, &ooff)); 14554bbf5ea8SMatthew G. Knepley if (dof <= 0) continue; 14564bbf5ea8SMatthew G. Knepley 14574bbf5ea8SMatthew G. Knepley for (k = 0; k < patch->nsubspaces; ++k) { 14584bbf5ea8SMatthew G. Knepley const PetscInt *cellNodeMap = patch->cellNodeMap[k]; 14594bbf5ea8SMatthew G. Knepley PetscInt nodesPerCell = patch->nodesPerCell[k]; 14604bbf5ea8SMatthew G. Knepley PetscInt subspaceOffset = patch->subspaceOffsets[k]; 14614bbf5ea8SMatthew G. Knepley PetscInt bs = patch->bs[k]; 1462d490bb3dSLawrence Mitchell PetscInt goff; 14634bbf5ea8SMatthew G. Knepley 14644bbf5ea8SMatthew G. Knepley for (i = off; i < off + dof; ++i) { 14654bbf5ea8SMatthew G. Knepley /* Reconstruct mapping of global-to-local on this patch. */ 14664bbf5ea8SMatthew G. Knepley const PetscInt c = cellsArray[i]; 14675f824522SMatthew G. Knepley PetscInt cell = c; 14684bbf5ea8SMatthew G. Knepley 14699566063dSJacob Faibussowitsch if (cellNumbering) PetscCall(PetscSectionGetOffset(cellNumbering, c, &cell)); 14704bbf5ea8SMatthew G. Knepley for (j = 0; j < nodesPerCell; ++j) { 14714bbf5ea8SMatthew G. Knepley for (l = 0; l < bs; ++l) { 14725f824522SMatthew G. Knepley const PetscInt globalDof = cellNodeMap[cell * nodesPerCell + j] * bs + l + subspaceOffset; 1473c2e6f3c0SFlorian Wechsung const PetscInt localDof = dofsArray[key]; 14749566063dSJacob Faibussowitsch if (localDof >= 0) PetscCall(PetscHMapISet(ht, globalDof, localDof)); 14750904074fSPatrick Farrell if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) { 1476c2e6f3c0SFlorian Wechsung const PetscInt localDofWithArtificial = dofsArrayWithArtificial[key]; 147748a46eb9SPierre Jolivet if (localDofWithArtificial >= 0) PetscCall(PetscHMapISet(htWithArtificial, globalDof, localDofWithArtificial)); 1478c2e6f3c0SFlorian Wechsung } 14790904074fSPatrick Farrell if (isNonlinear) { 14800904074fSPatrick Farrell const PetscInt localDofWithAll = dofsArrayWithAll[key]; 148148a46eb9SPierre Jolivet if (localDofWithAll >= 0) PetscCall(PetscHMapISet(htWithAll, globalDof, localDofWithAll)); 14820904074fSPatrick Farrell } 1483c2e6f3c0SFlorian Wechsung key++; 14844bbf5ea8SMatthew G. Knepley } 14854bbf5ea8SMatthew G. Knepley } 14864bbf5ea8SMatthew G. Knepley } 1487557beb66SLawrence Mitchell 14884bbf5ea8SMatthew G. Knepley /* Shove it in the output data structure. */ 14899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(gtolCounts, v, &goff)); 14901b68eb51SMatthew G. Knepley PetscHashIterBegin(ht, hi); 14911b68eb51SMatthew G. Knepley while (!PetscHashIterAtEnd(ht, hi)) { 14924bbf5ea8SMatthew G. Knepley PetscInt globalDof, localDof; 14934bbf5ea8SMatthew G. Knepley 14941b68eb51SMatthew G. Knepley PetscHashIterGetKey(ht, hi, globalDof); 14951b68eb51SMatthew G. Knepley PetscHashIterGetVal(ht, hi, localDof); 14964bbf5ea8SMatthew G. Knepley if (globalDof >= 0) globalDofsArray[goff + localDof] = globalDof; 14971b68eb51SMatthew G. Knepley PetscHashIterNext(ht, hi); 14984bbf5ea8SMatthew G. Knepley } 14995f824522SMatthew G. Knepley 15000904074fSPatrick Farrell if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) { 15019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(gtolCountsWithArtificial, v, &goff)); 1502c2e6f3c0SFlorian Wechsung PetscHashIterBegin(htWithArtificial, hi); 1503c2e6f3c0SFlorian Wechsung while (!PetscHashIterAtEnd(htWithArtificial, hi)) { 1504c2e6f3c0SFlorian Wechsung PetscInt globalDof, localDof; 1505c2e6f3c0SFlorian Wechsung PetscHashIterGetKey(htWithArtificial, hi, globalDof); 1506c2e6f3c0SFlorian Wechsung PetscHashIterGetVal(htWithArtificial, hi, localDof); 1507c2e6f3c0SFlorian Wechsung if (globalDof >= 0) globalDofsArrayWithArtificial[goff + localDof] = globalDof; 1508c2e6f3c0SFlorian Wechsung PetscHashIterNext(htWithArtificial, hi); 1509c2e6f3c0SFlorian Wechsung } 1510c2e6f3c0SFlorian Wechsung } 15110904074fSPatrick Farrell if (isNonlinear) { 15129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(gtolCountsWithAll, v, &goff)); 15130904074fSPatrick Farrell PetscHashIterBegin(htWithAll, hi); 15140904074fSPatrick Farrell while (!PetscHashIterAtEnd(htWithAll, hi)) { 15150904074fSPatrick Farrell PetscInt globalDof, localDof; 15160904074fSPatrick Farrell PetscHashIterGetKey(htWithAll, hi, globalDof); 15170904074fSPatrick Farrell PetscHashIterGetVal(htWithAll, hi, localDof); 15180904074fSPatrick Farrell if (globalDof >= 0) globalDofsArrayWithAll[goff + localDof] = globalDof; 15190904074fSPatrick Farrell PetscHashIterNext(htWithAll, hi); 15200904074fSPatrick Farrell } 15210904074fSPatrick Farrell } 1522c2e6f3c0SFlorian Wechsung 15235f824522SMatthew G. Knepley for (p = 0; p < Np; ++p) { 15245f824522SMatthew G. Knepley const PetscInt point = pointsArray[ooff + p]; 15255f824522SMatthew G. Knepley PetscInt globalDof, localDof; 15265f824522SMatthew G. Knepley 15279566063dSJacob Faibussowitsch PetscCall(PCPatchGetGlobalDofs(pc, patch->dofSection, k, patch->combined, point, NULL, &globalDof)); 15289566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(ht, globalDof, &localDof)); 15295f824522SMatthew G. Knepley offsArray[(ooff + p) * Nf + k] = localDof; 15300904074fSPatrick Farrell if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) { 15319566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(htWithArtificial, globalDof, &localDof)); 1532c2e6f3c0SFlorian Wechsung offsArrayWithArtificial[(ooff + p) * Nf + k] = localDof; 1533c2e6f3c0SFlorian Wechsung } 15340904074fSPatrick Farrell if (isNonlinear) { 15359566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(htWithAll, globalDof, &localDof)); 15360904074fSPatrick Farrell offsArrayWithAll[(ooff + p) * Nf + k] = localDof; 15370904074fSPatrick Farrell } 15385f824522SMatthew G. Knepley } 15394bbf5ea8SMatthew G. Knepley } 15404bbf5ea8SMatthew G. Knepley 15419566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&globalBcs)); 15429566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&ownedpts)); 15439566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&seenpts)); 15449566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&owneddofs)); 15459566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&seendofs)); 15469566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&artificialbcs)); 1547557beb66SLawrence Mitchell 15484bbf5ea8SMatthew G. Knepley /* At this point, we have a hash table ht built that maps globalDof -> localDof. 15494bbf5ea8SMatthew G. Knepley We need to create the dof table laid out cellwise first, then by subspace, 15504bbf5ea8SMatthew G. Knepley as the assembler assembles cell-wise and we need to stuff the different 15514bbf5ea8SMatthew G. Knepley contributions of the different function spaces to the right places. So we loop 15524bbf5ea8SMatthew G. Knepley over cells, then over subspaces. */ 15534bbf5ea8SMatthew G. Knepley if (patch->nsubspaces > 1) { /* for nsubspaces = 1, data we need is already in dofsArray */ 15544bbf5ea8SMatthew G. Knepley for (i = off; i < off + dof; ++i) { 15554bbf5ea8SMatthew G. Knepley const PetscInt c = cellsArray[i]; 15565f824522SMatthew G. Knepley PetscInt cell = c; 15574bbf5ea8SMatthew G. Knepley 15589566063dSJacob Faibussowitsch if (cellNumbering) PetscCall(PetscSectionGetOffset(cellNumbering, c, &cell)); 15594bbf5ea8SMatthew G. Knepley for (k = 0; k < patch->nsubspaces; ++k) { 15604bbf5ea8SMatthew G. Knepley const PetscInt *cellNodeMap = patch->cellNodeMap[k]; 15614bbf5ea8SMatthew G. Knepley PetscInt nodesPerCell = patch->nodesPerCell[k]; 15624bbf5ea8SMatthew G. Knepley PetscInt subspaceOffset = patch->subspaceOffsets[k]; 15634bbf5ea8SMatthew G. Knepley PetscInt bs = patch->bs[k]; 15644bbf5ea8SMatthew G. Knepley 15654bbf5ea8SMatthew G. Knepley for (j = 0; j < nodesPerCell; ++j) { 15664bbf5ea8SMatthew G. Knepley for (l = 0; l < bs; ++l) { 15675f824522SMatthew G. Knepley const PetscInt globalDof = cellNodeMap[cell * nodesPerCell + j] * bs + l + subspaceOffset; 15684bbf5ea8SMatthew G. Knepley PetscInt localDof; 15694bbf5ea8SMatthew G. Knepley 15709566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(ht, globalDof, &localDof)); 1571557beb66SLawrence Mitchell /* If it's not in the hash table, i.e. is a BC dof, 15721b68eb51SMatthew G. Knepley then the PetscHSetIMap above gives -1, which matches 1573557beb66SLawrence Mitchell exactly the convention for PETSc's matrix assembly to 1574557beb66SLawrence Mitchell ignore the dof. So we don't need to do anything here */ 1575c2e6f3c0SFlorian Wechsung asmArray[asmKey] = localDof; 15760904074fSPatrick Farrell if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) { 15779566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(htWithArtificial, globalDof, &localDof)); 1578c2e6f3c0SFlorian Wechsung asmArrayWithArtificial[asmKey] = localDof; 1579c2e6f3c0SFlorian Wechsung } 15800904074fSPatrick Farrell if (isNonlinear) { 15819566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(htWithAll, globalDof, &localDof)); 15820904074fSPatrick Farrell asmArrayWithAll[asmKey] = localDof; 15830904074fSPatrick Farrell } 1584c2e6f3c0SFlorian Wechsung asmKey++; 15854bbf5ea8SMatthew G. Knepley } 15864bbf5ea8SMatthew G. Knepley } 15874bbf5ea8SMatthew G. Knepley } 15884bbf5ea8SMatthew G. Knepley } 15894bbf5ea8SMatthew G. Knepley } 15904bbf5ea8SMatthew G. Knepley } 1591c2e6f3c0SFlorian Wechsung if (1 == patch->nsubspaces) { 15929566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(asmArray, dofsArray, numDofs)); 159348a46eb9SPierre Jolivet if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) PetscCall(PetscArraycpy(asmArrayWithArtificial, dofsArrayWithArtificial, numDofs)); 15941baa6e33SBarry Smith if (isNonlinear) PetscCall(PetscArraycpy(asmArrayWithAll, dofsArrayWithAll, numDofs)); 1595c2e6f3c0SFlorian Wechsung } 15964bbf5ea8SMatthew G. Knepley 15979566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&ht)); 15989566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&htWithArtificial)); 15999566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&htWithAll)); 16009566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cells, &cellsArray)); 16019566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(points, &pointsArray)); 16029566063dSJacob Faibussowitsch PetscCall(PetscFree(dofsArray)); 160348a46eb9SPierre Jolivet if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) PetscCall(PetscFree(dofsArrayWithArtificial)); 16041baa6e33SBarry Smith if (isNonlinear) PetscCall(PetscFree(dofsArrayWithAll)); 16055f824522SMatthew G. Knepley /* Create placeholder section for map from points to patch dofs */ 16069566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &patch->patchSection)); 16079566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(patch->patchSection, patch->nsubspaces)); 16081e5fa6bbSLawrence Mitchell if (patch->combined) { 16091e5fa6bbSLawrence Mitchell PetscInt numFields; 16109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(patch->dofSection[0], &numFields)); 161163a3b9bcSJacob Faibussowitsch PetscCheck(numFields == patch->nsubspaces, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Mismatch between number of section fields %" PetscInt_FMT " and number of subspaces %" PetscInt_FMT, numFields, patch->nsubspaces); 16129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(patch->dofSection[0], &pStart, &pEnd)); 16139566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(patch->patchSection, pStart, pEnd)); 16145f824522SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 16155f824522SMatthew G. Knepley PetscInt dof, fdof, f; 16165f824522SMatthew G. Knepley 16179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->dofSection[0], p, &dof)); 16189566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(patch->patchSection, p, dof)); 16195f824522SMatthew G. Knepley for (f = 0; f < patch->nsubspaces; ++f) { 16209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(patch->dofSection[0], p, f, &fdof)); 16219566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(patch->patchSection, p, f, fdof)); 16225f824522SMatthew G. Knepley } 16231e5fa6bbSLawrence Mitchell } 16241e5fa6bbSLawrence Mitchell } else { 16251e5fa6bbSLawrence Mitchell PetscInt pStartf, pEndf, f; 16261e5fa6bbSLawrence Mitchell pStart = PETSC_MAX_INT; 16271e5fa6bbSLawrence Mitchell pEnd = PETSC_MIN_INT; 16281e5fa6bbSLawrence Mitchell for (f = 0; f < patch->nsubspaces; ++f) { 16299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(patch->dofSection[f], &pStartf, &pEndf)); 16301e5fa6bbSLawrence Mitchell pStart = PetscMin(pStart, pStartf); 16311e5fa6bbSLawrence Mitchell pEnd = PetscMax(pEnd, pEndf); 16321e5fa6bbSLawrence Mitchell } 16339566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(patch->patchSection, pStart, pEnd)); 16341e5fa6bbSLawrence Mitchell for (f = 0; f < patch->nsubspaces; ++f) { 16359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(patch->dofSection[f], &pStartf, &pEndf)); 16361e5fa6bbSLawrence Mitchell for (p = pStartf; p < pEndf; ++p) { 16371e5fa6bbSLawrence Mitchell PetscInt fdof; 16389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->dofSection[f], p, &fdof)); 16399566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(patch->patchSection, p, fdof)); 16409566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(patch->patchSection, p, f, fdof)); 1641bdd9e0cdSPatrick Farrell } 1642bdd9e0cdSPatrick Farrell } 16435f824522SMatthew G. Knepley } 16449566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(patch->patchSection)); 16459566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUseFieldOffsets(patch->patchSection, PETSC_TRUE)); 16464bbf5ea8SMatthew G. Knepley /* Replace cell indices with firedrake-numbered ones. */ 16479566063dSJacob Faibussowitsch PetscCall(ISGeneralSetIndices(cells, numCells, (const PetscInt *)newCellsArray, PETSC_OWN_POINTER)); 16489566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numGlobalDofs, globalDofsArray, PETSC_OWN_POINTER, &patch->gtol)); 16499566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)patch->gtol, "Global Indices")); 16509566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_g2l_view", patch->classname)); 16519566063dSJacob Faibussowitsch PetscCall(PetscSectionViewFromOptions(patch->gtolCounts, (PetscObject)pc, option)); 16529566063dSJacob Faibussowitsch PetscCall(ISViewFromOptions(patch->gtol, (PetscObject)pc, option)); 16539566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numDofs, asmArray, PETSC_OWN_POINTER, &patch->dofs)); 16549566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numPoints * Nf, offsArray, PETSC_OWN_POINTER, &patch->offs)); 16550904074fSPatrick Farrell if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) { 16569566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numGlobalDofsWithArtificial, globalDofsArrayWithArtificial, PETSC_OWN_POINTER, &patch->gtolWithArtificial)); 16579566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numDofs, asmArrayWithArtificial, PETSC_OWN_POINTER, &patch->dofsWithArtificial)); 16589566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numPoints * Nf, offsArrayWithArtificial, PETSC_OWN_POINTER, &patch->offsWithArtificial)); 1659c2e6f3c0SFlorian Wechsung } 16600904074fSPatrick Farrell if (isNonlinear) { 16619566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numGlobalDofsWithAll, globalDofsArrayWithAll, PETSC_OWN_POINTER, &patch->gtolWithAll)); 16629566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numDofs, asmArrayWithAll, PETSC_OWN_POINTER, &patch->dofsWithAll)); 16639566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numPoints * Nf, offsArrayWithAll, PETSC_OWN_POINTER, &patch->offsWithAll)); 16640904074fSPatrick Farrell } 16654bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 16664bbf5ea8SMatthew G. Knepley } 16674bbf5ea8SMatthew G. Knepley 16689371c9d4SSatish Balay static PetscErrorCode PCPatchCreateMatrix_Private(PC pc, PetscInt point, Mat *mat, PetscBool withArtificial) { 16694bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 16704bbf5ea8SMatthew G. Knepley PetscBool flg; 16714bbf5ea8SMatthew G. Knepley PetscInt csize, rsize; 16724bbf5ea8SMatthew G. Knepley const char *prefix = NULL; 16734bbf5ea8SMatthew G. Knepley 16744bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 1675c2e6f3c0SFlorian Wechsung if (withArtificial) { 1676e047a90bSFlorian Wechsung /* would be nice if we could create a rectangular matrix of size numDofsWithArtificial x numDofs here */ 16779d4fc724SLawrence Mitchell PetscInt pStart; 16789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(patch->gtolCountsWithArtificial, &pStart, NULL)); 16799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCountsWithArtificial, point + pStart, &rsize)); 16809d4fc724SLawrence Mitchell csize = rsize; 1681ff201f6aSFlorian Wechsung } else { 16829d4fc724SLawrence Mitchell PetscInt pStart; 16839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(patch->gtolCounts, &pStart, NULL)); 16849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCounts, point + pStart, &rsize)); 16859d4fc724SLawrence Mitchell csize = rsize; 1686c2e6f3c0SFlorian Wechsung } 1687c2e6f3c0SFlorian Wechsung 16889566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, mat)); 16899566063dSJacob Faibussowitsch PetscCall(PCGetOptionsPrefix(pc, &prefix)); 16909566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(*mat, prefix)); 16919566063dSJacob Faibussowitsch PetscCall(MatAppendOptionsPrefix(*mat, "pc_patch_sub_")); 16929566063dSJacob Faibussowitsch if (patch->sub_mat_type) PetscCall(MatSetType(*mat, patch->sub_mat_type)); 16939566063dSJacob Faibussowitsch else if (!patch->sub_mat_type) PetscCall(MatSetType(*mat, MATDENSE)); 16949566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mat, rsize, csize, rsize, csize)); 16959566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)*mat, MATDENSE, &flg)); 16969566063dSJacob Faibussowitsch if (!flg) PetscCall(PetscObjectTypeCompare((PetscObject)*mat, MATSEQDENSE, &flg)); 16974bbf5ea8SMatthew G. Knepley /* Sparse patch matrices */ 16984bbf5ea8SMatthew G. Knepley if (!flg) { 16994bbf5ea8SMatthew G. Knepley PetscBT bt; 17004bbf5ea8SMatthew G. Knepley PetscInt *dnnz = NULL; 17014bbf5ea8SMatthew G. Knepley const PetscInt *dofsArray = NULL; 17024bbf5ea8SMatthew G. Knepley PetscInt pStart, pEnd, ncell, offset, c, i, j; 17034bbf5ea8SMatthew G. Knepley 1704c2e6f3c0SFlorian Wechsung if (withArtificial) { 17059566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->dofsWithArtificial, &dofsArray)); 1706ff201f6aSFlorian Wechsung } else { 17079566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->dofs, &dofsArray)); 1708c2e6f3c0SFlorian Wechsung } 17099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(patch->cellCounts, &pStart, &pEnd)); 17104bbf5ea8SMatthew G. Knepley point += pStart; 171163a3b9bcSJacob Faibussowitsch PetscCheck(point < pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Operator point %" PetscInt_FMT " not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, pStart, pEnd); 17129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->cellCounts, point, &ncell)); 17139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->cellCounts, point, &offset)); 17149566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_Patch_Prealloc, pc, 0, 0, 0)); 1715b2866507SPatrick Farrell /* A PetscBT uses N^2 bits to store the sparsity pattern on a 17164bbf5ea8SMatthew G. Knepley * patch. This is probably OK if the patches are not too big, 1717b2866507SPatrick Farrell * but uses too much memory. We therefore switch based on rsize. */ 1718b2866507SPatrick Farrell if (rsize < 3000) { /* FIXME: I picked this switch value out of my hat */ 1719d63cebbaSPatrick Farrell PetscScalar *zeroes; 1720d63cebbaSPatrick Farrell PetscInt rows; 1721d63cebbaSPatrick Farrell 17229566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(rsize, &dnnz)); 17239566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(rsize * rsize, &bt)); 17244bbf5ea8SMatthew G. Knepley for (c = 0; c < ncell; ++c) { 17254bbf5ea8SMatthew G. Knepley const PetscInt *idx = dofsArray + (offset + c) * patch->totalDofsPerCell; 17264bbf5ea8SMatthew G. Knepley for (i = 0; i < patch->totalDofsPerCell; ++i) { 17274bbf5ea8SMatthew G. Knepley const PetscInt row = idx[i]; 1728557beb66SLawrence Mitchell if (row < 0) continue; 17294bbf5ea8SMatthew G. Knepley for (j = 0; j < patch->totalDofsPerCell; ++j) { 17304bbf5ea8SMatthew G. Knepley const PetscInt col = idx[j]; 17314bbf5ea8SMatthew G. Knepley const PetscInt key = row * rsize + col; 1732557beb66SLawrence Mitchell if (col < 0) continue; 17334bbf5ea8SMatthew G. Knepley if (!PetscBTLookupSet(bt, key)) ++dnnz[row]; 17344bbf5ea8SMatthew G. Knepley } 17354bbf5ea8SMatthew G. Knepley } 17364bbf5ea8SMatthew G. Knepley } 1737d63cebbaSPatrick Farrell 1738d63cebbaSPatrick Farrell if (patch->usercomputeopintfacet) { 1739d63cebbaSPatrick Farrell const PetscInt *intFacetsArray = NULL; 1740d63cebbaSPatrick Farrell PetscInt i, numIntFacets, intFacetOffset; 1741d63cebbaSPatrick Farrell const PetscInt *facetCells = NULL; 1742d63cebbaSPatrick Farrell 17439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->intFacetCounts, point, &numIntFacets)); 17449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->intFacetCounts, point, &intFacetOffset)); 17459566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->intFacetsToPatchCell, &facetCells)); 17469566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->intFacets, &intFacetsArray)); 1747d63cebbaSPatrick Farrell for (i = 0; i < numIntFacets; i++) { 1748d63cebbaSPatrick Farrell const PetscInt cell0 = facetCells[2 * (intFacetOffset + i) + 0]; 1749d63cebbaSPatrick Farrell const PetscInt cell1 = facetCells[2 * (intFacetOffset + i) + 1]; 1750d63cebbaSPatrick Farrell PetscInt celli, cellj; 1751d63cebbaSPatrick Farrell 1752d63cebbaSPatrick Farrell for (celli = 0; celli < patch->totalDofsPerCell; celli++) { 1753d63cebbaSPatrick Farrell const PetscInt row = dofsArray[(offset + cell0) * patch->totalDofsPerCell + celli]; 1754b5c64f08SPatrick Farrell if (row < 0) continue; 1755d63cebbaSPatrick Farrell for (cellj = 0; cellj < patch->totalDofsPerCell; cellj++) { 1756d63cebbaSPatrick Farrell const PetscInt col = dofsArray[(offset + cell1) * patch->totalDofsPerCell + cellj]; 1757d63cebbaSPatrick Farrell const PetscInt key = row * rsize + col; 1758d63cebbaSPatrick Farrell if (col < 0) continue; 1759d63cebbaSPatrick Farrell if (!PetscBTLookupSet(bt, key)) ++dnnz[row]; 1760d63cebbaSPatrick Farrell } 1761d63cebbaSPatrick Farrell } 1762d63cebbaSPatrick Farrell 1763d63cebbaSPatrick Farrell for (celli = 0; celli < patch->totalDofsPerCell; celli++) { 1764d63cebbaSPatrick Farrell const PetscInt row = dofsArray[(offset + cell1) * patch->totalDofsPerCell + celli]; 1765b5c64f08SPatrick Farrell if (row < 0) continue; 1766d63cebbaSPatrick Farrell for (cellj = 0; cellj < patch->totalDofsPerCell; cellj++) { 1767d63cebbaSPatrick Farrell const PetscInt col = dofsArray[(offset + cell0) * patch->totalDofsPerCell + cellj]; 1768d63cebbaSPatrick Farrell const PetscInt key = row * rsize + col; 1769d63cebbaSPatrick Farrell if (col < 0) continue; 1770d63cebbaSPatrick Farrell if (!PetscBTLookupSet(bt, key)) ++dnnz[row]; 1771d63cebbaSPatrick Farrell } 1772d63cebbaSPatrick Farrell } 1773d63cebbaSPatrick Farrell } 1774d63cebbaSPatrick Farrell } 17759566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&bt)); 17769566063dSJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(*mat, 1, dnnz, NULL, NULL, NULL)); 17779566063dSJacob Faibussowitsch PetscCall(PetscFree(dnnz)); 1778d63cebbaSPatrick Farrell 17799566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(patch->totalDofsPerCell * patch->totalDofsPerCell, &zeroes)); 1780d63cebbaSPatrick Farrell for (c = 0; c < ncell; ++c) { 1781d63cebbaSPatrick Farrell const PetscInt *idx = &dofsArray[(offset + c) * patch->totalDofsPerCell]; 17829566063dSJacob Faibussowitsch PetscCall(MatSetValues(*mat, patch->totalDofsPerCell, idx, patch->totalDofsPerCell, idx, zeroes, INSERT_VALUES)); 1783d63cebbaSPatrick Farrell } 17849566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(*mat, &rows, NULL)); 178548a46eb9SPierre Jolivet for (i = 0; i < rows; ++i) PetscCall(MatSetValues(*mat, 1, &i, 1, &i, zeroes, INSERT_VALUES)); 1786d63cebbaSPatrick Farrell 1787d63cebbaSPatrick Farrell if (patch->usercomputeopintfacet) { 1788d63cebbaSPatrick Farrell const PetscInt *intFacetsArray = NULL; 1789d63cebbaSPatrick Farrell PetscInt i, numIntFacets, intFacetOffset; 1790d63cebbaSPatrick Farrell const PetscInt *facetCells = NULL; 1791d63cebbaSPatrick Farrell 17929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->intFacetCounts, point, &numIntFacets)); 17939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->intFacetCounts, point, &intFacetOffset)); 17949566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->intFacetsToPatchCell, &facetCells)); 17959566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->intFacets, &intFacetsArray)); 1796d63cebbaSPatrick Farrell for (i = 0; i < numIntFacets; i++) { 1797d63cebbaSPatrick Farrell const PetscInt cell0 = facetCells[2 * (intFacetOffset + i) + 0]; 1798d63cebbaSPatrick Farrell const PetscInt cell1 = facetCells[2 * (intFacetOffset + i) + 1]; 1799d63cebbaSPatrick Farrell const PetscInt *cell0idx = &dofsArray[(offset + cell0) * patch->totalDofsPerCell]; 1800d63cebbaSPatrick Farrell const PetscInt *cell1idx = &dofsArray[(offset + cell1) * patch->totalDofsPerCell]; 18019566063dSJacob Faibussowitsch PetscCall(MatSetValues(*mat, patch->totalDofsPerCell, cell0idx, patch->totalDofsPerCell, cell1idx, zeroes, INSERT_VALUES)); 18029566063dSJacob Faibussowitsch PetscCall(MatSetValues(*mat, patch->totalDofsPerCell, cell1idx, patch->totalDofsPerCell, cell0idx, zeroes, INSERT_VALUES)); 1803d63cebbaSPatrick Farrell } 1804d63cebbaSPatrick Farrell } 1805d63cebbaSPatrick Farrell 18069566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY)); 18079566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY)); 1808d63cebbaSPatrick Farrell 18099566063dSJacob Faibussowitsch PetscCall(PetscFree(zeroes)); 1810d63cebbaSPatrick Farrell 1811b2866507SPatrick Farrell } else { /* rsize too big, use MATPREALLOCATOR */ 1812b2866507SPatrick Farrell Mat preallocator; 1813b2866507SPatrick Farrell PetscScalar *vals; 1814b2866507SPatrick Farrell 18159566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(patch->totalDofsPerCell * patch->totalDofsPerCell, &vals)); 18169566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &preallocator)); 18179566063dSJacob Faibussowitsch PetscCall(MatSetType(preallocator, MATPREALLOCATOR)); 18189566063dSJacob Faibussowitsch PetscCall(MatSetSizes(preallocator, rsize, rsize, rsize, rsize)); 18199566063dSJacob Faibussowitsch PetscCall(MatSetUp(preallocator)); 182011bcd083SPatrick Farrell 1821b2866507SPatrick Farrell for (c = 0; c < ncell; ++c) { 1822b2866507SPatrick Farrell const PetscInt *idx = dofsArray + (offset + c) * patch->totalDofsPerCell; 18239566063dSJacob Faibussowitsch PetscCall(MatSetValues(preallocator, patch->totalDofsPerCell, idx, patch->totalDofsPerCell, idx, vals, INSERT_VALUES)); 1824b2866507SPatrick Farrell } 182511bcd083SPatrick Farrell 182611bcd083SPatrick Farrell if (patch->usercomputeopintfacet) { 182711bcd083SPatrick Farrell const PetscInt *intFacetsArray = NULL; 182811bcd083SPatrick Farrell PetscInt i, numIntFacets, intFacetOffset; 182911bcd083SPatrick Farrell const PetscInt *facetCells = NULL; 183011bcd083SPatrick Farrell 18319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->intFacetCounts, point, &numIntFacets)); 18329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->intFacetCounts, point, &intFacetOffset)); 18339566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->intFacetsToPatchCell, &facetCells)); 18349566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->intFacets, &intFacetsArray)); 183511bcd083SPatrick Farrell for (i = 0; i < numIntFacets; i++) { 183611bcd083SPatrick Farrell const PetscInt cell0 = facetCells[2 * (intFacetOffset + i) + 0]; 183711bcd083SPatrick Farrell const PetscInt cell1 = facetCells[2 * (intFacetOffset + i) + 1]; 183811bcd083SPatrick Farrell const PetscInt *cell0idx = &dofsArray[(offset + cell0) * patch->totalDofsPerCell]; 183911bcd083SPatrick Farrell const PetscInt *cell1idx = &dofsArray[(offset + cell1) * patch->totalDofsPerCell]; 18409566063dSJacob Faibussowitsch PetscCall(MatSetValues(preallocator, patch->totalDofsPerCell, cell0idx, patch->totalDofsPerCell, cell1idx, vals, INSERT_VALUES)); 18419566063dSJacob Faibussowitsch PetscCall(MatSetValues(preallocator, patch->totalDofsPerCell, cell1idx, patch->totalDofsPerCell, cell0idx, vals, INSERT_VALUES)); 184211bcd083SPatrick Farrell } 184311bcd083SPatrick Farrell } 184411bcd083SPatrick Farrell 18459566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 18469566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(preallocator, MAT_FINAL_ASSEMBLY)); 18479566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(preallocator, MAT_FINAL_ASSEMBLY)); 18489566063dSJacob Faibussowitsch PetscCall(MatPreallocatorPreallocate(preallocator, PETSC_TRUE, *mat)); 18499566063dSJacob Faibussowitsch PetscCall(MatDestroy(&preallocator)); 1850b2866507SPatrick Farrell } 18519566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_Patch_Prealloc, pc, 0, 0, 0)); 1852fe117d09SFlorian Wechsung if (withArtificial) { 18539566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->dofsWithArtificial, &dofsArray)); 1854fe117d09SFlorian Wechsung } else { 18559566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->dofs, &dofsArray)); 18564bbf5ea8SMatthew G. Knepley } 1857fe117d09SFlorian Wechsung } 18589566063dSJacob Faibussowitsch PetscCall(MatSetUp(*mat)); 18594bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 18604bbf5ea8SMatthew G. Knepley } 18614bbf5ea8SMatthew G. Knepley 18629371c9d4SSatish Balay static PetscErrorCode PCPatchComputeFunction_DMPlex_Private(PC pc, PetscInt patchNum, Vec x, Vec F, IS cellIS, PetscInt n, const PetscInt *l2p, const PetscInt *l2pWithAll, void *ctx) { 186392d50984SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 1864b6bb21d1SLawrence Mitchell DM dm, plex; 186592d50984SMatthew G. Knepley PetscSection s; 186692d50984SMatthew G. Knepley const PetscInt *parray, *oarray; 186792d50984SMatthew G. Knepley PetscInt Nf = patch->nsubspaces, Np, poff, p, f; 186892d50984SMatthew G. Knepley 186992d50984SMatthew G. Knepley PetscFunctionBegin; 187028b400f6SJacob Faibussowitsch PetscCheck(!patch->precomputeElementTensors, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Precomputing element tensors not implemented with DMPlex compute operator"); 18719566063dSJacob Faibussowitsch PetscCall(PCGetDM(pc, &dm)); 18729566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 1873b6bb21d1SLawrence Mitchell dm = plex; 18749566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, &s)); 187592d50984SMatthew G. Knepley /* Set offset into patch */ 18769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->pointCounts, patchNum, &Np)); 18779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->pointCounts, patchNum, &poff)); 18789566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->points, &parray)); 18799566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->offs, &oarray)); 188092d50984SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 188192d50984SMatthew G. Knepley for (p = 0; p < Np; ++p) { 188292d50984SMatthew G. Knepley const PetscInt point = parray[poff + p]; 188392d50984SMatthew G. Knepley PetscInt dof; 188492d50984SMatthew G. Knepley 18859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(patch->patchSection, point, f, &dof)); 18869566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldOffset(patch->patchSection, point, f, oarray[(poff + p) * Nf + f])); 18879566063dSJacob Faibussowitsch if (patch->nsubspaces == 1) PetscCall(PetscSectionSetOffset(patch->patchSection, point, oarray[(poff + p) * Nf + f])); 18889566063dSJacob Faibussowitsch else PetscCall(PetscSectionSetOffset(patch->patchSection, point, -1)); 188992d50984SMatthew G. Knepley } 189092d50984SMatthew G. Knepley } 18919566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->points, &parray)); 18929566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->offs, &oarray)); 18939566063dSJacob Faibussowitsch if (patch->viewSection) PetscCall(ObjectView((PetscObject)patch->patchSection, patch->viewerSection, patch->formatSection)); 18949566063dSJacob Faibussowitsch PetscCall(DMPlexComputeResidual_Patch_Internal(dm, patch->patchSection, cellIS, 0.0, x, NULL, F, ctx)); 18959566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dm)); 189692d50984SMatthew G. Knepley PetscFunctionReturn(0); 189792d50984SMatthew G. Knepley } 189892d50984SMatthew G. Knepley 18999371c9d4SSatish Balay PetscErrorCode PCPatchComputeFunction_Internal(PC pc, Vec x, Vec F, PetscInt point) { 190092d50984SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 190192d50984SMatthew G. Knepley const PetscInt *dofsArray; 19020904074fSPatrick Farrell const PetscInt *dofsArrayWithAll; 190392d50984SMatthew G. Knepley const PetscInt *cellsArray; 190492d50984SMatthew G. Knepley PetscInt ncell, offset, pStart, pEnd; 190592d50984SMatthew G. Knepley 190692d50984SMatthew G. Knepley PetscFunctionBegin; 19079566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_Patch_ComputeOp, pc, 0, 0, 0)); 1908ef1023bdSBarry Smith PetscCheck(patch->usercomputeop, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call PCPatchSetComputeOperator() to set callback"); 19099566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->dofs, &dofsArray)); 19109566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->dofsWithAll, &dofsArrayWithAll)); 19119566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->cells, &cellsArray)); 19129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(patch->cellCounts, &pStart, &pEnd)); 191392d50984SMatthew G. Knepley 191492d50984SMatthew G. Knepley point += pStart; 191563a3b9bcSJacob Faibussowitsch PetscCheck(point < pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Operator point %" PetscInt_FMT " not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, pStart, pEnd); 191692d50984SMatthew G. Knepley 19179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->cellCounts, point, &ncell)); 19189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->cellCounts, point, &offset)); 191992d50984SMatthew G. Knepley if (ncell <= 0) { 19209566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_Patch_ComputeOp, pc, 0, 0, 0)); 192192d50984SMatthew G. Knepley PetscFunctionReturn(0); 192292d50984SMatthew G. Knepley } 19239566063dSJacob Faibussowitsch PetscCall(VecSet(F, 0.0)); 192492d50984SMatthew G. Knepley /* Cannot reuse the same IS because the geometry info is being cached in it */ 19259566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ncell, cellsArray + offset, PETSC_USE_POINTER, &patch->cellIS)); 1926792fecdfSBarry Smith PetscCallBack("PCPatch callback", patch->usercomputef(pc, point, x, F, patch->cellIS, ncell * patch->totalDofsPerCell, dofsArray + offset * patch->totalDofsPerCell, dofsArrayWithAll + offset * patch->totalDofsPerCell, patch->usercomputefctx)); 19279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->cellIS)); 19289566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->dofs, &dofsArray)); 19299566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->dofsWithAll, &dofsArrayWithAll)); 19309566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->cells, &cellsArray)); 193192d50984SMatthew G. Knepley if (patch->viewMatrix) { 193292d50984SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 193392d50984SMatthew G. Knepley 193463a3b9bcSJacob Faibussowitsch PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN - 1, "Patch vector for Point %" PetscInt_FMT, point)); 19359566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)F, name)); 19369566063dSJacob Faibussowitsch PetscCall(ObjectView((PetscObject)F, patch->viewerMatrix, patch->formatMatrix)); 193792d50984SMatthew G. Knepley } 19389566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_Patch_ComputeOp, pc, 0, 0, 0)); 193992d50984SMatthew G. Knepley PetscFunctionReturn(0); 194092d50984SMatthew G. Knepley } 194192d50984SMatthew G. Knepley 19429371c9d4SSatish Balay static PetscErrorCode PCPatchComputeOperator_DMPlex_Private(PC pc, PetscInt patchNum, Vec x, Mat J, IS cellIS, PetscInt n, const PetscInt *l2p, const PetscInt *l2pWithAll, void *ctx) { 19435f824522SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 1944b6bb21d1SLawrence Mitchell DM dm, plex; 19455f824522SMatthew G. Knepley PetscSection s; 19465f824522SMatthew G. Knepley const PetscInt *parray, *oarray; 19475f824522SMatthew G. Knepley PetscInt Nf = patch->nsubspaces, Np, poff, p, f; 19485f824522SMatthew G. Knepley 19495f824522SMatthew G. Knepley PetscFunctionBegin; 19509566063dSJacob Faibussowitsch PetscCall(PCGetDM(pc, &dm)); 19519566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 1952b6bb21d1SLawrence Mitchell dm = plex; 19539566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, &s)); 19545f824522SMatthew G. Knepley /* Set offset into patch */ 19559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->pointCounts, patchNum, &Np)); 19569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->pointCounts, patchNum, &poff)); 19579566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->points, &parray)); 19589566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->offs, &oarray)); 19595f824522SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 19605f824522SMatthew G. Knepley for (p = 0; p < Np; ++p) { 19615f824522SMatthew G. Knepley const PetscInt point = parray[poff + p]; 19625f824522SMatthew G. Knepley PetscInt dof; 19635f824522SMatthew G. Knepley 19649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(patch->patchSection, point, f, &dof)); 19659566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldOffset(patch->patchSection, point, f, oarray[(poff + p) * Nf + f])); 19669566063dSJacob Faibussowitsch if (patch->nsubspaces == 1) PetscCall(PetscSectionSetOffset(patch->patchSection, point, oarray[(poff + p) * Nf + f])); 19679566063dSJacob Faibussowitsch else PetscCall(PetscSectionSetOffset(patch->patchSection, point, -1)); 19685f824522SMatthew G. Knepley } 19695f824522SMatthew G. Knepley } 19709566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->points, &parray)); 19719566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->offs, &oarray)); 19729566063dSJacob Faibussowitsch if (patch->viewSection) PetscCall(ObjectView((PetscObject)patch->patchSection, patch->viewerSection, patch->formatSection)); 19735f824522SMatthew G. Knepley /* TODO Shut off MatViewFromOptions() in MatAssemblyEnd() here */ 19749566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Patch_Internal(dm, patch->patchSection, patch->patchSection, cellIS, 0.0, 0.0, x, NULL, J, J, ctx)); 19759566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dm)); 19765f824522SMatthew G. Knepley PetscFunctionReturn(0); 19775f824522SMatthew G. Knepley } 19785f824522SMatthew G. Knepley 1979a685ae26SLawrence Mitchell /* This function zeros mat on entry */ 19809371c9d4SSatish Balay PetscErrorCode PCPatchComputeOperator_Internal(PC pc, Vec x, Mat mat, PetscInt point, PetscBool withArtificial) { 19814bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 19824bbf5ea8SMatthew G. Knepley const PetscInt *dofsArray; 19830904074fSPatrick Farrell const PetscInt *dofsArrayWithAll = NULL; 19844bbf5ea8SMatthew G. Knepley const PetscInt *cellsArray; 1985eb62eeaaSLawrence Mitchell PetscInt ncell, offset, pStart, pEnd, numIntFacets, intFacetOffset; 19864d04e9f1SPatrick Farrell PetscBool isNonlinear; 19874bbf5ea8SMatthew G. Knepley 19884bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 19899566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_Patch_ComputeOp, pc, 0, 0, 0)); 1990debbdec3SPatrick Farrell isNonlinear = patch->isNonlinear; 1991ef1023bdSBarry Smith PetscCheck(patch->usercomputeop, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call PCPatchSetComputeOperator() to set callback"); 1992c2e6f3c0SFlorian Wechsung if (withArtificial) { 19939566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->dofsWithArtificial, &dofsArray)); 1994c2e6f3c0SFlorian Wechsung } else { 19959566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->dofs, &dofsArray)); 1996c2e6f3c0SFlorian Wechsung } 199748a46eb9SPierre Jolivet if (isNonlinear) PetscCall(ISGetIndices(patch->dofsWithAll, &dofsArrayWithAll)); 19989566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->cells, &cellsArray)); 19999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(patch->cellCounts, &pStart, &pEnd)); 20004bbf5ea8SMatthew G. Knepley 20014bbf5ea8SMatthew G. Knepley point += pStart; 200263a3b9bcSJacob Faibussowitsch PetscCheck(point < pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Operator point %" PetscInt_FMT " not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, pStart, pEnd); 20034bbf5ea8SMatthew G. Knepley 20049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->cellCounts, point, &ncell)); 20059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->cellCounts, point, &offset)); 20064bbf5ea8SMatthew G. Knepley if (ncell <= 0) { 20079566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_Patch_ComputeOp, pc, 0, 0, 0)); 20084bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 20094bbf5ea8SMatthew G. Knepley } 20109566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(mat)); 2011fa84ea4cSLawrence Mitchell if (patch->precomputeElementTensors) { 2012fa84ea4cSLawrence Mitchell PetscInt i; 2013fa84ea4cSLawrence Mitchell PetscInt ndof = patch->totalDofsPerCell; 2014fa84ea4cSLawrence Mitchell const PetscScalar *elementTensors; 2015fa84ea4cSLawrence Mitchell 20169566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(patch->cellMats, &elementTensors)); 2017fa84ea4cSLawrence Mitchell for (i = 0; i < ncell; i++) { 2018fa84ea4cSLawrence Mitchell const PetscInt cell = cellsArray[i + offset]; 2019fa84ea4cSLawrence Mitchell const PetscInt *idx = dofsArray + (offset + i) * ndof; 2020fe988be2SFlorian Wechsung const PetscScalar *v = elementTensors + patch->precomputedTensorLocations[cell] * ndof * ndof; 20219566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, ndof, idx, ndof, idx, v, ADD_VALUES)); 2022fa84ea4cSLawrence Mitchell } 20239566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(patch->cellMats, &elementTensors)); 20249566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 20259566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 2026fa84ea4cSLawrence Mitchell } else { 20272aa6f319SMatthew G. Knepley /* Cannot reuse the same IS because the geometry info is being cached in it */ 20289566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ncell, cellsArray + offset, PETSC_USE_POINTER, &patch->cellIS)); 20299371c9d4SSatish Balay PetscCallBack("PCPatch callback", 20309371c9d4SSatish Balay patch->usercomputeop(pc, point, x, mat, patch->cellIS, ncell * patch->totalDofsPerCell, dofsArray + offset * patch->totalDofsPerCell, dofsArrayWithAll ? dofsArrayWithAll + offset * patch->totalDofsPerCell : NULL, patch->usercomputeopctx)); 2031fa84ea4cSLawrence Mitchell } 203259109abcSLawrence Mitchell if (patch->usercomputeopintfacet) { 20339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->intFacetCounts, point, &numIntFacets)); 20349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->intFacetCounts, point, &intFacetOffset)); 2035eb62eeaaSLawrence Mitchell if (numIntFacets > 0) { 2036eb62eeaaSLawrence Mitchell /* For each interior facet, grab the two cells (in local numbering, and concatenate dof numberings for those cells) */ 2037eb62eeaaSLawrence Mitchell PetscInt *facetDofs = NULL, *facetDofsWithAll = NULL; 2038eb62eeaaSLawrence Mitchell const PetscInt *intFacetsArray = NULL; 2039eb62eeaaSLawrence Mitchell PetscInt idx = 0; 2040eb62eeaaSLawrence Mitchell PetscInt i, c, d; 2041de2d1767SPatrick Farrell PetscInt fStart; 2042b6bb21d1SLawrence Mitchell DM dm, plex; 2043eb62eeaaSLawrence Mitchell IS facetIS = NULL; 2044eb62eeaaSLawrence Mitchell const PetscInt *facetCells = NULL; 20457a50e09dSPatrick Farrell 20469566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->intFacetsToPatchCell, &facetCells)); 20479566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->intFacets, &intFacetsArray)); 20489566063dSJacob Faibussowitsch PetscCall(PCGetDM(pc, &dm)); 20499566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 2050b6bb21d1SLawrence Mitchell dm = plex; 20519566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, NULL)); 2052eb62eeaaSLawrence Mitchell /* FIXME: Pull this malloc out. */ 20539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2 * patch->totalDofsPerCell * numIntFacets, &facetDofs)); 205448a46eb9SPierre Jolivet if (dofsArrayWithAll) PetscCall(PetscMalloc1(2 * patch->totalDofsPerCell * numIntFacets, &facetDofsWithAll)); 2055f98464cbSLawrence Mitchell if (patch->precomputeElementTensors) { 2056f98464cbSLawrence Mitchell PetscInt nFacetDof = 2 * patch->totalDofsPerCell; 2057f98464cbSLawrence Mitchell const PetscScalar *elementTensors; 2058f98464cbSLawrence Mitchell 20599566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(patch->intFacetMats, &elementTensors)); 2060f98464cbSLawrence Mitchell 2061f98464cbSLawrence Mitchell for (i = 0; i < numIntFacets; i++) { 2062f98464cbSLawrence Mitchell const PetscInt facet = intFacetsArray[i + intFacetOffset]; 2063de2d1767SPatrick Farrell const PetscScalar *v = elementTensors + patch->precomputedIntFacetTensorLocations[facet - fStart] * nFacetDof * nFacetDof; 2064f98464cbSLawrence Mitchell idx = 0; 2065f98464cbSLawrence Mitchell /* 2066*f1580f4eSBarry Smith 0--1 2067*f1580f4eSBarry Smith |\-| 2068*f1580f4eSBarry Smith |+\| 2069*f1580f4eSBarry Smith 2--3 2070*f1580f4eSBarry Smith [0, 2, 3, 0, 1, 3] 2071f98464cbSLawrence Mitchell */ 2072f98464cbSLawrence Mitchell for (c = 0; c < 2; c++) { 2073f98464cbSLawrence Mitchell const PetscInt cell = facetCells[2 * (intFacetOffset + i) + c]; 2074f98464cbSLawrence Mitchell for (d = 0; d < patch->totalDofsPerCell; d++) { 2075f98464cbSLawrence Mitchell facetDofs[idx] = dofsArray[(offset + cell) * patch->totalDofsPerCell + d]; 2076f98464cbSLawrence Mitchell idx++; 2077f98464cbSLawrence Mitchell } 2078f98464cbSLawrence Mitchell } 20799566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, nFacetDof, facetDofs, nFacetDof, facetDofs, v, ADD_VALUES)); 2080f98464cbSLawrence Mitchell } 20819566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(patch->intFacetMats, &elementTensors)); 2082f98464cbSLawrence Mitchell } else { 2083eb62eeaaSLawrence Mitchell /* 2084*f1580f4eSBarry Smith 0--1 2085*f1580f4eSBarry Smith |\-| 2086*f1580f4eSBarry Smith |+\| 2087*f1580f4eSBarry Smith 2--3 2088*f1580f4eSBarry Smith [0, 2, 3, 0, 1, 3] 2089eb62eeaaSLawrence Mitchell */ 2090eb62eeaaSLawrence Mitchell for (i = 0; i < numIntFacets; i++) { 2091eb62eeaaSLawrence Mitchell for (c = 0; c < 2; c++) { 2092eb62eeaaSLawrence Mitchell const PetscInt cell = facetCells[2 * (intFacetOffset + i) + c]; 2093eb62eeaaSLawrence Mitchell for (d = 0; d < patch->totalDofsPerCell; d++) { 2094eb62eeaaSLawrence Mitchell facetDofs[idx] = dofsArray[(offset + cell) * patch->totalDofsPerCell + d]; 2095ad540459SPierre Jolivet if (dofsArrayWithAll) facetDofsWithAll[idx] = dofsArrayWithAll[(offset + cell) * patch->totalDofsPerCell + d]; 2096eb62eeaaSLawrence Mitchell idx++; 2097eb62eeaaSLawrence Mitchell } 2098eb62eeaaSLawrence Mitchell } 2099eb62eeaaSLawrence Mitchell } 21009566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numIntFacets, intFacetsArray + intFacetOffset, PETSC_USE_POINTER, &facetIS)); 21019566063dSJacob Faibussowitsch PetscCall(patch->usercomputeopintfacet(pc, point, x, mat, facetIS, 2 * numIntFacets * patch->totalDofsPerCell, facetDofs, facetDofsWithAll, patch->usercomputeopintfacetctx)); 21029566063dSJacob Faibussowitsch PetscCall(ISDestroy(&facetIS)); 2103f98464cbSLawrence Mitchell } 21049566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->intFacetsToPatchCell, &facetCells)); 21059566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->intFacets, &intFacetsArray)); 21069566063dSJacob Faibussowitsch PetscCall(PetscFree(facetDofs)); 21079566063dSJacob Faibussowitsch PetscCall(PetscFree(facetDofsWithAll)); 21089566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dm)); 2109eb62eeaaSLawrence Mitchell } 211059109abcSLawrence Mitchell } 21116710cc29SPatrick Farrell 21129566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 21139566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 21146710cc29SPatrick Farrell 2115c73d2cf6SLawrence Mitchell if (!(withArtificial || isNonlinear) && patch->denseinverse) { 2116c73d2cf6SLawrence Mitchell MatFactorInfo info; 2117c73d2cf6SLawrence Mitchell PetscBool flg; 21189566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)mat, MATSEQDENSE, &flg)); 211928b400f6SJacob Faibussowitsch PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Invalid Mat type for dense inverse"); 21209566063dSJacob Faibussowitsch PetscCall(MatFactorInfoInitialize(&info)); 21219566063dSJacob Faibussowitsch PetscCall(MatLUFactor(mat, NULL, NULL, &info)); 21229566063dSJacob Faibussowitsch PetscCall(MatSeqDenseInvertFactors_Private(mat)); 2123c73d2cf6SLawrence Mitchell } 21249566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->cellIS)); 21254d04e9f1SPatrick Farrell if (withArtificial) { 21269566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->dofsWithArtificial, &dofsArray)); 2127c2e6f3c0SFlorian Wechsung } else { 21289566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->dofs, &dofsArray)); 2129c2e6f3c0SFlorian Wechsung } 213048a46eb9SPierre Jolivet if (isNonlinear) PetscCall(ISRestoreIndices(patch->dofsWithAll, &dofsArrayWithAll)); 21319566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->cells, &cellsArray)); 21322aa6f319SMatthew G. Knepley if (patch->viewMatrix) { 21332aa6f319SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 21342aa6f319SMatthew G. Knepley 213563a3b9bcSJacob Faibussowitsch PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN - 1, "Patch matrix for Point %" PetscInt_FMT, point)); 21369566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)mat, name)); 21379566063dSJacob Faibussowitsch PetscCall(ObjectView((PetscObject)mat, patch->viewerMatrix, patch->formatMatrix)); 21382aa6f319SMatthew G. Knepley } 21399566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_Patch_ComputeOp, pc, 0, 0, 0)); 21404bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 21414bbf5ea8SMatthew G. Knepley } 21424bbf5ea8SMatthew G. Knepley 21439371c9d4SSatish Balay static PetscErrorCode MatSetValues_PCPatch_Private(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar *v, InsertMode addv) { 2144fa84ea4cSLawrence Mitchell Vec data; 2145fa84ea4cSLawrence Mitchell PetscScalar *array; 2146fe988be2SFlorian Wechsung PetscInt bs, nz, i, j, cell; 2147fa84ea4cSLawrence Mitchell 21489566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(mat, &data)); 21499566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(data, &bs)); 21509566063dSJacob Faibussowitsch PetscCall(VecGetSize(data, &nz)); 21519566063dSJacob Faibussowitsch PetscCall(VecGetArray(data, &array)); 215208401ef6SPierre Jolivet PetscCheck(m == n, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Only for square insertion"); 215333cbca70SPatrick Farrell cell = (PetscInt)(idxm[0] / bs); /* use the fact that this is called once per cell */ 2154fa84ea4cSLawrence Mitchell for (i = 0; i < m; i++) { 215508401ef6SPierre Jolivet PetscCheck(idxm[i] == idxn[i], PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Row and column indices must match!"); 2156fa84ea4cSLawrence Mitchell for (j = 0; j < n; j++) { 2157fa84ea4cSLawrence Mitchell const PetscScalar v_ = v[i * bs + j]; 2158fa84ea4cSLawrence Mitchell /* Indexing is special to the data structure we have! */ 2159fa84ea4cSLawrence Mitchell if (addv == INSERT_VALUES) { 2160fe988be2SFlorian Wechsung array[cell * bs * bs + i * bs + j] = v_; 2161fa84ea4cSLawrence Mitchell } else { 2162fe988be2SFlorian Wechsung array[cell * bs * bs + i * bs + j] += v_; 2163fa84ea4cSLawrence Mitchell } 2164fa84ea4cSLawrence Mitchell } 2165fa84ea4cSLawrence Mitchell } 21669566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(data, &array)); 2167fa84ea4cSLawrence Mitchell PetscFunctionReturn(0); 2168fa84ea4cSLawrence Mitchell } 2169fa84ea4cSLawrence Mitchell 21709371c9d4SSatish Balay static PetscErrorCode PCPatchPrecomputePatchTensors_Private(PC pc) { 2171fa84ea4cSLawrence Mitchell PC_PATCH *patch = (PC_PATCH *)pc->data; 2172fa84ea4cSLawrence Mitchell const PetscInt *cellsArray; 2173fa84ea4cSLawrence Mitchell PetscInt ncell, offset; 2174fa84ea4cSLawrence Mitchell const PetscInt *dofMapArray; 2175fa84ea4cSLawrence Mitchell PetscInt i, j; 2176fa84ea4cSLawrence Mitchell IS dofMap; 2177fa84ea4cSLawrence Mitchell IS cellIS; 2178fa84ea4cSLawrence Mitchell const PetscInt ndof = patch->totalDofsPerCell; 2179fa84ea4cSLawrence Mitchell Mat vecMat; 2180fe988be2SFlorian Wechsung PetscInt cStart, cEnd; 2181fe988be2SFlorian Wechsung DM dm, plex; 2182fe988be2SFlorian Wechsung 21839566063dSJacob Faibussowitsch PetscCall(ISGetSize(patch->cells, &ncell)); 2184e9c2c94bSFlorian Wechsung if (!ncell) { /* No cells to assemble over -> skip */ 2185e9c2c94bSFlorian Wechsung PetscFunctionReturn(0); 2186e9c2c94bSFlorian Wechsung } 2187e9c2c94bSFlorian Wechsung 21889566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_Patch_ComputeOp, pc, 0, 0, 0)); 2189fa84ea4cSLawrence Mitchell 21909566063dSJacob Faibussowitsch PetscCall(PCGetDM(pc, &dm)); 21919566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 2192b6bb21d1SLawrence Mitchell dm = plex; 2193fa84ea4cSLawrence Mitchell if (!patch->allCells) { 2194fa84ea4cSLawrence Mitchell PetscHSetI cells; 2195fa84ea4cSLawrence Mitchell PetscHashIter hi; 2196fa84ea4cSLawrence Mitchell PetscInt pStart, pEnd; 2197fa84ea4cSLawrence Mitchell PetscInt *allCells = NULL; 21989566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&cells)); 21999566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->cells, &cellsArray)); 22009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(patch->cellCounts, &pStart, &pEnd)); 2201fa84ea4cSLawrence Mitchell for (i = pStart; i < pEnd; i++) { 22029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->cellCounts, i, &ncell)); 22039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->cellCounts, i, &offset)); 2204fa84ea4cSLawrence Mitchell if (ncell <= 0) continue; 220548a46eb9SPierre Jolivet for (j = 0; j < ncell; j++) PetscCall(PetscHSetIAdd(cells, cellsArray[offset + j])); 2206fa84ea4cSLawrence Mitchell } 22079566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->cells, &cellsArray)); 22089566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(cells, &ncell)); 22099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncell, &allCells)); 22109566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 22119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEnd - cStart, &patch->precomputedTensorLocations)); 2212fa84ea4cSLawrence Mitchell i = 0; 2213fa84ea4cSLawrence Mitchell PetscHashIterBegin(cells, hi); 2214fa84ea4cSLawrence Mitchell while (!PetscHashIterAtEnd(cells, hi)) { 2215fe988be2SFlorian Wechsung PetscHashIterGetKey(cells, hi, allCells[i]); 2216fe988be2SFlorian Wechsung patch->precomputedTensorLocations[allCells[i]] = i; 2217fa84ea4cSLawrence Mitchell PetscHashIterNext(cells, hi); 2218fe988be2SFlorian Wechsung i++; 2219fa84ea4cSLawrence Mitchell } 22209566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&cells)); 22219566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ncell, allCells, PETSC_OWN_POINTER, &patch->allCells)); 2222fa84ea4cSLawrence Mitchell } 22239566063dSJacob Faibussowitsch PetscCall(ISGetSize(patch->allCells, &ncell)); 2224fa84ea4cSLawrence Mitchell if (!patch->cellMats) { 22259566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, ncell * ndof * ndof, &patch->cellMats)); 22269566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(patch->cellMats, ndof)); 2227fa84ea4cSLawrence Mitchell } 22289566063dSJacob Faibussowitsch PetscCall(VecSet(patch->cellMats, 0)); 2229fa84ea4cSLawrence Mitchell 2230d0609cedSBarry Smith PetscCall(MatCreateShell(PETSC_COMM_SELF, ncell * ndof, ncell * ndof, ncell * ndof, ncell * ndof, (void *)patch->cellMats, &vecMat)); 22319566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(vecMat, MATOP_SET_VALUES, (void (*)(void)) & MatSetValues_PCPatch_Private)); 22329566063dSJacob Faibussowitsch PetscCall(ISGetSize(patch->allCells, &ncell)); 22339566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, ndof * ncell, 0, 1, &dofMap)); 22349566063dSJacob Faibussowitsch PetscCall(ISGetIndices(dofMap, &dofMapArray)); 22359566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->allCells, &cellsArray)); 22369566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ncell, cellsArray, PETSC_USE_POINTER, &cellIS)); 2237fa84ea4cSLawrence Mitchell /* TODO: Fix for DMPlex compute op, this bypasses a lot of the machinery and just assembles every element tensor. */ 2238792fecdfSBarry Smith PetscCallBack("PCPatch callback", patch->usercomputeop(pc, -1, NULL, vecMat, cellIS, ndof * ncell, dofMapArray, NULL, patch->usercomputeopctx)); 22399566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 22409566063dSJacob Faibussowitsch PetscCall(MatDestroy(&vecMat)); 22419566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->allCells, &cellsArray)); 22429566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(dofMap, &dofMapArray)); 22439566063dSJacob Faibussowitsch PetscCall(ISDestroy(&dofMap)); 2244f98464cbSLawrence Mitchell 2245f98464cbSLawrence Mitchell if (patch->usercomputeopintfacet) { 2246f98464cbSLawrence Mitchell PetscInt nIntFacets; 2247f98464cbSLawrence Mitchell IS intFacetsIS; 2248f98464cbSLawrence Mitchell const PetscInt *intFacetsArray = NULL; 2249f98464cbSLawrence Mitchell if (!patch->allIntFacets) { 2250f98464cbSLawrence Mitchell PetscHSetI facets; 2251f98464cbSLawrence Mitchell PetscHashIter hi; 2252f98464cbSLawrence Mitchell PetscInt pStart, pEnd, fStart, fEnd; 2253f98464cbSLawrence Mitchell PetscInt *allIntFacets = NULL; 22549566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&facets)); 22559566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->intFacets, &intFacetsArray)); 22569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(patch->intFacetCounts, &pStart, &pEnd)); 22579566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 2258f98464cbSLawrence Mitchell for (i = pStart; i < pEnd; i++) { 22599566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->intFacetCounts, i, &nIntFacets)); 22609566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->intFacetCounts, i, &offset)); 2261f98464cbSLawrence Mitchell if (nIntFacets <= 0) continue; 226248a46eb9SPierre Jolivet for (j = 0; j < nIntFacets; j++) PetscCall(PetscHSetIAdd(facets, intFacetsArray[offset + j])); 2263f98464cbSLawrence Mitchell } 22649566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->intFacets, &intFacetsArray)); 22659566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(facets, &nIntFacets)); 22669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nIntFacets, &allIntFacets)); 22679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(fEnd - fStart, &patch->precomputedIntFacetTensorLocations)); 2268f98464cbSLawrence Mitchell i = 0; 2269f98464cbSLawrence Mitchell PetscHashIterBegin(facets, hi); 2270f98464cbSLawrence Mitchell while (!PetscHashIterAtEnd(facets, hi)) { 2271f98464cbSLawrence Mitchell PetscHashIterGetKey(facets, hi, allIntFacets[i]); 2272de2d1767SPatrick Farrell patch->precomputedIntFacetTensorLocations[allIntFacets[i] - fStart] = i; 2273f98464cbSLawrence Mitchell PetscHashIterNext(facets, hi); 2274f98464cbSLawrence Mitchell i++; 2275f98464cbSLawrence Mitchell } 22769566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&facets)); 22779566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nIntFacets, allIntFacets, PETSC_OWN_POINTER, &patch->allIntFacets)); 2278f98464cbSLawrence Mitchell } 22799566063dSJacob Faibussowitsch PetscCall(ISGetSize(patch->allIntFacets, &nIntFacets)); 2280f98464cbSLawrence Mitchell if (!patch->intFacetMats) { 22819566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, nIntFacets * ndof * ndof * 4, &patch->intFacetMats)); 22829566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(patch->intFacetMats, ndof * 2)); 2283f98464cbSLawrence Mitchell } 22849566063dSJacob Faibussowitsch PetscCall(VecSet(patch->intFacetMats, 0)); 2285f98464cbSLawrence Mitchell 2286d0609cedSBarry Smith PetscCall(MatCreateShell(PETSC_COMM_SELF, nIntFacets * ndof * 2, nIntFacets * ndof * 2, nIntFacets * ndof * 2, nIntFacets * ndof * 2, (void *)patch->intFacetMats, &vecMat)); 22879566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(vecMat, MATOP_SET_VALUES, (void (*)(void)) & MatSetValues_PCPatch_Private)); 22889566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, 2 * ndof * nIntFacets, 0, 1, &dofMap)); 22899566063dSJacob Faibussowitsch PetscCall(ISGetIndices(dofMap, &dofMapArray)); 22909566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->allIntFacets, &intFacetsArray)); 22919566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nIntFacets, intFacetsArray, PETSC_USE_POINTER, &intFacetsIS)); 2292f98464cbSLawrence Mitchell /* TODO: Fix for DMPlex compute op, this bypasses a lot of the machinery and just assembles every element tensor. */ 2293792fecdfSBarry Smith PetscCallBack("PCPatch callback (interior facets)", patch->usercomputeopintfacet(pc, -1, NULL, vecMat, intFacetsIS, 2 * ndof * nIntFacets, dofMapArray, NULL, patch->usercomputeopintfacetctx)); 22949566063dSJacob Faibussowitsch PetscCall(ISDestroy(&intFacetsIS)); 22959566063dSJacob Faibussowitsch PetscCall(MatDestroy(&vecMat)); 22969566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->allIntFacets, &intFacetsArray)); 22979566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(dofMap, &dofMapArray)); 22989566063dSJacob Faibussowitsch PetscCall(ISDestroy(&dofMap)); 2299f98464cbSLawrence Mitchell } 23009566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dm)); 23019566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_Patch_ComputeOp, pc, 0, 0, 0)); 2302fa84ea4cSLawrence Mitchell 2303fa84ea4cSLawrence Mitchell PetscFunctionReturn(0); 2304fa84ea4cSLawrence Mitchell } 2305fa84ea4cSLawrence Mitchell 23069371c9d4SSatish Balay PetscErrorCode PCPatch_ScatterLocal_Private(PC pc, PetscInt p, Vec x, Vec y, InsertMode mode, ScatterMode scat, PatchScatterType scattertype) { 23074bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 23084bbf5ea8SMatthew G. Knepley const PetscScalar *xArray = NULL; 23094bbf5ea8SMatthew G. Knepley PetscScalar *yArray = NULL; 23104bbf5ea8SMatthew G. Knepley const PetscInt *gtolArray = NULL; 23114bbf5ea8SMatthew G. Knepley PetscInt dof, offset, lidx; 23124bbf5ea8SMatthew G. Knepley 23134bbf5ea8SMatthew G. Knepley PetscFunctionBeginHot; 23149566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &xArray)); 23159566063dSJacob Faibussowitsch PetscCall(VecGetArray(y, &yArray)); 23160904074fSPatrick Farrell if (scattertype == SCATTER_WITHARTIFICIAL) { 23179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCountsWithArtificial, p, &dof)); 23189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->gtolCountsWithArtificial, p, &offset)); 23199566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->gtolWithArtificial, >olArray)); 23200904074fSPatrick Farrell } else if (scattertype == SCATTER_WITHALL) { 23219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCountsWithAll, p, &dof)); 23229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->gtolCountsWithAll, p, &offset)); 23239566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->gtolWithAll, >olArray)); 2324c2e6f3c0SFlorian Wechsung } else { 23259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCounts, p, &dof)); 23269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->gtolCounts, p, &offset)); 23279566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->gtol, >olArray)); 2328c2e6f3c0SFlorian Wechsung } 23292472a847SBarry Smith PetscCheck(mode != INSERT_VALUES || scat == SCATTER_FORWARD, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Can't insert if not scattering forward"); 23302472a847SBarry Smith PetscCheck(mode != ADD_VALUES || scat == SCATTER_REVERSE, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Can't add if not scattering reverse"); 23314bbf5ea8SMatthew G. Knepley for (lidx = 0; lidx < dof; ++lidx) { 23324bbf5ea8SMatthew G. Knepley const PetscInt gidx = gtolArray[offset + lidx]; 23334bbf5ea8SMatthew G. Knepley 23344bbf5ea8SMatthew G. Knepley if (mode == INSERT_VALUES) yArray[lidx] = xArray[gidx]; /* Forward */ 23354bbf5ea8SMatthew G. Knepley else yArray[gidx] += xArray[lidx]; /* Reverse */ 23364bbf5ea8SMatthew G. Knepley } 23370904074fSPatrick Farrell if (scattertype == SCATTER_WITHARTIFICIAL) { 23389566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->gtolWithArtificial, >olArray)); 23390904074fSPatrick Farrell } else if (scattertype == SCATTER_WITHALL) { 23409566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->gtolWithAll, >olArray)); 2341c2e6f3c0SFlorian Wechsung } else { 23429566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->gtol, >olArray)); 2343c2e6f3c0SFlorian Wechsung } 23449566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &xArray)); 23459566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(y, &yArray)); 23464bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 23474bbf5ea8SMatthew G. Knepley } 23484bbf5ea8SMatthew G. Knepley 23499371c9d4SSatish Balay static PetscErrorCode PCSetUp_PATCH_Linear(PC pc) { 2350dadc69c5SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 2351dadc69c5SMatthew G. Knepley const char *prefix; 2352dadc69c5SMatthew G. Knepley PetscInt i; 2353dadc69c5SMatthew G. Knepley 2354dadc69c5SMatthew G. Knepley PetscFunctionBegin; 2355dadc69c5SMatthew G. Knepley if (!pc->setupcalled) { 23567827d75bSBarry Smith PetscCheck(patch->save_operators || !patch->denseinverse, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Can't have dense inverse without save operators"); 2357c73d2cf6SLawrence Mitchell if (!patch->denseinverse) { 23589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(patch->npatch, &patch->solver)); 23599566063dSJacob Faibussowitsch PetscCall(PCGetOptionsPrefix(pc, &prefix)); 2360dadc69c5SMatthew G. Knepley for (i = 0; i < patch->npatch; ++i) { 2361dadc69c5SMatthew G. Knepley KSP ksp; 2362dadc69c5SMatthew G. Knepley PC subpc; 2363dadc69c5SMatthew G. Knepley 23649566063dSJacob Faibussowitsch PetscCall(KSPCreate(PETSC_COMM_SELF, &ksp)); 23659566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(ksp, pc->erroriffailure)); 23669566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(ksp, prefix)); 23679566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(ksp, "sub_")); 23689566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)ksp, (PetscObject)pc, 1)); 23699566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &subpc)); 23709566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)subpc, (PetscObject)pc, 1)); 23719566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)pc, (PetscObject)ksp)); 2372dadc69c5SMatthew G. Knepley patch->solver[i] = (PetscObject)ksp; 2373dadc69c5SMatthew G. Knepley } 2374dadc69c5SMatthew G. Knepley } 2375c73d2cf6SLawrence Mitchell } 2376dadc69c5SMatthew G. Knepley if (patch->save_operators) { 23771baa6e33SBarry Smith if (patch->precomputeElementTensors) PetscCall(PCPatchPrecomputePatchTensors_Private(pc)); 2378dadc69c5SMatthew G. Knepley for (i = 0; i < patch->npatch; ++i) { 23799566063dSJacob Faibussowitsch PetscCall(PCPatchComputeOperator_Internal(pc, NULL, patch->mat[i], i, PETSC_FALSE)); 2380c73d2cf6SLawrence Mitchell if (!patch->denseinverse) { 23819566063dSJacob Faibussowitsch PetscCall(KSPSetOperators((KSP)patch->solver[i], patch->mat[i], patch->mat[i])); 23829d4fc724SLawrence Mitchell } else if (patch->mat[i] && !patch->densesolve) { 23839d4fc724SLawrence Mitchell /* Setup matmult callback */ 23849566063dSJacob Faibussowitsch PetscCall(MatGetOperation(patch->mat[i], MATOP_MULT, (void (**)(void)) & patch->densesolve)); 2385dadc69c5SMatthew G. Knepley } 2386dadc69c5SMatthew G. Knepley } 2387c73d2cf6SLawrence Mitchell } 238834d8b122SPatrick Farrell if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) { 238934d8b122SPatrick Farrell for (i = 0; i < patch->npatch; ++i) { 23901202d238SPatrick Farrell /* Instead of padding patch->patchUpdate with zeros to get */ 23911202d238SPatrick Farrell /* patch->patchUpdateWithArtificial and then multiplying with the matrix, */ 239234d8b122SPatrick Farrell /* just get rid of the columns that correspond to the dofs with */ 239334d8b122SPatrick Farrell /* artificial bcs. That's of course fairly inefficient, hopefully we */ 239434d8b122SPatrick Farrell /* can just assemble the rectangular matrix in the first place. */ 239534d8b122SPatrick Farrell Mat matSquare; 239634d8b122SPatrick Farrell IS rowis; 239734d8b122SPatrick Farrell PetscInt dof; 239834d8b122SPatrick Farrell 23999566063dSJacob Faibussowitsch PetscCall(MatGetSize(patch->mat[i], &dof, NULL)); 240034d8b122SPatrick Farrell if (dof == 0) { 240134d8b122SPatrick Farrell patch->matWithArtificial[i] = NULL; 240234d8b122SPatrick Farrell continue; 240334d8b122SPatrick Farrell } 240434d8b122SPatrick Farrell 24059566063dSJacob Faibussowitsch PetscCall(PCPatchCreateMatrix_Private(pc, i, &matSquare, PETSC_TRUE)); 24069566063dSJacob Faibussowitsch PetscCall(PCPatchComputeOperator_Internal(pc, NULL, matSquare, i, PETSC_TRUE)); 240734d8b122SPatrick Farrell 24089566063dSJacob Faibussowitsch PetscCall(MatGetSize(matSquare, &dof, NULL)); 24099566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, dof, 0, 1, &rowis)); 241034d8b122SPatrick Farrell if (pc->setupcalled) { 24119566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(matSquare, rowis, patch->dofMappingWithoutToWithArtificial[i], MAT_REUSE_MATRIX, &patch->matWithArtificial[i])); 241234d8b122SPatrick Farrell } else { 24139566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(matSquare, rowis, patch->dofMappingWithoutToWithArtificial[i], MAT_INITIAL_MATRIX, &patch->matWithArtificial[i])); 241434d8b122SPatrick Farrell } 24159566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rowis)); 24169566063dSJacob Faibussowitsch PetscCall(MatDestroy(&matSquare)); 241734d8b122SPatrick Farrell } 241834d8b122SPatrick Farrell } 2419dadc69c5SMatthew G. Knepley PetscFunctionReturn(0); 2420dadc69c5SMatthew G. Knepley } 2421dadc69c5SMatthew G. Knepley 24229371c9d4SSatish Balay static PetscErrorCode PCSetUp_PATCH(PC pc) { 24234bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 2424557beb66SLawrence Mitchell PetscInt i; 242539fd2e8aSPatrick Farrell PetscBool isNonlinear; 24269d4fc724SLawrence Mitchell PetscInt maxDof = -1, maxDofWithArtificial = -1; 24274bbf5ea8SMatthew G. Knepley 24284bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 24294bbf5ea8SMatthew G. Knepley if (!pc->setupcalled) { 24304bbf5ea8SMatthew G. Knepley PetscInt pStart, pEnd, p; 24314bbf5ea8SMatthew G. Knepley PetscInt localSize; 24324bbf5ea8SMatthew G. Knepley 24339566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_Patch_CreatePatches, pc, 0, 0, 0)); 24344bbf5ea8SMatthew G. Knepley 2435debbdec3SPatrick Farrell isNonlinear = patch->isNonlinear; 24365f824522SMatthew G. Knepley if (!patch->nsubspaces) { 2437b6bb21d1SLawrence Mitchell DM dm, plex; 24385f824522SMatthew G. Knepley PetscSection s; 2439bd026e97SJed Brown PetscInt cStart, cEnd, c, Nf, f, numGlobalBcs = 0, *globalBcs, *Nb, **cellDofs; 24405f824522SMatthew G. Knepley 24419566063dSJacob Faibussowitsch PetscCall(PCGetDM(pc, &dm)); 244228b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Must set DM for PCPATCH or call PCPatchSetDiscretisationInfo()"); 24439566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 2444b6bb21d1SLawrence Mitchell dm = plex; 24459566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, &s)); 24469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(s, &Nf)); 24479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(s, &pStart, &pEnd)); 24485f824522SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 24495f824522SMatthew G. Knepley PetscInt cdof; 24509566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(s, p, &cdof)); 24515f824522SMatthew G. Knepley numGlobalBcs += cdof; 24525f824522SMatthew G. Knepley } 24539566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 24549566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(Nf, &Nb, Nf, &cellDofs, numGlobalBcs, &globalBcs)); 24555f824522SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 24565f824522SMatthew G. Knepley PetscFE fe; 24575f824522SMatthew G. Knepley PetscDualSpace sp; 24585f824522SMatthew G. Knepley PetscInt cdoff = 0; 24595f824522SMatthew G. Knepley 24609566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, f, NULL, (PetscObject *)&fe)); 24619566063dSJacob Faibussowitsch /* PetscCall(PetscFEGetNumComponents(fe, &Nc[f])); */ 24629566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace(fe, &sp)); 24639566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(sp, &Nb[f])); 24645f824522SMatthew G. Knepley 24659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((cEnd - cStart) * Nb[f], &cellDofs[f])); 24665f824522SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 24675f824522SMatthew G. Knepley PetscInt *closure = NULL; 24685f824522SMatthew G. Knepley PetscInt clSize = 0, cl; 24695f824522SMatthew G. Knepley 24709566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 24715f824522SMatthew G. Knepley for (cl = 0; cl < clSize * 2; cl += 2) { 24725f824522SMatthew G. Knepley const PetscInt p = closure[cl]; 24735f824522SMatthew G. Knepley PetscInt fdof, d, foff; 24745f824522SMatthew G. Knepley 24759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(s, p, f, &fdof)); 24769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(s, p, f, &foff)); 24775f824522SMatthew G. Knepley for (d = 0; d < fdof; ++d, ++cdoff) cellDofs[f][cdoff] = foff + d; 24785f824522SMatthew G. Knepley } 24799566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 24805f824522SMatthew G. Knepley } 248163a3b9bcSJacob Faibussowitsch PetscCheck(cdoff == (cEnd - cStart) * Nb[f], PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_SIZ, "Total number of cellDofs %" PetscInt_FMT " for field %" PetscInt_FMT " should be Nc (%" PetscInt_FMT ") * cellDof (%" PetscInt_FMT ")", cdoff, f, cEnd - cStart, Nb[f]); 24825f824522SMatthew G. Knepley } 24835f824522SMatthew G. Knepley numGlobalBcs = 0; 24845f824522SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 24855f824522SMatthew G. Knepley const PetscInt *ind; 24865f824522SMatthew G. Knepley PetscInt off, cdof, d; 24875f824522SMatthew G. Knepley 24889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(s, p, &off)); 24899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(s, p, &cdof)); 24909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(s, p, &ind)); 24915f824522SMatthew G. Knepley for (d = 0; d < cdof; ++d) globalBcs[numGlobalBcs++] = off + ind[d]; 24925f824522SMatthew G. Knepley } 24935f824522SMatthew G. Knepley 24949566063dSJacob Faibussowitsch PetscCall(PCPatchSetDiscretisationInfoCombined(pc, dm, Nb, (const PetscInt **)cellDofs, numGlobalBcs, globalBcs, numGlobalBcs, globalBcs)); 249548a46eb9SPierre Jolivet for (f = 0; f < Nf; ++f) PetscCall(PetscFree(cellDofs[f])); 24969566063dSJacob Faibussowitsch PetscCall(PetscFree3(Nb, cellDofs, globalBcs)); 24979566063dSJacob Faibussowitsch PetscCall(PCPatchSetComputeFunction(pc, PCPatchComputeFunction_DMPlex_Private, NULL)); 24989566063dSJacob Faibussowitsch PetscCall(PCPatchSetComputeOperator(pc, PCPatchComputeOperator_DMPlex_Private, NULL)); 24999566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dm)); 25005f824522SMatthew G. Knepley } 25015f824522SMatthew G. Knepley 25024bbf5ea8SMatthew G. Knepley localSize = patch->subspaceOffsets[patch->nsubspaces]; 25039566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, localSize, &patch->localRHS)); 25049566063dSJacob Faibussowitsch PetscCall(VecSetUp(patch->localRHS)); 25059566063dSJacob Faibussowitsch PetscCall(VecDuplicate(patch->localRHS, &patch->localUpdate)); 25069566063dSJacob Faibussowitsch PetscCall(PCPatchCreateCellPatches(pc)); 25079566063dSJacob Faibussowitsch PetscCall(PCPatchCreateCellPatchDiscretisationInfo(pc)); 25084bbf5ea8SMatthew G. Knepley 25094bbf5ea8SMatthew G. Knepley /* OK, now build the work vectors */ 25109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(patch->gtolCounts, &pStart, &pEnd)); 2511c2e6f3c0SFlorian Wechsung 251248a46eb9SPierre Jolivet if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) PetscCall(PetscMalloc1(patch->npatch, &patch->dofMappingWithoutToWithArtificial)); 251348a46eb9SPierre Jolivet if (isNonlinear) PetscCall(PetscMalloc1(patch->npatch, &patch->dofMappingWithoutToWithAll)); 25144bbf5ea8SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 25154bbf5ea8SMatthew G. Knepley PetscInt dof; 25164bbf5ea8SMatthew G. Knepley 25179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCounts, p, &dof)); 25182f613bf5SBarry Smith maxDof = PetscMax(maxDof, dof); 25190904074fSPatrick Farrell if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) { 25203bb0e8f7SKarl Rupp const PetscInt *gtolArray, *gtolArrayWithArtificial = NULL; 25213bb0e8f7SKarl Rupp PetscInt numPatchDofs, offset; 25223bb0e8f7SKarl Rupp PetscInt numPatchDofsWithArtificial, offsetWithArtificial; 25233bb0e8f7SKarl Rupp PetscInt dofWithoutArtificialCounter = 0; 25243bb0e8f7SKarl Rupp PetscInt *patchWithoutArtificialToWithArtificialArray; 25253bb0e8f7SKarl Rupp 25269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCountsWithArtificial, p, &dof)); 25279d4fc724SLawrence Mitchell maxDofWithArtificial = PetscMax(maxDofWithArtificial, dof); 2528c2e6f3c0SFlorian Wechsung 2529e047a90bSFlorian Wechsung /* Now build the mapping that for a dof in a patch WITHOUT dofs that have artificial bcs gives the */ 2530e047a90bSFlorian Wechsung /* the index in the patch with all dofs */ 25319566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->gtol, >olArray)); 253263deea8eSPatrick Farrell 25339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCounts, p, &numPatchDofs)); 253447aca4a6SPatrick Farrell if (numPatchDofs == 0) { 253547aca4a6SPatrick Farrell patch->dofMappingWithoutToWithArtificial[p - pStart] = NULL; 253647aca4a6SPatrick Farrell continue; 253747aca4a6SPatrick Farrell } 253863deea8eSPatrick Farrell 25399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->gtolCounts, p, &offset)); 25409566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->gtolWithArtificial, >olArrayWithArtificial)); 25419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCountsWithArtificial, p, &numPatchDofsWithArtificial)); 25429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->gtolCountsWithArtificial, p, &offsetWithArtificial)); 2543c2e6f3c0SFlorian Wechsung 25449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPatchDofs, &patchWithoutArtificialToWithArtificialArray)); 2545b0c21b6aSKarl Rupp for (i = 0; i < numPatchDofsWithArtificial; i++) { 2546e047a90bSFlorian Wechsung if (gtolArrayWithArtificial[i + offsetWithArtificial] == gtolArray[offset + dofWithoutArtificialCounter]) { 2547c2e6f3c0SFlorian Wechsung patchWithoutArtificialToWithArtificialArray[dofWithoutArtificialCounter] = i; 2548c2e6f3c0SFlorian Wechsung dofWithoutArtificialCounter++; 25499371c9d4SSatish Balay if (dofWithoutArtificialCounter == numPatchDofs) break; 2550c2e6f3c0SFlorian Wechsung } 2551c2e6f3c0SFlorian Wechsung } 25529566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numPatchDofs, patchWithoutArtificialToWithArtificialArray, PETSC_OWN_POINTER, &patch->dofMappingWithoutToWithArtificial[p - pStart])); 25539566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->gtol, >olArray)); 25549566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->gtolWithArtificial, >olArrayWithArtificial)); 2555c2e6f3c0SFlorian Wechsung } 25560997d788SPatrick Farrell } 25570997d788SPatrick Farrell for (p = pStart; p < pEnd; ++p) { 25580904074fSPatrick Farrell if (isNonlinear) { 25590904074fSPatrick Farrell const PetscInt *gtolArray, *gtolArrayWithAll = NULL; 25600904074fSPatrick Farrell PetscInt numPatchDofs, offset; 25610904074fSPatrick Farrell PetscInt numPatchDofsWithAll, offsetWithAll; 25620904074fSPatrick Farrell PetscInt dofWithoutAllCounter = 0; 25630904074fSPatrick Farrell PetscInt *patchWithoutAllToWithAllArray; 25640904074fSPatrick Farrell 25650904074fSPatrick Farrell /* Now build the mapping that for a dof in a patch WITHOUT dofs that have artificial bcs gives the */ 25660904074fSPatrick Farrell /* the index in the patch with all dofs */ 25679566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->gtol, >olArray)); 25680904074fSPatrick Farrell 25699566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCounts, p, &numPatchDofs)); 257047aca4a6SPatrick Farrell if (numPatchDofs == 0) { 2571b88cb22dSPatrick Farrell patch->dofMappingWithoutToWithAll[p - pStart] = NULL; 257247aca4a6SPatrick Farrell continue; 257347aca4a6SPatrick Farrell } 25740904074fSPatrick Farrell 25759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->gtolCounts, p, &offset)); 25769566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->gtolWithAll, >olArrayWithAll)); 25779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCountsWithAll, p, &numPatchDofsWithAll)); 25789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->gtolCountsWithAll, p, &offsetWithAll)); 25790904074fSPatrick Farrell 25809566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPatchDofs, &patchWithoutAllToWithAllArray)); 25810904074fSPatrick Farrell 25820904074fSPatrick Farrell for (i = 0; i < numPatchDofsWithAll; i++) { 25830904074fSPatrick Farrell if (gtolArrayWithAll[i + offsetWithAll] == gtolArray[offset + dofWithoutAllCounter]) { 25840904074fSPatrick Farrell patchWithoutAllToWithAllArray[dofWithoutAllCounter] = i; 25850904074fSPatrick Farrell dofWithoutAllCounter++; 25869371c9d4SSatish Balay if (dofWithoutAllCounter == numPatchDofs) break; 25870904074fSPatrick Farrell } 25880904074fSPatrick Farrell } 25899566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numPatchDofs, patchWithoutAllToWithAllArray, PETSC_OWN_POINTER, &patch->dofMappingWithoutToWithAll[p - pStart])); 25909566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->gtol, >olArray)); 25919566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->gtolWithAll, >olArrayWithAll)); 25920904074fSPatrick Farrell } 25934bbf5ea8SMatthew G. Knepley } 259460dd46caSLawrence Mitchell if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) { 25959566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, maxDofWithArtificial, &patch->patchRHSWithArtificial)); 25969566063dSJacob Faibussowitsch PetscCall(VecSetUp(patch->patchRHSWithArtificial)); 259760dd46caSLawrence Mitchell } 25989566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, maxDof, &patch->patchRHS)); 25999566063dSJacob Faibussowitsch PetscCall(VecSetUp(patch->patchRHS)); 26009566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, maxDof, &patch->patchUpdate)); 26019566063dSJacob Faibussowitsch PetscCall(VecSetUp(patch->patchUpdate)); 26024bbf5ea8SMatthew G. Knepley if (patch->save_operators) { 26039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(patch->npatch, &patch->mat)); 260448a46eb9SPierre Jolivet for (i = 0; i < patch->npatch; ++i) PetscCall(PCPatchCreateMatrix_Private(pc, i, &patch->mat[i], PETSC_FALSE)); 26054bbf5ea8SMatthew G. Knepley } 26069566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_Patch_CreatePatches, pc, 0, 0, 0)); 26074bbf5ea8SMatthew G. Knepley 26084bbf5ea8SMatthew G. Knepley /* If desired, calculate weights for dof multiplicity */ 26094bbf5ea8SMatthew G. Knepley if (patch->partition_of_unity) { 26103bb0e8f7SKarl Rupp PetscScalar *input = NULL; 26113bb0e8f7SKarl Rupp PetscScalar *output = NULL; 26123bb0e8f7SKarl Rupp Vec global; 26133bb0e8f7SKarl Rupp 26149566063dSJacob Faibussowitsch PetscCall(VecDuplicate(patch->localRHS, &patch->dof_weights)); 261561c4b389SFlorian Wechsung if (patch->local_composition_type == PC_COMPOSITE_ADDITIVE) { 26164bbf5ea8SMatthew G. Knepley for (i = 0; i < patch->npatch; ++i) { 26174bbf5ea8SMatthew G. Knepley PetscInt dof; 26184bbf5ea8SMatthew G. Knepley 26199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCounts, i + pStart, &dof)); 26204bbf5ea8SMatthew G. Knepley if (dof <= 0) continue; 26219566063dSJacob Faibussowitsch PetscCall(VecSet(patch->patchRHS, 1.0)); 26229566063dSJacob Faibussowitsch PetscCall(PCPatch_ScatterLocal_Private(pc, i + pStart, patch->patchRHS, patch->dof_weights, ADD_VALUES, SCATTER_REVERSE, SCATTER_INTERIOR)); 26234bbf5ea8SMatthew G. Knepley } 2624c2e6f3c0SFlorian Wechsung } else { 2625e047a90bSFlorian Wechsung /* multiplicative is actually only locally multiplicative and globally additive. need the pou where the mesh decomposition overlaps */ 26269566063dSJacob Faibussowitsch PetscCall(VecSet(patch->dof_weights, 1.0)); 26274bbf5ea8SMatthew G. Knepley } 2628d132cafaSFlorian Wechsung 2629d132cafaSFlorian Wechsung VecDuplicate(patch->dof_weights, &global); 2630d132cafaSFlorian Wechsung VecSet(global, 0.); 2631d132cafaSFlorian Wechsung 26329566063dSJacob Faibussowitsch PetscCall(VecGetArray(patch->dof_weights, &input)); 26339566063dSJacob Faibussowitsch PetscCall(VecGetArray(global, &output)); 26349566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(patch->sectionSF, MPIU_SCALAR, input, output, MPI_SUM)); 26359566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(patch->sectionSF, MPIU_SCALAR, input, output, MPI_SUM)); 26369566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(patch->dof_weights, &input)); 26379566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(global, &output)); 2638d132cafaSFlorian Wechsung 26399566063dSJacob Faibussowitsch PetscCall(VecReciprocal(global)); 2640d132cafaSFlorian Wechsung 26419566063dSJacob Faibussowitsch PetscCall(VecGetArray(patch->dof_weights, &output)); 26429566063dSJacob Faibussowitsch PetscCall(VecGetArray(global, &input)); 26439566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(patch->sectionSF, MPIU_SCALAR, input, output, MPI_REPLACE)); 26449566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(patch->sectionSF, MPIU_SCALAR, input, output, MPI_REPLACE)); 26459566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(patch->dof_weights, &output)); 26469566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(global, &input)); 26479566063dSJacob Faibussowitsch PetscCall(VecDestroy(&global)); 26484bbf5ea8SMatthew G. Knepley } 264948a46eb9SPierre Jolivet if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE && patch->save_operators && !patch->isNonlinear) PetscCall(PetscMalloc1(patch->npatch, &patch->matWithArtificial)); 26504bbf5ea8SMatthew G. Knepley } 26519566063dSJacob Faibussowitsch PetscCall((*patch->setupsolver)(pc)); 2652dadc69c5SMatthew G. Knepley PetscFunctionReturn(0); 26534bbf5ea8SMatthew G. Knepley } 2654dadc69c5SMatthew G. Knepley 26559371c9d4SSatish Balay static PetscErrorCode PCApply_PATCH_Linear(PC pc, PetscInt i, Vec x, Vec y) { 2656dadc69c5SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 2657c73d2cf6SLawrence Mitchell KSP ksp; 26589d4fc724SLawrence Mitchell Mat op; 26599d4fc724SLawrence Mitchell PetscInt m, n; 2660dadc69c5SMatthew G. Knepley 2661dadc69c5SMatthew G. Knepley PetscFunctionBegin; 2662c73d2cf6SLawrence Mitchell if (patch->denseinverse) { 26639566063dSJacob Faibussowitsch PetscCall((*patch->densesolve)(patch->mat[i], x, y)); 2664c73d2cf6SLawrence Mitchell PetscFunctionReturn(0); 2665c73d2cf6SLawrence Mitchell } 2666c73d2cf6SLawrence Mitchell ksp = (KSP)patch->solver[i]; 2667dadc69c5SMatthew G. Knepley if (!patch->save_operators) { 2668dadc69c5SMatthew G. Knepley Mat mat; 2669dadc69c5SMatthew G. Knepley 26709566063dSJacob Faibussowitsch PetscCall(PCPatchCreateMatrix_Private(pc, i, &mat, PETSC_FALSE)); 2671dadc69c5SMatthew G. Knepley /* Populate operator here. */ 26729566063dSJacob Faibussowitsch PetscCall(PCPatchComputeOperator_Internal(pc, NULL, mat, i, PETSC_FALSE)); 26739566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(ksp, mat, mat)); 2674dadc69c5SMatthew G. Knepley /* Drop reference so the KSPSetOperators below will blow it away. */ 26759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mat)); 2676dadc69c5SMatthew G. Knepley } 26779566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_Patch_Solve, pc, 0, 0, 0)); 267848a46eb9SPierre Jolivet if (!ksp->setfromoptionscalled) PetscCall(KSPSetFromOptions(ksp)); 26799d4fc724SLawrence Mitchell /* Disgusting trick to reuse work vectors */ 26809566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(ksp, &op, NULL)); 26819566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(op, &m, &n)); 26829d4fc724SLawrence Mitchell x->map->n = m; 26839d4fc724SLawrence Mitchell y->map->n = n; 26849d4fc724SLawrence Mitchell x->map->N = m; 26859d4fc724SLawrence Mitchell y->map->N = n; 26869566063dSJacob Faibussowitsch PetscCall(KSPSolve(ksp, x, y)); 26879566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(ksp, pc, y)); 26889566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_Patch_Solve, pc, 0, 0, 0)); 2689dadc69c5SMatthew G. Knepley if (!patch->save_operators) { 2690dadc69c5SMatthew G. Knepley PC pc; 26919566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(ksp, NULL, NULL)); 26929566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc)); 2693dadc69c5SMatthew G. Knepley /* Destroy PC context too, otherwise the factored matrix hangs around. */ 26949566063dSJacob Faibussowitsch PetscCall(PCReset(pc)); 26954bbf5ea8SMatthew G. Knepley } 26964bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 26974bbf5ea8SMatthew G. Knepley } 26984bbf5ea8SMatthew G. Knepley 26999371c9d4SSatish Balay static PetscErrorCode PCUpdateMultiplicative_PATCH_Linear(PC pc, PetscInt i, PetscInt pStart) { 27006c9c532dSPatrick Farrell PC_PATCH *patch = (PC_PATCH *)pc->data; 27016c9c532dSPatrick Farrell Mat multMat; 27029d4fc724SLawrence Mitchell PetscInt n, m; 27036c9c532dSPatrick Farrell 27044d04e9f1SPatrick Farrell PetscFunctionBegin; 27054d04e9f1SPatrick Farrell 27066c9c532dSPatrick Farrell if (patch->save_operators) { 27076c9c532dSPatrick Farrell multMat = patch->matWithArtificial[i]; 27086c9c532dSPatrick Farrell } else { 27096c9c532dSPatrick Farrell /*Very inefficient, hopefully we can just assemble the rectangular matrix in the first place.*/ 27106c9c532dSPatrick Farrell Mat matSquare; 27116c9c532dSPatrick Farrell PetscInt dof; 27126c9c532dSPatrick Farrell IS rowis; 27139566063dSJacob Faibussowitsch PetscCall(PCPatchCreateMatrix_Private(pc, i, &matSquare, PETSC_TRUE)); 27149566063dSJacob Faibussowitsch PetscCall(PCPatchComputeOperator_Internal(pc, NULL, matSquare, i, PETSC_TRUE)); 27159566063dSJacob Faibussowitsch PetscCall(MatGetSize(matSquare, &dof, NULL)); 27169566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, dof, 0, 1, &rowis)); 27179566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(matSquare, rowis, patch->dofMappingWithoutToWithArtificial[i], MAT_INITIAL_MATRIX, &multMat)); 27189566063dSJacob Faibussowitsch PetscCall(MatDestroy(&matSquare)); 27199566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rowis)); 27206c9c532dSPatrick Farrell } 27219d4fc724SLawrence Mitchell /* Disgusting trick to reuse work vectors */ 27229566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(multMat, &m, &n)); 27239d4fc724SLawrence Mitchell patch->patchUpdate->map->n = n; 27249d4fc724SLawrence Mitchell patch->patchRHSWithArtificial->map->n = m; 27259d4fc724SLawrence Mitchell patch->patchUpdate->map->N = n; 27269d4fc724SLawrence Mitchell patch->patchRHSWithArtificial->map->N = m; 27279566063dSJacob Faibussowitsch PetscCall(MatMult(multMat, patch->patchUpdate, patch->patchRHSWithArtificial)); 27289566063dSJacob Faibussowitsch PetscCall(VecScale(patch->patchRHSWithArtificial, -1.0)); 27299566063dSJacob Faibussowitsch PetscCall(PCPatch_ScatterLocal_Private(pc, i + pStart, patch->patchRHSWithArtificial, patch->localRHS, ADD_VALUES, SCATTER_REVERSE, SCATTER_WITHARTIFICIAL)); 273048a46eb9SPierre Jolivet if (!patch->save_operators) PetscCall(MatDestroy(&multMat)); 27314d04e9f1SPatrick Farrell PetscFunctionReturn(0); 27326c9c532dSPatrick Farrell } 27336c9c532dSPatrick Farrell 27349371c9d4SSatish Balay static PetscErrorCode PCApply_PATCH(PC pc, Vec x, Vec y) { 27354bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 27361202d238SPatrick Farrell const PetscScalar *globalRHS = NULL; 27371202d238SPatrick Farrell PetscScalar *localRHS = NULL; 27381202d238SPatrick Farrell PetscScalar *globalUpdate = NULL; 27394bbf5ea8SMatthew G. Knepley const PetscInt *bcNodes = NULL; 27404bbf5ea8SMatthew G. Knepley PetscInt nsweep = patch->symmetrise_sweep ? 2 : 1; 27414bbf5ea8SMatthew G. Knepley PetscInt start[2] = {0, 0}; 27424bbf5ea8SMatthew G. Knepley PetscInt end[2] = {-1, -1}; 27434bbf5ea8SMatthew G. Knepley const PetscInt inc[2] = {1, -1}; 27441202d238SPatrick Farrell const PetscScalar *localUpdate; 27454bbf5ea8SMatthew G. Knepley const PetscInt *iterationSet; 27464bbf5ea8SMatthew G. Knepley PetscInt pStart, numBcs, n, sweep, bc, j; 27474bbf5ea8SMatthew G. Knepley 27484bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 27499566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_Patch_Apply, pc, 0, 0, 0)); 27509566063dSJacob Faibussowitsch PetscCall(PetscOptionsPushGetViewerOff(PETSC_TRUE)); 275192d50984SMatthew G. Knepley /* start, end, inc have 2 entries to manage a second backward sweep if we symmetrize */ 27524bbf5ea8SMatthew G. Knepley end[0] = patch->npatch; 27534bbf5ea8SMatthew G. Knepley start[1] = patch->npatch - 1; 27544bbf5ea8SMatthew G. Knepley if (patch->user_patches) { 27559566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(patch->iterationSet, &end[0])); 27564bbf5ea8SMatthew G. Knepley start[1] = end[0] - 1; 27579566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->iterationSet, &iterationSet)); 27584bbf5ea8SMatthew G. Knepley } 27594bbf5ea8SMatthew G. Knepley /* Scatter from global space into overlapped local spaces */ 27609566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &globalRHS)); 27619566063dSJacob Faibussowitsch PetscCall(VecGetArray(patch->localRHS, &localRHS)); 27629566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(patch->sectionSF, MPIU_SCALAR, globalRHS, localRHS, MPI_REPLACE)); 27639566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(patch->sectionSF, MPIU_SCALAR, globalRHS, localRHS, MPI_REPLACE)); 27649566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &globalRHS)); 27659566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(patch->localRHS, &localRHS)); 27664bbf5ea8SMatthew G. Knepley 27679566063dSJacob Faibussowitsch PetscCall(VecSet(patch->localUpdate, 0.0)); 27689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(patch->gtolCounts, &pStart, NULL)); 27699566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_Patch_Solve, pc, 0, 0, 0)); 27704bbf5ea8SMatthew G. Knepley for (sweep = 0; sweep < nsweep; sweep++) { 27714bbf5ea8SMatthew G. Knepley for (j = start[sweep]; j * inc[sweep] < end[sweep] * inc[sweep]; j += inc[sweep]) { 27724bbf5ea8SMatthew G. Knepley PetscInt i = patch->user_patches ? iterationSet[j] : j; 27734bbf5ea8SMatthew G. Knepley PetscInt start, len; 27744bbf5ea8SMatthew G. Knepley 27759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCounts, i + pStart, &len)); 27769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->gtolCounts, i + pStart, &start)); 27774bbf5ea8SMatthew G. Knepley /* TODO: Squash out these guys in the setup as well. */ 27784bbf5ea8SMatthew G. Knepley if (len <= 0) continue; 27794bbf5ea8SMatthew G. Knepley /* TODO: Do we need different scatters for X and Y? */ 27809566063dSJacob Faibussowitsch PetscCall(PCPatch_ScatterLocal_Private(pc, i + pStart, patch->localRHS, patch->patchRHS, INSERT_VALUES, SCATTER_FORWARD, SCATTER_INTERIOR)); 27819566063dSJacob Faibussowitsch PetscCall((*patch->applysolver)(pc, i, patch->patchRHS, patch->patchUpdate)); 27829566063dSJacob Faibussowitsch PetscCall(PCPatch_ScatterLocal_Private(pc, i + pStart, patch->patchUpdate, patch->localUpdate, ADD_VALUES, SCATTER_REVERSE, SCATTER_INTERIOR)); 278348a46eb9SPierre Jolivet if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) PetscCall((*patch->updatemultiplicative)(pc, i, pStart)); 27844bbf5ea8SMatthew G. Knepley } 27854bbf5ea8SMatthew G. Knepley } 27869566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_Patch_Solve, pc, 0, 0, 0)); 27879566063dSJacob Faibussowitsch if (patch->user_patches) PetscCall(ISRestoreIndices(patch->iterationSet, &iterationSet)); 27884bbf5ea8SMatthew G. Knepley /* XXX: should we do this on the global vector? */ 27891baa6e33SBarry Smith if (patch->partition_of_unity) PetscCall(VecPointwiseMult(patch->localUpdate, patch->localUpdate, patch->dof_weights)); 27901202d238SPatrick Farrell /* Now patch->localUpdate contains the solution of the patch solves, so we need to combine them all. */ 27919566063dSJacob Faibussowitsch PetscCall(VecSet(y, 0.0)); 27929566063dSJacob Faibussowitsch PetscCall(VecGetArray(y, &globalUpdate)); 27939566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(patch->localUpdate, &localUpdate)); 27949566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(patch->sectionSF, MPIU_SCALAR, localUpdate, globalUpdate, MPI_SUM)); 27959566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(patch->sectionSF, MPIU_SCALAR, localUpdate, globalUpdate, MPI_SUM)); 27969566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(patch->localUpdate, &localUpdate)); 27974bbf5ea8SMatthew G. Knepley 27984bbf5ea8SMatthew G. Knepley /* Now we need to send the global BC values through */ 27999566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &globalRHS)); 28009566063dSJacob Faibussowitsch PetscCall(ISGetSize(patch->globalBcNodes, &numBcs)); 28019566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->globalBcNodes, &bcNodes)); 28029566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(x, &n)); 28034bbf5ea8SMatthew G. Knepley for (bc = 0; bc < numBcs; ++bc) { 28044bbf5ea8SMatthew G. Knepley const PetscInt idx = bcNodes[bc]; 28051202d238SPatrick Farrell if (idx < n) globalUpdate[idx] = globalRHS[idx]; 28064bbf5ea8SMatthew G. Knepley } 28074bbf5ea8SMatthew G. Knepley 28089566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->globalBcNodes, &bcNodes)); 28099566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &globalRHS)); 28109566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(y, &globalUpdate)); 28114bbf5ea8SMatthew G. Knepley 28129566063dSJacob Faibussowitsch PetscCall(PetscOptionsPopGetViewerOff()); 28139566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_Patch_Apply, pc, 0, 0, 0)); 28144bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 28154bbf5ea8SMatthew G. Knepley } 28164bbf5ea8SMatthew G. Knepley 28179371c9d4SSatish Balay static PetscErrorCode PCReset_PATCH_Linear(PC pc) { 2818dadc69c5SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 2819dadc69c5SMatthew G. Knepley PetscInt i; 2820dadc69c5SMatthew G. Knepley 2821dadc69c5SMatthew G. Knepley PetscFunctionBegin; 2822dadc69c5SMatthew G. Knepley if (patch->solver) { 28239566063dSJacob Faibussowitsch for (i = 0; i < patch->npatch; ++i) PetscCall(KSPReset((KSP)patch->solver[i])); 2824dadc69c5SMatthew G. Knepley } 2825dadc69c5SMatthew G. Knepley PetscFunctionReturn(0); 2826dadc69c5SMatthew G. Knepley } 2827dadc69c5SMatthew G. Knepley 28289371c9d4SSatish Balay static PetscErrorCode PCReset_PATCH(PC pc) { 28294bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 28304bbf5ea8SMatthew G. Knepley PetscInt i; 28314bbf5ea8SMatthew G. Knepley 28324bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 2833fa84ea4cSLawrence Mitchell 28349566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&patch->sectionSF)); 28359566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&patch->cellCounts)); 28369566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&patch->pointCounts)); 28379566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&patch->cellNumbering)); 28389566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&patch->gtolCounts)); 28399566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->gtol)); 28409566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->cells)); 28419566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->points)); 28429566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->dofs)); 28439566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->offs)); 28449566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&patch->patchSection)); 28459566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->ghostBcNodes)); 28469566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->globalBcNodes)); 28479566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&patch->gtolCountsWithArtificial)); 28489566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->gtolWithArtificial)); 28499566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->dofsWithArtificial)); 28509566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->offsWithArtificial)); 28519566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&patch->gtolCountsWithAll)); 28529566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->gtolWithAll)); 28539566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->dofsWithAll)); 28549566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->offsWithAll)); 28559566063dSJacob Faibussowitsch PetscCall(VecDestroy(&patch->cellMats)); 28569566063dSJacob Faibussowitsch PetscCall(VecDestroy(&patch->intFacetMats)); 28579566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->allCells)); 28589566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->intFacets)); 28599566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->extFacets)); 28609566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->intFacetsToPatchCell)); 28619566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&patch->intFacetCounts)); 28629566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&patch->extFacetCounts)); 28634bbf5ea8SMatthew G. Knepley 28649371c9d4SSatish Balay if (patch->dofSection) 28659371c9d4SSatish Balay for (i = 0; i < patch->nsubspaces; i++) PetscCall(PetscSectionDestroy(&patch->dofSection[i])); 28669566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->dofSection)); 28679566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->bs)); 28689566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->nodesPerCell)); 28699371c9d4SSatish Balay if (patch->cellNodeMap) 28709371c9d4SSatish Balay for (i = 0; i < patch->nsubspaces; i++) PetscCall(PetscFree(patch->cellNodeMap[i])); 28719566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->cellNodeMap)); 28729566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->subspaceOffsets)); 28734bbf5ea8SMatthew G. Knepley 28749566063dSJacob Faibussowitsch PetscCall((*patch->resetsolver)(pc)); 28754bbf5ea8SMatthew G. Knepley 287648a46eb9SPierre Jolivet if (patch->subspaces_to_exclude) PetscCall(PetscHSetIDestroy(&patch->subspaces_to_exclude)); 2877e4c66b91SPatrick Farrell 28789566063dSJacob Faibussowitsch PetscCall(VecDestroy(&patch->localRHS)); 28799566063dSJacob Faibussowitsch PetscCall(VecDestroy(&patch->localUpdate)); 28809566063dSJacob Faibussowitsch PetscCall(VecDestroy(&patch->patchRHS)); 28819566063dSJacob Faibussowitsch PetscCall(VecDestroy(&patch->patchUpdate)); 28829566063dSJacob Faibussowitsch PetscCall(VecDestroy(&patch->dof_weights)); 28834bbf5ea8SMatthew G. Knepley if (patch->patch_dof_weights) { 28849566063dSJacob Faibussowitsch for (i = 0; i < patch->npatch; ++i) PetscCall(VecDestroy(&patch->patch_dof_weights[i])); 28859566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->patch_dof_weights)); 28864bbf5ea8SMatthew G. Knepley } 28874bbf5ea8SMatthew G. Knepley if (patch->mat) { 28889566063dSJacob Faibussowitsch for (i = 0; i < patch->npatch; ++i) PetscCall(MatDestroy(&patch->mat[i])); 28899566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->mat)); 28905f824522SMatthew G. Knepley } 28910997d788SPatrick Farrell if (patch->matWithArtificial && !patch->isNonlinear) { 28929566063dSJacob Faibussowitsch for (i = 0; i < patch->npatch; ++i) PetscCall(MatDestroy(&patch->matWithArtificial[i])); 28939566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->matWithArtificial)); 289411ac8bb0SFlorian Wechsung } 28959566063dSJacob Faibussowitsch PetscCall(VecDestroy(&patch->patchRHSWithArtificial)); 289696b79ebeSFlorian Wechsung if (patch->dofMappingWithoutToWithArtificial) { 28979566063dSJacob Faibussowitsch for (i = 0; i < patch->npatch; ++i) PetscCall(ISDestroy(&patch->dofMappingWithoutToWithArtificial[i])); 28989566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->dofMappingWithoutToWithArtificial)); 289996b79ebeSFlorian Wechsung } 29000904074fSPatrick Farrell if (patch->dofMappingWithoutToWithAll) { 29019566063dSJacob Faibussowitsch for (i = 0; i < patch->npatch; ++i) PetscCall(ISDestroy(&patch->dofMappingWithoutToWithAll[i])); 29029566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->dofMappingWithoutToWithAll)); 29030904074fSPatrick Farrell } 29049566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->sub_mat_type)); 29055f824522SMatthew G. Knepley if (patch->userIS) { 29069566063dSJacob Faibussowitsch for (i = 0; i < patch->npatch; ++i) PetscCall(ISDestroy(&patch->userIS[i])); 29079566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->userIS)); 29085f824522SMatthew G. Knepley } 29099566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->precomputedTensorLocations)); 29109566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->precomputedIntFacetTensorLocations)); 2911f98464cbSLawrence Mitchell 29120a545947SLisandro Dalcin patch->bs = NULL; 29134bbf5ea8SMatthew G. Knepley patch->cellNodeMap = NULL; 29147974b488SMatthew G. Knepley patch->nsubspaces = 0; 29159566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->iterationSet)); 29165f824522SMatthew G. Knepley 29179566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&patch->viewerSection)); 29184bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 29194bbf5ea8SMatthew G. Knepley } 29204bbf5ea8SMatthew G. Knepley 29219371c9d4SSatish Balay static PetscErrorCode PCDestroy_PATCH_Linear(PC pc) { 29224bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 29234bbf5ea8SMatthew G. Knepley PetscInt i; 29244bbf5ea8SMatthew G. Knepley 29254bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 2926dadc69c5SMatthew G. Knepley if (patch->solver) { 29279566063dSJacob Faibussowitsch for (i = 0; i < patch->npatch; ++i) PetscCall(KSPDestroy((KSP *)&patch->solver[i])); 29289566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->solver)); 29294bbf5ea8SMatthew G. Knepley } 2930dadc69c5SMatthew G. Knepley PetscFunctionReturn(0); 2931dadc69c5SMatthew G. Knepley } 2932dadc69c5SMatthew G. Knepley 29339371c9d4SSatish Balay static PetscErrorCode PCDestroy_PATCH(PC pc) { 2934dadc69c5SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 2935dadc69c5SMatthew G. Knepley 2936dadc69c5SMatthew G. Knepley PetscFunctionBegin; 29379566063dSJacob Faibussowitsch PetscCall(PCReset_PATCH(pc)); 29389566063dSJacob Faibussowitsch PetscCall((*patch->destroysolver)(pc)); 29399566063dSJacob Faibussowitsch PetscCall(PetscFree(pc->data)); 29404bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 29414bbf5ea8SMatthew G. Knepley } 29424bbf5ea8SMatthew G. Knepley 29439371c9d4SSatish Balay static PetscErrorCode PCSetFromOptions_PATCH(PC pc, PetscOptionItems *PetscOptionsObject) { 29444bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 29454bbf5ea8SMatthew G. Knepley PCPatchConstructType patchConstructionType = PC_PATCH_STAR; 29465f824522SMatthew G. Knepley char sub_mat_type[PETSC_MAX_PATH_LEN]; 294710534d48SPatrick Farrell char option[PETSC_MAX_PATH_LEN]; 29485f824522SMatthew G. Knepley const char *prefix; 29494bbf5ea8SMatthew G. Knepley PetscBool flg, dimflg, codimflg; 29505f824522SMatthew G. Knepley MPI_Comm comm; 2951a48c39c8SPatrick Farrell PetscInt *ifields, nfields, k; 295261c4b389SFlorian Wechsung PCCompositeType loctype = PC_COMPOSITE_ADDITIVE; 29534bbf5ea8SMatthew G. Knepley 29544bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 29559566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)pc, &comm)); 29569566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)pc, &prefix)); 2957d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "Patch solver options"); 295810534d48SPatrick Farrell 29599566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_save_operators", patch->classname)); 29609566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool(option, "Store all patch operators for lifetime of object?", "PCPatchSetSaveOperators", patch->save_operators, &patch->save_operators, &flg)); 296110534d48SPatrick Farrell 29629566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_precompute_element_tensors", patch->classname)); 29639566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool(option, "Compute each element tensor only once?", "PCPatchSetPrecomputeElementTensors", patch->precomputeElementTensors, &patch->precomputeElementTensors, &flg)); 29649566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_partition_of_unity", patch->classname)); 29659566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool(option, "Weight contributions by dof multiplicity?", "PCPatchSetPartitionOfUnity", patch->partition_of_unity, &patch->partition_of_unity, &flg)); 296610534d48SPatrick Farrell 29679566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_local_type", patch->classname)); 29689566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum(option, "Type of local solver composition (additive or multiplicative)", "PCPatchSetLocalComposition", PCCompositeTypes, (PetscEnum)loctype, (PetscEnum *)&loctype, &flg)); 29699566063dSJacob Faibussowitsch if (flg) PetscCall(PCPatchSetLocalComposition(pc, loctype)); 29709566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_dense_inverse", patch->classname)); 29719566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool(option, "Compute inverses of patch matrices and apply directly? Ignores KSP/PC settings on patch.", "PCPatchSetDenseInverse", patch->denseinverse, &patch->denseinverse, &flg)); 29729566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_construct_dim", patch->classname)); 29739566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt(option, "What dimension of mesh point to construct patches by? (0 = vertices)", "PCPATCH", patch->dim, &patch->dim, &dimflg)); 29749566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_construct_codim", patch->classname)); 29759566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt(option, "What co-dimension of mesh point to construct patches by? (0 = cells)", "PCPATCH", patch->codim, &patch->codim, &codimflg)); 297608401ef6SPierre Jolivet PetscCheck(!dimflg || !codimflg, comm, PETSC_ERR_ARG_WRONG, "Can only set one of dimension or co-dimension"); 297710534d48SPatrick Farrell 29789566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_construct_type", patch->classname)); 29799566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum(option, "How should the patches be constructed?", "PCPatchSetConstructType", PCPatchConstructTypes, (PetscEnum)patchConstructionType, (PetscEnum *)&patchConstructionType, &flg)); 29809566063dSJacob Faibussowitsch if (flg) PetscCall(PCPatchSetConstructType(pc, patchConstructionType, NULL, NULL)); 298110534d48SPatrick Farrell 29829566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_vanka_dim", patch->classname)); 29839566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt(option, "Topological dimension of entities for Vanka to ignore", "PCPATCH", patch->vankadim, &patch->vankadim, &flg)); 298410534d48SPatrick Farrell 29859566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_ignore_dim", patch->classname)); 29869566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt(option, "Topological dimension of entities for completion to ignore", "PCPATCH", patch->ignoredim, &patch->ignoredim, &flg)); 298710534d48SPatrick Farrell 29889566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_pardecomp_overlap", patch->classname)); 29899566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt(option, "What overlap should we use in construct type pardecomp?", "PCPATCH", patch->pardecomp_overlap, &patch->pardecomp_overlap, &flg)); 2990b525f888SPatrick Farrell 29919566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_sub_mat_type", patch->classname)); 29929566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList(option, "Matrix type for patch solves", "PCPatchSetSubMatType", MatList, NULL, sub_mat_type, PETSC_MAX_PATH_LEN, &flg)); 29939566063dSJacob Faibussowitsch if (flg) PetscCall(PCPatchSetSubMatType(pc, sub_mat_type)); 299410534d48SPatrick Farrell 29959566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_symmetrise_sweep", patch->classname)); 29969566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool(option, "Go start->end, end->start?", "PCPATCH", patch->symmetrise_sweep, &patch->symmetrise_sweep, &flg)); 2997e4c66b91SPatrick Farrell 2998a48c39c8SPatrick Farrell /* If the user has set the number of subspaces, use that for the buffer size, 2999a48c39c8SPatrick Farrell otherwise use a large number */ 3000a48c39c8SPatrick Farrell if (patch->nsubspaces <= 0) { 3001a48c39c8SPatrick Farrell nfields = 128; 3002a48c39c8SPatrick Farrell } else { 3003a48c39c8SPatrick Farrell nfields = patch->nsubspaces; 3004a48c39c8SPatrick Farrell } 30059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nfields, &ifields)); 30069566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_exclude_subspaces", patch->classname)); 30079566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetIntArray(((PetscObject)pc)->options, ((PetscObject)pc)->prefix, option, ifields, &nfields, &flg)); 300808401ef6SPierre Jolivet PetscCheck(!flg || !(patchConstructionType == PC_PATCH_USER), comm, PETSC_ERR_ARG_INCOMP, "We cannot support excluding a subspace with user patches because we do not index patches with a mesh point"); 3009e4c66b91SPatrick Farrell if (flg) { 30109566063dSJacob Faibussowitsch PetscCall(PetscHSetIClear(patch->subspaces_to_exclude)); 301148a46eb9SPierre Jolivet for (k = 0; k < nfields; k++) PetscCall(PetscHSetIAdd(patch->subspaces_to_exclude, ifields[k])); 3012e4c66b91SPatrick Farrell } 30139566063dSJacob Faibussowitsch PetscCall(PetscFree(ifields)); 30145f824522SMatthew G. Knepley 30159566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_patches_view", patch->classname)); 30169566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool(option, "Print out information during patch construction", "PCPATCH", patch->viewPatches, &patch->viewPatches, &flg)); 30179566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_cells_view", patch->classname)); 30189566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, ((PetscObject)pc)->options, prefix, option, &patch->viewerCells, &patch->formatCells, &patch->viewCells)); 30199566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_interior_facets_view", patch->classname)); 30209566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, ((PetscObject)pc)->options, prefix, option, &patch->viewerIntFacets, &patch->formatIntFacets, &patch->viewIntFacets)); 30219566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_exterior_facets_view", patch->classname)); 30229566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, ((PetscObject)pc)->options, prefix, option, &patch->viewerExtFacets, &patch->formatExtFacets, &patch->viewExtFacets)); 30239566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_points_view", patch->classname)); 30249566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, ((PetscObject)pc)->options, prefix, option, &patch->viewerPoints, &patch->formatPoints, &patch->viewPoints)); 30259566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_section_view", patch->classname)); 30269566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, ((PetscObject)pc)->options, prefix, option, &patch->viewerSection, &patch->formatSection, &patch->viewSection)); 30279566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_mat_view", patch->classname)); 30289566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, ((PetscObject)pc)->options, prefix, option, &patch->viewerMatrix, &patch->formatMatrix, &patch->viewMatrix)); 3029d0609cedSBarry Smith PetscOptionsHeadEnd(); 30305f824522SMatthew G. Knepley patch->optionsSet = PETSC_TRUE; 30314bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 30324bbf5ea8SMatthew G. Knepley } 30334bbf5ea8SMatthew G. Knepley 30349371c9d4SSatish Balay static PetscErrorCode PCSetUpOnBlocks_PATCH(PC pc) { 30354bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 30364bbf5ea8SMatthew G. Knepley KSPConvergedReason reason; 30374bbf5ea8SMatthew G. Knepley PetscInt i; 30384bbf5ea8SMatthew G. Knepley 30394bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 3040a1eac568SLawrence Mitchell if (!patch->save_operators) { 3041a1eac568SLawrence Mitchell /* Can't do this here because the sub KSPs don't have an operator attached yet. */ 3042a1eac568SLawrence Mitchell PetscFunctionReturn(0); 3043a1eac568SLawrence Mitchell } 3044c73d2cf6SLawrence Mitchell if (patch->denseinverse) { 3045c73d2cf6SLawrence Mitchell /* No solvers */ 3046c73d2cf6SLawrence Mitchell PetscFunctionReturn(0); 3047c73d2cf6SLawrence Mitchell } 30484bbf5ea8SMatthew G. Knepley for (i = 0; i < patch->npatch; ++i) { 304948a46eb9SPierre Jolivet if (!((KSP)patch->solver[i])->setfromoptionscalled) PetscCall(KSPSetFromOptions((KSP)patch->solver[i])); 30509566063dSJacob Faibussowitsch PetscCall(KSPSetUp((KSP)patch->solver[i])); 30519566063dSJacob Faibussowitsch PetscCall(KSPGetConvergedReason((KSP)patch->solver[i], &reason)); 3052c0decd05SBarry Smith if (reason == KSP_DIVERGED_PC_FAILED) pc->failedreason = PC_SUBPC_ERROR; 30534bbf5ea8SMatthew G. Knepley } 30544bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 30554bbf5ea8SMatthew G. Knepley } 30564bbf5ea8SMatthew G. Knepley 30579371c9d4SSatish Balay static PetscErrorCode PCView_PATCH(PC pc, PetscViewer viewer) { 30584bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 30594bbf5ea8SMatthew G. Knepley PetscViewer sviewer; 30604bbf5ea8SMatthew G. Knepley PetscBool isascii; 30614bbf5ea8SMatthew G. Knepley PetscMPIInt rank; 30624bbf5ea8SMatthew G. Knepley 30634bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 30644bbf5ea8SMatthew G. Knepley /* TODO Redo tabbing with set tbas in new style */ 30659566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 30664bbf5ea8SMatthew G. Knepley if (!isascii) PetscFunctionReturn(0); 30679566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc), &rank)); 30689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 306963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Subspace Correction preconditioner with %" PetscInt_FMT " patches\n", patch->npatch)); 307061c4b389SFlorian Wechsung if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) { 30719566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Schwarz type: multiplicative\n")); 3072e047a90bSFlorian Wechsung } else { 30739566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Schwarz type: additive\n")); 3074c2e6f3c0SFlorian Wechsung } 30759566063dSJacob Faibussowitsch if (patch->partition_of_unity) PetscCall(PetscViewerASCIIPrintf(viewer, "Weighting by partition of unity\n")); 30769566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Not weighting by partition of unity\n")); 30779566063dSJacob Faibussowitsch if (patch->symmetrise_sweep) PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetrising sweep (start->end, then end->start)\n")); 30789566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Not symmetrising sweep\n")); 30799566063dSJacob Faibussowitsch if (!patch->precomputeElementTensors) PetscCall(PetscViewerASCIIPrintf(viewer, "Not precomputing element tensors (overlapping cells rebuilt in every patch assembly)\n")); 30809566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Precomputing element tensors (each cell assembled only once)\n")); 30819566063dSJacob Faibussowitsch if (!patch->save_operators) PetscCall(PetscViewerASCIIPrintf(viewer, "Not saving patch operators (rebuilt every PCApply)\n")); 30829566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Saving patch operators (rebuilt every PCSetUp)\n")); 30839566063dSJacob Faibussowitsch if (patch->patchconstructop == PCPatchConstruct_Star) PetscCall(PetscViewerASCIIPrintf(viewer, "Patch construction operator: star\n")); 30849566063dSJacob Faibussowitsch else if (patch->patchconstructop == PCPatchConstruct_Vanka) PetscCall(PetscViewerASCIIPrintf(viewer, "Patch construction operator: Vanka\n")); 30859566063dSJacob Faibussowitsch else if (patch->patchconstructop == PCPatchConstruct_User) PetscCall(PetscViewerASCIIPrintf(viewer, "Patch construction operator: user-specified\n")); 30869566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Patch construction operator: unknown\n")); 30875d30859aSPatrick Farrell 3088c73d2cf6SLawrence Mitchell if (patch->denseinverse) { 30899566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Explicitly forming dense inverse and applying patch solver via MatMult.\n")); 3090c73d2cf6SLawrence Mitchell } else { 30915d30859aSPatrick Farrell if (patch->isNonlinear) { 30929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "SNES on patches (all same):\n")); 30935d30859aSPatrick Farrell } else { 30949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "KSP on patches (all same):\n")); 30955d30859aSPatrick Farrell } 3096dadc69c5SMatthew G. Knepley if (patch->solver) { 30979566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 3098dd400576SPatrick Sanan if (rank == 0) { 30999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(sviewer)); 31009566063dSJacob Faibussowitsch PetscCall(PetscObjectView(patch->solver[0], sviewer)); 31019566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(sviewer)); 31024bbf5ea8SMatthew G. Knepley } 31039566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 31044bbf5ea8SMatthew G. Knepley } else { 31059566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 31069566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Solver not yet set.\n")); 31079566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 31084bbf5ea8SMatthew G. Knepley } 3109c73d2cf6SLawrence Mitchell } 31109566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 31114bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 31124bbf5ea8SMatthew G. Knepley } 31134bbf5ea8SMatthew G. Knepley 3114e5893cccSMatthew G. Knepley /*MC 3115*f1580f4eSBarry Smith PCPATCH - A `PC` object that encapsulates flexible definition of blocks for overlapping and non-overlapping 311698ed095eSMatthew G. Knepley small block additive preconditioners. Block definition is based on topology from 3117*f1580f4eSBarry Smith a `DM` and equation numbering from a `PetscSection`. 3118e5893cccSMatthew G. Knepley 3119e5893cccSMatthew G. Knepley Options Database Keys: 3120e5893cccSMatthew G. Knepley + -pc_patch_cells_view - Views the process local cell numbers for each patch 3121e5893cccSMatthew G. Knepley . -pc_patch_points_view - Views the process local mesh point numbers for each patch 3122e5893cccSMatthew G. Knepley . -pc_patch_g2l_view - Views the map between global dofs and patch local dofs for each patch 3123e5893cccSMatthew G. Knepley . -pc_patch_patches_view - Views the global dofs associated with each patch and its boundary 3124e5893cccSMatthew G. Knepley - -pc_patch_sub_mat_view - Views the matrix associated with each patch 3125e5893cccSMatthew G. Knepley 3126e5893cccSMatthew G. Knepley Level: intermediate 3127e5893cccSMatthew G. Knepley 3128*f1580f4eSBarry Smith .seealso: `PCType`, `PCCreate()`, `PCSetType()`, `PCASM`, `PCJACOBI`, `PCPBJACOBI`, `PCVPBJACOBI`, `SNESPATCH` 3129e5893cccSMatthew G. Knepley M*/ 31309371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PCCreate_Patch(PC pc) { 31314bbf5ea8SMatthew G. Knepley PC_PATCH *patch; 31324bbf5ea8SMatthew G. Knepley 31334bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 31349566063dSJacob Faibussowitsch PetscCall(PetscNewLog(pc, &patch)); 31354bbf5ea8SMatthew G. Knepley 313648a46eb9SPierre Jolivet if (patch->subspaces_to_exclude) PetscCall(PetscHSetIDestroy(&patch->subspaces_to_exclude)); 31379566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&patch->subspaces_to_exclude)); 3138e4c66b91SPatrick Farrell 313910534d48SPatrick Farrell patch->classname = "pc"; 3140debbdec3SPatrick Farrell patch->isNonlinear = PETSC_FALSE; 314110534d48SPatrick Farrell 31424bbf5ea8SMatthew G. Knepley /* Set some defaults */ 31435f824522SMatthew G. Knepley patch->combined = PETSC_FALSE; 31444bbf5ea8SMatthew G. Knepley patch->save_operators = PETSC_TRUE; 314561c4b389SFlorian Wechsung patch->local_composition_type = PC_COMPOSITE_ADDITIVE; 3146fa84ea4cSLawrence Mitchell patch->precomputeElementTensors = PETSC_FALSE; 31474bbf5ea8SMatthew G. Knepley patch->partition_of_unity = PETSC_FALSE; 31484bbf5ea8SMatthew G. Knepley patch->codim = -1; 31494bbf5ea8SMatthew G. Knepley patch->dim = -1; 31504bbf5ea8SMatthew G. Knepley patch->vankadim = -1; 31515f824522SMatthew G. Knepley patch->ignoredim = -1; 3152b525f888SPatrick Farrell patch->pardecomp_overlap = 0; 31534bbf5ea8SMatthew G. Knepley patch->patchconstructop = PCPatchConstruct_Star; 31544bbf5ea8SMatthew G. Knepley patch->symmetrise_sweep = PETSC_FALSE; 31555f824522SMatthew G. Knepley patch->npatch = 0; 31564bbf5ea8SMatthew G. Knepley patch->userIS = NULL; 31575f824522SMatthew G. Knepley patch->optionsSet = PETSC_FALSE; 31584bbf5ea8SMatthew G. Knepley patch->iterationSet = NULL; 31594bbf5ea8SMatthew G. Knepley patch->user_patches = PETSC_FALSE; 31609566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATDENSE, (char **)&patch->sub_mat_type)); 31615f824522SMatthew G. Knepley patch->viewPatches = PETSC_FALSE; 31625f824522SMatthew G. Knepley patch->viewCells = PETSC_FALSE; 31635f824522SMatthew G. Knepley patch->viewPoints = PETSC_FALSE; 31645f824522SMatthew G. Knepley patch->viewSection = PETSC_FALSE; 31655f824522SMatthew G. Knepley patch->viewMatrix = PETSC_FALSE; 31669d4fc724SLawrence Mitchell patch->densesolve = NULL; 3167dadc69c5SMatthew G. Knepley patch->setupsolver = PCSetUp_PATCH_Linear; 3168dadc69c5SMatthew G. Knepley patch->applysolver = PCApply_PATCH_Linear; 3169dadc69c5SMatthew G. Knepley patch->resetsolver = PCReset_PATCH_Linear; 3170dadc69c5SMatthew G. Knepley patch->destroysolver = PCDestroy_PATCH_Linear; 31716c9c532dSPatrick Farrell patch->updatemultiplicative = PCUpdateMultiplicative_PATCH_Linear; 317247aca4a6SPatrick Farrell patch->dofMappingWithoutToWithArtificial = NULL; 317347aca4a6SPatrick Farrell patch->dofMappingWithoutToWithAll = NULL; 31744bbf5ea8SMatthew G. Knepley 31754bbf5ea8SMatthew G. Knepley pc->data = (void *)patch; 31764bbf5ea8SMatthew G. Knepley pc->ops->apply = PCApply_PATCH; 31770a545947SLisandro Dalcin pc->ops->applytranspose = NULL; /* PCApplyTranspose_PATCH; */ 31784bbf5ea8SMatthew G. Knepley pc->ops->setup = PCSetUp_PATCH; 31794bbf5ea8SMatthew G. Knepley pc->ops->reset = PCReset_PATCH; 31804bbf5ea8SMatthew G. Knepley pc->ops->destroy = PCDestroy_PATCH; 31814bbf5ea8SMatthew G. Knepley pc->ops->setfromoptions = PCSetFromOptions_PATCH; 31824bbf5ea8SMatthew G. Knepley pc->ops->setuponblocks = PCSetUpOnBlocks_PATCH; 31834bbf5ea8SMatthew G. Knepley pc->ops->view = PCView_PATCH; 31840a545947SLisandro Dalcin pc->ops->applyrichardson = NULL; 31854bbf5ea8SMatthew G. Knepley 31864bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 31874bbf5ea8SMatthew G. Knepley } 3188