Date: 2025-03-28T21:10:44+00:00

Actual source code: dmfieldshell.c

      1: #include <petsc/private/dmfieldimpl.h>

      3: typedef struct _n_DMField_Shell {
      4:   void *ctx;
      5:   PetscErrorCode (*destroy)(DMField);
      6: } DMField_Shell;

      8: PetscErrorCode DMFieldShellGetContext(DMField field, void *ctx)
      9: {
     10:   PetscBool flg;

     12:   PetscFunctionBegin;
     14:   PetscAssertPointer(ctx, 2);
     15:   PetscCall(PetscObjectTypeCompare((PetscObject)field, DMFIELDSHELL, &flg));
     16:   if (flg) *(void **)ctx = ((DMField_Shell *)field->data)->ctx;
     17:   else SETERRQ(PetscObjectComm((PetscObject)field), PETSC_ERR_SUP, "Cannot get context from non-shell shield");
     18:   PetscFunctionReturn(PETSC_SUCCESS);
     19: }

     21: static PetscErrorCode DMFieldDestroy_Shell(DMField field)
     22: {
     23:   DMField_Shell *shell = (DMField_Shell *)field->data;

     25:   PetscFunctionBegin;
     26:   if (shell->destroy) PetscCall((*shell->destroy)(field));
     27:   PetscCall(PetscFree(field->data));
     28:   PetscFunctionReturn(PETSC_SUCCESS);
     29: }

     31: PetscErrorCode DMFieldShellEvaluateFEDefault(DMField field, IS pointIS, PetscQuadrature quad, PetscDataType type, void *B, void *D, void *H)
     32: {
     33:   DM           dm = field->dm;
     34:   DMField      coordField;
     35:   PetscFEGeom *geom;
     36:   Vec          pushforward;
     37:   PetscInt     dimC, dim, numPoints, Nq, p, Nc;
     38:   PetscScalar *pfArray;

     40:   PetscFunctionBegin;
     41:   Nc = field->numComponents;
     42:   PetscCall(DMGetCoordinateField(dm, &coordField));
     43:   PetscCall(DMFieldCreateFEGeom(coordField, pointIS, quad, PETSC_FALSE, &geom));
     44:   PetscCall(DMGetCoordinateDim(dm, &dimC));
     45:   PetscCall(PetscQuadratureGetData(quad, &dim, NULL, &Nq, NULL, NULL));
     46:   PetscCall(ISGetLocalSize(pointIS, &numPoints));
     47:   PetscCall(PetscMalloc1(dimC * Nq * numPoints, &pfArray));
     48:   for (p = 0; p < numPoints * dimC * Nq; p++) pfArray[p] = (PetscScalar)geom->v[p];
     49:   PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)pointIS), dimC, dimC * Nq * numPoints, PETSC_DETERMINE, pfArray, &pushforward));
     50:   PetscCall(DMFieldEvaluate(field, pushforward, type, B, D, H));
     51:   /* TODO: handle covariant/contravariant pullbacks */
     52:   if (D) {
     53:     if (type == PETSC_SCALAR) {
     54:       PetscScalar *sD = (PetscScalar *)D;
     55:       PetscInt     q;

     57:       for (p = 0; p < numPoints * Nq; p++) {
     58:         for (q = 0; q < Nc; q++) {
     59:           PetscScalar d[3];

     61:           PetscInt i, j;

     63:           for (i = 0; i < dimC; i++) d[i] = sD[(p * Nc + q) * dimC + i];
     64:           for (i = 0; i < dimC; i++) sD[(p * Nc + q) * dimC + i] = 0.;
     65:           for (i = 0; i < dimC; i++) {
     66:             for (j = 0; j < dimC; j++) sD[(p * Nc + q) * dimC + i] += geom->J[(p * dimC + j) * dimC + i] * d[j];
     67:           }
     68:         }
     69:       }
     70:     } else {
     71:       PetscReal *rD = (PetscReal *)D;
     72:       PetscInt   q;

     74:       for (p = 0; p < numPoints * Nq; p++) {
     75:         for (q = 0; q < Nc; q++) {
     76:           PetscReal d[3];

     78:           PetscInt i, j;

     80:           for (i = 0; i < dimC; i++) d[i] = rD[(p * Nc + q) * dimC + i];
     81:           for (i = 0; i < dimC; i++) rD[(p * Nc + q) * dimC + i] = 0.;
     82:           for (i = 0; i < dimC; i++) {
     83:             for (j = 0; j < dimC; j++) rD[(p * Nc + q) * dimC + i] += geom->J[(p * dimC + j) * dimC + i] * d[j];
     84:           }
     85:         }
     86:       }
     87:     }
     88:   }
     89:   if (H) {
     90:     if (type == PETSC_SCALAR) {
     91:       PetscScalar *sH = (PetscScalar *)H;
     92:       PetscInt     q;

     94:       for (p = 0; p < numPoints * Nq; p++) {
     95:         for (q = 0; q < Nc; q++) {
     96:           PetscScalar d[3][3];

     98:           PetscInt i, j, k, l;

    100:           for (i = 0; i < dimC; i++)
    101:             for (j = 0; j < dimC; j++) d[i][j] = sH[((p * Nc + q) * dimC + i) * dimC + j];
    102:           for (i = 0; i < dimC; i++)
    103:             for (j = 0; j < dimC; j++) sH[((p * Nc + q) * dimC + i) * dimC + j] = 0.;
    104:           for (i = 0; i < dimC; i++) {
    105:             for (j = 0; j < dimC; j++) {
    106:               for (k = 0; k < dimC; k++) {
    107:                 for (l = 0; l < dimC; l++) sH[((p * Nc + q) * dimC + i) * dimC + j] += geom->J[(p * dimC + k) * dimC + i] * geom->J[(p * dimC + l) * dimC + j] * d[k][l];
    108:               }
    109:             }
    110:           }
    111:         }
    112:       }
    113:     } else {
    114:       PetscReal *rH = (PetscReal *)H;
    115:       PetscInt   q;

    117:       for (p = 0; p < numPoints * Nq; p++) {
    118:         for (q = 0; q < Nc; q++) {
    119:           PetscReal d[3][3];

    121:           PetscInt i, j, k, l;

    123:           for (i = 0; i < dimC; i++)
    124:             for (j = 0; j < dimC; j++) d[i][j] = rH[((p * Nc + q) * dimC + i) * dimC + j];
    125:           for (i = 0; i < dimC; i++)
    126:             for (j = 0; j < dimC; j++) rH[((p * Nc + q) * dimC + i) * dimC + j] = 0.;
    127:           for (i = 0; i < dimC; i++) {
    128:             for (j = 0; j < dimC; j++) {
    129:               for (k = 0; k < dimC; k++) {
    130:                 for (l = 0; l < dimC; l++) rH[((p * Nc + q) * dimC + i) * dimC + j] += geom->J[(p * dimC + k) * dimC + i] * geom->J[(p * dimC + l) * dimC + j] * d[k][l];
    131:               }
    132:             }
    133:           }
    134:         }
    135:       }
    136:     }
    137:   }
    138:   PetscCall(VecDestroy(&pushforward));
    139:   PetscCall(PetscFree(pfArray));
    140:   PetscCall(PetscFEGeomDestroy(&geom));
    141:   PetscFunctionReturn(PETSC_SUCCESS);
    142: }

    144: PetscErrorCode DMFieldShellEvaluateFVDefault(DMField field, IS pointIS, PetscDataType type, void *B, void *D, void *H)
    145: {
    146:   DM              dm = field->dm;
    147:   DMField         coordField;
    148:   PetscFEGeom    *geom;
    149:   Vec             pushforward;
    150:   PetscInt        dimC, dim, numPoints, Nq, p;
    151:   PetscScalar    *pfArray;
    152:   PetscQuadrature quad;
    153:   MPI_Comm        comm;

    155:   PetscFunctionBegin;
    156:   PetscCall(PetscObjectGetComm((PetscObject)field, &comm));
    157:   PetscCall(DMGetDimension(dm, &dim));
    158:   PetscCall(DMGetCoordinateDim(dm, &dimC));
    159:   PetscCall(DMGetCoordinateField(dm, &coordField));
    160:   PetscCall(DMFieldGetFVQuadrature_Internal(coordField, pointIS, &quad));
    161:   PetscCheck(quad, comm, PETSC_ERR_ARG_WRONGSTATE, "coordinate field must have default quadrature for FV computation");
    162:   PetscCall(PetscQuadratureGetData(quad, NULL, NULL, &Nq, NULL, NULL));
    163:   PetscCheck(Nq == 1, comm, PETSC_ERR_ARG_WRONGSTATE, "quadrature must have only one point");
    164:   PetscCall(DMFieldCreateFEGeom(coordField, pointIS, quad, PETSC_FALSE, &geom));
    165:   PetscCall(ISGetLocalSize(pointIS, &numPoints));
    166:   PetscCall(PetscMalloc1(dimC * numPoints, &pfArray));
    167:   for (p = 0; p < numPoints * dimC; p++) pfArray[p] = (PetscScalar)geom->v[p];
    168:   PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)pointIS), dimC, dimC * numPoints, PETSC_DETERMINE, pfArray, &pushforward));
    169:   PetscCall(DMFieldEvaluate(field, pushforward, type, B, D, H));
    170:   PetscCall(PetscQuadratureDestroy(&quad));
    171:   PetscCall(VecDestroy(&pushforward));
    172:   PetscCall(PetscFree(pfArray));
    173:   PetscCall(PetscFEGeomDestroy(&geom));
    174:   PetscFunctionReturn(PETSC_SUCCESS);
    175: }

    177: PetscErrorCode DMFieldShellSetDestroy(DMField field, PetscErrorCode (*destroy)(DMField))
    178: {
    179:   DMField_Shell *shell = (DMField_Shell *)field->data;

    181:   PetscFunctionBegin;
    183:   shell->destroy = destroy;
    184:   PetscFunctionReturn(PETSC_SUCCESS);
    185: }

    187: PetscErrorCode DMFieldShellSetEvaluate(DMField field, PetscErrorCode (*evaluate)(DMField, Vec, PetscDataType, void *, void *, void *))
    188: {
    189:   PetscFunctionBegin;
    191:   field->ops->evaluate = evaluate;
    192:   PetscFunctionReturn(PETSC_SUCCESS);
    193: }

    195: PetscErrorCode DMFieldShellSetEvaluateFE(DMField field, PetscErrorCode (*evaluateFE)(DMField, IS, PetscQuadrature, PetscDataType, void *, void *, void *))
    196: {
    197:   PetscFunctionBegin;
    199:   field->ops->evaluateFE = evaluateFE;
    200:   PetscFunctionReturn(PETSC_SUCCESS);
    201: }

    203: PetscErrorCode DMFieldShellSetEvaluateFV(DMField field, PetscErrorCode (*evaluateFV)(DMField, IS, PetscDataType, void *, void *, void *))
    204: {
    205:   PetscFunctionBegin;
    207:   field->ops->evaluateFV = evaluateFV;
    208:   PetscFunctionReturn(PETSC_SUCCESS);
    209: }

    211: PetscErrorCode DMFieldShellSetGetDegree(DMField field, PetscErrorCode (*getDegree)(DMField, IS, PetscInt *, PetscInt *))
    212: {
    213:   PetscFunctionBegin;
    215:   field->ops->getDegree = getDegree;
    216:   PetscFunctionReturn(PETSC_SUCCESS);
    217: }

    219: PetscErrorCode DMFieldShellSetCreateDefaultQuadrature(DMField field, PetscErrorCode (*createDefaultQuadrature)(DMField, IS, PetscQuadrature *))
    220: {
    221:   PetscFunctionBegin;
    223:   field->ops->createDefaultQuadrature = createDefaultQuadrature;
    224:   PetscFunctionReturn(PETSC_SUCCESS);
    225: }

    227: static PetscErrorCode DMFieldInitialize_Shell(DMField field)
    228: {
    229:   PetscFunctionBegin;
    230:   field->ops->destroy                 = DMFieldDestroy_Shell;
    231:   field->ops->evaluate                = NULL;
    232:   field->ops->evaluateFE              = DMFieldShellEvaluateFEDefault;
    233:   field->ops->evaluateFV              = DMFieldShellEvaluateFVDefault;
    234:   field->ops->getDegree               = NULL;
    235:   field->ops->createDefaultQuadrature = NULL;
    236:   field->ops->view                    = NULL;
    237:   PetscFunctionReturn(PETSC_SUCCESS);
    238: }

    240: PETSC_INTERN PetscErrorCode DMFieldCreate_Shell(DMField field)
    241: {
    242:   DMField_Shell *shell;

    244:   PetscFunctionBegin;
    245:   PetscCall(PetscNew(&shell));
    246:   field->data = shell;
    247:   PetscCall(DMFieldInitialize_Shell(field));
    248:   PetscFunctionReturn(PETSC_SUCCESS);
    249: }

    251: PetscErrorCode DMFieldCreateShell(DM dm, PetscInt numComponents, DMFieldContinuity continuity, void *ctx, DMField *field)
    252: {
    253:   DMField        b;
    254:   DMField_Shell *shell;

    256:   PetscFunctionBegin;
    258:   if (ctx) PetscAssertPointer(ctx, 4);
    259:   PetscAssertPointer(field, 5);
    260:   PetscCall(DMFieldCreate(dm, numComponents, continuity, &b));
    261:   PetscCall(DMFieldSetType(b, DMFIELDSHELL));
    262:   shell      = (DMField_Shell *)b->data;
    263:   shell->ctx = ctx;
    264:   *field     = b;
    265:   PetscFunctionReturn(PETSC_SUCCESS);
    266: }