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.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 0; 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 0; 60 } 61 62 /** 63 @brief Get data size for a Context 64 65 @param ctx CeedQFunctionContext 66 @param[out] ctxsize 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 *ctxsize) { 74 *ctxsize = ctx->ctxsize; 75 return 0; 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 0; 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 0; 106 } 107 108 /// @} 109 110 /// ---------------------------------------------------------------------------- 111 /// CeedQFunctionContext Public API 112 /// ---------------------------------------------------------------------------- 113 /// @addtogroup CeedQFunctionUser 114 /// @{ 115 116 /** 117 @brief Create a CeedQFunctionContext for storing CeedQFunction user context data 118 119 @param ceed A Ceed object where the CeedQFunctionContext will be created 120 @param[out] ctx Address of the variable where the newly created 121 CeedQFunctionContext will be stored 122 123 @return An error code: 0 - success, otherwise - failure 124 125 @ref User 126 **/ 127 int CeedQFunctionContextCreate(Ceed ceed, CeedQFunctionContext *ctx) { 128 int ierr; 129 130 if (!ceed->QFunctionContextCreate) { 131 Ceed delegate; 132 ierr = CeedGetObjectDelegate(ceed, &delegate, "Context"); CeedChk(ierr); 133 134 if (!delegate) 135 // LCOV_EXCL_START 136 return CeedError(ceed, 1, "Backend does not support ContextCreate"); 137 // LCOV_EXCL_STOP 138 139 ierr = CeedQFunctionContextCreate(delegate, ctx); CeedChk(ierr); 140 return 0; 141 } 142 143 ierr = CeedCalloc(1, ctx); CeedChk(ierr); 144 (*ctx)->ceed = ceed; 145 ceed->refcount++; 146 (*ctx)->refcount = 1; 147 ierr = ceed->QFunctionContextCreate(*ctx); CeedChk(ierr); 148 return 0; 149 } 150 151 /** 152 @brief Set the data used by a CeedQFunctionContext, freeing any previously allocated 153 data if applicable. The backend may copy values to a different 154 memtype, such as during @ref CeedQFunctionApply(). 155 See also @ref CeedQFunctionContextTakeData(). 156 157 @param ctx CeedQFunctionContext 158 @param mtype Memory type of the data being passed 159 @param cmode Copy mode for the data 160 @param data Data to be used 161 162 @return An error code: 0 - success, otherwise - failure 163 164 @ref User 165 **/ 166 int CeedQFunctionContextSetData(CeedQFunctionContext ctx, CeedMemType mtype, 167 CeedCopyMode cmode, 168 size_t size, void *data) { 169 int ierr; 170 171 if (!ctx->SetData) 172 // LCOV_EXCL_START 173 return CeedError(ctx->ceed, 1, "Backend does not support ContextSetData"); 174 // LCOV_EXCL_STOP 175 176 if (ctx->state % 2 == 1) 177 // LCOV_EXCL_START 178 return CeedError(ctx->ceed, 1, 179 "Cannot grant CeedQFunctionContext data access, the " 180 "access lock is already in use"); 181 // LCOV_EXCL_STOP 182 183 ctx->ctxsize = size; 184 ierr = ctx->SetData(ctx, mtype, cmode, data); CeedChk(ierr); 185 ctx->state += 2; 186 187 return 0; 188 } 189 190 /** 191 @brief Get read/write access to a CeedQFunctionContext via the specified memory type. 192 Restore access with @ref CeedQFunctionContextRestoreData(). 193 194 @param ctx CeedQFunctionContext to access 195 @param mtype Memory type on which to access the data. If the backend 196 uses a different memory type, this will perform a copy. 197 @param[out] data Data on memory type mtype 198 199 @note The CeedQFunctionContextGetData() and @ref CeedQFunctionContextRestoreData() functions 200 provide access to array pointers in the desired memory space. Pairing 201 get/restore allows the Context to track access. 202 203 @return An error code: 0 - success, otherwise - failure 204 205 @ref User 206 **/ 207 int CeedQFunctionContextGetData(CeedQFunctionContext ctx, CeedMemType mtype, 208 void *data) { 209 int ierr; 210 211 if (!ctx->GetData) 212 // LCOV_EXCL_START 213 return CeedError(ctx->ceed, 1, "Backend does not support GetData"); 214 // LCOV_EXCL_STOP 215 216 if (ctx->state % 2 == 1) 217 // LCOV_EXCL_START 218 return CeedError(ctx->ceed, 1, 219 "Cannot grant CeedQFunctionContext data access, the " 220 "access lock is already in use"); 221 // LCOV_EXCL_STOP 222 223 ierr = ctx->GetData(ctx, mtype, data); CeedChk(ierr); 224 ctx->state += 1; 225 226 return 0; 227 } 228 229 /** 230 @brief Restore data obtained using @ref CeedQFunctionContextGetData() 231 232 @param ctx CeedQFunctionContext to restore 233 @param data Data to restore 234 235 @return An error code: 0 - success, otherwise - failure 236 237 @ref User 238 **/ 239 int CeedQFunctionContextRestoreData(CeedQFunctionContext ctx, void *data) { 240 int ierr; 241 242 if (!ctx->RestoreData) 243 // LCOV_EXCL_START 244 return CeedError(ctx->ceed, 1, "Backend does not support RestoreData"); 245 // LCOV_EXCL_STOP 246 247 if (ctx->state % 2 != 1) 248 // LCOV_EXCL_START 249 return CeedError(ctx->ceed, 1, 250 "Cannot restore CeedQFunctionContext array access, " 251 "access was not granted"); 252 // LCOV_EXCL_STOP 253 254 ierr = ctx->RestoreData(ctx); CeedChk(ierr); 255 *(void **)data = NULL; 256 ctx->state += 1; 257 258 return 0; 259 } 260 261 /** 262 @brief View a CeedQFunctionContext 263 264 @param[in] ctx CeedQFunctionContext to view 265 @param[in] stream Filestream to write to 266 267 @return An error code: 0 - success, otherwise - failure 268 269 @ref User 270 **/ 271 int CeedQFunctionContextView(CeedQFunctionContext ctx, FILE *stream) { 272 fprintf(stream, "CeedQFunctionContext\n"); 273 fprintf(stream, " Context Data Size: %ld\n", ctx->ctxsize); 274 return 0; 275 } 276 277 /** 278 @brief Destroy a CeedQFunctionContext 279 280 @param ctx CeedQFunctionContext to destroy 281 282 @return An error code: 0 - success, otherwise - failure 283 284 @ref User 285 **/ 286 int CeedQFunctionContextDestroy(CeedQFunctionContext *ctx) { 287 int ierr; 288 289 if (!*ctx || --(*ctx)->refcount > 0) 290 return 0; 291 292 if ((*ctx) && ((*ctx)->state % 2) == 1) 293 // LCOV_EXCL_START 294 return CeedError((*ctx)->ceed, 1, 295 "Cannot destroy CeedQFunctionContext, the access " 296 "lock is in use"); 297 // LCOV_EXCL_STOP 298 299 if ((*ctx)->Destroy) { 300 ierr = (*ctx)->Destroy(*ctx); CeedChk(ierr); 301 } 302 303 ierr = CeedDestroy(&(*ctx)->ceed); CeedChk(ierr); 304 ierr = CeedFree(ctx); CeedChk(ierr); 305 return 0; 306 } 307 308 /// @} 309