1 static const char help[] = "Tests for injecting basis functions"; 2 3 #include <petscdmplex.h> 4 #include <petscfe.h> 5 #include <petscds.h> 6 7 typedef struct { 8 PetscInt its; /* Number of replications for timing */ 9 } AppCtx; 10 11 static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options) 12 { 13 PetscErrorCode ierr; 14 15 PetscFunctionBeginUser; 16 options->its = 1; 17 18 ierr = PetscOptionsBegin(comm, "", "FE Injection Options", "PETSCFE");CHKERRQ(ierr); 19 ierr = PetscOptionsInt("-its", "The number of replications for timing", "ex1.c", options->its, &options->its, NULL);CHKERRQ(ierr); 20 ierr = PetscOptionsEnd();CHKERRQ(ierr); 21 PetscFunctionReturn(0); 22 } 23 24 static PetscErrorCode trig_u(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx) 25 { 26 PetscInt d; 27 *u = 0.0; 28 for (d = 0; d < dim; ++d) *u += PetscSinReal(2.0*PETSC_PI*x[d]); 29 return 0; 30 } 31 32 static void f0_trig_u(PetscInt dim, PetscInt Nf, PetscInt NfAux, 33 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 34 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 35 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 36 { 37 PetscInt d; 38 for (d = 0; d < dim; ++d) f0[0] += -4.0*PetscSqr(PETSC_PI)*PetscSinReal(2.0*PETSC_PI*x[d]); 39 } 40 41 static void f1_u(PetscInt dim, PetscInt Nf, PetscInt NfAux, 42 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 43 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 44 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]) 45 { 46 PetscInt d; 47 for (d = 0; d < dim; ++d) f1[d] = u_x[d]; 48 } 49 50 static void g3_uu(PetscInt dim, PetscInt Nf, PetscInt NfAux, 51 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 52 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 53 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]) 54 { 55 PetscInt d; 56 for (d = 0; d < dim; ++d) g3[d*dim+d] = 1.0; 57 } 58 59 static PetscErrorCode SetupPrimalProblem(DM dm, AppCtx *user) 60 { 61 PetscDS ds; 62 DMLabel label; 63 const PetscInt id = 1; 64 PetscErrorCode ierr; 65 66 PetscFunctionBeginUser; 67 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 68 ierr = PetscDSSetResidual(ds, 0, f0_trig_u, f1_u);CHKERRQ(ierr); 69 ierr = PetscDSSetJacobian(ds, 0, 0, NULL, NULL, NULL, g3_uu);CHKERRQ(ierr); 70 ierr = PetscDSSetExactSolution(ds, 0, trig_u, user);CHKERRQ(ierr); 71 ierr = DMGetLabel(dm, "marker", &label);CHKERRQ(ierr); 72 if (label) {ierr = DMAddBoundary(dm, DM_BC_ESSENTIAL, "wall", label, 1, &id, 0, 0, NULL, (void (*)(void)) trig_u, NULL, user, NULL);CHKERRQ(ierr);} 73 PetscFunctionReturn(0); 74 } 75 76 static PetscErrorCode SetupDiscretization(DM dm, const char name[], PetscErrorCode (*setup)(DM, AppCtx *), AppCtx *user) 77 { 78 DM cdm = dm; 79 PetscFE fe; 80 char prefix[PETSC_MAX_PATH_LEN]; 81 PetscInt dim; 82 PetscErrorCode ierr; 83 84 PetscFunctionBeginUser; 85 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 86 ierr = PetscSNPrintf(prefix, PETSC_MAX_PATH_LEN, "%s_", name);CHKERRQ(ierr); 87 ierr = DMCreateFEDefault(dm, dim, name ? prefix : NULL, -1, &fe);CHKERRQ(ierr); 88 ierr = PetscObjectSetName((PetscObject) fe, name);CHKERRQ(ierr); 89 /* Set discretization and boundary conditions for each mesh */ 90 ierr = DMSetField(dm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 91 ierr = DMCreateDS(dm);CHKERRQ(ierr); 92 ierr = (*setup)(dm, user);CHKERRQ(ierr); 93 while (cdm) { 94 ierr = DMCopyDisc(dm,cdm);CHKERRQ(ierr); 95 ierr = DMGetCoarseDM(cdm, &cdm);CHKERRQ(ierr); 96 } 97 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 98 PetscFunctionReturn(0); 99 } 100 101 static PetscErrorCode PetscContainerUserDestroy_PetscFEGeom(void *ctx) 102 { 103 PetscFEGeom *geom = (PetscFEGeom *) ctx; 104 PetscErrorCode ierr; 105 106 PetscFunctionBegin; 107 ierr = PetscFEGeomDestroy(&geom);CHKERRQ(ierr); 108 PetscFunctionReturn(0); 109 } 110 111 PetscErrorCode CellRangeGetFEGeom(IS cellIS, DMField coordField, PetscQuadrature quad, PetscBool faceData, PetscFEGeom **geom) 112 { 113 char composeStr[33] = {0}; 114 PetscObjectId id; 115 PetscContainer container; 116 PetscErrorCode ierr; 117 118 PetscFunctionBegin; 119 ierr = PetscObjectGetId((PetscObject) quad, &id);CHKERRQ(ierr); 120 ierr = PetscSNPrintf(composeStr, 32, "CellRangeGetFEGeom_%x\n", id);CHKERRQ(ierr); 121 ierr = PetscObjectQuery((PetscObject) cellIS, composeStr, (PetscObject *) &container);CHKERRQ(ierr); 122 if (container) { 123 ierr = PetscContainerGetPointer(container, (void **) geom);CHKERRQ(ierr); 124 } else { 125 ierr = DMFieldCreateFEGeom(coordField, cellIS, quad, faceData, geom);CHKERRQ(ierr); 126 ierr = PetscContainerCreate(PETSC_COMM_SELF, &container);CHKERRQ(ierr); 127 ierr = PetscContainerSetPointer(container, (void *) *geom);CHKERRQ(ierr); 128 ierr = PetscContainerSetUserDestroy(container, PetscContainerUserDestroy_PetscFEGeom);CHKERRQ(ierr); 129 ierr = PetscObjectCompose((PetscObject) cellIS, composeStr, (PetscObject) container);CHKERRQ(ierr); 130 ierr = PetscContainerDestroy(&container);CHKERRQ(ierr); 131 } 132 PetscFunctionReturn(0); 133 } 134 135 PetscErrorCode CellRangeRestoreFEGeom(IS cellIS, DMField coordField, PetscQuadrature quad, PetscBool faceData, PetscFEGeom **geom) 136 { 137 PetscFunctionBegin; 138 *geom = NULL; 139 PetscFunctionReturn(0); 140 } 141 142 static PetscErrorCode CreateFEGeometry(DM dm, PetscDS ds, IS cellIS, PetscQuadrature *affineQuad, PetscFEGeom **affineGeom, PetscQuadrature **quads, PetscFEGeom ***geoms) 143 { 144 DMField coordField; 145 PetscInt Nf, f, maxDegree; 146 PetscErrorCode ierr; 147 148 PetscFunctionBeginUser; 149 *affineQuad = NULL; 150 *affineGeom = NULL; 151 *quads = NULL; 152 *geoms = NULL; 153 ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr); 154 ierr = DMGetCoordinateField(dm, &coordField);CHKERRQ(ierr); 155 ierr = DMFieldGetDegree(coordField, cellIS, NULL, &maxDegree);CHKERRQ(ierr); 156 if (maxDegree <= 1) { 157 ierr = DMFieldCreateDefaultQuadrature(coordField, cellIS, affineQuad);CHKERRQ(ierr); 158 if (*affineQuad) {ierr = CellRangeGetFEGeom(cellIS, coordField, *affineQuad, PETSC_FALSE, affineGeom);CHKERRQ(ierr);} 159 } else { 160 ierr = PetscCalloc2(Nf, quads, Nf, geoms);CHKERRQ(ierr); 161 for (f = 0; f < Nf; ++f) { 162 PetscFE fe; 163 164 ierr = PetscDSGetDiscretization(ds, f, (PetscObject *) &fe);CHKERRQ(ierr); 165 ierr = PetscFEGetQuadrature(fe, &(*quads)[f]);CHKERRQ(ierr); 166 ierr = PetscObjectReference((PetscObject) (*quads)[f]);CHKERRQ(ierr); 167 ierr = CellRangeGetFEGeom(cellIS, coordField, (*quads)[f], PETSC_FALSE, &(*geoms)[f]);CHKERRQ(ierr); 168 } 169 } 170 PetscFunctionReturn(0); 171 } 172 173 static PetscErrorCode DestroyFEGeometry(DM dm, PetscDS ds, IS cellIS, PetscQuadrature *affineQuad, PetscFEGeom **affineGeom, PetscQuadrature **quads, PetscFEGeom ***geoms) 174 { 175 DMField coordField; 176 PetscInt Nf, f; 177 PetscErrorCode ierr; 178 179 PetscFunctionBeginUser; 180 ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr); 181 ierr = DMGetCoordinateField(dm, &coordField);CHKERRQ(ierr); 182 if (*affineQuad) { 183 ierr = CellRangeRestoreFEGeom(cellIS, coordField, *affineQuad, PETSC_FALSE, affineGeom);CHKERRQ(ierr); 184 ierr = PetscQuadratureDestroy(affineQuad);CHKERRQ(ierr); 185 } else { 186 for (f = 0; f < Nf; ++f) { 187 ierr = CellRangeRestoreFEGeom(cellIS, coordField, (*quads)[f], PETSC_FALSE, &(*geoms)[f]);CHKERRQ(ierr); 188 ierr = PetscQuadratureDestroy(&(*quads)[f]);CHKERRQ(ierr); 189 } 190 ierr = PetscFree2(*quads, *geoms);CHKERRQ(ierr); 191 } 192 PetscFunctionReturn(0); 193 } 194 195 static PetscErrorCode TestEvaluation(DM dm) 196 { 197 PetscFE fe; 198 PetscSpace sp; 199 PetscReal *points; 200 PetscReal *B, *D, *H; 201 PetscInt dim, Nb, b, Nc, c, Np, p; 202 PetscErrorCode ierr; 203 204 PetscFunctionBeginUser; 205 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 206 ierr = DMGetField(dm, 0, NULL, (PetscObject *) &fe);CHKERRQ(ierr); 207 Np = 6; 208 ierr = PetscMalloc1(Np*dim, &points);CHKERRQ(ierr); 209 if (dim == 3) { 210 points[0] = -1.0; points[1] = -1.0; points[2] = -1.0; 211 points[3] = 1.0; points[4] = -1.0; points[5] = -1.0; 212 points[6] = -1.0; points[7] = 1.0; points[8] = -1.0; 213 points[9] = -1.0; points[10] = -1.0; points[11] = 1.0; 214 points[12] = 1.0; points[13] = -1.0; points[14] = 1.0; 215 points[15] = -1.0; points[16] = 1.0; points[17] = 1.0; 216 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only for 3D right now"); 217 ierr = PetscFEGetBasisSpace(fe, &sp);CHKERRQ(ierr); 218 ierr = PetscSpaceGetDimension(sp, &Nb);CHKERRQ(ierr); 219 ierr = PetscSpaceGetNumComponents(sp, &Nc);CHKERRQ(ierr); 220 ierr = DMGetWorkArray(dm, Np*Nb*Nc, MPIU_REAL, &B);CHKERRQ(ierr); 221 ierr = DMGetWorkArray(dm, Np*Nb*Nc*dim, MPIU_REAL, &D);CHKERRQ(ierr); 222 ierr = DMGetWorkArray(dm, Np*Nb*Nc*dim*dim, MPIU_REAL, &H);CHKERRQ(ierr); 223 ierr = PetscSpaceEvaluate(sp, Np, points, B, NULL, NULL /*D, H*/);CHKERRQ(ierr); 224 for (p = 0; p < Np; ++p) { 225 ierr = PetscPrintf(PETSC_COMM_SELF, "Point %" PetscInt_FMT "\n", p);CHKERRQ(ierr); 226 for (b = 0; b < Nb; ++b) { 227 ierr = PetscPrintf(PETSC_COMM_SELF, "B[%" PetscInt_FMT "]:", b);CHKERRQ(ierr); 228 for (c = 0; c < Nc; ++c) {ierr = PetscPrintf(PETSC_COMM_SELF, " %g", (double) B[(p*Nb+b)*Nc+c]);CHKERRQ(ierr);} 229 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 230 #if 0 231 for (c = 0; c < Nc; ++c) { 232 ierr = PetscPrintf(PETSC_COMM_SELF, " D[%" PetscInt_FMT ",%" PetscInt_FMT "]:", b, c);CHKERRQ(ierr); 233 for (d = 0; d < dim; ++d) {ierr = PetscPrintf(PETSC_COMM_SELF, " %g", (double) B[((p*Nb+b)*Nc+c)*dim+d)]);CHKERRQ(ierr);} 234 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 235 } 236 #endif 237 } 238 } 239 ierr = DMRestoreWorkArray(dm, Np*Nb, MPIU_REAL, &B);CHKERRQ(ierr); 240 ierr = DMRestoreWorkArray(dm, Np*Nb*dim, MPIU_REAL, &D);CHKERRQ(ierr); 241 ierr = DMRestoreWorkArray(dm, Np*Nb*dim*dim, MPIU_REAL, &H);CHKERRQ(ierr); 242 ierr = PetscFree(points);CHKERRQ(ierr); 243 PetscFunctionReturn(0); 244 } 245 246 static PetscErrorCode TestIntegration(DM dm, PetscInt cbs, PetscInt its) 247 { 248 PetscDS ds; 249 PetscFEGeom *chunkGeom = NULL; 250 PetscQuadrature affineQuad, *quads = NULL; 251 PetscFEGeom *affineGeom, **geoms = NULL; 252 PetscScalar *u, *elemVec; 253 IS cellIS; 254 PetscInt depth, cStart, cEnd, cell, chunkSize = cbs, Nch = 0, Nf, f, totDim, i, k; 255 PetscErrorCode ierr; 256 257 PetscFunctionBeginUser; 258 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 259 ierr = DMGetStratumIS(dm, "depth", depth, &cellIS);CHKERRQ(ierr); 260 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 261 ierr = DMGetCellDS(dm, cStart, &ds);CHKERRQ(ierr); 262 ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr); 263 ierr = PetscDSGetTotalDimension(ds, &totDim);CHKERRQ(ierr); 264 ierr = CreateFEGeometry(dm, ds, cellIS, &affineQuad, &affineGeom, &quads, &geoms);CHKERRQ(ierr); 265 ierr = PetscMalloc2(chunkSize*totDim, &u, chunkSize*totDim, &elemVec);CHKERRQ(ierr); 266 /* Assumptions: 267 - Single field 268 - No input data 269 - No auxiliary data 270 - No time-dependence 271 */ 272 for (i = 0; i < its; ++i) { 273 for (cell = cStart; cell < cEnd; cell += chunkSize, ++Nch) { 274 const PetscInt cS = cell, cE = PetscMin(cS + chunkSize, cEnd), Ne = cE - cS; 275 276 ierr = PetscArrayzero(elemVec, chunkSize*totDim);CHKERRQ(ierr); 277 /* TODO Replace with DMPlexGetCellFields() */ 278 for (k = 0; k < chunkSize*totDim; ++k) u[k] = 1.0; 279 for (f = 0; f < Nf; ++f) { 280 PetscFormKey key; 281 PetscFEGeom *geom = affineGeom ? affineGeom : geoms[f]; 282 /* PetscQuadrature quad = affineQuad ? affineQuad : quads[f]; */ 283 284 key.label = NULL; key.value = 0; key.field = f; 285 ierr = PetscFEGeomGetChunk(geom, cS, cE, &chunkGeom);CHKERRQ(ierr); 286 ierr = PetscFEIntegrateResidual(ds, key, Ne, chunkGeom, u, NULL, NULL, NULL, 0.0, elemVec);CHKERRQ(ierr); 287 } 288 } 289 } 290 ierr = PetscFEGeomRestoreChunk(affineGeom, cStart, cEnd, &chunkGeom);CHKERRQ(ierr); 291 ierr = DestroyFEGeometry(dm, ds, cellIS, &affineQuad, &affineGeom, &quads, &geoms);CHKERRQ(ierr); 292 ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 293 ierr = PetscFree2(u, elemVec);CHKERRQ(ierr); 294 PetscFunctionReturn(0); 295 } 296 297 static PetscErrorCode TestUnisolvence(DM dm) 298 { 299 Mat M; 300 Vec v; 301 PetscErrorCode ierr; 302 303 PetscFunctionBeginUser; 304 ierr = DMGetLocalVector(dm, &v);CHKERRQ(ierr); 305 ierr = DMRestoreLocalVector(dm, &v);CHKERRQ(ierr); 306 ierr = DMCreateMassMatrix(dm, dm, &M);CHKERRQ(ierr); 307 ierr = MatViewFromOptions(M, NULL, "-mass_view");CHKERRQ(ierr); 308 ierr = MatDestroy(&M);CHKERRQ(ierr); 309 PetscFunctionReturn(0); 310 } 311 312 int main(int argc, char **argv) 313 { 314 DM dm; 315 AppCtx ctx; 316 PetscMPIInt size; 317 PetscErrorCode ierr; 318 319 ierr = PetscInitialize(&argc, &argv, NULL, help); if (ierr) return ierr; 320 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &size);CHKERRMPI(ierr); 321 PetscCheck(size == 1, PETSC_COMM_WORLD, PETSC_ERR_SUP, "This is a uniprocessor example only."); 322 ierr = ProcessOptions(PETSC_COMM_WORLD, &ctx);CHKERRQ(ierr); 323 ierr = DMCreate(PETSC_COMM_WORLD, &dm);CHKERRQ(ierr); 324 ierr = DMSetType(dm, DMPLEX);CHKERRQ(ierr); 325 ierr = DMSetFromOptions(dm);CHKERRQ(ierr); 326 ierr = PetscObjectSetName((PetscObject) dm, "Mesh");CHKERRQ(ierr); 327 ierr = PetscObjectViewFromOptions((PetscObject) dm, NULL, "-dm_view");CHKERRQ(ierr); 328 ierr = SetupDiscretization(dm, "field", SetupPrimalProblem, &ctx);CHKERRQ(ierr); 329 ierr = TestEvaluation(dm);CHKERRQ(ierr); 330 ierr = TestIntegration(dm, 1, ctx.its);CHKERRQ(ierr); 331 ierr = TestUnisolvence(dm);CHKERRQ(ierr); 332 ierr = DMDestroy(&dm);CHKERRQ(ierr); 333 ierr = PetscFinalize(); 334 return ierr; 335 } 336 337 /*TEST 338 test: 339 suffix: 0 340 args: -dm_plex_reference_cell_domain -dm_plex_cell triangular_prism -field_petscspace_degree 0 341 342 test: 343 suffix: 2 344 args: -dm_plex_reference_cell_domain -dm_plex_cell triangular_prism \ 345 -field_petscspace_type sum \ 346 -field_petscspace_variables 3 \ 347 -field_petscspace_components 3 \ 348 -field_petscspace_sum_spaces 2 \ 349 -field_petscspace_sum_concatenate false \ 350 -field_sumcomp_0_petscspace_variables 3 \ 351 -field_sumcomp_0_petscspace_components 3 \ 352 -field_sumcomp_0_petscspace_degree 1 \ 353 -field_sumcomp_1_petscspace_variables 3 \ 354 -field_sumcomp_1_petscspace_components 3 \ 355 -field_sumcomp_1_petscspace_type wxy \ 356 -field_petscdualspace_form_degree 0 \ 357 -field_petscdualspace_order 1 \ 358 -field_petscdualspace_components 3 359 360 TEST*/ 361