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