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