xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-qfunctioncontext.c (revision 9c774eddf8c0b4f5416196d32c5355c9591a7190)
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 Check for valid data in a CeedQFunctionContext
49 
50   @param ctx                  CeedQFunctionContext to check validity
51   @param[out] has_valid_data  Variable to store validity
52 
53   @return An error code: 0 - success, otherwise - failure
54 
55   @ref Backend
56 **/
57 int CeedQFunctionContextHasValidData(CeedQFunctionContext ctx,
58                                      bool *has_valid_data) {
59   int ierr;
60 
61   if (!ctx->HasValidData)
62     // LCOV_EXCL_START
63     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED,
64                      "Backend does not support HasValidData");
65   // LCOV_EXCL_STOP
66 
67   ierr = ctx->HasValidData(ctx, has_valid_data); CeedChk(ierr);
68 
69   return CEED_ERROR_SUCCESS;
70 }
71 
72 /**
73   @brief Check for borrowed data of a specific CeedMemType in a
74            CeedQFunctionContext
75 
76   @param ctx                             CeedQFunctionContext to check
77   @param mem_type                        Memory type to check
78   @param[out] has_borrowed_data_of_type  Variable to store result
79 
80   @return An error code: 0 - success, otherwise - failure
81 
82   @ref Backend
83 **/
84 int CeedQFunctionContextHasBorrowedDataOfType(CeedQFunctionContext ctx,
85     CeedMemType mem_type, bool *has_borrowed_data_of_type) {
86   int ierr;
87 
88   if (!ctx->HasBorrowedDataOfType)
89     // LCOV_EXCL_START
90     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED,
91                      "Backend does not support HasBorrowedDataOfType");
92   // LCOV_EXCL_STOP
93 
94   ierr = ctx->HasBorrowedDataOfType(ctx, mem_type, has_borrowed_data_of_type);
95   CeedChk(ierr);
96 
97   return CEED_ERROR_SUCCESS;
98 }
99 
100 /**
101   @brief Get the state of a CeedQFunctionContext
102 
103   @param ctx         CeedQFunctionContext to retrieve state
104   @param[out] state  Variable to store state
105 
106   @return An error code: 0 - success, otherwise - failure
107 
108   @ref Backend
109 **/
110 int CeedQFunctionContextGetState(CeedQFunctionContext ctx, uint64_t *state) {
111   *state = ctx->state;
112   return CEED_ERROR_SUCCESS;
113 }
114 
115 /**
116   @brief Get backend data of a CeedQFunctionContext
117 
118   @param ctx        CeedQFunctionContext
119   @param[out] data  Variable to store data
120 
121   @return An error code: 0 - success, otherwise - failure
122 
123   @ref Backend
124 **/
125 int CeedQFunctionContextGetBackendData(CeedQFunctionContext ctx, void *data) {
126   *(void **)data = ctx->data;
127   return CEED_ERROR_SUCCESS;
128 }
129 
130 /**
131   @brief Set backend data of a CeedQFunctionContext
132 
133   @param[out] ctx  CeedQFunctionContext
134   @param data      Data to set
135 
136   @return An error code: 0 - success, otherwise - failure
137 
138   @ref Backend
139 **/
140 int CeedQFunctionContextSetBackendData(CeedQFunctionContext ctx, void *data) {
141   ctx->data = data;
142   return CEED_ERROR_SUCCESS;
143 }
144 
145 /**
146   @brief Increment the reference counter for a CeedQFunctionContext
147 
148   @param ctx  CeedQFunctionContext to increment the reference counter
149 
150   @return An error code: 0 - success, otherwise - failure
151 
152   @ref Backend
153 **/
154 int CeedQFunctionContextReference(CeedQFunctionContext ctx) {
155   ctx->ref_count++;
156   return CEED_ERROR_SUCCESS;
157 }
158 
159 /// @}
160 
161 /// ----------------------------------------------------------------------------
162 /// CeedQFunctionContext Public API
163 /// ----------------------------------------------------------------------------
164 /// @addtogroup CeedQFunctionUser
165 /// @{
166 
167 /**
168   @brief Create a CeedQFunctionContext for storing CeedQFunction user context data
169 
170   @param ceed      A Ceed object where the CeedQFunctionContext will be created
171   @param[out] ctx  Address of the variable where the newly created
172                      CeedQFunctionContext will be stored
173 
174   @return An error code: 0 - success, otherwise - failure
175 
176   @ref User
177 **/
178 int CeedQFunctionContextCreate(Ceed ceed, CeedQFunctionContext *ctx) {
179   int ierr;
180 
181   if (!ceed->QFunctionContextCreate) {
182     Ceed delegate;
183     ierr = CeedGetObjectDelegate(ceed, &delegate, "Context"); CeedChk(ierr);
184 
185     if (!delegate)
186       // LCOV_EXCL_START
187       return CeedError(ceed, CEED_ERROR_UNSUPPORTED,
188                        "Backend does not support ContextCreate");
189     // LCOV_EXCL_STOP
190 
191     ierr = CeedQFunctionContextCreate(delegate, ctx); CeedChk(ierr);
192     return CEED_ERROR_SUCCESS;
193   }
194 
195   ierr = CeedCalloc(1, ctx); CeedChk(ierr);
196   (*ctx)->ceed = ceed;
197   ierr = CeedReference(ceed); CeedChk(ierr);
198   (*ctx)->ref_count = 1;
199   ierr = ceed->QFunctionContextCreate(*ctx); CeedChk(ierr);
200   return CEED_ERROR_SUCCESS;
201 }
202 
203 /**
204   @brief Copy the pointer to a CeedQFunctionContext. Both pointers should
205            be destroyed with `CeedQFunctionContextDestroy()`;
206            Note: If `*ctx_copy` is non-NULL, then it is assumed that
207            `*ctx_copy` is a pointer to a CeedQFunctionContext. This
208            CeedQFunctionContext will be destroyed if `*ctx_copy` is the
209            only reference to this CeedQFunctionContext.
210 
211   @param ctx            CeedQFunctionContext to copy reference to
212   @param[out] ctx_copy  Variable to store copied reference
213 
214   @return An error code: 0 - success, otherwise - failure
215 
216   @ref User
217 **/
218 int CeedQFunctionContextReferenceCopy(CeedQFunctionContext ctx,
219                                       CeedQFunctionContext *ctx_copy) {
220   int ierr;
221 
222   ierr = CeedQFunctionContextReference(ctx); CeedChk(ierr);
223   ierr = CeedQFunctionContextDestroy(ctx_copy); CeedChk(ierr);
224   *ctx_copy = ctx;
225   return CEED_ERROR_SUCCESS;
226 }
227 
228 /**
229   @brief Set the data used by a CeedQFunctionContext, freeing any previously allocated
230            data if applicable. The backend may copy values to a different
231            memtype, such as during @ref CeedQFunctionApply().
232            See also @ref CeedQFunctionContextTakeData().
233 
234   @param ctx        CeedQFunctionContext
235   @param mem_type   Memory type of the data being passed
236   @param copy_mode  Copy mode for the data
237   @param size       Size of data, in bytes
238   @param data       Data to be used
239 
240   @return An error code: 0 - success, otherwise - failure
241 
242   @ref User
243 **/
244 int CeedQFunctionContextSetData(CeedQFunctionContext ctx, CeedMemType mem_type,
245                                 CeedCopyMode copy_mode,
246                                 size_t size, void *data) {
247   int ierr;
248 
249   if (!ctx->SetData)
250     // LCOV_EXCL_START
251     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED,
252                      "Backend does not support ContextSetData");
253   // LCOV_EXCL_STOP
254 
255   if (ctx->state % 2 == 1)
256     // LCOV_EXCL_START
257     return CeedError(ctx->ceed, 1,
258                      "Cannot grant CeedQFunctionContext data access, the "
259                      "access lock is already in use");
260   // LCOV_EXCL_STOP
261 
262   ctx->ctx_size = size;
263   ierr = ctx->SetData(ctx, mem_type, copy_mode, data); CeedChk(ierr);
264   ctx->state += 2;
265   return CEED_ERROR_SUCCESS;
266 }
267 
268 /**
269   @brief Take ownership of the data in a CeedQFunctionContext via the specified memory type.
270            The caller is responsible for managing and freeing the memory.
271 
272   @param ctx        CeedQFunctionContext to access
273   @param mem_type   Memory type on which to access the data. If the backend
274                       uses a different memory type, this will perform a copy.
275   @param[out] data  Data on memory type mem_type
276 
277   @return An error code: 0 - success, otherwise - failure
278 
279   @ref User
280 **/
281 int CeedQFunctionContextTakeData(CeedQFunctionContext ctx, CeedMemType mem_type,
282                                  void *data) {
283   int ierr;
284 
285   bool has_valid_data = true;
286   ierr = CeedQFunctionContextHasValidData(ctx, &has_valid_data); CeedChk(ierr);
287   if (!has_valid_data)
288     // LCOV_EXCL_START
289     return CeedError(ctx->ceed, CEED_ERROR_BACKEND,
290                      "CeedQFunctionContext has no valid data to take, must set data");
291   // LCOV_EXCL_STOP
292 
293   if (!ctx->TakeData)
294     // LCOV_EXCL_START
295     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED,
296                      "Backend does not support TakeData");
297   // LCOV_EXCL_STOP
298 
299   if (ctx->state % 2 == 1)
300     // LCOV_EXCL_START
301     return CeedError(ctx->ceed, 1,
302                      "Cannot grant CeedQFunctionContext data access, the "
303                      "access lock is already in use");
304   // LCOV_EXCL_STOP
305 
306   bool has_borrowed_data_of_type = true;
307   ierr = CeedQFunctionContextHasBorrowedDataOfType(ctx, mem_type,
308          &has_borrowed_data_of_type); CeedChk(ierr);
309   if (!has_borrowed_data_of_type)
310     // LCOV_EXCL_START
311     return CeedError(ctx->ceed, CEED_ERROR_BACKEND,
312                      "CeedQFunctionContext has no borowed %s data, "
313                      "must set data with CeedQFunctionContextSetData",
314                      CeedMemTypes[mem_type]);
315   // LCOV_EXCL_STOP
316 
317   void *temp_data = NULL;
318   ierr = ctx->TakeData(ctx, mem_type, &temp_data); CeedChk(ierr);
319   if (data) (*(void **)data) = temp_data;
320   return CEED_ERROR_SUCCESS;
321 }
322 
323 /**
324   @brief Get read/write access to a CeedQFunctionContext via the specified memory type.
325            Restore access with @ref CeedQFunctionContextRestoreData().
326 
327   @param ctx        CeedQFunctionContext to access
328   @param mem_type   Memory type on which to access the data. If the backend
329                       uses a different memory type, this will perform a copy.
330   @param[out] data  Data on memory type mem_type
331 
332   @note The CeedQFunctionContextGetData() and @ref CeedQFunctionContextRestoreData() functions
333     provide access to array pointers in the desired memory space. Pairing
334     get/restore allows the Context to track access.
335 
336   @return An error code: 0 - success, otherwise - failure
337 
338   @ref User
339 **/
340 int CeedQFunctionContextGetData(CeedQFunctionContext ctx, CeedMemType mem_type,
341                                 void *data) {
342   int ierr;
343 
344   if (!ctx->GetData)
345     // LCOV_EXCL_START
346     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED,
347                      "Backend does not support GetData");
348   // LCOV_EXCL_STOP
349 
350   if (ctx->state % 2 == 1)
351     // LCOV_EXCL_START
352     return CeedError(ctx->ceed, 1,
353                      "Cannot grant CeedQFunctionContext data access, the "
354                      "access lock is already in use");
355   // LCOV_EXCL_STOP
356 
357   bool has_valid_data = true;
358   ierr = CeedQFunctionContextHasValidData(ctx, &has_valid_data); CeedChk(ierr);
359   if (!has_valid_data)
360     // LCOV_EXCL_START
361     return CeedError(ctx->ceed, CEED_ERROR_BACKEND,
362                      "CeedQFunctionContext has no valid data to get, must set data");
363   // LCOV_EXCL_STOP
364 
365   ierr = ctx->GetData(ctx, mem_type, data); CeedChk(ierr);
366   ctx->state += 1;
367   return CEED_ERROR_SUCCESS;
368 }
369 
370 /**
371   @brief Restore data obtained using @ref CeedQFunctionContextGetData()
372 
373   @param ctx   CeedQFunctionContext to restore
374   @param data  Data to restore
375 
376   @return An error code: 0 - success, otherwise - failure
377 
378   @ref User
379 **/
380 int CeedQFunctionContextRestoreData(CeedQFunctionContext ctx, void *data) {
381   int ierr;
382 
383   if (!ctx->RestoreData)
384     // LCOV_EXCL_START
385     return CeedError(ctx->ceed, CEED_ERROR_UNSUPPORTED,
386                      "Backend does not support RestoreData");
387   // LCOV_EXCL_STOP
388 
389   if (ctx->state % 2 != 1)
390     // LCOV_EXCL_START
391     return CeedError(ctx->ceed, 1,
392                      "Cannot restore CeedQFunctionContext array access, "
393                      "access was not granted");
394   // LCOV_EXCL_STOP
395 
396   ierr = ctx->RestoreData(ctx); CeedChk(ierr);
397   *(void **)data = NULL;
398   ctx->state += 1;
399   return CEED_ERROR_SUCCESS;
400 }
401 
402 /**
403   @brief Get data size for a Context
404 
405   @param ctx            CeedQFunctionContext
406   @param[out] ctx_size  Variable to store size of context data values
407 
408   @return An error code: 0 - success, otherwise - failure
409 
410   @ref User
411 **/
412 int CeedQFunctionContextGetContextSize(CeedQFunctionContext ctx,
413                                        size_t *ctx_size) {
414   *ctx_size = ctx->ctx_size;
415   return CEED_ERROR_SUCCESS;
416 }
417 
418 
419 /**
420   @brief View a CeedQFunctionContext
421 
422   @param[in] ctx     CeedQFunctionContext to view
423   @param[in] stream  Filestream to write to
424 
425   @return An error code: 0 - success, otherwise - failure
426 
427   @ref User
428 **/
429 int CeedQFunctionContextView(CeedQFunctionContext ctx, FILE *stream) {
430   fprintf(stream, "CeedQFunctionContext\n");
431   fprintf(stream, "  Context Data Size: %ld\n", ctx->ctx_size);
432   return CEED_ERROR_SUCCESS;
433 }
434 
435 /**
436   @brief Destroy a CeedQFunctionContext
437 
438   @param ctx  CeedQFunctionContext to destroy
439 
440   @return An error code: 0 - success, otherwise - failure
441 
442   @ref User
443 **/
444 int CeedQFunctionContextDestroy(CeedQFunctionContext *ctx) {
445   int ierr;
446 
447   if (!*ctx || --(*ctx)->ref_count > 0)
448     return CEED_ERROR_SUCCESS;
449 
450   if ((*ctx) && ((*ctx)->state % 2) == 1)
451     // LCOV_EXCL_START
452     return CeedError((*ctx)->ceed, 1,
453                      "Cannot destroy CeedQFunctionContext, the access "
454                      "lock is in use");
455   // LCOV_EXCL_STOP
456 
457   if ((*ctx)->Destroy) {
458     ierr = (*ctx)->Destroy(*ctx); CeedChk(ierr);
459   }
460   ierr = CeedDestroy(&(*ctx)->ceed); CeedChk(ierr);
461   ierr = CeedFree(ctx); CeedChk(ierr);
462   return CEED_ERROR_SUCCESS;
463 }
464 
465 /// @}
466