Actual source code: or.c

      1: #include <petsc/private/vecimpl.h>
      2: #include "../src/vec/vec/utils/tagger/impls/andor.h"

      4: /*@C
      5:   VecTaggerOrGetSubs - Get the sub `VecTagger`s whose union defines the outer `VecTagger`

      7:   Not Collective

      9:   Input Parameter:
     10: . tagger - the `VecTagger` context

     12:   Output Parameters:
     13: + nsubs - the number of sub `VecTagger`s
     14: - subs  - the sub `VecTagger`s

     16:   Level: advanced

     18: .seealso: `VecTaggerOrSetSubs()`
     19: @*/
     20: PetscErrorCode VecTaggerOrGetSubs(VecTagger tagger, PetscInt *nsubs, VecTagger *subs[])
     21: {
     22:   PetscFunctionBegin;
     23:   PetscCall(VecTaggerGetSubs_AndOr(tagger, nsubs, subs));
     24:   PetscFunctionReturn(PETSC_SUCCESS);
     25: }

     27: /*@C
     28:   VecTaggerOrSetSubs - Set the sub `VecTagger`s whose union defines the outer `VecTagger`

     30:   Logically Collective

     32:   Input Parameters:
     33: + tagger - the `VecTagger` context
     34: . nsubs  - the number of sub `VecTagger`s
     35: . subs   - the sub `VecTagger`s
     36: - mode   - the copy mode to use for `subs`

     38:   Level: advanced

     40: .seealso: `VecTaggetOrGetStubs()`
     41: @*/
     42: PetscErrorCode VecTaggerOrSetSubs(VecTagger tagger, PetscInt nsubs, VecTagger subs[], PetscCopyMode mode)
     43: {
     44:   PetscFunctionBegin;
     45:   PetscCall(VecTaggerSetSubs_AndOr(tagger, nsubs, subs, mode));
     46:   PetscFunctionReturn(PETSC_SUCCESS);
     47: }

     49: static PetscErrorCode VecTaggerComputeBoxes_Or(VecTagger tagger, Vec vec, PetscInt *numBoxes, VecTaggerBox **boxes, PetscBool *listed)
     50: {
     51:   PetscInt       i, bs, nsubs, *numSubBoxes, nboxes, total;
     52:   VecTaggerBox **subBoxes;
     53:   VecTagger     *subs;
     54:   VecTaggerBox  *bxs;
     55:   PetscBool      boxlisted;

     57:   PetscFunctionBegin;
     58:   PetscCall(VecTaggerGetBlockSize(tagger, &bs));
     59:   PetscCall(VecTaggerOrGetSubs(tagger, &nsubs, &subs));
     60:   PetscCall(PetscMalloc2(nsubs, &numSubBoxes, nsubs, &subBoxes));
     61:   for (i = 0, total = 0; i < nsubs; i++) {
     62:     PetscCall(VecTaggerComputeBoxes(subs[i], vec, &numSubBoxes[i], &subBoxes[i], &boxlisted));
     63:     if (!boxlisted) { /* no support, clean up and exit */
     64:       PetscInt j;

     66:       for (j = 0; j < i; j++) PetscCall(PetscFree(subBoxes[j]));
     67:       PetscCall(PetscFree2(numSubBoxes, subBoxes));
     68:       if (listed) *listed = PETSC_FALSE;
     69:     }
     70:     total += numSubBoxes[i];
     71:   }
     72:   PetscCall(PetscMalloc1(bs * total, &bxs));
     73:   for (i = 0, nboxes = 0; i < nsubs; i++) { /* stupid O(N^2) check to remove subboxes */
     74:     PetscInt j;

     76:     for (j = 0; j < numSubBoxes[i]; j++) {
     77:       PetscInt      k;
     78:       VecTaggerBox *subBox = &subBoxes[i][j * bs];

     80:       for (k = 0; k < nboxes; k++) {
     81:         PetscBool isSub = PETSC_FALSE;

     83:         VecTaggerBox *prevBox = &bxs[bs * k];
     84:         PetscCall(VecTaggerAndOrIsSubBox_Private(bs, prevBox, subBox, &isSub));
     85:         if (isSub) break;
     86:         PetscCall(VecTaggerAndOrIsSubBox_Private(bs, subBox, prevBox, &isSub));
     87:         if (isSub) {
     88:           PetscInt l;

     90:           for (l = 0; l < bs; l++) prevBox[l] = subBox[l];
     91:           break;
     92:         }
     93:       }
     94:       if (k < nboxes) continue;
     95:       for (k = 0; k < bs; k++) bxs[nboxes * bs + k] = subBox[k];
     96:       nboxes++;
     97:     }
     98:     PetscCall(PetscFree(subBoxes[i]));
     99:   }
    100:   PetscCall(PetscFree2(numSubBoxes, subBoxes));
    101:   *numBoxes = nboxes;
    102:   *boxes    = bxs;
    103:   if (listed) *listed = PETSC_TRUE;
    104:   PetscFunctionReturn(PETSC_SUCCESS);
    105: }

    107: static PetscErrorCode VecTaggerComputeIS_Or(VecTagger tagger, Vec vec, IS *is, PetscBool *listed)
    108: {
    109:   PetscInt   nsubs, i;
    110:   VecTagger *subs;
    111:   IS         unionIS;
    112:   PetscBool  boxlisted;

    114:   PetscFunctionBegin;
    115:   PetscCall(VecTaggerComputeIS_FromBoxes(tagger, vec, is, &boxlisted));
    116:   if (boxlisted) {
    117:     if (listed) *listed = PETSC_TRUE;
    118:     PetscFunctionReturn(PETSC_SUCCESS);
    119:   }
    120:   PetscCall(VecTaggerOrGetSubs(tagger, &nsubs, &subs));
    121:   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)vec), 0, NULL, PETSC_OWN_POINTER, &unionIS));
    122:   for (i = 0; i < nsubs; i++) {
    123:     IS subIS, newUnionIS;

    125:     PetscCall(VecTaggerComputeIS(subs[i], vec, &subIS, &boxlisted));
    126:     PetscCheck(boxlisted, PetscObjectComm((PetscObject)tagger), PETSC_ERR_SUP, "Tagger cannot VecTaggerComputeIS()");
    127:     PetscCall(ISExpand(unionIS, subIS, &newUnionIS));
    128:     PetscCall(ISSort(newUnionIS));
    129:     PetscCall(ISDestroy(&unionIS));
    130:     unionIS = newUnionIS;
    131:     PetscCall(ISDestroy(&subIS));
    132:   }
    133:   *is = unionIS;
    134:   if (listed) *listed = PETSC_TRUE;
    135:   PetscFunctionReturn(PETSC_SUCCESS);
    136: }

    138: PETSC_INTERN PetscErrorCode VecTaggerCreate_Or(VecTagger tagger)
    139: {
    140:   PetscFunctionBegin;
    141:   PetscCall(VecTaggerCreate_AndOr(tagger));
    142:   tagger->ops->computeboxes = VecTaggerComputeBoxes_Or;
    143:   tagger->ops->computeis    = VecTaggerComputeIS_Or;
    144:   PetscFunctionReturn(PETSC_SUCCESS);
    145: }