1 // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at 2 // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights 3 // reserved. See files LICENSE and NOTICE for details. 4 // 5 // This file is part of CEED, a collection of benchmarks, miniapps, software 6 // libraries and APIs for efficient high-order finite element and spectral 7 // element discretizations for exascale applications. For more information and 8 // source code availability see http://github.com/ceed. 9 // 10 // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 11 // a collaborative effort of two U.S. Department of Energy organizations (Office 12 // of Science and the National Nuclear Security Administration) responsible for 13 // the planning and preparation of a capable exascale ecosystem, including 14 // software, applications, hardware, advanced system engineering and early 15 // testbed platforms, in support of the nation's exascale computing imperative. 16 17 #include <ceed/ceed.h> 18 #include <ceed/backend.h> 19 #include <ceed-impl.h> 20 #include <stdint.h> 21 #include <stdio.h> 22 23 /// @file 24 /// Implementation of public CeedQFunctionContext interfaces 25 26 /// ---------------------------------------------------------------------------- 27 /// CeedQFunctionContext Backend API 28 /// ---------------------------------------------------------------------------- 29 /// @addtogroup CeedQFunctionBackend 30 /// @{ 31 32 /** 33 @brief Get the Ceed associated with a CeedQFunctionContext 34 35 @param ctx CeedQFunctionContext 36 @param[out] ceed Variable to store Ceed 37 38 @return An error code: 0 - success, otherwise - failure 39 40 @ref Backend 41 **/ 42 int CeedQFunctionContextGetCeed(CeedQFunctionContext ctx, Ceed *ceed) { 43 *ceed = ctx->ceed; 44 return CEED_ERROR_SUCCESS; 45 } 46 47 /** 48 @brief Get the state of a CeedQFunctionContext 49 50 @param ctx CeedQFunctionContext to retrieve state 51 @param[out] state Variable to store state 52 53 @return An error code: 0 - success, otherwise - failure 54 55 @ref Backend 56 **/ 57 int CeedQFunctionContextGetState(CeedQFunctionContext ctx, uint64_t *state) { 58 *state = ctx->state; 59 return CEED_ERROR_SUCCESS; 60 } 61 62 /** 63 @brief Get backend data of a CeedQFunctionContext 64 65 @param ctx CeedQFunctionContext 66 @param[out] data Variable to store data 67 68 @return An error code: 0 - success, otherwise - failure 69 70 @ref Backend 71 **/ 72 int CeedQFunctionContextGetBackendData(CeedQFunctionContext ctx, void *data) { 73 *(void **)data = ctx->data; 74 return CEED_ERROR_SUCCESS; 75 } 76 77 /** 78 @brief Set backend data of a CeedQFunctionContext 79 80 @param[out] ctx CeedQFunctionContext 81 @param data Data to set 82 83 @return An error code: 0 - success, otherwise - failure 84 85 @ref Backend 86 **/ 87 int CeedQFunctionContextSetBackendData(CeedQFunctionContext ctx, void *data) { 88 ctx->data = data; 89 return CEED_ERROR_SUCCESS; 90 } 91 92 /** 93 @brief Increment the reference counter for a CeedQFunctionContext 94 95 @param ctx CeedQFunctionContext to increment the reference counter 96 97 @return An error code: 0 - success, otherwise - failure 98 99 @ref Backend 100 **/ 101 int CeedQFunctionContextReference(CeedQFunctionContext ctx) { 102 ctx->ref_count++; 103 return CEED_ERROR_SUCCESS; 104 } 105 106 /// @} 107 108 /// ---------------------------------------------------------------------------- 109 /// CeedQFunctionContext Public API 110 /// ---------------------------------------------------------------------------- 111 /// @addtogroup CeedQFunctionUser 112 /// @{ 113 114 /** 115 @brief Create a CeedQFunctionContext for storing CeedQFunction user context data 116 117 @param ceed A Ceed object where the CeedQFunctionContext will be created 118 @param[out] ctx Address of the variable where the newly created 119 CeedQFunctionContext will be stored 120 121 @return An error code: 0 - success, otherwise - failure 122 123 @ref User 124 **/ 125 int CeedQFunctionContextCreate(Ceed ceed, CeedQFunctionContext *ctx) { 126 int ierr; 127 128 if (!ceed->QFunctionContextCreate) { 129 Ceed delegate; 130 ierr = CeedGetObjectDelegate(ceed, &delegate, "Context"); CeedChk(ierr); 131 132 if (!delegate) 133 // LCOV_EXCL_START 134 return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 135 "Backend does not support ContextCreate"); 136 // LCOV_EXCL_STOP 137 138 ierr = CeedQFunctionContextCreate(delegate, ctx); CeedChk(ierr); 139 return CEED_ERROR_SUCCESS; 140 } 141 142 ierr = CeedCalloc(1, ctx); CeedChk(ierr); 143 (*ctx)->ceed = ceed; 144 ierr = CeedReference(ceed); CeedChk(ierr); 145 (*ctx)->ref_count = 1; 146 ierr = ceed->QFunctionContextCreate(*ctx); CeedChk(ierr); 147 return CEED_ERROR_SUCCESS; 148 } 149 150 /** 151 @brief Copy the pointer to a CeedQFunctionContext. Both pointers should 152 be destroyed with `CeedQFunctionContextDestroy()`; 153 Note: If `*ctx_copy` is non-NULL, then it is assumed that 154 `*ctx_copy` is a pointer to a CeedQFunctionContext. This 155 CeedQFunctionContext will be destroyed if `*ctx_copy` is the 156 only reference to this CeedQFunctionContext. 157 158 @param ctx CeedQFunctionContext to copy reference to 159 @param[out] ctx_copy Variable to store copied reference 160 161 @return An error code: 0 - success, otherwise - failure 162 163 @ref User 164 **/ 165 int CeedQFunctionContextReferenceCopy(CeedQFunctionContext ctx, 166 CeedQFunctionContext *ctx_copy) { 167 int ierr; 168 169 ierr = CeedQFunctionContextReference(ctx); CeedChk(ierr); 170 ierr = CeedQFunctionContextDestroy(ctx_copy); CeedChk(ierr); 171 *ctx_copy = ctx; 172 return CEED_ERROR_SUCCESS; 173 } 174 175 /** 176 @brief Set the data used by a CeedQFunctionContext, freeing any previously allocated 177 data if applicable. The backend may copy values to a different 178 memtype, such as during @ref CeedQFunctionApply(). 179 See also @ref CeedQFunctionContextTakeData(). 180 181 @param ctx CeedQFunctionContext 182 @param mem_type Memory type of the data being passed 183 @param copy_mode Copy mode for the data 184 @param size Size of data, in bytes 185 @param data Data to be used 186 187 @return An error code: 0 - success, otherwise - failure 188 189 @ref User 190 **/ 191 int CeedQFunctionContextSetData(CeedQFunctionContext ctx, CeedMemType mem_type, 192 CeedCopyMode copy_mode, 193 size_t size, void *data) { 194 int ierr; 195 196 if (!ctx->SetData) 197 // LCOV_EXCL_START 198 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 199 "Backend does not support ContextSetData"); 200 // LCOV_EXCL_STOP 201 202 if (ctx->state % 2 == 1) 203 // LCOV_EXCL_START 204 return CeedError(ctx->ceed, 1, 205 "Cannot grant CeedQFunctionContext data access, the " 206 "access lock is already in use"); 207 // LCOV_EXCL_STOP 208 209 ctx->ctx_size = size; 210 ierr = ctx->SetData(ctx, mem_type, copy_mode, data); CeedChk(ierr); 211 ctx->state += 2; 212 return CEED_ERROR_SUCCESS; 213 } 214 215 /** 216 @brief Take ownership of the data in a CeedQFunctionContext via the specified memory type. 217 The caller is responsible for managing and freeing the memory. 218 219 @param ctx CeedQFunctionContext to access 220 @param mem_type Memory type on which to access the data. If the backend 221 uses a different memory type, this will perform a copy. 222 @param[out] data Data on memory type mem_type 223 224 @return An error code: 0 - success, otherwise - failure 225 226 @ref User 227 **/ 228 int CeedQFunctionContextTakeData(CeedQFunctionContext ctx, CeedMemType mem_type, 229 void *data) { 230 int ierr; 231 232 if (!ctx->TakeData) 233 // LCOV_EXCL_START 234 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 235 "Backend does not support TakeData"); 236 // LCOV_EXCL_STOP 237 238 if (ctx->state % 2 == 1) 239 // LCOV_EXCL_START 240 return CeedError(ctx->ceed, 1, 241 "Cannot grant CeedQFunctionContext data access, the " 242 "access lock is already in use"); 243 // LCOV_EXCL_STOP 244 245 void *temp_data = NULL; 246 ierr = ctx->TakeData(ctx, mem_type, &temp_data); CeedChk(ierr); 247 if (data) (*(void **)data) = temp_data; 248 return CEED_ERROR_SUCCESS; 249 } 250 251 /** 252 @brief Get read/write access to a CeedQFunctionContext via the specified memory type. 253 Restore access with @ref CeedQFunctionContextRestoreData(). 254 255 @param ctx CeedQFunctionContext to access 256 @param mem_type Memory type on which to access the data. If the backend 257 uses a different memory type, this will perform a copy. 258 @param[out] data Data on memory type mem_type 259 260 @note The CeedQFunctionContextGetData() and @ref CeedQFunctionContextRestoreData() functions 261 provide access to array pointers in the desired memory space. Pairing 262 get/restore allows the Context to track access. 263 264 @return An error code: 0 - success, otherwise - failure 265 266 @ref User 267 **/ 268 int CeedQFunctionContextGetData(CeedQFunctionContext ctx, CeedMemType mem_type, 269 void *data) { 270 int ierr; 271 272 if (!ctx->GetData) 273 // LCOV_EXCL_START 274 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 275 "Backend does not support GetData"); 276 // LCOV_EXCL_STOP 277 278 if (ctx->state % 2 == 1) 279 // LCOV_EXCL_START 280 return CeedError(ctx->ceed, 1, 281 "Cannot grant CeedQFunctionContext data access, the " 282 "access lock is already in use"); 283 // LCOV_EXCL_STOP 284 285 ierr = ctx->GetData(ctx, mem_type, data); CeedChk(ierr); 286 ctx->state += 1; 287 return CEED_ERROR_SUCCESS; 288 } 289 290 /** 291 @brief Restore data obtained using @ref CeedQFunctionContextGetData() 292 293 @param ctx CeedQFunctionContext to restore 294 @param data Data to restore 295 296 @return An error code: 0 - success, otherwise - failure 297 298 @ref User 299 **/ 300 int CeedQFunctionContextRestoreData(CeedQFunctionContext ctx, void *data) { 301 int ierr; 302 303 if (!ctx->RestoreData) 304 // LCOV_EXCL_START 305 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 306 "Backend does not support RestoreData"); 307 // LCOV_EXCL_STOP 308 309 if (ctx->state % 2 != 1) 310 // LCOV_EXCL_START 311 return CeedError(ctx->ceed, 1, 312 "Cannot restore CeedQFunctionContext array access, " 313 "access was not granted"); 314 // LCOV_EXCL_STOP 315 316 ierr = ctx->RestoreData(ctx); CeedChk(ierr); 317 *(void **)data = NULL; 318 ctx->state += 1; 319 return CEED_ERROR_SUCCESS; 320 } 321 322 /** 323 @brief Get data size for a Context 324 325 @param ctx CeedQFunctionContext 326 @param[out] ctx_size Variable to store size of context data values 327 328 @return An error code: 0 - success, otherwise - failure 329 330 @ref User 331 **/ 332 int CeedQFunctionContextGetContextSize(CeedQFunctionContext ctx, 333 size_t *ctx_size) { 334 *ctx_size = ctx->ctx_size; 335 return CEED_ERROR_SUCCESS; 336 } 337 338 339 /** 340 @brief View a CeedQFunctionContext 341 342 @param[in] ctx CeedQFunctionContext to view 343 @param[in] stream Filestream to write to 344 345 @return An error code: 0 - success, otherwise - failure 346 347 @ref User 348 **/ 349 int CeedQFunctionContextView(CeedQFunctionContext ctx, FILE *stream) { 350 fprintf(stream, "CeedQFunctionContext\n"); 351 fprintf(stream, " Context Data Size: %ld\n", ctx->ctx_size); 352 return CEED_ERROR_SUCCESS; 353 } 354 355 /** 356 @brief Destroy a CeedQFunctionContext 357 358 @param ctx CeedQFunctionContext to destroy 359 360 @return An error code: 0 - success, otherwise - failure 361 362 @ref User 363 **/ 364 int CeedQFunctionContextDestroy(CeedQFunctionContext *ctx) { 365 int ierr; 366 367 if (!*ctx || --(*ctx)->ref_count > 0) 368 return CEED_ERROR_SUCCESS; 369 370 if ((*ctx) && ((*ctx)->state % 2) == 1) 371 // LCOV_EXCL_START 372 return CeedError((*ctx)->ceed, 1, 373 "Cannot destroy CeedQFunctionContext, the access " 374 "lock is in use"); 375 // LCOV_EXCL_STOP 376 377 if ((*ctx)->Destroy) { 378 ierr = (*ctx)->Destroy(*ctx); CeedChk(ierr); 379 } 380 ierr = CeedDestroy(&(*ctx)->ceed); CeedChk(ierr); 381 ierr = CeedFree(ctx); CeedChk(ierr); 382 return CEED_ERROR_SUCCESS; 383 } 384 385 /// @} 386