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");CHKERRQ(ierr); 48 CHKERRQ(PetscOptionsRangeInt("-dim", "The topological mesh dimension", "ex9.c", options->dim, &options->dim, NULL,1,3)); 49 CHKERRQ(PetscOptionsBool("-cellSimplex", "Flag for simplices", "ex9.c", options->cellSimplex, &options->cellSimplex, NULL)); 50 CHKERRQ(PetscOptionsBool("-spectral", "Flag for spectral element layout", "ex9.c", options->spectral, &options->spectral, NULL)); 51 CHKERRQ(PetscOptionsBool("-interpolate", "Flag for mesh interpolation", "ex9.c", options->interpolate, &options->interpolate, NULL)); 52 CHKERRQ(PetscOptionsReal("-refinement_limit", "The maximum volume of a refined cell", "ex9.c", options->refinementLimit, &options->refinementLimit, NULL)); 53 CHKERRQ(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 CHKERRQ(PetscMalloc1(len, &options->numComponents)); 57 CHKERRQ(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 CHKERRQ(PetscMalloc1(len, &options->numDof)); 62 CHKERRQ(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 CHKERRQ(PetscOptionsBool("-reuse_array", "Pass in user allocated array to VecGetClosure()", "ex9.c", options->reuseArray, &options->reuseArray, NULL)); 75 CHKERRQ(PetscOptionsBool("-errors", "Treat failures as errors", "ex9.c", options->errors, &options->errors, NULL)); 76 CHKERRQ(PetscOptionsBoundedInt("-iterations", "The number of iterations for a query", "ex9.c", options->iterations, &options->iterations, NULL,0)); 77 CHKERRQ(PetscOptionsReal("-max_cone_time", "The maximum time per run for DMPlexGetCone()", "ex9.c", options->maxConeTime, &options->maxConeTime, NULL)); 78 CHKERRQ(PetscOptionsReal("-max_closure_time", "The maximum time per run for DMPlexGetTransitiveClosure()", "ex9.c", options->maxClosureTime, &options->maxClosureTime, NULL)); 79 CHKERRQ(PetscOptionsReal("-max_vec_closure_time", "The maximum time per run for DMPlexVecGetClosure()", "ex9.c", options->maxVecClosureTime, &options->maxVecClosureTime, NULL)); 80 CHKERRQ(PetscOptionsBool("-print_times", "Print total times, do not check limits", "ex9.c", options->printTimes, &options->printTimes, NULL)); 81 ierr = PetscOptionsEnd();CHKERRQ(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 CHKERRQ(DMCreate(comm, &dm)); 98 CHKERRQ(PetscObjectSetName((PetscObject) dm, "triangular")); 99 CHKERRQ(DMSetType(dm, DMPLEX)); 100 CHKERRQ(DMSetDimension(dm, dim)); 101 CHKERRQ(DMPlexCreateFromDAG(dm, depth, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 102 for (p = 0; p < 4; ++p) { 103 CHKERRQ(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 CHKERRQ(DMCreate(comm, &dm)); 122 CHKERRQ(PetscObjectSetName((PetscObject) dm, "tetrahedral")); 123 CHKERRQ(DMSetType(dm, DMPLEX)); 124 CHKERRQ(DMSetDimension(dm, dim)); 125 CHKERRQ(DMPlexCreateFromDAG(dm, depth, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 126 for (p = 0; p < 5; ++p) { 127 CHKERRQ(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 CHKERRQ(DMCreate(comm, &dm)); 146 CHKERRQ(PetscObjectSetName((PetscObject) dm, "quadrilateral")); 147 CHKERRQ(DMSetType(dm, DMPLEX)); 148 CHKERRQ(DMSetDimension(dm, dim)); 149 CHKERRQ(DMPlexCreateFromDAG(dm, depth, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 150 for (p = 0; p < 6; ++p) { 151 CHKERRQ(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 CHKERRQ(DMCreate(comm, &dm)); 172 CHKERRQ(PetscObjectSetName((PetscObject) dm, "hexahedral")); 173 CHKERRQ(DMSetType(dm, DMPLEX)); 174 CHKERRQ(DMSetDimension(dm, dim)); 175 CHKERRQ(DMPlexCreateFromDAG(dm, depth, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 176 for (p = 0; p < 12; ++p) { 177 CHKERRQ(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 CHKERRQ(CreateSimplex_2D(comm, newdm)); 193 } else { 194 CHKERRQ(CreateQuad_2D(comm, newdm)); 195 } 196 break; 197 case 3: 198 if (cellSimplex) { 199 CHKERRQ(CreateSimplex_3D(comm, newdm)); 200 } else { 201 CHKERRQ(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 CHKERRQ(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE)); 212 CHKERRQ(DMPlexSetRefinementLimit(*newdm, user->refinementLimit)); 213 CHKERRQ(DMRefine(*newdm, PETSC_COMM_SELF, &rdm)); 214 CHKERRQ(PetscObjectGetName((PetscObject) *newdm, &name)); 215 CHKERRQ(PetscObjectSetName((PetscObject) rdm, name)); 216 CHKERRQ(DMDestroy(newdm)); 217 *newdm = rdm; 218 } 219 if (user->interpolate) { 220 DM idm; 221 222 CHKERRQ(DMPlexInterpolate(*newdm, &idm)); 223 CHKERRQ(DMDestroy(newdm)); 224 *newdm = idm; 225 } 226 CHKERRQ(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 CHKERRQ(PetscObjectGetComm((PetscObject)dm, &comm)); 242 CHKERRMPI(MPI_Comm_rank(comm, &rank)); 243 CHKERRQ(PetscLogStageRegister("DMPlex Cone Test", &stage)); 244 CHKERRQ(PetscLogEventRegister("Cone", PETSC_OBJECT_CLASSID, &event)); 245 CHKERRQ(PetscLogStagePush(stage)); 246 CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 247 CHKERRQ(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 CHKERRQ(DMPlexGetCone(dm, c, &cone)); 253 } 254 } 255 CHKERRQ(PetscLogEventEnd(event,0,0,0,0)); 256 CHKERRQ(PetscLogStagePop()); 257 258 CHKERRQ(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 CHKERRQ(PetscSynchronizedPrintf(comm, "[%d] Cones: %d Total time: %.3es Average time per cone: %.3es\n", rank, numRuns, eventInfo.time, eventInfo.time/numRuns)); 264 CHKERRQ(PetscSynchronizedFlush(comm, PETSC_STDOUT)); 265 } else if (eventInfo.time > maxTimePerRun * numRuns) { 266 CHKERRQ(PetscSynchronizedPrintf(comm, "[%d] Cones: %d Average time per cone: %gs standard: %gs\n", rank, numRuns, eventInfo.time/numRuns, maxTimePerRun)); 267 CHKERRQ(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 CHKERRQ(PetscObjectGetComm((PetscObject)dm, &comm)); 285 CHKERRMPI(MPI_Comm_rank(comm, &rank)); 286 CHKERRQ(PetscLogStageRegister("DMPlex Transitive Closure Test", &stage)); 287 CHKERRQ(PetscLogEventRegister("TransitiveClosure", PETSC_OBJECT_CLASSID, &event)); 288 CHKERRQ(PetscLogStagePush(stage)); 289 CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 290 CHKERRQ(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 CHKERRQ(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 297 CHKERRQ(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 298 } 299 } 300 CHKERRQ(PetscLogEventEnd(event,0,0,0,0)); 301 CHKERRQ(PetscLogStagePop()); 302 303 CHKERRQ(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 CHKERRQ(PetscSynchronizedPrintf(comm, "[%d] Closures: %d Total time: %.3es Average time per cone: %.3es\n", rank, numRuns, eventInfo.time, eventInfo.time/numRuns)); 309 CHKERRQ(PetscSynchronizedFlush(comm, PETSC_STDOUT)); 310 } else if (eventInfo.time > maxTimePerRun * numRuns) { 311 CHKERRQ(PetscSynchronizedPrintf(comm, "[%d] Closures: %d Average time per cone: %gs standard: %gs\n", rank, numRuns, eventInfo.time/numRuns, maxTimePerRun)); 312 CHKERRQ(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 CHKERRQ(PetscObjectGetComm((PetscObject)dm, &comm)); 334 CHKERRMPI(MPI_Comm_rank(comm, &rank)); 335 if (useIndex) { 336 if (useSpectral) { 337 CHKERRQ(PetscLogStageRegister("DMPlex Vector Closure with Index Test", &stage)); 338 CHKERRQ(PetscLogEventRegister("VecClosureInd", PETSC_OBJECT_CLASSID, &event)); 339 } else { 340 CHKERRQ(PetscLogStageRegister("DMPlex Vector Spectral Closure with Index Test", &stage)); 341 CHKERRQ(PetscLogEventRegister("VecClosureSpecInd", PETSC_OBJECT_CLASSID, &event)); 342 } 343 } else { 344 if (useSpectral) { 345 CHKERRQ(PetscLogStageRegister("DMPlex Vector Spectral Closure Test", &stage)); 346 CHKERRQ(PetscLogEventRegister("VecClosureSpec", PETSC_OBJECT_CLASSID, &event)); 347 } else { 348 CHKERRQ(PetscLogStageRegister("DMPlex Vector Closure Test", &stage)); 349 CHKERRQ(PetscLogEventRegister("VecClosure", PETSC_OBJECT_CLASSID, &event)); 350 } 351 } 352 CHKERRQ(PetscLogStagePush(stage)); 353 CHKERRQ(DMSetNumFields(dm, user->numFields)); 354 CHKERRQ(DMPlexCreateSection(dm, NULL, user->numComponents, user->numDof, 0, NULL, NULL, NULL, NULL, &s)); 355 CHKERRQ(DMSetLocalSection(dm, s)); 356 if (useIndex) CHKERRQ(DMPlexCreateClosureIndex(dm, s)); 357 if (useSpectral) CHKERRQ(DMPlexSetClosurePermutationTensor(dm, PETSC_DETERMINE, s)); 358 CHKERRQ(PetscSectionDestroy(&s)); 359 CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 360 CHKERRQ(DMGetLocalVector(dm, &v)); 361 CHKERRQ(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 CHKERRQ(DMPlexVecGetClosure(dm, s, v, c, &closureSize, &closure)); 368 if (!user->reuseArray) CHKERRQ(DMPlexVecRestoreClosure(dm, s, v, c, &closureSize, &closure)); 369 } 370 } 371 CHKERRQ(PetscLogEventEnd(event,0,0,0,0)); 372 CHKERRQ(DMRestoreLocalVector(dm, &v)); 373 CHKERRQ(PetscLogStagePop()); 374 375 CHKERRQ(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 CHKERRQ(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 CHKERRQ(PetscSynchronizedFlush(comm, PETSC_STDOUT)); 388 } else { 389 CHKERRQ(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 CHKERRQ(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 CHKERRQ(PetscFree(user->numComponents)); 401 CHKERRQ(PetscFree(user->numDof)); 402 PetscFunctionReturn(0); 403 } 404 405 int main(int argc, char **argv) 406 { 407 DM dm; 408 AppCtx user; 409 PetscErrorCode ierr; 410 411 ierr = PetscInitialize(&argc, &argv, NULL,help);if (ierr) return ierr; 412 CHKERRQ(ProcessOptions(&user)); 413 CHKERRQ(PetscLogDefaultBegin()); 414 CHKERRQ(CreateMesh(PETSC_COMM_WORLD, &user, &dm)); 415 CHKERRQ(TestCone(dm, &user)); 416 CHKERRQ(TestTransitiveClosure(dm, &user)); 417 CHKERRQ(TestVecClosure(dm, PETSC_FALSE, PETSC_FALSE, &user)); 418 CHKERRQ(TestVecClosure(dm, PETSC_TRUE, PETSC_FALSE, &user)); 419 if (!user.cellSimplex && user.spectral) { 420 CHKERRQ(TestVecClosure(dm, PETSC_FALSE, PETSC_TRUE, &user)); 421 CHKERRQ(TestVecClosure(dm, PETSC_TRUE, PETSC_TRUE, &user)); 422 } 423 CHKERRQ(DMDestroy(&dm)); 424 CHKERRQ(CleanupContext(&user)); 425 ierr = PetscFinalize(); 426 return ierr; 427 } 428 429 /*TEST 430 431 build: 432 requires: defined(PETSC_USE_LOG) 433 434 # 2D Simplex P_1 scalar tests 435 testset: 436 args: -num_dof 1,0,0 -iterations 2 -print_times 437 test: 438 suffix: correctness_0 439 test: 440 suffix: correctness_1 441 args: -interpolate -dm_refine 2 442 test: 443 suffix: correctness_2 444 requires: triangle 445 args: -interpolate -refinement_limit 1.0e-5 446 test: 447 suffix: 0 448 TODO: Only for performance testing 449 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 450 test: 451 suffix: 1 452 requires: triangle 453 TODO: Only for performance testing 454 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 455 test: 456 suffix: 2 457 TODO: Only for performance testing 458 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 459 test: 460 suffix: 3 461 requires: triangle 462 TODO: Only for performance testing 463 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 464 test: 465 suffix: 4 466 TODO: Only for performance testing 467 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 468 test: 469 suffix: 5 470 requires: triangle 471 TODO: Only for performance testing 472 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 473 test: 474 suffix: 6 475 TODO: Only for performance testing 476 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 477 test: 478 suffix: 7 479 requires: triangle 480 TODO: Only for performance testing 481 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 482 483 # 2D Simplex P_1 vector tests 484 # 2D Simplex P_2 scalar tests 485 # 2D Simplex P_2 vector tests 486 # 2D Simplex P_2/P_1 vector/scalar tests 487 # 2D Quad P_1 scalar tests 488 # 2D Quad P_1 vector tests 489 # 2D Quad P_2 scalar tests 490 # 2D Quad P_2 vector tests 491 # 3D Simplex P_1 scalar tests 492 # 3D Simplex P_1 vector tests 493 # 3D Simplex P_2 scalar tests 494 # 3D Simplex P_2 vector tests 495 # 3D Hex P_1 scalar tests 496 # 3D Hex P_1 vector tests 497 # 3D Hex P_2 scalar tests 498 # 3D Hex P_2 vector tests 499 500 TEST*/ 501