1 static char help[] = "Performance tests for DMPlex query operations\n\n"; 2 3 #include <petscdmplex.h> 4 5 typedef struct { 6 PetscInt dim; /* The topological mesh dimension */ 7 PetscBool cellSimplex; /* Flag for simplices */ 8 PetscBool spectral; /* Flag for spectral element layout */ 9 PetscBool interpolate; /* Flag for mesh interpolation */ 10 PetscReal refinementLimit; /* Maximum volume of a refined cell */ 11 PetscInt numFields; /* The number of section fields */ 12 PetscInt *numComponents; /* The number of field components */ 13 PetscInt *numDof; /* The dof signature for the section */ 14 PetscBool reuseArray; /* Pass in user allocated array to VecGetClosure() */ 15 /* Test data */ 16 PetscBool errors; /* Treat failures as errors */ 17 PetscInt iterations; /* The number of iterations for a query */ 18 PetscReal maxConeTime; /* Max time per run for DMPlexGetCone() */ 19 PetscReal maxClosureTime; /* Max time per run for DMPlexGetTransitiveClosure() */ 20 PetscReal maxVecClosureTime; /* Max time per run for DMPlexVecGetClosure() */ 21 PetscBool printTimes; /* Print total times, do not check limits */ 22 } AppCtx; 23 24 static PetscErrorCode ProcessOptions(AppCtx *options) 25 { 26 PetscInt len; 27 PetscBool flg; 28 PetscErrorCode ierr; 29 30 PetscFunctionBegin; 31 options->dim = 2; 32 options->cellSimplex = PETSC_TRUE; 33 options->spectral = PETSC_FALSE; 34 options->interpolate = PETSC_FALSE; 35 options->refinementLimit = 0.0; 36 options->numFields = 0; 37 options->numComponents = NULL; 38 options->numDof = NULL; 39 options->reuseArray = PETSC_FALSE; 40 options->errors = PETSC_FALSE; 41 options->iterations = 1; 42 options->maxConeTime = 0.0; 43 options->maxClosureTime = 0.0; 44 options->maxVecClosureTime = 0.0; 45 options->printTimes = PETSC_FALSE; 46 47 ierr = PetscOptionsBegin(PETSC_COMM_SELF, "", "Meshing Problem Options", "DMPLEX");PetscCall(ierr); 48 PetscCall(PetscOptionsRangeInt("-dim", "The topological mesh dimension", "ex9.c", options->dim, &options->dim, NULL,1,3)); 49 PetscCall(PetscOptionsBool("-cellSimplex", "Flag for simplices", "ex9.c", options->cellSimplex, &options->cellSimplex, NULL)); 50 PetscCall(PetscOptionsBool("-spectral", "Flag for spectral element layout", "ex9.c", options->spectral, &options->spectral, NULL)); 51 PetscCall(PetscOptionsBool("-interpolate", "Flag for mesh interpolation", "ex9.c", options->interpolate, &options->interpolate, NULL)); 52 PetscCall(PetscOptionsReal("-refinement_limit", "The maximum volume of a refined cell", "ex9.c", options->refinementLimit, &options->refinementLimit, NULL)); 53 PetscCall(PetscOptionsBoundedInt("-num_fields", "The number of section fields", "ex9.c", options->numFields, &options->numFields, NULL, 0)); 54 if (options->numFields) { 55 len = options->numFields; 56 PetscCall(PetscMalloc1(len, &options->numComponents)); 57 PetscCall(PetscOptionsIntArray("-num_components", "The number of components per field", "ex9.c", options->numComponents, &len, &flg)); 58 PetscCheckFalse(flg && (len != options->numFields),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Length of components array is %d should be %d", len, options->numFields); 59 } 60 len = (options->dim+1) * PetscMax(1, options->numFields); 61 PetscCall(PetscMalloc1(len, &options->numDof)); 62 PetscCall(PetscOptionsIntArray("-num_dof", "The dof signature for the section", "ex9.c", options->numDof, &len, &flg)); 63 PetscCheckFalse(flg && (len != (options->dim+1) * PetscMax(1, options->numFields)),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Length of dof array is %d should be %d", len, (options->dim+1) * PetscMax(1, options->numFields)); 64 65 /* We are specifying the scalar dof, so augment it for multiple components */ 66 { 67 PetscInt f, d; 68 69 for (f = 0; f < options->numFields; ++f) { 70 for (d = 0; d <= options->dim; ++d) options->numDof[f*(options->dim+1)+d] *= options->numComponents[f]; 71 } 72 } 73 74 PetscCall(PetscOptionsBool("-reuse_array", "Pass in user allocated array to VecGetClosure()", "ex9.c", options->reuseArray, &options->reuseArray, NULL)); 75 PetscCall(PetscOptionsBool("-errors", "Treat failures as errors", "ex9.c", options->errors, &options->errors, NULL)); 76 PetscCall(PetscOptionsBoundedInt("-iterations", "The number of iterations for a query", "ex9.c", options->iterations, &options->iterations, NULL,0)); 77 PetscCall(PetscOptionsReal("-max_cone_time", "The maximum time per run for DMPlexGetCone()", "ex9.c", options->maxConeTime, &options->maxConeTime, NULL)); 78 PetscCall(PetscOptionsReal("-max_closure_time", "The maximum time per run for DMPlexGetTransitiveClosure()", "ex9.c", options->maxClosureTime, &options->maxClosureTime, NULL)); 79 PetscCall(PetscOptionsReal("-max_vec_closure_time", "The maximum time per run for DMPlexVecGetClosure()", "ex9.c", options->maxVecClosureTime, &options->maxVecClosureTime, NULL)); 80 PetscCall(PetscOptionsBool("-print_times", "Print total times, do not check limits", "ex9.c", options->printTimes, &options->printTimes, NULL)); 81 ierr = PetscOptionsEnd();PetscCall(ierr); 82 PetscFunctionReturn(0); 83 } 84 85 static PetscErrorCode CreateSimplex_2D(MPI_Comm comm, DM *newdm) 86 { 87 DM dm; 88 PetscInt numPoints[2] = {4, 2}; 89 PetscInt coneSize[6] = {3, 3, 0, 0, 0, 0}; 90 PetscInt cones[6] = {2, 3, 4, 5, 4, 3}; 91 PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 92 PetscScalar vertexCoords[8] = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5}; 93 PetscInt markerPoints[8] = {2, 1, 3, 1, 4, 1, 5, 1}; 94 PetscInt dim = 2, depth = 1, p; 95 96 PetscFunctionBegin; 97 PetscCall(DMCreate(comm, &dm)); 98 PetscCall(PetscObjectSetName((PetscObject) dm, "triangular")); 99 PetscCall(DMSetType(dm, DMPLEX)); 100 PetscCall(DMSetDimension(dm, dim)); 101 PetscCall(DMPlexCreateFromDAG(dm, depth, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 102 for (p = 0; p < 4; ++p) { 103 PetscCall(DMSetLabelValue(dm, "marker", markerPoints[p*2], markerPoints[p*2+1])); 104 } 105 *newdm = dm; 106 PetscFunctionReturn(0); 107 } 108 109 static PetscErrorCode CreateSimplex_3D(MPI_Comm comm, DM *newdm) 110 { 111 DM dm; 112 PetscInt numPoints[2] = {5, 2}; 113 PetscInt coneSize[23] = {4, 4, 0, 0, 0, 0, 0}; 114 PetscInt cones[8] = {2, 4, 3, 5, 3, 4, 6, 5}; 115 PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 116 PetscScalar vertexCoords[15] = {0.0, 0.0, -0.5, 0.0, -0.5, 0.0, 1.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5}; 117 PetscInt markerPoints[10] = {2, 1, 3, 1, 4, 1, 5, 1, 6, 1}; 118 PetscInt dim = 3, depth = 1, p; 119 120 PetscFunctionBegin; 121 PetscCall(DMCreate(comm, &dm)); 122 PetscCall(PetscObjectSetName((PetscObject) dm, "tetrahedral")); 123 PetscCall(DMSetType(dm, DMPLEX)); 124 PetscCall(DMSetDimension(dm, dim)); 125 PetscCall(DMPlexCreateFromDAG(dm, depth, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 126 for (p = 0; p < 5; ++p) { 127 PetscCall(DMSetLabelValue(dm, "marker", markerPoints[p*2], markerPoints[p*2+1])); 128 } 129 *newdm = dm; 130 PetscFunctionReturn(0); 131 } 132 133 static PetscErrorCode CreateQuad_2D(MPI_Comm comm, DM *newdm) 134 { 135 DM dm; 136 PetscInt numPoints[2] = {6, 2}; 137 PetscInt coneSize[8] = {4, 4, 0, 0, 0, 0, 0, 0}; 138 PetscInt cones[8] = {2, 3, 4, 5, 3, 6, 7, 4}; 139 PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 140 PetscScalar vertexCoords[12] = {-0.5, 0.0, 0.0, 0.0, 0.0, 1.0, -0.5, 1.0, 0.5, 0.0, 0.5, 1.0}; 141 PetscInt markerPoints[12] = {2, 1, 3, 1, 4, 1, 5, 1, 6, 1, 7, 1}; 142 PetscInt dim = 2, depth = 1, p; 143 144 PetscFunctionBegin; 145 PetscCall(DMCreate(comm, &dm)); 146 PetscCall(PetscObjectSetName((PetscObject) dm, "quadrilateral")); 147 PetscCall(DMSetType(dm, DMPLEX)); 148 PetscCall(DMSetDimension(dm, dim)); 149 PetscCall(DMPlexCreateFromDAG(dm, depth, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 150 for (p = 0; p < 6; ++p) { 151 PetscCall(DMSetLabelValue(dm, "marker", markerPoints[p*2], markerPoints[p*2+1])); 152 } 153 *newdm = dm; 154 PetscFunctionReturn(0); 155 } 156 157 static PetscErrorCode CreateHex_3D(MPI_Comm comm, DM *newdm) 158 { 159 DM dm; 160 PetscInt numPoints[2] = {12, 2}; 161 PetscInt coneSize[14] = {8, 8, 0,0,0,0,0,0,0,0,0,0,0,0}; 162 PetscInt cones[16] = {2,5,4,3,6,7,8,9, 3,4,11,10,7,12,13,8}; 163 PetscInt coneOrientations[16] = {0,0,0,0,0,0,0,0, 0,0, 0, 0,0, 0, 0,0}; 164 PetscScalar vertexCoords[36] = {-0.5,0.0,0.0, 0.0,0.0,0.0, 0.0,1.0,0.0, -0.5,1.0,0.0, 165 -0.5,0.0,1.0, 0.0,0.0,1.0, 0.0,1.0,1.0, -0.5,1.0,1.0, 166 0.5,0.0,0.0, 0.5,1.0,0.0, 0.5,0.0,1.0, 0.5,1.0,1.0}; 167 PetscInt markerPoints[24] = {2,1,3,1,4,1,5,1,6,1,7,1,8,1,9,1,10,1,11,1,12,1,13,1}; 168 PetscInt dim = 3, depth = 1, p; 169 170 PetscFunctionBegin; 171 PetscCall(DMCreate(comm, &dm)); 172 PetscCall(PetscObjectSetName((PetscObject) dm, "hexahedral")); 173 PetscCall(DMSetType(dm, DMPLEX)); 174 PetscCall(DMSetDimension(dm, dim)); 175 PetscCall(DMPlexCreateFromDAG(dm, depth, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 176 for (p = 0; p < 12; ++p) { 177 PetscCall(DMSetLabelValue(dm, "marker", markerPoints[p*2], markerPoints[p*2+1])); 178 } 179 *newdm = dm; 180 PetscFunctionReturn(0); 181 } 182 183 static PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *newdm) 184 { 185 PetscInt dim = user->dim; 186 PetscBool cellSimplex = user->cellSimplex; 187 188 PetscFunctionBegin; 189 switch (dim) { 190 case 2: 191 if (cellSimplex) { 192 PetscCall(CreateSimplex_2D(comm, newdm)); 193 } else { 194 PetscCall(CreateQuad_2D(comm, newdm)); 195 } 196 break; 197 case 3: 198 if (cellSimplex) { 199 PetscCall(CreateSimplex_3D(comm, newdm)); 200 } else { 201 PetscCall(CreateHex_3D(comm, newdm)); 202 } 203 break; 204 default: 205 SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %d", dim); 206 } 207 if (user->refinementLimit > 0.0) { 208 DM rdm; 209 const char *name; 210 211 PetscCall(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE)); 212 PetscCall(DMPlexSetRefinementLimit(*newdm, user->refinementLimit)); 213 PetscCall(DMRefine(*newdm, PETSC_COMM_SELF, &rdm)); 214 PetscCall(PetscObjectGetName((PetscObject) *newdm, &name)); 215 PetscCall(PetscObjectSetName((PetscObject) rdm, name)); 216 PetscCall(DMDestroy(newdm)); 217 *newdm = rdm; 218 } 219 if (user->interpolate) { 220 DM idm; 221 222 PetscCall(DMPlexInterpolate(*newdm, &idm)); 223 PetscCall(DMDestroy(newdm)); 224 *newdm = idm; 225 } 226 PetscCall(DMSetFromOptions(*newdm)); 227 PetscFunctionReturn(0); 228 } 229 230 static PetscErrorCode TestCone(DM dm, AppCtx *user) 231 { 232 PetscInt numRuns, cStart, cEnd, c, i; 233 PetscReal maxTimePerRun = user->maxConeTime; 234 PetscLogStage stage; 235 PetscLogEvent event; 236 PetscEventPerfInfo eventInfo; 237 MPI_Comm comm; 238 PetscMPIInt rank; 239 240 PetscFunctionBegin; 241 PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 242 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 243 PetscCall(PetscLogStageRegister("DMPlex Cone Test", &stage)); 244 PetscCall(PetscLogEventRegister("Cone", PETSC_OBJECT_CLASSID, &event)); 245 PetscCall(PetscLogStagePush(stage)); 246 PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 247 PetscCall(PetscLogEventBegin(event,0,0,0,0)); 248 for (i = 0; i < user->iterations; ++i) { 249 for (c = cStart; c < cEnd; ++c) { 250 const PetscInt *cone; 251 252 PetscCall(DMPlexGetCone(dm, c, &cone)); 253 } 254 } 255 PetscCall(PetscLogEventEnd(event,0,0,0,0)); 256 PetscCall(PetscLogStagePop()); 257 258 PetscCall(PetscLogEventGetPerfInfo(stage, event, &eventInfo)); 259 numRuns = (cEnd-cStart) * user->iterations; 260 PetscCheckFalse(eventInfo.count != 1,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of event calls %d should be %d", eventInfo.count, 1); 261 PetscCheckFalse((PetscInt) eventInfo.flops != 0,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of event flops %d should be %d", (PetscInt) eventInfo.flops, 0); 262 if (user->printTimes) { 263 PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cones: %d Total time: %.3es Average time per cone: %.3es\n", rank, numRuns, eventInfo.time, eventInfo.time/numRuns)); 264 PetscCall(PetscSynchronizedFlush(comm, PETSC_STDOUT)); 265 } else if (eventInfo.time > maxTimePerRun * numRuns) { 266 PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cones: %d Average time per cone: %gs standard: %gs\n", rank, numRuns, eventInfo.time/numRuns, maxTimePerRun)); 267 PetscCall(PetscSynchronizedFlush(comm, PETSC_STDOUT)); 268 PetscCheck(!user->errors,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Average time for cone %g > standard %g", eventInfo.time/numRuns, maxTimePerRun); 269 } 270 PetscFunctionReturn(0); 271 } 272 273 static PetscErrorCode TestTransitiveClosure(DM dm, AppCtx *user) 274 { 275 PetscInt numRuns, cStart, cEnd, c, i; 276 PetscReal maxTimePerRun = user->maxClosureTime; 277 PetscLogStage stage; 278 PetscLogEvent event; 279 PetscEventPerfInfo eventInfo; 280 MPI_Comm comm; 281 PetscMPIInt rank; 282 283 PetscFunctionBegin; 284 PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 285 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 286 PetscCall(PetscLogStageRegister("DMPlex Transitive Closure Test", &stage)); 287 PetscCall(PetscLogEventRegister("TransitiveClosure", PETSC_OBJECT_CLASSID, &event)); 288 PetscCall(PetscLogStagePush(stage)); 289 PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 290 PetscCall(PetscLogEventBegin(event,0,0,0,0)); 291 for (i = 0; i < user->iterations; ++i) { 292 for (c = cStart; c < cEnd; ++c) { 293 PetscInt *closure = NULL; 294 PetscInt closureSize; 295 296 PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 297 PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 298 } 299 } 300 PetscCall(PetscLogEventEnd(event,0,0,0,0)); 301 PetscCall(PetscLogStagePop()); 302 303 PetscCall(PetscLogEventGetPerfInfo(stage, event, &eventInfo)); 304 numRuns = (cEnd-cStart) * user->iterations; 305 PetscCheckFalse(eventInfo.count != 1,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of event calls %d should be %d", eventInfo.count, 1); 306 PetscCheckFalse((PetscInt) eventInfo.flops != 0,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of event flops %d should be %d", (PetscInt) eventInfo.flops, 0); 307 if (user->printTimes) { 308 PetscCall(PetscSynchronizedPrintf(comm, "[%d] Closures: %d Total time: %.3es Average time per cone: %.3es\n", rank, numRuns, eventInfo.time, eventInfo.time/numRuns)); 309 PetscCall(PetscSynchronizedFlush(comm, PETSC_STDOUT)); 310 } else if (eventInfo.time > maxTimePerRun * numRuns) { 311 PetscCall(PetscSynchronizedPrintf(comm, "[%d] Closures: %d Average time per cone: %gs standard: %gs\n", rank, numRuns, eventInfo.time/numRuns, maxTimePerRun)); 312 PetscCall(PetscSynchronizedFlush(comm, PETSC_STDOUT)); 313 PetscCheck(!user->errors,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Average time for closure %g > standard %g", eventInfo.time/numRuns, maxTimePerRun); 314 } 315 PetscFunctionReturn(0); 316 } 317 318 static PetscErrorCode TestVecClosure(DM dm, PetscBool useIndex, PetscBool useSpectral, AppCtx *user) 319 { 320 PetscSection s; 321 Vec v; 322 PetscInt numRuns, cStart, cEnd, c, i; 323 PetscScalar tmpArray[64]; 324 PetscScalar *userArray = user->reuseArray ? tmpArray : NULL; 325 PetscReal maxTimePerRun = user->maxVecClosureTime; 326 PetscLogStage stage; 327 PetscLogEvent event; 328 PetscEventPerfInfo eventInfo; 329 MPI_Comm comm; 330 PetscMPIInt rank; 331 332 PetscFunctionBegin; 333 PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 334 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 335 if (useIndex) { 336 if (useSpectral) { 337 PetscCall(PetscLogStageRegister("DMPlex Vector Closure with Index Test", &stage)); 338 PetscCall(PetscLogEventRegister("VecClosureInd", PETSC_OBJECT_CLASSID, &event)); 339 } else { 340 PetscCall(PetscLogStageRegister("DMPlex Vector Spectral Closure with Index Test", &stage)); 341 PetscCall(PetscLogEventRegister("VecClosureSpecInd", PETSC_OBJECT_CLASSID, &event)); 342 } 343 } else { 344 if (useSpectral) { 345 PetscCall(PetscLogStageRegister("DMPlex Vector Spectral Closure Test", &stage)); 346 PetscCall(PetscLogEventRegister("VecClosureSpec", PETSC_OBJECT_CLASSID, &event)); 347 } else { 348 PetscCall(PetscLogStageRegister("DMPlex Vector Closure Test", &stage)); 349 PetscCall(PetscLogEventRegister("VecClosure", PETSC_OBJECT_CLASSID, &event)); 350 } 351 } 352 PetscCall(PetscLogStagePush(stage)); 353 PetscCall(DMSetNumFields(dm, user->numFields)); 354 PetscCall(DMPlexCreateSection(dm, NULL, user->numComponents, user->numDof, 0, NULL, NULL, NULL, NULL, &s)); 355 PetscCall(DMSetLocalSection(dm, s)); 356 if (useIndex) PetscCall(DMPlexCreateClosureIndex(dm, s)); 357 if (useSpectral) PetscCall(DMPlexSetClosurePermutationTensor(dm, PETSC_DETERMINE, s)); 358 PetscCall(PetscSectionDestroy(&s)); 359 PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 360 PetscCall(DMGetLocalVector(dm, &v)); 361 PetscCall(PetscLogEventBegin(event,0,0,0,0)); 362 for (i = 0; i < user->iterations; ++i) { 363 for (c = cStart; c < cEnd; ++c) { 364 PetscScalar *closure = userArray; 365 PetscInt closureSize = 64; 366 367 PetscCall(DMPlexVecGetClosure(dm, s, v, c, &closureSize, &closure)); 368 if (!user->reuseArray) PetscCall(DMPlexVecRestoreClosure(dm, s, v, c, &closureSize, &closure)); 369 } 370 } 371 PetscCall(PetscLogEventEnd(event,0,0,0,0)); 372 PetscCall(DMRestoreLocalVector(dm, &v)); 373 PetscCall(PetscLogStagePop()); 374 375 PetscCall(PetscLogEventGetPerfInfo(stage, event, &eventInfo)); 376 numRuns = (cEnd-cStart) * user->iterations; 377 PetscCheckFalse(eventInfo.count != 1,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of event calls %d should be %d", eventInfo.count, 1); 378 PetscCheckFalse((PetscInt) eventInfo.flops != 0,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of event flops %d should be %d", (PetscInt) eventInfo.flops, 0); 379 if (user->printTimes || eventInfo.time > maxTimePerRun * numRuns) { 380 const char *title = "VecClosures"; 381 const char *titleIndex = "VecClosures with Index"; 382 const char *titleSpec = "VecClosures Spectral"; 383 const char *titleSpecIndex = "VecClosures Spectral with Index"; 384 385 if (user->printTimes) { 386 PetscCall(PetscSynchronizedPrintf(comm, "[%d] %s: %d Total time: %.3es Average time per vector closure: %.3es\n", rank, useIndex ? (useSpectral ? titleSpecIndex : titleIndex) : (useSpectral ? titleSpec : title), numRuns, eventInfo.time, eventInfo.time/numRuns)); 387 PetscCall(PetscSynchronizedFlush(comm, PETSC_STDOUT)); 388 } else { 389 PetscCall(PetscSynchronizedPrintf(comm, "[%d] %s: %d Average time per vector closure: %gs standard: %gs\n", rank, useIndex ? (useSpectral ? titleSpecIndex : titleIndex) : (useSpectral ? titleSpec : title), numRuns, eventInfo.time/numRuns, maxTimePerRun)); 390 PetscCall(PetscSynchronizedFlush(comm, PETSC_STDOUT)); 391 PetscCheck(!user->errors,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Average time for vector closure %g > standard %g", eventInfo.time/numRuns, maxTimePerRun); 392 } 393 } 394 PetscFunctionReturn(0); 395 } 396 397 static PetscErrorCode CleanupContext(AppCtx *user) 398 { 399 PetscFunctionBegin; 400 PetscCall(PetscFree(user->numComponents)); 401 PetscCall(PetscFree(user->numDof)); 402 PetscFunctionReturn(0); 403 } 404 405 int main(int argc, char **argv) 406 { 407 DM dm; 408 AppCtx user; 409 410 PetscCall(PetscInitialize(&argc, &argv, NULL,help)); 411 PetscCall(ProcessOptions(&user)); 412 PetscCall(PetscLogDefaultBegin()); 413 PetscCall(CreateMesh(PETSC_COMM_WORLD, &user, &dm)); 414 PetscCall(TestCone(dm, &user)); 415 PetscCall(TestTransitiveClosure(dm, &user)); 416 PetscCall(TestVecClosure(dm, PETSC_FALSE, PETSC_FALSE, &user)); 417 PetscCall(TestVecClosure(dm, PETSC_TRUE, PETSC_FALSE, &user)); 418 if (!user.cellSimplex && user.spectral) { 419 PetscCall(TestVecClosure(dm, PETSC_FALSE, PETSC_TRUE, &user)); 420 PetscCall(TestVecClosure(dm, PETSC_TRUE, PETSC_TRUE, &user)); 421 } 422 PetscCall(DMDestroy(&dm)); 423 PetscCall(CleanupContext(&user)); 424 PetscCall(PetscFinalize()); 425 return 0; 426 } 427 428 /*TEST 429 430 build: 431 requires: defined(PETSC_USE_LOG) 432 433 # 2D Simplex P_1 scalar tests 434 testset: 435 args: -num_dof 1,0,0 -iterations 2 -print_times 436 test: 437 suffix: correctness_0 438 test: 439 suffix: correctness_1 440 args: -interpolate -dm_refine 2 441 test: 442 suffix: correctness_2 443 requires: triangle 444 args: -interpolate -refinement_limit 1.0e-5 445 test: 446 suffix: 0 447 TODO: Only for performance testing 448 args: -num_dof 1,0,0 -iterations 10000 -max_cone_time 1.1e-8 -max_closure_time 1.3e-7 -max_vec_closure_time 3.6e-7 449 test: 450 suffix: 1 451 requires: triangle 452 TODO: Only for performance testing 453 args: -refinement_limit 1.0e-5 -num_dof 1,0,0 -iterations 2 -max_cone_time 2.1e-8 -max_closure_time 1.5e-7 -max_vec_closure_time 3.6e-7 454 test: 455 suffix: 2 456 TODO: Only for performance testing 457 args: -num_fields 1 -num_components 1 -num_dof 1,0,0 -iterations 10000 -max_cone_time 1.1e-8 -max_closure_time 1.3e-7 -max_vec_closure_time 4.5e-7 458 test: 459 suffix: 3 460 requires: triangle 461 TODO: Only for performance testing 462 args: -refinement_limit 1.0e-5 -num_fields 1 -num_components 1 -num_dof 1,0,0 -iterations 2 -max_cone_time 2.1e-8 -max_closure_time 1.5e-7 -max_vec_closure_time 4.7e-7 463 test: 464 suffix: 4 465 TODO: Only for performance testing 466 args: -interpolate -num_dof 1,0,0 -iterations 10000 -max_cone_time 1.1e-8 -max_closure_time 6.5e-7 -max_vec_closure_time 1.0e-6 467 test: 468 suffix: 5 469 requires: triangle 470 TODO: Only for performance testing 471 args: -interpolate -refinement_limit 1.0e-4 -num_dof 1,0,0 -iterations 2 -max_cone_time 2.1e-8 -max_closure_time 6.5e-7 -max_vec_closure_time 1.0e-6 472 test: 473 suffix: 6 474 TODO: Only for performance testing 475 args: -interpolate -num_fields 1 -num_components 1 -num_dof 1,0,0 -iterations 10000 -max_cone_time 1.1e-8 -max_closure_time 6.5e-7 -max_vec_closure_time 1.1e-6 476 test: 477 suffix: 7 478 requires: triangle 479 TODO: Only for performance testing 480 args: -interpolate -refinement_limit 1.0e-4 -num_fields 1 -num_components 1 -num_dof 1,0,0 -iterations 2 -max_cone_time 2.1e-8 -max_closure_time 6.5e-7 -max_vec_closure_time 1.2e-6 481 482 # 2D Simplex P_1 vector tests 483 # 2D Simplex P_2 scalar tests 484 # 2D Simplex P_2 vector tests 485 # 2D Simplex P_2/P_1 vector/scalar tests 486 # 2D Quad P_1 scalar tests 487 # 2D Quad P_1 vector tests 488 # 2D Quad P_2 scalar tests 489 # 2D Quad P_2 vector tests 490 # 3D Simplex P_1 scalar tests 491 # 3D Simplex P_1 vector tests 492 # 3D Simplex P_2 scalar tests 493 # 3D Simplex P_2 vector tests 494 # 3D Hex P_1 scalar tests 495 # 3D Hex P_1 vector tests 496 # 3D Hex P_2 scalar tests 497 # 3D Hex P_2 vector tests 498 499 TEST*/ 500