1 // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at 2 // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights 3 // reserved. See files LICENSE and NOTICE for details. 4 // 5 // This file is part of CEED, a collection of benchmarks, miniapps, software 6 // libraries and APIs for efficient high-order finite element and spectral 7 // element discretizations for exascale applications. For more information and 8 // source code availability see http://github.com/ceed. 9 // 10 // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 11 // a collaborative effort of two U.S. Department of Energy organizations (Office 12 // of Science and the National Nuclear Security Administration) responsible for 13 // the planning and preparation of a capable exascale ecosystem, including 14 // software, applications, hardware, advanced system engineering and early 15 // testbed platforms, in support of the nation's exascale computing imperative. 16 17 #include <ceed/ceed.h> 18 #include <ceed/backend.h> 19 #include <ceed-impl.h> 20 #include <stdint.h> 21 #include <stdio.h> 22 #include <string.h> 23 24 /// @file 25 /// Implementation of public CeedQFunctionContext interfaces 26 27 /// ---------------------------------------------------------------------------- 28 /// CeedQFunctionContext Library Internal Functions 29 /// ---------------------------------------------------------------------------- 30 /// @addtogroup CeedQFunctionDeveloper 31 /// @{ 32 33 /** 34 @brief Get index for QFunctionContext field 35 36 @param ctx CeedQFunctionContext 37 @param field_name Name of field 38 @param field_index Index of field, or -1 if field is not registered 39 40 @return An error code: 0 - success, otherwise - failure 41 42 @ref Developer 43 **/ 44 int CeedQFunctionContextGetFieldIndex(CeedQFunctionContext ctx, 45 const char *field_name, CeedInt *field_index) { 46 *field_index = -1; 47 for (CeedInt i=0; i<ctx->num_fields; i++) 48 if (!strcmp(ctx->field_descriptions[i].name, field_name)) 49 *field_index = i; 50 return CEED_ERROR_SUCCESS; 51 } 52 53 /** 54 @brief Common function for registering QFunctionContext fields 55 56 @param ctx CeedQFunctionContext 57 @param field_name Name of field to register 58 @param field_offset Offset of field to register 59 @param field_description Description of field, or NULL for none 60 @param field_type Field data type, such as double or int32 61 @param field_size Size of field, in bytes 62 63 @return An error code: 0 - success, otherwise - failure 64 65 @ref Developer 66 **/ 67 int CeedQFunctionContextRegisterGeneric(CeedQFunctionContext ctx, 68 const char *field_name, size_t field_offset, 69 const char *field_description, 70 CeedContextFieldType field_type, 71 size_t field_size) { 72 int ierr; 73 74 // Check for duplicate 75 CeedInt field_index = -1; 76 ierr = CeedQFunctionContextGetFieldIndex(ctx, field_name, &field_index); 77 CeedChk(ierr); 78 if (field_index != -1) 79 // LCOV_EXCL_START 80 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 81 "QFunctionContext field with name \"%s\" already registered", 82 field_name); 83 // LCOV_EXCL_STOP 84 85 // Allocate space for field data 86 if (ctx->num_fields == 0) { 87 ierr = CeedCalloc(1, &ctx->field_descriptions); CeedChk(ierr); 88 ctx->max_fields = 1; 89 } else if (ctx->num_fields == ctx->max_fields) { 90 ierr = CeedRealloc(2*ctx->max_fields, &ctx->field_descriptions); 91 CeedChk(ierr); 92 ctx->max_fields *= 2; 93 } 94 95 // Copy field data 96 ierr = CeedStringAllocCopy(field_name, 97 (char **)&ctx->field_descriptions[ctx->num_fields].name); 98 CeedChk(ierr); 99 ierr = CeedStringAllocCopy(field_description, 100 (char **)&ctx->field_descriptions[ctx->num_fields].description); 101 CeedChk(ierr); 102 ctx->field_descriptions[ctx->num_fields].type = field_type; 103 ctx->field_descriptions[ctx->num_fields].offset = field_offset; 104 ctx->field_descriptions[ctx->num_fields].size = field_size; 105 ctx->num_fields++; 106 return CEED_ERROR_SUCCESS; 107 } 108 109 /// @} 110 111 /// ---------------------------------------------------------------------------- 112 /// CeedQFunctionContext Backend API 113 /// ---------------------------------------------------------------------------- 114 /// @addtogroup CeedQFunctionBackend 115 /// @{ 116 117 /** 118 @brief Get the Ceed associated with a CeedQFunctionContext 119 120 @param ctx CeedQFunctionContext 121 @param[out] ceed Variable to store Ceed 122 123 @return An error code: 0 - success, otherwise - failure 124 125 @ref Backend 126 **/ 127 int CeedQFunctionContextGetCeed(CeedQFunctionContext ctx, Ceed *ceed) { 128 *ceed = ctx->ceed; 129 return CEED_ERROR_SUCCESS; 130 } 131 132 /** 133 @brief Check for valid data in a CeedQFunctionContext 134 135 @param ctx CeedQFunctionContext to check validity 136 @param[out] has_valid_data Variable to store validity 137 138 @return An error code: 0 - success, otherwise - failure 139 140 @ref Backend 141 **/ 142 int CeedQFunctionContextHasValidData(CeedQFunctionContext ctx, 143 bool *has_valid_data) { 144 int ierr; 145 146 if (!ctx->HasValidData) 147 // LCOV_EXCL_START 148 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 149 "Backend does not support HasValidData"); 150 // LCOV_EXCL_STOP 151 152 ierr = ctx->HasValidData(ctx, has_valid_data); CeedChk(ierr); 153 154 return CEED_ERROR_SUCCESS; 155 } 156 157 /** 158 @brief Check for borrowed data of a specific CeedMemType in a 159 CeedQFunctionContext 160 161 @param ctx CeedQFunctionContext to check 162 @param mem_type Memory type to check 163 @param[out] has_borrowed_data_of_type Variable to store result 164 165 @return An error code: 0 - success, otherwise - failure 166 167 @ref Backend 168 **/ 169 int CeedQFunctionContextHasBorrowedDataOfType(CeedQFunctionContext ctx, 170 CeedMemType mem_type, bool *has_borrowed_data_of_type) { 171 int ierr; 172 173 if (!ctx->HasBorrowedDataOfType) 174 // LCOV_EXCL_START 175 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 176 "Backend does not support HasBorrowedDataOfType"); 177 // LCOV_EXCL_STOP 178 179 ierr = ctx->HasBorrowedDataOfType(ctx, mem_type, has_borrowed_data_of_type); 180 CeedChk(ierr); 181 182 return CEED_ERROR_SUCCESS; 183 } 184 185 /** 186 @brief Get the state of a CeedQFunctionContext 187 188 @param ctx CeedQFunctionContext to retrieve state 189 @param[out] state Variable to store state 190 191 @return An error code: 0 - success, otherwise - failure 192 193 @ref Backend 194 **/ 195 int CeedQFunctionContextGetState(CeedQFunctionContext ctx, uint64_t *state) { 196 *state = ctx->state; 197 return CEED_ERROR_SUCCESS; 198 } 199 200 /** 201 @brief Get backend data of a CeedQFunctionContext 202 203 @param ctx CeedQFunctionContext 204 @param[out] data Variable to store data 205 206 @return An error code: 0 - success, otherwise - failure 207 208 @ref Backend 209 **/ 210 int CeedQFunctionContextGetBackendData(CeedQFunctionContext ctx, void *data) { 211 *(void **)data = ctx->data; 212 return CEED_ERROR_SUCCESS; 213 } 214 215 /** 216 @brief Set backend data of a CeedQFunctionContext 217 218 @param[out] ctx CeedQFunctionContext 219 @param data Data to set 220 221 @return An error code: 0 - success, otherwise - failure 222 223 @ref Backend 224 **/ 225 int CeedQFunctionContextSetBackendData(CeedQFunctionContext ctx, void *data) { 226 ctx->data = data; 227 return CEED_ERROR_SUCCESS; 228 } 229 230 /** 231 @brief Set QFunctionContext field 232 233 @param ctx CeedQFunctionContext 234 @param field_name Name of field to set 235 @param field_type Type of field to set 236 @param is_set Boolean flag if value was set 237 @param value Value to set 238 239 @return An error code: 0 - success, otherwise - failure 240 241 @ref User 242 **/ 243 int CeedQFunctionContextSetGeneric(CeedQFunctionContext ctx, 244 const char *field_name, 245 CeedContextFieldType field_type, 246 bool *is_set, void *value) { 247 int ierr; 248 249 // Check field index 250 *is_set = false; 251 CeedInt field_index = -1; 252 ierr = CeedQFunctionContextGetFieldIndex(ctx, field_name, &field_index); 253 CeedChk(ierr); 254 if (field_index == -1) 255 return CEED_ERROR_SUCCESS; 256 257 if (ctx->field_descriptions[field_index].type != field_type) 258 // LCOV_EXCL_START 259 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 260 "QFunctionContext field with name \"%s\" registered as %s, " 261 "not registered as %s", field_name, 262 CeedContextFieldTypes[ctx->field_descriptions[field_index].type], 263 CeedContextFieldTypes[field_type]); 264 // LCOV_EXCL_STOP 265 266 char *data; 267 ierr = CeedQFunctionContextGetData(ctx, CEED_MEM_HOST, &data); CeedChk(ierr); 268 memcpy(&data[ctx->field_descriptions[field_index].offset], value, 269 ctx->field_descriptions[field_index].size); 270 ierr = CeedQFunctionContextRestoreData(ctx, &data); CeedChk(ierr); 271 *is_set = true; 272 273 return CEED_ERROR_SUCCESS; 274 } 275 276 /** 277 @brief Increment the reference counter for a CeedQFunctionContext 278 279 @param ctx CeedQFunctionContext to increment the reference counter 280 281 @return An error code: 0 - success, otherwise - failure 282 283 @ref Backend 284 **/ 285 int CeedQFunctionContextReference(CeedQFunctionContext ctx) { 286 ctx->ref_count++; 287 return CEED_ERROR_SUCCESS; 288 } 289 290 /// @} 291 292 /// ---------------------------------------------------------------------------- 293 /// CeedQFunctionContext Public API 294 /// ---------------------------------------------------------------------------- 295 /// @addtogroup CeedQFunctionUser 296 /// @{ 297 298 /** 299 @brief Create a CeedQFunctionContext for storing CeedQFunction user context data 300 301 @param ceed A Ceed object where the CeedQFunctionContext will be created 302 @param[out] ctx Address of the variable where the newly created 303 CeedQFunctionContext will be stored 304 305 @return An error code: 0 - success, otherwise - failure 306 307 @ref User 308 **/ 309 int CeedQFunctionContextCreate(Ceed ceed, CeedQFunctionContext *ctx) { 310 int ierr; 311 312 if (!ceed->QFunctionContextCreate) { 313 Ceed delegate; 314 ierr = CeedGetObjectDelegate(ceed, &delegate, "Context"); CeedChk(ierr); 315 316 if (!delegate) 317 // LCOV_EXCL_START 318 return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 319 "Backend does not support ContextCreate"); 320 // LCOV_EXCL_STOP 321 322 ierr = CeedQFunctionContextCreate(delegate, ctx); CeedChk(ierr); 323 return CEED_ERROR_SUCCESS; 324 } 325 326 ierr = CeedCalloc(1, ctx); CeedChk(ierr); 327 (*ctx)->ceed = ceed; 328 ierr = CeedReference(ceed); CeedChk(ierr); 329 (*ctx)->ref_count = 1; 330 ierr = ceed->QFunctionContextCreate(*ctx); CeedChk(ierr); 331 return CEED_ERROR_SUCCESS; 332 } 333 334 /** 335 @brief Copy the pointer to a CeedQFunctionContext. Both pointers should 336 be destroyed with `CeedQFunctionContextDestroy()`; 337 Note: If `*ctx_copy` is non-NULL, then it is assumed that 338 `*ctx_copy` is a pointer to a CeedQFunctionContext. This 339 CeedQFunctionContext will be destroyed if `*ctx_copy` is the 340 only reference to this CeedQFunctionContext. 341 342 @param ctx CeedQFunctionContext to copy reference to 343 @param[out] ctx_copy Variable to store copied reference 344 345 @return An error code: 0 - success, otherwise - failure 346 347 @ref User 348 **/ 349 int CeedQFunctionContextReferenceCopy(CeedQFunctionContext ctx, 350 CeedQFunctionContext *ctx_copy) { 351 int ierr; 352 353 ierr = CeedQFunctionContextReference(ctx); CeedChk(ierr); 354 ierr = CeedQFunctionContextDestroy(ctx_copy); CeedChk(ierr); 355 *ctx_copy = ctx; 356 return CEED_ERROR_SUCCESS; 357 } 358 359 /** 360 @brief Set the data used by a CeedQFunctionContext, freeing any previously allocated 361 data if applicable. The backend may copy values to a different 362 memtype, such as during @ref CeedQFunctionApply(). 363 See also @ref CeedQFunctionContextTakeData(). 364 365 @param ctx CeedQFunctionContext 366 @param mem_type Memory type of the data being passed 367 @param copy_mode Copy mode for the data 368 @param size Size of data, in bytes 369 @param data Data to be used 370 371 @return An error code: 0 - success, otherwise - failure 372 373 @ref User 374 **/ 375 int CeedQFunctionContextSetData(CeedQFunctionContext ctx, CeedMemType mem_type, 376 CeedCopyMode copy_mode, 377 size_t size, void *data) { 378 int ierr; 379 380 if (!ctx->SetData) 381 // LCOV_EXCL_START 382 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 383 "Backend does not support ContextSetData"); 384 // LCOV_EXCL_STOP 385 386 if (ctx->state % 2 == 1) 387 // LCOV_EXCL_START 388 return CeedError(ctx->ceed, 1, 389 "Cannot grant CeedQFunctionContext data access, the " 390 "access lock is already in use"); 391 // LCOV_EXCL_STOP 392 393 ctx->ctx_size = size; 394 ierr = ctx->SetData(ctx, mem_type, copy_mode, data); CeedChk(ierr); 395 ctx->state += 2; 396 return CEED_ERROR_SUCCESS; 397 } 398 399 /** 400 @brief Take ownership of the data in a CeedQFunctionContext via the specified memory type. 401 The caller is responsible for managing and freeing the memory. 402 403 @param ctx CeedQFunctionContext to access 404 @param mem_type Memory type on which to access the data. If the backend 405 uses a different memory type, this will perform a copy. 406 @param[out] data Data on memory type mem_type 407 408 @return An error code: 0 - success, otherwise - failure 409 410 @ref User 411 **/ 412 int CeedQFunctionContextTakeData(CeedQFunctionContext ctx, CeedMemType mem_type, 413 void *data) { 414 int ierr; 415 416 bool has_valid_data = true; 417 ierr = CeedQFunctionContextHasValidData(ctx, &has_valid_data); CeedChk(ierr); 418 if (!has_valid_data) 419 // LCOV_EXCL_START 420 return CeedError(ctx->ceed, CEED_ERROR_BACKEND, 421 "CeedQFunctionContext has no valid data to take, must set data"); 422 // LCOV_EXCL_STOP 423 424 if (!ctx->TakeData) 425 // LCOV_EXCL_START 426 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 427 "Backend does not support TakeData"); 428 // LCOV_EXCL_STOP 429 430 if (ctx->state % 2 == 1) 431 // LCOV_EXCL_START 432 return CeedError(ctx->ceed, 1, 433 "Cannot grant CeedQFunctionContext data access, the " 434 "access lock is already in use"); 435 // LCOV_EXCL_STOP 436 437 bool has_borrowed_data_of_type = true; 438 ierr = CeedQFunctionContextHasBorrowedDataOfType(ctx, mem_type, 439 &has_borrowed_data_of_type); CeedChk(ierr); 440 if (!has_borrowed_data_of_type) 441 // LCOV_EXCL_START 442 return CeedError(ctx->ceed, CEED_ERROR_BACKEND, 443 "CeedQFunctionContext has no borowed %s data, " 444 "must set data with CeedQFunctionContextSetData", 445 CeedMemTypes[mem_type]); 446 // LCOV_EXCL_STOP 447 448 void *temp_data = NULL; 449 ierr = ctx->TakeData(ctx, mem_type, &temp_data); CeedChk(ierr); 450 if (data) (*(void **)data) = temp_data; 451 return CEED_ERROR_SUCCESS; 452 } 453 454 /** 455 @brief Get read/write access to a CeedQFunctionContext via the specified memory type. 456 Restore access with @ref CeedQFunctionContextRestoreData(). 457 458 @param ctx CeedQFunctionContext to access 459 @param mem_type Memory type on which to access the data. If the backend 460 uses a different memory type, this will perform a copy. 461 @param[out] data Data on memory type mem_type 462 463 @note The CeedQFunctionContextGetData() and @ref CeedQFunctionContextRestoreData() functions 464 provide access to array pointers in the desired memory space. Pairing 465 get/restore allows the Context to track access. 466 467 @return An error code: 0 - success, otherwise - failure 468 469 @ref User 470 **/ 471 int CeedQFunctionContextGetData(CeedQFunctionContext ctx, CeedMemType mem_type, 472 void *data) { 473 int ierr; 474 475 if (!ctx->GetData) 476 // LCOV_EXCL_START 477 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 478 "Backend does not support GetData"); 479 // LCOV_EXCL_STOP 480 481 if (ctx->state % 2 == 1) 482 // LCOV_EXCL_START 483 return CeedError(ctx->ceed, 1, 484 "Cannot grant CeedQFunctionContext data access, the " 485 "access lock is already in use"); 486 // LCOV_EXCL_STOP 487 488 bool has_valid_data = true; 489 ierr = CeedQFunctionContextHasValidData(ctx, &has_valid_data); CeedChk(ierr); 490 if (!has_valid_data) 491 // LCOV_EXCL_START 492 return CeedError(ctx->ceed, CEED_ERROR_BACKEND, 493 "CeedQFunctionContext has no valid data to get, must set data"); 494 // LCOV_EXCL_STOP 495 496 ierr = ctx->GetData(ctx, mem_type, data); CeedChk(ierr); 497 ctx->state += 1; 498 return CEED_ERROR_SUCCESS; 499 } 500 501 /** 502 @brief Restore data obtained using @ref CeedQFunctionContextGetData() 503 504 @param ctx CeedQFunctionContext to restore 505 @param data Data to restore 506 507 @return An error code: 0 - success, otherwise - failure 508 509 @ref User 510 **/ 511 int CeedQFunctionContextRestoreData(CeedQFunctionContext ctx, void *data) { 512 int ierr; 513 514 if (!ctx->RestoreData) 515 // LCOV_EXCL_START 516 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 517 "Backend does not support RestoreData"); 518 // LCOV_EXCL_STOP 519 520 if (ctx->state % 2 != 1) 521 // LCOV_EXCL_START 522 return CeedError(ctx->ceed, 1, 523 "Cannot restore CeedQFunctionContext array access, " 524 "access was not granted"); 525 // LCOV_EXCL_STOP 526 527 ierr = ctx->RestoreData(ctx); CeedChk(ierr); 528 *(void **)data = NULL; 529 ctx->state += 1; 530 return CEED_ERROR_SUCCESS; 531 } 532 533 /** 534 @brief Register QFunctionContext a field holding a double precision value 535 536 @param ctx CeedQFunctionContext 537 @param field_name Name of field to register 538 @param field_offset Offset of field to register 539 @param field_description Description of field, or NULL for none 540 541 @return An error code: 0 - success, otherwise - failure 542 543 @ref User 544 **/ 545 int CeedQFunctionContextRegisterDouble(CeedQFunctionContext ctx, 546 const char *field_name, size_t field_offset, 547 const char *field_description) { 548 return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, 549 field_description, CEED_CONTEXT_FIELD_DOUBLE, sizeof(double)); 550 } 551 552 /** 553 @brief Register QFunctionContext a field holding a int32 value 554 555 @param ctx CeedQFunctionContext 556 @param field_name Name of field to register 557 @param field_offset Offset of field to register 558 @param field_description Description of field, or NULL for none 559 560 @return An error code: 0 - success, otherwise - failure 561 562 @ref User 563 **/ 564 int CeedQFunctionContextRegisterInt32(CeedQFunctionContext ctx, 565 const char *field_name, size_t field_offset, 566 const char *field_description) { 567 return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, 568 field_description, CEED_CONTEXT_FIELD_INT32, sizeof(int)); 569 } 570 571 /** 572 @brief Get descriptions for registered QFunctionContext fields 573 574 @param ctx CeedQFunctionContext 575 @param[out] field_descriptions Variable to hold array of field descriptions 576 @param[out] num_fields Length of field descriptions array 577 578 @return An error code: 0 - success, otherwise - failure 579 580 @ref User 581 **/ 582 int CeedQFunctionContextGetFieldDescriptions(CeedQFunctionContext ctx, 583 const CeedQFunctionContextFieldDescription **field_descriptions, 584 CeedInt *num_fields) { 585 *field_descriptions = ctx->field_descriptions; 586 *num_fields = ctx->num_fields; 587 return CEED_ERROR_SUCCESS; 588 } 589 590 /** 591 @brief Set QFunctionContext field holding a double precision value 592 593 @param ctx CeedQFunctionContext 594 @param field_name Name of field to register 595 @param value Value to set 596 597 @return An error code: 0 - success, otherwise - failure 598 599 @ref User 600 **/ 601 int CeedQFunctionContextSetDouble(CeedQFunctionContext ctx, 602 const char *field_name, double value) { 603 int ierr; 604 bool is_set = false; 605 606 ierr = CeedQFunctionContextSetGeneric(ctx, field_name, 607 CEED_CONTEXT_FIELD_DOUBLE, 608 &is_set, &value); CeedChk(ierr); 609 if (!is_set) 610 // LCOV_EXCL_START 611 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 612 "QFunctionContext field with name \"%s\" not registered", 613 field_name); 614 // LCOV_EXCL_STOP 615 616 return CEED_ERROR_SUCCESS; 617 } 618 619 /** 620 @brief Set QFunctionContext field holding an int32 value 621 622 @param ctx CeedQFunctionContext 623 @param field_name Name of field to set 624 @param value Value to set 625 626 @return An error code: 0 - success, otherwise - failure 627 628 @ref User 629 **/ 630 int CeedQFunctionContextSetInt32(CeedQFunctionContext ctx, 631 const char *field_name, int value) { 632 int ierr; 633 bool is_set = false; 634 635 ierr = CeedQFunctionContextSetGeneric(ctx, field_name, 636 CEED_CONTEXT_FIELD_INT32, 637 &is_set, &value); CeedChk(ierr); 638 if (!is_set) 639 // LCOV_EXCL_START 640 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 641 "QFunctionContext field with name \"%s\" not registered", 642 field_name); 643 // LCOV_EXCL_STOP 644 645 return CEED_ERROR_SUCCESS; 646 } 647 648 /** 649 @brief Get data size for a Context 650 651 @param ctx CeedQFunctionContext 652 @param[out] ctx_size Variable to store size of context data values 653 654 @return An error code: 0 - success, otherwise - failure 655 656 @ref User 657 **/ 658 int CeedQFunctionContextGetContextSize(CeedQFunctionContext ctx, 659 size_t *ctx_size) { 660 *ctx_size = ctx->ctx_size; 661 return CEED_ERROR_SUCCESS; 662 } 663 664 665 /** 666 @brief View a CeedQFunctionContext 667 668 @param[in] ctx CeedQFunctionContext to view 669 @param[in] stream Filestream to write to 670 671 @return An error code: 0 - success, otherwise - failure 672 673 @ref User 674 **/ 675 int CeedQFunctionContextView(CeedQFunctionContext ctx, FILE *stream) { 676 fprintf(stream, "CeedQFunctionContext\n"); 677 fprintf(stream, " Context Data Size: %ld\n", ctx->ctx_size); 678 return CEED_ERROR_SUCCESS; 679 } 680 681 /** 682 @brief Destroy a CeedQFunctionContext 683 684 @param ctx CeedQFunctionContext to destroy 685 686 @return An error code: 0 - success, otherwise - failure 687 688 @ref User 689 **/ 690 int CeedQFunctionContextDestroy(CeedQFunctionContext *ctx) { 691 int ierr; 692 693 if (!*ctx || --(*ctx)->ref_count > 0) 694 return CEED_ERROR_SUCCESS; 695 696 if ((*ctx) && ((*ctx)->state % 2) == 1) 697 // LCOV_EXCL_START 698 return CeedError((*ctx)->ceed, 1, 699 "Cannot destroy CeedQFunctionContext, the access " 700 "lock is in use"); 701 // LCOV_EXCL_STOP 702 703 if ((*ctx)->Destroy) { 704 ierr = (*ctx)->Destroy(*ctx); CeedChk(ierr); 705 } 706 for (CeedInt i=0; i<(*ctx)->num_fields; i++) { 707 ierr = CeedFree(&(*ctx)->field_descriptions[i].name); CeedChk(ierr); 708 ierr = CeedFree(&(*ctx)->field_descriptions[i].description); CeedChk(ierr); 709 } 710 ierr = CeedFree(&(*ctx)->field_descriptions); CeedChk(ierr); 711 ierr = CeedDestroy(&(*ctx)->ceed); CeedChk(ierr); 712 ierr = CeedFree(ctx); CeedChk(ierr); 713 714 return CEED_ERROR_SUCCESS; 715 } 716 717 /// @} 718