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