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_labels[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 @param num_values Number of values to register, must be contiguous in memory 63 64 @return An error code: 0 - success, otherwise - failure 65 66 @ref Developer 67 **/ 68 int CeedQFunctionContextRegisterGeneric(CeedQFunctionContext ctx, 69 const char *field_name, size_t field_offset, 70 const char *field_description, 71 CeedContextFieldType field_type, 72 size_t field_size, size_t num_values) { 73 int ierr; 74 75 // Check for duplicate 76 CeedInt field_index = -1; 77 ierr = CeedQFunctionContextGetFieldIndex(ctx, field_name, &field_index); 78 CeedChk(ierr); 79 if (field_index != -1) 80 // LCOV_EXCL_START 81 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 82 "QFunctionContext field with name \"%s\" already registered", 83 field_name); 84 // LCOV_EXCL_STOP 85 86 // Allocate space for field data 87 if (ctx->num_fields == 0) { 88 ierr = CeedCalloc(1, &ctx->field_labels); CeedChk(ierr); 89 ctx->max_fields = 1; 90 } else if (ctx->num_fields == ctx->max_fields) { 91 ierr = CeedRealloc(2*ctx->max_fields, &ctx->field_labels); 92 CeedChk(ierr); 93 ctx->max_fields *= 2; 94 } 95 ierr = CeedCalloc(1, &ctx->field_labels[ctx->num_fields]); CeedChk(ierr); 96 97 // Copy field data 98 ierr = CeedStringAllocCopy(field_name, 99 (char **)&ctx->field_labels[ctx->num_fields]->name); 100 CeedChk(ierr); 101 ierr = CeedStringAllocCopy(field_description, 102 (char **)&ctx->field_labels[ctx->num_fields]->description); 103 CeedChk(ierr); 104 ctx->field_labels[ctx->num_fields]->type = field_type; 105 ctx->field_labels[ctx->num_fields]->offset = field_offset; 106 ctx->field_labels[ctx->num_fields]->size = field_size * num_values; 107 ctx->field_labels[ctx->num_fields]->num_values = num_values; 108 ctx->num_fields++; 109 return CEED_ERROR_SUCCESS; 110 } 111 112 /// @} 113 114 /// ---------------------------------------------------------------------------- 115 /// CeedQFunctionContext Backend API 116 /// ---------------------------------------------------------------------------- 117 /// @addtogroup CeedQFunctionBackend 118 /// @{ 119 120 /** 121 @brief Get the Ceed associated with a CeedQFunctionContext 122 123 @param ctx CeedQFunctionContext 124 @param[out] ceed Variable to store Ceed 125 126 @return An error code: 0 - success, otherwise - failure 127 128 @ref Backend 129 **/ 130 int CeedQFunctionContextGetCeed(CeedQFunctionContext ctx, Ceed *ceed) { 131 *ceed = ctx->ceed; 132 return CEED_ERROR_SUCCESS; 133 } 134 135 /** 136 @brief Check for valid data in a CeedQFunctionContext 137 138 @param ctx CeedQFunctionContext to check validity 139 @param[out] has_valid_data Variable to store validity 140 141 @return An error code: 0 - success, otherwise - failure 142 143 @ref Backend 144 **/ 145 int CeedQFunctionContextHasValidData(CeedQFunctionContext ctx, 146 bool *has_valid_data) { 147 int ierr; 148 149 if (!ctx->HasValidData) 150 // LCOV_EXCL_START 151 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 152 "Backend does not support HasValidData"); 153 // LCOV_EXCL_STOP 154 155 ierr = ctx->HasValidData(ctx, has_valid_data); CeedChk(ierr); 156 157 return CEED_ERROR_SUCCESS; 158 } 159 160 /** 161 @brief Check for borrowed data of a specific CeedMemType in a 162 CeedQFunctionContext 163 164 @param ctx CeedQFunctionContext to check 165 @param mem_type Memory type to check 166 @param[out] has_borrowed_data_of_type Variable to store result 167 168 @return An error code: 0 - success, otherwise - failure 169 170 @ref Backend 171 **/ 172 int CeedQFunctionContextHasBorrowedDataOfType(CeedQFunctionContext ctx, 173 CeedMemType mem_type, bool *has_borrowed_data_of_type) { 174 int ierr; 175 176 if (!ctx->HasBorrowedDataOfType) 177 // LCOV_EXCL_START 178 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 179 "Backend does not support HasBorrowedDataOfType"); 180 // LCOV_EXCL_STOP 181 182 ierr = ctx->HasBorrowedDataOfType(ctx, mem_type, has_borrowed_data_of_type); 183 CeedChk(ierr); 184 185 return CEED_ERROR_SUCCESS; 186 } 187 188 /** 189 @brief Get the state of a CeedQFunctionContext 190 191 @param ctx CeedQFunctionContext to retrieve state 192 @param[out] state Variable to store state 193 194 @return An error code: 0 - success, otherwise - failure 195 196 @ref Backend 197 **/ 198 int CeedQFunctionContextGetState(CeedQFunctionContext ctx, uint64_t *state) { 199 *state = ctx->state; 200 return CEED_ERROR_SUCCESS; 201 } 202 203 /** 204 @brief Get backend data of a CeedQFunctionContext 205 206 @param ctx CeedQFunctionContext 207 @param[out] data Variable to store data 208 209 @return An error code: 0 - success, otherwise - failure 210 211 @ref Backend 212 **/ 213 int CeedQFunctionContextGetBackendData(CeedQFunctionContext ctx, void *data) { 214 *(void **)data = ctx->data; 215 return CEED_ERROR_SUCCESS; 216 } 217 218 /** 219 @brief Set backend data of a CeedQFunctionContext 220 221 @param[out] ctx CeedQFunctionContext 222 @param data Data to set 223 224 @return An error code: 0 - success, otherwise - failure 225 226 @ref Backend 227 **/ 228 int CeedQFunctionContextSetBackendData(CeedQFunctionContext ctx, void *data) { 229 ctx->data = data; 230 return CEED_ERROR_SUCCESS; 231 } 232 233 /** 234 @brief Set QFunctionContext field 235 236 @param ctx CeedQFunctionContext 237 @param field_label Label of field to set 238 @param field_type Type of field to set 239 @param value Value to set 240 241 @return An error code: 0 - success, otherwise - failure 242 243 @ref User 244 **/ 245 int CeedQFunctionContextSetGeneric(CeedQFunctionContext ctx, 246 CeedContextFieldLabel field_label, 247 CeedContextFieldType field_type, 248 void *value) { 249 int ierr; 250 251 // Check field type 252 if (field_label->type != field_type) 253 // LCOV_EXCL_START 254 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 255 "QFunctionContext field with name \"%s\" registered as %s, " 256 "not registered as %s", field_label->name, 257 CeedContextFieldTypes[field_label->type], 258 CeedContextFieldTypes[field_type]); 259 // LCOV_EXCL_STOP 260 261 char *data; 262 ierr = CeedQFunctionContextGetData(ctx, CEED_MEM_HOST, &data); CeedChk(ierr); 263 memcpy(&data[field_label->offset], value, field_label->size); 264 ierr = CeedQFunctionContextRestoreData(ctx, &data); CeedChk(ierr); 265 266 return CEED_ERROR_SUCCESS; 267 } 268 269 /** 270 @brief Increment the reference counter for a CeedQFunctionContext 271 272 @param ctx CeedQFunctionContext to increment the reference counter 273 274 @return An error code: 0 - success, otherwise - failure 275 276 @ref Backend 277 **/ 278 int CeedQFunctionContextReference(CeedQFunctionContext ctx) { 279 ctx->ref_count++; 280 return CEED_ERROR_SUCCESS; 281 } 282 283 /// @} 284 285 /// ---------------------------------------------------------------------------- 286 /// CeedQFunctionContext Public API 287 /// ---------------------------------------------------------------------------- 288 /// @addtogroup CeedQFunctionUser 289 /// @{ 290 291 /** 292 @brief Create a CeedQFunctionContext for storing CeedQFunction user context data 293 294 @param ceed A Ceed object where the CeedQFunctionContext will be created 295 @param[out] ctx Address of the variable where the newly created 296 CeedQFunctionContext will be stored 297 298 @return An error code: 0 - success, otherwise - failure 299 300 @ref User 301 **/ 302 int CeedQFunctionContextCreate(Ceed ceed, CeedQFunctionContext *ctx) { 303 int ierr; 304 305 if (!ceed->QFunctionContextCreate) { 306 Ceed delegate; 307 ierr = CeedGetObjectDelegate(ceed, &delegate, "Context"); CeedChk(ierr); 308 309 if (!delegate) 310 // LCOV_EXCL_START 311 return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 312 "Backend does not support ContextCreate"); 313 // LCOV_EXCL_STOP 314 315 ierr = CeedQFunctionContextCreate(delegate, ctx); CeedChk(ierr); 316 return CEED_ERROR_SUCCESS; 317 } 318 319 ierr = CeedCalloc(1, ctx); CeedChk(ierr); 320 (*ctx)->ceed = ceed; 321 ierr = CeedReference(ceed); CeedChk(ierr); 322 (*ctx)->ref_count = 1; 323 ierr = ceed->QFunctionContextCreate(*ctx); CeedChk(ierr); 324 return CEED_ERROR_SUCCESS; 325 } 326 327 /** 328 @brief Copy the pointer to a CeedQFunctionContext. Both pointers should 329 be destroyed with `CeedQFunctionContextDestroy()`; 330 Note: If `*ctx_copy` is non-NULL, then it is assumed that 331 `*ctx_copy` is a pointer to a CeedQFunctionContext. This 332 CeedQFunctionContext will be destroyed if `*ctx_copy` is the 333 only reference to this CeedQFunctionContext. 334 335 @param ctx CeedQFunctionContext to copy reference to 336 @param[out] ctx_copy Variable to store copied reference 337 338 @return An error code: 0 - success, otherwise - failure 339 340 @ref User 341 **/ 342 int CeedQFunctionContextReferenceCopy(CeedQFunctionContext ctx, 343 CeedQFunctionContext *ctx_copy) { 344 int ierr; 345 346 ierr = CeedQFunctionContextReference(ctx); CeedChk(ierr); 347 ierr = CeedQFunctionContextDestroy(ctx_copy); CeedChk(ierr); 348 *ctx_copy = ctx; 349 return CEED_ERROR_SUCCESS; 350 } 351 352 /** 353 @brief Set the data used by a CeedQFunctionContext, freeing any previously allocated 354 data if applicable. The backend may copy values to a different 355 memtype, such as during @ref CeedQFunctionApply(). 356 See also @ref CeedQFunctionContextTakeData(). 357 358 @param ctx CeedQFunctionContext 359 @param mem_type Memory type of the data being passed 360 @param copy_mode Copy mode for the data 361 @param size Size of data, in bytes 362 @param data Data to be used 363 364 @return An error code: 0 - success, otherwise - failure 365 366 @ref User 367 **/ 368 int CeedQFunctionContextSetData(CeedQFunctionContext ctx, CeedMemType mem_type, 369 CeedCopyMode copy_mode, 370 size_t size, void *data) { 371 int ierr; 372 373 if (!ctx->SetData) 374 // LCOV_EXCL_START 375 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 376 "Backend does not support ContextSetData"); 377 // LCOV_EXCL_STOP 378 379 if (ctx->state % 2 == 1) 380 // LCOV_EXCL_START 381 return CeedError(ctx->ceed, 1, 382 "Cannot grant CeedQFunctionContext data access, the " 383 "access lock is already in use"); 384 // LCOV_EXCL_STOP 385 386 ctx->ctx_size = size; 387 ierr = ctx->SetData(ctx, mem_type, copy_mode, data); CeedChk(ierr); 388 ctx->state += 2; 389 return CEED_ERROR_SUCCESS; 390 } 391 392 /** 393 @brief Take ownership of the data in a CeedQFunctionContext via the specified memory type. 394 The caller is responsible for managing and freeing the memory. 395 396 @param ctx CeedQFunctionContext to access 397 @param mem_type Memory type on which to access the data. If the backend 398 uses a different memory type, this will perform a copy. 399 @param[out] data Data on memory type mem_type 400 401 @return An error code: 0 - success, otherwise - failure 402 403 @ref User 404 **/ 405 int CeedQFunctionContextTakeData(CeedQFunctionContext ctx, CeedMemType mem_type, 406 void *data) { 407 int ierr; 408 409 bool has_valid_data = true; 410 ierr = CeedQFunctionContextHasValidData(ctx, &has_valid_data); CeedChk(ierr); 411 if (!has_valid_data) 412 // LCOV_EXCL_START 413 return CeedError(ctx->ceed, CEED_ERROR_BACKEND, 414 "CeedQFunctionContext has no valid data to take, must set data"); 415 // LCOV_EXCL_STOP 416 417 if (!ctx->TakeData) 418 // LCOV_EXCL_START 419 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 420 "Backend does not support TakeData"); 421 // LCOV_EXCL_STOP 422 423 if (ctx->state % 2 == 1) 424 // LCOV_EXCL_START 425 return CeedError(ctx->ceed, 1, 426 "Cannot grant CeedQFunctionContext data access, the " 427 "access lock is already in use"); 428 // LCOV_EXCL_STOP 429 430 bool has_borrowed_data_of_type = true; 431 ierr = CeedQFunctionContextHasBorrowedDataOfType(ctx, mem_type, 432 &has_borrowed_data_of_type); CeedChk(ierr); 433 if (!has_borrowed_data_of_type) 434 // LCOV_EXCL_START 435 return CeedError(ctx->ceed, CEED_ERROR_BACKEND, 436 "CeedQFunctionContext has no borowed %s data, " 437 "must set data with CeedQFunctionContextSetData", 438 CeedMemTypes[mem_type]); 439 // LCOV_EXCL_STOP 440 441 void *temp_data = NULL; 442 ierr = ctx->TakeData(ctx, mem_type, &temp_data); CeedChk(ierr); 443 if (data) (*(void **)data) = temp_data; 444 return CEED_ERROR_SUCCESS; 445 } 446 447 /** 448 @brief Get read/write access to a CeedQFunctionContext via the specified memory type. 449 Restore access with @ref CeedQFunctionContextRestoreData(). 450 451 @param ctx CeedQFunctionContext to access 452 @param mem_type Memory type on which to access the data. If the backend 453 uses a different memory type, this will perform a copy. 454 @param[out] data Data on memory type mem_type 455 456 @note The CeedQFunctionContextGetData() and @ref CeedQFunctionContextRestoreData() functions 457 provide access to array pointers in the desired memory space. Pairing 458 get/restore allows the Context to track access. 459 460 @return An error code: 0 - success, otherwise - failure 461 462 @ref User 463 **/ 464 int CeedQFunctionContextGetData(CeedQFunctionContext ctx, CeedMemType mem_type, 465 void *data) { 466 int ierr; 467 468 if (!ctx->GetData) 469 // LCOV_EXCL_START 470 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 471 "Backend does not support GetData"); 472 // LCOV_EXCL_STOP 473 474 if (ctx->state % 2 == 1) 475 // LCOV_EXCL_START 476 return CeedError(ctx->ceed, 1, 477 "Cannot grant CeedQFunctionContext data access, the " 478 "access lock is already in use"); 479 // LCOV_EXCL_STOP 480 481 if (ctx->num_readers > 0) 482 // LCOV_EXCL_START 483 return CeedError(ctx->ceed, 1, 484 "Cannot grant CeedQFunctionContext data access, a " 485 "process has read access"); 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++; 498 return CEED_ERROR_SUCCESS; 499 } 500 501 /** 502 @brief Get read only access to a CeedQFunctionContext via the specified memory type. 503 Restore access with @ref CeedQFunctionContextRestoreData(). 504 505 @param ctx CeedQFunctionContext to access 506 @param mem_type Memory type on which to access the data. If the backend 507 uses a different memory type, this will perform a copy. 508 @param[out] data Data on memory type mem_type 509 510 @note The CeedQFunctionContextGetDataRead() and @ref CeedQFunctionContextRestoreDataRead() 511 functions provide access to array pointers in the desired memory space. Pairing 512 get/restore allows the Context to track access. 513 514 @return An error code: 0 - success, otherwise - failure 515 516 @ref User 517 **/ 518 int CeedQFunctionContextGetDataRead(CeedQFunctionContext ctx, 519 CeedMemType mem_type, 520 void *data) { 521 int ierr; 522 523 if (!ctx->GetDataRead) 524 // LCOV_EXCL_START 525 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 526 "Backend does not support GetDataRead"); 527 // LCOV_EXCL_STOP 528 529 if (ctx->state % 2 == 1) 530 // LCOV_EXCL_START 531 return CeedError(ctx->ceed, 1, 532 "Cannot grant CeedQFunctionContext data access, the " 533 "access lock is already in use"); 534 // LCOV_EXCL_STOP 535 536 bool has_valid_data = true; 537 ierr = CeedQFunctionContextHasValidData(ctx, &has_valid_data); CeedChk(ierr); 538 if (!has_valid_data) 539 // LCOV_EXCL_START 540 return CeedError(ctx->ceed, CEED_ERROR_BACKEND, 541 "CeedQFunctionContext has no valid data to get, must set data"); 542 // LCOV_EXCL_STOP 543 544 ierr = ctx->GetDataRead(ctx, mem_type, data); CeedChk(ierr); 545 ctx->num_readers++; 546 return CEED_ERROR_SUCCESS; 547 } 548 549 /** 550 @brief Restore data obtained using @ref CeedQFunctionContextGetData() 551 552 @param ctx CeedQFunctionContext to restore 553 @param data Data to restore 554 555 @return An error code: 0 - success, otherwise - failure 556 557 @ref User 558 **/ 559 int CeedQFunctionContextRestoreData(CeedQFunctionContext ctx, void *data) { 560 int ierr; 561 562 if (ctx->state % 2 != 1) 563 // LCOV_EXCL_START 564 return CeedError(ctx->ceed, 1, 565 "Cannot restore CeedQFunctionContext array access, " 566 "access was not granted"); 567 // LCOV_EXCL_STOP 568 569 if (ctx->RestoreData) { 570 ierr = ctx->RestoreData(ctx); CeedChk(ierr); 571 } 572 *(void **)data = NULL; 573 ctx->state++; 574 return CEED_ERROR_SUCCESS; 575 } 576 577 /** 578 @brief Restore data obtained using @ref CeedQFunctionContextGetDataRead() 579 580 @param ctx CeedQFunctionContext to restore 581 @param data Data to restore 582 583 @return An error code: 0 - success, otherwise - failure 584 585 @ref User 586 **/ 587 int CeedQFunctionContextRestoreDataRead(CeedQFunctionContext ctx, void *data) { 588 int ierr; 589 590 if (ctx->num_readers == 0) 591 // LCOV_EXCL_START 592 return CeedError(ctx->ceed, 1, 593 "Cannot restore CeedQFunctionContext array access, " 594 "access was not granted"); 595 // LCOV_EXCL_STOP 596 597 if (ctx->RestoreDataRead) { 598 ierr = ctx->RestoreData(ctx); CeedChk(ierr); 599 } 600 *(void **)data = NULL; 601 ctx->num_readers--; 602 return CEED_ERROR_SUCCESS; 603 } 604 605 /** 606 @brief Register QFunctionContext a field holding a double precision value 607 608 @param ctx CeedQFunctionContext 609 @param field_name Name of field to register 610 @param field_offset Offset of field to register 611 @param num_values Number of values to register, must be contiguous in memory 612 @param field_description Description of field, or NULL for none 613 614 @return An error code: 0 - success, otherwise - failure 615 616 @ref User 617 **/ 618 int CeedQFunctionContextRegisterDouble(CeedQFunctionContext ctx, 619 const char *field_name, size_t field_offset, 620 size_t num_values, 621 const char *field_description) { 622 return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, 623 field_description, CEED_CONTEXT_FIELD_DOUBLE, sizeof(double), num_values); 624 } 625 626 /** 627 @brief Register QFunctionContext a field holding a int32 value 628 629 @param ctx CeedQFunctionContext 630 @param field_name Name of field to register 631 @param field_offset Offset of field to register 632 @param num_values Number of values to register, must be contiguous in memory 633 @param field_description Description of field, or NULL for none 634 635 @return An error code: 0 - success, otherwise - failure 636 637 @ref User 638 **/ 639 int CeedQFunctionContextRegisterInt32(CeedQFunctionContext ctx, 640 const char *field_name, size_t field_offset, 641 size_t num_values, 642 const char *field_description) { 643 return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, 644 field_description, CEED_CONTEXT_FIELD_INT32, sizeof(int), num_values); 645 } 646 647 /** 648 @brief Get labels for all registered QFunctionContext fields 649 650 @param ctx CeedQFunctionContext 651 @param[out] field_labels Variable to hold array of field labels 652 @param[out] num_fields Length of field descriptions array 653 654 @return An error code: 0 - success, otherwise - failure 655 656 @ref User 657 **/ 658 int CeedQFunctionContextGetAllFieldLabels(CeedQFunctionContext ctx, 659 const CeedContextFieldLabel **field_labels, CeedInt *num_fields) { 660 *field_labels = ctx->field_labels; 661 *num_fields = ctx->num_fields; 662 return CEED_ERROR_SUCCESS; 663 } 664 665 /** 666 @brief Get label for a registered QFunctionContext field, or `NULL` if no 667 field has been registered with this `field_name` 668 669 @param[in] ctx CeedQFunctionContext 670 @param[in] field_name Name of field to retrieve label 671 @param[out] field_label Variable to field label 672 673 @return An error code: 0 - success, otherwise - failure 674 675 @ref User 676 **/ 677 int CeedQFunctionContextGetFieldLabel(CeedQFunctionContext ctx, 678 const char *field_name, 679 CeedContextFieldLabel *field_label) { 680 int ierr; 681 682 CeedInt field_index; 683 ierr = CeedQFunctionContextGetFieldIndex(ctx, field_name, &field_index); 684 CeedChk(ierr); 685 686 if (field_index != -1) { 687 *field_label = ctx->field_labels[field_index]; 688 } else { 689 *field_label = NULL; 690 } 691 692 return CEED_ERROR_SUCCESS; 693 } 694 695 /** 696 @brief Get the descriptive information about a CeedContextFieldLabel 697 698 @param[in] label CeedContextFieldLabel 699 @param[out] field_name Name of labeled field 700 @param[out] field_description Description of field, or NULL for none 701 @param[out] num_values Number of values registered 702 @param[out] field_type CeedContextFieldType 703 704 @return An error code: 0 - success, otherwise - failure 705 706 @ref User 707 **/ 708 int CeedContextFieldLabelGetDescription(CeedContextFieldLabel label, 709 const char **field_name, 710 const char **field_description, 711 size_t *num_values, 712 CeedContextFieldType *field_type) { 713 if (field_name) *field_name = label->name; 714 if (field_description) *field_description = label->description; 715 if (num_values) *num_values = label->num_values; 716 if (field_type) *field_type = label->type; 717 return CEED_ERROR_SUCCESS; 718 } 719 720 /** 721 @brief Set QFunctionContext field holding a double precision value 722 723 @param ctx CeedQFunctionContext 724 @param field_label Label for field to register 725 @param values Values to set 726 727 @return An error code: 0 - success, otherwise - failure 728 729 @ref User 730 **/ 731 int CeedQFunctionContextSetDouble(CeedQFunctionContext ctx, 732 CeedContextFieldLabel field_label, double *values) { 733 int ierr; 734 735 if (!field_label) 736 // LCOV_EXCL_START 737 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 738 "Invalid field label"); 739 // LCOV_EXCL_STOP 740 741 ierr = CeedQFunctionContextSetGeneric(ctx, field_label, 742 CEED_CONTEXT_FIELD_DOUBLE, 743 values); CeedChk(ierr); 744 745 return CEED_ERROR_SUCCESS; 746 } 747 748 /** 749 @brief Set QFunctionContext field holding an int32 value 750 751 @param ctx CeedQFunctionContext 752 @param field_label Label for field to register 753 @param values Values to set 754 755 @return An error code: 0 - success, otherwise - failure 756 757 @ref User 758 **/ 759 int CeedQFunctionContextSetInt32(CeedQFunctionContext ctx, 760 CeedContextFieldLabel field_label, int *values) { 761 int ierr; 762 763 if (!field_label) 764 // LCOV_EXCL_START 765 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 766 "Invalid field label"); 767 // LCOV_EXCL_STOP 768 769 ierr = CeedQFunctionContextSetGeneric(ctx, field_label, 770 CEED_CONTEXT_FIELD_INT32, 771 values); CeedChk(ierr); 772 773 return CEED_ERROR_SUCCESS; 774 } 775 776 /** 777 @brief Get data size for a Context 778 779 @param ctx CeedQFunctionContext 780 @param[out] ctx_size Variable to store size of context data values 781 782 @return An error code: 0 - success, otherwise - failure 783 784 @ref User 785 **/ 786 int CeedQFunctionContextGetContextSize(CeedQFunctionContext ctx, 787 size_t *ctx_size) { 788 *ctx_size = ctx->ctx_size; 789 return CEED_ERROR_SUCCESS; 790 } 791 792 793 /** 794 @brief View a CeedQFunctionContext 795 796 @param[in] ctx CeedQFunctionContext to view 797 @param[in] stream Filestream to write to 798 799 @return An error code: 0 - success, otherwise - failure 800 801 @ref User 802 **/ 803 int CeedQFunctionContextView(CeedQFunctionContext ctx, FILE *stream) { 804 fprintf(stream, "CeedQFunctionContext\n"); 805 fprintf(stream, " Context Data Size: %ld\n", ctx->ctx_size); 806 for (CeedInt i = 0; i < ctx->num_fields; i++) { 807 // LCOV_EXCL_START 808 fprintf(stream, " Labeled %s field: %s\n", 809 CeedContextFieldTypes[ctx->field_labels[i]->type], 810 ctx->field_labels[i]->name); 811 // LCOV_EXCL_STOP 812 } 813 return CEED_ERROR_SUCCESS; 814 } 815 816 /** 817 @brief Destroy a CeedQFunctionContext 818 819 @param ctx CeedQFunctionContext to destroy 820 821 @return An error code: 0 - success, otherwise - failure 822 823 @ref User 824 **/ 825 int CeedQFunctionContextDestroy(CeedQFunctionContext *ctx) { 826 int ierr; 827 828 if (!*ctx || --(*ctx)->ref_count > 0) 829 return CEED_ERROR_SUCCESS; 830 831 if ((*ctx) && ((*ctx)->state % 2) == 1) 832 // LCOV_EXCL_START 833 return CeedError((*ctx)->ceed, 1, 834 "Cannot destroy CeedQFunctionContext, the access " 835 "lock is in use"); 836 // LCOV_EXCL_STOP 837 838 if ((*ctx)->Destroy) { 839 ierr = (*ctx)->Destroy(*ctx); CeedChk(ierr); 840 } 841 for (CeedInt i=0; i<(*ctx)->num_fields; i++) { 842 ierr = CeedFree(&(*ctx)->field_labels[i]->name); CeedChk(ierr); 843 ierr = CeedFree(&(*ctx)->field_labels[i]->description); CeedChk(ierr); 844 ierr = CeedFree(&(*ctx)->field_labels[i]); CeedChk(ierr); 845 } 846 ierr = CeedFree(&(*ctx)->field_labels); CeedChk(ierr); 847 ierr = CeedDestroy(&(*ctx)->ceed); CeedChk(ierr); 848 ierr = CeedFree(ctx); CeedChk(ierr); 849 850 return CEED_ERROR_SUCCESS; 851 } 852 853 /// @} 854