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