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 Set QFunctionContext field holding a double precision value 292 293 @param ctx CeedQFunctionContext 294 @param field_label Label for field to register 295 @param values Values to set 296 297 @return An error code: 0 - success, otherwise - failure 298 299 @ref User 300 **/ 301 int CeedQFunctionContextSetDouble(CeedQFunctionContext ctx, 302 CeedContextFieldLabel field_label, double *values) { 303 int ierr; 304 305 if (!field_label) 306 // LCOV_EXCL_START 307 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 308 "Invalid field label"); 309 // LCOV_EXCL_STOP 310 311 ierr = CeedQFunctionContextSetGeneric(ctx, field_label, 312 CEED_CONTEXT_FIELD_DOUBLE, 313 values); CeedChk(ierr); 314 315 return CEED_ERROR_SUCCESS; 316 } 317 318 /** 319 @brief Set QFunctionContext field holding an int32 value 320 321 @param ctx CeedQFunctionContext 322 @param field_label Label for field to register 323 @param values Values to set 324 325 @return An error code: 0 - success, otherwise - failure 326 327 @ref User 328 **/ 329 int CeedQFunctionContextSetInt32(CeedQFunctionContext ctx, 330 CeedContextFieldLabel field_label, int *values) { 331 int ierr; 332 333 if (!field_label) 334 // LCOV_EXCL_START 335 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 336 "Invalid field label"); 337 // LCOV_EXCL_STOP 338 339 ierr = CeedQFunctionContextSetGeneric(ctx, field_label, 340 CEED_CONTEXT_FIELD_INT32, 341 values); CeedChk(ierr); 342 343 return CEED_ERROR_SUCCESS; 344 } 345 346 /** 347 @brief Increment the reference counter for a CeedQFunctionContext 348 349 @param ctx CeedQFunctionContext to increment the reference counter 350 351 @return An error code: 0 - success, otherwise - failure 352 353 @ref Backend 354 **/ 355 int CeedQFunctionContextReference(CeedQFunctionContext ctx) { 356 ctx->ref_count++; 357 return CEED_ERROR_SUCCESS; 358 } 359 360 /// @} 361 362 /// ---------------------------------------------------------------------------- 363 /// CeedQFunctionContext Public API 364 /// ---------------------------------------------------------------------------- 365 /// @addtogroup CeedQFunctionUser 366 /// @{ 367 368 /** 369 @brief Create a CeedQFunctionContext for storing CeedQFunction user context data 370 371 @param ceed A Ceed object where the CeedQFunctionContext will be created 372 @param[out] ctx Address of the variable where the newly created 373 CeedQFunctionContext will be stored 374 375 @return An error code: 0 - success, otherwise - failure 376 377 @ref User 378 **/ 379 int CeedQFunctionContextCreate(Ceed ceed, CeedQFunctionContext *ctx) { 380 int ierr; 381 382 if (!ceed->QFunctionContextCreate) { 383 Ceed delegate; 384 ierr = CeedGetObjectDelegate(ceed, &delegate, "Context"); CeedChk(ierr); 385 386 if (!delegate) 387 // LCOV_EXCL_START 388 return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 389 "Backend does not support ContextCreate"); 390 // LCOV_EXCL_STOP 391 392 ierr = CeedQFunctionContextCreate(delegate, ctx); CeedChk(ierr); 393 return CEED_ERROR_SUCCESS; 394 } 395 396 ierr = CeedCalloc(1, ctx); CeedChk(ierr); 397 (*ctx)->ceed = ceed; 398 ierr = CeedReference(ceed); CeedChk(ierr); 399 (*ctx)->ref_count = 1; 400 ierr = ceed->QFunctionContextCreate(*ctx); CeedChk(ierr); 401 return CEED_ERROR_SUCCESS; 402 } 403 404 /** 405 @brief Copy the pointer to a CeedQFunctionContext. Both pointers should 406 be destroyed with `CeedQFunctionContextDestroy()`; 407 Note: If `*ctx_copy` is non-NULL, then it is assumed that 408 `*ctx_copy` is a pointer to a CeedQFunctionContext. This 409 CeedQFunctionContext will be destroyed if `*ctx_copy` is the 410 only reference to this CeedQFunctionContext. 411 412 @param ctx CeedQFunctionContext to copy reference to 413 @param[out] ctx_copy Variable to store copied reference 414 415 @return An error code: 0 - success, otherwise - failure 416 417 @ref User 418 **/ 419 int CeedQFunctionContextReferenceCopy(CeedQFunctionContext ctx, 420 CeedQFunctionContext *ctx_copy) { 421 int ierr; 422 423 ierr = CeedQFunctionContextReference(ctx); CeedChk(ierr); 424 ierr = CeedQFunctionContextDestroy(ctx_copy); CeedChk(ierr); 425 *ctx_copy = ctx; 426 return CEED_ERROR_SUCCESS; 427 } 428 429 /** 430 @brief Set the data used by a CeedQFunctionContext, freeing any previously allocated 431 data if applicable. The backend may copy values to a different 432 memtype, such as during @ref CeedQFunctionApply(). 433 See also @ref CeedQFunctionContextTakeData(). 434 435 @param ctx CeedQFunctionContext 436 @param mem_type Memory type of the data being passed 437 @param copy_mode Copy mode for the data 438 @param size Size of data, in bytes 439 @param data Data to be used 440 441 @return An error code: 0 - success, otherwise - failure 442 443 @ref User 444 **/ 445 int CeedQFunctionContextSetData(CeedQFunctionContext ctx, CeedMemType mem_type, 446 CeedCopyMode copy_mode, 447 size_t size, void *data) { 448 int ierr; 449 450 if (!ctx->SetData) 451 // LCOV_EXCL_START 452 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 453 "Backend does not support ContextSetData"); 454 // LCOV_EXCL_STOP 455 456 if (ctx->state % 2 == 1) 457 // LCOV_EXCL_START 458 return CeedError(ctx->ceed, 1, 459 "Cannot grant CeedQFunctionContext data access, the " 460 "access lock is already in use"); 461 // LCOV_EXCL_STOP 462 463 ctx->ctx_size = size; 464 ierr = ctx->SetData(ctx, mem_type, copy_mode, data); CeedChk(ierr); 465 ctx->state += 2; 466 return CEED_ERROR_SUCCESS; 467 } 468 469 /** 470 @brief Take ownership of the data in a CeedQFunctionContext via the specified memory type. 471 The caller is responsible for managing and freeing the memory. 472 473 @param ctx CeedQFunctionContext to access 474 @param mem_type Memory type on which to access the data. If the backend 475 uses a different memory type, this will perform a copy. 476 @param[out] data Data on memory type mem_type 477 478 @return An error code: 0 - success, otherwise - failure 479 480 @ref User 481 **/ 482 int CeedQFunctionContextTakeData(CeedQFunctionContext ctx, CeedMemType mem_type, 483 void *data) { 484 int ierr; 485 486 bool has_valid_data = true; 487 ierr = CeedQFunctionContextHasValidData(ctx, &has_valid_data); CeedChk(ierr); 488 if (!has_valid_data) 489 // LCOV_EXCL_START 490 return CeedError(ctx->ceed, CEED_ERROR_BACKEND, 491 "CeedQFunctionContext has no valid data to take, must set data"); 492 // LCOV_EXCL_STOP 493 494 if (!ctx->TakeData) 495 // LCOV_EXCL_START 496 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 497 "Backend does not support TakeData"); 498 // LCOV_EXCL_STOP 499 500 if (ctx->state % 2 == 1) 501 // LCOV_EXCL_START 502 return CeedError(ctx->ceed, 1, 503 "Cannot grant CeedQFunctionContext data access, the " 504 "access lock is already in use"); 505 // LCOV_EXCL_STOP 506 507 bool has_borrowed_data_of_type = true; 508 ierr = CeedQFunctionContextHasBorrowedDataOfType(ctx, mem_type, 509 &has_borrowed_data_of_type); CeedChk(ierr); 510 if (!has_borrowed_data_of_type) 511 // LCOV_EXCL_START 512 return CeedError(ctx->ceed, CEED_ERROR_BACKEND, 513 "CeedQFunctionContext has no borowed %s data, " 514 "must set data with CeedQFunctionContextSetData", 515 CeedMemTypes[mem_type]); 516 // LCOV_EXCL_STOP 517 518 void *temp_data = NULL; 519 ierr = ctx->TakeData(ctx, mem_type, &temp_data); CeedChk(ierr); 520 if (data) (*(void **)data) = temp_data; 521 return CEED_ERROR_SUCCESS; 522 } 523 524 /** 525 @brief Get read/write access to a CeedQFunctionContext via the specified memory type. 526 Restore access with @ref CeedQFunctionContextRestoreData(). 527 528 @param ctx CeedQFunctionContext to access 529 @param mem_type Memory type on which to access the data. If the backend 530 uses a different memory type, this will perform a copy. 531 @param[out] data Data on memory type mem_type 532 533 @note The CeedQFunctionContextGetData() and @ref CeedQFunctionContextRestoreData() functions 534 provide access to array pointers in the desired memory space. Pairing 535 get/restore allows the Context to track access. 536 537 @return An error code: 0 - success, otherwise - failure 538 539 @ref User 540 **/ 541 int CeedQFunctionContextGetData(CeedQFunctionContext ctx, CeedMemType mem_type, 542 void *data) { 543 int ierr; 544 545 if (!ctx->GetData) 546 // LCOV_EXCL_START 547 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 548 "Backend does not support GetData"); 549 // LCOV_EXCL_STOP 550 551 if (ctx->state % 2 == 1) 552 // LCOV_EXCL_START 553 return CeedError(ctx->ceed, 1, 554 "Cannot grant CeedQFunctionContext data access, the " 555 "access lock is already in use"); 556 // LCOV_EXCL_STOP 557 558 if (ctx->num_readers > 0) 559 // LCOV_EXCL_START 560 return CeedError(ctx->ceed, 1, 561 "Cannot grant CeedQFunctionContext data access, a " 562 "process has read access"); 563 // LCOV_EXCL_STOP 564 565 bool has_valid_data = true; 566 ierr = CeedQFunctionContextHasValidData(ctx, &has_valid_data); CeedChk(ierr); 567 if (!has_valid_data) 568 // LCOV_EXCL_START 569 return CeedError(ctx->ceed, CEED_ERROR_BACKEND, 570 "CeedQFunctionContext has no valid data to get, must set data"); 571 // LCOV_EXCL_STOP 572 573 ierr = ctx->GetData(ctx, mem_type, data); CeedChk(ierr); 574 ctx->state++; 575 return CEED_ERROR_SUCCESS; 576 } 577 578 /** 579 @brief Get read only access to a CeedQFunctionContext via the specified memory type. 580 Restore access with @ref CeedQFunctionContextRestoreData(). 581 582 @param ctx CeedQFunctionContext to access 583 @param mem_type Memory type on which to access the data. If the backend 584 uses a different memory type, this will perform a copy. 585 @param[out] data Data on memory type mem_type 586 587 @note The CeedQFunctionContextGetDataRead() and @ref CeedQFunctionContextRestoreDataRead() 588 functions provide access to array pointers in the desired memory space. Pairing 589 get/restore allows the Context to track access. 590 591 @return An error code: 0 - success, otherwise - failure 592 593 @ref User 594 **/ 595 int CeedQFunctionContextGetDataRead(CeedQFunctionContext ctx, 596 CeedMemType mem_type, 597 void *data) { 598 int ierr; 599 600 if (!ctx->GetDataRead) 601 // LCOV_EXCL_START 602 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 603 "Backend does not support GetDataRead"); 604 // LCOV_EXCL_STOP 605 606 if (ctx->state % 2 == 1) 607 // LCOV_EXCL_START 608 return CeedError(ctx->ceed, 1, 609 "Cannot grant CeedQFunctionContext data access, the " 610 "access lock is already in use"); 611 // LCOV_EXCL_STOP 612 613 bool has_valid_data = true; 614 ierr = CeedQFunctionContextHasValidData(ctx, &has_valid_data); CeedChk(ierr); 615 if (!has_valid_data) 616 // LCOV_EXCL_START 617 return CeedError(ctx->ceed, CEED_ERROR_BACKEND, 618 "CeedQFunctionContext has no valid data to get, must set data"); 619 // LCOV_EXCL_STOP 620 621 ierr = ctx->GetDataRead(ctx, mem_type, data); CeedChk(ierr); 622 ctx->num_readers++; 623 return CEED_ERROR_SUCCESS; 624 } 625 626 /** 627 @brief Restore data obtained using @ref CeedQFunctionContextGetData() 628 629 @param ctx CeedQFunctionContext to restore 630 @param data Data to restore 631 632 @return An error code: 0 - success, otherwise - failure 633 634 @ref User 635 **/ 636 int CeedQFunctionContextRestoreData(CeedQFunctionContext ctx, void *data) { 637 int ierr; 638 639 if (ctx->state % 2 != 1) 640 // LCOV_EXCL_START 641 return CeedError(ctx->ceed, 1, 642 "Cannot restore CeedQFunctionContext array access, " 643 "access was not granted"); 644 // LCOV_EXCL_STOP 645 646 if (ctx->RestoreData) { 647 ierr = ctx->RestoreData(ctx); CeedChk(ierr); 648 } 649 *(void **)data = NULL; 650 ctx->state++; 651 return CEED_ERROR_SUCCESS; 652 } 653 654 /** 655 @brief Restore data obtained using @ref CeedQFunctionContextGetDataRead() 656 657 @param ctx CeedQFunctionContext to restore 658 @param data Data to restore 659 660 @return An error code: 0 - success, otherwise - failure 661 662 @ref User 663 **/ 664 int CeedQFunctionContextRestoreDataRead(CeedQFunctionContext ctx, void *data) { 665 int ierr; 666 667 if (ctx->num_readers == 0) 668 // LCOV_EXCL_START 669 return CeedError(ctx->ceed, 1, 670 "Cannot restore CeedQFunctionContext array access, " 671 "access was not granted"); 672 // LCOV_EXCL_STOP 673 674 if (ctx->RestoreDataRead) { 675 ierr = ctx->RestoreData(ctx); CeedChk(ierr); 676 } 677 *(void **)data = NULL; 678 ctx->num_readers--; 679 return CEED_ERROR_SUCCESS; 680 } 681 682 /** 683 @brief Register QFunctionContext a field holding a double precision value 684 685 @param ctx CeedQFunctionContext 686 @param field_name Name of field to register 687 @param field_offset Offset of field to register 688 @param num_values Number of values to register, must be contiguous in memory 689 @param field_description Description of field, or NULL for none 690 691 @return An error code: 0 - success, otherwise - failure 692 693 @ref User 694 **/ 695 int CeedQFunctionContextRegisterDouble(CeedQFunctionContext ctx, 696 const char *field_name, size_t field_offset, 697 size_t num_values, 698 const char *field_description) { 699 return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, 700 field_description, CEED_CONTEXT_FIELD_DOUBLE, sizeof(double), num_values); 701 } 702 703 /** 704 @brief Register QFunctionContext a field holding a int32 value 705 706 @param ctx CeedQFunctionContext 707 @param field_name Name of field to register 708 @param field_offset Offset of field to register 709 @param num_values Number of values to register, must be contiguous in memory 710 @param field_description Description of field, or NULL for none 711 712 @return An error code: 0 - success, otherwise - failure 713 714 @ref User 715 **/ 716 int CeedQFunctionContextRegisterInt32(CeedQFunctionContext ctx, 717 const char *field_name, size_t field_offset, 718 size_t num_values, 719 const char *field_description) { 720 return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, 721 field_description, CEED_CONTEXT_FIELD_INT32, sizeof(int), num_values); 722 } 723 724 /** 725 @brief Get labels for all registered QFunctionContext fields 726 727 @param ctx CeedQFunctionContext 728 @param[out] field_labels Variable to hold array of field labels 729 @param[out] num_fields Length of field descriptions array 730 731 @return An error code: 0 - success, otherwise - failure 732 733 @ref User 734 **/ 735 int CeedQFunctionContextGetAllFieldLabels(CeedQFunctionContext ctx, 736 const CeedContextFieldLabel **field_labels, CeedInt *num_fields) { 737 *field_labels = ctx->field_labels; 738 *num_fields = ctx->num_fields; 739 return CEED_ERROR_SUCCESS; 740 } 741 742 /** 743 @brief Get the descriptive information about a CeedContextFieldLabel 744 745 @param[in] label CeedContextFieldLabel 746 @param[out] field_name Name of labeled field 747 @param[out] field_description Description of field, or NULL for none 748 @param[out] num_values Number of values registered 749 @param[out] field_type CeedContextFieldType 750 751 @return An error code: 0 - success, otherwise - failure 752 753 @ref User 754 **/ 755 int CeedContextFieldLabelGetDescription(CeedContextFieldLabel label, 756 const char **field_name, 757 const char **field_description, 758 size_t *num_values, 759 CeedContextFieldType *field_type) { 760 if (field_name) *field_name = label->name; 761 if (field_description) *field_description = label->description; 762 if (num_values) *num_values = label->num_values; 763 if (field_type) *field_type = label->type; 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