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-impl.h> 18 #include <ceed-backend.h> 19 #include <limits.h> 20 21 /// @file 22 /// Implementation of public CeedQFunctionContext interfaces 23 24 /// ---------------------------------------------------------------------------- 25 /// CeedQFunctionContext Backend API 26 /// ---------------------------------------------------------------------------- 27 /// @addtogroup CeedQFunctionBackend 28 /// @{ 29 30 /** 31 @brief Get the Ceed associated with a CeedQFunctionContext 32 33 @param ctx CeedQFunctionContext 34 @param[out] ceed Variable to store Ceed 35 36 @return An error code: 0 - success, otherwise - failure 37 38 @ref Backend 39 **/ 40 int CeedQFunctionContextGetCeed(CeedQFunctionContext ctx, Ceed *ceed) { 41 *ceed = ctx->ceed; 42 return 0; 43 } 44 45 /** 46 @brief Get the state of a CeedQFunctionContext 47 48 @param ctx CeedQFunctionContext to retrieve state 49 @param[out] state Variable to store state 50 51 @return An error code: 0 - success, otherwise - failure 52 53 @ref Backend 54 **/ 55 int CeedQFunctionContextGetState(CeedQFunctionContext ctx, uint64_t *state) { 56 *state = ctx->state; 57 return 0; 58 } 59 60 /** 61 @brief Get data size for a Context 62 63 @param ctx CeedQFunctionContext 64 @param[out] ctxsize Variable to store size of context data values 65 66 @return An error code: 0 - success, otherwise - failure 67 68 @ref Backend 69 **/ 70 int CeedQFunctionContextGetContextSize(CeedQFunctionContext ctx, 71 size_t *ctxsize) { 72 *ctxsize = ctx->ctxsize; 73 return 0; 74 } 75 76 /** 77 @brief Get backend data of a CeedQFunctionContext 78 79 @param ctx CeedQFunctionContext 80 @param[out] data Variable to store data 81 82 @return An error code: 0 - success, otherwise - failure 83 84 @ref Backend 85 **/ 86 int CeedQFunctionContextGetBackendData(CeedQFunctionContext ctx, void *data) { 87 *(void **)data = ctx->data; 88 return 0; 89 } 90 91 /** 92 @brief Set backend data of a CeedQFunctionContext 93 94 @param[out] ctx CeedQFunctionContext 95 @param data Data to set 96 97 @return An error code: 0 - success, otherwise - failure 98 99 @ref Backend 100 **/ 101 int CeedQFunctionContextSetBackendData(CeedQFunctionContext ctx, void *data) { 102 ctx->data = data; 103 return 0; 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, 1, "Backend does not support ContextCreate"); 135 // LCOV_EXCL_STOP 136 137 ierr = CeedQFunctionContextCreate(delegate, ctx); CeedChk(ierr); 138 return 0; 139 } 140 141 ierr = CeedCalloc(1, ctx); CeedChk(ierr); 142 (*ctx)->ceed = ceed; 143 ceed->refcount++; 144 (*ctx)->refcount = 1; 145 ierr = ceed->QFunctionContextCreate(*ctx); CeedChk(ierr); 146 return 0; 147 } 148 149 /** 150 @brief Set the data used by a CeedQFunctionContext, freeing any previously allocated 151 data if applicable. The backend may copy values to a different 152 memtype, such as during @ref CeedQFunctionApply(). 153 See also @ref CeedQFunctionContextTakeData(). 154 155 @param ctx CeedQFunctionContext 156 @param mtype Memory type of the data being passed 157 @param cmode Copy mode for the data 158 @param data Data to be used 159 160 @return An error code: 0 - success, otherwise - failure 161 162 @ref User 163 **/ 164 int CeedQFunctionContextSetData(CeedQFunctionContext ctx, CeedMemType mtype, 165 CeedCopyMode cmode, 166 size_t size, void *data) { 167 int ierr; 168 169 if (!ctx->SetData) 170 // LCOV_EXCL_START 171 return CeedError(ctx->ceed, 1, "Backend does not support ContextSetData"); 172 // LCOV_EXCL_STOP 173 174 if (ctx->state % 2 == 1) 175 // LCOV_EXCL_START 176 return CeedError(ctx->ceed, 1, 177 "Cannot grant CeedQFunctionContext data access, the " 178 "access lock is already in use"); 179 // LCOV_EXCL_STOP 180 181 ctx->ctxsize = size; 182 ierr = ctx->SetData(ctx, mtype, cmode, data); CeedChk(ierr); 183 ctx->state += 2; 184 185 return 0; 186 } 187 188 /** 189 @brief Get read/write access to a CeedQFunctionContext via the specified memory type. 190 Restore access with @ref CeedQFunctionContextRestoreData(). 191 192 @param ctx CeedQFunctionContext to access 193 @param mtype Memory type on which to access the data. If the backend 194 uses a different memory type, this will perform a copy. 195 @param[out] data Data on memory type mtype 196 197 @note The CeedQFunctionContextGetData() and @ref CeedQFunctionContextRestoreData() functions 198 provide access to array pointers in the desired memory space. Pairing 199 get/restore allows the Context to track access. 200 201 @return An error code: 0 - success, otherwise - failure 202 203 @ref User 204 **/ 205 int CeedQFunctionContextGetData(CeedQFunctionContext ctx, CeedMemType mtype, 206 void *data) { 207 int ierr; 208 209 if (!ctx->GetData) 210 // LCOV_EXCL_START 211 return CeedError(ctx->ceed, 1, "Backend does not support GetData"); 212 // LCOV_EXCL_STOP 213 214 if (ctx->state % 2 == 1) 215 // LCOV_EXCL_START 216 return CeedError(ctx->ceed, 1, 217 "Cannot grant CeedQFunctionContext data access, the " 218 "access lock is already in use"); 219 // LCOV_EXCL_STOP 220 221 ierr = ctx->GetData(ctx, mtype, data); CeedChk(ierr); 222 ctx->state += 1; 223 224 return 0; 225 } 226 227 /** 228 @brief Restore data obtained using @ref CeedQFunctionContextGetData() 229 230 @param ctx CeedQFunctionContext to restore 231 @param data Data to restore 232 233 @return An error code: 0 - success, otherwise - failure 234 235 @ref User 236 **/ 237 int CeedQFunctionContextRestoreData(CeedQFunctionContext ctx, void *data) { 238 int ierr; 239 240 if (!ctx->RestoreData) 241 // LCOV_EXCL_START 242 return CeedError(ctx->ceed, 1, "Backend does not support RestoreData"); 243 // LCOV_EXCL_STOP 244 245 if (ctx->state % 2 != 1) 246 // LCOV_EXCL_START 247 return CeedError(ctx->ceed, 1, 248 "Cannot restore CeedQFunctionContext array access, " 249 "access was not granted"); 250 // LCOV_EXCL_STOP 251 252 ierr = ctx->RestoreData(ctx); CeedChk(ierr); 253 *(void **)data = NULL; 254 ctx->state += 1; 255 256 return 0; 257 } 258 259 /** 260 @brief View a CeedQFunctionContext 261 262 @param[in] ctx CeedQFunctionContext to view 263 @param[in] stream Filestream to write to 264 265 @return An error code: 0 - success, otherwise - failure 266 267 @ref User 268 **/ 269 int CeedQFunctionContextView(CeedQFunctionContext ctx, FILE *stream) { 270 fprintf(stream, "CeedQFunctionContext\n"); 271 fprintf(stream, " Context Data Size: %ld\n", ctx->ctxsize); 272 return 0; 273 } 274 275 /** 276 @brief Destroy a CeedQFunctionContext 277 278 @param ctx CeedQFunctionContext to destroy 279 280 @return An error code: 0 - success, otherwise - failure 281 282 @ref User 283 **/ 284 int CeedQFunctionContextDestroy(CeedQFunctionContext *ctx) { 285 int ierr; 286 287 if (!*ctx || --(*ctx)->refcount > 0) 288 return 0; 289 290 if ((*ctx) && ((*ctx)->state % 2) == 1) 291 // LCOV_EXCL_START 292 return CeedError((*ctx)->ceed, 1, 293 "Cannot destroy CeedQFunctionContext, the access " 294 "lock is in use"); 295 // LCOV_EXCL_STOP 296 297 if ((*ctx)->Destroy) { 298 ierr = (*ctx)->Destroy(*ctx); CeedChk(ierr); 299 } 300 301 ierr = CeedDestroy(&(*ctx)->ceed); CeedChk(ierr); 302 ierr = CeedFree(ctx); CeedChk(ierr); 303 return 0; 304 } 305 306 /// @} 307