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