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 data size for a Context 64 65 @param ctx CeedQFunctionContext 66 @param[out] ctx_size Variable to store size of context data values 67 68 @return An error code: 0 - success, otherwise - failure 69 70 @ref Backend 71 **/ 72 int CeedQFunctionContextGetContextSize(CeedQFunctionContext ctx, 73 size_t *ctx_size) { 74 *ctx_size = ctx->ctx_size; 75 return CEED_ERROR_SUCCESS; 76 } 77 78 /** 79 @brief Get backend data of a CeedQFunctionContext 80 81 @param ctx CeedQFunctionContext 82 @param[out] data Variable to store data 83 84 @return An error code: 0 - success, otherwise - failure 85 86 @ref Backend 87 **/ 88 int CeedQFunctionContextGetBackendData(CeedQFunctionContext ctx, void *data) { 89 *(void **)data = ctx->data; 90 return CEED_ERROR_SUCCESS; 91 } 92 93 /** 94 @brief Set backend data of a CeedQFunctionContext 95 96 @param[out] ctx CeedQFunctionContext 97 @param data Data to set 98 99 @return An error code: 0 - success, otherwise - failure 100 101 @ref Backend 102 **/ 103 int CeedQFunctionContextSetBackendData(CeedQFunctionContext ctx, void *data) { 104 ctx->data = data; 105 return CEED_ERROR_SUCCESS; 106 } 107 108 /** 109 @brief Increment the reference counter for a CeedQFunctionContext 110 111 @param ctx CeedQFunctionContext to increment the reference counter 112 113 @return An error code: 0 - success, otherwise - failure 114 115 @ref Backend 116 **/ 117 int CeedQFunctionContextReference(CeedQFunctionContext ctx) { 118 ctx->ref_count++; 119 return CEED_ERROR_SUCCESS; 120 } 121 122 /// @} 123 124 /// ---------------------------------------------------------------------------- 125 /// CeedQFunctionContext Public API 126 /// ---------------------------------------------------------------------------- 127 /// @addtogroup CeedQFunctionUser 128 /// @{ 129 130 /** 131 @brief Create a CeedQFunctionContext for storing CeedQFunction user context data 132 133 @param ceed A Ceed object where the CeedQFunctionContext will be created 134 @param[out] ctx Address of the variable where the newly created 135 CeedQFunctionContext will be stored 136 137 @return An error code: 0 - success, otherwise - failure 138 139 @ref User 140 **/ 141 int CeedQFunctionContextCreate(Ceed ceed, CeedQFunctionContext *ctx) { 142 int ierr; 143 144 if (!ceed->QFunctionContextCreate) { 145 Ceed delegate; 146 ierr = CeedGetObjectDelegate(ceed, &delegate, "Context"); CeedChk(ierr); 147 148 if (!delegate) 149 // LCOV_EXCL_START 150 return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 151 "Backend does not support ContextCreate"); 152 // LCOV_EXCL_STOP 153 154 ierr = CeedQFunctionContextCreate(delegate, ctx); CeedChk(ierr); 155 return CEED_ERROR_SUCCESS; 156 } 157 158 ierr = CeedCalloc(1, ctx); CeedChk(ierr); 159 (*ctx)->ceed = ceed; 160 ierr = CeedReference(ceed); CeedChk(ierr); 161 (*ctx)->ref_count = 1; 162 ierr = ceed->QFunctionContextCreate(*ctx); CeedChk(ierr); 163 return CEED_ERROR_SUCCESS; 164 } 165 166 /** 167 @brief Copy the pointer to a CeedQFunctionContext. Both pointers should 168 be destroyed with `CeedQFunctionContextDestroy()`; 169 Note: If `*ctx_copy` is non-NULL, then it is assumed that 170 `*ctx_copy` is a pointer to a CeedQFunctionContext. This 171 CeedQFunctionContext will be destroyed if `*ctx_copy` is the 172 only reference to this CeedQFunctionContext. 173 174 @param ctx CeedQFunctionContext to copy reference to 175 @param[out] ctx_copy Variable to store copied reference 176 177 @return An error code: 0 - success, otherwise - failure 178 179 @ref User 180 **/ 181 int CeedQFunctionContextReferenceCopy(CeedQFunctionContext ctx, 182 CeedQFunctionContext *ctx_copy) { 183 int ierr; 184 185 ierr = CeedQFunctionContextReference(ctx); CeedChk(ierr); 186 ierr = CeedQFunctionContextDestroy(ctx_copy); CeedChk(ierr); 187 *ctx_copy = ctx; 188 return CEED_ERROR_SUCCESS; 189 } 190 191 /** 192 @brief Set the data used by a CeedQFunctionContext, freeing any previously allocated 193 data if applicable. The backend may copy values to a different 194 memtype, such as during @ref CeedQFunctionApply(). 195 See also @ref CeedQFunctionContextTakeData(). 196 197 @param ctx CeedQFunctionContext 198 @param mem_type Memory type of the data being passed 199 @param copy_mode Copy mode for the data 200 @param size Size of data, in bytes 201 @param data Data to be used 202 203 @return An error code: 0 - success, otherwise - failure 204 205 @ref User 206 **/ 207 int CeedQFunctionContextSetData(CeedQFunctionContext ctx, CeedMemType mem_type, 208 CeedCopyMode copy_mode, 209 size_t size, void *data) { 210 int ierr; 211 212 if (!ctx->SetData) 213 // LCOV_EXCL_START 214 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 215 "Backend does not support ContextSetData"); 216 // LCOV_EXCL_STOP 217 218 if (ctx->state % 2 == 1) 219 // LCOV_EXCL_START 220 return CeedError(ctx->ceed, 1, 221 "Cannot grant CeedQFunctionContext data access, the " 222 "access lock is already in use"); 223 // LCOV_EXCL_STOP 224 225 ctx->ctx_size = size; 226 ierr = ctx->SetData(ctx, mem_type, copy_mode, data); CeedChk(ierr); 227 ctx->state += 2; 228 return CEED_ERROR_SUCCESS; 229 } 230 231 /** 232 @brief Take ownership of the data in a CeedQFunctionContext via the specified memory type. 233 The caller is responsible for managing and freeing the memory. 234 235 @param ctx CeedQFunctionContext to access 236 @param mem_type Memory type on which to access the data. If the backend 237 uses a different memory type, this will perform a copy. 238 @param[out] data Data on memory type mem_type 239 240 @return An error code: 0 - success, otherwise - failure 241 242 @ref User 243 **/ 244 int CeedQFunctionContextTakeData(CeedQFunctionContext ctx, CeedMemType mem_type, 245 void *data) { 246 int ierr; 247 248 if (!ctx->TakeData) 249 // LCOV_EXCL_START 250 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 251 "Backend does not support TakeData"); 252 // LCOV_EXCL_STOP 253 254 if (ctx->state % 2 == 1) 255 // LCOV_EXCL_START 256 return CeedError(ctx->ceed, 1, 257 "Cannot grant CeedQFunctionContext data access, the " 258 "access lock is already in use"); 259 // LCOV_EXCL_STOP 260 261 void *temp_data = NULL; 262 ierr = ctx->TakeData(ctx, mem_type, &temp_data); CeedChk(ierr); 263 if (data) (*(void **)data) = temp_data; 264 return CEED_ERROR_SUCCESS; 265 } 266 267 /** 268 @brief Get read/write access to a CeedQFunctionContext via the specified memory type. 269 Restore access with @ref CeedQFunctionContextRestoreData(). 270 271 @param ctx CeedQFunctionContext to access 272 @param mem_type Memory type on which to access the data. If the backend 273 uses a different memory type, this will perform a copy. 274 @param[out] data Data on memory type mem_type 275 276 @note The CeedQFunctionContextGetData() and @ref CeedQFunctionContextRestoreData() functions 277 provide access to array pointers in the desired memory space. Pairing 278 get/restore allows the Context to track access. 279 280 @return An error code: 0 - success, otherwise - failure 281 282 @ref User 283 **/ 284 int CeedQFunctionContextGetData(CeedQFunctionContext ctx, CeedMemType mem_type, 285 void *data) { 286 int ierr; 287 288 if (!ctx->GetData) 289 // LCOV_EXCL_START 290 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 291 "Backend does not support GetData"); 292 // LCOV_EXCL_STOP 293 294 if (ctx->state % 2 == 1) 295 // LCOV_EXCL_START 296 return CeedError(ctx->ceed, 1, 297 "Cannot grant CeedQFunctionContext data access, the " 298 "access lock is already in use"); 299 // LCOV_EXCL_STOP 300 301 ierr = ctx->GetData(ctx, mem_type, data); CeedChk(ierr); 302 ctx->state += 1; 303 return CEED_ERROR_SUCCESS; 304 } 305 306 /** 307 @brief Restore data obtained using @ref CeedQFunctionContextGetData() 308 309 @param ctx CeedQFunctionContext to restore 310 @param data Data to restore 311 312 @return An error code: 0 - success, otherwise - failure 313 314 @ref User 315 **/ 316 int CeedQFunctionContextRestoreData(CeedQFunctionContext ctx, void *data) { 317 int ierr; 318 319 if (!ctx->RestoreData) 320 // LCOV_EXCL_START 321 return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED, 322 "Backend does not support RestoreData"); 323 // LCOV_EXCL_STOP 324 325 if (ctx->state % 2 != 1) 326 // LCOV_EXCL_START 327 return CeedError(ctx->ceed, 1, 328 "Cannot restore CeedQFunctionContext array access, " 329 "access was not granted"); 330 // LCOV_EXCL_STOP 331 332 ierr = ctx->RestoreData(ctx); CeedChk(ierr); 333 *(void **)data = NULL; 334 ctx->state += 1; 335 return CEED_ERROR_SUCCESS; 336 } 337 338 /** 339 @brief View a CeedQFunctionContext 340 341 @param[in] ctx CeedQFunctionContext to view 342 @param[in] stream Filestream to write to 343 344 @return An error code: 0 - success, otherwise - failure 345 346 @ref User 347 **/ 348 int CeedQFunctionContextView(CeedQFunctionContext ctx, FILE *stream) { 349 fprintf(stream, "CeedQFunctionContext\n"); 350 fprintf(stream, " Context Data Size: %ld\n", ctx->ctx_size); 351 return CEED_ERROR_SUCCESS; 352 } 353 354 /** 355 @brief Destroy a CeedQFunctionContext 356 357 @param ctx CeedQFunctionContext to destroy 358 359 @return An error code: 0 - success, otherwise - failure 360 361 @ref User 362 **/ 363 int CeedQFunctionContextDestroy(CeedQFunctionContext *ctx) { 364 int ierr; 365 366 if (!*ctx || --(*ctx)->ref_count > 0) 367 return CEED_ERROR_SUCCESS; 368 369 if ((*ctx) && ((*ctx)->state % 2) == 1) 370 // LCOV_EXCL_START 371 return CeedError((*ctx)->ceed, 1, 372 "Cannot destroy CeedQFunctionContext, the access " 373 "lock is in use"); 374 // LCOV_EXCL_STOP 375 376 if ((*ctx)->Destroy) { 377 ierr = (*ctx)->Destroy(*ctx); CeedChk(ierr); 378 } 379 ierr = CeedDestroy(&(*ctx)->ceed); CeedChk(ierr); 380 ierr = CeedFree(ctx); CeedChk(ierr); 381 return CEED_ERROR_SUCCESS; 382 } 383 384 /// @} 385