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 Backend 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 Backend 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 Backend 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 Backend 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 Get additional destroy routine for CeedQFunctionContext user data 348 349 @param[in] ctx CeedQFunctionContext to get user destroy function 350 @param[out] f_mem_type Memory type to use when passing data into `f` 351 @param[out] f Additional routine to use to destroy user data 352 353 @return An error code: 0 - success, otherwise - failure 354 355 @ref Backend 356 **/ 357 int CeedQFunctionContextGetDataDestroy(CeedQFunctionContext ctx, 358 CeedMemType *f_mem_type, CeedQFunctionContextDataDestroyUser *f) { 359 if (f_mem_type) *f_mem_type = ctx->data_destroy_mem_type; 360 if (f) *f = ctx->data_destroy_function; 361 return CEED_ERROR_SUCCESS; 362 } 363 364 /** 365 @brief Destroy user data held by CeedQFunctionContext, using function set by 366 CeedQFunctionContextSetDataDestroy, if applicable 367 368 @param[in,out] ctx CeedQFunctionContext to destroy user data 369 370 @return An error code: 0 - success, otherwise - failure 371 372 @ref Backend 373 **/ 374 int CeedQFunctionContextDestroyData(CeedQFunctionContext ctx) { 375 int ierr; 376 377 if (ctx->DataDestroy) { 378 ierr = ctx->DataDestroy(ctx); CeedChk(ierr); 379 } else { 380 CeedQFunctionContextDataDestroyUser data_destroy_function; 381 CeedMemType data_destroy_mem_type; 382 383 ierr = CeedQFunctionContextGetDataDestroy(ctx, &data_destroy_mem_type, 384 &data_destroy_function); CeedChk(ierr); 385 if (data_destroy_function) { 386 void *data; 387 388 ierr = CeedQFunctionContextGetData(ctx, data_destroy_mem_type, &data); 389 CeedChk(ierr); 390 ierr = data_destroy_function(data); CeedChk(ierr); 391 ierr = CeedQFunctionContextRestoreData(ctx, &data); CeedChk(ierr); 392 } 393 } 394 395 return CEED_ERROR_SUCCESS; 396 } 397 398 /** 399 @brief Increment the reference counter for a CeedQFunctionContext 400 401 @param ctx CeedQFunctionContext to increment the reference counter 402 403 @return An error code: 0 - success, otherwise - failure 404 405 @ref Backend 406 **/ 407 int CeedQFunctionContextReference(CeedQFunctionContext ctx) { 408 ctx->ref_count++; 409 return CEED_ERROR_SUCCESS; 410 } 411 412 /// @} 413 414 /// ---------------------------------------------------------------------------- 415 /// CeedQFunctionContext Public API 416 /// ---------------------------------------------------------------------------- 417 /// @addtogroup CeedQFunctionUser 418 /// @{ 419 420 /** 421 @brief Create a CeedQFunctionContext for storing CeedQFunction user context data 422 423 @param ceed A Ceed object where the CeedQFunctionContext will be created 424 @param[out] ctx Address of the variable where the newly created 425 CeedQFunctionContext will be stored 426 427 @return An error code: 0 - success, otherwise - failure 428 429 @ref User 430 **/ 431 int CeedQFunctionContextCreate(Ceed ceed, CeedQFunctionContext *ctx) { 432 int ierr; 433 434 if (!ceed->QFunctionContextCreate) { 435 Ceed delegate; 436 ierr = CeedGetObjectDelegate(ceed, &delegate, "Context"); CeedChk(ierr); 437 438 if (!delegate) 439 // LCOV_EXCL_START 440 return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 441 "Backend does not support ContextCreate"); 442 // LCOV_EXCL_STOP 443 444 ierr = CeedQFunctionContextCreate(delegate, ctx); CeedChk(ierr); 445 return CEED_ERROR_SUCCESS; 446 } 447 448 ierr = CeedCalloc(1, ctx); CeedChk(ierr); 449 (*ctx)->ceed = ceed; 450 ierr = CeedReference(ceed); CeedChk(ierr); 451 (*ctx)->ref_count = 1; 452 ierr = ceed->QFunctionContextCreate(*ctx); CeedChk(ierr); 453 return CEED_ERROR_SUCCESS; 454 } 455 456 /** 457 @brief Copy the pointer to a CeedQFunctionContext. Both pointers should 458 be destroyed with `CeedQFunctionContextDestroy()`; 459 Note: If `*ctx_copy` is non-NULL, then it is assumed that 460 `*ctx_copy` is a pointer to a CeedQFunctionContext. This 461 CeedQFunctionContext will be destroyed if `*ctx_copy` is the 462 only reference to this CeedQFunctionContext. 463 464 @param ctx CeedQFunctionContext to copy reference to 465 @param[out] ctx_copy Variable to store copied reference 466 467 @return An error code: 0 - success, otherwise - failure 468 469 @ref User 470 **/ 471 int CeedQFunctionContextReferenceCopy(CeedQFunctionContext ctx, 472 CeedQFunctionContext *ctx_copy) { 473 int ierr; 474 475 ierr = CeedQFunctionContextReference(ctx); CeedChk(ierr); 476 ierr = CeedQFunctionContextDestroy(ctx_copy); CeedChk(ierr); 477 *ctx_copy = ctx; 478 return CEED_ERROR_SUCCESS; 479 } 480 481 /** 482 @brief Set the data used by a CeedQFunctionContext, freeing any previously allocated 483 data if applicable. The backend may copy values to a different 484 memtype, such as during @ref CeedQFunctionApply(). 485 See also @ref CeedQFunctionContextTakeData(). 486 487 @param ctx CeedQFunctionContext 488 @param mem_type Memory type of the data being passed 489 @param copy_mode Copy mode for the data 490 @param size Size of data, in bytes 491 @param data Data to be used 492 493 @return An error code: 0 - success, otherwise - failure 494 495 @ref User 496 **/ 497 int CeedQFunctionContextSetData(CeedQFunctionContext ctx, CeedMemType mem_type, 498 CeedCopyMode copy_mode, 499 size_t size, void *data) { 500 int ierr; 501 502 if (!ctx->SetData) 503 // LCOV_EXCL_START 504 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 505 "Backend does not support ContextSetData"); 506 // LCOV_EXCL_STOP 507 508 if (ctx->state % 2 == 1) 509 // LCOV_EXCL_START 510 return CeedError(ctx->ceed, 1, 511 "Cannot grant CeedQFunctionContext data access, the " 512 "access lock is already in use"); 513 // LCOV_EXCL_STOP 514 515 ierr = CeedQFunctionContextDestroyData(ctx); CeedChk(ierr); 516 ctx->ctx_size = size; 517 ierr = ctx->SetData(ctx, mem_type, copy_mode, data); CeedChk(ierr); 518 ctx->state += 2; 519 return CEED_ERROR_SUCCESS; 520 } 521 522 /** 523 @brief Take ownership of the data in a CeedQFunctionContext via the specified memory type. 524 The caller is responsible for managing and freeing the memory. 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 @return An error code: 0 - success, otherwise - failure 532 533 @ref User 534 **/ 535 int CeedQFunctionContextTakeData(CeedQFunctionContext ctx, CeedMemType mem_type, 536 void *data) { 537 int ierr; 538 539 bool has_valid_data = true; 540 ierr = CeedQFunctionContextHasValidData(ctx, &has_valid_data); CeedChk(ierr); 541 if (!has_valid_data) 542 // LCOV_EXCL_START 543 return CeedError(ctx->ceed, CEED_ERROR_BACKEND, 544 "CeedQFunctionContext has no valid data to take, must set data"); 545 // LCOV_EXCL_STOP 546 547 if (!ctx->TakeData) 548 // LCOV_EXCL_START 549 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 550 "Backend does not support TakeData"); 551 // LCOV_EXCL_STOP 552 553 if (ctx->state % 2 == 1) 554 // LCOV_EXCL_START 555 return CeedError(ctx->ceed, 1, 556 "Cannot grant CeedQFunctionContext data access, the " 557 "access lock is already in use"); 558 // LCOV_EXCL_STOP 559 560 bool has_borrowed_data_of_type = true; 561 ierr = CeedQFunctionContextHasBorrowedDataOfType(ctx, mem_type, 562 &has_borrowed_data_of_type); CeedChk(ierr); 563 if (!has_borrowed_data_of_type) 564 // LCOV_EXCL_START 565 return CeedError(ctx->ceed, CEED_ERROR_BACKEND, 566 "CeedQFunctionContext has no borowed %s data, " 567 "must set data with CeedQFunctionContextSetData", 568 CeedMemTypes[mem_type]); 569 // LCOV_EXCL_STOP 570 571 void *temp_data = NULL; 572 ierr = ctx->TakeData(ctx, mem_type, &temp_data); CeedChk(ierr); 573 if (data) (*(void **)data) = temp_data; 574 return CEED_ERROR_SUCCESS; 575 } 576 577 /** 578 @brief Get read/write access to a CeedQFunctionContext via the specified memory type. 579 Restore access with @ref CeedQFunctionContextRestoreData(). 580 581 @param ctx CeedQFunctionContext to access 582 @param mem_type Memory type on which to access the data. If the backend 583 uses a different memory type, this will perform a copy. 584 @param[out] data Data on memory type mem_type 585 586 @note The CeedQFunctionContextGetData() and @ref CeedQFunctionContextRestoreData() functions 587 provide access to array pointers in the desired memory space. Pairing 588 get/restore allows the Context to track access. 589 590 @return An error code: 0 - success, otherwise - failure 591 592 @ref User 593 **/ 594 int CeedQFunctionContextGetData(CeedQFunctionContext ctx, CeedMemType mem_type, 595 void *data) { 596 int ierr; 597 598 if (!ctx->GetData) 599 // LCOV_EXCL_START 600 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 601 "Backend does not support GetData"); 602 // LCOV_EXCL_STOP 603 604 if (ctx->state % 2 == 1) 605 // LCOV_EXCL_START 606 return CeedError(ctx->ceed, 1, 607 "Cannot grant CeedQFunctionContext data access, the " 608 "access lock is already in use"); 609 // LCOV_EXCL_STOP 610 611 if (ctx->num_readers > 0) 612 // LCOV_EXCL_START 613 return CeedError(ctx->ceed, 1, 614 "Cannot grant CeedQFunctionContext data access, a " 615 "process has read access"); 616 // LCOV_EXCL_STOP 617 618 bool has_valid_data = true; 619 ierr = CeedQFunctionContextHasValidData(ctx, &has_valid_data); CeedChk(ierr); 620 if (!has_valid_data) 621 // LCOV_EXCL_START 622 return CeedError(ctx->ceed, CEED_ERROR_BACKEND, 623 "CeedQFunctionContext has no valid data to get, must set data"); 624 // LCOV_EXCL_STOP 625 626 ierr = ctx->GetData(ctx, mem_type, data); CeedChk(ierr); 627 ctx->state++; 628 return CEED_ERROR_SUCCESS; 629 } 630 631 /** 632 @brief Get read only access to a CeedQFunctionContext via the specified memory type. 633 Restore access with @ref CeedQFunctionContextRestoreData(). 634 635 @param ctx CeedQFunctionContext to access 636 @param mem_type Memory type on which to access the data. If the backend 637 uses a different memory type, this will perform a copy. 638 @param[out] data Data on memory type mem_type 639 640 @note The CeedQFunctionContextGetDataRead() and @ref CeedQFunctionContextRestoreDataRead() 641 functions provide access to array pointers in the desired memory space. Pairing 642 get/restore allows the Context to track access. 643 644 @return An error code: 0 - success, otherwise - failure 645 646 @ref User 647 **/ 648 int CeedQFunctionContextGetDataRead(CeedQFunctionContext ctx, 649 CeedMemType mem_type, 650 void *data) { 651 int ierr; 652 653 if (!ctx->GetDataRead) 654 // LCOV_EXCL_START 655 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 656 "Backend does not support GetDataRead"); 657 // LCOV_EXCL_STOP 658 659 if (ctx->state % 2 == 1) 660 // LCOV_EXCL_START 661 return CeedError(ctx->ceed, 1, 662 "Cannot grant CeedQFunctionContext data access, the " 663 "access lock is already in use"); 664 // LCOV_EXCL_STOP 665 666 bool has_valid_data = true; 667 ierr = CeedQFunctionContextHasValidData(ctx, &has_valid_data); CeedChk(ierr); 668 if (!has_valid_data) 669 // LCOV_EXCL_START 670 return CeedError(ctx->ceed, CEED_ERROR_BACKEND, 671 "CeedQFunctionContext has no valid data to get, must set data"); 672 // LCOV_EXCL_STOP 673 674 ierr = ctx->GetDataRead(ctx, mem_type, data); CeedChk(ierr); 675 ctx->num_readers++; 676 return CEED_ERROR_SUCCESS; 677 } 678 679 /** 680 @brief Restore data obtained using @ref CeedQFunctionContextGetData() 681 682 @param ctx CeedQFunctionContext to restore 683 @param data Data to restore 684 685 @return An error code: 0 - success, otherwise - failure 686 687 @ref User 688 **/ 689 int CeedQFunctionContextRestoreData(CeedQFunctionContext ctx, void *data) { 690 int ierr; 691 692 if (ctx->state % 2 != 1) 693 // LCOV_EXCL_START 694 return CeedError(ctx->ceed, 1, 695 "Cannot restore CeedQFunctionContext array access, " 696 "access was not granted"); 697 // LCOV_EXCL_STOP 698 699 if (ctx->RestoreData) { 700 ierr = ctx->RestoreData(ctx); CeedChk(ierr); 701 } 702 *(void **)data = NULL; 703 ctx->state++; 704 return CEED_ERROR_SUCCESS; 705 } 706 707 /** 708 @brief Restore data obtained using @ref CeedQFunctionContextGetDataRead() 709 710 @param ctx CeedQFunctionContext to restore 711 @param data Data to restore 712 713 @return An error code: 0 - success, otherwise - failure 714 715 @ref User 716 **/ 717 int CeedQFunctionContextRestoreDataRead(CeedQFunctionContext ctx, void *data) { 718 int ierr; 719 720 if (ctx->num_readers == 0) 721 // LCOV_EXCL_START 722 return CeedError(ctx->ceed, 1, 723 "Cannot restore CeedQFunctionContext array access, " 724 "access was not granted"); 725 // LCOV_EXCL_STOP 726 727 if (ctx->RestoreDataRead) { 728 ierr = ctx->RestoreData(ctx); CeedChk(ierr); 729 } 730 *(void **)data = NULL; 731 ctx->num_readers--; 732 return CEED_ERROR_SUCCESS; 733 } 734 735 /** 736 @brief Register QFunctionContext a field holding a double precision value 737 738 @param ctx CeedQFunctionContext 739 @param field_name Name of field to register 740 @param field_offset Offset of field to register 741 @param num_values Number of values to register, must be contiguous in memory 742 @param field_description Description of field, or NULL for none 743 744 @return An error code: 0 - success, otherwise - failure 745 746 @ref User 747 **/ 748 int CeedQFunctionContextRegisterDouble(CeedQFunctionContext ctx, 749 const char *field_name, size_t field_offset, 750 size_t num_values, 751 const char *field_description) { 752 return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, 753 field_description, CEED_CONTEXT_FIELD_DOUBLE, sizeof(double), num_values); 754 } 755 756 /** 757 @brief Register QFunctionContext a field holding a int32 value 758 759 @param ctx CeedQFunctionContext 760 @param field_name Name of field to register 761 @param field_offset Offset of field to register 762 @param num_values Number of values to register, must be contiguous in memory 763 @param field_description Description of field, or NULL for none 764 765 @return An error code: 0 - success, otherwise - failure 766 767 @ref User 768 **/ 769 int CeedQFunctionContextRegisterInt32(CeedQFunctionContext ctx, 770 const char *field_name, size_t field_offset, 771 size_t num_values, 772 const char *field_description) { 773 return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, 774 field_description, CEED_CONTEXT_FIELD_INT32, sizeof(int), num_values); 775 } 776 777 /** 778 @brief Get labels for all registered QFunctionContext fields 779 780 @param ctx CeedQFunctionContext 781 @param[out] field_labels Variable to hold array of field labels 782 @param[out] num_fields Length of field descriptions array 783 784 @return An error code: 0 - success, otherwise - failure 785 786 @ref User 787 **/ 788 int CeedQFunctionContextGetAllFieldLabels(CeedQFunctionContext ctx, 789 const CeedContextFieldLabel **field_labels, CeedInt *num_fields) { 790 *field_labels = ctx->field_labels; 791 *num_fields = ctx->num_fields; 792 return CEED_ERROR_SUCCESS; 793 } 794 795 /** 796 @brief Get the descriptive information about a CeedContextFieldLabel 797 798 @param[in] label CeedContextFieldLabel 799 @param[out] field_name Name of labeled field 800 @param[out] field_description Description of field, or NULL for none 801 @param[out] num_values Number of values registered 802 @param[out] field_type CeedContextFieldType 803 804 @return An error code: 0 - success, otherwise - failure 805 806 @ref User 807 **/ 808 int CeedContextFieldLabelGetDescription(CeedContextFieldLabel label, 809 const char **field_name, 810 const char **field_description, 811 size_t *num_values, 812 CeedContextFieldType *field_type) { 813 if (field_name) *field_name = label->name; 814 if (field_description) *field_description = label->description; 815 if (num_values) *num_values = label->num_values; 816 if (field_type) *field_type = label->type; 817 return CEED_ERROR_SUCCESS; 818 } 819 820 /** 821 @brief Get data size for a Context 822 823 @param ctx CeedQFunctionContext 824 @param[out] ctx_size Variable to store size of context data values 825 826 @return An error code: 0 - success, otherwise - failure 827 828 @ref User 829 **/ 830 int CeedQFunctionContextGetContextSize(CeedQFunctionContext ctx, 831 size_t *ctx_size) { 832 *ctx_size = ctx->ctx_size; 833 return CEED_ERROR_SUCCESS; 834 } 835 836 837 /** 838 @brief View a CeedQFunctionContext 839 840 @param[in] ctx CeedQFunctionContext to view 841 @param[in] stream Filestream to write to 842 843 @return An error code: 0 - success, otherwise - failure 844 845 @ref User 846 **/ 847 int CeedQFunctionContextView(CeedQFunctionContext ctx, FILE *stream) { 848 fprintf(stream, "CeedQFunctionContext\n"); 849 fprintf(stream, " Context Data Size: %ld\n", ctx->ctx_size); 850 for (CeedInt i = 0; i < ctx->num_fields; i++) { 851 // LCOV_EXCL_START 852 fprintf(stream, " Labeled %s field: %s\n", 853 CeedContextFieldTypes[ctx->field_labels[i]->type], 854 ctx->field_labels[i]->name); 855 // LCOV_EXCL_STOP 856 } 857 return CEED_ERROR_SUCCESS; 858 } 859 860 /** 861 @brief Set additional destroy routine for CeedQFunctionContext user data 862 863 @param[in] ctx CeedQFunctionContext to set user destroy function 864 @param[in] f_mem_type Memory type to use when passing data into `f` 865 @param[in] f Additional routine to use to destroy user data 866 867 @return An error code: 0 - success, otherwise - failure 868 869 @ref User 870 **/ 871 int CeedQFunctionContextSetDataDestroy(CeedQFunctionContext ctx, 872 CeedMemType f_mem_type, CeedQFunctionContextDataDestroyUser f) { 873 if (!f) 874 // LCOV_EXCL_START 875 return CeedError(ctx->ceed, 1, 876 "Must provide valid callback function for destroying user data"); 877 // LCOV_EXCL_STOP 878 ctx->data_destroy_mem_type = f_mem_type; 879 ctx->data_destroy_function = f; 880 return CEED_ERROR_SUCCESS; 881 } 882 883 /** 884 @brief Destroy a CeedQFunctionContext 885 886 @param ctx CeedQFunctionContext to destroy 887 888 @return An error code: 0 - success, otherwise - failure 889 890 @ref User 891 **/ 892 int CeedQFunctionContextDestroy(CeedQFunctionContext *ctx) { 893 int ierr; 894 895 if (!*ctx || --(*ctx)->ref_count > 0) 896 return CEED_ERROR_SUCCESS; 897 898 if ((*ctx) && ((*ctx)->state % 2) == 1) 899 // LCOV_EXCL_START 900 return CeedError((*ctx)->ceed, 1, 901 "Cannot destroy CeedQFunctionContext, the access " 902 "lock is in use"); 903 // LCOV_EXCL_STOP 904 905 ierr = CeedQFunctionContextDestroyData(*ctx); CeedChk(ierr); 906 if ((*ctx)->Destroy) { 907 ierr = (*ctx)->Destroy(*ctx); CeedChk(ierr); 908 } 909 for (CeedInt i=0; i<(*ctx)->num_fields; i++) { 910 ierr = CeedFree(&(*ctx)->field_labels[i]->name); CeedChk(ierr); 911 ierr = CeedFree(&(*ctx)->field_labels[i]->description); CeedChk(ierr); 912 ierr = CeedFree(&(*ctx)->field_labels[i]); CeedChk(ierr); 913 } 914 ierr = CeedFree(&(*ctx)->field_labels); CeedChk(ierr); 915 ierr = CeedDestroy(&(*ctx)->ceed); CeedChk(ierr); 916 ierr = CeedFree(ctx); CeedChk(ierr); 917 918 return CEED_ERROR_SUCCESS; 919 } 920 921 /// @} 922