xref: /libCEED/interface/ceed-qfunctioncontext.c (revision 6f5dc8ba493eb609f13fe336f2a5e06988b93c70)
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