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