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