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.h> 10 #include <ceed/backend.h> 11 #include <stdbool.h> 12 #include <stdint.h> 13 #include <stdio.h> 14 #include <string.h> 15 16 /// @file 17 /// Implementation of public CeedQFunctionContext interfaces 18 19 /// ---------------------------------------------------------------------------- 20 /// CeedQFunctionContext Library Internal Functions 21 /// ---------------------------------------------------------------------------- 22 /// @addtogroup CeedQFunctionDeveloper 23 /// @{ 24 25 /** 26 @brief Get index for QFunctionContext field 27 28 @param[in] ctx CeedQFunctionContext 29 @param[in] field_name Name of field 30 @param[out] field_index Index of field, or -1 if field is not registered 31 32 @return An error code: 0 - success, otherwise - failure 33 34 @ref Developer 35 **/ 36 int CeedQFunctionContextGetFieldIndex(CeedQFunctionContext ctx, 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)) *field_index = i; 40 } 41 return CEED_ERROR_SUCCESS; 42 } 43 44 /** 45 @brief Common function for registering QFunctionContext fields 46 47 @param[in,out] ctx CeedQFunctionContext 48 @param[in] field_name Name of field to register 49 @param[in] field_offset Offset of field to register 50 @param[in] field_description Description of field, or NULL for none 51 @param[in] field_type Field data type, such as double or int32 52 @param[in] field_size Size of field, in bytes 53 @param[in] 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, const char *field_name, size_t field_offset, const char *field_description, 60 CeedContextFieldType field_type, size_t field_size, size_t num_values) { 61 // Check for duplicate 62 CeedInt field_index = -1; 63 CeedCall(CeedQFunctionContextGetFieldIndex(ctx, field_name, &field_index)); 64 if (field_index != -1) { 65 // LCOV_EXCL_START 66 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "QFunctionContext field with name \"%s\" already registered", field_name); 67 // LCOV_EXCL_STOP 68 } 69 70 // Allocate space for field data 71 if (ctx->num_fields == 0) { 72 CeedCall(CeedCalloc(1, &ctx->field_labels)); 73 ctx->max_fields = 1; 74 } else if (ctx->num_fields == ctx->max_fields) { 75 CeedCall(CeedRealloc(2 * ctx->max_fields, &ctx->field_labels)); 76 ctx->max_fields *= 2; 77 } 78 CeedCall(CeedCalloc(1, &ctx->field_labels[ctx->num_fields])); 79 80 // Copy field data 81 CeedCall(CeedStringAllocCopy(field_name, (char **)&ctx->field_labels[ctx->num_fields]->name)); 82 CeedCall(CeedStringAllocCopy(field_description, (char **)&ctx->field_labels[ctx->num_fields]->description)); 83 ctx->field_labels[ctx->num_fields]->type = field_type; 84 ctx->field_labels[ctx->num_fields]->offset = field_offset; 85 ctx->field_labels[ctx->num_fields]->size = field_size * num_values; 86 ctx->field_labels[ctx->num_fields]->num_values = num_values; 87 ctx->num_fields++; 88 return CEED_ERROR_SUCCESS; 89 } 90 91 /** 92 @brief Destroy user data held by CeedQFunctionContext, using function set by 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[in] 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[in] 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 CeedQFunctionContext 167 168 @param[in] ctx CeedQFunctionContext to check 169 @param[in] mem_type Memory type to check 170 @param[out] has_borrowed_data_of_type Variable to store result 171 172 @return An error code: 0 - success, otherwise - failure 173 174 @ref Backend 175 **/ 176 int CeedQFunctionContextHasBorrowedDataOfType(CeedQFunctionContext ctx, CeedMemType mem_type, bool *has_borrowed_data_of_type) { 177 if (!ctx->HasBorrowedDataOfType) { 178 // LCOV_EXCL_START 179 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support HasBorrowedDataOfType"); 180 // LCOV_EXCL_STOP 181 } 182 183 CeedCall(ctx->HasBorrowedDataOfType(ctx, mem_type, has_borrowed_data_of_type)); 184 185 return CEED_ERROR_SUCCESS; 186 } 187 188 /** 189 @brief Get the state of a CeedQFunctionContext 190 191 @param[in] ctx CeedQFunctionContext to retrieve state 192 @param[out] state Variable to store state 193 194 @return An error code: 0 - success, otherwise - failure 195 196 @ref Backend 197 **/ 198 int CeedQFunctionContextGetState(CeedQFunctionContext ctx, uint64_t *state) { 199 *state = ctx->state; 200 return CEED_ERROR_SUCCESS; 201 } 202 203 /** 204 @brief Get backend data of a CeedQFunctionContext 205 206 @param[in] ctx CeedQFunctionContext 207 @param[out] data Variable to store data 208 209 @return An error code: 0 - success, otherwise - failure 210 211 @ref Backend 212 **/ 213 int CeedQFunctionContextGetBackendData(CeedQFunctionContext ctx, void *data) { 214 *(void **)data = ctx->data; 215 return CEED_ERROR_SUCCESS; 216 } 217 218 /** 219 @brief Set backend data of a CeedQFunctionContext 220 221 @param[in,out] ctx CeedQFunctionContext 222 @param[in] data Data to set 223 224 @return An error code: 0 - success, otherwise - failure 225 226 @ref Backend 227 **/ 228 int CeedQFunctionContextSetBackendData(CeedQFunctionContext ctx, void *data) { 229 ctx->data = data; 230 return CEED_ERROR_SUCCESS; 231 } 232 233 /** 234 @brief Get label for a registered QFunctionContext field, or `NULL` if no field has been registered with this `field_name` 235 236 @param[in] ctx CeedQFunctionContext 237 @param[in] field_name Name of field to retrieve label 238 @param[out] field_label Variable to field label 239 240 @return An error code: 0 - success, otherwise - failure 241 242 @ref Backend 243 **/ 244 int CeedQFunctionContextGetFieldLabel(CeedQFunctionContext ctx, const char *field_name, CeedContextFieldLabel *field_label) { 245 CeedInt field_index; 246 CeedCall(CeedQFunctionContextGetFieldIndex(ctx, field_name, &field_index)); 247 248 if (field_index != -1) { 249 *field_label = ctx->field_labels[field_index]; 250 } else { 251 *field_label = NULL; 252 } 253 254 return CEED_ERROR_SUCCESS; 255 } 256 257 /** 258 @brief Set QFunctionContext field 259 260 @param[in,out] ctx CeedQFunctionContext 261 @param[in] field_label Label of field to set 262 @param[in] field_type Type of field to set 263 @param[in] values Value to set 264 265 @return An error code: 0 - success, otherwise - failure 266 267 @ref Backend 268 **/ 269 int CeedQFunctionContextSetGeneric(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, CeedContextFieldType field_type, void *values) { 270 // Check field type 271 if (field_label->type != field_type) { 272 // LCOV_EXCL_START 273 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "QFunctionContext field with name \"%s\" registered as %s, not registered as %s", 274 field_label->name, CeedContextFieldTypes[field_label->type], CeedContextFieldTypes[field_type]); 275 // LCOV_EXCL_STOP 276 } 277 278 char *data; 279 CeedCall(CeedQFunctionContextGetData(ctx, CEED_MEM_HOST, &data)); 280 memcpy(&data[field_label->offset], values, field_label->size); 281 CeedCall(CeedQFunctionContextRestoreData(ctx, &data)); 282 283 return CEED_ERROR_SUCCESS; 284 } 285 286 /** 287 @brief Get QFunctionContext field data, read-only 288 289 @param[in] ctx CeedQFunctionContext 290 @param[in] field_label Label of field to read 291 @param[in] field_type Type of field to read 292 @param[out] num_values Number of values in the field label 293 @param[out] values Pointer to context values 294 295 @return An error code: 0 - success, otherwise - failure 296 297 @ref Backend 298 **/ 299 int CeedQFunctionContextGetGenericRead(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, CeedContextFieldType field_type, 300 size_t *num_values, void *values) { 301 // Check field type 302 if (field_label->type != field_type) { 303 // LCOV_EXCL_START 304 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "QFunctionContext field with name \"%s\" registered as %s, not registered as %s", 305 field_label->name, CeedContextFieldTypes[field_label->type], CeedContextFieldTypes[field_type]); 306 // LCOV_EXCL_STOP 307 } 308 309 char *data; 310 CeedCall(CeedQFunctionContextGetDataRead(ctx, CEED_MEM_HOST, &data)); 311 *(void **)values = &data[field_label->offset]; 312 switch (field_type) { 313 case CEED_CONTEXT_FIELD_INT32: 314 *num_values = field_label->size / sizeof(int); 315 break; 316 case CEED_CONTEXT_FIELD_DOUBLE: 317 *num_values = field_label->size / sizeof(double); 318 break; 319 } 320 321 return CEED_ERROR_SUCCESS; 322 } 323 324 /** 325 @brief Restore QFunctionContext field data, read-only 326 327 @param[in] ctx CeedQFunctionContext 328 @param[in] field_label Label of field to restore 329 @param[in] field_type Type of field to restore 330 @param[out] values Pointer to context values 331 332 @return An error code: 0 - success, otherwise - failure 333 334 @ref Backend 335 **/ 336 int CeedQFunctionContextRestoreGenericRead(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, CeedContextFieldType field_type, 337 void *values) { 338 // Check field type 339 if (field_label->type != field_type) { 340 // LCOV_EXCL_START 341 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "QFunctionContext field with name \"%s\" registered as %s, not registered as %s", 342 field_label->name, CeedContextFieldTypes[field_label->type], CeedContextFieldTypes[field_type]); 343 // LCOV_EXCL_STOP 344 } 345 346 CeedCall(CeedQFunctionContextRestoreDataRead(ctx, values)); 347 348 return CEED_ERROR_SUCCESS; 349 } 350 351 /** 352 @brief Set QFunctionContext field holding a double precision value 353 354 @param[in,out] ctx CeedQFunctionContext 355 @param[in] field_label Label for field to set 356 @param[in] values Values to set 357 358 @return An error code: 0 - success, otherwise - failure 359 360 @ref Backend 361 **/ 362 int CeedQFunctionContextSetDouble(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, double *values) { 363 if (!field_label) { 364 // LCOV_EXCL_START 365 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label"); 366 // LCOV_EXCL_STOP 367 } 368 369 CeedCall(CeedQFunctionContextSetGeneric(ctx, field_label, CEED_CONTEXT_FIELD_DOUBLE, values)); 370 371 return CEED_ERROR_SUCCESS; 372 } 373 374 /** 375 @brief Get QFunctionContext field holding a double precision value, read-only 376 377 @param[in] ctx CeedQFunctionContext 378 @param[in] field_label Label for field to get 379 @param[out] num_values Number of values in the field label 380 @param[out] values Pointer to context values 381 382 @return An error code: 0 - success, otherwise - failure 383 384 @ref Backend 385 **/ 386 int CeedQFunctionContextGetDoubleRead(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, size_t *num_values, const double **values) { 387 if (!field_label) { 388 // LCOV_EXCL_START 389 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label"); 390 // LCOV_EXCL_STOP 391 } 392 393 CeedCall(CeedQFunctionContextGetGenericRead(ctx, field_label, CEED_CONTEXT_FIELD_DOUBLE, num_values, values)); 394 395 return CEED_ERROR_SUCCESS; 396 } 397 398 /** 399 @brief Restore QFunctionContext field holding a double precision value, read-only 400 401 @param[in] ctx CeedQFunctionContext 402 @param[in] field_label Label for field to restore 403 @param[out] values Pointer to context values 404 405 @return An error code: 0 - success, otherwise - failure 406 407 @ref Backend 408 **/ 409 int CeedQFunctionContextRestoreDoubleRead(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, const double **values) { 410 if (!field_label) { 411 // LCOV_EXCL_START 412 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label"); 413 // LCOV_EXCL_STOP 414 } 415 416 CeedCall(CeedQFunctionContextRestoreGenericRead(ctx, field_label, CEED_CONTEXT_FIELD_DOUBLE, values)); 417 418 return CEED_ERROR_SUCCESS; 419 } 420 421 /** 422 @brief Set QFunctionContext field holding an int32 value 423 424 @param[in,out] ctx CeedQFunctionContext 425 @param[in] field_label Label for field to set 426 @param[in] values Values to set 427 428 @return An error code: 0 - success, otherwise - failure 429 430 @ref Backend 431 **/ 432 int CeedQFunctionContextSetInt32(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, int *values) { 433 if (!field_label) { 434 // LCOV_EXCL_START 435 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label"); 436 // LCOV_EXCL_STOP 437 } 438 439 CeedCall(CeedQFunctionContextSetGeneric(ctx, field_label, CEED_CONTEXT_FIELD_INT32, values)); 440 441 return CEED_ERROR_SUCCESS; 442 } 443 444 /** 445 @brief Get QFunctionContext field holding a int32 value, read-only 446 447 @param[in] ctx CeedQFunctionContext 448 @param[in] field_label Label for field to get 449 @param[out] num_values Number of values in the field label 450 @param[out] values Pointer to context values 451 452 @return An error code: 0 - success, otherwise - failure 453 454 @ref Backend 455 **/ 456 int CeedQFunctionContextGetInt32Read(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, size_t *num_values, const int **values) { 457 if (!field_label) { 458 // LCOV_EXCL_START 459 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label"); 460 // LCOV_EXCL_STOP 461 } 462 463 CeedCall(CeedQFunctionContextGetGenericRead(ctx, field_label, CEED_CONTEXT_FIELD_INT32, num_values, values)); 464 465 return CEED_ERROR_SUCCESS; 466 } 467 468 /** 469 @brief Restore QFunctionContext field holding a int32 value, read-only 470 471 @param[in] ctx CeedQFunctionContext 472 @param[in] field_label Label for field to restore 473 @param[out] values Pointer to context values 474 475 @return An error code: 0 - success, otherwise - failure 476 477 @ref Backend 478 **/ 479 int CeedQFunctionContextRestoreInt32Read(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, const int **values) { 480 if (!field_label) { 481 // LCOV_EXCL_START 482 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label"); 483 // LCOV_EXCL_STOP 484 } 485 486 CeedCall(CeedQFunctionContextRestoreGenericRead(ctx, field_label, CEED_CONTEXT_FIELD_INT32, values)); 487 488 return CEED_ERROR_SUCCESS; 489 } 490 491 /** 492 @brief Get additional destroy routine for CeedQFunctionContext user data 493 494 @param[in] ctx CeedQFunctionContext to get user destroy function 495 @param[out] f_mem_type Memory type to use when passing data into `f` 496 @param[out] f Additional routine to use to destroy user data 497 498 @return An error code: 0 - success, otherwise - failure 499 500 @ref Backend 501 **/ 502 int CeedQFunctionContextGetDataDestroy(CeedQFunctionContext ctx, CeedMemType *f_mem_type, CeedQFunctionContextDataDestroyUser *f) { 503 if (f_mem_type) *f_mem_type = ctx->data_destroy_mem_type; 504 if (f) *f = ctx->data_destroy_function; 505 return CEED_ERROR_SUCCESS; 506 } 507 508 /** 509 @brief Increment the reference counter for a CeedQFunctionContext 510 511 @param[in,out] ctx CeedQFunctionContext to increment the reference counter 512 513 @return An error code: 0 - success, otherwise - failure 514 515 @ref Backend 516 **/ 517 int CeedQFunctionContextReference(CeedQFunctionContext ctx) { 518 ctx->ref_count++; 519 return CEED_ERROR_SUCCESS; 520 } 521 522 /// @} 523 524 /// ---------------------------------------------------------------------------- 525 /// CeedQFunctionContext Public API 526 /// ---------------------------------------------------------------------------- 527 /// @addtogroup CeedQFunctionUser 528 /// @{ 529 530 /** 531 @brief Create a CeedQFunctionContext for storing CeedQFunction user context data 532 533 @param[in] ceed Ceed object where the CeedQFunctionContext will be created 534 @param[out] ctx Address of the variable where the newly created CeedQFunctionContext will be stored 535 536 @return An error code: 0 - success, otherwise - failure 537 538 @ref User 539 **/ 540 int CeedQFunctionContextCreate(Ceed ceed, CeedQFunctionContext *ctx) { 541 if (!ceed->QFunctionContextCreate) { 542 Ceed delegate; 543 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "Context")); 544 545 if (!delegate) { 546 // LCOV_EXCL_START 547 return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ContextCreate"); 548 // LCOV_EXCL_STOP 549 } 550 551 CeedCall(CeedQFunctionContextCreate(delegate, ctx)); 552 return CEED_ERROR_SUCCESS; 553 } 554 555 CeedCall(CeedCalloc(1, ctx)); 556 (*ctx)->ceed = ceed; 557 CeedCall(CeedReference(ceed)); 558 (*ctx)->ref_count = 1; 559 CeedCall(ceed->QFunctionContextCreate(*ctx)); 560 return CEED_ERROR_SUCCESS; 561 } 562 563 /** 564 @brief Copy the pointer to a CeedQFunctionContext. 565 Both pointers should be destroyed with `CeedQFunctionContextDestroy()`. 566 567 Note: If the value of `ctx_copy` passed to this function is non-NULL, then it is assumed that `ctx_copy` is a pointer to a 568 CeedQFunctionContext. This CeedQFunctionContext will be destroyed if `ctx_copy` is the only reference to this CeedQFunctionContext. 569 570 @param[in] ctx CeedQFunctionContext to copy reference to 571 @param[in,out] ctx_copy Variable to store copied reference 572 573 @return An error code: 0 - success, otherwise - failure 574 575 @ref User 576 **/ 577 int CeedQFunctionContextReferenceCopy(CeedQFunctionContext ctx, CeedQFunctionContext *ctx_copy) { 578 CeedCall(CeedQFunctionContextReference(ctx)); 579 CeedCall(CeedQFunctionContextDestroy(ctx_copy)); 580 *ctx_copy = ctx; 581 return CEED_ERROR_SUCCESS; 582 } 583 584 /** 585 @brief Set the data used by a CeedQFunctionContext, freeing any previously allocated data if applicable. 586 The backend may copy values to a different memtype, such as during @ref CeedQFunctionApply(). 587 See also @ref CeedQFunctionContextTakeData(). 588 589 @param[in,out] ctx CeedQFunctionContext 590 @param[in] mem_type Memory type of the data being passed 591 @param[in] copy_mode Copy mode for the data 592 @param[in] size Size of data, in bytes 593 @param[in] data Data to be used 594 595 @return An error code: 0 - success, otherwise - failure 596 597 @ref User 598 **/ 599 int CeedQFunctionContextSetData(CeedQFunctionContext ctx, CeedMemType mem_type, CeedCopyMode copy_mode, size_t size, void *data) { 600 if (!ctx->SetData) { 601 // LCOV_EXCL_START 602 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ContextSetData"); 603 // LCOV_EXCL_STOP 604 } 605 if (ctx->state % 2 == 1) { 606 // LCOV_EXCL_START 607 return CeedError(ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use"); 608 // LCOV_EXCL_STOP 609 } 610 611 CeedCall(CeedQFunctionContextDestroyData(ctx)); 612 ctx->ctx_size = size; 613 CeedCall(ctx->SetData(ctx, mem_type, copy_mode, data)); 614 ctx->state += 2; 615 return CEED_ERROR_SUCCESS; 616 } 617 618 /** 619 @brief Take ownership of the data in a CeedQFunctionContext via the specified memory type. 620 The caller is responsible for managing and freeing the memory. 621 622 @param[in] ctx CeedQFunctionContext to access 623 @param[in] mem_type Memory type on which to access the data. 624 If the backend uses a different memory type, this will perform a copy. 625 @param[out] data Data on memory type mem_type 626 627 @return An error code: 0 - success, otherwise - failure 628 629 @ref User 630 **/ 631 int CeedQFunctionContextTakeData(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) { 632 bool has_valid_data = true; 633 CeedCall(CeedQFunctionContextHasValidData(ctx, &has_valid_data)); 634 if (!has_valid_data) { 635 // LCOV_EXCL_START 636 return CeedError(ctx->ceed, CEED_ERROR_BACKEND, "CeedQFunctionContext has no valid data to take, must set data"); 637 // LCOV_EXCL_STOP 638 } 639 640 if (!ctx->TakeData) { 641 // LCOV_EXCL_START 642 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support TakeData"); 643 // LCOV_EXCL_STOP 644 } 645 if (ctx->state % 2 == 1) { 646 // LCOV_EXCL_START 647 return CeedError(ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use"); 648 // LCOV_EXCL_STOP 649 } 650 651 bool has_borrowed_data_of_type = true; 652 CeedCall(CeedQFunctionContextHasBorrowedDataOfType(ctx, mem_type, &has_borrowed_data_of_type)); 653 if (!has_borrowed_data_of_type) { 654 // LCOV_EXCL_START 655 return CeedError(ctx->ceed, CEED_ERROR_BACKEND, "CeedQFunctionContext has no borrowed %s data, must set data with CeedQFunctionContextSetData", 656 CeedMemTypes[mem_type]); 657 // LCOV_EXCL_STOP 658 } 659 660 void *temp_data = NULL; 661 CeedCall(ctx->TakeData(ctx, mem_type, &temp_data)); 662 if (data) (*(void **)data) = temp_data; 663 return CEED_ERROR_SUCCESS; 664 } 665 666 /** 667 @brief Get read/write access to a CeedQFunctionContext via the specified memory type. 668 Restore access with @ref CeedQFunctionContextRestoreData(). 669 670 @param[in] ctx CeedQFunctionContext to access 671 @param[in] mem_type Memory type on which to access the data. 672 If the backend uses a different memory type, this will perform a copy. 673 @param[out] data Data on memory type mem_type 674 675 @note The CeedQFunctionContextGetData() and @ref CeedQFunctionContextRestoreData() functions provide access to array pointers in the desired memory 676 space. Pairing get/restore allows the Context to track access. 677 678 @return An error code: 0 - success, otherwise - failure 679 680 @ref User 681 **/ 682 int CeedQFunctionContextGetData(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) { 683 if (!ctx->GetData) { 684 // LCOV_EXCL_START 685 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetData"); 686 // LCOV_EXCL_STOP 687 } 688 if (ctx->state % 2 == 1) { 689 // LCOV_EXCL_START 690 return CeedError(ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use"); 691 // LCOV_EXCL_STOP 692 } 693 if (ctx->num_readers > 0) { 694 // LCOV_EXCL_START 695 return CeedError(ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, a process has read access"); 696 // LCOV_EXCL_STOP 697 } 698 699 bool has_valid_data = true; 700 CeedCall(CeedQFunctionContextHasValidData(ctx, &has_valid_data)); 701 if (!has_valid_data) { 702 // LCOV_EXCL_START 703 return CeedError(ctx->ceed, CEED_ERROR_BACKEND, "CeedQFunctionContext has no valid data to get, must set data"); 704 // LCOV_EXCL_STOP 705 } 706 707 CeedCall(ctx->GetData(ctx, mem_type, data)); 708 ctx->state++; 709 return CEED_ERROR_SUCCESS; 710 } 711 712 /** 713 @brief Get read only access to a CeedQFunctionContext via the specified memory type. 714 Restore access with @ref CeedQFunctionContextRestoreData(). 715 716 @param[in] ctx CeedQFunctionContext to access 717 @param[in] mem_type Memory type on which to access the data. 718 If the backend uses a different memory type, this will perform a copy. 719 @param[out] data Data on memory type mem_type 720 721 @note The CeedQFunctionContextGetDataRead() and @ref CeedQFunctionContextRestoreDataRead() functions provide access to array pointers in the desired 722 memory space. Pairing get/restore allows the Context to track access. 723 724 @return An error code: 0 - success, otherwise - failure 725 726 @ref User 727 **/ 728 int CeedQFunctionContextGetDataRead(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) { 729 if (!ctx->GetDataRead) { 730 // LCOV_EXCL_START 731 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetDataRead"); 732 // LCOV_EXCL_STOP 733 } 734 if (ctx->state % 2 == 1) { 735 // LCOV_EXCL_START 736 return CeedError(ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use"); 737 // LCOV_EXCL_STOP 738 } 739 740 bool has_valid_data = true; 741 CeedCall(CeedQFunctionContextHasValidData(ctx, &has_valid_data)); 742 if (!has_valid_data) { 743 // LCOV_EXCL_START 744 return CeedError(ctx->ceed, CEED_ERROR_BACKEND, "CeedQFunctionContext has no valid data to get, must set data"); 745 // LCOV_EXCL_STOP 746 } 747 748 CeedCall(ctx->GetDataRead(ctx, mem_type, data)); 749 ctx->num_readers++; 750 return CEED_ERROR_SUCCESS; 751 } 752 753 /** 754 @brief Restore data obtained using @ref CeedQFunctionContextGetData() 755 756 @param[in] ctx CeedQFunctionContext to restore 757 @param[in,out] data Data to restore 758 759 @return An error code: 0 - success, otherwise - failure 760 761 @ref User 762 **/ 763 int CeedQFunctionContextRestoreData(CeedQFunctionContext ctx, void *data) { 764 if (ctx->state % 2 != 1) { 765 // LCOV_EXCL_START 766 return CeedError(ctx->ceed, 1, "Cannot restore CeedQFunctionContext array access, access was not granted"); 767 // LCOV_EXCL_STOP 768 } 769 770 if (ctx->RestoreData) { 771 CeedCall(ctx->RestoreData(ctx)); 772 } 773 *(void **)data = NULL; 774 ctx->state++; 775 return CEED_ERROR_SUCCESS; 776 } 777 778 /** 779 @brief Restore data obtained using @ref CeedQFunctionContextGetDataRead() 780 781 @param[in] ctx CeedQFunctionContext to restore 782 @param[in,out] data Data to restore 783 784 @return An error code: 0 - success, otherwise - failure 785 786 @ref User 787 **/ 788 int CeedQFunctionContextRestoreDataRead(CeedQFunctionContext ctx, void *data) { 789 if (ctx->num_readers == 0) { 790 // LCOV_EXCL_START 791 return CeedError(ctx->ceed, 1, "Cannot restore CeedQFunctionContext array access, access was not granted"); 792 // LCOV_EXCL_STOP 793 } 794 795 ctx->num_readers--; 796 if (ctx->num_readers == 0 && ctx->RestoreDataRead) { 797 CeedCall(ctx->RestoreDataRead(ctx)); 798 } 799 *(void **)data = NULL; 800 801 return CEED_ERROR_SUCCESS; 802 } 803 804 /** 805 @brief Register QFunctionContext a field holding a double precision value 806 807 @param[in,out] ctx CeedQFunctionContext 808 @param[in] field_name Name of field to register 809 @param[in] field_offset Offset of field to register 810 @param[in] num_values Number of values to register, must be contiguous in memory 811 @param[in] field_description Description of field, or NULL for none 812 813 @return An error code: 0 - success, otherwise - failure 814 815 @ref User 816 **/ 817 int CeedQFunctionContextRegisterDouble(CeedQFunctionContext ctx, const char *field_name, size_t field_offset, size_t num_values, 818 const char *field_description) { 819 return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, field_description, CEED_CONTEXT_FIELD_DOUBLE, sizeof(double), num_values); 820 } 821 822 /** 823 @brief Register QFunctionContext a field holding a int32 value 824 825 @param[in,out] ctx CeedQFunctionContext 826 @param[in] field_name Name of field to register 827 @param[in] field_offset Offset of field to register 828 @param[in] num_values Number of values to register, must be contiguous in memory 829 @param[in] field_description Description of field, or NULL for none 830 831 @return An error code: 0 - success, otherwise - failure 832 833 @ref User 834 **/ 835 int CeedQFunctionContextRegisterInt32(CeedQFunctionContext ctx, const char *field_name, size_t field_offset, size_t num_values, 836 const char *field_description) { 837 return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, field_description, CEED_CONTEXT_FIELD_INT32, sizeof(int), num_values); 838 } 839 840 /** 841 @brief Get labels for all registered QFunctionContext fields 842 843 @param[in] ctx CeedQFunctionContext 844 @param[out] field_labels Variable to hold array of field labels 845 @param[out] num_fields Length of field descriptions array 846 847 @return An error code: 0 - success, otherwise - failure 848 849 @ref User 850 **/ 851 int CeedQFunctionContextGetAllFieldLabels(CeedQFunctionContext ctx, const CeedContextFieldLabel **field_labels, CeedInt *num_fields) { 852 *field_labels = ctx->field_labels; 853 *num_fields = ctx->num_fields; 854 return CEED_ERROR_SUCCESS; 855 } 856 857 /** 858 @brief Get the descriptive information about a CeedContextFieldLabel 859 860 @param[in] label CeedContextFieldLabel 861 @param[out] field_name Name of labeled field 862 @param[out] field_description Description of field, or NULL for none 863 @param[out] num_values Number of values registered 864 @param[out] field_type CeedContextFieldType 865 866 @return An error code: 0 - success, otherwise - failure 867 868 @ref User 869 **/ 870 int CeedContextFieldLabelGetDescription(CeedContextFieldLabel label, const char **field_name, const char **field_description, size_t *num_values, 871 CeedContextFieldType *field_type) { 872 if (field_name) *field_name = label->name; 873 if (field_description) *field_description = label->description; 874 if (num_values) *num_values = label->num_values; 875 if (field_type) *field_type = label->type; 876 return CEED_ERROR_SUCCESS; 877 } 878 879 /** 880 @brief Get data size for a Context 881 882 @param[in] ctx CeedQFunctionContext 883 @param[out] ctx_size Variable to store size of context data values 884 885 @return An error code: 0 - success, otherwise - failure 886 887 @ref User 888 **/ 889 int CeedQFunctionContextGetContextSize(CeedQFunctionContext ctx, size_t *ctx_size) { 890 *ctx_size = ctx->ctx_size; 891 return CEED_ERROR_SUCCESS; 892 } 893 894 /** 895 @brief View a CeedQFunctionContext 896 897 @param[in] ctx CeedQFunctionContext to view 898 @param[in] stream Filestream to write to 899 900 @return An error code: 0 - success, otherwise - failure 901 902 @ref User 903 **/ 904 int CeedQFunctionContextView(CeedQFunctionContext ctx, FILE *stream) { 905 fprintf(stream, "CeedQFunctionContext\n"); 906 fprintf(stream, " Context Data Size: %ld\n", ctx->ctx_size); 907 for (CeedInt i = 0; i < ctx->num_fields; i++) { 908 // LCOV_EXCL_START 909 fprintf(stream, " Labeled %s field: %s\n", CeedContextFieldTypes[ctx->field_labels[i]->type], ctx->field_labels[i]->name); 910 // LCOV_EXCL_STOP 911 } 912 return CEED_ERROR_SUCCESS; 913 } 914 915 /** 916 @brief Set additional destroy routine for CeedQFunctionContext user data 917 918 @param[in,out] ctx CeedQFunctionContext to set user destroy function 919 @param[in] f_mem_type Memory type to use when passing data into `f` 920 @param[in] f Additional routine to use to destroy user data 921 922 @return An error code: 0 - success, otherwise - failure 923 924 @ref User 925 **/ 926 int CeedQFunctionContextSetDataDestroy(CeedQFunctionContext ctx, CeedMemType f_mem_type, CeedQFunctionContextDataDestroyUser f) { 927 if (!f) { 928 // LCOV_EXCL_START 929 return CeedError(ctx->ceed, 1, "Must provide valid callback function for destroying user data"); 930 // LCOV_EXCL_STOP 931 } 932 ctx->data_destroy_mem_type = f_mem_type; 933 ctx->data_destroy_function = f; 934 return CEED_ERROR_SUCCESS; 935 } 936 937 /** 938 @brief Destroy a CeedQFunctionContext 939 940 @param[in,out] ctx CeedQFunctionContext to destroy 941 942 @return An error code: 0 - success, otherwise - failure 943 944 @ref User 945 **/ 946 int CeedQFunctionContextDestroy(CeedQFunctionContext *ctx) { 947 if (!*ctx || --(*ctx)->ref_count > 0) { 948 *ctx = NULL; 949 return CEED_ERROR_SUCCESS; 950 } 951 if ((*ctx) && ((*ctx)->state % 2) == 1) { 952 // LCOV_EXCL_START 953 return CeedError((*ctx)->ceed, 1, "Cannot destroy CeedQFunctionContext, the access lock is in use"); 954 // LCOV_EXCL_STOP 955 } 956 957 CeedCall(CeedQFunctionContextDestroyData(*ctx)); 958 if ((*ctx)->Destroy) CeedCall((*ctx)->Destroy(*ctx)); 959 for (CeedInt i = 0; i < (*ctx)->num_fields; i++) { 960 CeedCall(CeedFree(&(*ctx)->field_labels[i]->name)); 961 CeedCall(CeedFree(&(*ctx)->field_labels[i]->description)); 962 CeedCall(CeedFree(&(*ctx)->field_labels[i])); 963 } 964 CeedCall(CeedFree(&(*ctx)->field_labels)); 965 CeedCall(CeedDestroy(&(*ctx)->ceed)); 966 CeedCall(CeedFree(ctx)); 967 968 return CEED_ERROR_SUCCESS; 969 } 970 971 /// @} 972