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