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 566 Both pointers should be destroyed with `CeedQFunctionContextDestroy()`. 567 568 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 569 CeedQFunctionContext. This CeedQFunctionContext will be destroyed if `ctx_copy` is the only reference to this CeedQFunctionContext. 570 571 @param[in] ctx CeedQFunctionContext to copy reference to 572 @param[in,out] ctx_copy Variable to store copied reference 573 574 @return An error code: 0 - success, otherwise - failure 575 576 @ref User 577 **/ 578 int CeedQFunctionContextReferenceCopy(CeedQFunctionContext ctx, CeedQFunctionContext *ctx_copy) { 579 CeedCall(CeedQFunctionContextReference(ctx)); 580 CeedCall(CeedQFunctionContextDestroy(ctx_copy)); 581 *ctx_copy = ctx; 582 return CEED_ERROR_SUCCESS; 583 } 584 585 /** 586 @brief Set the data used by a CeedQFunctionContext, freeing any previously allocated data if applicable. 587 588 The backend may copy values to a different memtype, such as during @ref CeedQFunctionApply(). 589 See also @ref CeedQFunctionContextTakeData(). 590 591 @param[in,out] ctx CeedQFunctionContext 592 @param[in] mem_type Memory type of the data being passed 593 @param[in] copy_mode Copy mode for the data 594 @param[in] size Size of data, in bytes 595 @param[in] data Data to be used 596 597 @return An error code: 0 - success, otherwise - failure 598 599 @ref User 600 **/ 601 int CeedQFunctionContextSetData(CeedQFunctionContext ctx, CeedMemType mem_type, CeedCopyMode copy_mode, size_t size, void *data) { 602 if (!ctx->SetData) { 603 // LCOV_EXCL_START 604 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ContextSetData"); 605 // LCOV_EXCL_STOP 606 } 607 if (ctx->state % 2 == 1) { 608 // LCOV_EXCL_START 609 return CeedError(ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use"); 610 // LCOV_EXCL_STOP 611 } 612 613 CeedCall(CeedQFunctionContextDestroyData(ctx)); 614 ctx->ctx_size = size; 615 CeedCall(ctx->SetData(ctx, mem_type, copy_mode, data)); 616 ctx->state += 2; 617 return CEED_ERROR_SUCCESS; 618 } 619 620 /** 621 @brief Take ownership of the data in a CeedQFunctionContext via the specified memory type. 622 623 The caller is responsible for managing and freeing the memory. 624 625 @param[in] ctx CeedQFunctionContext to access 626 @param[in] mem_type Memory type on which to access the data. 627 If the backend uses a different memory type, this will perform a copy. 628 @param[out] data Data on memory type mem_type 629 630 @return An error code: 0 - success, otherwise - failure 631 632 @ref User 633 **/ 634 int CeedQFunctionContextTakeData(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) { 635 bool has_valid_data = true; 636 CeedCall(CeedQFunctionContextHasValidData(ctx, &has_valid_data)); 637 if (!has_valid_data) { 638 // LCOV_EXCL_START 639 return CeedError(ctx->ceed, CEED_ERROR_BACKEND, "CeedQFunctionContext has no valid data to take, must set data"); 640 // LCOV_EXCL_STOP 641 } 642 643 if (!ctx->TakeData) { 644 // LCOV_EXCL_START 645 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support TakeData"); 646 // LCOV_EXCL_STOP 647 } 648 if (ctx->state % 2 == 1) { 649 // LCOV_EXCL_START 650 return CeedError(ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use"); 651 // LCOV_EXCL_STOP 652 } 653 654 bool has_borrowed_data_of_type = true; 655 CeedCall(CeedQFunctionContextHasBorrowedDataOfType(ctx, mem_type, &has_borrowed_data_of_type)); 656 if (!has_borrowed_data_of_type) { 657 // LCOV_EXCL_START 658 return CeedError(ctx->ceed, CEED_ERROR_BACKEND, "CeedQFunctionContext has no borrowed %s data, must set data with CeedQFunctionContextSetData", 659 CeedMemTypes[mem_type]); 660 // LCOV_EXCL_STOP 661 } 662 663 void *temp_data = NULL; 664 CeedCall(ctx->TakeData(ctx, mem_type, &temp_data)); 665 if (data) (*(void **)data) = temp_data; 666 return CEED_ERROR_SUCCESS; 667 } 668 669 /** 670 @brief Get read/write access to a CeedQFunctionContext via the specified memory type. 671 672 Restore access with @ref CeedQFunctionContextRestoreData(). 673 674 @param[in] ctx CeedQFunctionContext to access 675 @param[in] mem_type Memory type on which to access the data. 676 If the backend uses a different memory type, this will perform a copy. 677 @param[out] data Data on memory type mem_type 678 679 @note The CeedQFunctionContextGetData() and @ref CeedQFunctionContextRestoreData() functions provide access to array pointers in the desired memory 680 space. 681 Pairing get/restore allows the Context to track access. 682 683 @return An error code: 0 - success, otherwise - failure 684 685 @ref User 686 **/ 687 int CeedQFunctionContextGetData(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) { 688 if (!ctx->GetData) { 689 // LCOV_EXCL_START 690 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetData"); 691 // LCOV_EXCL_STOP 692 } 693 if (ctx->state % 2 == 1) { 694 // LCOV_EXCL_START 695 return CeedError(ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use"); 696 // LCOV_EXCL_STOP 697 } 698 if (ctx->num_readers > 0) { 699 // LCOV_EXCL_START 700 return CeedError(ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, a process has read access"); 701 // LCOV_EXCL_STOP 702 } 703 704 bool has_valid_data = true; 705 CeedCall(CeedQFunctionContextHasValidData(ctx, &has_valid_data)); 706 if (!has_valid_data) { 707 // LCOV_EXCL_START 708 return CeedError(ctx->ceed, CEED_ERROR_BACKEND, "CeedQFunctionContext has no valid data to get, must set data"); 709 // LCOV_EXCL_STOP 710 } 711 712 CeedCall(ctx->GetData(ctx, mem_type, data)); 713 ctx->state++; 714 return CEED_ERROR_SUCCESS; 715 } 716 717 /** 718 @brief Get read only access to a CeedQFunctionContext via the specified memory type. 719 720 Restore access with @ref CeedQFunctionContextRestoreData(). 721 722 @param[in] ctx CeedQFunctionContext to access 723 @param[in] mem_type Memory type on which to access the data. 724 If the backend uses a different memory type, this will perform a copy. 725 @param[out] data Data on memory type mem_type 726 727 @note The CeedQFunctionContextGetDataRead() and @ref CeedQFunctionContextRestoreDataRead() functions provide access to array pointers in the desired 728 memory space. 729 Pairing get/restore allows the Context to track access. 730 731 @return An error code: 0 - success, otherwise - failure 732 733 @ref User 734 **/ 735 int CeedQFunctionContextGetDataRead(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) { 736 if (!ctx->GetDataRead) { 737 // LCOV_EXCL_START 738 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetDataRead"); 739 // LCOV_EXCL_STOP 740 } 741 if (ctx->state % 2 == 1) { 742 // LCOV_EXCL_START 743 return CeedError(ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use"); 744 // LCOV_EXCL_STOP 745 } 746 747 bool has_valid_data = true; 748 CeedCall(CeedQFunctionContextHasValidData(ctx, &has_valid_data)); 749 if (!has_valid_data) { 750 // LCOV_EXCL_START 751 return CeedError(ctx->ceed, CEED_ERROR_BACKEND, "CeedQFunctionContext has no valid data to get, must set data"); 752 // LCOV_EXCL_STOP 753 } 754 755 CeedCall(ctx->GetDataRead(ctx, mem_type, data)); 756 ctx->num_readers++; 757 return CEED_ERROR_SUCCESS; 758 } 759 760 /** 761 @brief Restore data obtained using @ref CeedQFunctionContextGetData() 762 763 @param[in] ctx CeedQFunctionContext to restore 764 @param[in,out] data Data to restore 765 766 @return An error code: 0 - success, otherwise - failure 767 768 @ref User 769 **/ 770 int CeedQFunctionContextRestoreData(CeedQFunctionContext ctx, void *data) { 771 if (ctx->state % 2 != 1) { 772 // LCOV_EXCL_START 773 return CeedError(ctx->ceed, 1, "Cannot restore CeedQFunctionContext array access, access was not granted"); 774 // LCOV_EXCL_STOP 775 } 776 777 if (ctx->RestoreData) { 778 CeedCall(ctx->RestoreData(ctx)); 779 } 780 *(void **)data = NULL; 781 ctx->state++; 782 return CEED_ERROR_SUCCESS; 783 } 784 785 /** 786 @brief Restore data obtained using @ref CeedQFunctionContextGetDataRead() 787 788 @param[in] ctx CeedQFunctionContext to restore 789 @param[in,out] data Data to restore 790 791 @return An error code: 0 - success, otherwise - failure 792 793 @ref User 794 **/ 795 int CeedQFunctionContextRestoreDataRead(CeedQFunctionContext ctx, void *data) { 796 if (ctx->num_readers == 0) { 797 // LCOV_EXCL_START 798 return CeedError(ctx->ceed, 1, "Cannot restore CeedQFunctionContext array access, access was not granted"); 799 // LCOV_EXCL_STOP 800 } 801 802 ctx->num_readers--; 803 if (ctx->num_readers == 0 && ctx->RestoreDataRead) { 804 CeedCall(ctx->RestoreDataRead(ctx)); 805 } 806 *(void **)data = NULL; 807 808 return CEED_ERROR_SUCCESS; 809 } 810 811 /** 812 @brief Register QFunctionContext a field holding a double precision value 813 814 @param[in,out] ctx CeedQFunctionContext 815 @param[in] field_name Name of field to register 816 @param[in] field_offset Offset of field to register 817 @param[in] num_values Number of values to register, must be contiguous in memory 818 @param[in] field_description Description of field, or NULL for none 819 820 @return An error code: 0 - success, otherwise - failure 821 822 @ref User 823 **/ 824 int CeedQFunctionContextRegisterDouble(CeedQFunctionContext ctx, const char *field_name, size_t field_offset, size_t num_values, 825 const char *field_description) { 826 return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, field_description, CEED_CONTEXT_FIELD_DOUBLE, sizeof(double), num_values); 827 } 828 829 /** 830 @brief Register QFunctionContext a field holding a int32 value 831 832 @param[in,out] ctx CeedQFunctionContext 833 @param[in] field_name Name of field to register 834 @param[in] field_offset Offset of field to register 835 @param[in] num_values Number of values to register, must be contiguous in memory 836 @param[in] field_description Description of field, or NULL for none 837 838 @return An error code: 0 - success, otherwise - failure 839 840 @ref User 841 **/ 842 int CeedQFunctionContextRegisterInt32(CeedQFunctionContext ctx, const char *field_name, size_t field_offset, size_t num_values, 843 const char *field_description) { 844 return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, field_description, CEED_CONTEXT_FIELD_INT32, sizeof(int), num_values); 845 } 846 847 /** 848 @brief Get labels for all registered QFunctionContext fields 849 850 @param[in] ctx CeedQFunctionContext 851 @param[out] field_labels Variable to hold array of field labels 852 @param[out] num_fields Length of field descriptions array 853 854 @return An error code: 0 - success, otherwise - failure 855 856 @ref User 857 **/ 858 int CeedQFunctionContextGetAllFieldLabels(CeedQFunctionContext ctx, const CeedContextFieldLabel **field_labels, CeedInt *num_fields) { 859 *field_labels = ctx->field_labels; 860 *num_fields = ctx->num_fields; 861 return CEED_ERROR_SUCCESS; 862 } 863 864 /** 865 @brief Get the descriptive information about a CeedContextFieldLabel 866 867 @param[in] label CeedContextFieldLabel 868 @param[out] field_name Name of labeled field 869 @param[out] field_description Description of field, or NULL for none 870 @param[out] num_values Number of values registered 871 @param[out] field_type CeedContextFieldType 872 873 @return An error code: 0 - success, otherwise - failure 874 875 @ref User 876 **/ 877 int CeedContextFieldLabelGetDescription(CeedContextFieldLabel label, const char **field_name, const char **field_description, size_t *num_values, 878 CeedContextFieldType *field_type) { 879 if (field_name) *field_name = label->name; 880 if (field_description) *field_description = label->description; 881 if (num_values) *num_values = label->num_values; 882 if (field_type) *field_type = label->type; 883 return CEED_ERROR_SUCCESS; 884 } 885 886 /** 887 @brief Get data size for a Context 888 889 @param[in] ctx CeedQFunctionContext 890 @param[out] ctx_size Variable to store size of context data values 891 892 @return An error code: 0 - success, otherwise - failure 893 894 @ref User 895 **/ 896 int CeedQFunctionContextGetContextSize(CeedQFunctionContext ctx, size_t *ctx_size) { 897 *ctx_size = ctx->ctx_size; 898 return CEED_ERROR_SUCCESS; 899 } 900 901 /** 902 @brief View a CeedQFunctionContext 903 904 @param[in] ctx CeedQFunctionContext to view 905 @param[in] stream Filestream to write to 906 907 @return An error code: 0 - success, otherwise - failure 908 909 @ref User 910 **/ 911 int CeedQFunctionContextView(CeedQFunctionContext ctx, FILE *stream) { 912 fprintf(stream, "CeedQFunctionContext\n"); 913 fprintf(stream, " Context Data Size: %ld\n", ctx->ctx_size); 914 for (CeedInt i = 0; i < ctx->num_fields; i++) { 915 // LCOV_EXCL_START 916 fprintf(stream, " Labeled %s field: %s\n", CeedContextFieldTypes[ctx->field_labels[i]->type], ctx->field_labels[i]->name); 917 // LCOV_EXCL_STOP 918 } 919 return CEED_ERROR_SUCCESS; 920 } 921 922 /** 923 @brief Set additional destroy routine for CeedQFunctionContext user data 924 925 @param[in,out] ctx CeedQFunctionContext to set user destroy function 926 @param[in] f_mem_type Memory type to use when passing data into `f` 927 @param[in] f Additional routine to use to destroy user data 928 929 @return An error code: 0 - success, otherwise - failure 930 931 @ref User 932 **/ 933 int CeedQFunctionContextSetDataDestroy(CeedQFunctionContext ctx, CeedMemType f_mem_type, CeedQFunctionContextDataDestroyUser f) { 934 if (!f) { 935 // LCOV_EXCL_START 936 return CeedError(ctx->ceed, 1, "Must provide valid callback function for destroying user data"); 937 // LCOV_EXCL_STOP 938 } 939 ctx->data_destroy_mem_type = f_mem_type; 940 ctx->data_destroy_function = f; 941 return CEED_ERROR_SUCCESS; 942 } 943 944 /** 945 @brief Destroy a CeedQFunctionContext 946 947 @param[in,out] ctx CeedQFunctionContext to destroy 948 949 @return An error code: 0 - success, otherwise - failure 950 951 @ref User 952 **/ 953 int CeedQFunctionContextDestroy(CeedQFunctionContext *ctx) { 954 if (!*ctx || --(*ctx)->ref_count > 0) { 955 *ctx = NULL; 956 return CEED_ERROR_SUCCESS; 957 } 958 if ((*ctx) && ((*ctx)->state % 2) == 1) { 959 // LCOV_EXCL_START 960 return CeedError((*ctx)->ceed, 1, "Cannot destroy CeedQFunctionContext, the access lock is in use"); 961 // LCOV_EXCL_STOP 962 } 963 964 CeedCall(CeedQFunctionContextDestroyData(*ctx)); 965 if ((*ctx)->Destroy) CeedCall((*ctx)->Destroy(*ctx)); 966 for (CeedInt i = 0; i < (*ctx)->num_fields; i++) { 967 CeedCall(CeedFree(&(*ctx)->field_labels[i]->name)); 968 CeedCall(CeedFree(&(*ctx)->field_labels[i]->description)); 969 CeedCall(CeedFree(&(*ctx)->field_labels[i])); 970 } 971 CeedCall(CeedFree(&(*ctx)->field_labels)); 972 CeedCall(CeedDestroy(&(*ctx)->ceed)); 973 CeedCall(CeedFree(ctx)); 974 975 return CEED_ERROR_SUCCESS; 976 } 977 978 /// @} 979