Actual source code: or.c

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

  4: /*@
  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: `VecTagger`, `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: /*@
 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: `VecTagger`, `VecTaggerOrGetSubs()`
 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:       for (PetscInt j = 0; j < i; j++) PetscCall(PetscFree(subBoxes[j]));
 65:       PetscCall(PetscFree2(numSubBoxes, subBoxes));
 66:       if (listed) *listed = PETSC_FALSE;
 67:     }
 68:     total += numSubBoxes[i];
 69:   }
 70:   PetscCall(PetscMalloc1(bs * total, &bxs));
 71:   for (i = 0, nboxes = 0; i < nsubs; i++) { /* stupid O(N^2) check to remove subboxes */
 72:     for (PetscInt j = 0; j < numSubBoxes[i]; j++) {
 73:       PetscInt      k;
 74:       VecTaggerBox *subBox = &subBoxes[i][j * bs];

 76:       for (k = 0; k < nboxes; k++) {
 77:         PetscBool isSub = PETSC_FALSE;

 79:         VecTaggerBox *prevBox = &bxs[bs * k];
 80:         PetscCall(VecTaggerAndOrIsSubBox_Private(bs, prevBox, subBox, &isSub));
 81:         if (isSub) break;
 82:         PetscCall(VecTaggerAndOrIsSubBox_Private(bs, subBox, prevBox, &isSub));
 83:         if (isSub) {
 84:           for (PetscInt l = 0; l < bs; l++) prevBox[l] = subBox[l];
 85:           break;
 86:         }
 87:       }
 88:       if (k < nboxes) continue;
 89:       for (k = 0; k < bs; k++) bxs[nboxes * bs + k] = subBox[k];
 90:       nboxes++;
 91:     }
 92:     PetscCall(PetscFree(subBoxes[i]));
 93:   }
 94:   PetscCall(PetscFree2(numSubBoxes, subBoxes));
 95:   *numBoxes = nboxes;
 96:   *boxes    = bxs;
 97:   if (listed) *listed = PETSC_TRUE;
 98:   PetscFunctionReturn(PETSC_SUCCESS);
 99: }

101: static PetscErrorCode VecTaggerComputeIS_Or(VecTagger tagger, Vec vec, IS *is, PetscBool *listed)
102: {
103:   PetscInt   nsubs;
104:   VecTagger *subs;
105:   IS         unionIS;
106:   PetscBool  boxlisted;

108:   PetscFunctionBegin;
109:   PetscCall(VecTaggerComputeIS_FromBoxes(tagger, vec, is, &boxlisted));
110:   if (boxlisted) {
111:     if (listed) *listed = PETSC_TRUE;
112:     PetscFunctionReturn(PETSC_SUCCESS);
113:   }
114:   PetscCall(VecTaggerOrGetSubs(tagger, &nsubs, &subs));
115:   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)vec), 0, NULL, PETSC_OWN_POINTER, &unionIS));
116:   for (PetscInt i = 0; i < nsubs; i++) {
117:     IS subIS, newUnionIS;

119:     PetscCall(VecTaggerComputeIS(subs[i], vec, &subIS, &boxlisted));
120:     PetscCheck(boxlisted, PetscObjectComm((PetscObject)tagger), PETSC_ERR_SUP, "Tagger cannot VecTaggerComputeIS()");
121:     PetscCall(ISExpand(unionIS, subIS, &newUnionIS));
122:     PetscCall(ISSort(newUnionIS));
123:     PetscCall(ISDestroy(&unionIS));
124:     unionIS = newUnionIS;
125:     PetscCall(ISDestroy(&subIS));
126:   }
127:   *is = unionIS;
128:   if (listed) *listed = PETSC_TRUE;
129:   PetscFunctionReturn(PETSC_SUCCESS);
130: }

132: PETSC_INTERN PetscErrorCode VecTaggerCreate_Or(VecTagger tagger)
133: {
134:   PetscFunctionBegin;
135:   PetscCall(VecTaggerCreate_AndOr(tagger));
136:   tagger->ops->computeboxes = VecTaggerComputeBoxes_Or;
137:   tagger->ops->computeis    = VecTaggerComputeIS_Or;
138:   PetscFunctionReturn(PETSC_SUCCESS);
139: }