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