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 @brief Destroy user data held by CeedQFunctionContext, using function set by 105 CeedQFunctionContextSetDataDestroy, if applicable 106 107 @param[in,out] ctx CeedQFunctionContext to destroy user data 108 109 @return An error code: 0 - success, otherwise - failure 110 111 @ref Developer 112 **/ 113 static int CeedQFunctionContextDestroyData(CeedQFunctionContext ctx) { 114 int ierr; 115 116 if (ctx->DataDestroy) { 117 ierr = ctx->DataDestroy(ctx); CeedChk(ierr); 118 } else { 119 CeedQFunctionContextDataDestroyUser data_destroy_function; 120 CeedMemType data_destroy_mem_type; 121 122 ierr = CeedQFunctionContextGetDataDestroy(ctx, &data_destroy_mem_type, 123 &data_destroy_function); CeedChk(ierr); 124 if (data_destroy_function) { 125 void *data; 126 127 ierr = CeedQFunctionContextGetData(ctx, data_destroy_mem_type, &data); 128 CeedChk(ierr); 129 ierr = data_destroy_function(data); CeedChk(ierr); 130 ierr = CeedQFunctionContextRestoreData(ctx, &data); CeedChk(ierr); 131 } 132 } 133 134 return CEED_ERROR_SUCCESS; 135 } 136 137 /// @} 138 139 /// ---------------------------------------------------------------------------- 140 /// CeedQFunctionContext Backend API 141 /// ---------------------------------------------------------------------------- 142 /// @addtogroup CeedQFunctionBackend 143 /// @{ 144 145 /** 146 @brief Get the Ceed associated with a CeedQFunctionContext 147 148 @param ctx CeedQFunctionContext 149 @param[out] ceed Variable to store Ceed 150 151 @return An error code: 0 - success, otherwise - failure 152 153 @ref Backend 154 **/ 155 int CeedQFunctionContextGetCeed(CeedQFunctionContext ctx, Ceed *ceed) { 156 *ceed = ctx->ceed; 157 return CEED_ERROR_SUCCESS; 158 } 159 160 /** 161 @brief Check for valid data in a CeedQFunctionContext 162 163 @param ctx CeedQFunctionContext to check validity 164 @param[out] has_valid_data Variable to store validity 165 166 @return An error code: 0 - success, otherwise - failure 167 168 @ref Backend 169 **/ 170 int CeedQFunctionContextHasValidData(CeedQFunctionContext ctx, 171 bool *has_valid_data) { 172 int ierr; 173 174 if (!ctx->HasValidData) 175 // LCOV_EXCL_START 176 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 177 "Backend does not support HasValidData"); 178 // LCOV_EXCL_STOP 179 180 ierr = ctx->HasValidData(ctx, has_valid_data); CeedChk(ierr); 181 182 return CEED_ERROR_SUCCESS; 183 } 184 185 /** 186 @brief Check for borrowed data of a specific CeedMemType in a 187 CeedQFunctionContext 188 189 @param ctx CeedQFunctionContext to check 190 @param mem_type Memory type to check 191 @param[out] has_borrowed_data_of_type Variable to store result 192 193 @return An error code: 0 - success, otherwise - failure 194 195 @ref Backend 196 **/ 197 int CeedQFunctionContextHasBorrowedDataOfType(CeedQFunctionContext ctx, 198 CeedMemType mem_type, bool *has_borrowed_data_of_type) { 199 int ierr; 200 201 if (!ctx->HasBorrowedDataOfType) 202 // LCOV_EXCL_START 203 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 204 "Backend does not support HasBorrowedDataOfType"); 205 // LCOV_EXCL_STOP 206 207 ierr = ctx->HasBorrowedDataOfType(ctx, mem_type, has_borrowed_data_of_type); 208 CeedChk(ierr); 209 210 return CEED_ERROR_SUCCESS; 211 } 212 213 /** 214 @brief Get the state of a CeedQFunctionContext 215 216 @param ctx CeedQFunctionContext to retrieve state 217 @param[out] state Variable to store state 218 219 @return An error code: 0 - success, otherwise - failure 220 221 @ref Backend 222 **/ 223 int CeedQFunctionContextGetState(CeedQFunctionContext ctx, uint64_t *state) { 224 *state = ctx->state; 225 return CEED_ERROR_SUCCESS; 226 } 227 228 /** 229 @brief Get backend data of a CeedQFunctionContext 230 231 @param ctx CeedQFunctionContext 232 @param[out] data Variable to store data 233 234 @return An error code: 0 - success, otherwise - failure 235 236 @ref Backend 237 **/ 238 int CeedQFunctionContextGetBackendData(CeedQFunctionContext ctx, void *data) { 239 *(void **)data = ctx->data; 240 return CEED_ERROR_SUCCESS; 241 } 242 243 /** 244 @brief Set backend data of a CeedQFunctionContext 245 246 @param[out] ctx CeedQFunctionContext 247 @param data Data to set 248 249 @return An error code: 0 - success, otherwise - failure 250 251 @ref Backend 252 **/ 253 int CeedQFunctionContextSetBackendData(CeedQFunctionContext ctx, void *data) { 254 ctx->data = data; 255 return CEED_ERROR_SUCCESS; 256 } 257 258 /** 259 @brief Get label for a registered QFunctionContext field, or `NULL` if no 260 field has been registered with this `field_name` 261 262 @param[in] ctx CeedQFunctionContext 263 @param[in] field_name Name of field to retrieve label 264 @param[out] field_label Variable to field label 265 266 @return An error code: 0 - success, otherwise - failure 267 268 @ref Backend 269 **/ 270 int CeedQFunctionContextGetFieldLabel(CeedQFunctionContext ctx, 271 const char *field_name, 272 CeedContextFieldLabel *field_label) { 273 int ierr; 274 275 CeedInt field_index; 276 ierr = CeedQFunctionContextGetFieldIndex(ctx, field_name, &field_index); 277 CeedChk(ierr); 278 279 if (field_index != -1) { 280 *field_label = ctx->field_labels[field_index]; 281 } else { 282 *field_label = NULL; 283 } 284 285 return CEED_ERROR_SUCCESS; 286 } 287 288 /** 289 @brief Set QFunctionContext field 290 291 @param ctx CeedQFunctionContext 292 @param field_label Label of field to set 293 @param field_type Type of field to set 294 @param value Value to set 295 296 @return An error code: 0 - success, otherwise - failure 297 298 @ref Backend 299 **/ 300 int CeedQFunctionContextSetGeneric(CeedQFunctionContext ctx, 301 CeedContextFieldLabel field_label, 302 CeedContextFieldType field_type, 303 void *value) { 304 int ierr; 305 306 // Check field type 307 if (field_label->type != field_type) 308 // LCOV_EXCL_START 309 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 310 "QFunctionContext field with name \"%s\" registered as %s, " 311 "not registered as %s", field_label->name, 312 CeedContextFieldTypes[field_label->type], 313 CeedContextFieldTypes[field_type]); 314 // LCOV_EXCL_STOP 315 316 char *data; 317 ierr = CeedQFunctionContextGetData(ctx, CEED_MEM_HOST, &data); CeedChk(ierr); 318 memcpy(&data[field_label->offset], value, field_label->size); 319 ierr = CeedQFunctionContextRestoreData(ctx, &data); CeedChk(ierr); 320 321 return CEED_ERROR_SUCCESS; 322 } 323 324 /** 325 @brief Set QFunctionContext field holding a double precision value 326 327 @param ctx CeedQFunctionContext 328 @param field_label Label for field to register 329 @param values Values to set 330 331 @return An error code: 0 - success, otherwise - failure 332 333 @ref Backend 334 **/ 335 int CeedQFunctionContextSetDouble(CeedQFunctionContext ctx, 336 CeedContextFieldLabel field_label, double *values) { 337 int ierr; 338 339 if (!field_label) 340 // LCOV_EXCL_START 341 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 342 "Invalid field label"); 343 // LCOV_EXCL_STOP 344 345 ierr = CeedQFunctionContextSetGeneric(ctx, field_label, 346 CEED_CONTEXT_FIELD_DOUBLE, 347 values); CeedChk(ierr); 348 349 return CEED_ERROR_SUCCESS; 350 } 351 352 /** 353 @brief Set QFunctionContext field holding an int32 value 354 355 @param ctx CeedQFunctionContext 356 @param field_label Label for field to register 357 @param values Values to set 358 359 @return An error code: 0 - success, otherwise - failure 360 361 @ref Backend 362 **/ 363 int CeedQFunctionContextSetInt32(CeedQFunctionContext ctx, 364 CeedContextFieldLabel field_label, int *values) { 365 int ierr; 366 367 if (!field_label) 368 // LCOV_EXCL_START 369 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 370 "Invalid field label"); 371 // LCOV_EXCL_STOP 372 373 ierr = CeedQFunctionContextSetGeneric(ctx, field_label, 374 CEED_CONTEXT_FIELD_INT32, 375 values); CeedChk(ierr); 376 377 return CEED_ERROR_SUCCESS; 378 } 379 380 /** 381 @brief Get additional destroy routine for CeedQFunctionContext user data 382 383 @param[in] ctx CeedQFunctionContext to get user destroy function 384 @param[out] f_mem_type Memory type to use when passing data into `f` 385 @param[out] f Additional routine to use to destroy user data 386 387 @return An error code: 0 - success, otherwise - failure 388 389 @ref Backend 390 **/ 391 int CeedQFunctionContextGetDataDestroy(CeedQFunctionContext ctx, 392 CeedMemType *f_mem_type, CeedQFunctionContextDataDestroyUser *f) { 393 if (f_mem_type) *f_mem_type = ctx->data_destroy_mem_type; 394 if (f) *f = ctx->data_destroy_function; 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 ctx->num_readers--; 728 if (ctx->num_readers == 0 && ctx->RestoreDataRead) { 729 ierr = ctx->RestoreData(ctx); CeedChk(ierr); 730 } 731 *(void **)data = NULL; 732 733 return CEED_ERROR_SUCCESS; 734 } 735 736 /** 737 @brief Register QFunctionContext a field holding a double precision value 738 739 @param ctx CeedQFunctionContext 740 @param field_name Name of field to register 741 @param field_offset Offset of field to register 742 @param num_values Number of values to register, must be contiguous in memory 743 @param field_description Description of field, or NULL for none 744 745 @return An error code: 0 - success, otherwise - failure 746 747 @ref User 748 **/ 749 int CeedQFunctionContextRegisterDouble(CeedQFunctionContext ctx, 750 const char *field_name, size_t field_offset, 751 size_t num_values, 752 const char *field_description) { 753 return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, 754 field_description, CEED_CONTEXT_FIELD_DOUBLE, sizeof(double), num_values); 755 } 756 757 /** 758 @brief Register QFunctionContext a field holding a int32 value 759 760 @param ctx CeedQFunctionContext 761 @param field_name Name of field to register 762 @param field_offset Offset of field to register 763 @param num_values Number of values to register, must be contiguous in memory 764 @param field_description Description of field, or NULL for none 765 766 @return An error code: 0 - success, otherwise - failure 767 768 @ref User 769 **/ 770 int CeedQFunctionContextRegisterInt32(CeedQFunctionContext ctx, 771 const char *field_name, size_t field_offset, 772 size_t num_values, 773 const char *field_description) { 774 return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, 775 field_description, CEED_CONTEXT_FIELD_INT32, sizeof(int), num_values); 776 } 777 778 /** 779 @brief Get labels for all registered QFunctionContext fields 780 781 @param ctx CeedQFunctionContext 782 @param[out] field_labels Variable to hold array of field labels 783 @param[out] num_fields Length of field descriptions array 784 785 @return An error code: 0 - success, otherwise - failure 786 787 @ref User 788 **/ 789 int CeedQFunctionContextGetAllFieldLabels(CeedQFunctionContext ctx, 790 const CeedContextFieldLabel **field_labels, CeedInt *num_fields) { 791 *field_labels = ctx->field_labels; 792 *num_fields = ctx->num_fields; 793 return CEED_ERROR_SUCCESS; 794 } 795 796 /** 797 @brief Get the descriptive information about a CeedContextFieldLabel 798 799 @param[in] label CeedContextFieldLabel 800 @param[out] field_name Name of labeled field 801 @param[out] field_description Description of field, or NULL for none 802 @param[out] num_values Number of values registered 803 @param[out] field_type CeedContextFieldType 804 805 @return An error code: 0 - success, otherwise - failure 806 807 @ref User 808 **/ 809 int CeedContextFieldLabelGetDescription(CeedContextFieldLabel label, 810 const char **field_name, 811 const char **field_description, 812 size_t *num_values, 813 CeedContextFieldType *field_type) { 814 if (field_name) *field_name = label->name; 815 if (field_description) *field_description = label->description; 816 if (num_values) *num_values = label->num_values; 817 if (field_type) *field_type = label->type; 818 return CEED_ERROR_SUCCESS; 819 } 820 821 /** 822 @brief Get data size for a Context 823 824 @param ctx CeedQFunctionContext 825 @param[out] ctx_size Variable to store size of context data values 826 827 @return An error code: 0 - success, otherwise - failure 828 829 @ref User 830 **/ 831 int CeedQFunctionContextGetContextSize(CeedQFunctionContext ctx, 832 size_t *ctx_size) { 833 *ctx_size = ctx->ctx_size; 834 return CEED_ERROR_SUCCESS; 835 } 836 837 838 /** 839 @brief View a CeedQFunctionContext 840 841 @param[in] ctx CeedQFunctionContext to view 842 @param[in] stream Filestream to write to 843 844 @return An error code: 0 - success, otherwise - failure 845 846 @ref User 847 **/ 848 int CeedQFunctionContextView(CeedQFunctionContext ctx, FILE *stream) { 849 fprintf(stream, "CeedQFunctionContext\n"); 850 fprintf(stream, " Context Data Size: %ld\n", ctx->ctx_size); 851 for (CeedInt i = 0; i < ctx->num_fields; i++) { 852 // LCOV_EXCL_START 853 fprintf(stream, " Labeled %s field: %s\n", 854 CeedContextFieldTypes[ctx->field_labels[i]->type], 855 ctx->field_labels[i]->name); 856 // LCOV_EXCL_STOP 857 } 858 return CEED_ERROR_SUCCESS; 859 } 860 861 /** 862 @brief Set additional destroy routine for CeedQFunctionContext user data 863 864 @param[in] ctx CeedQFunctionContext to set user destroy function 865 @param[in] f_mem_type Memory type to use when passing data into `f` 866 @param[in] f Additional routine to use to destroy user data 867 868 @return An error code: 0 - success, otherwise - failure 869 870 @ref User 871 **/ 872 int CeedQFunctionContextSetDataDestroy(CeedQFunctionContext ctx, 873 CeedMemType f_mem_type, CeedQFunctionContextDataDestroyUser f) { 874 if (!f) 875 // LCOV_EXCL_START 876 return CeedError(ctx->ceed, 1, 877 "Must provide valid callback function for destroying user data"); 878 // LCOV_EXCL_STOP 879 ctx->data_destroy_mem_type = f_mem_type; 880 ctx->data_destroy_function = f; 881 return CEED_ERROR_SUCCESS; 882 } 883 884 /** 885 @brief Destroy a CeedQFunctionContext 886 887 @param ctx CeedQFunctionContext to destroy 888 889 @return An error code: 0 - success, otherwise - failure 890 891 @ref User 892 **/ 893 int CeedQFunctionContextDestroy(CeedQFunctionContext *ctx) { 894 int ierr; 895 896 if (!*ctx || --(*ctx)->ref_count > 0) 897 return CEED_ERROR_SUCCESS; 898 899 if ((*ctx) && ((*ctx)->state % 2) == 1) 900 // LCOV_EXCL_START 901 return CeedError((*ctx)->ceed, 1, 902 "Cannot destroy CeedQFunctionContext, the access " 903 "lock is in use"); 904 // LCOV_EXCL_STOP 905 906 ierr = CeedQFunctionContextDestroyData(*ctx); CeedChk(ierr); 907 if ((*ctx)->Destroy) { 908 ierr = (*ctx)->Destroy(*ctx); CeedChk(ierr); 909 } 910 for (CeedInt i=0; i<(*ctx)->num_fields; i++) { 911 ierr = CeedFree(&(*ctx)->field_labels[i]->name); CeedChk(ierr); 912 ierr = CeedFree(&(*ctx)->field_labels[i]->description); CeedChk(ierr); 913 ierr = CeedFree(&(*ctx)->field_labels[i]); CeedChk(ierr); 914 } 915 ierr = CeedFree(&(*ctx)->field_labels); CeedChk(ierr); 916 ierr = CeedDestroy(&(*ctx)->ceed); CeedChk(ierr); 917 ierr = CeedFree(ctx); CeedChk(ierr); 918 919 return CEED_ERROR_SUCCESS; 920 } 921 922 /// @} 923