1 // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors. 2 // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 3 // 4 // SPDX-License-Identifier: BSD-2-Clause 5 // 6 // This file is part of CEED: http://github.com/ceed 7 8 #include <ceed-impl.h> 9 #include <ceed.h> 10 #include <ceed/backend.h> 11 #include <stdbool.h> 12 #include <stdint.h> 13 #include <stdio.h> 14 #include <string.h> 15 16 /// @file 17 /// Implementation of public CeedQFunctionContext interfaces 18 19 /// ---------------------------------------------------------------------------- 20 /// CeedQFunctionContext Library Internal Functions 21 /// ---------------------------------------------------------------------------- 22 /// @addtogroup CeedQFunctionDeveloper 23 /// @{ 24 25 /** 26 @brief Get index for QFunctionContext field 27 28 @param[in] ctx CeedQFunctionContext 29 @param[in] field_name Name of field 30 @param[out] field_index Index of field, or -1 if field is not registered 31 32 @return An error code: 0 - success, otherwise - failure 33 34 @ref Developer 35 **/ 36 int CeedQFunctionContextGetFieldIndex(CeedQFunctionContext ctx, const char *field_name, CeedInt *field_index) { 37 *field_index = -1; 38 for (CeedInt i = 0; i < ctx->num_fields; i++) { 39 if (!strcmp(ctx->field_labels[i]->name, field_name)) *field_index = i; 40 } 41 return CEED_ERROR_SUCCESS; 42 } 43 44 /** 45 @brief Common function for registering QFunctionContext fields 46 47 @param[in,out] ctx CeedQFunctionContext 48 @param[in] field_name Name of field to register 49 @param[in] field_offset Offset of field to register 50 @param[in] field_description Description of field, or NULL for none 51 @param[in] field_type Field data type, such as double or int32 52 @param[in] field_size Size of field, in bytes 53 @param[in] num_values Number of values to register, must be contiguous in memory 54 55 @return An error code: 0 - success, otherwise - failure 56 57 @ref Developer 58 **/ 59 int CeedQFunctionContextRegisterGeneric(CeedQFunctionContext ctx, const char *field_name, size_t field_offset, const char *field_description, 60 CeedContextFieldType field_type, size_t field_size, size_t num_values) { 61 // Check for duplicate 62 CeedInt field_index = -1; 63 CeedCall(CeedQFunctionContextGetFieldIndex(ctx, field_name, &field_index)); 64 CeedCheck(field_index == -1, ctx->ceed, CEED_ERROR_UNSUPPORTED, "QFunctionContext field with name \"%s\" already registered", field_name); 65 66 // Allocate space for field data 67 if (ctx->num_fields == 0) { 68 CeedCall(CeedCalloc(1, &ctx->field_labels)); 69 ctx->max_fields = 1; 70 } else if (ctx->num_fields == ctx->max_fields) { 71 CeedCall(CeedRealloc(2 * ctx->max_fields, &ctx->field_labels)); 72 ctx->max_fields *= 2; 73 } 74 CeedCall(CeedCalloc(1, &ctx->field_labels[ctx->num_fields])); 75 76 // Copy field data 77 CeedCall(CeedStringAllocCopy(field_name, (char **)&ctx->field_labels[ctx->num_fields]->name)); 78 CeedCall(CeedStringAllocCopy(field_description, (char **)&ctx->field_labels[ctx->num_fields]->description)); 79 ctx->field_labels[ctx->num_fields]->type = field_type; 80 ctx->field_labels[ctx->num_fields]->offset = field_offset; 81 ctx->field_labels[ctx->num_fields]->size = field_size * num_values; 82 ctx->field_labels[ctx->num_fields]->num_values = num_values; 83 ctx->num_fields++; 84 return CEED_ERROR_SUCCESS; 85 } 86 87 /** 88 @brief Destroy user data held by CeedQFunctionContext, using function set by CeedQFunctionContextSetDataDestroy, if applicable 89 90 @param[in,out] ctx CeedQFunctionContext to destroy user data 91 92 @return An error code: 0 - success, otherwise - failure 93 94 @ref Developer 95 **/ 96 static int CeedQFunctionContextDestroyData(CeedQFunctionContext ctx) { 97 if (ctx->DataDestroy) { 98 CeedCall(ctx->DataDestroy(ctx)); 99 } else { 100 CeedQFunctionContextDataDestroyUser data_destroy_function; 101 CeedMemType data_destroy_mem_type; 102 103 CeedCall(CeedQFunctionContextGetDataDestroy(ctx, &data_destroy_mem_type, &data_destroy_function)); 104 if (data_destroy_function) { 105 void *data; 106 107 CeedCall(CeedQFunctionContextGetData(ctx, data_destroy_mem_type, &data)); 108 CeedCall(data_destroy_function(data)); 109 CeedCall(CeedQFunctionContextRestoreData(ctx, &data)); 110 } 111 } 112 113 return CEED_ERROR_SUCCESS; 114 } 115 116 /// @} 117 118 /// ---------------------------------------------------------------------------- 119 /// CeedQFunctionContext Backend API 120 /// ---------------------------------------------------------------------------- 121 /// @addtogroup CeedQFunctionBackend 122 /// @{ 123 124 /** 125 @brief Get the Ceed associated with a CeedQFunctionContext 126 127 @param[in] ctx CeedQFunctionContext 128 @param[out] ceed Variable to store Ceed 129 130 @return An error code: 0 - success, otherwise - failure 131 132 @ref Backend 133 **/ 134 int CeedQFunctionContextGetCeed(CeedQFunctionContext ctx, Ceed *ceed) { 135 *ceed = ctx->ceed; 136 return CEED_ERROR_SUCCESS; 137 } 138 139 /** 140 @brief Check for valid data in a CeedQFunctionContext 141 142 @param[in] ctx CeedQFunctionContext to check validity 143 @param[out] has_valid_data Variable to store validity 144 145 @return An error code: 0 - success, otherwise - failure 146 147 @ref Backend 148 **/ 149 int CeedQFunctionContextHasValidData(CeedQFunctionContext ctx, bool *has_valid_data) { 150 CeedCheck(ctx->HasValidData, ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support HasValidData"); 151 CeedCall(ctx->HasValidData(ctx, has_valid_data)); 152 return CEED_ERROR_SUCCESS; 153 } 154 155 /** 156 @brief Check for borrowed data of a specific CeedMemType in a CeedQFunctionContext 157 158 @param[in] ctx CeedQFunctionContext to check 159 @param[in] mem_type Memory type to check 160 @param[out] has_borrowed_data_of_type Variable to store result 161 162 @return An error code: 0 - success, otherwise - failure 163 164 @ref Backend 165 **/ 166 int CeedQFunctionContextHasBorrowedDataOfType(CeedQFunctionContext ctx, CeedMemType mem_type, bool *has_borrowed_data_of_type) { 167 CeedCheck(ctx->HasBorrowedDataOfType, ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support HasBorrowedDataOfType"); 168 CeedCall(ctx->HasBorrowedDataOfType(ctx, mem_type, has_borrowed_data_of_type)); 169 return CEED_ERROR_SUCCESS; 170 } 171 172 /** 173 @brief Get the state of a CeedQFunctionContext 174 175 @param[in] ctx CeedQFunctionContext to retrieve state 176 @param[out] state Variable to store state 177 178 @return An error code: 0 - success, otherwise - failure 179 180 @ref Backend 181 **/ 182 int CeedQFunctionContextGetState(CeedQFunctionContext ctx, uint64_t *state) { 183 *state = ctx->state; 184 return CEED_ERROR_SUCCESS; 185 } 186 187 /** 188 @brief Get backend data of a CeedQFunctionContext 189 190 @param[in] ctx CeedQFunctionContext 191 @param[out] data Variable to store data 192 193 @return An error code: 0 - success, otherwise - failure 194 195 @ref Backend 196 **/ 197 int CeedQFunctionContextGetBackendData(CeedQFunctionContext ctx, void *data) { 198 *(void **)data = ctx->data; 199 return CEED_ERROR_SUCCESS; 200 } 201 202 /** 203 @brief Set backend data of a CeedQFunctionContext 204 205 @param[in,out] ctx CeedQFunctionContext 206 @param[in] data Data to set 207 208 @return An error code: 0 - success, otherwise - failure 209 210 @ref Backend 211 **/ 212 int CeedQFunctionContextSetBackendData(CeedQFunctionContext ctx, void *data) { 213 ctx->data = data; 214 return CEED_ERROR_SUCCESS; 215 } 216 217 /** 218 @brief Get label for a registered QFunctionContext field, or `NULL` if no field has been registered with this `field_name` 219 220 @param[in] ctx CeedQFunctionContext 221 @param[in] field_name Name of field to retrieve label 222 @param[out] field_label Variable to field label 223 224 @return An error code: 0 - success, otherwise - failure 225 226 @ref Backend 227 **/ 228 int CeedQFunctionContextGetFieldLabel(CeedQFunctionContext ctx, const char *field_name, CeedContextFieldLabel *field_label) { 229 CeedInt field_index; 230 CeedCall(CeedQFunctionContextGetFieldIndex(ctx, field_name, &field_index)); 231 232 if (field_index != -1) { 233 *field_label = ctx->field_labels[field_index]; 234 } else { 235 *field_label = NULL; 236 } 237 238 return CEED_ERROR_SUCCESS; 239 } 240 241 /** 242 @brief Set QFunctionContext field 243 244 @param[in,out] ctx CeedQFunctionContext 245 @param[in] field_label Label of field to set 246 @param[in] field_type Type of field to set 247 @param[in] values Value to set 248 249 @return An error code: 0 - success, otherwise - failure 250 251 @ref Backend 252 **/ 253 int CeedQFunctionContextSetGeneric(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, CeedContextFieldType field_type, void *values) { 254 // Check field type 255 CeedCheck(field_label->type == field_type, ctx->ceed, CEED_ERROR_UNSUPPORTED, 256 "QFunctionContext field with name \"%s\" registered as %s, not registered as %s", field_label->name, 257 CeedContextFieldTypes[field_label->type], CeedContextFieldTypes[field_type]); 258 259 char *data; 260 CeedCall(CeedQFunctionContextGetData(ctx, CEED_MEM_HOST, &data)); 261 memcpy(&data[field_label->offset], values, field_label->size); 262 CeedCall(CeedQFunctionContextRestoreData(ctx, &data)); 263 264 return CEED_ERROR_SUCCESS; 265 } 266 267 /** 268 @brief Get QFunctionContext field data, read-only 269 270 @param[in] ctx CeedQFunctionContext 271 @param[in] field_label Label of field to read 272 @param[in] field_type Type of field to read 273 @param[out] num_values Number of values in the field label 274 @param[out] values Pointer to context values 275 276 @return An error code: 0 - success, otherwise - failure 277 278 @ref Backend 279 **/ 280 int CeedQFunctionContextGetGenericRead(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, CeedContextFieldType field_type, 281 size_t *num_values, void *values) { 282 // Check field type 283 CeedCheck(field_label->type == field_type, ctx->ceed, CEED_ERROR_UNSUPPORTED, 284 "QFunctionContext field with name \"%s\" registered as %s, not registered as %s", field_label->name, 285 CeedContextFieldTypes[field_label->type], CeedContextFieldTypes[field_type]); 286 287 char *data; 288 CeedCall(CeedQFunctionContextGetDataRead(ctx, CEED_MEM_HOST, &data)); 289 *(void **)values = &data[field_label->offset]; 290 switch (field_type) { 291 case CEED_CONTEXT_FIELD_INT32: 292 *num_values = field_label->size / sizeof(int); 293 break; 294 case CEED_CONTEXT_FIELD_DOUBLE: 295 *num_values = field_label->size / sizeof(double); 296 break; 297 } 298 299 return CEED_ERROR_SUCCESS; 300 } 301 302 /** 303 @brief Restore QFunctionContext field data, read-only 304 305 @param[in] ctx CeedQFunctionContext 306 @param[in] field_label Label of field to restore 307 @param[in] field_type Type of field to restore 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 CeedQFunctionContextRestoreGenericRead(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, CeedContextFieldType field_type, 315 void *values) { 316 // Check field type 317 CeedCheck(field_label->type == field_type, ctx->ceed, CEED_ERROR_UNSUPPORTED, 318 "QFunctionContext field with name \"%s\" registered as %s, not registered as %s", field_label->name, 319 CeedContextFieldTypes[field_label->type], CeedContextFieldTypes[field_type]); 320 321 CeedCall(CeedQFunctionContextRestoreDataRead(ctx, values)); 322 323 return CEED_ERROR_SUCCESS; 324 } 325 326 /** 327 @brief Set QFunctionContext field holding a double precision value 328 329 @param[in,out] ctx CeedQFunctionContext 330 @param[in] field_label Label for field to set 331 @param[in] values Values to set 332 333 @return An error code: 0 - success, otherwise - failure 334 335 @ref Backend 336 **/ 337 int CeedQFunctionContextSetDouble(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, double *values) { 338 CeedCheck(field_label, ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label"); 339 CeedCall(CeedQFunctionContextSetGeneric(ctx, field_label, CEED_CONTEXT_FIELD_DOUBLE, values)); 340 return CEED_ERROR_SUCCESS; 341 } 342 343 /** 344 @brief Get QFunctionContext field holding a double precision value, read-only 345 346 @param[in] ctx CeedQFunctionContext 347 @param[in] field_label Label for field to get 348 @param[out] num_values Number of values in the field label 349 @param[out] values Pointer to context values 350 351 @return An error code: 0 - success, otherwise - failure 352 353 @ref Backend 354 **/ 355 int CeedQFunctionContextGetDoubleRead(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, size_t *num_values, const double **values) { 356 CeedCheck(field_label, ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label"); 357 CeedCall(CeedQFunctionContextGetGenericRead(ctx, field_label, CEED_CONTEXT_FIELD_DOUBLE, num_values, values)); 358 return CEED_ERROR_SUCCESS; 359 } 360 361 /** 362 @brief Restore QFunctionContext field holding a double precision value, read-only 363 364 @param[in] ctx CeedQFunctionContext 365 @param[in] field_label Label for field to restore 366 @param[out] values Pointer to context values 367 368 @return An error code: 0 - success, otherwise - failure 369 370 @ref Backend 371 **/ 372 int CeedQFunctionContextRestoreDoubleRead(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, const double **values) { 373 CeedCheck(field_label, ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label"); 374 CeedCall(CeedQFunctionContextRestoreGenericRead(ctx, field_label, CEED_CONTEXT_FIELD_DOUBLE, values)); 375 return CEED_ERROR_SUCCESS; 376 } 377 378 /** 379 @brief Set QFunctionContext field holding an int32 value 380 381 @param[in,out] ctx CeedQFunctionContext 382 @param[in] field_label Label for field to set 383 @param[in] values Values to set 384 385 @return An error code: 0 - success, otherwise - failure 386 387 @ref Backend 388 **/ 389 int CeedQFunctionContextSetInt32(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, int *values) { 390 CeedCheck(field_label, ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label"); 391 CeedCall(CeedQFunctionContextSetGeneric(ctx, field_label, CEED_CONTEXT_FIELD_INT32, values)); 392 return CEED_ERROR_SUCCESS; 393 } 394 395 /** 396 @brief Get QFunctionContext field holding a int32 value, read-only 397 398 @param[in] ctx CeedQFunctionContext 399 @param[in] field_label Label for field to get 400 @param[out] num_values Number of values in the field label 401 @param[out] values Pointer to context values 402 403 @return An error code: 0 - success, otherwise - failure 404 405 @ref Backend 406 **/ 407 int CeedQFunctionContextGetInt32Read(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, size_t *num_values, const int **values) { 408 CeedCheck(field_label, ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label"); 409 CeedCall(CeedQFunctionContextGetGenericRead(ctx, field_label, CEED_CONTEXT_FIELD_INT32, num_values, values)); 410 return CEED_ERROR_SUCCESS; 411 } 412 413 /** 414 @brief Restore QFunctionContext field holding a int32 value, read-only 415 416 @param[in] ctx CeedQFunctionContext 417 @param[in] field_label Label for field to restore 418 @param[out] values Pointer to context values 419 420 @return An error code: 0 - success, otherwise - failure 421 422 @ref Backend 423 **/ 424 int CeedQFunctionContextRestoreInt32Read(CeedQFunctionContext ctx, CeedContextFieldLabel field_label, const int **values) { 425 CeedCheck(field_label, ctx->ceed, CEED_ERROR_UNSUPPORTED, "Invalid field label"); 426 CeedCall(CeedQFunctionContextRestoreGenericRead(ctx, field_label, CEED_CONTEXT_FIELD_INT32, values)); 427 return CEED_ERROR_SUCCESS; 428 } 429 430 /** 431 @brief Get additional destroy routine for CeedQFunctionContext user data 432 433 @param[in] ctx CeedQFunctionContext to get user destroy function 434 @param[out] f_mem_type Memory type to use when passing data into `f` 435 @param[out] f Additional routine to use to destroy user data 436 437 @return An error code: 0 - success, otherwise - failure 438 439 @ref Backend 440 **/ 441 int CeedQFunctionContextGetDataDestroy(CeedQFunctionContext ctx, CeedMemType *f_mem_type, CeedQFunctionContextDataDestroyUser *f) { 442 if (f_mem_type) *f_mem_type = ctx->data_destroy_mem_type; 443 if (f) *f = ctx->data_destroy_function; 444 return CEED_ERROR_SUCCESS; 445 } 446 447 /** 448 @brief Increment the reference counter for a CeedQFunctionContext 449 450 @param[in,out] ctx CeedQFunctionContext to increment the reference counter 451 452 @return An error code: 0 - success, otherwise - failure 453 454 @ref Backend 455 **/ 456 int CeedQFunctionContextReference(CeedQFunctionContext ctx) { 457 ctx->ref_count++; 458 return CEED_ERROR_SUCCESS; 459 } 460 461 /// @} 462 463 /// ---------------------------------------------------------------------------- 464 /// CeedQFunctionContext Public API 465 /// ---------------------------------------------------------------------------- 466 /// @addtogroup CeedQFunctionUser 467 /// @{ 468 469 /** 470 @brief Create a CeedQFunctionContext for storing CeedQFunction user context data 471 472 @param[in] ceed Ceed object where the CeedQFunctionContext will be created 473 @param[out] ctx Address of the variable where the newly created CeedQFunctionContext will be stored 474 475 @return An error code: 0 - success, otherwise - failure 476 477 @ref User 478 **/ 479 int CeedQFunctionContextCreate(Ceed ceed, CeedQFunctionContext *ctx) { 480 if (!ceed->QFunctionContextCreate) { 481 Ceed delegate; 482 483 CeedCall(CeedGetObjectDelegate(ceed, &delegate, "Context")); 484 CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ContextCreate"); 485 CeedCall(CeedQFunctionContextCreate(delegate, ctx)); 486 return CEED_ERROR_SUCCESS; 487 } 488 489 CeedCall(CeedCalloc(1, ctx)); 490 (*ctx)->ceed = ceed; 491 CeedCall(CeedReference(ceed)); 492 (*ctx)->ref_count = 1; 493 CeedCall(ceed->QFunctionContextCreate(*ctx)); 494 return CEED_ERROR_SUCCESS; 495 } 496 497 /** 498 @brief Copy the pointer to a CeedQFunctionContext. 499 500 Both pointers should be destroyed with `CeedQFunctionContextDestroy()`. 501 502 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 503 CeedQFunctionContext. This CeedQFunctionContext will be destroyed if `ctx_copy` is the only reference to this CeedQFunctionContext. 504 505 @param[in] ctx CeedQFunctionContext to copy reference to 506 @param[in,out] ctx_copy Variable to store copied reference 507 508 @return An error code: 0 - success, otherwise - failure 509 510 @ref User 511 **/ 512 int CeedQFunctionContextReferenceCopy(CeedQFunctionContext ctx, CeedQFunctionContext *ctx_copy) { 513 CeedCall(CeedQFunctionContextReference(ctx)); 514 CeedCall(CeedQFunctionContextDestroy(ctx_copy)); 515 *ctx_copy = ctx; 516 return CEED_ERROR_SUCCESS; 517 } 518 519 /** 520 @brief Set the data used by a CeedQFunctionContext, freeing any previously allocated data if applicable. 521 522 The backend may copy values to a different memtype, such as during @ref CeedQFunctionApply(). 523 See also @ref CeedQFunctionContextTakeData(). 524 525 @param[in,out] ctx CeedQFunctionContext 526 @param[in] mem_type Memory type of the data being passed 527 @param[in] copy_mode Copy mode for the data 528 @param[in] size Size of data, in bytes 529 @param[in] data Data to be used 530 531 @return An error code: 0 - success, otherwise - failure 532 533 @ref User 534 **/ 535 int CeedQFunctionContextSetData(CeedQFunctionContext ctx, CeedMemType mem_type, CeedCopyMode copy_mode, size_t size, void *data) { 536 CeedCheck(ctx->SetData, ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support ContextSetData"); 537 CeedCheck(ctx->state % 2 == 0, ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use"); 538 539 CeedCall(CeedQFunctionContextDestroyData(ctx)); 540 ctx->ctx_size = size; 541 CeedCall(ctx->SetData(ctx, mem_type, copy_mode, data)); 542 ctx->state += 2; 543 return CEED_ERROR_SUCCESS; 544 } 545 546 /** 547 @brief Take ownership of the data in a CeedQFunctionContext via the specified memory type. 548 549 The caller is responsible for managing and freeing the memory. 550 551 @param[in] ctx CeedQFunctionContext to access 552 @param[in] mem_type Memory type on which to access the data. 553 If the backend uses a different memory type, this will perform a copy. 554 @param[out] data Data on memory type mem_type 555 556 @return An error code: 0 - success, otherwise - failure 557 558 @ref User 559 **/ 560 int CeedQFunctionContextTakeData(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) { 561 bool has_valid_data = true; 562 CeedCall(CeedQFunctionContextHasValidData(ctx, &has_valid_data)); 563 CeedCheck(has_valid_data, ctx->ceed, CEED_ERROR_BACKEND, "CeedQFunctionContext has no valid data to take, must set data"); 564 565 CeedCheck(ctx->TakeData, ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support TakeData"); 566 CeedCheck(ctx->state % 2 == 0, ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use"); 567 568 bool has_borrowed_data_of_type = true; 569 CeedCall(CeedQFunctionContextHasBorrowedDataOfType(ctx, mem_type, &has_borrowed_data_of_type)); 570 CeedCheck(has_borrowed_data_of_type, ctx->ceed, CEED_ERROR_BACKEND, 571 "CeedQFunctionContext has no borrowed %s data, must set data with CeedQFunctionContextSetData", CeedMemTypes[mem_type]); 572 573 void *temp_data = NULL; 574 CeedCall(ctx->TakeData(ctx, mem_type, &temp_data)); 575 if (data) (*(void **)data) = temp_data; 576 return CEED_ERROR_SUCCESS; 577 } 578 579 /** 580 @brief Get read/write access to a CeedQFunctionContext via the specified memory type. 581 582 Restore access with @ref CeedQFunctionContextRestoreData(). 583 584 @param[in] ctx CeedQFunctionContext to access 585 @param[in] mem_type Memory type on which to access the data. 586 If the backend uses a different memory type, this will perform a copy. 587 @param[out] data Data on memory type mem_type 588 589 @note The CeedQFunctionContextGetData() and @ref CeedQFunctionContextRestoreData() functions provide access to array pointers in the desired memory 590 space. 591 Pairing get/restore allows the Context to track access. 592 593 @return An error code: 0 - success, otherwise - failure 594 595 @ref User 596 **/ 597 int CeedQFunctionContextGetData(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) { 598 CeedCheck(ctx->GetData, ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetData"); 599 CeedCheck(ctx->state % 2 == 0, ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use"); 600 CeedCheck(ctx->num_readers == 0, ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, a process has read access"); 601 602 bool has_valid_data = true; 603 CeedCall(CeedQFunctionContextHasValidData(ctx, &has_valid_data)); 604 CeedCheck(has_valid_data, ctx->ceed, CEED_ERROR_BACKEND, "CeedQFunctionContext has no valid data to get, must set data"); 605 606 CeedCall(ctx->GetData(ctx, mem_type, data)); 607 ctx->state++; 608 return CEED_ERROR_SUCCESS; 609 } 610 611 /** 612 @brief Get read only access to a CeedQFunctionContext via the specified memory type. 613 614 Restore access with @ref CeedQFunctionContextRestoreData(). 615 616 @param[in] ctx CeedQFunctionContext to access 617 @param[in] mem_type Memory type on which to access the data. 618 If the backend uses a different memory type, this will perform a copy. 619 @param[out] data Data on memory type mem_type 620 621 @note The CeedQFunctionContextGetDataRead() and @ref CeedQFunctionContextRestoreDataRead() functions provide access to array pointers in the desired 622 memory space. 623 Pairing get/restore allows the Context to track access. 624 625 @return An error code: 0 - success, otherwise - failure 626 627 @ref User 628 **/ 629 int CeedQFunctionContextGetDataRead(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) { 630 CeedCheck(ctx->GetDataRead, ctx->ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support GetDataRead"); 631 CeedCheck(ctx->state % 2 == 0, ctx->ceed, 1, "Cannot grant CeedQFunctionContext data access, the access lock is already in use"); 632 633 bool has_valid_data = true; 634 CeedCall(CeedQFunctionContextHasValidData(ctx, &has_valid_data)); 635 CeedCheck(has_valid_data, ctx->ceed, CEED_ERROR_BACKEND, "CeedQFunctionContext has no valid data to get, must set data"); 636 637 CeedCall(ctx->GetDataRead(ctx, mem_type, data)); 638 ctx->num_readers++; 639 return CEED_ERROR_SUCCESS; 640 } 641 642 /** 643 @brief Restore data obtained using @ref CeedQFunctionContextGetData() 644 645 @param[in] ctx CeedQFunctionContext to restore 646 @param[in,out] data Data to restore 647 648 @return An error code: 0 - success, otherwise - failure 649 650 @ref User 651 **/ 652 int CeedQFunctionContextRestoreData(CeedQFunctionContext ctx, void *data) { 653 CeedCheck(ctx->state % 2 == 1, ctx->ceed, 1, "Cannot restore CeedQFunctionContext array access, access was not granted"); 654 655 if (ctx->RestoreData) CeedCall(ctx->RestoreData(ctx)); 656 *(void **)data = NULL; 657 ctx->state++; 658 return CEED_ERROR_SUCCESS; 659 } 660 661 /** 662 @brief Restore data obtained using @ref CeedQFunctionContextGetDataRead() 663 664 @param[in] ctx CeedQFunctionContext to restore 665 @param[in,out] data Data to restore 666 667 @return An error code: 0 - success, otherwise - failure 668 669 @ref User 670 **/ 671 int CeedQFunctionContextRestoreDataRead(CeedQFunctionContext ctx, void *data) { 672 CeedCheck(ctx->num_readers > 0, ctx->ceed, 1, "Cannot restore CeedQFunctionContext array access, access was not granted"); 673 674 ctx->num_readers--; 675 if (ctx->num_readers == 0 && ctx->RestoreDataRead) CeedCall(ctx->RestoreDataRead(ctx)); 676 *(void **)data = NULL; 677 678 return CEED_ERROR_SUCCESS; 679 } 680 681 /** 682 @brief Register QFunctionContext a field holding a double precision value 683 684 @param[in,out] ctx CeedQFunctionContext 685 @param[in] field_name Name of field to register 686 @param[in] field_offset Offset of field to register 687 @param[in] num_values Number of values to register, must be contiguous in memory 688 @param[in] field_description Description of field, or NULL for none 689 690 @return An error code: 0 - success, otherwise - failure 691 692 @ref User 693 **/ 694 int CeedQFunctionContextRegisterDouble(CeedQFunctionContext ctx, const char *field_name, size_t field_offset, size_t num_values, 695 const char *field_description) { 696 return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, field_description, CEED_CONTEXT_FIELD_DOUBLE, sizeof(double), num_values); 697 } 698 699 /** 700 @brief Register QFunctionContext a field holding a int32 value 701 702 @param[in,out] ctx CeedQFunctionContext 703 @param[in] field_name Name of field to register 704 @param[in] field_offset Offset of field to register 705 @param[in] num_values Number of values to register, must be contiguous in memory 706 @param[in] field_description Description of field, or NULL for none 707 708 @return An error code: 0 - success, otherwise - failure 709 710 @ref User 711 **/ 712 int CeedQFunctionContextRegisterInt32(CeedQFunctionContext ctx, const char *field_name, size_t field_offset, size_t num_values, 713 const char *field_description) { 714 return CeedQFunctionContextRegisterGeneric(ctx, field_name, field_offset, field_description, CEED_CONTEXT_FIELD_INT32, sizeof(int), num_values); 715 } 716 717 /** 718 @brief Get labels for all registered QFunctionContext fields 719 720 @param[in] ctx CeedQFunctionContext 721 @param[out] field_labels Variable to hold array of field labels 722 @param[out] num_fields Length of field descriptions array 723 724 @return An error code: 0 - success, otherwise - failure 725 726 @ref User 727 **/ 728 int CeedQFunctionContextGetAllFieldLabels(CeedQFunctionContext ctx, const CeedContextFieldLabel **field_labels, CeedInt *num_fields) { 729 *field_labels = ctx->field_labels; 730 *num_fields = ctx->num_fields; 731 return CEED_ERROR_SUCCESS; 732 } 733 734 /** 735 @brief Get the descriptive information about a CeedContextFieldLabel 736 737 @param[in] label CeedContextFieldLabel 738 @param[out] field_name Name of labeled field 739 @param[out] field_description Description of field, or NULL for none 740 @param[out] num_values Number of values registered 741 @param[out] field_type CeedContextFieldType 742 743 @return An error code: 0 - success, otherwise - failure 744 745 @ref User 746 **/ 747 int CeedContextFieldLabelGetDescription(CeedContextFieldLabel label, const char **field_name, const char **field_description, size_t *num_values, 748 CeedContextFieldType *field_type) { 749 if (field_name) *field_name = label->name; 750 if (field_description) *field_description = label->description; 751 if (num_values) *num_values = label->num_values; 752 if (field_type) *field_type = label->type; 753 return CEED_ERROR_SUCCESS; 754 } 755 756 /** 757 @brief Get data size for a Context 758 759 @param[in] ctx CeedQFunctionContext 760 @param[out] ctx_size Variable to store size of context data values 761 762 @return An error code: 0 - success, otherwise - failure 763 764 @ref User 765 **/ 766 int CeedQFunctionContextGetContextSize(CeedQFunctionContext ctx, size_t *ctx_size) { 767 *ctx_size = ctx->ctx_size; 768 return CEED_ERROR_SUCCESS; 769 } 770 771 /** 772 @brief View a CeedQFunctionContext 773 774 @param[in] ctx CeedQFunctionContext to view 775 @param[in] stream Filestream to write to 776 777 @return An error code: 0 - success, otherwise - failure 778 779 @ref User 780 **/ 781 int CeedQFunctionContextView(CeedQFunctionContext ctx, FILE *stream) { 782 fprintf(stream, "CeedQFunctionContext\n"); 783 fprintf(stream, " Context Data Size: %ld\n", ctx->ctx_size); 784 for (CeedInt i = 0; i < ctx->num_fields; i++) { 785 // LCOV_EXCL_START 786 fprintf(stream, " Labeled %s field: %s\n", CeedContextFieldTypes[ctx->field_labels[i]->type], ctx->field_labels[i]->name); 787 // LCOV_EXCL_STOP 788 } 789 return CEED_ERROR_SUCCESS; 790 } 791 792 /** 793 @brief Set additional destroy routine for CeedQFunctionContext user data 794 795 @param[in,out] ctx CeedQFunctionContext to set user destroy function 796 @param[in] f_mem_type Memory type to use when passing data into `f` 797 @param[in] f Additional routine to use to destroy user data 798 799 @return An error code: 0 - success, otherwise - failure 800 801 @ref User 802 **/ 803 int CeedQFunctionContextSetDataDestroy(CeedQFunctionContext ctx, CeedMemType f_mem_type, CeedQFunctionContextDataDestroyUser f) { 804 CeedCheck(f, ctx->ceed, 1, "Must provide valid callback function for destroying user data"); 805 ctx->data_destroy_mem_type = f_mem_type; 806 ctx->data_destroy_function = f; 807 return CEED_ERROR_SUCCESS; 808 } 809 810 /** 811 @brief Destroy a CeedQFunctionContext 812 813 @param[in,out] ctx CeedQFunctionContext to destroy 814 815 @return An error code: 0 - success, otherwise - failure 816 817 @ref User 818 **/ 819 int CeedQFunctionContextDestroy(CeedQFunctionContext *ctx) { 820 if (!*ctx || --(*ctx)->ref_count > 0) { 821 *ctx = NULL; 822 return CEED_ERROR_SUCCESS; 823 } 824 CeedCheck(((*ctx)->state % 2) == 0, (*ctx)->ceed, 1, "Cannot destroy CeedQFunctionContext, the access lock is in use"); 825 826 CeedCall(CeedQFunctionContextDestroyData(*ctx)); 827 if ((*ctx)->Destroy) CeedCall((*ctx)->Destroy(*ctx)); 828 for (CeedInt i = 0; i < (*ctx)->num_fields; i++) { 829 CeedCall(CeedFree(&(*ctx)->field_labels[i]->name)); 830 CeedCall(CeedFree(&(*ctx)->field_labels[i]->description)); 831 CeedCall(CeedFree(&(*ctx)->field_labels[i])); 832 } 833 CeedCall(CeedFree(&(*ctx)->field_labels)); 834 CeedCall(CeedDestroy(&(*ctx)->ceed)); 835 CeedCall(CeedFree(ctx)); 836 837 return CEED_ERROR_SUCCESS; 838 } 839 840 /// @} 841