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. 1974bbf5ea8SMatthew G. Knepley * allRoots: number of owned global dofs; 1984bbf5ea8SMatthew G. Knepley * 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. */ 218*48a46eb9SPierre 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)); 2364bbf5ea8SMatthew G. Knepley /* OK, use it to communicate the root offset on the remote 2374bbf5ea8SMatthew G. Knepley * processes for each subspace. */ 2389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n, &offsets)); 2399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n * numRanks, &remoteOffsets)); 2404bbf5ea8SMatthew G. Knepley 2414bbf5ea8SMatthew G. Knepley offsets[0] = 0; 2424bbf5ea8SMatthew G. Knepley for (i = 1; i < n; ++i) { 2434bbf5ea8SMatthew G. Knepley PetscInt nroots; 2444bbf5ea8SMatthew G. Knepley 2459566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf[i - 1], &nroots, NULL, NULL, NULL)); 2464bbf5ea8SMatthew G. Knepley offsets[i] = offsets[i - 1] + nroots * bs[i - 1]; 2474bbf5ea8SMatthew G. Knepley } 2484bbf5ea8SMatthew G. Knepley /* Offsets are the offsets on the current process of the 2494bbf5ea8SMatthew G. Knepley * global dof numbering for the subspaces. */ 2509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(n, MPIU_INT, &contig)); 2519566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&contig)); 2524bbf5ea8SMatthew G. Knepley 2539566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(rankSF, contig, offsets, remoteOffsets, MPI_REPLACE)); 2549566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(rankSF, contig, offsets, remoteOffsets, MPI_REPLACE)); 2559566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&contig)); 2569566063dSJacob Faibussowitsch PetscCall(PetscFree(offsets)); 2579566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&rankSF)); 2584bbf5ea8SMatthew G. Knepley /* Now remoteOffsets contains the offsets on the remote 2594bbf5ea8SMatthew G. Knepley * processes who communicate with me. So now we can 2604bbf5ea8SMatthew G. Knepley * concatenate the list of SFs into a single one. */ 2614bbf5ea8SMatthew G. Knepley index = 0; 2624bbf5ea8SMatthew G. Knepley for (i = 0; i < n; ++i) { 2634bbf5ea8SMatthew G. Knepley const PetscSFNode *remote = NULL; 2644bbf5ea8SMatthew G. Knepley const PetscInt *local = NULL; 2654bbf5ea8SMatthew G. Knepley PetscInt nroots, nleaves, j; 2664bbf5ea8SMatthew G. Knepley 2679566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf[i], &nroots, &nleaves, &local, &remote)); 2684bbf5ea8SMatthew G. Knepley for (j = 0; j < nleaves; ++j) { 2694bbf5ea8SMatthew G. Knepley PetscInt rank = remote[j].rank; 2704bbf5ea8SMatthew G. Knepley PetscInt idx, rootOffset, k; 2714bbf5ea8SMatthew G. Knepley 2729566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(rankToIndex, rank, &idx)); 27308401ef6SPierre Jolivet PetscCheck(idx != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Didn't find rank, huh?"); 2744bbf5ea8SMatthew G. Knepley /* Offset on given rank for ith subspace */ 2754bbf5ea8SMatthew G. Knepley rootOffset = remoteOffsets[n * idx + i]; 2764bbf5ea8SMatthew G. Knepley for (k = 0; k < bs[i]; ++k) { 27773ec7555SLawrence Mitchell ilocal[index] = (local ? local[j] : j) * bs[i] + k + leafOffset; 2784bbf5ea8SMatthew G. Knepley iremote[index].rank = remote[j].rank; 2794bbf5ea8SMatthew G. Knepley iremote[index].index = remote[j].index * bs[i] + k + rootOffset; 2804bbf5ea8SMatthew G. Knepley ++index; 2814bbf5ea8SMatthew G. Knepley } 2824bbf5ea8SMatthew G. Knepley } 2834bbf5ea8SMatthew G. Knepley leafOffset += nleaves * bs[i]; 2844bbf5ea8SMatthew G. Knepley } 2859566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&rankToIndex)); 2869566063dSJacob Faibussowitsch PetscCall(PetscFree(remoteOffsets)); 2879566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)pc), &patch->sectionSF)); 2889566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(patch->sectionSF, allRoots, allLeaves, ilocal, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER)); 2894bbf5ea8SMatthew G. Knepley } 2904bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 2914bbf5ea8SMatthew G. Knepley } 2924bbf5ea8SMatthew G. Knepley 2939371c9d4SSatish Balay PetscErrorCode PCPatchSetDenseInverse(PC pc, PetscBool flg) { 294c73d2cf6SLawrence Mitchell PC_PATCH *patch = (PC_PATCH *)pc->data; 295c73d2cf6SLawrence Mitchell PetscFunctionBegin; 296c73d2cf6SLawrence Mitchell patch->denseinverse = flg; 297c73d2cf6SLawrence Mitchell PetscFunctionReturn(0); 298c73d2cf6SLawrence Mitchell } 299c73d2cf6SLawrence Mitchell 3009371c9d4SSatish Balay PetscErrorCode PCPatchGetDenseInverse(PC pc, PetscBool *flg) { 301c73d2cf6SLawrence Mitchell PC_PATCH *patch = (PC_PATCH *)pc->data; 302c73d2cf6SLawrence Mitchell PetscFunctionBegin; 303c73d2cf6SLawrence Mitchell *flg = patch->denseinverse; 304c73d2cf6SLawrence Mitchell PetscFunctionReturn(0); 305c73d2cf6SLawrence Mitchell } 306c73d2cf6SLawrence Mitchell 3074bbf5ea8SMatthew G. Knepley /* TODO: Docs */ 3089371c9d4SSatish Balay PetscErrorCode PCPatchSetIgnoreDim(PC pc, PetscInt dim) { 3095f824522SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 3105f824522SMatthew G. Knepley PetscFunctionBegin; 3115f824522SMatthew G. Knepley patch->ignoredim = dim; 3125f824522SMatthew G. Knepley PetscFunctionReturn(0); 3135f824522SMatthew G. Knepley } 3145f824522SMatthew G. Knepley 3155f824522SMatthew G. Knepley /* TODO: Docs */ 3169371c9d4SSatish Balay PetscErrorCode PCPatchGetIgnoreDim(PC pc, PetscInt *dim) { 3175f824522SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 3185f824522SMatthew G. Knepley PetscFunctionBegin; 3195f824522SMatthew G. Knepley *dim = patch->ignoredim; 3205f824522SMatthew G. Knepley PetscFunctionReturn(0); 3215f824522SMatthew G. Knepley } 3225f824522SMatthew G. Knepley 3235f824522SMatthew G. Knepley /* TODO: Docs */ 3249371c9d4SSatish Balay PetscErrorCode PCPatchSetSaveOperators(PC pc, PetscBool flg) { 3254bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 3264bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 3274bbf5ea8SMatthew G. Knepley patch->save_operators = flg; 3284bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 3294bbf5ea8SMatthew G. Knepley } 3304bbf5ea8SMatthew G. Knepley 3314bbf5ea8SMatthew G. Knepley /* TODO: Docs */ 3329371c9d4SSatish Balay PetscErrorCode PCPatchGetSaveOperators(PC pc, PetscBool *flg) { 3334bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 3344bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 3354bbf5ea8SMatthew G. Knepley *flg = patch->save_operators; 3364bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 3374bbf5ea8SMatthew G. Knepley } 3384bbf5ea8SMatthew G. Knepley 3394bbf5ea8SMatthew G. Knepley /* TODO: Docs */ 3409371c9d4SSatish Balay PetscErrorCode PCPatchSetPrecomputeElementTensors(PC pc, PetscBool flg) { 341fa84ea4cSLawrence Mitchell PC_PATCH *patch = (PC_PATCH *)pc->data; 342fa84ea4cSLawrence Mitchell PetscFunctionBegin; 343fa84ea4cSLawrence Mitchell patch->precomputeElementTensors = flg; 344fa84ea4cSLawrence Mitchell PetscFunctionReturn(0); 345fa84ea4cSLawrence Mitchell } 346fa84ea4cSLawrence Mitchell 347fa84ea4cSLawrence Mitchell /* TODO: Docs */ 3489371c9d4SSatish Balay PetscErrorCode PCPatchGetPrecomputeElementTensors(PC pc, PetscBool *flg) { 349fa84ea4cSLawrence Mitchell PC_PATCH *patch = (PC_PATCH *)pc->data; 350fa84ea4cSLawrence Mitchell PetscFunctionBegin; 351fa84ea4cSLawrence Mitchell *flg = patch->precomputeElementTensors; 352fa84ea4cSLawrence Mitchell PetscFunctionReturn(0); 353fa84ea4cSLawrence Mitchell } 354fa84ea4cSLawrence Mitchell 355fa84ea4cSLawrence Mitchell /* TODO: Docs */ 3569371c9d4SSatish Balay PetscErrorCode PCPatchSetPartitionOfUnity(PC pc, PetscBool flg) { 3574bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 3584bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 3594bbf5ea8SMatthew G. Knepley patch->partition_of_unity = flg; 3604bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 3614bbf5ea8SMatthew G. Knepley } 3624bbf5ea8SMatthew G. Knepley 3634bbf5ea8SMatthew G. Knepley /* TODO: Docs */ 3649371c9d4SSatish Balay PetscErrorCode PCPatchGetPartitionOfUnity(PC pc, PetscBool *flg) { 3654bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 3664bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 3674bbf5ea8SMatthew G. Knepley *flg = patch->partition_of_unity; 3684bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 3694bbf5ea8SMatthew G. Knepley } 3704bbf5ea8SMatthew G. Knepley 3714bbf5ea8SMatthew G. Knepley /* TODO: Docs */ 3729371c9d4SSatish Balay PetscErrorCode PCPatchSetLocalComposition(PC pc, PCCompositeType type) { 373c2e6f3c0SFlorian Wechsung PC_PATCH *patch = (PC_PATCH *)pc->data; 374c2e6f3c0SFlorian Wechsung PetscFunctionBegin; 3752472a847SBarry 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"); 37661c4b389SFlorian Wechsung patch->local_composition_type = type; 377c2e6f3c0SFlorian Wechsung PetscFunctionReturn(0); 378c2e6f3c0SFlorian Wechsung } 379c2e6f3c0SFlorian Wechsung 380c2e6f3c0SFlorian Wechsung /* TODO: Docs */ 3819371c9d4SSatish Balay PetscErrorCode PCPatchGetLocalComposition(PC pc, PCCompositeType *type) { 382c2e6f3c0SFlorian Wechsung PC_PATCH *patch = (PC_PATCH *)pc->data; 383c2e6f3c0SFlorian Wechsung PetscFunctionBegin; 38461c4b389SFlorian Wechsung *type = patch->local_composition_type; 385c2e6f3c0SFlorian Wechsung PetscFunctionReturn(0); 386c2e6f3c0SFlorian Wechsung } 387c2e6f3c0SFlorian Wechsung 388c2e6f3c0SFlorian Wechsung /* TODO: Docs */ 3899371c9d4SSatish Balay PetscErrorCode PCPatchSetSubMatType(PC pc, MatType sub_mat_type) { 3904bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 3914bbf5ea8SMatthew G. Knepley 3924bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 3939566063dSJacob Faibussowitsch if (patch->sub_mat_type) PetscCall(PetscFree(patch->sub_mat_type)); 3949566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(sub_mat_type, (char **)&patch->sub_mat_type)); 3954bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 3964bbf5ea8SMatthew G. Knepley } 3974bbf5ea8SMatthew G. Knepley 3984bbf5ea8SMatthew G. Knepley /* TODO: Docs */ 3999371c9d4SSatish Balay PetscErrorCode PCPatchGetSubMatType(PC pc, MatType *sub_mat_type) { 4004bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 4014bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 4024bbf5ea8SMatthew G. Knepley *sub_mat_type = patch->sub_mat_type; 4034bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 4044bbf5ea8SMatthew G. Knepley } 4054bbf5ea8SMatthew G. Knepley 4064bbf5ea8SMatthew G. Knepley /* TODO: Docs */ 4079371c9d4SSatish Balay PetscErrorCode PCPatchSetCellNumbering(PC pc, PetscSection cellNumbering) { 4084bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 4094bbf5ea8SMatthew G. Knepley 4104bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 4114bbf5ea8SMatthew G. Knepley patch->cellNumbering = cellNumbering; 4129566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)cellNumbering)); 4134bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 4144bbf5ea8SMatthew G. Knepley } 4154bbf5ea8SMatthew G. Knepley 4164bbf5ea8SMatthew G. Knepley /* TODO: Docs */ 4179371c9d4SSatish Balay PetscErrorCode PCPatchGetCellNumbering(PC pc, PetscSection *cellNumbering) { 4184bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 4194bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 4204bbf5ea8SMatthew G. Knepley *cellNumbering = patch->cellNumbering; 4214bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 4224bbf5ea8SMatthew G. Knepley } 4234bbf5ea8SMatthew G. Knepley 4244bbf5ea8SMatthew G. Knepley /* TODO: Docs */ 4259371c9d4SSatish Balay PetscErrorCode PCPatchSetConstructType(PC pc, PCPatchConstructType ctype, PetscErrorCode (*func)(PC, PetscInt *, IS **, IS *, void *), void *ctx) { 4264bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 4274bbf5ea8SMatthew G. Knepley 4284bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 4294bbf5ea8SMatthew G. Knepley patch->ctype = ctype; 4304bbf5ea8SMatthew G. Knepley switch (ctype) { 4314bbf5ea8SMatthew G. Knepley case PC_PATCH_STAR: 43240c17a03SPatrick Farrell patch->user_patches = PETSC_FALSE; 4334bbf5ea8SMatthew G. Knepley patch->patchconstructop = PCPatchConstruct_Star; 4344bbf5ea8SMatthew G. Knepley break; 4354bbf5ea8SMatthew G. Knepley case PC_PATCH_VANKA: 43640c17a03SPatrick Farrell patch->user_patches = PETSC_FALSE; 4374bbf5ea8SMatthew G. Knepley patch->patchconstructop = PCPatchConstruct_Vanka; 4384bbf5ea8SMatthew G. Knepley break; 439e5b9877fSPatrick Farrell case PC_PATCH_PARDECOMP: 4400a390943SPatrick Farrell patch->user_patches = PETSC_FALSE; 441e5b9877fSPatrick Farrell patch->patchconstructop = PCPatchConstruct_Pardecomp; 4420a390943SPatrick Farrell break; 4434bbf5ea8SMatthew G. Knepley case PC_PATCH_USER: 4444bbf5ea8SMatthew G. Knepley case PC_PATCH_PYTHON: 4454bbf5ea8SMatthew G. Knepley patch->user_patches = PETSC_TRUE; 4464bbf5ea8SMatthew G. Knepley patch->patchconstructop = PCPatchConstruct_User; 447bdd9e0cdSPatrick Farrell if (func) { 4484bbf5ea8SMatthew G. Knepley patch->userpatchconstructionop = func; 4494bbf5ea8SMatthew G. Knepley patch->userpatchconstructctx = ctx; 450bdd9e0cdSPatrick Farrell } 4514bbf5ea8SMatthew G. Knepley break; 4529371c9d4SSatish Balay default: SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "Unknown patch construction type %" PetscInt_FMT, (PetscInt)patch->ctype); 4534bbf5ea8SMatthew G. Knepley } 4544bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 4554bbf5ea8SMatthew G. Knepley } 4564bbf5ea8SMatthew G. Knepley 4574bbf5ea8SMatthew G. Knepley /* TODO: Docs */ 4589371c9d4SSatish Balay PetscErrorCode PCPatchGetConstructType(PC pc, PCPatchConstructType *ctype, PetscErrorCode (**func)(PC, PetscInt *, IS **, IS *, void *), void **ctx) { 4594bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 4604bbf5ea8SMatthew G. Knepley 4614bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 4624bbf5ea8SMatthew G. Knepley *ctype = patch->ctype; 4634bbf5ea8SMatthew G. Knepley switch (patch->ctype) { 4644bbf5ea8SMatthew G. Knepley case PC_PATCH_STAR: 4654bbf5ea8SMatthew G. Knepley case PC_PATCH_VANKA: 4669371c9d4SSatish Balay case PC_PATCH_PARDECOMP: break; 4674bbf5ea8SMatthew G. Knepley case PC_PATCH_USER: 4684bbf5ea8SMatthew G. Knepley case PC_PATCH_PYTHON: 4694bbf5ea8SMatthew G. Knepley *func = patch->userpatchconstructionop; 4704bbf5ea8SMatthew G. Knepley *ctx = patch->userpatchconstructctx; 4714bbf5ea8SMatthew G. Knepley break; 4729371c9d4SSatish Balay default: SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_USER, "Unknown patch construction type %" PetscInt_FMT, (PetscInt)patch->ctype); 4734bbf5ea8SMatthew G. Knepley } 4744bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 4754bbf5ea8SMatthew G. Knepley } 4764bbf5ea8SMatthew G. Knepley 4774bbf5ea8SMatthew G. Knepley /* TODO: Docs */ 4789371c9d4SSatish 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) { 4794bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 480b6bb21d1SLawrence Mitchell DM dm, plex; 4814bbf5ea8SMatthew G. Knepley PetscSF *sfs; 4825f824522SMatthew G. Knepley PetscInt cStart, cEnd, i, j; 4834bbf5ea8SMatthew G. Knepley 4844bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 4859566063dSJacob Faibussowitsch PetscCall(PCGetDM(pc, &dm)); 4869566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 487b6bb21d1SLawrence Mitchell dm = plex; 4889566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 4899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nsubspaces, &sfs)); 4909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nsubspaces, &patch->dofSection)); 4919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nsubspaces, &patch->bs)); 4929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nsubspaces, &patch->nodesPerCell)); 4939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nsubspaces, &patch->cellNodeMap)); 4949566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nsubspaces + 1, &patch->subspaceOffsets)); 4954bbf5ea8SMatthew G. Knepley 4964bbf5ea8SMatthew G. Knepley patch->nsubspaces = nsubspaces; 4974bbf5ea8SMatthew G. Knepley patch->totalDofsPerCell = 0; 4984bbf5ea8SMatthew G. Knepley for (i = 0; i < nsubspaces; ++i) { 4999566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dms[i], &patch->dofSection[i])); 5009566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)patch->dofSection[i])); 5019566063dSJacob Faibussowitsch PetscCall(DMGetSectionSF(dms[i], &sfs[i])); 5024bbf5ea8SMatthew G. Knepley patch->bs[i] = bs[i]; 5034bbf5ea8SMatthew G. Knepley patch->nodesPerCell[i] = nodesPerCell[i]; 5044bbf5ea8SMatthew G. Knepley patch->totalDofsPerCell += nodesPerCell[i] * bs[i]; 5059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((cEnd - cStart) * nodesPerCell[i], &patch->cellNodeMap[i])); 50680e8a965SFlorian Wechsung for (j = 0; j < (cEnd - cStart) * nodesPerCell[i]; ++j) patch->cellNodeMap[i][j] = cellNodeMap[i][j]; 5074bbf5ea8SMatthew G. Knepley patch->subspaceOffsets[i] = subspaceOffsets[i]; 5084bbf5ea8SMatthew G. Knepley } 5099566063dSJacob Faibussowitsch PetscCall(PCPatchCreateDefaultSF_Private(pc, nsubspaces, sfs, patch->bs)); 5109566063dSJacob Faibussowitsch PetscCall(PetscFree(sfs)); 5114bbf5ea8SMatthew G. Knepley 5124bbf5ea8SMatthew G. Knepley patch->subspaceOffsets[nsubspaces] = subspaceOffsets[nsubspaces]; 5139566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numGhostBcs, ghostBcNodes, PETSC_COPY_VALUES, &patch->ghostBcNodes)); 5149566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numGlobalBcs, globalBcNodes, PETSC_COPY_VALUES, &patch->globalBcNodes)); 5159566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dm)); 5164bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 5174bbf5ea8SMatthew G. Knepley } 5184bbf5ea8SMatthew G. Knepley 5194bbf5ea8SMatthew G. Knepley /* TODO: Docs */ 5209371c9d4SSatish Balay PetscErrorCode PCPatchSetDiscretisationInfoCombined(PC pc, DM dm, PetscInt *nodesPerCell, const PetscInt **cellNodeMap, PetscInt numGhostBcs, const PetscInt *ghostBcNodes, PetscInt numGlobalBcs, const PetscInt *globalBcNodes) { 5215f824522SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 5225f824522SMatthew G. Knepley PetscInt cStart, cEnd, i, j; 5235f824522SMatthew G. Knepley 5245f824522SMatthew G. Knepley PetscFunctionBegin; 5255f824522SMatthew G. Knepley patch->combined = PETSC_TRUE; 5269566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 5279566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &patch->nsubspaces)); 5289566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(patch->nsubspaces, &patch->dofSection)); 5299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(patch->nsubspaces, &patch->bs)); 5309566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(patch->nsubspaces, &patch->nodesPerCell)); 5319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(patch->nsubspaces, &patch->cellNodeMap)); 5329566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(patch->nsubspaces + 1, &patch->subspaceOffsets)); 5339566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, &patch->dofSection[0])); 5349566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)patch->dofSection[0])); 5359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(patch->dofSection[0], &patch->subspaceOffsets[patch->nsubspaces])); 5365f824522SMatthew G. Knepley patch->totalDofsPerCell = 0; 5375f824522SMatthew G. Knepley for (i = 0; i < patch->nsubspaces; ++i) { 5385f824522SMatthew G. Knepley patch->bs[i] = 1; 5395f824522SMatthew G. Knepley patch->nodesPerCell[i] = nodesPerCell[i]; 5405f824522SMatthew G. Knepley patch->totalDofsPerCell += nodesPerCell[i]; 5419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((cEnd - cStart) * nodesPerCell[i], &patch->cellNodeMap[i])); 5425f824522SMatthew G. Knepley for (j = 0; j < (cEnd - cStart) * nodesPerCell[i]; ++j) patch->cellNodeMap[i][j] = cellNodeMap[i][j]; 5435f824522SMatthew G. Knepley } 5449566063dSJacob Faibussowitsch PetscCall(DMGetSectionSF(dm, &patch->sectionSF)); 5459566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)patch->sectionSF)); 5469566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numGhostBcs, ghostBcNodes, PETSC_COPY_VALUES, &patch->ghostBcNodes)); 5479566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numGlobalBcs, globalBcNodes, PETSC_COPY_VALUES, &patch->globalBcNodes)); 5485f824522SMatthew G. Knepley PetscFunctionReturn(0); 5495f824522SMatthew G. Knepley } 5505f824522SMatthew G. Knepley 5515f824522SMatthew G. Knepley /*@C 5525f824522SMatthew G. Knepley 55392d50984SMatthew G. Knepley PCPatchSetComputeFunction - Set the callback used to compute patch residuals 55492d50984SMatthew G. Knepley 55599b7e5c6SPatrick Farrell Logically collective on PC 55699b7e5c6SPatrick Farrell 55792d50984SMatthew G. Knepley Input Parameters: 55892d50984SMatthew G. Knepley + pc - The PC 55992d50984SMatthew G. Knepley . func - The callback 56092d50984SMatthew G. Knepley - ctx - The user context 56192d50984SMatthew G. Knepley 5627a50e09dSPatrick Farrell Calling sequence of func: 5637a50e09dSPatrick Farrell $ func (PC pc,PetscInt point,Vec x,Vec f,IS cellIS,PetscInt n,const PetscInt* dofsArray,const PetscInt* dofsArrayWithAll,void* ctx) 5647a50e09dSPatrick Farrell 5657a50e09dSPatrick Farrell + pc - The PC 5667a50e09dSPatrick Farrell . point - The point 5677a50e09dSPatrick Farrell . x - The input solution (not used in linear problems) 5687a50e09dSPatrick Farrell . f - The patch residual vector 5697a50e09dSPatrick Farrell . cellIS - An array of the cell numbers 5707a50e09dSPatrick Farrell . n - The size of dofsArray 5717a50e09dSPatrick Farrell . dofsArray - The dofmap for the dofs to be solved for 5727a50e09dSPatrick Farrell . dofsArrayWithAll - The dofmap for all dofs on the patch 5737a50e09dSPatrick Farrell - ctx - The user context 5747a50e09dSPatrick Farrell 57592d50984SMatthew G. Knepley Level: advanced 57692d50984SMatthew G. Knepley 5777a50e09dSPatrick Farrell Notes: 57826dc5b63SLawrence Mitchell The entries of F (the output residual vector) have been set to zero before the call. 57992d50984SMatthew G. Knepley 580db781477SPatrick Sanan .seealso: `PCPatchSetComputeOperator()`, `PCPatchGetComputeOperator()`, `PCPatchSetDiscretisationInfo()`, `PCPatchSetComputeFunctionInteriorFacets()` 58192d50984SMatthew G. Knepley @*/ 5829371c9d4SSatish Balay PetscErrorCode PCPatchSetComputeFunction(PC pc, PetscErrorCode (*func)(PC, PetscInt, Vec, Vec, IS, PetscInt, const PetscInt *, const PetscInt *, void *), void *ctx) { 58392d50984SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 58492d50984SMatthew G. Knepley 58592d50984SMatthew G. Knepley PetscFunctionBegin; 58692d50984SMatthew G. Knepley patch->usercomputef = func; 58792d50984SMatthew G. Knepley patch->usercomputefctx = ctx; 58892d50984SMatthew G. Knepley PetscFunctionReturn(0); 58992d50984SMatthew G. Knepley } 59092d50984SMatthew G. Knepley 59192d50984SMatthew G. Knepley /*@C 59292d50984SMatthew G. Knepley 59359109abcSLawrence Mitchell PCPatchSetComputeFunctionInteriorFacets - Set the callback used to compute facet integrals for patch residuals 59459109abcSLawrence Mitchell 5957a50e09dSPatrick Farrell Logically collective on PC 5967a50e09dSPatrick Farrell 59759109abcSLawrence Mitchell Input Parameters: 59859109abcSLawrence Mitchell + pc - The PC 59959109abcSLawrence Mitchell . func - The callback 60059109abcSLawrence Mitchell - ctx - The user context 60159109abcSLawrence Mitchell 6027a50e09dSPatrick Farrell Calling sequence of func: 6037a50e09dSPatrick Farrell $ func (PC pc,PetscInt point,Vec x,Vec f,IS facetIS,PetscInt n,const PetscInt* dofsArray,const PetscInt* dofsArrayWithAll,void* ctx) 6047a50e09dSPatrick Farrell 6057a50e09dSPatrick Farrell + pc - The PC 6067a50e09dSPatrick Farrell . point - The point 6077a50e09dSPatrick Farrell . x - The input solution (not used in linear problems) 6087a50e09dSPatrick Farrell . f - The patch residual vector 6097a50e09dSPatrick Farrell . facetIS - An array of the facet numbers 6107a50e09dSPatrick Farrell . n - The size of dofsArray 6117a50e09dSPatrick Farrell . dofsArray - The dofmap for the dofs to be solved for 6127a50e09dSPatrick Farrell . dofsArrayWithAll - The dofmap for all dofs on the patch 6137a50e09dSPatrick Farrell - ctx - The user context 6147a50e09dSPatrick Farrell 61559109abcSLawrence Mitchell Level: advanced 61659109abcSLawrence Mitchell 6177a50e09dSPatrick Farrell Notes: 61826dc5b63SLawrence Mitchell The entries of F (the output residual vector) have been set to zero before the call. 61959109abcSLawrence Mitchell 620db781477SPatrick Sanan .seealso: `PCPatchSetComputeOperator()`, `PCPatchGetComputeOperator()`, `PCPatchSetDiscretisationInfo()`, `PCPatchSetComputeFunction()` 62159109abcSLawrence Mitchell @*/ 6229371c9d4SSatish Balay PetscErrorCode PCPatchSetComputeFunctionInteriorFacets(PC pc, PetscErrorCode (*func)(PC, PetscInt, Vec, Vec, IS, PetscInt, const PetscInt *, const PetscInt *, void *), void *ctx) { 62359109abcSLawrence Mitchell PC_PATCH *patch = (PC_PATCH *)pc->data; 62459109abcSLawrence Mitchell 62559109abcSLawrence Mitchell PetscFunctionBegin; 62659109abcSLawrence Mitchell patch->usercomputefintfacet = func; 62759109abcSLawrence Mitchell patch->usercomputefintfacetctx = ctx; 62859109abcSLawrence Mitchell PetscFunctionReturn(0); 62959109abcSLawrence Mitchell } 63059109abcSLawrence Mitchell 63159109abcSLawrence Mitchell /*@C 63259109abcSLawrence Mitchell 6335f824522SMatthew G. Knepley PCPatchSetComputeOperator - Set the callback used to compute patch matrices 6345f824522SMatthew G. Knepley 6357a50e09dSPatrick Farrell Logically collective on PC 6367a50e09dSPatrick Farrell 6375f824522SMatthew G. Knepley Input Parameters: 6385f824522SMatthew G. Knepley + pc - The PC 6395f824522SMatthew G. Knepley . func - The callback 6405f824522SMatthew G. Knepley - ctx - The user context 6415f824522SMatthew G. Knepley 6427a50e09dSPatrick Farrell Calling sequence of func: 6437a50e09dSPatrick Farrell $ func (PC pc,PetscInt point,Vec x,Mat mat,IS facetIS,PetscInt n,const PetscInt* dofsArray,const PetscInt* dofsArrayWithAll,void* ctx) 6447a50e09dSPatrick Farrell 6457a50e09dSPatrick Farrell + pc - The PC 6467a50e09dSPatrick Farrell . point - The point 6477a50e09dSPatrick Farrell . x - The input solution (not used in linear problems) 6487a50e09dSPatrick Farrell . mat - The patch matrix 6497a50e09dSPatrick Farrell . cellIS - An array of the cell numbers 6507a50e09dSPatrick Farrell . n - The size of dofsArray 6517a50e09dSPatrick Farrell . dofsArray - The dofmap for the dofs to be solved for 6527a50e09dSPatrick Farrell . dofsArrayWithAll - The dofmap for all dofs on the patch 6537a50e09dSPatrick Farrell - ctx - The user context 6547a50e09dSPatrick Farrell 6555f824522SMatthew G. Knepley Level: advanced 6565f824522SMatthew G. Knepley 6577a50e09dSPatrick Farrell Notes: 6587a50e09dSPatrick Farrell The matrix entries have been set to zero before the call. 6595f824522SMatthew G. Knepley 660db781477SPatrick Sanan .seealso: `PCPatchGetComputeOperator()`, `PCPatchSetComputeFunction()`, `PCPatchSetDiscretisationInfo()` 6615f824522SMatthew G. Knepley @*/ 6629371c9d4SSatish Balay PetscErrorCode PCPatchSetComputeOperator(PC pc, PetscErrorCode (*func)(PC, PetscInt, Vec, Mat, IS, PetscInt, const PetscInt *, const PetscInt *, void *), void *ctx) { 6634bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 6644bbf5ea8SMatthew G. Knepley 6654bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 6664bbf5ea8SMatthew G. Knepley patch->usercomputeop = func; 667723f9013SMatthew G. Knepley patch->usercomputeopctx = ctx; 6684bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 6694bbf5ea8SMatthew G. Knepley } 6704bbf5ea8SMatthew G. Knepley 67159109abcSLawrence Mitchell /*@C 67259109abcSLawrence Mitchell 6737a50e09dSPatrick Farrell PCPatchSetComputeOperatorInteriorFacets - Set the callback used to compute facet integrals for patch matrices 67459109abcSLawrence Mitchell 67599b7e5c6SPatrick Farrell Logically collective on PC 67699b7e5c6SPatrick Farrell 67759109abcSLawrence Mitchell Input Parameters: 67859109abcSLawrence Mitchell + pc - The PC 67959109abcSLawrence Mitchell . func - The callback 68059109abcSLawrence Mitchell - ctx - The user context 68159109abcSLawrence Mitchell 6827a50e09dSPatrick Farrell Calling sequence of func: 6837a50e09dSPatrick Farrell $ func (PC pc,PetscInt point,Vec x,Mat mat,IS facetIS,PetscInt n,const PetscInt* dofsArray,const PetscInt* dofsArrayWithAll,void* ctx) 6847a50e09dSPatrick Farrell 6857a50e09dSPatrick Farrell + pc - The PC 6867a50e09dSPatrick Farrell . point - The point 6877a50e09dSPatrick Farrell . x - The input solution (not used in linear problems) 6887a50e09dSPatrick Farrell . mat - The patch matrix 6897a50e09dSPatrick Farrell . facetIS - An array of the facet numbers 6907a50e09dSPatrick Farrell . n - The size of dofsArray 6917a50e09dSPatrick Farrell . dofsArray - The dofmap for the dofs to be solved for 6927a50e09dSPatrick Farrell . dofsArrayWithAll - The dofmap for all dofs on the patch 6937a50e09dSPatrick Farrell - ctx - The user context 6947a50e09dSPatrick Farrell 69559109abcSLawrence Mitchell Level: advanced 69659109abcSLawrence Mitchell 6977a50e09dSPatrick Farrell Notes: 6987a50e09dSPatrick Farrell The matrix entries have been set to zero before the call. 69959109abcSLawrence Mitchell 700db781477SPatrick Sanan .seealso: `PCPatchGetComputeOperator()`, `PCPatchSetComputeFunction()`, `PCPatchSetDiscretisationInfo()` 70159109abcSLawrence Mitchell @*/ 7029371c9d4SSatish Balay PetscErrorCode PCPatchSetComputeOperatorInteriorFacets(PC pc, PetscErrorCode (*func)(PC, PetscInt, Vec, Mat, IS, PetscInt, const PetscInt *, const PetscInt *, void *), void *ctx) { 70359109abcSLawrence Mitchell PC_PATCH *patch = (PC_PATCH *)pc->data; 70459109abcSLawrence Mitchell 70559109abcSLawrence Mitchell PetscFunctionBegin; 70659109abcSLawrence Mitchell patch->usercomputeopintfacet = func; 70759109abcSLawrence Mitchell patch->usercomputeopintfacetctx = ctx; 70859109abcSLawrence Mitchell PetscFunctionReturn(0); 70959109abcSLawrence Mitchell } 71059109abcSLawrence Mitchell 7114bbf5ea8SMatthew G. Knepley /* On entry, ht contains the topological entities whose dofs we are responsible for solving for; 7124bbf5ea8SMatthew G. Knepley on exit, cht contains all the topological entities we need to compute their residuals. 7134bbf5ea8SMatthew G. Knepley In full generality this should incorporate knowledge of the sparsity pattern of the matrix; 7144bbf5ea8SMatthew G. Knepley here we assume a standard FE sparsity pattern.*/ 7154bbf5ea8SMatthew G. Knepley /* TODO: Use DMPlexGetAdjacency() */ 7169371c9d4SSatish Balay static PetscErrorCode PCPatchCompleteCellPatch(PC pc, PetscHSetI ht, PetscHSetI cht) { 717b6bb21d1SLawrence Mitchell DM dm, plex; 718bc7fa33aSFlorian Wechsung PC_PATCH *patch = (PC_PATCH *)pc->data; 7191b68eb51SMatthew G. Knepley PetscHashIter hi; 7204bbf5ea8SMatthew G. Knepley PetscInt point; 7214bbf5ea8SMatthew G. Knepley PetscInt *star = NULL, *closure = NULL; 7224c954380SMatthew G. Knepley PetscInt ignoredim, iStart = 0, iEnd = -1, starSize, closureSize, si, ci; 723bc7fa33aSFlorian Wechsung PetscInt *fStar = NULL, *fClosure = NULL; 724bc7fa33aSFlorian Wechsung PetscInt fBegin, fEnd, fsi, fci, fStarSize, fClosureSize; 7254bbf5ea8SMatthew G. Knepley 7264bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 7279566063dSJacob Faibussowitsch PetscCall(PCGetDM(pc, &dm)); 7289566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 729b6bb21d1SLawrence Mitchell dm = plex; 7309566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fBegin, &fEnd)); 7319566063dSJacob Faibussowitsch PetscCall(PCPatchGetIgnoreDim(pc, &ignoredim)); 7329566063dSJacob Faibussowitsch if (ignoredim >= 0) PetscCall(DMPlexGetDepthStratum(dm, ignoredim, &iStart, &iEnd)); 7339566063dSJacob Faibussowitsch PetscCall(PetscHSetIClear(cht)); 7341b68eb51SMatthew G. Knepley PetscHashIterBegin(ht, hi); 7351b68eb51SMatthew G. Knepley while (!PetscHashIterAtEnd(ht, hi)) { 7361b68eb51SMatthew G. Knepley PetscHashIterGetKey(ht, hi, point); 7371b68eb51SMatthew G. Knepley PetscHashIterNext(ht, hi); 7384bbf5ea8SMatthew G. Knepley 7394bbf5ea8SMatthew G. Knepley /* Loop over all the cells that this point connects to */ 7409566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_FALSE, &starSize, &star)); 7415f824522SMatthew G. Knepley for (si = 0; si < starSize * 2; si += 2) { 7424c954380SMatthew G. Knepley const PetscInt ownedpoint = star[si]; 7435f824522SMatthew G. Knepley /* TODO Check for point in cht before running through closure again */ 7444bbf5ea8SMatthew G. Knepley /* now loop over all entities in the closure of that cell */ 7459566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, ownedpoint, PETSC_TRUE, &closureSize, &closure)); 7465f824522SMatthew G. Knepley for (ci = 0; ci < closureSize * 2; ci += 2) { 7474c954380SMatthew G. Knepley const PetscInt seenpoint = closure[ci]; 7485f824522SMatthew G. Knepley if (ignoredim >= 0 && seenpoint >= iStart && seenpoint < iEnd) continue; 7499566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(cht, seenpoint)); 750bc7fa33aSFlorian Wechsung /* Facet integrals couple dofs across facets, so in that case for each of 751bc7fa33aSFlorian Wechsung * the facets we need to add all dofs on the other side of the facet to 752bc7fa33aSFlorian Wechsung * the seen dofs. */ 753bc7fa33aSFlorian Wechsung if (patch->usercomputeopintfacet) { 754bc7fa33aSFlorian Wechsung if (fBegin <= seenpoint && seenpoint < fEnd) { 7559566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, seenpoint, PETSC_FALSE, &fStarSize, &fStar)); 756bc7fa33aSFlorian Wechsung for (fsi = 0; fsi < fStarSize * 2; fsi += 2) { 7579566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, fStar[fsi], PETSC_TRUE, &fClosureSize, &fClosure)); 758*48a46eb9SPierre Jolivet for (fci = 0; fci < fClosureSize * 2; fci += 2) PetscCall(PetscHSetIAdd(cht, fClosure[fci])); 7599566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, fStar[fsi], PETSC_TRUE, NULL, &fClosure)); 760bc7fa33aSFlorian Wechsung } 7619566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, seenpoint, PETSC_FALSE, NULL, &fStar)); 762bc7fa33aSFlorian Wechsung } 763bc7fa33aSFlorian Wechsung } 7644bbf5ea8SMatthew G. Knepley } 7659566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, ownedpoint, PETSC_TRUE, NULL, &closure)); 7664bbf5ea8SMatthew G. Knepley } 7679566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_FALSE, NULL, &star)); 7684bbf5ea8SMatthew G. Knepley } 7699566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dm)); 7705f824522SMatthew G. Knepley PetscFunctionReturn(0); 7715f824522SMatthew G. Knepley } 7725f824522SMatthew G. Knepley 7739371c9d4SSatish Balay static PetscErrorCode PCPatchGetGlobalDofs(PC pc, PetscSection dofSection[], PetscInt f, PetscBool combined, PetscInt p, PetscInt *dof, PetscInt *off) { 7745f824522SMatthew G. Knepley PetscFunctionBegin; 7755f824522SMatthew G. Knepley if (combined) { 7765f824522SMatthew G. Knepley if (f < 0) { 7779566063dSJacob Faibussowitsch if (dof) PetscCall(PetscSectionGetDof(dofSection[0], p, dof)); 7789566063dSJacob Faibussowitsch if (off) PetscCall(PetscSectionGetOffset(dofSection[0], p, off)); 7795f824522SMatthew G. Knepley } else { 7809566063dSJacob Faibussowitsch if (dof) PetscCall(PetscSectionGetFieldDof(dofSection[0], p, f, dof)); 7819566063dSJacob Faibussowitsch if (off) PetscCall(PetscSectionGetFieldOffset(dofSection[0], p, f, off)); 7825f824522SMatthew G. Knepley } 7835f824522SMatthew G. Knepley } else { 7845f824522SMatthew G. Knepley if (f < 0) { 7855f824522SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 7865f824522SMatthew G. Knepley PetscInt fdof, g; 7875f824522SMatthew G. Knepley 7885f824522SMatthew G. Knepley if (dof) { 7895f824522SMatthew G. Knepley *dof = 0; 7905f824522SMatthew G. Knepley for (g = 0; g < patch->nsubspaces; ++g) { 7919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(dofSection[g], p, &fdof)); 7925f824522SMatthew G. Knepley *dof += fdof; 7935f824522SMatthew G. Knepley } 7945f824522SMatthew G. Knepley } 795624e31c3SLawrence Mitchell if (off) { 796624e31c3SLawrence Mitchell *off = 0; 797624e31c3SLawrence Mitchell for (g = 0; g < patch->nsubspaces; ++g) { 7989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(dofSection[g], p, &fdof)); 799624e31c3SLawrence Mitchell *off += fdof; 800624e31c3SLawrence Mitchell } 801624e31c3SLawrence Mitchell } 8025f824522SMatthew G. Knepley } else { 8039566063dSJacob Faibussowitsch if (dof) PetscCall(PetscSectionGetDof(dofSection[f], p, dof)); 8049566063dSJacob Faibussowitsch if (off) PetscCall(PetscSectionGetOffset(dofSection[f], p, off)); 8055f824522SMatthew G. Knepley } 8065f824522SMatthew G. Knepley } 8074bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 8084bbf5ea8SMatthew G. Knepley } 8094bbf5ea8SMatthew G. Knepley 8104bbf5ea8SMatthew G. Knepley /* Given a hash table with a set of topological entities (pts), compute the degrees of 8114bbf5ea8SMatthew G. Knepley freedom in global concatenated numbering on those entities. 8124bbf5ea8SMatthew G. Knepley For Vanka smoothing, this needs to do something special: ignore dofs of the 8134bbf5ea8SMatthew G. Knepley constraint subspace on entities that aren't the base entity we're building the patch 8144bbf5ea8SMatthew G. Knepley around. */ 8159371c9d4SSatish Balay static PetscErrorCode PCPatchGetPointDofs(PC pc, PetscHSetI pts, PetscHSetI dofs, PetscInt base, PetscHSetI *subspaces_to_exclude) { 8165f824522SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 8171b68eb51SMatthew G. Knepley PetscHashIter hi; 8184bbf5ea8SMatthew G. Knepley PetscInt ldof, loff; 8194bbf5ea8SMatthew G. Knepley PetscInt k, p; 8204bbf5ea8SMatthew G. Knepley 8214bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 8229566063dSJacob Faibussowitsch PetscCall(PetscHSetIClear(dofs)); 8234bbf5ea8SMatthew G. Knepley for (k = 0; k < patch->nsubspaces; ++k) { 8244bbf5ea8SMatthew G. Knepley PetscInt subspaceOffset = patch->subspaceOffsets[k]; 8254bbf5ea8SMatthew G. Knepley PetscInt bs = patch->bs[k]; 8264bbf5ea8SMatthew G. Knepley PetscInt j, l; 8274bbf5ea8SMatthew G. Knepley 828e4c66b91SPatrick Farrell if (subspaces_to_exclude != NULL) { 829e4c66b91SPatrick Farrell PetscBool should_exclude_k = PETSC_FALSE; 8309566063dSJacob Faibussowitsch PetscCall(PetscHSetIHas(*subspaces_to_exclude, k, &should_exclude_k)); 831e4c66b91SPatrick Farrell if (should_exclude_k) { 8324bbf5ea8SMatthew G. Knepley /* only get this subspace dofs at the base entity, not any others */ 8339566063dSJacob Faibussowitsch PetscCall(PCPatchGetGlobalDofs(pc, patch->dofSection, k, patch->combined, base, &ldof, &loff)); 8344bbf5ea8SMatthew G. Knepley if (0 == ldof) continue; 8354bbf5ea8SMatthew G. Knepley for (j = loff; j < ldof + loff; ++j) { 8364bbf5ea8SMatthew G. Knepley for (l = 0; l < bs; ++l) { 8374bbf5ea8SMatthew G. Knepley PetscInt dof = bs * j + l + subspaceOffset; 8389566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(dofs, dof)); 8394bbf5ea8SMatthew G. Knepley } 8404bbf5ea8SMatthew G. Knepley } 8414bbf5ea8SMatthew G. Knepley continue; /* skip the other dofs of this subspace */ 8424bbf5ea8SMatthew G. Knepley } 843e4c66b91SPatrick Farrell } 8444bbf5ea8SMatthew G. Knepley 8451b68eb51SMatthew G. Knepley PetscHashIterBegin(pts, hi); 8461b68eb51SMatthew G. Knepley while (!PetscHashIterAtEnd(pts, hi)) { 8471b68eb51SMatthew G. Knepley PetscHashIterGetKey(pts, hi, p); 8481b68eb51SMatthew G. Knepley PetscHashIterNext(pts, hi); 8499566063dSJacob Faibussowitsch PetscCall(PCPatchGetGlobalDofs(pc, patch->dofSection, k, patch->combined, p, &ldof, &loff)); 8504bbf5ea8SMatthew G. Knepley if (0 == ldof) continue; 8514bbf5ea8SMatthew G. Knepley for (j = loff; j < ldof + loff; ++j) { 8524bbf5ea8SMatthew G. Knepley for (l = 0; l < bs; ++l) { 8534bbf5ea8SMatthew G. Knepley PetscInt dof = bs * j + l + subspaceOffset; 8549566063dSJacob Faibussowitsch PetscCall(PetscHSetIAdd(dofs, dof)); 8554bbf5ea8SMatthew G. Knepley } 8564bbf5ea8SMatthew G. Knepley } 8574bbf5ea8SMatthew G. Knepley } 8584bbf5ea8SMatthew G. Knepley } 8594bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 8604bbf5ea8SMatthew G. Knepley } 8614bbf5ea8SMatthew G. Knepley 8624bbf5ea8SMatthew G. Knepley /* Given two hash tables A and B, compute the keys in B that are not in A, and put them in C */ 8639371c9d4SSatish Balay static PetscErrorCode PCPatchComputeSetDifference_Private(PetscHSetI A, PetscHSetI B, PetscHSetI C) { 8641b68eb51SMatthew G. Knepley PetscHashIter hi; 8651b68eb51SMatthew G. Knepley PetscInt key; 8664bbf5ea8SMatthew G. Knepley PetscBool flg; 8674bbf5ea8SMatthew G. Knepley 8684bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 8699566063dSJacob Faibussowitsch PetscCall(PetscHSetIClear(C)); 8701b68eb51SMatthew G. Knepley PetscHashIterBegin(B, hi); 8711b68eb51SMatthew G. Knepley while (!PetscHashIterAtEnd(B, hi)) { 8721b68eb51SMatthew G. Knepley PetscHashIterGetKey(B, hi, key); 8731b68eb51SMatthew G. Knepley PetscHashIterNext(B, hi); 8749566063dSJacob Faibussowitsch PetscCall(PetscHSetIHas(A, key, &flg)); 8759566063dSJacob Faibussowitsch if (!flg) PetscCall(PetscHSetIAdd(C, key)); 8764bbf5ea8SMatthew G. Knepley } 8774bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 8784bbf5ea8SMatthew G. Knepley } 8794bbf5ea8SMatthew G. Knepley 8804bbf5ea8SMatthew G. Knepley /* 8814bbf5ea8SMatthew G. Knepley * PCPatchCreateCellPatches - create patches. 8824bbf5ea8SMatthew G. Knepley * 8834bbf5ea8SMatthew G. Knepley * Input Parameters: 8844bbf5ea8SMatthew G. Knepley * + dm - The DMPlex object defining the mesh 8854bbf5ea8SMatthew G. Knepley * 8864bbf5ea8SMatthew G. Knepley * Output Parameters: 8874bbf5ea8SMatthew G. Knepley * + cellCounts - Section with counts of cells around each vertex 8885f824522SMatthew G. Knepley * . cells - IS of the cell point indices of cells in each patch 8895f824522SMatthew G. Knepley * . pointCounts - Section with counts of cells around each vertex 8905f824522SMatthew G. Knepley * - point - IS of the cell point indices of cells in each patch 8914bbf5ea8SMatthew G. Knepley */ 8929371c9d4SSatish Balay static PetscErrorCode PCPatchCreateCellPatches(PC pc) { 8934bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 8945f824522SMatthew G. Knepley DMLabel ghost = NULL; 8954bbf5ea8SMatthew G. Knepley DM dm, plex; 89676ce8f1aSJose E. Roman PetscHSetI ht = NULL, cht = NULL; 8970e126c0bSLawrence Mitchell PetscSection cellCounts, pointCounts, intFacetCounts, extFacetCounts; 898eb62eeaaSLawrence Mitchell PetscInt *cellsArray, *pointsArray, *intFacetsArray, *extFacetsArray, *intFacetsToPatchCell; 8990e126c0bSLawrence Mitchell PetscInt numCells, numPoints, numIntFacets, numExtFacets; 9005f824522SMatthew G. Knepley const PetscInt *leaves; 90133cbca70SPatrick Farrell PetscInt nleaves, pStart, pEnd, cStart, cEnd, vStart, vEnd, fStart, fEnd, v; 9025f824522SMatthew G. Knepley PetscBool isFiredrake; 9034bbf5ea8SMatthew G. Knepley 9044bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 9054bbf5ea8SMatthew G. Knepley /* Used to keep track of the cells in the patch. */ 9069566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&ht)); 9079566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&cht)); 9084bbf5ea8SMatthew G. Knepley 9099566063dSJacob Faibussowitsch PetscCall(PCGetDM(pc, &dm)); 91028b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "DM not yet set on patch PC"); 9119566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 912b6bb21d1SLawrence Mitchell dm = plex; 9139566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 9149566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 9154bbf5ea8SMatthew G. Knepley 9164bbf5ea8SMatthew G. Knepley if (patch->user_patches) { 9179566063dSJacob Faibussowitsch PetscCall(patch->userpatchconstructionop(pc, &patch->npatch, &patch->userIS, &patch->iterationSet, patch->userpatchconstructctx)); 9189371c9d4SSatish Balay vStart = 0; 9199371c9d4SSatish Balay vEnd = patch->npatch; 920e5b9877fSPatrick Farrell } else if (patch->ctype == PC_PATCH_PARDECOMP) { 9219371c9d4SSatish Balay vStart = 0; 9229371c9d4SSatish Balay vEnd = 1; 9235f824522SMatthew G. Knepley } else if (patch->codim < 0) { 9249566063dSJacob Faibussowitsch if (patch->dim < 0) PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 9259566063dSJacob Faibussowitsch else PetscCall(DMPlexGetDepthStratum(dm, patch->dim, &vStart, &vEnd)); 9269566063dSJacob Faibussowitsch } else PetscCall(DMPlexGetHeightStratum(dm, patch->codim, &vStart, &vEnd)); 9275f824522SMatthew G. Knepley patch->npatch = vEnd - vStart; 9284bbf5ea8SMatthew G. Knepley 9294bbf5ea8SMatthew G. Knepley /* These labels mark the owned points. We only create patches around points that this process owns. */ 9309566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, "pyop2_ghost", &isFiredrake)); 9315f824522SMatthew G. Knepley if (isFiredrake) { 9329566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "pyop2_ghost", &ghost)); 9339566063dSJacob Faibussowitsch PetscCall(DMLabelCreateIndex(ghost, pStart, pEnd)); 9345f824522SMatthew G. Knepley } else { 9355f824522SMatthew G. Knepley PetscSF sf; 9365f824522SMatthew G. Knepley 9379566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 9389566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, &nleaves, &leaves, NULL)); 9395f824522SMatthew G. Knepley nleaves = PetscMax(nleaves, 0); 9405f824522SMatthew G. Knepley } 9414bbf5ea8SMatthew G. Knepley 9429566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &patch->cellCounts)); 9439566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)patch->cellCounts, "Patch Cell Layout")); 9444bbf5ea8SMatthew G. Knepley cellCounts = patch->cellCounts; 9459566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(cellCounts, vStart, vEnd)); 9469566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &patch->pointCounts)); 9479566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)patch->pointCounts, "Patch Point Layout")); 9485f824522SMatthew G. Knepley pointCounts = patch->pointCounts; 9499566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(pointCounts, vStart, vEnd)); 9509566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &patch->extFacetCounts)); 9519566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)patch->extFacetCounts, "Patch Exterior Facet Layout")); 9520e126c0bSLawrence Mitchell extFacetCounts = patch->extFacetCounts; 9539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(extFacetCounts, vStart, vEnd)); 9549566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &patch->intFacetCounts)); 9559566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)patch->intFacetCounts, "Patch Interior Facet Layout")); 9560e126c0bSLawrence Mitchell intFacetCounts = patch->intFacetCounts; 9579566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(intFacetCounts, vStart, vEnd)); 9585f824522SMatthew G. Knepley /* Count cells and points in the patch surrounding each entity */ 9599566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 9604bbf5ea8SMatthew G. Knepley for (v = vStart; v < vEnd; ++v) { 9611b68eb51SMatthew G. Knepley PetscHashIter hi; 9625f824522SMatthew G. Knepley PetscInt chtSize, loc = -1; 9635f824522SMatthew G. Knepley PetscBool flg; 9644bbf5ea8SMatthew G. Knepley 965b525f888SPatrick Farrell if (!patch->user_patches && patch->ctype != PC_PATCH_PARDECOMP) { 9669566063dSJacob Faibussowitsch if (ghost) PetscCall(DMLabelHasPoint(ghost, v, &flg)); 9679371c9d4SSatish Balay else { 9689371c9d4SSatish Balay PetscCall(PetscFindInt(v, nleaves, leaves, &loc)); 9699371c9d4SSatish Balay flg = loc >= 0 ? PETSC_TRUE : PETSC_FALSE; 9709371c9d4SSatish Balay } 9714bbf5ea8SMatthew G. Knepley /* Not an owned entity, don't make a cell patch. */ 9724bbf5ea8SMatthew G. Knepley if (flg) continue; 9734bbf5ea8SMatthew G. Knepley } 9744bbf5ea8SMatthew G. Knepley 9759566063dSJacob Faibussowitsch PetscCall(patch->patchconstructop((void *)patch, dm, v, ht)); 9769566063dSJacob Faibussowitsch PetscCall(PCPatchCompleteCellPatch(pc, ht, cht)); 9779566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(cht, &chtSize)); 9784bbf5ea8SMatthew G. Knepley /* empty patch, continue */ 9794bbf5ea8SMatthew G. Knepley if (chtSize == 0) continue; 9804bbf5ea8SMatthew G. Knepley 9814bbf5ea8SMatthew G. Knepley /* safe because size(cht) > 0 from above */ 9821b68eb51SMatthew G. Knepley PetscHashIterBegin(cht, hi); 9831b68eb51SMatthew G. Knepley while (!PetscHashIterAtEnd(cht, hi)) { 9845f824522SMatthew G. Knepley PetscInt point, pdof; 9854bbf5ea8SMatthew G. Knepley 9861b68eb51SMatthew G. Knepley PetscHashIterGetKey(cht, hi, point); 9870e126c0bSLawrence Mitchell if (fStart <= point && point < fEnd) { 9880e126c0bSLawrence Mitchell const PetscInt *support; 9890e126c0bSLawrence Mitchell PetscInt supportSize, p; 9900e126c0bSLawrence Mitchell PetscBool interior = PETSC_TRUE; 9919566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, point, &support)); 9929566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, point, &supportSize)); 9930e126c0bSLawrence Mitchell if (supportSize == 1) { 9940e126c0bSLawrence Mitchell interior = PETSC_FALSE; 9950e126c0bSLawrence Mitchell } else { 9960e126c0bSLawrence Mitchell for (p = 0; p < supportSize; p++) { 9970e126c0bSLawrence Mitchell PetscBool found; 9980e126c0bSLawrence Mitchell /* FIXME: can I do this while iterating over cht? */ 9999566063dSJacob Faibussowitsch PetscCall(PetscHSetIHas(cht, support[p], &found)); 10000e126c0bSLawrence Mitchell if (!found) { 10010e126c0bSLawrence Mitchell interior = PETSC_FALSE; 10020e126c0bSLawrence Mitchell break; 10030e126c0bSLawrence Mitchell } 10040e126c0bSLawrence Mitchell } 10050e126c0bSLawrence Mitchell } 10060e126c0bSLawrence Mitchell if (interior) { 10079566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(intFacetCounts, v, 1)); 10080e126c0bSLawrence Mitchell } else { 10099566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(extFacetCounts, v, 1)); 10100e126c0bSLawrence Mitchell } 10110e126c0bSLawrence Mitchell } 10129566063dSJacob Faibussowitsch PetscCall(PCPatchGetGlobalDofs(pc, patch->dofSection, -1, patch->combined, point, &pdof, NULL)); 10139566063dSJacob Faibussowitsch if (pdof) PetscCall(PetscSectionAddDof(pointCounts, v, 1)); 10149566063dSJacob Faibussowitsch if (point >= cStart && point < cEnd) PetscCall(PetscSectionAddDof(cellCounts, v, 1)); 10151b68eb51SMatthew G. Knepley PetscHashIterNext(cht, hi); 10164bbf5ea8SMatthew G. Knepley } 10174bbf5ea8SMatthew G. Knepley } 10189566063dSJacob Faibussowitsch if (isFiredrake) PetscCall(DMLabelDestroyIndex(ghost)); 10194bbf5ea8SMatthew G. Knepley 10209566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(cellCounts)); 10219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(cellCounts, &numCells)); 10229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numCells, &cellsArray)); 10239566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(pointCounts)); 10249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(pointCounts, &numPoints)); 10259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints, &pointsArray)); 10264bbf5ea8SMatthew G. Knepley 10279566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(intFacetCounts)); 10289566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(extFacetCounts)); 10299566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(intFacetCounts, &numIntFacets)); 10309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(extFacetCounts, &numExtFacets)); 10319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numIntFacets, &intFacetsArray)); 10329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numIntFacets * 2, &intFacetsToPatchCell)); 10339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numExtFacets, &extFacetsArray)); 10340e126c0bSLawrence Mitchell 10354bbf5ea8SMatthew G. Knepley /* Now that we know how much space we need, run through again and actually remember the cells. */ 10364bbf5ea8SMatthew G. Knepley for (v = vStart; v < vEnd; v++) { 10371b68eb51SMatthew G. Knepley PetscHashIter hi; 10380e126c0bSLawrence Mitchell PetscInt dof, off, cdof, coff, efdof, efoff, ifdof, ifoff, pdof, n = 0, cn = 0, ifn = 0, efn = 0; 10394bbf5ea8SMatthew G. Knepley 10409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(pointCounts, v, &dof)); 10419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(pointCounts, v, &off)); 10429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cellCounts, v, &cdof)); 10439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cellCounts, v, &coff)); 10449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(intFacetCounts, v, &ifdof)); 10459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(intFacetCounts, v, &ifoff)); 10469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(extFacetCounts, v, &efdof)); 10479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(extFacetCounts, v, &efoff)); 10485f824522SMatthew G. Knepley if (dof <= 0) continue; 10499566063dSJacob Faibussowitsch PetscCall(patch->patchconstructop((void *)patch, dm, v, ht)); 10509566063dSJacob Faibussowitsch PetscCall(PCPatchCompleteCellPatch(pc, ht, cht)); 10511b68eb51SMatthew G. Knepley PetscHashIterBegin(cht, hi); 10521b68eb51SMatthew G. Knepley while (!PetscHashIterAtEnd(cht, hi)) { 10534bbf5ea8SMatthew G. Knepley PetscInt point; 10544bbf5ea8SMatthew G. Knepley 10551b68eb51SMatthew G. Knepley PetscHashIterGetKey(cht, hi, point); 10560e126c0bSLawrence Mitchell if (fStart <= point && point < fEnd) { 10570e126c0bSLawrence Mitchell const PetscInt *support; 10580e126c0bSLawrence Mitchell PetscInt supportSize, p; 10590e126c0bSLawrence Mitchell PetscBool interior = PETSC_TRUE; 10609566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, point, &support)); 10619566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, point, &supportSize)); 10620e126c0bSLawrence Mitchell if (supportSize == 1) { 10630e126c0bSLawrence Mitchell interior = PETSC_FALSE; 10640e126c0bSLawrence Mitchell } else { 10650e126c0bSLawrence Mitchell for (p = 0; p < supportSize; p++) { 10660e126c0bSLawrence Mitchell PetscBool found; 10670e126c0bSLawrence Mitchell /* FIXME: can I do this while iterating over cht? */ 10689566063dSJacob Faibussowitsch PetscCall(PetscHSetIHas(cht, support[p], &found)); 10690e126c0bSLawrence Mitchell if (!found) { 10700e126c0bSLawrence Mitchell interior = PETSC_FALSE; 10710e126c0bSLawrence Mitchell break; 10720e126c0bSLawrence Mitchell } 10730e126c0bSLawrence Mitchell } 10740e126c0bSLawrence Mitchell } 10750e126c0bSLawrence Mitchell if (interior) { 107644b625f7SLawrence Mitchell intFacetsToPatchCell[2 * (ifoff + ifn)] = support[0]; 107744b625f7SLawrence Mitchell intFacetsToPatchCell[2 * (ifoff + ifn) + 1] = support[1]; 10780e126c0bSLawrence Mitchell intFacetsArray[ifoff + ifn++] = point; 10790e126c0bSLawrence Mitchell } else { 10800e126c0bSLawrence Mitchell extFacetsArray[efoff + efn++] = point; 10810e126c0bSLawrence Mitchell } 10820e126c0bSLawrence Mitchell } 10839566063dSJacob Faibussowitsch PetscCall(PCPatchGetGlobalDofs(pc, patch->dofSection, -1, patch->combined, point, &pdof, NULL)); 10845f824522SMatthew G. Knepley if (pdof) { pointsArray[off + n++] = point; } 10855f824522SMatthew G. Knepley if (point >= cStart && point < cEnd) { cellsArray[coff + cn++] = point; } 10861b68eb51SMatthew G. Knepley PetscHashIterNext(cht, hi); 10874bbf5ea8SMatthew G. Knepley } 108863a3b9bcSJacob 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); 108963a3b9bcSJacob 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); 109063a3b9bcSJacob 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); 109163a3b9bcSJacob 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); 1092eb62eeaaSLawrence Mitchell 1093eb62eeaaSLawrence Mitchell for (ifn = 0; ifn < ifdof; ifn++) { 109444b625f7SLawrence Mitchell PetscInt cell0 = intFacetsToPatchCell[2 * (ifoff + ifn)]; 109544b625f7SLawrence Mitchell PetscInt cell1 = intFacetsToPatchCell[2 * (ifoff + ifn) + 1]; 1096eb62eeaaSLawrence Mitchell PetscBool found0 = PETSC_FALSE, found1 = PETSC_FALSE; 1097eb62eeaaSLawrence Mitchell for (n = 0; n < cdof; n++) { 10987c54fef0SLawrence Mitchell if (!found0 && cell0 == cellsArray[coff + n]) { 1099c3faab33SLawrence Mitchell intFacetsToPatchCell[2 * (ifoff + ifn)] = n; 1100eb62eeaaSLawrence Mitchell found0 = PETSC_TRUE; 1101eb62eeaaSLawrence Mitchell } 11027c54fef0SLawrence Mitchell if (!found1 && cell1 == cellsArray[coff + n]) { 1103c3faab33SLawrence Mitchell intFacetsToPatchCell[2 * (ifoff + ifn) + 1] = n; 110480fc4459SLawrence Mitchell found1 = PETSC_TRUE; 1105eb62eeaaSLawrence Mitchell } 1106eb62eeaaSLawrence Mitchell if (found0 && found1) break; 1107eb62eeaaSLawrence Mitchell } 11087827d75bSBarry Smith PetscCheck(found0 && found1, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Didn't manage to find local point numbers for facet support"); 1109eb62eeaaSLawrence Mitchell } 11104bbf5ea8SMatthew G. Knepley } 11119566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&ht)); 11129566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&cht)); 11135f824522SMatthew G. Knepley 11149566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numCells, cellsArray, PETSC_OWN_POINTER, &patch->cells)); 11159566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)patch->cells, "Patch Cells")); 11165f824522SMatthew G. Knepley if (patch->viewCells) { 11179566063dSJacob Faibussowitsch PetscCall(ObjectView((PetscObject)patch->cellCounts, patch->viewerCells, patch->formatCells)); 11189566063dSJacob Faibussowitsch PetscCall(ObjectView((PetscObject)patch->cells, patch->viewerCells, patch->formatCells)); 11195f824522SMatthew G. Knepley } 11209566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numIntFacets, intFacetsArray, PETSC_OWN_POINTER, &patch->intFacets)); 11219566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)patch->intFacets, "Patch Interior Facets")); 11229566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, 2 * numIntFacets, intFacetsToPatchCell, PETSC_OWN_POINTER, &patch->intFacetsToPatchCell)); 11239566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)patch->intFacetsToPatchCell, "Patch Interior Facets local support")); 11240e126c0bSLawrence Mitchell if (patch->viewIntFacets) { 11259566063dSJacob Faibussowitsch PetscCall(ObjectView((PetscObject)patch->intFacetCounts, patch->viewerIntFacets, patch->formatIntFacets)); 11269566063dSJacob Faibussowitsch PetscCall(ObjectView((PetscObject)patch->intFacets, patch->viewerIntFacets, patch->formatIntFacets)); 11279566063dSJacob Faibussowitsch PetscCall(ObjectView((PetscObject)patch->intFacetsToPatchCell, patch->viewerIntFacets, patch->formatIntFacets)); 11280e126c0bSLawrence Mitchell } 11299566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numExtFacets, extFacetsArray, PETSC_OWN_POINTER, &patch->extFacets)); 11309566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)patch->extFacets, "Patch Exterior Facets")); 11310e126c0bSLawrence Mitchell if (patch->viewExtFacets) { 11329566063dSJacob Faibussowitsch PetscCall(ObjectView((PetscObject)patch->extFacetCounts, patch->viewerExtFacets, patch->formatExtFacets)); 11339566063dSJacob Faibussowitsch PetscCall(ObjectView((PetscObject)patch->extFacets, patch->viewerExtFacets, patch->formatExtFacets)); 11340e126c0bSLawrence Mitchell } 11359566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numPoints, pointsArray, PETSC_OWN_POINTER, &patch->points)); 11369566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)patch->points, "Patch Points")); 11375f824522SMatthew G. Knepley if (patch->viewPoints) { 11389566063dSJacob Faibussowitsch PetscCall(ObjectView((PetscObject)patch->pointCounts, patch->viewerPoints, patch->formatPoints)); 11399566063dSJacob Faibussowitsch PetscCall(ObjectView((PetscObject)patch->points, patch->viewerPoints, patch->formatPoints)); 11405f824522SMatthew G. Knepley } 11419566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dm)); 11424bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 11434bbf5ea8SMatthew G. Knepley } 11444bbf5ea8SMatthew G. Knepley 11454bbf5ea8SMatthew G. Knepley /* 11464bbf5ea8SMatthew G. Knepley * PCPatchCreateCellPatchDiscretisationInfo - Build the dof maps for cell patches 11474bbf5ea8SMatthew G. Knepley * 11484bbf5ea8SMatthew G. Knepley * Input Parameters: 11494bbf5ea8SMatthew G. Knepley * + dm - The DMPlex object defining the mesh 11504bbf5ea8SMatthew G. Knepley * . cellCounts - Section with counts of cells around each vertex 11514bbf5ea8SMatthew G. Knepley * . cells - IS of the cell point indices of cells in each patch 11524bbf5ea8SMatthew G. Knepley * . cellNumbering - Section mapping plex cell points to Firedrake cell indices. 11534bbf5ea8SMatthew G. Knepley * . nodesPerCell - number of nodes per cell. 11544bbf5ea8SMatthew G. Knepley * - cellNodeMap - map from cells to node indices (nodesPerCell * numCells) 11554bbf5ea8SMatthew G. Knepley * 11564bbf5ea8SMatthew G. Knepley * Output Parameters: 11575f824522SMatthew G. Knepley * + dofs - IS of local dof numbers of each cell in the patch, where local is a patch local numbering 11584bbf5ea8SMatthew G. Knepley * . gtolCounts - Section with counts of dofs per cell patch 11594bbf5ea8SMatthew G. Knepley * - gtol - IS mapping from global dofs to local dofs for each patch. 11604bbf5ea8SMatthew G. Knepley */ 11619371c9d4SSatish Balay static PetscErrorCode PCPatchCreateCellPatchDiscretisationInfo(PC pc) { 11624bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 11634bbf5ea8SMatthew G. Knepley PetscSection cellCounts = patch->cellCounts; 11645f824522SMatthew G. Knepley PetscSection pointCounts = patch->pointCounts; 11650904074fSPatrick Farrell PetscSection gtolCounts, gtolCountsWithArtificial = NULL, gtolCountsWithAll = NULL; 11664bbf5ea8SMatthew G. Knepley IS cells = patch->cells; 11675f824522SMatthew G. Knepley IS points = patch->points; 11684bbf5ea8SMatthew G. Knepley PetscSection cellNumbering = patch->cellNumbering; 11695f824522SMatthew G. Knepley PetscInt Nf = patch->nsubspaces; 11705f824522SMatthew G. Knepley PetscInt numCells, numPoints; 11714bbf5ea8SMatthew G. Knepley PetscInt numDofs; 11720904074fSPatrick Farrell PetscInt numGlobalDofs, numGlobalDofsWithArtificial, numGlobalDofsWithAll; 11734bbf5ea8SMatthew G. Knepley PetscInt totalDofsPerCell = patch->totalDofsPerCell; 11744bbf5ea8SMatthew G. Knepley PetscInt vStart, vEnd, v; 11755f824522SMatthew G. Knepley const PetscInt *cellsArray, *pointsArray; 11764bbf5ea8SMatthew G. Knepley PetscInt *newCellsArray = NULL; 11774bbf5ea8SMatthew G. Knepley PetscInt *dofsArray = NULL; 1178c2e6f3c0SFlorian Wechsung PetscInt *dofsArrayWithArtificial = NULL; 11790904074fSPatrick Farrell PetscInt *dofsArrayWithAll = NULL; 11805f824522SMatthew G. Knepley PetscInt *offsArray = NULL; 1181c2e6f3c0SFlorian Wechsung PetscInt *offsArrayWithArtificial = NULL; 11820904074fSPatrick Farrell PetscInt *offsArrayWithAll = NULL; 11834bbf5ea8SMatthew G. Knepley PetscInt *asmArray = NULL; 1184c2e6f3c0SFlorian Wechsung PetscInt *asmArrayWithArtificial = NULL; 11850904074fSPatrick Farrell PetscInt *asmArrayWithAll = NULL; 11864bbf5ea8SMatthew G. Knepley PetscInt *globalDofsArray = NULL; 1187c2e6f3c0SFlorian Wechsung PetscInt *globalDofsArrayWithArtificial = NULL; 11880904074fSPatrick Farrell PetscInt *globalDofsArrayWithAll = NULL; 11894bbf5ea8SMatthew G. Knepley PetscInt globalIndex = 0; 11904bbf5ea8SMatthew G. Knepley PetscInt key = 0; 11914bbf5ea8SMatthew G. Knepley PetscInt asmKey = 0; 1192b6bb21d1SLawrence Mitchell DM dm = NULL, plex; 1193557beb66SLawrence Mitchell const PetscInt *bcNodes = NULL; 11941b68eb51SMatthew G. Knepley PetscHMapI ht; 1195c2e6f3c0SFlorian Wechsung PetscHMapI htWithArtificial; 11960904074fSPatrick Farrell PetscHMapI htWithAll; 11971b68eb51SMatthew G. Knepley PetscHSetI globalBcs; 1198557beb66SLawrence Mitchell PetscInt numBcs; 11991b68eb51SMatthew G. Knepley PetscHSetI ownedpts, seenpts, owneddofs, seendofs, artificialbcs; 1200cda239d9SMatthew G. Knepley PetscInt pStart, pEnd, p, i; 120110534d48SPatrick Farrell char option[PETSC_MAX_PATH_LEN]; 120239fd2e8aSPatrick Farrell PetscBool isNonlinear; 12034bbf5ea8SMatthew G. Knepley 12044bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 1205557beb66SLawrence Mitchell 12069566063dSJacob Faibussowitsch PetscCall(PCGetDM(pc, &dm)); 12079566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 1208b6bb21d1SLawrence Mitchell dm = plex; 12094bbf5ea8SMatthew G. Knepley /* dofcounts section is cellcounts section * dofPerCell */ 12109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(cellCounts, &numCells)); 12119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(patch->pointCounts, &numPoints)); 12124bbf5ea8SMatthew G. Knepley numDofs = numCells * totalDofsPerCell; 12139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numDofs, &dofsArray)); 12149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints * Nf, &offsArray)); 12159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numDofs, &asmArray)); 12169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numCells, &newCellsArray)); 12179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(cellCounts, &vStart, &vEnd)); 12189566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &patch->gtolCounts)); 12194bbf5ea8SMatthew G. Knepley gtolCounts = patch->gtolCounts; 12209566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(gtolCounts, vStart, vEnd)); 12219566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)patch->gtolCounts, "Patch Global Index Section")); 12224bbf5ea8SMatthew G. Knepley 1223b6bb21d1SLawrence Mitchell if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) { 12249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints * Nf, &offsArrayWithArtificial)); 12259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numDofs, &asmArrayWithArtificial)); 12269566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numDofs, &dofsArrayWithArtificial)); 12279566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &patch->gtolCountsWithArtificial)); 1228c2e6f3c0SFlorian Wechsung gtolCountsWithArtificial = patch->gtolCountsWithArtificial; 12299566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(gtolCountsWithArtificial, vStart, vEnd)); 12309566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)patch->gtolCountsWithArtificial, "Patch Global Index Section Including Artificial BCs")); 1231c2e6f3c0SFlorian Wechsung } 1232c2e6f3c0SFlorian Wechsung 12330904074fSPatrick Farrell isNonlinear = patch->isNonlinear; 1234b6bb21d1SLawrence Mitchell if (isNonlinear) { 12359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPoints * Nf, &offsArrayWithAll)); 12369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numDofs, &asmArrayWithAll)); 12379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numDofs, &dofsArrayWithAll)); 12389566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &patch->gtolCountsWithAll)); 12390904074fSPatrick Farrell gtolCountsWithAll = patch->gtolCountsWithAll; 12409566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(gtolCountsWithAll, vStart, vEnd)); 12419566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)patch->gtolCountsWithAll, "Patch Global Index Section Including All BCs")); 12420904074fSPatrick Farrell } 12430904074fSPatrick Farrell 1244557beb66SLawrence Mitchell /* Outside the patch loop, get the dofs that are globally-enforced Dirichlet 1245557beb66SLawrence Mitchell conditions */ 12469566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&globalBcs)); 12479566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->ghostBcNodes, &bcNodes)); 12489566063dSJacob Faibussowitsch PetscCall(ISGetSize(patch->ghostBcNodes, &numBcs)); 12499371c9d4SSatish Balay for (i = 0; i < numBcs; ++i) { PetscCall(PetscHSetIAdd(globalBcs, bcNodes[i])); /* these are already in concatenated numbering */ } 12509566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->ghostBcNodes, &bcNodes)); 12519566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->ghostBcNodes)); /* memory optimisation */ 1252557beb66SLawrence Mitchell 1253557beb66SLawrence Mitchell /* Hash tables for artificial BC construction */ 12549566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&ownedpts)); 12559566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&seenpts)); 12569566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&owneddofs)); 12579566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&seendofs)); 12589566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&artificialbcs)); 1259557beb66SLawrence Mitchell 12609566063dSJacob Faibussowitsch PetscCall(ISGetIndices(cells, &cellsArray)); 12619566063dSJacob Faibussowitsch PetscCall(ISGetIndices(points, &pointsArray)); 12629566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&ht)); 12639566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&htWithArtificial)); 12649566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&htWithAll)); 12654bbf5ea8SMatthew G. Knepley for (v = vStart; v < vEnd; ++v) { 12664bbf5ea8SMatthew G. Knepley PetscInt localIndex = 0; 1267c2e6f3c0SFlorian Wechsung PetscInt localIndexWithArtificial = 0; 12680904074fSPatrick Farrell PetscInt localIndexWithAll = 0; 12694bbf5ea8SMatthew G. Knepley PetscInt dof, off, i, j, k, l; 12704bbf5ea8SMatthew G. Knepley 12719566063dSJacob Faibussowitsch PetscCall(PetscHMapIClear(ht)); 12729566063dSJacob Faibussowitsch PetscCall(PetscHMapIClear(htWithArtificial)); 12739566063dSJacob Faibussowitsch PetscCall(PetscHMapIClear(htWithAll)); 12749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cellCounts, v, &dof)); 12759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cellCounts, v, &off)); 12764bbf5ea8SMatthew G. Knepley if (dof <= 0) continue; 12774bbf5ea8SMatthew G. Knepley 1278557beb66SLawrence Mitchell /* Calculate the global numbers of the artificial BC dofs here first */ 12799566063dSJacob Faibussowitsch PetscCall(patch->patchconstructop((void *)patch, dm, v, ownedpts)); 12809566063dSJacob Faibussowitsch PetscCall(PCPatchCompleteCellPatch(pc, ownedpts, seenpts)); 12819566063dSJacob Faibussowitsch PetscCall(PCPatchGetPointDofs(pc, ownedpts, owneddofs, v, &patch->subspaces_to_exclude)); 12829566063dSJacob Faibussowitsch PetscCall(PCPatchGetPointDofs(pc, seenpts, seendofs, v, NULL)); 12839566063dSJacob Faibussowitsch PetscCall(PCPatchComputeSetDifference_Private(owneddofs, seendofs, artificialbcs)); 12848135ed82SLawrence Mitchell if (patch->viewPatches) { 12851b68eb51SMatthew G. Knepley PetscHSetI globalbcdofs; 12861b68eb51SMatthew G. Knepley PetscHashIter hi; 12878135ed82SLawrence Mitchell MPI_Comm comm = PetscObjectComm((PetscObject)pc); 12881b68eb51SMatthew G. Knepley 12899566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&globalbcdofs)); 129063a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "Patch %" PetscInt_FMT ": owned dofs:\n", v)); 12911b68eb51SMatthew G. Knepley PetscHashIterBegin(owneddofs, hi); 12921b68eb51SMatthew G. Knepley while (!PetscHashIterAtEnd(owneddofs, hi)) { 12938135ed82SLawrence Mitchell PetscInt globalDof; 12948135ed82SLawrence Mitchell 12951b68eb51SMatthew G. Knepley PetscHashIterGetKey(owneddofs, hi, globalDof); 12961b68eb51SMatthew G. Knepley PetscHashIterNext(owneddofs, hi); 129763a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "%" PetscInt_FMT " ", globalDof)); 12988135ed82SLawrence Mitchell } 12999566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "\n")); 130063a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "Patch %" PetscInt_FMT ": seen dofs:\n", v)); 13011b68eb51SMatthew G. Knepley PetscHashIterBegin(seendofs, hi); 13021b68eb51SMatthew G. Knepley while (!PetscHashIterAtEnd(seendofs, hi)) { 13038135ed82SLawrence Mitchell PetscInt globalDof; 13048135ed82SLawrence Mitchell PetscBool flg; 13058135ed82SLawrence Mitchell 13061b68eb51SMatthew G. Knepley PetscHashIterGetKey(seendofs, hi, globalDof); 13071b68eb51SMatthew G. Knepley PetscHashIterNext(seendofs, hi); 130863a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "%" PetscInt_FMT " ", globalDof)); 13098135ed82SLawrence Mitchell 13109566063dSJacob Faibussowitsch PetscCall(PetscHSetIHas(globalBcs, globalDof, &flg)); 13119566063dSJacob Faibussowitsch if (flg) PetscCall(PetscHSetIAdd(globalbcdofs, globalDof)); 13128135ed82SLawrence Mitchell } 13139566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "\n")); 131463a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "Patch %" PetscInt_FMT ": global BCs:\n", v)); 13159566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(globalbcdofs, &numBcs)); 13168135ed82SLawrence Mitchell if (numBcs > 0) { 13171b68eb51SMatthew G. Knepley PetscHashIterBegin(globalbcdofs, hi); 13181b68eb51SMatthew G. Knepley while (!PetscHashIterAtEnd(globalbcdofs, hi)) { 13198135ed82SLawrence Mitchell PetscInt globalDof; 13201b68eb51SMatthew G. Knepley PetscHashIterGetKey(globalbcdofs, hi, globalDof); 13211b68eb51SMatthew G. Knepley PetscHashIterNext(globalbcdofs, hi); 132263a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "%" PetscInt_FMT " ", globalDof)); 13238135ed82SLawrence Mitchell } 13248135ed82SLawrence Mitchell } 13259566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "\n")); 132663a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "Patch %" PetscInt_FMT ": artificial BCs:\n", v)); 13279566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(artificialbcs, &numBcs)); 13288135ed82SLawrence Mitchell if (numBcs > 0) { 13291b68eb51SMatthew G. Knepley PetscHashIterBegin(artificialbcs, hi); 13301b68eb51SMatthew G. Knepley while (!PetscHashIterAtEnd(artificialbcs, hi)) { 13318135ed82SLawrence Mitchell PetscInt globalDof; 13321b68eb51SMatthew G. Knepley PetscHashIterGetKey(artificialbcs, hi, globalDof); 13331b68eb51SMatthew G. Knepley PetscHashIterNext(artificialbcs, hi); 133463a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "%" PetscInt_FMT " ", globalDof)); 13358135ed82SLawrence Mitchell } 13368135ed82SLawrence Mitchell } 13379566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(comm, "\n\n")); 13389566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&globalbcdofs)); 13398135ed82SLawrence Mitchell } 13404bbf5ea8SMatthew G. Knepley for (k = 0; k < patch->nsubspaces; ++k) { 13414bbf5ea8SMatthew G. Knepley const PetscInt *cellNodeMap = patch->cellNodeMap[k]; 13424bbf5ea8SMatthew G. Knepley PetscInt nodesPerCell = patch->nodesPerCell[k]; 13434bbf5ea8SMatthew G. Knepley PetscInt subspaceOffset = patch->subspaceOffsets[k]; 13444bbf5ea8SMatthew G. Knepley PetscInt bs = patch->bs[k]; 13454bbf5ea8SMatthew G. Knepley 13464bbf5ea8SMatthew G. Knepley for (i = off; i < off + dof; ++i) { 13474bbf5ea8SMatthew G. Knepley /* Walk over the cells in this patch. */ 13484bbf5ea8SMatthew G. Knepley const PetscInt c = cellsArray[i]; 13495f824522SMatthew G. Knepley PetscInt cell = c; 13504bbf5ea8SMatthew G. Knepley 13515f824522SMatthew G. Knepley /* TODO Change this to an IS */ 13525f824522SMatthew G. Knepley if (cellNumbering) { 13539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cellNumbering, c, &cell)); 135463a3b9bcSJacob Faibussowitsch PetscCheck(cell > 0, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " doesn't appear in cell numbering map", c); 13559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cellNumbering, c, &cell)); 13565f824522SMatthew G. Knepley } 13574bbf5ea8SMatthew G. Knepley newCellsArray[i] = cell; 13584bbf5ea8SMatthew G. Knepley for (j = 0; j < nodesPerCell; ++j) { 13594bbf5ea8SMatthew G. Knepley /* For each global dof, map it into contiguous local storage. */ 13604bbf5ea8SMatthew G. Knepley const PetscInt globalDof = cellNodeMap[cell * nodesPerCell + j] * bs + subspaceOffset; 13614bbf5ea8SMatthew G. Knepley /* finally, loop over block size */ 13624bbf5ea8SMatthew G. Knepley for (l = 0; l < bs; ++l) { 13631b68eb51SMatthew G. Knepley PetscInt localDof; 13641b68eb51SMatthew G. Knepley PetscBool isGlobalBcDof, isArtificialBcDof; 13654bbf5ea8SMatthew G. Knepley 1366557beb66SLawrence Mitchell /* first, check if this is either a globally enforced or locally enforced BC dof */ 13679566063dSJacob Faibussowitsch PetscCall(PetscHSetIHas(globalBcs, globalDof + l, &isGlobalBcDof)); 13689566063dSJacob Faibussowitsch PetscCall(PetscHSetIHas(artificialbcs, globalDof + l, &isArtificialBcDof)); 1369557beb66SLawrence Mitchell 1370557beb66SLawrence Mitchell /* if it's either, don't ever give it a local dof number */ 13711b68eb51SMatthew G. Knepley if (isGlobalBcDof || isArtificialBcDof) { 1372c2e6f3c0SFlorian Wechsung dofsArray[globalIndex] = -1; /* don't use this in assembly in this patch */ 1373557beb66SLawrence Mitchell } else { 13749566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(ht, globalDof + l, &localDof)); 13754bbf5ea8SMatthew G. Knepley if (localDof == -1) { 13764bbf5ea8SMatthew G. Knepley localDof = localIndex++; 13779566063dSJacob Faibussowitsch PetscCall(PetscHMapISet(ht, globalDof + l, localDof)); 13784bbf5ea8SMatthew G. Knepley } 137963a3b9bcSJacob Faibussowitsch PetscCheck(globalIndex < numDofs, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Found more dofs %" PetscInt_FMT " than expected %" PetscInt_FMT, globalIndex + 1, numDofs); 13804bbf5ea8SMatthew G. Knepley /* And store. */ 1381c2e6f3c0SFlorian Wechsung dofsArray[globalIndex] = localDof; 13824bbf5ea8SMatthew G. Knepley } 1383c2e6f3c0SFlorian Wechsung 13840904074fSPatrick Farrell if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) { 1385c2e6f3c0SFlorian Wechsung if (isGlobalBcDof) { 1386e047a90bSFlorian Wechsung dofsArrayWithArtificial[globalIndex] = -1; /* don't use this in assembly in this patch */ 1387c2e6f3c0SFlorian Wechsung } else { 13889566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(htWithArtificial, globalDof + l, &localDof)); 1389c2e6f3c0SFlorian Wechsung if (localDof == -1) { 1390c2e6f3c0SFlorian Wechsung localDof = localIndexWithArtificial++; 13919566063dSJacob Faibussowitsch PetscCall(PetscHMapISet(htWithArtificial, globalDof + l, localDof)); 1392c2e6f3c0SFlorian Wechsung } 139363a3b9bcSJacob Faibussowitsch PetscCheck(globalIndex < numDofs, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Found more dofs %" PetscInt_FMT " than expected %" PetscInt_FMT, globalIndex + 1, numDofs); 1394c2e6f3c0SFlorian Wechsung /* And store.*/ 1395c2e6f3c0SFlorian Wechsung dofsArrayWithArtificial[globalIndex] = localDof; 1396c2e6f3c0SFlorian Wechsung } 1397c2e6f3c0SFlorian Wechsung } 13980904074fSPatrick Farrell 13990904074fSPatrick Farrell if (isNonlinear) { 14000904074fSPatrick Farrell /* Build the dofmap for the function space with _all_ dofs, 14010904074fSPatrick Farrell including those in any kind of boundary condition */ 14029566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(htWithAll, globalDof + l, &localDof)); 14030904074fSPatrick Farrell if (localDof == -1) { 14040904074fSPatrick Farrell localDof = localIndexWithAll++; 14059566063dSJacob Faibussowitsch PetscCall(PetscHMapISet(htWithAll, globalDof + l, localDof)); 14060904074fSPatrick Farrell } 140763a3b9bcSJacob Faibussowitsch PetscCheck(globalIndex < numDofs, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Found more dofs %" PetscInt_FMT " than expected %" PetscInt_FMT, globalIndex + 1, numDofs); 14080904074fSPatrick Farrell /* And store.*/ 14090904074fSPatrick Farrell dofsArrayWithAll[globalIndex] = localDof; 14100904074fSPatrick Farrell } 1411c2e6f3c0SFlorian Wechsung globalIndex++; 14124bbf5ea8SMatthew G. Knepley } 14134bbf5ea8SMatthew G. Knepley } 14144bbf5ea8SMatthew G. Knepley } 1415557beb66SLawrence Mitchell } 14164bbf5ea8SMatthew G. Knepley /*How many local dofs in this patch? */ 14170904074fSPatrick Farrell if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) { 14189566063dSJacob Faibussowitsch PetscCall(PetscHMapIGetSize(htWithArtificial, &dof)); 14199566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(gtolCountsWithArtificial, v, dof)); 1420c2e6f3c0SFlorian Wechsung } 14210904074fSPatrick Farrell if (isNonlinear) { 14229566063dSJacob Faibussowitsch PetscCall(PetscHMapIGetSize(htWithAll, &dof)); 14239566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(gtolCountsWithAll, v, dof)); 14240904074fSPatrick Farrell } 14259566063dSJacob Faibussowitsch PetscCall(PetscHMapIGetSize(ht, &dof)); 14269566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(gtolCounts, v, dof)); 14274bbf5ea8SMatthew G. Knepley } 1428b6bb21d1SLawrence Mitchell 14299566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dm)); 143063a3b9bcSJacob 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); 14319566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(gtolCounts)); 14329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(gtolCounts, &numGlobalDofs)); 14339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numGlobalDofs, &globalDofsArray)); 14344bbf5ea8SMatthew G. Knepley 14350904074fSPatrick Farrell if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) { 14369566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(gtolCountsWithArtificial)); 14379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(gtolCountsWithArtificial, &numGlobalDofsWithArtificial)); 14389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numGlobalDofsWithArtificial, &globalDofsArrayWithArtificial)); 1439c2e6f3c0SFlorian Wechsung } 14400904074fSPatrick Farrell if (isNonlinear) { 14419566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(gtolCountsWithAll)); 14429566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(gtolCountsWithAll, &numGlobalDofsWithAll)); 14439566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numGlobalDofsWithAll, &globalDofsArrayWithAll)); 14440904074fSPatrick Farrell } 14454bbf5ea8SMatthew 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. */ 14464bbf5ea8SMatthew G. Knepley for (v = vStart; v < vEnd; ++v) { 14471b68eb51SMatthew G. Knepley PetscHashIter hi; 14485f824522SMatthew G. Knepley PetscInt dof, off, Np, ooff, i, j, k, l; 14494bbf5ea8SMatthew G. Knepley 14509566063dSJacob Faibussowitsch PetscCall(PetscHMapIClear(ht)); 14519566063dSJacob Faibussowitsch PetscCall(PetscHMapIClear(htWithArtificial)); 14529566063dSJacob Faibussowitsch PetscCall(PetscHMapIClear(htWithAll)); 14539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(cellCounts, v, &dof)); 14549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(cellCounts, v, &off)); 14559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(pointCounts, v, &Np)); 14569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(pointCounts, v, &ooff)); 14574bbf5ea8SMatthew G. Knepley if (dof <= 0) continue; 14584bbf5ea8SMatthew G. Knepley 14594bbf5ea8SMatthew G. Knepley for (k = 0; k < patch->nsubspaces; ++k) { 14604bbf5ea8SMatthew G. Knepley const PetscInt *cellNodeMap = patch->cellNodeMap[k]; 14614bbf5ea8SMatthew G. Knepley PetscInt nodesPerCell = patch->nodesPerCell[k]; 14624bbf5ea8SMatthew G. Knepley PetscInt subspaceOffset = patch->subspaceOffsets[k]; 14634bbf5ea8SMatthew G. Knepley PetscInt bs = patch->bs[k]; 1464d490bb3dSLawrence Mitchell PetscInt goff; 14654bbf5ea8SMatthew G. Knepley 14664bbf5ea8SMatthew G. Knepley for (i = off; i < off + dof; ++i) { 14674bbf5ea8SMatthew G. Knepley /* Reconstruct mapping of global-to-local on this patch. */ 14684bbf5ea8SMatthew G. Knepley const PetscInt c = cellsArray[i]; 14695f824522SMatthew G. Knepley PetscInt cell = c; 14704bbf5ea8SMatthew G. Knepley 14719566063dSJacob Faibussowitsch if (cellNumbering) PetscCall(PetscSectionGetOffset(cellNumbering, c, &cell)); 14724bbf5ea8SMatthew G. Knepley for (j = 0; j < nodesPerCell; ++j) { 14734bbf5ea8SMatthew G. Knepley for (l = 0; l < bs; ++l) { 14745f824522SMatthew G. Knepley const PetscInt globalDof = cellNodeMap[cell * nodesPerCell + j] * bs + l + subspaceOffset; 1475c2e6f3c0SFlorian Wechsung const PetscInt localDof = dofsArray[key]; 14769566063dSJacob Faibussowitsch if (localDof >= 0) PetscCall(PetscHMapISet(ht, globalDof, localDof)); 14770904074fSPatrick Farrell if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) { 1478c2e6f3c0SFlorian Wechsung const PetscInt localDofWithArtificial = dofsArrayWithArtificial[key]; 1479*48a46eb9SPierre Jolivet if (localDofWithArtificial >= 0) PetscCall(PetscHMapISet(htWithArtificial, globalDof, localDofWithArtificial)); 1480c2e6f3c0SFlorian Wechsung } 14810904074fSPatrick Farrell if (isNonlinear) { 14820904074fSPatrick Farrell const PetscInt localDofWithAll = dofsArrayWithAll[key]; 1483*48a46eb9SPierre Jolivet if (localDofWithAll >= 0) PetscCall(PetscHMapISet(htWithAll, globalDof, localDofWithAll)); 14840904074fSPatrick Farrell } 1485c2e6f3c0SFlorian Wechsung key++; 14864bbf5ea8SMatthew G. Knepley } 14874bbf5ea8SMatthew G. Knepley } 14884bbf5ea8SMatthew G. Knepley } 1489557beb66SLawrence Mitchell 14904bbf5ea8SMatthew G. Knepley /* Shove it in the output data structure. */ 14919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(gtolCounts, v, &goff)); 14921b68eb51SMatthew G. Knepley PetscHashIterBegin(ht, hi); 14931b68eb51SMatthew G. Knepley while (!PetscHashIterAtEnd(ht, hi)) { 14944bbf5ea8SMatthew G. Knepley PetscInt globalDof, localDof; 14954bbf5ea8SMatthew G. Knepley 14961b68eb51SMatthew G. Knepley PetscHashIterGetKey(ht, hi, globalDof); 14971b68eb51SMatthew G. Knepley PetscHashIterGetVal(ht, hi, localDof); 14984bbf5ea8SMatthew G. Knepley if (globalDof >= 0) globalDofsArray[goff + localDof] = globalDof; 14991b68eb51SMatthew G. Knepley PetscHashIterNext(ht, hi); 15004bbf5ea8SMatthew G. Knepley } 15015f824522SMatthew G. Knepley 15020904074fSPatrick Farrell if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) { 15039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(gtolCountsWithArtificial, v, &goff)); 1504c2e6f3c0SFlorian Wechsung PetscHashIterBegin(htWithArtificial, hi); 1505c2e6f3c0SFlorian Wechsung while (!PetscHashIterAtEnd(htWithArtificial, hi)) { 1506c2e6f3c0SFlorian Wechsung PetscInt globalDof, localDof; 1507c2e6f3c0SFlorian Wechsung PetscHashIterGetKey(htWithArtificial, hi, globalDof); 1508c2e6f3c0SFlorian Wechsung PetscHashIterGetVal(htWithArtificial, hi, localDof); 1509c2e6f3c0SFlorian Wechsung if (globalDof >= 0) globalDofsArrayWithArtificial[goff + localDof] = globalDof; 1510c2e6f3c0SFlorian Wechsung PetscHashIterNext(htWithArtificial, hi); 1511c2e6f3c0SFlorian Wechsung } 1512c2e6f3c0SFlorian Wechsung } 15130904074fSPatrick Farrell if (isNonlinear) { 15149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(gtolCountsWithAll, v, &goff)); 15150904074fSPatrick Farrell PetscHashIterBegin(htWithAll, hi); 15160904074fSPatrick Farrell while (!PetscHashIterAtEnd(htWithAll, hi)) { 15170904074fSPatrick Farrell PetscInt globalDof, localDof; 15180904074fSPatrick Farrell PetscHashIterGetKey(htWithAll, hi, globalDof); 15190904074fSPatrick Farrell PetscHashIterGetVal(htWithAll, hi, localDof); 15200904074fSPatrick Farrell if (globalDof >= 0) globalDofsArrayWithAll[goff + localDof] = globalDof; 15210904074fSPatrick Farrell PetscHashIterNext(htWithAll, hi); 15220904074fSPatrick Farrell } 15230904074fSPatrick Farrell } 1524c2e6f3c0SFlorian Wechsung 15255f824522SMatthew G. Knepley for (p = 0; p < Np; ++p) { 15265f824522SMatthew G. Knepley const PetscInt point = pointsArray[ooff + p]; 15275f824522SMatthew G. Knepley PetscInt globalDof, localDof; 15285f824522SMatthew G. Knepley 15299566063dSJacob Faibussowitsch PetscCall(PCPatchGetGlobalDofs(pc, patch->dofSection, k, patch->combined, point, NULL, &globalDof)); 15309566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(ht, globalDof, &localDof)); 15315f824522SMatthew G. Knepley offsArray[(ooff + p) * Nf + k] = localDof; 15320904074fSPatrick Farrell if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) { 15339566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(htWithArtificial, globalDof, &localDof)); 1534c2e6f3c0SFlorian Wechsung offsArrayWithArtificial[(ooff + p) * Nf + k] = localDof; 1535c2e6f3c0SFlorian Wechsung } 15360904074fSPatrick Farrell if (isNonlinear) { 15379566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(htWithAll, globalDof, &localDof)); 15380904074fSPatrick Farrell offsArrayWithAll[(ooff + p) * Nf + k] = localDof; 15390904074fSPatrick Farrell } 15405f824522SMatthew G. Knepley } 15414bbf5ea8SMatthew G. Knepley } 15424bbf5ea8SMatthew G. Knepley 15439566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&globalBcs)); 15449566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&ownedpts)); 15459566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&seenpts)); 15469566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&owneddofs)); 15479566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&seendofs)); 15489566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&artificialbcs)); 1549557beb66SLawrence Mitchell 15504bbf5ea8SMatthew G. Knepley /* At this point, we have a hash table ht built that maps globalDof -> localDof. 15514bbf5ea8SMatthew G. Knepley We need to create the dof table laid out cellwise first, then by subspace, 15524bbf5ea8SMatthew G. Knepley as the assembler assembles cell-wise and we need to stuff the different 15534bbf5ea8SMatthew G. Knepley contributions of the different function spaces to the right places. So we loop 15544bbf5ea8SMatthew G. Knepley over cells, then over subspaces. */ 15554bbf5ea8SMatthew G. Knepley if (patch->nsubspaces > 1) { /* for nsubspaces = 1, data we need is already in dofsArray */ 15564bbf5ea8SMatthew G. Knepley for (i = off; i < off + dof; ++i) { 15574bbf5ea8SMatthew G. Knepley const PetscInt c = cellsArray[i]; 15585f824522SMatthew G. Knepley PetscInt cell = c; 15594bbf5ea8SMatthew G. Knepley 15609566063dSJacob Faibussowitsch if (cellNumbering) PetscCall(PetscSectionGetOffset(cellNumbering, c, &cell)); 15614bbf5ea8SMatthew G. Knepley for (k = 0; k < patch->nsubspaces; ++k) { 15624bbf5ea8SMatthew G. Knepley const PetscInt *cellNodeMap = patch->cellNodeMap[k]; 15634bbf5ea8SMatthew G. Knepley PetscInt nodesPerCell = patch->nodesPerCell[k]; 15644bbf5ea8SMatthew G. Knepley PetscInt subspaceOffset = patch->subspaceOffsets[k]; 15654bbf5ea8SMatthew G. Knepley PetscInt bs = patch->bs[k]; 15664bbf5ea8SMatthew G. Knepley 15674bbf5ea8SMatthew G. Knepley for (j = 0; j < nodesPerCell; ++j) { 15684bbf5ea8SMatthew G. Knepley for (l = 0; l < bs; ++l) { 15695f824522SMatthew G. Knepley const PetscInt globalDof = cellNodeMap[cell * nodesPerCell + j] * bs + l + subspaceOffset; 15704bbf5ea8SMatthew G. Knepley PetscInt localDof; 15714bbf5ea8SMatthew G. Knepley 15729566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(ht, globalDof, &localDof)); 1573557beb66SLawrence Mitchell /* If it's not in the hash table, i.e. is a BC dof, 15741b68eb51SMatthew G. Knepley then the PetscHSetIMap above gives -1, which matches 1575557beb66SLawrence Mitchell exactly the convention for PETSc's matrix assembly to 1576557beb66SLawrence Mitchell ignore the dof. So we don't need to do anything here */ 1577c2e6f3c0SFlorian Wechsung asmArray[asmKey] = localDof; 15780904074fSPatrick Farrell if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) { 15799566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(htWithArtificial, globalDof, &localDof)); 1580c2e6f3c0SFlorian Wechsung asmArrayWithArtificial[asmKey] = localDof; 1581c2e6f3c0SFlorian Wechsung } 15820904074fSPatrick Farrell if (isNonlinear) { 15839566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(htWithAll, globalDof, &localDof)); 15840904074fSPatrick Farrell asmArrayWithAll[asmKey] = localDof; 15850904074fSPatrick Farrell } 1586c2e6f3c0SFlorian Wechsung asmKey++; 15874bbf5ea8SMatthew G. Knepley } 15884bbf5ea8SMatthew G. Knepley } 15894bbf5ea8SMatthew G. Knepley } 15904bbf5ea8SMatthew G. Knepley } 15914bbf5ea8SMatthew G. Knepley } 15924bbf5ea8SMatthew G. Knepley } 1593c2e6f3c0SFlorian Wechsung if (1 == patch->nsubspaces) { 15949566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(asmArray, dofsArray, numDofs)); 1595*48a46eb9SPierre Jolivet if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) PetscCall(PetscArraycpy(asmArrayWithArtificial, dofsArrayWithArtificial, numDofs)); 15961baa6e33SBarry Smith if (isNonlinear) PetscCall(PetscArraycpy(asmArrayWithAll, dofsArrayWithAll, numDofs)); 1597c2e6f3c0SFlorian Wechsung } 15984bbf5ea8SMatthew G. Knepley 15999566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&ht)); 16009566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&htWithArtificial)); 16019566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&htWithAll)); 16029566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(cells, &cellsArray)); 16039566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(points, &pointsArray)); 16049566063dSJacob Faibussowitsch PetscCall(PetscFree(dofsArray)); 1605*48a46eb9SPierre Jolivet if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) PetscCall(PetscFree(dofsArrayWithArtificial)); 16061baa6e33SBarry Smith if (isNonlinear) PetscCall(PetscFree(dofsArrayWithAll)); 16075f824522SMatthew G. Knepley /* Create placeholder section for map from points to patch dofs */ 16089566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &patch->patchSection)); 16099566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(patch->patchSection, patch->nsubspaces)); 16101e5fa6bbSLawrence Mitchell if (patch->combined) { 16111e5fa6bbSLawrence Mitchell PetscInt numFields; 16129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(patch->dofSection[0], &numFields)); 161363a3b9bcSJacob 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); 16149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(patch->dofSection[0], &pStart, &pEnd)); 16159566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(patch->patchSection, pStart, pEnd)); 16165f824522SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 16175f824522SMatthew G. Knepley PetscInt dof, fdof, f; 16185f824522SMatthew G. Knepley 16199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->dofSection[0], p, &dof)); 16209566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(patch->patchSection, p, dof)); 16215f824522SMatthew G. Knepley for (f = 0; f < patch->nsubspaces; ++f) { 16229566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(patch->dofSection[0], p, f, &fdof)); 16239566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(patch->patchSection, p, f, fdof)); 16245f824522SMatthew G. Knepley } 16251e5fa6bbSLawrence Mitchell } 16261e5fa6bbSLawrence Mitchell } else { 16271e5fa6bbSLawrence Mitchell PetscInt pStartf, pEndf, f; 16281e5fa6bbSLawrence Mitchell pStart = PETSC_MAX_INT; 16291e5fa6bbSLawrence Mitchell pEnd = PETSC_MIN_INT; 16301e5fa6bbSLawrence Mitchell for (f = 0; f < patch->nsubspaces; ++f) { 16319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(patch->dofSection[f], &pStartf, &pEndf)); 16321e5fa6bbSLawrence Mitchell pStart = PetscMin(pStart, pStartf); 16331e5fa6bbSLawrence Mitchell pEnd = PetscMax(pEnd, pEndf); 16341e5fa6bbSLawrence Mitchell } 16359566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(patch->patchSection, pStart, pEnd)); 16361e5fa6bbSLawrence Mitchell for (f = 0; f < patch->nsubspaces; ++f) { 16379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(patch->dofSection[f], &pStartf, &pEndf)); 16381e5fa6bbSLawrence Mitchell for (p = pStartf; p < pEndf; ++p) { 16391e5fa6bbSLawrence Mitchell PetscInt fdof; 16409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->dofSection[f], p, &fdof)); 16419566063dSJacob Faibussowitsch PetscCall(PetscSectionAddDof(patch->patchSection, p, fdof)); 16429566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(patch->patchSection, p, f, fdof)); 1643bdd9e0cdSPatrick Farrell } 1644bdd9e0cdSPatrick Farrell } 16455f824522SMatthew G. Knepley } 16469566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(patch->patchSection)); 16479566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUseFieldOffsets(patch->patchSection, PETSC_TRUE)); 16484bbf5ea8SMatthew G. Knepley /* Replace cell indices with firedrake-numbered ones. */ 16499566063dSJacob Faibussowitsch PetscCall(ISGeneralSetIndices(cells, numCells, (const PetscInt *)newCellsArray, PETSC_OWN_POINTER)); 16509566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numGlobalDofs, globalDofsArray, PETSC_OWN_POINTER, &patch->gtol)); 16519566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)patch->gtol, "Global Indices")); 16529566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_g2l_view", patch->classname)); 16539566063dSJacob Faibussowitsch PetscCall(PetscSectionViewFromOptions(patch->gtolCounts, (PetscObject)pc, option)); 16549566063dSJacob Faibussowitsch PetscCall(ISViewFromOptions(patch->gtol, (PetscObject)pc, option)); 16559566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numDofs, asmArray, PETSC_OWN_POINTER, &patch->dofs)); 16569566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numPoints * Nf, offsArray, PETSC_OWN_POINTER, &patch->offs)); 16570904074fSPatrick Farrell if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) { 16589566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numGlobalDofsWithArtificial, globalDofsArrayWithArtificial, PETSC_OWN_POINTER, &patch->gtolWithArtificial)); 16599566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numDofs, asmArrayWithArtificial, PETSC_OWN_POINTER, &patch->dofsWithArtificial)); 16609566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numPoints * Nf, offsArrayWithArtificial, PETSC_OWN_POINTER, &patch->offsWithArtificial)); 1661c2e6f3c0SFlorian Wechsung } 16620904074fSPatrick Farrell if (isNonlinear) { 16639566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numGlobalDofsWithAll, globalDofsArrayWithAll, PETSC_OWN_POINTER, &patch->gtolWithAll)); 16649566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numDofs, asmArrayWithAll, PETSC_OWN_POINTER, &patch->dofsWithAll)); 16659566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numPoints * Nf, offsArrayWithAll, PETSC_OWN_POINTER, &patch->offsWithAll)); 16660904074fSPatrick Farrell } 16674bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 16684bbf5ea8SMatthew G. Knepley } 16694bbf5ea8SMatthew G. Knepley 16709371c9d4SSatish Balay static PetscErrorCode PCPatchCreateMatrix_Private(PC pc, PetscInt point, Mat *mat, PetscBool withArtificial) { 16714bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 16724bbf5ea8SMatthew G. Knepley PetscBool flg; 16734bbf5ea8SMatthew G. Knepley PetscInt csize, rsize; 16744bbf5ea8SMatthew G. Knepley const char *prefix = NULL; 16754bbf5ea8SMatthew G. Knepley 16764bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 1677c2e6f3c0SFlorian Wechsung if (withArtificial) { 1678e047a90bSFlorian Wechsung /* would be nice if we could create a rectangular matrix of size numDofsWithArtificial x numDofs here */ 16799d4fc724SLawrence Mitchell PetscInt pStart; 16809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(patch->gtolCountsWithArtificial, &pStart, NULL)); 16819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCountsWithArtificial, point + pStart, &rsize)); 16829d4fc724SLawrence Mitchell csize = rsize; 1683ff201f6aSFlorian Wechsung } else { 16849d4fc724SLawrence Mitchell PetscInt pStart; 16859566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(patch->gtolCounts, &pStart, NULL)); 16869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCounts, point + pStart, &rsize)); 16879d4fc724SLawrence Mitchell csize = rsize; 1688c2e6f3c0SFlorian Wechsung } 1689c2e6f3c0SFlorian Wechsung 16909566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, mat)); 16919566063dSJacob Faibussowitsch PetscCall(PCGetOptionsPrefix(pc, &prefix)); 16929566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(*mat, prefix)); 16939566063dSJacob Faibussowitsch PetscCall(MatAppendOptionsPrefix(*mat, "pc_patch_sub_")); 16949566063dSJacob Faibussowitsch if (patch->sub_mat_type) PetscCall(MatSetType(*mat, patch->sub_mat_type)); 16959566063dSJacob Faibussowitsch else if (!patch->sub_mat_type) PetscCall(MatSetType(*mat, MATDENSE)); 16969566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mat, rsize, csize, rsize, csize)); 16979566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)*mat, MATDENSE, &flg)); 16989566063dSJacob Faibussowitsch if (!flg) PetscCall(PetscObjectTypeCompare((PetscObject)*mat, MATSEQDENSE, &flg)); 16994bbf5ea8SMatthew G. Knepley /* Sparse patch matrices */ 17004bbf5ea8SMatthew G. Knepley if (!flg) { 17014bbf5ea8SMatthew G. Knepley PetscBT bt; 17024bbf5ea8SMatthew G. Knepley PetscInt *dnnz = NULL; 17034bbf5ea8SMatthew G. Knepley const PetscInt *dofsArray = NULL; 17044bbf5ea8SMatthew G. Knepley PetscInt pStart, pEnd, ncell, offset, c, i, j; 17054bbf5ea8SMatthew G. Knepley 1706c2e6f3c0SFlorian Wechsung if (withArtificial) { 17079566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->dofsWithArtificial, &dofsArray)); 1708ff201f6aSFlorian Wechsung } else { 17099566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->dofs, &dofsArray)); 1710c2e6f3c0SFlorian Wechsung } 17119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(patch->cellCounts, &pStart, &pEnd)); 17124bbf5ea8SMatthew G. Knepley point += pStart; 171363a3b9bcSJacob Faibussowitsch PetscCheck(point < pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Operator point %" PetscInt_FMT " not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, pStart, pEnd); 17149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->cellCounts, point, &ncell)); 17159566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->cellCounts, point, &offset)); 17169566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_Patch_Prealloc, pc, 0, 0, 0)); 1717b2866507SPatrick Farrell /* A PetscBT uses N^2 bits to store the sparsity pattern on a 17184bbf5ea8SMatthew G. Knepley * patch. This is probably OK if the patches are not too big, 1719b2866507SPatrick Farrell * but uses too much memory. We therefore switch based on rsize. */ 1720b2866507SPatrick Farrell if (rsize < 3000) { /* FIXME: I picked this switch value out of my hat */ 1721d63cebbaSPatrick Farrell PetscScalar *zeroes; 1722d63cebbaSPatrick Farrell PetscInt rows; 1723d63cebbaSPatrick Farrell 17249566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(rsize, &dnnz)); 17259566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(rsize * rsize, &bt)); 17264bbf5ea8SMatthew G. Knepley for (c = 0; c < ncell; ++c) { 17274bbf5ea8SMatthew G. Knepley const PetscInt *idx = dofsArray + (offset + c) * patch->totalDofsPerCell; 17284bbf5ea8SMatthew G. Knepley for (i = 0; i < patch->totalDofsPerCell; ++i) { 17294bbf5ea8SMatthew G. Knepley const PetscInt row = idx[i]; 1730557beb66SLawrence Mitchell if (row < 0) continue; 17314bbf5ea8SMatthew G. Knepley for (j = 0; j < patch->totalDofsPerCell; ++j) { 17324bbf5ea8SMatthew G. Knepley const PetscInt col = idx[j]; 17334bbf5ea8SMatthew G. Knepley const PetscInt key = row * rsize + col; 1734557beb66SLawrence Mitchell if (col < 0) continue; 17354bbf5ea8SMatthew G. Knepley if (!PetscBTLookupSet(bt, key)) ++dnnz[row]; 17364bbf5ea8SMatthew G. Knepley } 17374bbf5ea8SMatthew G. Knepley } 17384bbf5ea8SMatthew G. Knepley } 1739d63cebbaSPatrick Farrell 1740d63cebbaSPatrick Farrell if (patch->usercomputeopintfacet) { 1741d63cebbaSPatrick Farrell const PetscInt *intFacetsArray = NULL; 1742d63cebbaSPatrick Farrell PetscInt i, numIntFacets, intFacetOffset; 1743d63cebbaSPatrick Farrell const PetscInt *facetCells = NULL; 1744d63cebbaSPatrick Farrell 17459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->intFacetCounts, point, &numIntFacets)); 17469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->intFacetCounts, point, &intFacetOffset)); 17479566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->intFacetsToPatchCell, &facetCells)); 17489566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->intFacets, &intFacetsArray)); 1749d63cebbaSPatrick Farrell for (i = 0; i < numIntFacets; i++) { 1750d63cebbaSPatrick Farrell const PetscInt cell0 = facetCells[2 * (intFacetOffset + i) + 0]; 1751d63cebbaSPatrick Farrell const PetscInt cell1 = facetCells[2 * (intFacetOffset + i) + 1]; 1752d63cebbaSPatrick Farrell PetscInt celli, cellj; 1753d63cebbaSPatrick Farrell 1754d63cebbaSPatrick Farrell for (celli = 0; celli < patch->totalDofsPerCell; celli++) { 1755d63cebbaSPatrick Farrell const PetscInt row = dofsArray[(offset + cell0) * patch->totalDofsPerCell + celli]; 1756b5c64f08SPatrick Farrell if (row < 0) continue; 1757d63cebbaSPatrick Farrell for (cellj = 0; cellj < patch->totalDofsPerCell; cellj++) { 1758d63cebbaSPatrick Farrell const PetscInt col = dofsArray[(offset + cell1) * patch->totalDofsPerCell + cellj]; 1759d63cebbaSPatrick Farrell const PetscInt key = row * rsize + col; 1760d63cebbaSPatrick Farrell if (col < 0) continue; 1761d63cebbaSPatrick Farrell if (!PetscBTLookupSet(bt, key)) ++dnnz[row]; 1762d63cebbaSPatrick Farrell } 1763d63cebbaSPatrick Farrell } 1764d63cebbaSPatrick Farrell 1765d63cebbaSPatrick Farrell for (celli = 0; celli < patch->totalDofsPerCell; celli++) { 1766d63cebbaSPatrick Farrell const PetscInt row = dofsArray[(offset + cell1) * patch->totalDofsPerCell + celli]; 1767b5c64f08SPatrick Farrell if (row < 0) continue; 1768d63cebbaSPatrick Farrell for (cellj = 0; cellj < patch->totalDofsPerCell; cellj++) { 1769d63cebbaSPatrick Farrell const PetscInt col = dofsArray[(offset + cell0) * patch->totalDofsPerCell + cellj]; 1770d63cebbaSPatrick Farrell const PetscInt key = row * rsize + col; 1771d63cebbaSPatrick Farrell if (col < 0) continue; 1772d63cebbaSPatrick Farrell if (!PetscBTLookupSet(bt, key)) ++dnnz[row]; 1773d63cebbaSPatrick Farrell } 1774d63cebbaSPatrick Farrell } 1775d63cebbaSPatrick Farrell } 1776d63cebbaSPatrick Farrell } 17779566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&bt)); 17789566063dSJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(*mat, 1, dnnz, NULL, NULL, NULL)); 17799566063dSJacob Faibussowitsch PetscCall(PetscFree(dnnz)); 1780d63cebbaSPatrick Farrell 17819566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(patch->totalDofsPerCell * patch->totalDofsPerCell, &zeroes)); 1782d63cebbaSPatrick Farrell for (c = 0; c < ncell; ++c) { 1783d63cebbaSPatrick Farrell const PetscInt *idx = &dofsArray[(offset + c) * patch->totalDofsPerCell]; 17849566063dSJacob Faibussowitsch PetscCall(MatSetValues(*mat, patch->totalDofsPerCell, idx, patch->totalDofsPerCell, idx, zeroes, INSERT_VALUES)); 1785d63cebbaSPatrick Farrell } 17869566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(*mat, &rows, NULL)); 1787*48a46eb9SPierre Jolivet for (i = 0; i < rows; ++i) PetscCall(MatSetValues(*mat, 1, &i, 1, &i, zeroes, INSERT_VALUES)); 1788d63cebbaSPatrick Farrell 1789d63cebbaSPatrick Farrell if (patch->usercomputeopintfacet) { 1790d63cebbaSPatrick Farrell const PetscInt *intFacetsArray = NULL; 1791d63cebbaSPatrick Farrell PetscInt i, numIntFacets, intFacetOffset; 1792d63cebbaSPatrick Farrell const PetscInt *facetCells = NULL; 1793d63cebbaSPatrick Farrell 17949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->intFacetCounts, point, &numIntFacets)); 17959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->intFacetCounts, point, &intFacetOffset)); 17969566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->intFacetsToPatchCell, &facetCells)); 17979566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->intFacets, &intFacetsArray)); 1798d63cebbaSPatrick Farrell for (i = 0; i < numIntFacets; i++) { 1799d63cebbaSPatrick Farrell const PetscInt cell0 = facetCells[2 * (intFacetOffset + i) + 0]; 1800d63cebbaSPatrick Farrell const PetscInt cell1 = facetCells[2 * (intFacetOffset + i) + 1]; 1801d63cebbaSPatrick Farrell const PetscInt *cell0idx = &dofsArray[(offset + cell0) * patch->totalDofsPerCell]; 1802d63cebbaSPatrick Farrell const PetscInt *cell1idx = &dofsArray[(offset + cell1) * patch->totalDofsPerCell]; 18039566063dSJacob Faibussowitsch PetscCall(MatSetValues(*mat, patch->totalDofsPerCell, cell0idx, patch->totalDofsPerCell, cell1idx, zeroes, INSERT_VALUES)); 18049566063dSJacob Faibussowitsch PetscCall(MatSetValues(*mat, patch->totalDofsPerCell, cell1idx, patch->totalDofsPerCell, cell0idx, zeroes, INSERT_VALUES)); 1805d63cebbaSPatrick Farrell } 1806d63cebbaSPatrick Farrell } 1807d63cebbaSPatrick Farrell 18089566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*mat, MAT_FINAL_ASSEMBLY)); 18099566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*mat, MAT_FINAL_ASSEMBLY)); 1810d63cebbaSPatrick Farrell 18119566063dSJacob Faibussowitsch PetscCall(PetscFree(zeroes)); 1812d63cebbaSPatrick Farrell 1813b2866507SPatrick Farrell } else { /* rsize too big, use MATPREALLOCATOR */ 1814b2866507SPatrick Farrell Mat preallocator; 1815b2866507SPatrick Farrell PetscScalar *vals; 1816b2866507SPatrick Farrell 18179566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(patch->totalDofsPerCell * patch->totalDofsPerCell, &vals)); 18189566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &preallocator)); 18199566063dSJacob Faibussowitsch PetscCall(MatSetType(preallocator, MATPREALLOCATOR)); 18209566063dSJacob Faibussowitsch PetscCall(MatSetSizes(preallocator, rsize, rsize, rsize, rsize)); 18219566063dSJacob Faibussowitsch PetscCall(MatSetUp(preallocator)); 182211bcd083SPatrick Farrell 1823b2866507SPatrick Farrell for (c = 0; c < ncell; ++c) { 1824b2866507SPatrick Farrell const PetscInt *idx = dofsArray + (offset + c) * patch->totalDofsPerCell; 18259566063dSJacob Faibussowitsch PetscCall(MatSetValues(preallocator, patch->totalDofsPerCell, idx, patch->totalDofsPerCell, idx, vals, INSERT_VALUES)); 1826b2866507SPatrick Farrell } 182711bcd083SPatrick Farrell 182811bcd083SPatrick Farrell if (patch->usercomputeopintfacet) { 182911bcd083SPatrick Farrell const PetscInt *intFacetsArray = NULL; 183011bcd083SPatrick Farrell PetscInt i, numIntFacets, intFacetOffset; 183111bcd083SPatrick Farrell const PetscInt *facetCells = NULL; 183211bcd083SPatrick Farrell 18339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->intFacetCounts, point, &numIntFacets)); 18349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->intFacetCounts, point, &intFacetOffset)); 18359566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->intFacetsToPatchCell, &facetCells)); 18369566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->intFacets, &intFacetsArray)); 183711bcd083SPatrick Farrell for (i = 0; i < numIntFacets; i++) { 183811bcd083SPatrick Farrell const PetscInt cell0 = facetCells[2 * (intFacetOffset + i) + 0]; 183911bcd083SPatrick Farrell const PetscInt cell1 = facetCells[2 * (intFacetOffset + i) + 1]; 184011bcd083SPatrick Farrell const PetscInt *cell0idx = &dofsArray[(offset + cell0) * patch->totalDofsPerCell]; 184111bcd083SPatrick Farrell const PetscInt *cell1idx = &dofsArray[(offset + cell1) * patch->totalDofsPerCell]; 18429566063dSJacob Faibussowitsch PetscCall(MatSetValues(preallocator, patch->totalDofsPerCell, cell0idx, patch->totalDofsPerCell, cell1idx, vals, INSERT_VALUES)); 18439566063dSJacob Faibussowitsch PetscCall(MatSetValues(preallocator, patch->totalDofsPerCell, cell1idx, patch->totalDofsPerCell, cell0idx, vals, INSERT_VALUES)); 184411bcd083SPatrick Farrell } 184511bcd083SPatrick Farrell } 184611bcd083SPatrick Farrell 18479566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 18489566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(preallocator, MAT_FINAL_ASSEMBLY)); 18499566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(preallocator, MAT_FINAL_ASSEMBLY)); 18509566063dSJacob Faibussowitsch PetscCall(MatPreallocatorPreallocate(preallocator, PETSC_TRUE, *mat)); 18519566063dSJacob Faibussowitsch PetscCall(MatDestroy(&preallocator)); 1852b2866507SPatrick Farrell } 18539566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_Patch_Prealloc, pc, 0, 0, 0)); 1854fe117d09SFlorian Wechsung if (withArtificial) { 18559566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->dofsWithArtificial, &dofsArray)); 1856fe117d09SFlorian Wechsung } else { 18579566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->dofs, &dofsArray)); 18584bbf5ea8SMatthew G. Knepley } 1859fe117d09SFlorian Wechsung } 18609566063dSJacob Faibussowitsch PetscCall(MatSetUp(*mat)); 18614bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 18624bbf5ea8SMatthew G. Knepley } 18634bbf5ea8SMatthew G. Knepley 18649371c9d4SSatish 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) { 186592d50984SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 1866b6bb21d1SLawrence Mitchell DM dm, plex; 186792d50984SMatthew G. Knepley PetscSection s; 186892d50984SMatthew G. Knepley const PetscInt *parray, *oarray; 186992d50984SMatthew G. Knepley PetscInt Nf = patch->nsubspaces, Np, poff, p, f; 187092d50984SMatthew G. Knepley 187192d50984SMatthew G. Knepley PetscFunctionBegin; 187228b400f6SJacob Faibussowitsch PetscCheck(!patch->precomputeElementTensors, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Precomputing element tensors not implemented with DMPlex compute operator"); 18739566063dSJacob Faibussowitsch PetscCall(PCGetDM(pc, &dm)); 18749566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 1875b6bb21d1SLawrence Mitchell dm = plex; 18769566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, &s)); 187792d50984SMatthew G. Knepley /* Set offset into patch */ 18789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->pointCounts, patchNum, &Np)); 18799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->pointCounts, patchNum, &poff)); 18809566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->points, &parray)); 18819566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->offs, &oarray)); 188292d50984SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 188392d50984SMatthew G. Knepley for (p = 0; p < Np; ++p) { 188492d50984SMatthew G. Knepley const PetscInt point = parray[poff + p]; 188592d50984SMatthew G. Knepley PetscInt dof; 188692d50984SMatthew G. Knepley 18879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(patch->patchSection, point, f, &dof)); 18889566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldOffset(patch->patchSection, point, f, oarray[(poff + p) * Nf + f])); 18899566063dSJacob Faibussowitsch if (patch->nsubspaces == 1) PetscCall(PetscSectionSetOffset(patch->patchSection, point, oarray[(poff + p) * Nf + f])); 18909566063dSJacob Faibussowitsch else PetscCall(PetscSectionSetOffset(patch->patchSection, point, -1)); 189192d50984SMatthew G. Knepley } 189292d50984SMatthew G. Knepley } 18939566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->points, &parray)); 18949566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->offs, &oarray)); 18959566063dSJacob Faibussowitsch if (patch->viewSection) PetscCall(ObjectView((PetscObject)patch->patchSection, patch->viewerSection, patch->formatSection)); 18969566063dSJacob Faibussowitsch PetscCall(DMPlexComputeResidual_Patch_Internal(dm, patch->patchSection, cellIS, 0.0, x, NULL, F, ctx)); 18979566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dm)); 189892d50984SMatthew G. Knepley PetscFunctionReturn(0); 189992d50984SMatthew G. Knepley } 190092d50984SMatthew G. Knepley 19019371c9d4SSatish Balay PetscErrorCode PCPatchComputeFunction_Internal(PC pc, Vec x, Vec F, PetscInt point) { 190292d50984SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 190392d50984SMatthew G. Knepley const PetscInt *dofsArray; 19040904074fSPatrick Farrell const PetscInt *dofsArrayWithAll; 190592d50984SMatthew G. Knepley const PetscInt *cellsArray; 190692d50984SMatthew G. Knepley PetscInt ncell, offset, pStart, pEnd; 190792d50984SMatthew G. Knepley 190892d50984SMatthew G. Knepley PetscFunctionBegin; 19099566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_Patch_ComputeOp, pc, 0, 0, 0)); 1910ef1023bdSBarry Smith PetscCheck(patch->usercomputeop, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call PCPatchSetComputeOperator() to set callback"); 19119566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->dofs, &dofsArray)); 19129566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->dofsWithAll, &dofsArrayWithAll)); 19139566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->cells, &cellsArray)); 19149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(patch->cellCounts, &pStart, &pEnd)); 191592d50984SMatthew G. Knepley 191692d50984SMatthew G. Knepley point += pStart; 191763a3b9bcSJacob Faibussowitsch PetscCheck(point < pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Operator point %" PetscInt_FMT " not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, pStart, pEnd); 191892d50984SMatthew G. Knepley 19199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->cellCounts, point, &ncell)); 19209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->cellCounts, point, &offset)); 192192d50984SMatthew G. Knepley if (ncell <= 0) { 19229566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_Patch_ComputeOp, pc, 0, 0, 0)); 192392d50984SMatthew G. Knepley PetscFunctionReturn(0); 192492d50984SMatthew G. Knepley } 19259566063dSJacob Faibussowitsch PetscCall(VecSet(F, 0.0)); 192692d50984SMatthew G. Knepley /* Cannot reuse the same IS because the geometry info is being cached in it */ 19279566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ncell, cellsArray + offset, PETSC_USE_POINTER, &patch->cellIS)); 1928792fecdfSBarry 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)); 19299566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->cellIS)); 19309566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->dofs, &dofsArray)); 19319566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->dofsWithAll, &dofsArrayWithAll)); 19329566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->cells, &cellsArray)); 193392d50984SMatthew G. Knepley if (patch->viewMatrix) { 193492d50984SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 193592d50984SMatthew G. Knepley 193663a3b9bcSJacob Faibussowitsch PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN - 1, "Patch vector for Point %" PetscInt_FMT, point)); 19379566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)F, name)); 19389566063dSJacob Faibussowitsch PetscCall(ObjectView((PetscObject)F, patch->viewerMatrix, patch->formatMatrix)); 193992d50984SMatthew G. Knepley } 19409566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_Patch_ComputeOp, pc, 0, 0, 0)); 194192d50984SMatthew G. Knepley PetscFunctionReturn(0); 194292d50984SMatthew G. Knepley } 194392d50984SMatthew G. Knepley 19449371c9d4SSatish 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) { 19455f824522SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 1946b6bb21d1SLawrence Mitchell DM dm, plex; 19475f824522SMatthew G. Knepley PetscSection s; 19485f824522SMatthew G. Knepley const PetscInt *parray, *oarray; 19495f824522SMatthew G. Knepley PetscInt Nf = patch->nsubspaces, Np, poff, p, f; 19505f824522SMatthew G. Knepley 19515f824522SMatthew G. Knepley PetscFunctionBegin; 19529566063dSJacob Faibussowitsch PetscCall(PCGetDM(pc, &dm)); 19539566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 1954b6bb21d1SLawrence Mitchell dm = plex; 19559566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, &s)); 19565f824522SMatthew G. Knepley /* Set offset into patch */ 19579566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->pointCounts, patchNum, &Np)); 19589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->pointCounts, patchNum, &poff)); 19599566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->points, &parray)); 19609566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->offs, &oarray)); 19615f824522SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 19625f824522SMatthew G. Knepley for (p = 0; p < Np; ++p) { 19635f824522SMatthew G. Knepley const PetscInt point = parray[poff + p]; 19645f824522SMatthew G. Knepley PetscInt dof; 19655f824522SMatthew G. Knepley 19669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(patch->patchSection, point, f, &dof)); 19679566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldOffset(patch->patchSection, point, f, oarray[(poff + p) * Nf + f])); 19689566063dSJacob Faibussowitsch if (patch->nsubspaces == 1) PetscCall(PetscSectionSetOffset(patch->patchSection, point, oarray[(poff + p) * Nf + f])); 19699566063dSJacob Faibussowitsch else PetscCall(PetscSectionSetOffset(patch->patchSection, point, -1)); 19705f824522SMatthew G. Knepley } 19715f824522SMatthew G. Knepley } 19729566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->points, &parray)); 19739566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->offs, &oarray)); 19749566063dSJacob Faibussowitsch if (patch->viewSection) PetscCall(ObjectView((PetscObject)patch->patchSection, patch->viewerSection, patch->formatSection)); 19755f824522SMatthew G. Knepley /* TODO Shut off MatViewFromOptions() in MatAssemblyEnd() here */ 19769566063dSJacob Faibussowitsch PetscCall(DMPlexComputeJacobian_Patch_Internal(dm, patch->patchSection, patch->patchSection, cellIS, 0.0, 0.0, x, NULL, J, J, ctx)); 19779566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dm)); 19785f824522SMatthew G. Knepley PetscFunctionReturn(0); 19795f824522SMatthew G. Knepley } 19805f824522SMatthew G. Knepley 1981a685ae26SLawrence Mitchell /* This function zeros mat on entry */ 19829371c9d4SSatish Balay PetscErrorCode PCPatchComputeOperator_Internal(PC pc, Vec x, Mat mat, PetscInt point, PetscBool withArtificial) { 19834bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 19844bbf5ea8SMatthew G. Knepley const PetscInt *dofsArray; 19850904074fSPatrick Farrell const PetscInt *dofsArrayWithAll = NULL; 19864bbf5ea8SMatthew G. Knepley const PetscInt *cellsArray; 1987eb62eeaaSLawrence Mitchell PetscInt ncell, offset, pStart, pEnd, numIntFacets, intFacetOffset; 19884d04e9f1SPatrick Farrell PetscBool isNonlinear; 19894bbf5ea8SMatthew G. Knepley 19904bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 19919566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_Patch_ComputeOp, pc, 0, 0, 0)); 1992debbdec3SPatrick Farrell isNonlinear = patch->isNonlinear; 1993ef1023bdSBarry Smith PetscCheck(patch->usercomputeop, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call PCPatchSetComputeOperator() to set callback"); 1994c2e6f3c0SFlorian Wechsung if (withArtificial) { 19959566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->dofsWithArtificial, &dofsArray)); 1996c2e6f3c0SFlorian Wechsung } else { 19979566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->dofs, &dofsArray)); 1998c2e6f3c0SFlorian Wechsung } 1999*48a46eb9SPierre Jolivet if (isNonlinear) PetscCall(ISGetIndices(patch->dofsWithAll, &dofsArrayWithAll)); 20009566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->cells, &cellsArray)); 20019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(patch->cellCounts, &pStart, &pEnd)); 20024bbf5ea8SMatthew G. Knepley 20034bbf5ea8SMatthew G. Knepley point += pStart; 200463a3b9bcSJacob Faibussowitsch PetscCheck(point < pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Operator point %" PetscInt_FMT " not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", point, pStart, pEnd); 20054bbf5ea8SMatthew G. Knepley 20069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->cellCounts, point, &ncell)); 20079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->cellCounts, point, &offset)); 20084bbf5ea8SMatthew G. Knepley if (ncell <= 0) { 20099566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_Patch_ComputeOp, pc, 0, 0, 0)); 20104bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 20114bbf5ea8SMatthew G. Knepley } 20129566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(mat)); 2013fa84ea4cSLawrence Mitchell if (patch->precomputeElementTensors) { 2014fa84ea4cSLawrence Mitchell PetscInt i; 2015fa84ea4cSLawrence Mitchell PetscInt ndof = patch->totalDofsPerCell; 2016fa84ea4cSLawrence Mitchell const PetscScalar *elementTensors; 2017fa84ea4cSLawrence Mitchell 20189566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(patch->cellMats, &elementTensors)); 2019fa84ea4cSLawrence Mitchell for (i = 0; i < ncell; i++) { 2020fa84ea4cSLawrence Mitchell const PetscInt cell = cellsArray[i + offset]; 2021fa84ea4cSLawrence Mitchell const PetscInt *idx = dofsArray + (offset + i) * ndof; 2022fe988be2SFlorian Wechsung const PetscScalar *v = elementTensors + patch->precomputedTensorLocations[cell] * ndof * ndof; 20239566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, ndof, idx, ndof, idx, v, ADD_VALUES)); 2024fa84ea4cSLawrence Mitchell } 20259566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(patch->cellMats, &elementTensors)); 20269566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 20279566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 2028fa84ea4cSLawrence Mitchell } else { 20292aa6f319SMatthew G. Knepley /* Cannot reuse the same IS because the geometry info is being cached in it */ 20309566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ncell, cellsArray + offset, PETSC_USE_POINTER, &patch->cellIS)); 20319371c9d4SSatish Balay PetscCallBack("PCPatch callback", 20329371c9d4SSatish Balay patch->usercomputeop(pc, point, x, mat, patch->cellIS, ncell * patch->totalDofsPerCell, dofsArray + offset * patch->totalDofsPerCell, dofsArrayWithAll ? dofsArrayWithAll + offset * patch->totalDofsPerCell : NULL, patch->usercomputeopctx)); 2033fa84ea4cSLawrence Mitchell } 203459109abcSLawrence Mitchell if (patch->usercomputeopintfacet) { 20359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->intFacetCounts, point, &numIntFacets)); 20369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->intFacetCounts, point, &intFacetOffset)); 2037eb62eeaaSLawrence Mitchell if (numIntFacets > 0) { 2038eb62eeaaSLawrence Mitchell /* For each interior facet, grab the two cells (in local numbering, and concatenate dof numberings for those cells) */ 2039eb62eeaaSLawrence Mitchell PetscInt *facetDofs = NULL, *facetDofsWithAll = NULL; 2040eb62eeaaSLawrence Mitchell const PetscInt *intFacetsArray = NULL; 2041eb62eeaaSLawrence Mitchell PetscInt idx = 0; 2042eb62eeaaSLawrence Mitchell PetscInt i, c, d; 2043de2d1767SPatrick Farrell PetscInt fStart; 2044b6bb21d1SLawrence Mitchell DM dm, plex; 2045eb62eeaaSLawrence Mitchell IS facetIS = NULL; 2046eb62eeaaSLawrence Mitchell const PetscInt *facetCells = NULL; 20477a50e09dSPatrick Farrell 20489566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->intFacetsToPatchCell, &facetCells)); 20499566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->intFacets, &intFacetsArray)); 20509566063dSJacob Faibussowitsch PetscCall(PCGetDM(pc, &dm)); 20519566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 2052b6bb21d1SLawrence Mitchell dm = plex; 20539566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, NULL)); 2054eb62eeaaSLawrence Mitchell /* FIXME: Pull this malloc out. */ 20559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2 * patch->totalDofsPerCell * numIntFacets, &facetDofs)); 2056*48a46eb9SPierre Jolivet if (dofsArrayWithAll) PetscCall(PetscMalloc1(2 * patch->totalDofsPerCell * numIntFacets, &facetDofsWithAll)); 2057f98464cbSLawrence Mitchell if (patch->precomputeElementTensors) { 2058f98464cbSLawrence Mitchell PetscInt nFacetDof = 2 * patch->totalDofsPerCell; 2059f98464cbSLawrence Mitchell const PetscScalar *elementTensors; 2060f98464cbSLawrence Mitchell 20619566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(patch->intFacetMats, &elementTensors)); 2062f98464cbSLawrence Mitchell 2063f98464cbSLawrence Mitchell for (i = 0; i < numIntFacets; i++) { 2064f98464cbSLawrence Mitchell const PetscInt facet = intFacetsArray[i + intFacetOffset]; 2065de2d1767SPatrick Farrell const PetscScalar *v = elementTensors + patch->precomputedIntFacetTensorLocations[facet - fStart] * nFacetDof * nFacetDof; 2066f98464cbSLawrence Mitchell idx = 0; 2067f98464cbSLawrence Mitchell /* 2068f98464cbSLawrence Mitchell * 0--1 2069f98464cbSLawrence Mitchell * |\-| 2070f98464cbSLawrence Mitchell * |+\| 2071f98464cbSLawrence Mitchell * 2--3 2072f98464cbSLawrence Mitchell * [0, 2, 3, 0, 1, 3] 2073f98464cbSLawrence Mitchell */ 2074f98464cbSLawrence Mitchell for (c = 0; c < 2; c++) { 2075f98464cbSLawrence Mitchell const PetscInt cell = facetCells[2 * (intFacetOffset + i) + c]; 2076f98464cbSLawrence Mitchell for (d = 0; d < patch->totalDofsPerCell; d++) { 2077f98464cbSLawrence Mitchell facetDofs[idx] = dofsArray[(offset + cell) * patch->totalDofsPerCell + d]; 2078f98464cbSLawrence Mitchell idx++; 2079f98464cbSLawrence Mitchell } 2080f98464cbSLawrence Mitchell } 20819566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat, nFacetDof, facetDofs, nFacetDof, facetDofs, v, ADD_VALUES)); 2082f98464cbSLawrence Mitchell } 20839566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(patch->intFacetMats, &elementTensors)); 2084f98464cbSLawrence Mitchell } else { 2085eb62eeaaSLawrence Mitchell /* 2086eb62eeaaSLawrence Mitchell * 0--1 2087eb62eeaaSLawrence Mitchell * |\-| 2088eb62eeaaSLawrence Mitchell * |+\| 2089eb62eeaaSLawrence Mitchell * 2--3 2090eb62eeaaSLawrence Mitchell * [0, 2, 3, 0, 1, 3] 2091eb62eeaaSLawrence Mitchell */ 2092eb62eeaaSLawrence Mitchell for (i = 0; i < numIntFacets; i++) { 2093eb62eeaaSLawrence Mitchell for (c = 0; c < 2; c++) { 2094eb62eeaaSLawrence Mitchell const PetscInt cell = facetCells[2 * (intFacetOffset + i) + c]; 2095eb62eeaaSLawrence Mitchell for (d = 0; d < patch->totalDofsPerCell; d++) { 2096eb62eeaaSLawrence Mitchell facetDofs[idx] = dofsArray[(offset + cell) * patch->totalDofsPerCell + d]; 20979371c9d4SSatish Balay if (dofsArrayWithAll) { facetDofsWithAll[idx] = dofsArrayWithAll[(offset + cell) * patch->totalDofsPerCell + d]; } 2098eb62eeaaSLawrence Mitchell idx++; 2099eb62eeaaSLawrence Mitchell } 2100eb62eeaaSLawrence Mitchell } 2101eb62eeaaSLawrence Mitchell } 21029566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numIntFacets, intFacetsArray + intFacetOffset, PETSC_USE_POINTER, &facetIS)); 21039566063dSJacob Faibussowitsch PetscCall(patch->usercomputeopintfacet(pc, point, x, mat, facetIS, 2 * numIntFacets * patch->totalDofsPerCell, facetDofs, facetDofsWithAll, patch->usercomputeopintfacetctx)); 21049566063dSJacob Faibussowitsch PetscCall(ISDestroy(&facetIS)); 2105f98464cbSLawrence Mitchell } 21069566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->intFacetsToPatchCell, &facetCells)); 21079566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->intFacets, &intFacetsArray)); 21089566063dSJacob Faibussowitsch PetscCall(PetscFree(facetDofs)); 21099566063dSJacob Faibussowitsch PetscCall(PetscFree(facetDofsWithAll)); 21109566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dm)); 2111eb62eeaaSLawrence Mitchell } 211259109abcSLawrence Mitchell } 21136710cc29SPatrick Farrell 21149566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 21159566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); 21166710cc29SPatrick Farrell 2117c73d2cf6SLawrence Mitchell if (!(withArtificial || isNonlinear) && patch->denseinverse) { 2118c73d2cf6SLawrence Mitchell MatFactorInfo info; 2119c73d2cf6SLawrence Mitchell PetscBool flg; 21209566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)mat, MATSEQDENSE, &flg)); 212128b400f6SJacob Faibussowitsch PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Invalid Mat type for dense inverse"); 21229566063dSJacob Faibussowitsch PetscCall(MatFactorInfoInitialize(&info)); 21239566063dSJacob Faibussowitsch PetscCall(MatLUFactor(mat, NULL, NULL, &info)); 21249566063dSJacob Faibussowitsch PetscCall(MatSeqDenseInvertFactors_Private(mat)); 2125c73d2cf6SLawrence Mitchell } 21269566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->cellIS)); 21274d04e9f1SPatrick Farrell if (withArtificial) { 21289566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->dofsWithArtificial, &dofsArray)); 2129c2e6f3c0SFlorian Wechsung } else { 21309566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->dofs, &dofsArray)); 2131c2e6f3c0SFlorian Wechsung } 2132*48a46eb9SPierre Jolivet if (isNonlinear) PetscCall(ISRestoreIndices(patch->dofsWithAll, &dofsArrayWithAll)); 21339566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->cells, &cellsArray)); 21342aa6f319SMatthew G. Knepley if (patch->viewMatrix) { 21352aa6f319SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 21362aa6f319SMatthew G. Knepley 213763a3b9bcSJacob Faibussowitsch PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN - 1, "Patch matrix for Point %" PetscInt_FMT, point)); 21389566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)mat, name)); 21399566063dSJacob Faibussowitsch PetscCall(ObjectView((PetscObject)mat, patch->viewerMatrix, patch->formatMatrix)); 21402aa6f319SMatthew G. Knepley } 21419566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_Patch_ComputeOp, pc, 0, 0, 0)); 21424bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 21434bbf5ea8SMatthew G. Knepley } 21444bbf5ea8SMatthew G. Knepley 21459371c9d4SSatish Balay static PetscErrorCode MatSetValues_PCPatch_Private(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar *v, InsertMode addv) { 2146fa84ea4cSLawrence Mitchell Vec data; 2147fa84ea4cSLawrence Mitchell PetscScalar *array; 2148fe988be2SFlorian Wechsung PetscInt bs, nz, i, j, cell; 2149fa84ea4cSLawrence Mitchell 21509566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(mat, &data)); 21519566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(data, &bs)); 21529566063dSJacob Faibussowitsch PetscCall(VecGetSize(data, &nz)); 21539566063dSJacob Faibussowitsch PetscCall(VecGetArray(data, &array)); 215408401ef6SPierre Jolivet PetscCheck(m == n, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Only for square insertion"); 215533cbca70SPatrick Farrell cell = (PetscInt)(idxm[0] / bs); /* use the fact that this is called once per cell */ 2156fa84ea4cSLawrence Mitchell for (i = 0; i < m; i++) { 215708401ef6SPierre Jolivet PetscCheck(idxm[i] == idxn[i], PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Row and column indices must match!"); 2158fa84ea4cSLawrence Mitchell for (j = 0; j < n; j++) { 2159fa84ea4cSLawrence Mitchell const PetscScalar v_ = v[i * bs + j]; 2160fa84ea4cSLawrence Mitchell /* Indexing is special to the data structure we have! */ 2161fa84ea4cSLawrence Mitchell if (addv == INSERT_VALUES) { 2162fe988be2SFlorian Wechsung array[cell * bs * bs + i * bs + j] = v_; 2163fa84ea4cSLawrence Mitchell } else { 2164fe988be2SFlorian Wechsung array[cell * bs * bs + i * bs + j] += v_; 2165fa84ea4cSLawrence Mitchell } 2166fa84ea4cSLawrence Mitchell } 2167fa84ea4cSLawrence Mitchell } 21689566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(data, &array)); 2169fa84ea4cSLawrence Mitchell PetscFunctionReturn(0); 2170fa84ea4cSLawrence Mitchell } 2171fa84ea4cSLawrence Mitchell 21729371c9d4SSatish Balay static PetscErrorCode PCPatchPrecomputePatchTensors_Private(PC pc) { 2173fa84ea4cSLawrence Mitchell PC_PATCH *patch = (PC_PATCH *)pc->data; 2174fa84ea4cSLawrence Mitchell const PetscInt *cellsArray; 2175fa84ea4cSLawrence Mitchell PetscInt ncell, offset; 2176fa84ea4cSLawrence Mitchell const PetscInt *dofMapArray; 2177fa84ea4cSLawrence Mitchell PetscInt i, j; 2178fa84ea4cSLawrence Mitchell IS dofMap; 2179fa84ea4cSLawrence Mitchell IS cellIS; 2180fa84ea4cSLawrence Mitchell const PetscInt ndof = patch->totalDofsPerCell; 2181fa84ea4cSLawrence Mitchell Mat vecMat; 2182fe988be2SFlorian Wechsung PetscInt cStart, cEnd; 2183fe988be2SFlorian Wechsung DM dm, plex; 2184fe988be2SFlorian Wechsung 21859566063dSJacob Faibussowitsch PetscCall(ISGetSize(patch->cells, &ncell)); 2186e9c2c94bSFlorian Wechsung if (!ncell) { /* No cells to assemble over -> skip */ 2187e9c2c94bSFlorian Wechsung PetscFunctionReturn(0); 2188e9c2c94bSFlorian Wechsung } 2189e9c2c94bSFlorian Wechsung 21909566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_Patch_ComputeOp, pc, 0, 0, 0)); 2191fa84ea4cSLawrence Mitchell 21929566063dSJacob Faibussowitsch PetscCall(PCGetDM(pc, &dm)); 21939566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 2194b6bb21d1SLawrence Mitchell dm = plex; 2195fa84ea4cSLawrence Mitchell if (!patch->allCells) { 2196fa84ea4cSLawrence Mitchell PetscHSetI cells; 2197fa84ea4cSLawrence Mitchell PetscHashIter hi; 2198fa84ea4cSLawrence Mitchell PetscInt pStart, pEnd; 2199fa84ea4cSLawrence Mitchell PetscInt *allCells = NULL; 22009566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&cells)); 22019566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->cells, &cellsArray)); 22029566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(patch->cellCounts, &pStart, &pEnd)); 2203fa84ea4cSLawrence Mitchell for (i = pStart; i < pEnd; i++) { 22049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->cellCounts, i, &ncell)); 22059566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->cellCounts, i, &offset)); 2206fa84ea4cSLawrence Mitchell if (ncell <= 0) continue; 2207*48a46eb9SPierre Jolivet for (j = 0; j < ncell; j++) PetscCall(PetscHSetIAdd(cells, cellsArray[offset + j])); 2208fa84ea4cSLawrence Mitchell } 22099566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->cells, &cellsArray)); 22109566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(cells, &ncell)); 22119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncell, &allCells)); 22129566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 22139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(cEnd - cStart, &patch->precomputedTensorLocations)); 2214fa84ea4cSLawrence Mitchell i = 0; 2215fa84ea4cSLawrence Mitchell PetscHashIterBegin(cells, hi); 2216fa84ea4cSLawrence Mitchell while (!PetscHashIterAtEnd(cells, hi)) { 2217fe988be2SFlorian Wechsung PetscHashIterGetKey(cells, hi, allCells[i]); 2218fe988be2SFlorian Wechsung patch->precomputedTensorLocations[allCells[i]] = i; 2219fa84ea4cSLawrence Mitchell PetscHashIterNext(cells, hi); 2220fe988be2SFlorian Wechsung i++; 2221fa84ea4cSLawrence Mitchell } 22229566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&cells)); 22239566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ncell, allCells, PETSC_OWN_POINTER, &patch->allCells)); 2224fa84ea4cSLawrence Mitchell } 22259566063dSJacob Faibussowitsch PetscCall(ISGetSize(patch->allCells, &ncell)); 2226fa84ea4cSLawrence Mitchell if (!patch->cellMats) { 22279566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, ncell * ndof * ndof, &patch->cellMats)); 22289566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(patch->cellMats, ndof)); 2229fa84ea4cSLawrence Mitchell } 22309566063dSJacob Faibussowitsch PetscCall(VecSet(patch->cellMats, 0)); 2231fa84ea4cSLawrence Mitchell 2232d0609cedSBarry Smith PetscCall(MatCreateShell(PETSC_COMM_SELF, ncell * ndof, ncell * ndof, ncell * ndof, ncell * ndof, (void *)patch->cellMats, &vecMat)); 22339566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(vecMat, MATOP_SET_VALUES, (void (*)(void)) & MatSetValues_PCPatch_Private)); 22349566063dSJacob Faibussowitsch PetscCall(ISGetSize(patch->allCells, &ncell)); 22359566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, ndof * ncell, 0, 1, &dofMap)); 22369566063dSJacob Faibussowitsch PetscCall(ISGetIndices(dofMap, &dofMapArray)); 22379566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->allCells, &cellsArray)); 22389566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ncell, cellsArray, PETSC_USE_POINTER, &cellIS)); 2239fa84ea4cSLawrence Mitchell /* TODO: Fix for DMPlex compute op, this bypasses a lot of the machinery and just assembles every element tensor. */ 2240792fecdfSBarry Smith PetscCallBack("PCPatch callback", patch->usercomputeop(pc, -1, NULL, vecMat, cellIS, ndof * ncell, dofMapArray, NULL, patch->usercomputeopctx)); 22419566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cellIS)); 22429566063dSJacob Faibussowitsch PetscCall(MatDestroy(&vecMat)); 22439566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->allCells, &cellsArray)); 22449566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(dofMap, &dofMapArray)); 22459566063dSJacob Faibussowitsch PetscCall(ISDestroy(&dofMap)); 2246f98464cbSLawrence Mitchell 2247f98464cbSLawrence Mitchell if (patch->usercomputeopintfacet) { 2248f98464cbSLawrence Mitchell PetscInt nIntFacets; 2249f98464cbSLawrence Mitchell IS intFacetsIS; 2250f98464cbSLawrence Mitchell const PetscInt *intFacetsArray = NULL; 2251f98464cbSLawrence Mitchell if (!patch->allIntFacets) { 2252f98464cbSLawrence Mitchell PetscHSetI facets; 2253f98464cbSLawrence Mitchell PetscHashIter hi; 2254f98464cbSLawrence Mitchell PetscInt pStart, pEnd, fStart, fEnd; 2255f98464cbSLawrence Mitchell PetscInt *allIntFacets = NULL; 22569566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&facets)); 22579566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->intFacets, &intFacetsArray)); 22589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(patch->intFacetCounts, &pStart, &pEnd)); 22599566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 2260f98464cbSLawrence Mitchell for (i = pStart; i < pEnd; i++) { 22619566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->intFacetCounts, i, &nIntFacets)); 22629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->intFacetCounts, i, &offset)); 2263f98464cbSLawrence Mitchell if (nIntFacets <= 0) continue; 2264*48a46eb9SPierre Jolivet for (j = 0; j < nIntFacets; j++) PetscCall(PetscHSetIAdd(facets, intFacetsArray[offset + j])); 2265f98464cbSLawrence Mitchell } 22669566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->intFacets, &intFacetsArray)); 22679566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(facets, &nIntFacets)); 22689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nIntFacets, &allIntFacets)); 22699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(fEnd - fStart, &patch->precomputedIntFacetTensorLocations)); 2270f98464cbSLawrence Mitchell i = 0; 2271f98464cbSLawrence Mitchell PetscHashIterBegin(facets, hi); 2272f98464cbSLawrence Mitchell while (!PetscHashIterAtEnd(facets, hi)) { 2273f98464cbSLawrence Mitchell PetscHashIterGetKey(facets, hi, allIntFacets[i]); 2274de2d1767SPatrick Farrell patch->precomputedIntFacetTensorLocations[allIntFacets[i] - fStart] = i; 2275f98464cbSLawrence Mitchell PetscHashIterNext(facets, hi); 2276f98464cbSLawrence Mitchell i++; 2277f98464cbSLawrence Mitchell } 22789566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&facets)); 22799566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nIntFacets, allIntFacets, PETSC_OWN_POINTER, &patch->allIntFacets)); 2280f98464cbSLawrence Mitchell } 22819566063dSJacob Faibussowitsch PetscCall(ISGetSize(patch->allIntFacets, &nIntFacets)); 2282f98464cbSLawrence Mitchell if (!patch->intFacetMats) { 22839566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, nIntFacets * ndof * ndof * 4, &patch->intFacetMats)); 22849566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(patch->intFacetMats, ndof * 2)); 2285f98464cbSLawrence Mitchell } 22869566063dSJacob Faibussowitsch PetscCall(VecSet(patch->intFacetMats, 0)); 2287f98464cbSLawrence Mitchell 2288d0609cedSBarry Smith PetscCall(MatCreateShell(PETSC_COMM_SELF, nIntFacets * ndof * 2, nIntFacets * ndof * 2, nIntFacets * ndof * 2, nIntFacets * ndof * 2, (void *)patch->intFacetMats, &vecMat)); 22899566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(vecMat, MATOP_SET_VALUES, (void (*)(void)) & MatSetValues_PCPatch_Private)); 22909566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, 2 * ndof * nIntFacets, 0, 1, &dofMap)); 22919566063dSJacob Faibussowitsch PetscCall(ISGetIndices(dofMap, &dofMapArray)); 22929566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->allIntFacets, &intFacetsArray)); 22939566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nIntFacets, intFacetsArray, PETSC_USE_POINTER, &intFacetsIS)); 2294f98464cbSLawrence Mitchell /* TODO: Fix for DMPlex compute op, this bypasses a lot of the machinery and just assembles every element tensor. */ 2295792fecdfSBarry Smith PetscCallBack("PCPatch callback (interior facets)", patch->usercomputeopintfacet(pc, -1, NULL, vecMat, intFacetsIS, 2 * ndof * nIntFacets, dofMapArray, NULL, patch->usercomputeopintfacetctx)); 22969566063dSJacob Faibussowitsch PetscCall(ISDestroy(&intFacetsIS)); 22979566063dSJacob Faibussowitsch PetscCall(MatDestroy(&vecMat)); 22989566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->allIntFacets, &intFacetsArray)); 22999566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(dofMap, &dofMapArray)); 23009566063dSJacob Faibussowitsch PetscCall(ISDestroy(&dofMap)); 2301f98464cbSLawrence Mitchell } 23029566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dm)); 23039566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_Patch_ComputeOp, pc, 0, 0, 0)); 2304fa84ea4cSLawrence Mitchell 2305fa84ea4cSLawrence Mitchell PetscFunctionReturn(0); 2306fa84ea4cSLawrence Mitchell } 2307fa84ea4cSLawrence Mitchell 23089371c9d4SSatish Balay PetscErrorCode PCPatch_ScatterLocal_Private(PC pc, PetscInt p, Vec x, Vec y, InsertMode mode, ScatterMode scat, PatchScatterType scattertype) { 23094bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 23104bbf5ea8SMatthew G. Knepley const PetscScalar *xArray = NULL; 23114bbf5ea8SMatthew G. Knepley PetscScalar *yArray = NULL; 23124bbf5ea8SMatthew G. Knepley const PetscInt *gtolArray = NULL; 23134bbf5ea8SMatthew G. Knepley PetscInt dof, offset, lidx; 23144bbf5ea8SMatthew G. Knepley 23154bbf5ea8SMatthew G. Knepley PetscFunctionBeginHot; 23169566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &xArray)); 23179566063dSJacob Faibussowitsch PetscCall(VecGetArray(y, &yArray)); 23180904074fSPatrick Farrell if (scattertype == SCATTER_WITHARTIFICIAL) { 23199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCountsWithArtificial, p, &dof)); 23209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->gtolCountsWithArtificial, p, &offset)); 23219566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->gtolWithArtificial, >olArray)); 23220904074fSPatrick Farrell } else if (scattertype == SCATTER_WITHALL) { 23239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCountsWithAll, p, &dof)); 23249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->gtolCountsWithAll, p, &offset)); 23259566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->gtolWithAll, >olArray)); 2326c2e6f3c0SFlorian Wechsung } else { 23279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCounts, p, &dof)); 23289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->gtolCounts, p, &offset)); 23299566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->gtol, >olArray)); 2330c2e6f3c0SFlorian Wechsung } 23312472a847SBarry Smith PetscCheck(mode != INSERT_VALUES || scat == SCATTER_FORWARD, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Can't insert if not scattering forward"); 23322472a847SBarry Smith PetscCheck(mode != ADD_VALUES || scat == SCATTER_REVERSE, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Can't add if not scattering reverse"); 23334bbf5ea8SMatthew G. Knepley for (lidx = 0; lidx < dof; ++lidx) { 23344bbf5ea8SMatthew G. Knepley const PetscInt gidx = gtolArray[offset + lidx]; 23354bbf5ea8SMatthew G. Knepley 23364bbf5ea8SMatthew G. Knepley if (mode == INSERT_VALUES) yArray[lidx] = xArray[gidx]; /* Forward */ 23374bbf5ea8SMatthew G. Knepley else yArray[gidx] += xArray[lidx]; /* Reverse */ 23384bbf5ea8SMatthew G. Knepley } 23390904074fSPatrick Farrell if (scattertype == SCATTER_WITHARTIFICIAL) { 23409566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->gtolWithArtificial, >olArray)); 23410904074fSPatrick Farrell } else if (scattertype == SCATTER_WITHALL) { 23429566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->gtolWithAll, >olArray)); 2343c2e6f3c0SFlorian Wechsung } else { 23449566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->gtol, >olArray)); 2345c2e6f3c0SFlorian Wechsung } 23469566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &xArray)); 23479566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(y, &yArray)); 23484bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 23494bbf5ea8SMatthew G. Knepley } 23504bbf5ea8SMatthew G. Knepley 23519371c9d4SSatish Balay static PetscErrorCode PCSetUp_PATCH_Linear(PC pc) { 2352dadc69c5SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 2353dadc69c5SMatthew G. Knepley const char *prefix; 2354dadc69c5SMatthew G. Knepley PetscInt i; 2355dadc69c5SMatthew G. Knepley 2356dadc69c5SMatthew G. Knepley PetscFunctionBegin; 2357dadc69c5SMatthew G. Knepley if (!pc->setupcalled) { 23587827d75bSBarry Smith PetscCheck(patch->save_operators || !patch->denseinverse, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONGSTATE, "Can't have dense inverse without save operators"); 2359c73d2cf6SLawrence Mitchell if (!patch->denseinverse) { 23609566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(patch->npatch, &patch->solver)); 23619566063dSJacob Faibussowitsch PetscCall(PCGetOptionsPrefix(pc, &prefix)); 2362dadc69c5SMatthew G. Knepley for (i = 0; i < patch->npatch; ++i) { 2363dadc69c5SMatthew G. Knepley KSP ksp; 2364dadc69c5SMatthew G. Knepley PC subpc; 2365dadc69c5SMatthew G. Knepley 23669566063dSJacob Faibussowitsch PetscCall(KSPCreate(PETSC_COMM_SELF, &ksp)); 23679566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(ksp, pc->erroriffailure)); 23689566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(ksp, prefix)); 23699566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(ksp, "sub_")); 23709566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)ksp, (PetscObject)pc, 1)); 23719566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &subpc)); 23729566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)subpc, (PetscObject)pc, 1)); 23739566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)pc, (PetscObject)ksp)); 2374dadc69c5SMatthew G. Knepley patch->solver[i] = (PetscObject)ksp; 2375dadc69c5SMatthew G. Knepley } 2376dadc69c5SMatthew G. Knepley } 2377c73d2cf6SLawrence Mitchell } 2378dadc69c5SMatthew G. Knepley if (patch->save_operators) { 23791baa6e33SBarry Smith if (patch->precomputeElementTensors) PetscCall(PCPatchPrecomputePatchTensors_Private(pc)); 2380dadc69c5SMatthew G. Knepley for (i = 0; i < patch->npatch; ++i) { 23819566063dSJacob Faibussowitsch PetscCall(PCPatchComputeOperator_Internal(pc, NULL, patch->mat[i], i, PETSC_FALSE)); 2382c73d2cf6SLawrence Mitchell if (!patch->denseinverse) { 23839566063dSJacob Faibussowitsch PetscCall(KSPSetOperators((KSP)patch->solver[i], patch->mat[i], patch->mat[i])); 23849d4fc724SLawrence Mitchell } else if (patch->mat[i] && !patch->densesolve) { 23859d4fc724SLawrence Mitchell /* Setup matmult callback */ 23869566063dSJacob Faibussowitsch PetscCall(MatGetOperation(patch->mat[i], MATOP_MULT, (void (**)(void)) & patch->densesolve)); 2387dadc69c5SMatthew G. Knepley } 2388dadc69c5SMatthew G. Knepley } 2389c73d2cf6SLawrence Mitchell } 239034d8b122SPatrick Farrell if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) { 239134d8b122SPatrick Farrell for (i = 0; i < patch->npatch; ++i) { 23921202d238SPatrick Farrell /* Instead of padding patch->patchUpdate with zeros to get */ 23931202d238SPatrick Farrell /* patch->patchUpdateWithArtificial and then multiplying with the matrix, */ 239434d8b122SPatrick Farrell /* just get rid of the columns that correspond to the dofs with */ 239534d8b122SPatrick Farrell /* artificial bcs. That's of course fairly inefficient, hopefully we */ 239634d8b122SPatrick Farrell /* can just assemble the rectangular matrix in the first place. */ 239734d8b122SPatrick Farrell Mat matSquare; 239834d8b122SPatrick Farrell IS rowis; 239934d8b122SPatrick Farrell PetscInt dof; 240034d8b122SPatrick Farrell 24019566063dSJacob Faibussowitsch PetscCall(MatGetSize(patch->mat[i], &dof, NULL)); 240234d8b122SPatrick Farrell if (dof == 0) { 240334d8b122SPatrick Farrell patch->matWithArtificial[i] = NULL; 240434d8b122SPatrick Farrell continue; 240534d8b122SPatrick Farrell } 240634d8b122SPatrick Farrell 24079566063dSJacob Faibussowitsch PetscCall(PCPatchCreateMatrix_Private(pc, i, &matSquare, PETSC_TRUE)); 24089566063dSJacob Faibussowitsch PetscCall(PCPatchComputeOperator_Internal(pc, NULL, matSquare, i, PETSC_TRUE)); 240934d8b122SPatrick Farrell 24109566063dSJacob Faibussowitsch PetscCall(MatGetSize(matSquare, &dof, NULL)); 24119566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, dof, 0, 1, &rowis)); 241234d8b122SPatrick Farrell if (pc->setupcalled) { 24139566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(matSquare, rowis, patch->dofMappingWithoutToWithArtificial[i], MAT_REUSE_MATRIX, &patch->matWithArtificial[i])); 241434d8b122SPatrick Farrell } else { 24159566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(matSquare, rowis, patch->dofMappingWithoutToWithArtificial[i], MAT_INITIAL_MATRIX, &patch->matWithArtificial[i])); 241634d8b122SPatrick Farrell } 24179566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rowis)); 24189566063dSJacob Faibussowitsch PetscCall(MatDestroy(&matSquare)); 241934d8b122SPatrick Farrell } 242034d8b122SPatrick Farrell } 2421dadc69c5SMatthew G. Knepley PetscFunctionReturn(0); 2422dadc69c5SMatthew G. Knepley } 2423dadc69c5SMatthew G. Knepley 24249371c9d4SSatish Balay static PetscErrorCode PCSetUp_PATCH(PC pc) { 24254bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 2426557beb66SLawrence Mitchell PetscInt i; 242739fd2e8aSPatrick Farrell PetscBool isNonlinear; 24289d4fc724SLawrence Mitchell PetscInt maxDof = -1, maxDofWithArtificial = -1; 24294bbf5ea8SMatthew G. Knepley 24304bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 24314bbf5ea8SMatthew G. Knepley if (!pc->setupcalled) { 24324bbf5ea8SMatthew G. Knepley PetscInt pStart, pEnd, p; 24334bbf5ea8SMatthew G. Knepley PetscInt localSize; 24344bbf5ea8SMatthew G. Knepley 24359566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_Patch_CreatePatches, pc, 0, 0, 0)); 24364bbf5ea8SMatthew G. Knepley 2437debbdec3SPatrick Farrell isNonlinear = patch->isNonlinear; 24385f824522SMatthew G. Knepley if (!patch->nsubspaces) { 2439b6bb21d1SLawrence Mitchell DM dm, plex; 24405f824522SMatthew G. Knepley PetscSection s; 2441bd026e97SJed Brown PetscInt cStart, cEnd, c, Nf, f, numGlobalBcs = 0, *globalBcs, *Nb, **cellDofs; 24425f824522SMatthew G. Knepley 24439566063dSJacob Faibussowitsch PetscCall(PCGetDM(pc, &dm)); 244428b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Must set DM for PCPATCH or call PCPatchSetDiscretisationInfo()"); 24459566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 2446b6bb21d1SLawrence Mitchell dm = plex; 24479566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dm, &s)); 24489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetNumFields(s, &Nf)); 24499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(s, &pStart, &pEnd)); 24505f824522SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 24515f824522SMatthew G. Knepley PetscInt cdof; 24529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(s, p, &cdof)); 24535f824522SMatthew G. Knepley numGlobalBcs += cdof; 24545f824522SMatthew G. Knepley } 24559566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 24569566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(Nf, &Nb, Nf, &cellDofs, numGlobalBcs, &globalBcs)); 24575f824522SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 24585f824522SMatthew G. Knepley PetscFE fe; 24595f824522SMatthew G. Knepley PetscDualSpace sp; 24605f824522SMatthew G. Knepley PetscInt cdoff = 0; 24615f824522SMatthew G. Knepley 24629566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, f, NULL, (PetscObject *)&fe)); 24639566063dSJacob Faibussowitsch /* PetscCall(PetscFEGetNumComponents(fe, &Nc[f])); */ 24649566063dSJacob Faibussowitsch PetscCall(PetscFEGetDualSpace(fe, &sp)); 24659566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceGetDimension(sp, &Nb[f])); 24665f824522SMatthew G. Knepley 24679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((cEnd - cStart) * Nb[f], &cellDofs[f])); 24685f824522SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 24695f824522SMatthew G. Knepley PetscInt *closure = NULL; 24705f824522SMatthew G. Knepley PetscInt clSize = 0, cl; 24715f824522SMatthew G. Knepley 24729566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 24735f824522SMatthew G. Knepley for (cl = 0; cl < clSize * 2; cl += 2) { 24745f824522SMatthew G. Knepley const PetscInt p = closure[cl]; 24755f824522SMatthew G. Knepley PetscInt fdof, d, foff; 24765f824522SMatthew G. Knepley 24779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldDof(s, p, f, &fdof)); 24789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldOffset(s, p, f, &foff)); 24795f824522SMatthew G. Knepley for (d = 0; d < fdof; ++d, ++cdoff) cellDofs[f][cdoff] = foff + d; 24805f824522SMatthew G. Knepley } 24819566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure)); 24825f824522SMatthew G. Knepley } 248363a3b9bcSJacob 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]); 24845f824522SMatthew G. Knepley } 24855f824522SMatthew G. Knepley numGlobalBcs = 0; 24865f824522SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 24875f824522SMatthew G. Knepley const PetscInt *ind; 24885f824522SMatthew G. Knepley PetscInt off, cdof, d; 24895f824522SMatthew G. Knepley 24909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(s, p, &off)); 24919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintDof(s, p, &cdof)); 24929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstraintIndices(s, p, &ind)); 24935f824522SMatthew G. Knepley for (d = 0; d < cdof; ++d) globalBcs[numGlobalBcs++] = off + ind[d]; 24945f824522SMatthew G. Knepley } 24955f824522SMatthew G. Knepley 24969566063dSJacob Faibussowitsch PetscCall(PCPatchSetDiscretisationInfoCombined(pc, dm, Nb, (const PetscInt **)cellDofs, numGlobalBcs, globalBcs, numGlobalBcs, globalBcs)); 2497*48a46eb9SPierre Jolivet for (f = 0; f < Nf; ++f) PetscCall(PetscFree(cellDofs[f])); 24989566063dSJacob Faibussowitsch PetscCall(PetscFree3(Nb, cellDofs, globalBcs)); 24999566063dSJacob Faibussowitsch PetscCall(PCPatchSetComputeFunction(pc, PCPatchComputeFunction_DMPlex_Private, NULL)); 25009566063dSJacob Faibussowitsch PetscCall(PCPatchSetComputeOperator(pc, PCPatchComputeOperator_DMPlex_Private, NULL)); 25019566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dm)); 25025f824522SMatthew G. Knepley } 25035f824522SMatthew G. Knepley 25044bbf5ea8SMatthew G. Knepley localSize = patch->subspaceOffsets[patch->nsubspaces]; 25059566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, localSize, &patch->localRHS)); 25069566063dSJacob Faibussowitsch PetscCall(VecSetUp(patch->localRHS)); 25079566063dSJacob Faibussowitsch PetscCall(VecDuplicate(patch->localRHS, &patch->localUpdate)); 25089566063dSJacob Faibussowitsch PetscCall(PCPatchCreateCellPatches(pc)); 25099566063dSJacob Faibussowitsch PetscCall(PCPatchCreateCellPatchDiscretisationInfo(pc)); 25104bbf5ea8SMatthew G. Knepley 25114bbf5ea8SMatthew G. Knepley /* OK, now build the work vectors */ 25129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(patch->gtolCounts, &pStart, &pEnd)); 2513c2e6f3c0SFlorian Wechsung 2514*48a46eb9SPierre Jolivet if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) PetscCall(PetscMalloc1(patch->npatch, &patch->dofMappingWithoutToWithArtificial)); 2515*48a46eb9SPierre Jolivet if (isNonlinear) PetscCall(PetscMalloc1(patch->npatch, &patch->dofMappingWithoutToWithAll)); 25164bbf5ea8SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 25174bbf5ea8SMatthew G. Knepley PetscInt dof; 25184bbf5ea8SMatthew G. Knepley 25199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCounts, p, &dof)); 25202f613bf5SBarry Smith maxDof = PetscMax(maxDof, dof); 25210904074fSPatrick Farrell if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) { 25223bb0e8f7SKarl Rupp const PetscInt *gtolArray, *gtolArrayWithArtificial = NULL; 25233bb0e8f7SKarl Rupp PetscInt numPatchDofs, offset; 25243bb0e8f7SKarl Rupp PetscInt numPatchDofsWithArtificial, offsetWithArtificial; 25253bb0e8f7SKarl Rupp PetscInt dofWithoutArtificialCounter = 0; 25263bb0e8f7SKarl Rupp PetscInt *patchWithoutArtificialToWithArtificialArray; 25273bb0e8f7SKarl Rupp 25289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCountsWithArtificial, p, &dof)); 25299d4fc724SLawrence Mitchell maxDofWithArtificial = PetscMax(maxDofWithArtificial, dof); 2530c2e6f3c0SFlorian Wechsung 2531e047a90bSFlorian Wechsung /* Now build the mapping that for a dof in a patch WITHOUT dofs that have artificial bcs gives the */ 2532e047a90bSFlorian Wechsung /* the index in the patch with all dofs */ 25339566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->gtol, >olArray)); 253463deea8eSPatrick Farrell 25359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCounts, p, &numPatchDofs)); 253647aca4a6SPatrick Farrell if (numPatchDofs == 0) { 253747aca4a6SPatrick Farrell patch->dofMappingWithoutToWithArtificial[p - pStart] = NULL; 253847aca4a6SPatrick Farrell continue; 253947aca4a6SPatrick Farrell } 254063deea8eSPatrick Farrell 25419566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->gtolCounts, p, &offset)); 25429566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->gtolWithArtificial, >olArrayWithArtificial)); 25439566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCountsWithArtificial, p, &numPatchDofsWithArtificial)); 25449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->gtolCountsWithArtificial, p, &offsetWithArtificial)); 2545c2e6f3c0SFlorian Wechsung 25469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPatchDofs, &patchWithoutArtificialToWithArtificialArray)); 2547b0c21b6aSKarl Rupp for (i = 0; i < numPatchDofsWithArtificial; i++) { 2548e047a90bSFlorian Wechsung if (gtolArrayWithArtificial[i + offsetWithArtificial] == gtolArray[offset + dofWithoutArtificialCounter]) { 2549c2e6f3c0SFlorian Wechsung patchWithoutArtificialToWithArtificialArray[dofWithoutArtificialCounter] = i; 2550c2e6f3c0SFlorian Wechsung dofWithoutArtificialCounter++; 25519371c9d4SSatish Balay if (dofWithoutArtificialCounter == numPatchDofs) break; 2552c2e6f3c0SFlorian Wechsung } 2553c2e6f3c0SFlorian Wechsung } 25549566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numPatchDofs, patchWithoutArtificialToWithArtificialArray, PETSC_OWN_POINTER, &patch->dofMappingWithoutToWithArtificial[p - pStart])); 25559566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->gtol, >olArray)); 25569566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->gtolWithArtificial, >olArrayWithArtificial)); 2557c2e6f3c0SFlorian Wechsung } 25580997d788SPatrick Farrell } 25590997d788SPatrick Farrell for (p = pStart; p < pEnd; ++p) { 25600904074fSPatrick Farrell if (isNonlinear) { 25610904074fSPatrick Farrell const PetscInt *gtolArray, *gtolArrayWithAll = NULL; 25620904074fSPatrick Farrell PetscInt numPatchDofs, offset; 25630904074fSPatrick Farrell PetscInt numPatchDofsWithAll, offsetWithAll; 25640904074fSPatrick Farrell PetscInt dofWithoutAllCounter = 0; 25650904074fSPatrick Farrell PetscInt *patchWithoutAllToWithAllArray; 25660904074fSPatrick Farrell 25670904074fSPatrick Farrell /* Now build the mapping that for a dof in a patch WITHOUT dofs that have artificial bcs gives the */ 25680904074fSPatrick Farrell /* the index in the patch with all dofs */ 25699566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->gtol, >olArray)); 25700904074fSPatrick Farrell 25719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCounts, p, &numPatchDofs)); 257247aca4a6SPatrick Farrell if (numPatchDofs == 0) { 2573b88cb22dSPatrick Farrell patch->dofMappingWithoutToWithAll[p - pStart] = NULL; 257447aca4a6SPatrick Farrell continue; 257547aca4a6SPatrick Farrell } 25760904074fSPatrick Farrell 25779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->gtolCounts, p, &offset)); 25789566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->gtolWithAll, >olArrayWithAll)); 25799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCountsWithAll, p, &numPatchDofsWithAll)); 25809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->gtolCountsWithAll, p, &offsetWithAll)); 25810904074fSPatrick Farrell 25829566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numPatchDofs, &patchWithoutAllToWithAllArray)); 25830904074fSPatrick Farrell 25840904074fSPatrick Farrell for (i = 0; i < numPatchDofsWithAll; i++) { 25850904074fSPatrick Farrell if (gtolArrayWithAll[i + offsetWithAll] == gtolArray[offset + dofWithoutAllCounter]) { 25860904074fSPatrick Farrell patchWithoutAllToWithAllArray[dofWithoutAllCounter] = i; 25870904074fSPatrick Farrell dofWithoutAllCounter++; 25889371c9d4SSatish Balay if (dofWithoutAllCounter == numPatchDofs) break; 25890904074fSPatrick Farrell } 25900904074fSPatrick Farrell } 25919566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numPatchDofs, patchWithoutAllToWithAllArray, PETSC_OWN_POINTER, &patch->dofMappingWithoutToWithAll[p - pStart])); 25929566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->gtol, >olArray)); 25939566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->gtolWithAll, >olArrayWithAll)); 25940904074fSPatrick Farrell } 25954bbf5ea8SMatthew G. Knepley } 259660dd46caSLawrence Mitchell if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) { 25979566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, maxDofWithArtificial, &patch->patchRHSWithArtificial)); 25989566063dSJacob Faibussowitsch PetscCall(VecSetUp(patch->patchRHSWithArtificial)); 259960dd46caSLawrence Mitchell } 26009566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, maxDof, &patch->patchRHS)); 26019566063dSJacob Faibussowitsch PetscCall(VecSetUp(patch->patchRHS)); 26029566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF, maxDof, &patch->patchUpdate)); 26039566063dSJacob Faibussowitsch PetscCall(VecSetUp(patch->patchUpdate)); 26044bbf5ea8SMatthew G. Knepley if (patch->save_operators) { 26059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(patch->npatch, &patch->mat)); 2606*48a46eb9SPierre Jolivet for (i = 0; i < patch->npatch; ++i) PetscCall(PCPatchCreateMatrix_Private(pc, i, &patch->mat[i], PETSC_FALSE)); 26074bbf5ea8SMatthew G. Knepley } 26089566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_Patch_CreatePatches, pc, 0, 0, 0)); 26094bbf5ea8SMatthew G. Knepley 26104bbf5ea8SMatthew G. Knepley /* If desired, calculate weights for dof multiplicity */ 26114bbf5ea8SMatthew G. Knepley if (patch->partition_of_unity) { 26123bb0e8f7SKarl Rupp PetscScalar *input = NULL; 26133bb0e8f7SKarl Rupp PetscScalar *output = NULL; 26143bb0e8f7SKarl Rupp Vec global; 26153bb0e8f7SKarl Rupp 26169566063dSJacob Faibussowitsch PetscCall(VecDuplicate(patch->localRHS, &patch->dof_weights)); 261761c4b389SFlorian Wechsung if (patch->local_composition_type == PC_COMPOSITE_ADDITIVE) { 26184bbf5ea8SMatthew G. Knepley for (i = 0; i < patch->npatch; ++i) { 26194bbf5ea8SMatthew G. Knepley PetscInt dof; 26204bbf5ea8SMatthew G. Knepley 26219566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCounts, i + pStart, &dof)); 26224bbf5ea8SMatthew G. Knepley if (dof <= 0) continue; 26239566063dSJacob Faibussowitsch PetscCall(VecSet(patch->patchRHS, 1.0)); 26249566063dSJacob Faibussowitsch PetscCall(PCPatch_ScatterLocal_Private(pc, i + pStart, patch->patchRHS, patch->dof_weights, ADD_VALUES, SCATTER_REVERSE, SCATTER_INTERIOR)); 26254bbf5ea8SMatthew G. Knepley } 2626c2e6f3c0SFlorian Wechsung } else { 2627e047a90bSFlorian Wechsung /* multiplicative is actually only locally multiplicative and globally additive. need the pou where the mesh decomposition overlaps */ 26289566063dSJacob Faibussowitsch PetscCall(VecSet(patch->dof_weights, 1.0)); 26294bbf5ea8SMatthew G. Knepley } 2630d132cafaSFlorian Wechsung 2631d132cafaSFlorian Wechsung VecDuplicate(patch->dof_weights, &global); 2632d132cafaSFlorian Wechsung VecSet(global, 0.); 2633d132cafaSFlorian Wechsung 26349566063dSJacob Faibussowitsch PetscCall(VecGetArray(patch->dof_weights, &input)); 26359566063dSJacob Faibussowitsch PetscCall(VecGetArray(global, &output)); 26369566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(patch->sectionSF, MPIU_SCALAR, input, output, MPI_SUM)); 26379566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(patch->sectionSF, MPIU_SCALAR, input, output, MPI_SUM)); 26389566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(patch->dof_weights, &input)); 26399566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(global, &output)); 2640d132cafaSFlorian Wechsung 26419566063dSJacob Faibussowitsch PetscCall(VecReciprocal(global)); 2642d132cafaSFlorian Wechsung 26439566063dSJacob Faibussowitsch PetscCall(VecGetArray(patch->dof_weights, &output)); 26449566063dSJacob Faibussowitsch PetscCall(VecGetArray(global, &input)); 26459566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(patch->sectionSF, MPIU_SCALAR, input, output, MPI_REPLACE)); 26469566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(patch->sectionSF, MPIU_SCALAR, input, output, MPI_REPLACE)); 26479566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(patch->dof_weights, &output)); 26489566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(global, &input)); 26499566063dSJacob Faibussowitsch PetscCall(VecDestroy(&global)); 26504bbf5ea8SMatthew G. Knepley } 2651*48a46eb9SPierre Jolivet if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE && patch->save_operators && !patch->isNonlinear) PetscCall(PetscMalloc1(patch->npatch, &patch->matWithArtificial)); 26524bbf5ea8SMatthew G. Knepley } 26539566063dSJacob Faibussowitsch PetscCall((*patch->setupsolver)(pc)); 2654dadc69c5SMatthew G. Knepley PetscFunctionReturn(0); 26554bbf5ea8SMatthew G. Knepley } 2656dadc69c5SMatthew G. Knepley 26579371c9d4SSatish Balay static PetscErrorCode PCApply_PATCH_Linear(PC pc, PetscInt i, Vec x, Vec y) { 2658dadc69c5SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 2659c73d2cf6SLawrence Mitchell KSP ksp; 26609d4fc724SLawrence Mitchell Mat op; 26619d4fc724SLawrence Mitchell PetscInt m, n; 2662dadc69c5SMatthew G. Knepley 2663dadc69c5SMatthew G. Knepley PetscFunctionBegin; 2664c73d2cf6SLawrence Mitchell if (patch->denseinverse) { 26659566063dSJacob Faibussowitsch PetscCall((*patch->densesolve)(patch->mat[i], x, y)); 2666c73d2cf6SLawrence Mitchell PetscFunctionReturn(0); 2667c73d2cf6SLawrence Mitchell } 2668c73d2cf6SLawrence Mitchell ksp = (KSP)patch->solver[i]; 2669dadc69c5SMatthew G. Knepley if (!patch->save_operators) { 2670dadc69c5SMatthew G. Knepley Mat mat; 2671dadc69c5SMatthew G. Knepley 26729566063dSJacob Faibussowitsch PetscCall(PCPatchCreateMatrix_Private(pc, i, &mat, PETSC_FALSE)); 2673dadc69c5SMatthew G. Knepley /* Populate operator here. */ 26749566063dSJacob Faibussowitsch PetscCall(PCPatchComputeOperator_Internal(pc, NULL, mat, i, PETSC_FALSE)); 26759566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(ksp, mat, mat)); 2676dadc69c5SMatthew G. Knepley /* Drop reference so the KSPSetOperators below will blow it away. */ 26779566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mat)); 2678dadc69c5SMatthew G. Knepley } 26799566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_Patch_Solve, pc, 0, 0, 0)); 2680*48a46eb9SPierre Jolivet if (!ksp->setfromoptionscalled) PetscCall(KSPSetFromOptions(ksp)); 26819d4fc724SLawrence Mitchell /* Disgusting trick to reuse work vectors */ 26829566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(ksp, &op, NULL)); 26839566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(op, &m, &n)); 26849d4fc724SLawrence Mitchell x->map->n = m; 26859d4fc724SLawrence Mitchell y->map->n = n; 26869d4fc724SLawrence Mitchell x->map->N = m; 26879d4fc724SLawrence Mitchell y->map->N = n; 26889566063dSJacob Faibussowitsch PetscCall(KSPSolve(ksp, x, y)); 26899566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(ksp, pc, y)); 26909566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_Patch_Solve, pc, 0, 0, 0)); 2691dadc69c5SMatthew G. Knepley if (!patch->save_operators) { 2692dadc69c5SMatthew G. Knepley PC pc; 26939566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(ksp, NULL, NULL)); 26949566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc)); 2695dadc69c5SMatthew G. Knepley /* Destroy PC context too, otherwise the factored matrix hangs around. */ 26969566063dSJacob Faibussowitsch PetscCall(PCReset(pc)); 26974bbf5ea8SMatthew G. Knepley } 26984bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 26994bbf5ea8SMatthew G. Knepley } 27004bbf5ea8SMatthew G. Knepley 27019371c9d4SSatish Balay static PetscErrorCode PCUpdateMultiplicative_PATCH_Linear(PC pc, PetscInt i, PetscInt pStart) { 27026c9c532dSPatrick Farrell PC_PATCH *patch = (PC_PATCH *)pc->data; 27036c9c532dSPatrick Farrell Mat multMat; 27049d4fc724SLawrence Mitchell PetscInt n, m; 27056c9c532dSPatrick Farrell 27064d04e9f1SPatrick Farrell PetscFunctionBegin; 27074d04e9f1SPatrick Farrell 27086c9c532dSPatrick Farrell if (patch->save_operators) { 27096c9c532dSPatrick Farrell multMat = patch->matWithArtificial[i]; 27106c9c532dSPatrick Farrell } else { 27116c9c532dSPatrick Farrell /*Very inefficient, hopefully we can just assemble the rectangular matrix in the first place.*/ 27126c9c532dSPatrick Farrell Mat matSquare; 27136c9c532dSPatrick Farrell PetscInt dof; 27146c9c532dSPatrick Farrell IS rowis; 27159566063dSJacob Faibussowitsch PetscCall(PCPatchCreateMatrix_Private(pc, i, &matSquare, PETSC_TRUE)); 27169566063dSJacob Faibussowitsch PetscCall(PCPatchComputeOperator_Internal(pc, NULL, matSquare, i, PETSC_TRUE)); 27179566063dSJacob Faibussowitsch PetscCall(MatGetSize(matSquare, &dof, NULL)); 27189566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, dof, 0, 1, &rowis)); 27199566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(matSquare, rowis, patch->dofMappingWithoutToWithArtificial[i], MAT_INITIAL_MATRIX, &multMat)); 27209566063dSJacob Faibussowitsch PetscCall(MatDestroy(&matSquare)); 27219566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rowis)); 27226c9c532dSPatrick Farrell } 27239d4fc724SLawrence Mitchell /* Disgusting trick to reuse work vectors */ 27249566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(multMat, &m, &n)); 27259d4fc724SLawrence Mitchell patch->patchUpdate->map->n = n; 27269d4fc724SLawrence Mitchell patch->patchRHSWithArtificial->map->n = m; 27279d4fc724SLawrence Mitchell patch->patchUpdate->map->N = n; 27289d4fc724SLawrence Mitchell patch->patchRHSWithArtificial->map->N = m; 27299566063dSJacob Faibussowitsch PetscCall(MatMult(multMat, patch->patchUpdate, patch->patchRHSWithArtificial)); 27309566063dSJacob Faibussowitsch PetscCall(VecScale(patch->patchRHSWithArtificial, -1.0)); 27319566063dSJacob Faibussowitsch PetscCall(PCPatch_ScatterLocal_Private(pc, i + pStart, patch->patchRHSWithArtificial, patch->localRHS, ADD_VALUES, SCATTER_REVERSE, SCATTER_WITHARTIFICIAL)); 2732*48a46eb9SPierre Jolivet if (!patch->save_operators) PetscCall(MatDestroy(&multMat)); 27334d04e9f1SPatrick Farrell PetscFunctionReturn(0); 27346c9c532dSPatrick Farrell } 27356c9c532dSPatrick Farrell 27369371c9d4SSatish Balay static PetscErrorCode PCApply_PATCH(PC pc, Vec x, Vec y) { 27374bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 27381202d238SPatrick Farrell const PetscScalar *globalRHS = NULL; 27391202d238SPatrick Farrell PetscScalar *localRHS = NULL; 27401202d238SPatrick Farrell PetscScalar *globalUpdate = NULL; 27414bbf5ea8SMatthew G. Knepley const PetscInt *bcNodes = NULL; 27424bbf5ea8SMatthew G. Knepley PetscInt nsweep = patch->symmetrise_sweep ? 2 : 1; 27434bbf5ea8SMatthew G. Knepley PetscInt start[2] = {0, 0}; 27444bbf5ea8SMatthew G. Knepley PetscInt end[2] = {-1, -1}; 27454bbf5ea8SMatthew G. Knepley const PetscInt inc[2] = {1, -1}; 27461202d238SPatrick Farrell const PetscScalar *localUpdate; 27474bbf5ea8SMatthew G. Knepley const PetscInt *iterationSet; 27484bbf5ea8SMatthew G. Knepley PetscInt pStart, numBcs, n, sweep, bc, j; 27494bbf5ea8SMatthew G. Knepley 27504bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 27519566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_Patch_Apply, pc, 0, 0, 0)); 27529566063dSJacob Faibussowitsch PetscCall(PetscOptionsPushGetViewerOff(PETSC_TRUE)); 275392d50984SMatthew G. Knepley /* start, end, inc have 2 entries to manage a second backward sweep if we symmetrize */ 27544bbf5ea8SMatthew G. Knepley end[0] = patch->npatch; 27554bbf5ea8SMatthew G. Knepley start[1] = patch->npatch - 1; 27564bbf5ea8SMatthew G. Knepley if (patch->user_patches) { 27579566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(patch->iterationSet, &end[0])); 27584bbf5ea8SMatthew G. Knepley start[1] = end[0] - 1; 27599566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->iterationSet, &iterationSet)); 27604bbf5ea8SMatthew G. Knepley } 27614bbf5ea8SMatthew G. Knepley /* Scatter from global space into overlapped local spaces */ 27629566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &globalRHS)); 27639566063dSJacob Faibussowitsch PetscCall(VecGetArray(patch->localRHS, &localRHS)); 27649566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(patch->sectionSF, MPIU_SCALAR, globalRHS, localRHS, MPI_REPLACE)); 27659566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(patch->sectionSF, MPIU_SCALAR, globalRHS, localRHS, MPI_REPLACE)); 27669566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &globalRHS)); 27679566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(patch->localRHS, &localRHS)); 27684bbf5ea8SMatthew G. Knepley 27699566063dSJacob Faibussowitsch PetscCall(VecSet(patch->localUpdate, 0.0)); 27709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(patch->gtolCounts, &pStart, NULL)); 27719566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_Patch_Solve, pc, 0, 0, 0)); 27724bbf5ea8SMatthew G. Knepley for (sweep = 0; sweep < nsweep; sweep++) { 27734bbf5ea8SMatthew G. Knepley for (j = start[sweep]; j * inc[sweep] < end[sweep] * inc[sweep]; j += inc[sweep]) { 27744bbf5ea8SMatthew G. Knepley PetscInt i = patch->user_patches ? iterationSet[j] : j; 27754bbf5ea8SMatthew G. Knepley PetscInt start, len; 27764bbf5ea8SMatthew G. Knepley 27779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(patch->gtolCounts, i + pStart, &len)); 27789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(patch->gtolCounts, i + pStart, &start)); 27794bbf5ea8SMatthew G. Knepley /* TODO: Squash out these guys in the setup as well. */ 27804bbf5ea8SMatthew G. Knepley if (len <= 0) continue; 27814bbf5ea8SMatthew G. Knepley /* TODO: Do we need different scatters for X and Y? */ 27829566063dSJacob Faibussowitsch PetscCall(PCPatch_ScatterLocal_Private(pc, i + pStart, patch->localRHS, patch->patchRHS, INSERT_VALUES, SCATTER_FORWARD, SCATTER_INTERIOR)); 27839566063dSJacob Faibussowitsch PetscCall((*patch->applysolver)(pc, i, patch->patchRHS, patch->patchUpdate)); 27849566063dSJacob Faibussowitsch PetscCall(PCPatch_ScatterLocal_Private(pc, i + pStart, patch->patchUpdate, patch->localUpdate, ADD_VALUES, SCATTER_REVERSE, SCATTER_INTERIOR)); 2785*48a46eb9SPierre Jolivet if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) PetscCall((*patch->updatemultiplicative)(pc, i, pStart)); 27864bbf5ea8SMatthew G. Knepley } 27874bbf5ea8SMatthew G. Knepley } 27889566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_Patch_Solve, pc, 0, 0, 0)); 27899566063dSJacob Faibussowitsch if (patch->user_patches) PetscCall(ISRestoreIndices(patch->iterationSet, &iterationSet)); 27904bbf5ea8SMatthew G. Knepley /* XXX: should we do this on the global vector? */ 27911baa6e33SBarry Smith if (patch->partition_of_unity) PetscCall(VecPointwiseMult(patch->localUpdate, patch->localUpdate, patch->dof_weights)); 27921202d238SPatrick Farrell /* Now patch->localUpdate contains the solution of the patch solves, so we need to combine them all. */ 27939566063dSJacob Faibussowitsch PetscCall(VecSet(y, 0.0)); 27949566063dSJacob Faibussowitsch PetscCall(VecGetArray(y, &globalUpdate)); 27959566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(patch->localUpdate, &localUpdate)); 27969566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(patch->sectionSF, MPIU_SCALAR, localUpdate, globalUpdate, MPI_SUM)); 27979566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(patch->sectionSF, MPIU_SCALAR, localUpdate, globalUpdate, MPI_SUM)); 27989566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(patch->localUpdate, &localUpdate)); 27994bbf5ea8SMatthew G. Knepley 28004bbf5ea8SMatthew G. Knepley /* Now we need to send the global BC values through */ 28019566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &globalRHS)); 28029566063dSJacob Faibussowitsch PetscCall(ISGetSize(patch->globalBcNodes, &numBcs)); 28039566063dSJacob Faibussowitsch PetscCall(ISGetIndices(patch->globalBcNodes, &bcNodes)); 28049566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(x, &n)); 28054bbf5ea8SMatthew G. Knepley for (bc = 0; bc < numBcs; ++bc) { 28064bbf5ea8SMatthew G. Knepley const PetscInt idx = bcNodes[bc]; 28071202d238SPatrick Farrell if (idx < n) globalUpdate[idx] = globalRHS[idx]; 28084bbf5ea8SMatthew G. Knepley } 28094bbf5ea8SMatthew G. Knepley 28109566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(patch->globalBcNodes, &bcNodes)); 28119566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &globalRHS)); 28129566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(y, &globalUpdate)); 28134bbf5ea8SMatthew G. Knepley 28149566063dSJacob Faibussowitsch PetscCall(PetscOptionsPopGetViewerOff()); 28159566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_Patch_Apply, pc, 0, 0, 0)); 28164bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 28174bbf5ea8SMatthew G. Knepley } 28184bbf5ea8SMatthew G. Knepley 28199371c9d4SSatish Balay static PetscErrorCode PCReset_PATCH_Linear(PC pc) { 2820dadc69c5SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 2821dadc69c5SMatthew G. Knepley PetscInt i; 2822dadc69c5SMatthew G. Knepley 2823dadc69c5SMatthew G. Knepley PetscFunctionBegin; 2824dadc69c5SMatthew G. Knepley if (patch->solver) { 28259566063dSJacob Faibussowitsch for (i = 0; i < patch->npatch; ++i) PetscCall(KSPReset((KSP)patch->solver[i])); 2826dadc69c5SMatthew G. Knepley } 2827dadc69c5SMatthew G. Knepley PetscFunctionReturn(0); 2828dadc69c5SMatthew G. Knepley } 2829dadc69c5SMatthew G. Knepley 28309371c9d4SSatish Balay static PetscErrorCode PCReset_PATCH(PC pc) { 28314bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 28324bbf5ea8SMatthew G. Knepley PetscInt i; 28334bbf5ea8SMatthew G. Knepley 28344bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 2835fa84ea4cSLawrence Mitchell 28369566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&patch->sectionSF)); 28379566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&patch->cellCounts)); 28389566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&patch->pointCounts)); 28399566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&patch->cellNumbering)); 28409566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&patch->gtolCounts)); 28419566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->gtol)); 28429566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->cells)); 28439566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->points)); 28449566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->dofs)); 28459566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->offs)); 28469566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&patch->patchSection)); 28479566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->ghostBcNodes)); 28489566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->globalBcNodes)); 28499566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&patch->gtolCountsWithArtificial)); 28509566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->gtolWithArtificial)); 28519566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->dofsWithArtificial)); 28529566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->offsWithArtificial)); 28539566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&patch->gtolCountsWithAll)); 28549566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->gtolWithAll)); 28559566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->dofsWithAll)); 28569566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->offsWithAll)); 28579566063dSJacob Faibussowitsch PetscCall(VecDestroy(&patch->cellMats)); 28589566063dSJacob Faibussowitsch PetscCall(VecDestroy(&patch->intFacetMats)); 28599566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->allCells)); 28609566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->intFacets)); 28619566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->extFacets)); 28629566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->intFacetsToPatchCell)); 28639566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&patch->intFacetCounts)); 28649566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&patch->extFacetCounts)); 28654bbf5ea8SMatthew G. Knepley 28669371c9d4SSatish Balay if (patch->dofSection) 28679371c9d4SSatish Balay for (i = 0; i < patch->nsubspaces; i++) PetscCall(PetscSectionDestroy(&patch->dofSection[i])); 28689566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->dofSection)); 28699566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->bs)); 28709566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->nodesPerCell)); 28719371c9d4SSatish Balay if (patch->cellNodeMap) 28729371c9d4SSatish Balay for (i = 0; i < patch->nsubspaces; i++) PetscCall(PetscFree(patch->cellNodeMap[i])); 28739566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->cellNodeMap)); 28749566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->subspaceOffsets)); 28754bbf5ea8SMatthew G. Knepley 28769566063dSJacob Faibussowitsch PetscCall((*patch->resetsolver)(pc)); 28774bbf5ea8SMatthew G. Knepley 2878*48a46eb9SPierre Jolivet if (patch->subspaces_to_exclude) PetscCall(PetscHSetIDestroy(&patch->subspaces_to_exclude)); 2879e4c66b91SPatrick Farrell 28809566063dSJacob Faibussowitsch PetscCall(VecDestroy(&patch->localRHS)); 28819566063dSJacob Faibussowitsch PetscCall(VecDestroy(&patch->localUpdate)); 28829566063dSJacob Faibussowitsch PetscCall(VecDestroy(&patch->patchRHS)); 28839566063dSJacob Faibussowitsch PetscCall(VecDestroy(&patch->patchUpdate)); 28849566063dSJacob Faibussowitsch PetscCall(VecDestroy(&patch->dof_weights)); 28854bbf5ea8SMatthew G. Knepley if (patch->patch_dof_weights) { 28869566063dSJacob Faibussowitsch for (i = 0; i < patch->npatch; ++i) PetscCall(VecDestroy(&patch->patch_dof_weights[i])); 28879566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->patch_dof_weights)); 28884bbf5ea8SMatthew G. Knepley } 28894bbf5ea8SMatthew G. Knepley if (patch->mat) { 28909566063dSJacob Faibussowitsch for (i = 0; i < patch->npatch; ++i) PetscCall(MatDestroy(&patch->mat[i])); 28919566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->mat)); 28925f824522SMatthew G. Knepley } 28930997d788SPatrick Farrell if (patch->matWithArtificial && !patch->isNonlinear) { 28949566063dSJacob Faibussowitsch for (i = 0; i < patch->npatch; ++i) PetscCall(MatDestroy(&patch->matWithArtificial[i])); 28959566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->matWithArtificial)); 289611ac8bb0SFlorian Wechsung } 28979566063dSJacob Faibussowitsch PetscCall(VecDestroy(&patch->patchRHSWithArtificial)); 289896b79ebeSFlorian Wechsung if (patch->dofMappingWithoutToWithArtificial) { 28999566063dSJacob Faibussowitsch for (i = 0; i < patch->npatch; ++i) PetscCall(ISDestroy(&patch->dofMappingWithoutToWithArtificial[i])); 29009566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->dofMappingWithoutToWithArtificial)); 290196b79ebeSFlorian Wechsung } 29020904074fSPatrick Farrell if (patch->dofMappingWithoutToWithAll) { 29039566063dSJacob Faibussowitsch for (i = 0; i < patch->npatch; ++i) PetscCall(ISDestroy(&patch->dofMappingWithoutToWithAll[i])); 29049566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->dofMappingWithoutToWithAll)); 29050904074fSPatrick Farrell } 29069566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->sub_mat_type)); 29075f824522SMatthew G. Knepley if (patch->userIS) { 29089566063dSJacob Faibussowitsch for (i = 0; i < patch->npatch; ++i) PetscCall(ISDestroy(&patch->userIS[i])); 29099566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->userIS)); 29105f824522SMatthew G. Knepley } 29119566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->precomputedTensorLocations)); 29129566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->precomputedIntFacetTensorLocations)); 2913f98464cbSLawrence Mitchell 29140a545947SLisandro Dalcin patch->bs = NULL; 29154bbf5ea8SMatthew G. Knepley patch->cellNodeMap = NULL; 29167974b488SMatthew G. Knepley patch->nsubspaces = 0; 29179566063dSJacob Faibussowitsch PetscCall(ISDestroy(&patch->iterationSet)); 29185f824522SMatthew G. Knepley 29199566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&patch->viewerSection)); 29204bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 29214bbf5ea8SMatthew G. Knepley } 29224bbf5ea8SMatthew G. Knepley 29239371c9d4SSatish Balay static PetscErrorCode PCDestroy_PATCH_Linear(PC pc) { 29244bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 29254bbf5ea8SMatthew G. Knepley PetscInt i; 29264bbf5ea8SMatthew G. Knepley 29274bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 2928dadc69c5SMatthew G. Knepley if (patch->solver) { 29299566063dSJacob Faibussowitsch for (i = 0; i < patch->npatch; ++i) PetscCall(KSPDestroy((KSP *)&patch->solver[i])); 29309566063dSJacob Faibussowitsch PetscCall(PetscFree(patch->solver)); 29314bbf5ea8SMatthew G. Knepley } 2932dadc69c5SMatthew G. Knepley PetscFunctionReturn(0); 2933dadc69c5SMatthew G. Knepley } 2934dadc69c5SMatthew G. Knepley 29359371c9d4SSatish Balay static PetscErrorCode PCDestroy_PATCH(PC pc) { 2936dadc69c5SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 2937dadc69c5SMatthew G. Knepley 2938dadc69c5SMatthew G. Knepley PetscFunctionBegin; 29399566063dSJacob Faibussowitsch PetscCall(PCReset_PATCH(pc)); 29409566063dSJacob Faibussowitsch PetscCall((*patch->destroysolver)(pc)); 29419566063dSJacob Faibussowitsch PetscCall(PetscFree(pc->data)); 29424bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 29434bbf5ea8SMatthew G. Knepley } 29444bbf5ea8SMatthew G. Knepley 29459371c9d4SSatish Balay static PetscErrorCode PCSetFromOptions_PATCH(PC pc, PetscOptionItems *PetscOptionsObject) { 29464bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 29474bbf5ea8SMatthew G. Knepley PCPatchConstructType patchConstructionType = PC_PATCH_STAR; 29485f824522SMatthew G. Knepley char sub_mat_type[PETSC_MAX_PATH_LEN]; 294910534d48SPatrick Farrell char option[PETSC_MAX_PATH_LEN]; 29505f824522SMatthew G. Knepley const char *prefix; 29514bbf5ea8SMatthew G. Knepley PetscBool flg, dimflg, codimflg; 29525f824522SMatthew G. Knepley MPI_Comm comm; 2953a48c39c8SPatrick Farrell PetscInt *ifields, nfields, k; 295461c4b389SFlorian Wechsung PCCompositeType loctype = PC_COMPOSITE_ADDITIVE; 29554bbf5ea8SMatthew G. Knepley 29564bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 29579566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)pc, &comm)); 29589566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)pc, &prefix)); 2959d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "Patch solver options"); 296010534d48SPatrick Farrell 29619566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_save_operators", patch->classname)); 29629566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool(option, "Store all patch operators for lifetime of object?", "PCPatchSetSaveOperators", patch->save_operators, &patch->save_operators, &flg)); 296310534d48SPatrick Farrell 29649566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_precompute_element_tensors", patch->classname)); 29659566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool(option, "Compute each element tensor only once?", "PCPatchSetPrecomputeElementTensors", patch->precomputeElementTensors, &patch->precomputeElementTensors, &flg)); 29669566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_partition_of_unity", patch->classname)); 29679566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool(option, "Weight contributions by dof multiplicity?", "PCPatchSetPartitionOfUnity", patch->partition_of_unity, &patch->partition_of_unity, &flg)); 296810534d48SPatrick Farrell 29699566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_local_type", patch->classname)); 29709566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum(option, "Type of local solver composition (additive or multiplicative)", "PCPatchSetLocalComposition", PCCompositeTypes, (PetscEnum)loctype, (PetscEnum *)&loctype, &flg)); 29719566063dSJacob Faibussowitsch if (flg) PetscCall(PCPatchSetLocalComposition(pc, loctype)); 29729566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_dense_inverse", patch->classname)); 29739566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool(option, "Compute inverses of patch matrices and apply directly? Ignores KSP/PC settings on patch.", "PCPatchSetDenseInverse", patch->denseinverse, &patch->denseinverse, &flg)); 29749566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_construct_dim", patch->classname)); 29759566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt(option, "What dimension of mesh point to construct patches by? (0 = vertices)", "PCPATCH", patch->dim, &patch->dim, &dimflg)); 29769566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_construct_codim", patch->classname)); 29779566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt(option, "What co-dimension of mesh point to construct patches by? (0 = cells)", "PCPATCH", patch->codim, &patch->codim, &codimflg)); 297808401ef6SPierre Jolivet PetscCheck(!dimflg || !codimflg, comm, PETSC_ERR_ARG_WRONG, "Can only set one of dimension or co-dimension"); 297910534d48SPatrick Farrell 29809566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_construct_type", patch->classname)); 29819566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum(option, "How should the patches be constructed?", "PCPatchSetConstructType", PCPatchConstructTypes, (PetscEnum)patchConstructionType, (PetscEnum *)&patchConstructionType, &flg)); 29829566063dSJacob Faibussowitsch if (flg) PetscCall(PCPatchSetConstructType(pc, patchConstructionType, NULL, NULL)); 298310534d48SPatrick Farrell 29849566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_vanka_dim", patch->classname)); 29859566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt(option, "Topological dimension of entities for Vanka to ignore", "PCPATCH", patch->vankadim, &patch->vankadim, &flg)); 298610534d48SPatrick Farrell 29879566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_ignore_dim", patch->classname)); 29889566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt(option, "Topological dimension of entities for completion to ignore", "PCPATCH", patch->ignoredim, &patch->ignoredim, &flg)); 298910534d48SPatrick Farrell 29909566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_pardecomp_overlap", patch->classname)); 29919566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt(option, "What overlap should we use in construct type pardecomp?", "PCPATCH", patch->pardecomp_overlap, &patch->pardecomp_overlap, &flg)); 2992b525f888SPatrick Farrell 29939566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_sub_mat_type", patch->classname)); 29949566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList(option, "Matrix type for patch solves", "PCPatchSetSubMatType", MatList, NULL, sub_mat_type, PETSC_MAX_PATH_LEN, &flg)); 29959566063dSJacob Faibussowitsch if (flg) PetscCall(PCPatchSetSubMatType(pc, sub_mat_type)); 299610534d48SPatrick Farrell 29979566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_symmetrise_sweep", patch->classname)); 29989566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool(option, "Go start->end, end->start?", "PCPATCH", patch->symmetrise_sweep, &patch->symmetrise_sweep, &flg)); 2999e4c66b91SPatrick Farrell 3000a48c39c8SPatrick Farrell /* If the user has set the number of subspaces, use that for the buffer size, 3001a48c39c8SPatrick Farrell otherwise use a large number */ 3002a48c39c8SPatrick Farrell if (patch->nsubspaces <= 0) { 3003a48c39c8SPatrick Farrell nfields = 128; 3004a48c39c8SPatrick Farrell } else { 3005a48c39c8SPatrick Farrell nfields = patch->nsubspaces; 3006a48c39c8SPatrick Farrell } 30079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nfields, &ifields)); 30089566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_exclude_subspaces", patch->classname)); 30099566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetIntArray(((PetscObject)pc)->options, ((PetscObject)pc)->prefix, option, ifields, &nfields, &flg)); 301008401ef6SPierre 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"); 3011e4c66b91SPatrick Farrell if (flg) { 30129566063dSJacob Faibussowitsch PetscCall(PetscHSetIClear(patch->subspaces_to_exclude)); 3013*48a46eb9SPierre Jolivet for (k = 0; k < nfields; k++) PetscCall(PetscHSetIAdd(patch->subspaces_to_exclude, ifields[k])); 3014e4c66b91SPatrick Farrell } 30159566063dSJacob Faibussowitsch PetscCall(PetscFree(ifields)); 30165f824522SMatthew G. Knepley 30179566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_patches_view", patch->classname)); 30189566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool(option, "Print out information during patch construction", "PCPATCH", patch->viewPatches, &patch->viewPatches, &flg)); 30199566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_cells_view", patch->classname)); 30209566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, ((PetscObject)pc)->options, prefix, option, &patch->viewerCells, &patch->formatCells, &patch->viewCells)); 30219566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_interior_facets_view", patch->classname)); 30229566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, ((PetscObject)pc)->options, prefix, option, &patch->viewerIntFacets, &patch->formatIntFacets, &patch->viewIntFacets)); 30239566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_exterior_facets_view", patch->classname)); 30249566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, ((PetscObject)pc)->options, prefix, option, &patch->viewerExtFacets, &patch->formatExtFacets, &patch->viewExtFacets)); 30259566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_points_view", patch->classname)); 30269566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, ((PetscObject)pc)->options, prefix, option, &patch->viewerPoints, &patch->formatPoints, &patch->viewPoints)); 30279566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_section_view", patch->classname)); 30289566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, ((PetscObject)pc)->options, prefix, option, &patch->viewerSection, &patch->formatSection, &patch->viewSection)); 30299566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(option, PETSC_MAX_PATH_LEN, "-%s_patch_mat_view", patch->classname)); 30309566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetViewer(comm, ((PetscObject)pc)->options, prefix, option, &patch->viewerMatrix, &patch->formatMatrix, &patch->viewMatrix)); 3031d0609cedSBarry Smith PetscOptionsHeadEnd(); 30325f824522SMatthew G. Knepley patch->optionsSet = PETSC_TRUE; 30334bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 30344bbf5ea8SMatthew G. Knepley } 30354bbf5ea8SMatthew G. Knepley 30369371c9d4SSatish Balay static PetscErrorCode PCSetUpOnBlocks_PATCH(PC pc) { 30374bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 30384bbf5ea8SMatthew G. Knepley KSPConvergedReason reason; 30394bbf5ea8SMatthew G. Knepley PetscInt i; 30404bbf5ea8SMatthew G. Knepley 30414bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 3042a1eac568SLawrence Mitchell if (!patch->save_operators) { 3043a1eac568SLawrence Mitchell /* Can't do this here because the sub KSPs don't have an operator attached yet. */ 3044a1eac568SLawrence Mitchell PetscFunctionReturn(0); 3045a1eac568SLawrence Mitchell } 3046c73d2cf6SLawrence Mitchell if (patch->denseinverse) { 3047c73d2cf6SLawrence Mitchell /* No solvers */ 3048c73d2cf6SLawrence Mitchell PetscFunctionReturn(0); 3049c73d2cf6SLawrence Mitchell } 30504bbf5ea8SMatthew G. Knepley for (i = 0; i < patch->npatch; ++i) { 3051*48a46eb9SPierre Jolivet if (!((KSP)patch->solver[i])->setfromoptionscalled) PetscCall(KSPSetFromOptions((KSP)patch->solver[i])); 30529566063dSJacob Faibussowitsch PetscCall(KSPSetUp((KSP)patch->solver[i])); 30539566063dSJacob Faibussowitsch PetscCall(KSPGetConvergedReason((KSP)patch->solver[i], &reason)); 3054c0decd05SBarry Smith if (reason == KSP_DIVERGED_PC_FAILED) pc->failedreason = PC_SUBPC_ERROR; 30554bbf5ea8SMatthew G. Knepley } 30564bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 30574bbf5ea8SMatthew G. Knepley } 30584bbf5ea8SMatthew G. Knepley 30599371c9d4SSatish Balay static PetscErrorCode PCView_PATCH(PC pc, PetscViewer viewer) { 30604bbf5ea8SMatthew G. Knepley PC_PATCH *patch = (PC_PATCH *)pc->data; 30614bbf5ea8SMatthew G. Knepley PetscViewer sviewer; 30624bbf5ea8SMatthew G. Knepley PetscBool isascii; 30634bbf5ea8SMatthew G. Knepley PetscMPIInt rank; 30644bbf5ea8SMatthew G. Knepley 30654bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 30664bbf5ea8SMatthew G. Knepley /* TODO Redo tabbing with set tbas in new style */ 30679566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 30684bbf5ea8SMatthew G. Knepley if (!isascii) PetscFunctionReturn(0); 30699566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc), &rank)); 30709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 307163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Subspace Correction preconditioner with %" PetscInt_FMT " patches\n", patch->npatch)); 307261c4b389SFlorian Wechsung if (patch->local_composition_type == PC_COMPOSITE_MULTIPLICATIVE) { 30739566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Schwarz type: multiplicative\n")); 3074e047a90bSFlorian Wechsung } else { 30759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Schwarz type: additive\n")); 3076c2e6f3c0SFlorian Wechsung } 30779566063dSJacob Faibussowitsch if (patch->partition_of_unity) PetscCall(PetscViewerASCIIPrintf(viewer, "Weighting by partition of unity\n")); 30789566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Not weighting by partition of unity\n")); 30799566063dSJacob Faibussowitsch if (patch->symmetrise_sweep) PetscCall(PetscViewerASCIIPrintf(viewer, "Symmetrising sweep (start->end, then end->start)\n")); 30809566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Not symmetrising sweep\n")); 30819566063dSJacob Faibussowitsch if (!patch->precomputeElementTensors) PetscCall(PetscViewerASCIIPrintf(viewer, "Not precomputing element tensors (overlapping cells rebuilt in every patch assembly)\n")); 30829566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Precomputing element tensors (each cell assembled only once)\n")); 30839566063dSJacob Faibussowitsch if (!patch->save_operators) PetscCall(PetscViewerASCIIPrintf(viewer, "Not saving patch operators (rebuilt every PCApply)\n")); 30849566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Saving patch operators (rebuilt every PCSetUp)\n")); 30859566063dSJacob Faibussowitsch if (patch->patchconstructop == PCPatchConstruct_Star) PetscCall(PetscViewerASCIIPrintf(viewer, "Patch construction operator: star\n")); 30869566063dSJacob Faibussowitsch else if (patch->patchconstructop == PCPatchConstruct_Vanka) PetscCall(PetscViewerASCIIPrintf(viewer, "Patch construction operator: Vanka\n")); 30879566063dSJacob Faibussowitsch else if (patch->patchconstructop == PCPatchConstruct_User) PetscCall(PetscViewerASCIIPrintf(viewer, "Patch construction operator: user-specified\n")); 30889566063dSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Patch construction operator: unknown\n")); 30895d30859aSPatrick Farrell 3090c73d2cf6SLawrence Mitchell if (patch->denseinverse) { 30919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Explicitly forming dense inverse and applying patch solver via MatMult.\n")); 3092c73d2cf6SLawrence Mitchell } else { 30935d30859aSPatrick Farrell if (patch->isNonlinear) { 30949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "SNES on patches (all same):\n")); 30955d30859aSPatrick Farrell } else { 30969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "KSP on patches (all same):\n")); 30975d30859aSPatrick Farrell } 3098dadc69c5SMatthew G. Knepley if (patch->solver) { 30999566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 3100dd400576SPatrick Sanan if (rank == 0) { 31019566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(sviewer)); 31029566063dSJacob Faibussowitsch PetscCall(PetscObjectView(patch->solver[0], sviewer)); 31039566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(sviewer)); 31044bbf5ea8SMatthew G. Knepley } 31059566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 31064bbf5ea8SMatthew G. Knepley } else { 31079566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 31089566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Solver not yet set.\n")); 31099566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 31104bbf5ea8SMatthew G. Knepley } 3111c73d2cf6SLawrence Mitchell } 31129566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 31134bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 31144bbf5ea8SMatthew G. Knepley } 31154bbf5ea8SMatthew G. Knepley 3116e5893cccSMatthew G. Knepley /*MC 311798ed095eSMatthew G. Knepley PCPATCH - A PC object that encapsulates flexible definition of blocks for overlapping and non-overlapping 311898ed095eSMatthew G. Knepley small block additive preconditioners. Block definition is based on topology from 3119e5893cccSMatthew G. Knepley a DM and equation numbering from a PetscSection. 3120e5893cccSMatthew G. Knepley 3121e5893cccSMatthew G. Knepley Options Database Keys: 3122e5893cccSMatthew G. Knepley + -pc_patch_cells_view - Views the process local cell numbers for each patch 3123e5893cccSMatthew G. Knepley . -pc_patch_points_view - Views the process local mesh point numbers for each patch 3124e5893cccSMatthew G. Knepley . -pc_patch_g2l_view - Views the map between global dofs and patch local dofs for each patch 3125e5893cccSMatthew G. Knepley . -pc_patch_patches_view - Views the global dofs associated with each patch and its boundary 3126e5893cccSMatthew G. Knepley - -pc_patch_sub_mat_view - Views the matrix associated with each patch 3127e5893cccSMatthew G. Knepley 3128e5893cccSMatthew G. Knepley Level: intermediate 3129e5893cccSMatthew G. Knepley 3130db781477SPatrick Sanan .seealso: `PCType`, `PCCreate()`, `PCSetType()` 3131e5893cccSMatthew G. Knepley M*/ 31329371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PCCreate_Patch(PC pc) { 31334bbf5ea8SMatthew G. Knepley PC_PATCH *patch; 31344bbf5ea8SMatthew G. Knepley 31354bbf5ea8SMatthew G. Knepley PetscFunctionBegin; 31369566063dSJacob Faibussowitsch PetscCall(PetscNewLog(pc, &patch)); 31374bbf5ea8SMatthew G. Knepley 3138*48a46eb9SPierre Jolivet if (patch->subspaces_to_exclude) PetscCall(PetscHSetIDestroy(&patch->subspaces_to_exclude)); 31399566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&patch->subspaces_to_exclude)); 3140e4c66b91SPatrick Farrell 314110534d48SPatrick Farrell patch->classname = "pc"; 3142debbdec3SPatrick Farrell patch->isNonlinear = PETSC_FALSE; 314310534d48SPatrick Farrell 31444bbf5ea8SMatthew G. Knepley /* Set some defaults */ 31455f824522SMatthew G. Knepley patch->combined = PETSC_FALSE; 31464bbf5ea8SMatthew G. Knepley patch->save_operators = PETSC_TRUE; 314761c4b389SFlorian Wechsung patch->local_composition_type = PC_COMPOSITE_ADDITIVE; 3148fa84ea4cSLawrence Mitchell patch->precomputeElementTensors = PETSC_FALSE; 31494bbf5ea8SMatthew G. Knepley patch->partition_of_unity = PETSC_FALSE; 31504bbf5ea8SMatthew G. Knepley patch->codim = -1; 31514bbf5ea8SMatthew G. Knepley patch->dim = -1; 31524bbf5ea8SMatthew G. Knepley patch->vankadim = -1; 31535f824522SMatthew G. Knepley patch->ignoredim = -1; 3154b525f888SPatrick Farrell patch->pardecomp_overlap = 0; 31554bbf5ea8SMatthew G. Knepley patch->patchconstructop = PCPatchConstruct_Star; 31564bbf5ea8SMatthew G. Knepley patch->symmetrise_sweep = PETSC_FALSE; 31575f824522SMatthew G. Knepley patch->npatch = 0; 31584bbf5ea8SMatthew G. Knepley patch->userIS = NULL; 31595f824522SMatthew G. Knepley patch->optionsSet = PETSC_FALSE; 31604bbf5ea8SMatthew G. Knepley patch->iterationSet = NULL; 31614bbf5ea8SMatthew G. Knepley patch->user_patches = PETSC_FALSE; 31629566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATDENSE, (char **)&patch->sub_mat_type)); 31635f824522SMatthew G. Knepley patch->viewPatches = PETSC_FALSE; 31645f824522SMatthew G. Knepley patch->viewCells = PETSC_FALSE; 31655f824522SMatthew G. Knepley patch->viewPoints = PETSC_FALSE; 31665f824522SMatthew G. Knepley patch->viewSection = PETSC_FALSE; 31675f824522SMatthew G. Knepley patch->viewMatrix = PETSC_FALSE; 31689d4fc724SLawrence Mitchell patch->densesolve = NULL; 3169dadc69c5SMatthew G. Knepley patch->setupsolver = PCSetUp_PATCH_Linear; 3170dadc69c5SMatthew G. Knepley patch->applysolver = PCApply_PATCH_Linear; 3171dadc69c5SMatthew G. Knepley patch->resetsolver = PCReset_PATCH_Linear; 3172dadc69c5SMatthew G. Knepley patch->destroysolver = PCDestroy_PATCH_Linear; 31736c9c532dSPatrick Farrell patch->updatemultiplicative = PCUpdateMultiplicative_PATCH_Linear; 317447aca4a6SPatrick Farrell patch->dofMappingWithoutToWithArtificial = NULL; 317547aca4a6SPatrick Farrell patch->dofMappingWithoutToWithAll = NULL; 31764bbf5ea8SMatthew G. Knepley 31774bbf5ea8SMatthew G. Knepley pc->data = (void *)patch; 31784bbf5ea8SMatthew G. Knepley pc->ops->apply = PCApply_PATCH; 31790a545947SLisandro Dalcin pc->ops->applytranspose = NULL; /* PCApplyTranspose_PATCH; */ 31804bbf5ea8SMatthew G. Knepley pc->ops->setup = PCSetUp_PATCH; 31814bbf5ea8SMatthew G. Knepley pc->ops->reset = PCReset_PATCH; 31824bbf5ea8SMatthew G. Knepley pc->ops->destroy = PCDestroy_PATCH; 31834bbf5ea8SMatthew G. Knepley pc->ops->setfromoptions = PCSetFromOptions_PATCH; 31844bbf5ea8SMatthew G. Knepley pc->ops->setuponblocks = PCSetUpOnBlocks_PATCH; 31854bbf5ea8SMatthew G. Knepley pc->ops->view = PCView_PATCH; 31860a545947SLisandro Dalcin pc->ops->applyrichardson = NULL; 31874bbf5ea8SMatthew G. Knepley 31884bbf5ea8SMatthew G. Knepley PetscFunctionReturn(0); 31894bbf5ea8SMatthew G. Knepley } 3190