xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-qfunction.c (revision 1203703b5dc87b4acbe66c9a27384ca8ad07798d)
13d8e8822SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors.
23d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3d7b241e6Sjeremylt //
43d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause
5d7b241e6Sjeremylt //
63d8e8822SJeremy L Thompson // This file is part of CEED:  http://github.com/ceed
7d7b241e6Sjeremylt 
83d576824SJeremy L Thompson #include <ceed-impl.h>
949aac155SJeremy L Thompson #include <ceed.h>
102b730f8bSJeremy L Thompson #include <ceed/backend.h>
112b730f8bSJeremy L Thompson #include <ceed/jit-tools.h>
12288c0443SJeremy L Thompson #include <limits.h>
133d576824SJeremy L Thompson #include <stdbool.h>
143d576824SJeremy L Thompson #include <stdio.h>
153d576824SJeremy L Thompson #include <string.h>
16288c0443SJeremy L Thompson 
177a982d89SJeremy L. Thompson /// @file
187a982d89SJeremy L. Thompson /// Implementation of public CeedQFunction interfaces
197a982d89SJeremy L. Thompson 
20288c0443SJeremy L Thompson /// @cond DOXYGEN_SKIP
21442e7f0bSjeremylt static struct CeedQFunction_private ceed_qfunction_none;
22442e7f0bSjeremylt /// @endcond
23442e7f0bSjeremylt 
247a982d89SJeremy L. Thompson /// @addtogroup CeedQFunctionUser
257a982d89SJeremy L. Thompson /// @{
267a982d89SJeremy L. Thompson 
27ca94c3ddSJeremy L Thompson // Indicate that no `CeedQFunction` is provided by the user
287a982d89SJeremy L. Thompson const CeedQFunction CEED_QFUNCTION_NONE = &ceed_qfunction_none;
297a982d89SJeremy L. Thompson 
307a982d89SJeremy L. Thompson /// @}
317a982d89SJeremy L. Thompson 
32442e7f0bSjeremylt /// @cond DOXYGEN_SKIP
33288c0443SJeremy L Thompson static struct {
34288c0443SJeremy L Thompson   char              name[CEED_MAX_RESOURCE_LEN];
35288c0443SJeremy L Thompson   char              source[CEED_MAX_RESOURCE_LEN];
36d1d35e2fSjeremylt   CeedInt           vec_length;
37288c0443SJeremy L Thompson   CeedQFunctionUser f;
38288c0443SJeremy L Thompson   int (*init)(Ceed ceed, const char *name, CeedQFunction qf);
39d1d35e2fSjeremylt } gallery_qfunctions[1024];
40288c0443SJeremy L Thompson static size_t num_qfunctions;
41288c0443SJeremy L Thompson /// @endcond
42d7b241e6Sjeremylt 
43777ff853SJeremy L Thompson /// ----------------------------------------------------------------------------
44777ff853SJeremy L Thompson /// CeedQFunction Library Internal Functions
45777ff853SJeremy L Thompson /// ----------------------------------------------------------------------------
46777ff853SJeremy L Thompson /// @addtogroup CeedQFunctionDeveloper
47777ff853SJeremy L Thompson /// @{
48777ff853SJeremy L Thompson 
49b11c1e72Sjeremylt /**
50ca94c3ddSJeremy L Thompson   @brief Register a gallery `CeedQFunction`
51288c0443SJeremy L Thompson 
52ea61e9acSJeremy L Thompson   @param[in] name       Name for this backend to respond to
53ca94c3ddSJeremy L Thompson   @param[in] source     Absolute path to source of `CeedQFunction`, "\path\CEED_DIR\gallery\folder\file.h:function_name"
54ca94c3ddSJeremy L Thompson   @param[in] vec_length Vector length.
55ca94c3ddSJeremy L Thompson                           Caller must ensure that number of quadrature points is a multiple of `vec_length`.
56ea61e9acSJeremy L Thompson   @param[in] f          Function pointer to evaluate action at quadrature points.
57ca94c3ddSJeremy L Thompson                           See `CeedQFunctionUser`.
58ca94c3ddSJeremy L Thompson   @param[in] init       Initialization function called by @ref CeedQFunctionCreateInteriorByName() when the `CeedQFunction` is selected.
59288c0443SJeremy L Thompson 
60288c0443SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
61288c0443SJeremy L Thompson 
627a982d89SJeremy L. Thompson   @ref Developer
63288c0443SJeremy L Thompson **/
642b730f8bSJeremy L Thompson int CeedQFunctionRegister(const char *name, const char *source, CeedInt vec_length, CeedQFunctionUser f,
65288c0443SJeremy L Thompson                           int (*init)(Ceed, const char *, CeedQFunction)) {
661c66c397SJeremy L Thompson   const char *relative_file_path;
6758c07c4fSSebastian Grimberg   int         ierr = 0;
68c042f62fSJeremy L Thompson 
698ccf1006SJeremy L Thompson   CeedDebugEnv("Gallery Register: %s", name);
702b730f8bSJeremy L Thompson   CeedCall(CeedGetJitRelativePath(source, &relative_file_path));
7158c07c4fSSebastian Grimberg   CeedPragmaCritical(CeedQFunctionRegister) {
7258c07c4fSSebastian Grimberg     if (num_qfunctions < sizeof(gallery_qfunctions) / sizeof(gallery_qfunctions[0])) {
73d1d35e2fSjeremylt       strncpy(gallery_qfunctions[num_qfunctions].name, name, CEED_MAX_RESOURCE_LEN);
74d1d35e2fSjeremylt       gallery_qfunctions[num_qfunctions].name[CEED_MAX_RESOURCE_LEN - 1] = 0;
752b730f8bSJeremy L Thompson       strncpy(gallery_qfunctions[num_qfunctions].source, relative_file_path, CEED_MAX_RESOURCE_LEN);
76d1d35e2fSjeremylt       gallery_qfunctions[num_qfunctions].source[CEED_MAX_RESOURCE_LEN - 1] = 0;
77d1d35e2fSjeremylt       gallery_qfunctions[num_qfunctions].vec_length                        = vec_length;
78d1d35e2fSjeremylt       gallery_qfunctions[num_qfunctions].f                                 = f;
79d1d35e2fSjeremylt       gallery_qfunctions[num_qfunctions].init                              = init;
80288c0443SJeremy L Thompson       num_qfunctions++;
8158c07c4fSSebastian Grimberg     } else {
8258c07c4fSSebastian Grimberg       ierr = 1;
8358c07c4fSSebastian Grimberg     }
8458c07c4fSSebastian Grimberg   }
85ca94c3ddSJeremy L Thompson   CeedCheck(ierr == 0, NULL, CEED_ERROR_MAJOR, "Too many gallery CeedQFunctions");
86e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
87288c0443SJeremy L Thompson }
88288c0443SJeremy L Thompson 
89288c0443SJeremy L Thompson /**
90ca94c3ddSJeremy L Thompson   @brief Set a `CeedQFunction` field, used by @ref CeedQFunctionAddInput() and @ref CeedQFunctionAddOutput()
917a982d89SJeremy L. Thompson 
92ca94c3ddSJeremy L Thompson   @param[out] f           `CeedQFunctionField`
93ca94c3ddSJeremy L Thompson   @param[in]  field_name  Name of `CeedQFunction` field
94ca94c3ddSJeremy L Thompson   @param[in]  size        Size of `CeedQFunction` field, (`num_comp * 1`) for @ref CEED_EVAL_NONE and @ref CEED_EVAL_WEIGHT, (`num_comp * 1`) for @ref CEED_EVAL_INTERP for an \f$H^1\f$ space or (`num_comp * dim`) for an \f$H(\mathrm{div})\f$ or \f$H(\mathrm{curl})\f$ space, (`num_comp * dim`) for @ref CEED_EVAL_GRAD, or (num_comp * 1) for @ref CEED_EVAL_DIV, and (`num_comp * curl_dim`) with `curl_dim = 1` if `dim < 3` and `curl_dim = dim` for @ref CEED_EVAL_CURL.
95ca94c3ddSJeremy L Thompson   @param[in]  eval_mode   @ref CEED_EVAL_NONE to use values directly,
96ca94c3ddSJeremy L Thompson                             @ref CEED_EVAL_WEIGHT to use quadrature weights,
97ca94c3ddSJeremy L Thompson                             @ref CEED_EVAL_INTERP to use interpolated values,
98ca94c3ddSJeremy L Thompson                             @ref CEED_EVAL_GRAD to use gradients,
99ca94c3ddSJeremy L Thompson                             @ref CEED_EVAL_DIV to use divergence,
100ca94c3ddSJeremy L Thompson                             @ref CEED_EVAL_CURL to use curl
1017a982d89SJeremy L. Thompson 
1027a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1037a982d89SJeremy L. Thompson 
1047a982d89SJeremy L. Thompson   @ref Developer
1057a982d89SJeremy L. Thompson **/
1062b730f8bSJeremy L Thompson static int CeedQFunctionFieldSet(CeedQFunctionField *f, const char *field_name, CeedInt size, CeedEvalMode eval_mode) {
1072b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, f));
1082b730f8bSJeremy L Thompson   CeedCall(CeedStringAllocCopy(field_name, (char **)&(*f)->field_name));
1097a982d89SJeremy L. Thompson   (*f)->size      = size;
110d1d35e2fSjeremylt   (*f)->eval_mode = eval_mode;
111e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1127a982d89SJeremy L. Thompson }
1137a982d89SJeremy L. Thompson 
1147a982d89SJeremy L. Thompson /**
115ca94c3ddSJeremy L Thompson   @brief View a field of a `CeedQFunction`
1167a982d89SJeremy L. Thompson 
117ca94c3ddSJeremy L Thompson   @param[in] field        `CeedQFunction` field to view
118d1d35e2fSjeremylt   @param[in] field_number Number of field being viewed
1194c4400c7SValeria Barra   @param[in] in           true for input field, false for output
120ca94c3ddSJeremy L Thompson   @param[in] stream       Stream to view to, e.g., `stdout`
1217a982d89SJeremy L. Thompson 
1227a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1237a982d89SJeremy L. Thompson 
1247a982d89SJeremy L. Thompson   @ref Utility
1257a982d89SJeremy L. Thompson **/
1262b730f8bSJeremy L Thompson static int CeedQFunctionFieldView(CeedQFunctionField field, CeedInt field_number, bool in, FILE *stream) {
1277a982d89SJeremy L. Thompson   const char  *inout = in ? "Input" : "Output";
1288229195eSjeremylt   char        *field_name;
1298229195eSjeremylt   CeedInt      size;
1308229195eSjeremylt   CeedEvalMode eval_mode;
1311c66c397SJeremy L Thompson 
1321c66c397SJeremy L Thompson   CeedCall(CeedQFunctionFieldGetName(field, &field_name));
1331c66c397SJeremy L Thompson   CeedCall(CeedQFunctionFieldGetSize(field, &size));
1342b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionFieldGetEvalMode(field, &eval_mode));
1352b730f8bSJeremy L Thompson   fprintf(stream,
1362b730f8bSJeremy L Thompson           "    %s field %" CeedInt_FMT
1372b730f8bSJeremy L Thompson           ":\n"
1387a982d89SJeremy L. Thompson           "      Name: \"%s\"\n"
1392b730f8bSJeremy L Thompson           "      Size: %" CeedInt_FMT
1402b730f8bSJeremy L Thompson           "\n"
1417a982d89SJeremy L. Thompson           "      EvalMode: \"%s\"\n",
1428229195eSjeremylt           inout, field_number, field_name, size, CeedEvalModes[eval_mode]);
143e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1447a982d89SJeremy L. Thompson }
1457a982d89SJeremy L. Thompson 
146777ff853SJeremy L Thompson /**
147777ff853SJeremy L Thompson   @brief Set flag to determine if Fortran interface is used
148777ff853SJeremy L Thompson 
149ea61e9acSJeremy L Thompson   @param[in,out] qf     CeedQFunction
150ea61e9acSJeremy L Thompson   @param[in]     status Boolean value to set as Fortran status
151777ff853SJeremy L Thompson 
152777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
153777ff853SJeremy L Thompson 
154777ff853SJeremy L Thompson   @ref Backend
155777ff853SJeremy L Thompson **/
156777ff853SJeremy L Thompson int CeedQFunctionSetFortranStatus(CeedQFunction qf, bool status) {
157f04ea552SJeremy L Thompson   qf->is_fortran = status;
158e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
159777ff853SJeremy L Thompson }
160777ff853SJeremy L Thompson 
1617a982d89SJeremy L. Thompson /// @}
1627a982d89SJeremy L. Thompson 
1637a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
1647a982d89SJeremy L. Thompson /// CeedQFunction Backend API
1657a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
1667a982d89SJeremy L. Thompson /// @addtogroup CeedQFunctionBackend
1677a982d89SJeremy L. Thompson /// @{
1687a982d89SJeremy L. Thompson 
1697a982d89SJeremy L. Thompson /**
170ca94c3ddSJeremy L Thompson   @brief Get the vector length of a `CeedQFunction`
1717a982d89SJeremy L. Thompson 
172ca94c3ddSJeremy L Thompson   @param[in]  qf         `CeedQFunction`
173d1d35e2fSjeremylt   @param[out] vec_length Variable to store vector length
1747a982d89SJeremy L. Thompson 
1757a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1767a982d89SJeremy L. Thompson 
1777a982d89SJeremy L. Thompson   @ref Backend
1787a982d89SJeremy L. Thompson **/
179d1d35e2fSjeremylt int CeedQFunctionGetVectorLength(CeedQFunction qf, CeedInt *vec_length) {
180d1d35e2fSjeremylt   *vec_length = qf->vec_length;
181e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1827a982d89SJeremy L. Thompson }
1837a982d89SJeremy L. Thompson 
1847a982d89SJeremy L. Thompson /**
185ca94c3ddSJeremy L Thompson   @brief Get the number of inputs and outputs to a `CeedQFunction`
1867a982d89SJeremy L. Thompson 
187ca94c3ddSJeremy L Thompson   @param[in]  qf         `CeedQFunction`
188d1d35e2fSjeremylt   @param[out] num_input  Variable to store number of input fields
189d1d35e2fSjeremylt   @param[out] num_output Variable to store number of output fields
1907a982d89SJeremy L. Thompson 
1917a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1927a982d89SJeremy L. Thompson 
1937a982d89SJeremy L. Thompson   @ref Backend
1947a982d89SJeremy L. Thompson **/
1952b730f8bSJeremy L Thompson int CeedQFunctionGetNumArgs(CeedQFunction qf, CeedInt *num_input, CeedInt *num_output) {
196d1d35e2fSjeremylt   if (num_input) *num_input = qf->num_input_fields;
197d1d35e2fSjeremylt   if (num_output) *num_output = qf->num_output_fields;
198e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1997a982d89SJeremy L. Thompson }
2007a982d89SJeremy L. Thompson 
2017a982d89SJeremy L. Thompson /**
202ca94c3ddSJeremy L Thompson   @brief Get the name of the user function for a `CeedQFunction`
2037a982d89SJeremy L. Thompson 
204ca94c3ddSJeremy L Thompson   @param[in]  qf          `CeedQFunction`
20543e1b16fSJeremy L Thompson   @param[out] kernel_name Variable to store source path string
2067a982d89SJeremy L. Thompson 
2077a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2087a982d89SJeremy L. Thompson 
2097a982d89SJeremy L. Thompson   @ref Backend
2107a982d89SJeremy L. Thompson **/
21143e1b16fSJeremy L Thompson int CeedQFunctionGetKernelName(CeedQFunction qf, char **kernel_name) {
212ca5eadf8SJeremy L Thompson   if (!qf->kernel_name) {
213ca5eadf8SJeremy L Thompson     Ceed  ceed;
214ca5eadf8SJeremy L Thompson     char *kernel_name_copy;
215ca5eadf8SJeremy L Thompson 
2161c66c397SJeremy L Thompson     CeedCall(CeedQFunctionGetCeed(qf, &ceed));
217ca5eadf8SJeremy L Thompson     if (qf->user_source) {
218ca5eadf8SJeremy L Thompson       const char *kernel_name     = strrchr(qf->user_source, ':') + 1;
219ca5eadf8SJeremy L Thompson       size_t      kernel_name_len = strlen(kernel_name);
220ca5eadf8SJeremy L Thompson 
2212b730f8bSJeremy L Thompson       CeedCall(CeedCalloc(kernel_name_len + 1, &kernel_name_copy));
222ca5eadf8SJeremy L Thompson       memcpy(kernel_name_copy, kernel_name, kernel_name_len);
223ca5eadf8SJeremy L Thompson     } else {
2242b730f8bSJeremy L Thompson       CeedCall(CeedCalloc(1, &kernel_name_copy));
225ca5eadf8SJeremy L Thompson     }
226ca5eadf8SJeremy L Thompson     qf->kernel_name = kernel_name_copy;
227ca5eadf8SJeremy L Thompson   }
228ca5eadf8SJeremy L Thompson 
22943e1b16fSJeremy L Thompson   *kernel_name = (char *)qf->kernel_name;
23043e1b16fSJeremy L Thompson   return CEED_ERROR_SUCCESS;
23143e1b16fSJeremy L Thompson }
23243e1b16fSJeremy L Thompson 
23343e1b16fSJeremy L Thompson /**
234ca94c3ddSJeremy L Thompson   @brief Get the source path string for a `CeedQFunction`
23543e1b16fSJeremy L Thompson 
236ca94c3ddSJeremy L Thompson   @param[in]  qf          `CeedQFunction`
23743e1b16fSJeremy L Thompson   @param[out] source_path Variable to store source path string
23843e1b16fSJeremy L Thompson 
23943e1b16fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
24043e1b16fSJeremy L Thompson 
24143e1b16fSJeremy L Thompson   @ref Backend
24243e1b16fSJeremy L Thompson **/
24343e1b16fSJeremy L Thompson int CeedQFunctionGetSourcePath(CeedQFunction qf, char **source_path) {
244ca5eadf8SJeremy L Thompson   if (!qf->source_path && qf->user_source) {
245ca5eadf8SJeremy L Thompson     Ceed        ceed;
246ca5eadf8SJeremy L Thompson     bool        is_absolute_path;
247ca5eadf8SJeremy L Thompson     char       *absolute_path, *source_path_copy;
248ca5eadf8SJeremy L Thompson     const char *kernel_name     = strrchr(qf->user_source, ':') + 1;
249ca5eadf8SJeremy L Thompson     size_t      kernel_name_len = strlen(kernel_name);
250ca5eadf8SJeremy L Thompson 
2512b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionGetCeed(qf, &ceed));
2522b730f8bSJeremy L Thompson     CeedCall(CeedCheckFilePath(ceed, qf->user_source, &is_absolute_path));
253ca5eadf8SJeremy L Thompson     if (is_absolute_path) {
254ca5eadf8SJeremy L Thompson       absolute_path = (char *)qf->user_source;
255ca5eadf8SJeremy L Thompson     } else {
2562b730f8bSJeremy L Thompson       CeedCall(CeedGetJitAbsolutePath(ceed, qf->user_source, &absolute_path));
257ca5eadf8SJeremy L Thompson     }
258ca5eadf8SJeremy L Thompson 
259ca5eadf8SJeremy L Thompson     size_t source_len = strlen(absolute_path) - kernel_name_len - 1;
2601c66c397SJeremy L Thompson 
2612b730f8bSJeremy L Thompson     CeedCall(CeedCalloc(source_len + 1, &source_path_copy));
262ca5eadf8SJeremy L Thompson     memcpy(source_path_copy, absolute_path, source_len);
263ca5eadf8SJeremy L Thompson     qf->source_path = source_path_copy;
264ca5eadf8SJeremy L Thompson 
2652b730f8bSJeremy L Thompson     if (!is_absolute_path) CeedCall(CeedFree(&absolute_path));
266ca5eadf8SJeremy L Thompson   }
267ca5eadf8SJeremy L Thompson 
26843e1b16fSJeremy L Thompson   *source_path = (char *)qf->source_path;
269e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2707a982d89SJeremy L. Thompson }
2717a982d89SJeremy L. Thompson 
2727a982d89SJeremy L. Thompson /**
273ca94c3ddSJeremy L Thompson   @brief Initialize and load `CeedQFunction` source file into string buffer, including full text of local files in place of `#include "local.h"`.
2744385fb7fSSebastian Grimberg 
275ca94c3ddSJeremy L Thompson   The `buffer` is set to `NULL` if there is no `CeedQFunction` source file.
2764385fb7fSSebastian Grimberg 
277ca94c3ddSJeremy L Thompson   Note: Caller is responsible for freeing the string buffer with @ref CeedFree().
2783d3250a0SJeremy L Thompson 
279ca94c3ddSJeremy L Thompson   @param[in]  qf            `CeedQFunction`
280f74ec584SJeremy L Thompson   @param[out] source_buffer String buffer for source file contents
2813d3250a0SJeremy L Thompson 
2823d3250a0SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
2833d3250a0SJeremy L Thompson 
2843d3250a0SJeremy L Thompson   @ref Backend
2853d3250a0SJeremy L Thompson **/
2863d3250a0SJeremy L Thompson int CeedQFunctionLoadSourceToBuffer(CeedQFunction qf, char **source_buffer) {
2873d3250a0SJeremy L Thompson   char *source_path;
2883d3250a0SJeremy L Thompson 
2892b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionGetSourcePath(qf, &source_path));
2903d3250a0SJeremy L Thompson   *source_buffer = NULL;
2913d3250a0SJeremy L Thompson   if (source_path) {
292*1203703bSJeremy L Thompson     Ceed ceed;
293*1203703bSJeremy L Thompson 
294*1203703bSJeremy L Thompson     CeedCall(CeedQFunctionGetCeed(qf, &ceed));
295*1203703bSJeremy L Thompson     CeedCall(CeedLoadSourceToBuffer(ceed, source_path, source_buffer));
2963d3250a0SJeremy L Thompson   }
2973d3250a0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2983d3250a0SJeremy L Thompson }
2993d3250a0SJeremy L Thompson 
3003d3250a0SJeremy L Thompson /**
301ca94c3ddSJeremy L Thompson   @brief Get the User Function for a `CeedQFunction`
3027a982d89SJeremy L. Thompson 
303ca94c3ddSJeremy L Thompson   @param[in]  qf `CeedQFunction`
3047a982d89SJeremy L. Thompson   @param[out] f  Variable to store user function
3057a982d89SJeremy L. Thompson 
3067a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3077a982d89SJeremy L. Thompson 
3087a982d89SJeremy L. Thompson   @ref Backend
3097a982d89SJeremy L. Thompson **/
3107a982d89SJeremy L. Thompson int CeedQFunctionGetUserFunction(CeedQFunction qf, CeedQFunctionUser *f) {
3117a982d89SJeremy L. Thompson   *f = qf->function;
312e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3137a982d89SJeremy L. Thompson }
3147a982d89SJeremy L. Thompson 
3157a982d89SJeremy L. Thompson /**
316ca94c3ddSJeremy L Thompson   @brief Get global context for a `CeedQFunction`.
3174385fb7fSSebastian Grimberg 
318ca94c3ddSJeremy L Thompson   Note: For `CeedQFunction` from the Fortran interface, this function will return the Fortran context `CeedQFunctionContext`.
3197a982d89SJeremy L. Thompson 
320ea61e9acSJeremy L Thompson   @param[in]  qf  CeedQFunction
321777ff853SJeremy L Thompson   @param[out] ctx Variable to store CeedQFunctionContext
3227a982d89SJeremy L. Thompson 
3237a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3247a982d89SJeremy L. Thompson 
3257a982d89SJeremy L. Thompson   @ref Backend
3267a982d89SJeremy L. Thompson **/
327777ff853SJeremy L Thompson int CeedQFunctionGetContext(CeedQFunction qf, CeedQFunctionContext *ctx) {
3287a982d89SJeremy L. Thompson   *ctx = qf->ctx;
329e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3307a982d89SJeremy L. Thompson }
3317a982d89SJeremy L. Thompson 
3327a982d89SJeremy L. Thompson /**
333ca94c3ddSJeremy L Thompson   @brief Get context data of a `CeedQFunction`
334441428dfSJeremy L Thompson 
335ca94c3ddSJeremy L Thompson   @param[in]  qf       `CeedQFunction`
336ea61e9acSJeremy L Thompson   @param[in]  mem_type Memory type on which to access the data.
337ea61e9acSJeremy L Thompson                          If the backend uses a different memory type, this will perform a copy.
338441428dfSJeremy L Thompson   @param[out] data     Data on memory type mem_type
339441428dfSJeremy L Thompson 
340441428dfSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
341441428dfSJeremy L Thompson 
342441428dfSJeremy L Thompson   @ref Backend
343441428dfSJeremy L Thompson **/
3442b730f8bSJeremy L Thompson int CeedQFunctionGetContextData(CeedQFunction qf, CeedMemType mem_type, void *data) {
345441428dfSJeremy L Thompson   bool                 is_writable;
346441428dfSJeremy L Thompson   CeedQFunctionContext ctx;
347441428dfSJeremy L Thompson 
3482b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionGetContext(qf, &ctx));
349441428dfSJeremy L Thompson   if (ctx) {
3502b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionIsContextWritable(qf, &is_writable));
351441428dfSJeremy L Thompson     if (is_writable) {
3522b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextGetData(ctx, mem_type, data));
353441428dfSJeremy L Thompson     } else {
3542b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextGetDataRead(ctx, mem_type, data));
355441428dfSJeremy L Thompson     }
356441428dfSJeremy L Thompson   } else {
357441428dfSJeremy L Thompson     *(void **)data = NULL;
358441428dfSJeremy L Thompson   }
359441428dfSJeremy L Thompson   return CEED_ERROR_SUCCESS;
360441428dfSJeremy L Thompson }
361441428dfSJeremy L Thompson 
362441428dfSJeremy L Thompson /**
363ca94c3ddSJeremy L Thompson   @brief Restore context data of a `CeedQFunction`
364441428dfSJeremy L Thompson 
365ca94c3ddSJeremy L Thompson   @param[in]     qf   `CeedQFunction`
366ea61e9acSJeremy L Thompson   @param[in,out] data Data to restore
367441428dfSJeremy L Thompson 
368441428dfSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
369441428dfSJeremy L Thompson 
370441428dfSJeremy L Thompson   @ref Backend
371441428dfSJeremy L Thompson **/
372441428dfSJeremy L Thompson int CeedQFunctionRestoreContextData(CeedQFunction qf, void *data) {
373441428dfSJeremy L Thompson   bool                 is_writable;
374441428dfSJeremy L Thompson   CeedQFunctionContext ctx;
375441428dfSJeremy L Thompson 
3762b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionGetContext(qf, &ctx));
377441428dfSJeremy L Thompson   if (ctx) {
3782b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionIsContextWritable(qf, &is_writable));
379441428dfSJeremy L Thompson     if (is_writable) {
3802b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextRestoreData(ctx, data));
381441428dfSJeremy L Thompson     } else {
3822b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextRestoreDataRead(ctx, data));
383441428dfSJeremy L Thompson     }
384441428dfSJeremy L Thompson   }
3855f249b39SJeremy L Thompson   *(void **)data = NULL;
386441428dfSJeremy L Thompson   return CEED_ERROR_SUCCESS;
387441428dfSJeremy L Thompson }
388441428dfSJeremy L Thompson 
389441428dfSJeremy L Thompson /**
390ca94c3ddSJeremy L Thompson   @brief Get true user context for a `CeedQFunction`
3914385fb7fSSebastian Grimberg 
392ca94c3ddSJeremy L Thompson   Note: For all `CeedQFunction` this function will return the user `CeedQFunctionContext` and not interface context `CeedQFunctionContext`, if any such object exists.
3937a982d89SJeremy L. Thompson 
394ca94c3ddSJeremy L Thompson   @param[in]  qf  `CeedQFunction`
395ca94c3ddSJeremy L Thompson   @param[out] ctx Variable to store `CeedQFunctionContext`
3967a982d89SJeremy L. Thompson 
3977a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3987a982d89SJeremy L. Thompson   @ref Backend
3997a982d89SJeremy L. Thompson **/
400777ff853SJeremy L Thompson int CeedQFunctionGetInnerContext(CeedQFunction qf, CeedQFunctionContext *ctx) {
401*1203703bSJeremy L Thompson   CeedQFunctionContext qf_ctx;
402*1203703bSJeremy L Thompson 
403*1203703bSJeremy L Thompson   CeedCall(CeedQFunctionGetContext(qf, &qf_ctx));
404f04ea552SJeremy L Thompson   if (qf->is_fortran) {
405d1d35e2fSjeremylt     CeedFortranContext fortran_ctx = NULL;
4061c66c397SJeremy L Thompson 
407*1203703bSJeremy L Thompson     CeedCall(CeedQFunctionContextGetData(qf_ctx, CEED_MEM_HOST, &fortran_ctx));
4088cb0412aSJeremy L Thompson     *ctx = fortran_ctx->inner_ctx;
409*1203703bSJeremy L Thompson     CeedCall(CeedQFunctionContextRestoreData(qf_ctx, (void *)&fortran_ctx));
4107a982d89SJeremy L. Thompson   } else {
411*1203703bSJeremy L Thompson     *ctx = qf_ctx;
4127a982d89SJeremy L. Thompson   }
413e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4147a982d89SJeremy L. Thompson }
4157a982d89SJeremy L. Thompson 
4167a982d89SJeremy L. Thompson /**
417ca94c3ddSJeremy L Thompson   @brief Get inner context data of a `CeedQFunction`
418441428dfSJeremy L Thompson 
419ca94c3ddSJeremy L Thompson   @param[in]  qf       `CeedQFunction`
420ea61e9acSJeremy L Thompson   @param[in]  mem_type Memory type on which to access the data.
421ea61e9acSJeremy L Thompson                          If the backend uses a different memory type, this will perform a copy.
422441428dfSJeremy L Thompson   @param[out] data     Data on memory type mem_type
423441428dfSJeremy L Thompson 
424441428dfSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
425441428dfSJeremy L Thompson 
426441428dfSJeremy L Thompson   @ref Backend
427441428dfSJeremy L Thompson **/
4282b730f8bSJeremy L Thompson int CeedQFunctionGetInnerContextData(CeedQFunction qf, CeedMemType mem_type, void *data) {
429441428dfSJeremy L Thompson   bool                 is_writable;
430441428dfSJeremy L Thompson   CeedQFunctionContext ctx;
431441428dfSJeremy L Thompson 
4322b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionGetInnerContext(qf, &ctx));
433441428dfSJeremy L Thompson   if (ctx) {
4342b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionIsContextWritable(qf, &is_writable));
435441428dfSJeremy L Thompson     if (is_writable) {
4362b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextGetData(ctx, mem_type, data));
437441428dfSJeremy L Thompson     } else {
4382b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextGetDataRead(ctx, mem_type, data));
439441428dfSJeremy L Thompson     }
440441428dfSJeremy L Thompson   } else {
441441428dfSJeremy L Thompson     *(void **)data = NULL;
442441428dfSJeremy L Thompson   }
443441428dfSJeremy L Thompson   return CEED_ERROR_SUCCESS;
444441428dfSJeremy L Thompson }
445441428dfSJeremy L Thompson 
446441428dfSJeremy L Thompson /**
447ca94c3ddSJeremy L Thompson   @brief Restore inner context data of a `CeedQFunction`
448441428dfSJeremy L Thompson 
449ca94c3ddSJeremy L Thompson   @param[in]     qf   `CeedQFunction`
450ea61e9acSJeremy L Thompson   @param[in,out] data Data to restore
451441428dfSJeremy L Thompson 
452441428dfSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
453441428dfSJeremy L Thompson 
454441428dfSJeremy L Thompson   @ref Backend
455441428dfSJeremy L Thompson **/
456441428dfSJeremy L Thompson int CeedQFunctionRestoreInnerContextData(CeedQFunction qf, void *data) {
457441428dfSJeremy L Thompson   bool                 is_writable;
458441428dfSJeremy L Thompson   CeedQFunctionContext ctx;
459441428dfSJeremy L Thompson 
4602b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionGetInnerContext(qf, &ctx));
461441428dfSJeremy L Thompson   if (ctx) {
4622b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionIsContextWritable(qf, &is_writable));
463441428dfSJeremy L Thompson     if (is_writable) {
4642b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextRestoreData(ctx, data));
465441428dfSJeremy L Thompson     } else {
4662b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextRestoreDataRead(ctx, data));
467441428dfSJeremy L Thompson     }
468441428dfSJeremy L Thompson   }
4695f249b39SJeremy L Thompson   *(void **)data = NULL;
470441428dfSJeremy L Thompson   return CEED_ERROR_SUCCESS;
471441428dfSJeremy L Thompson }
472441428dfSJeremy L Thompson 
473441428dfSJeremy L Thompson /**
474ca94c3ddSJeremy L Thompson   @brief Determine if `CeedQFunction` is identity
4757a982d89SJeremy L. Thompson 
476ca94c3ddSJeremy L Thompson   @param[in]  qf          `CeedQFunction`
477d1d35e2fSjeremylt   @param[out] is_identity Variable to store identity status
4787a982d89SJeremy L. Thompson 
4797a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4807a982d89SJeremy L. Thompson 
4817a982d89SJeremy L. Thompson   @ref Backend
4827a982d89SJeremy L. Thompson **/
483d1d35e2fSjeremylt int CeedQFunctionIsIdentity(CeedQFunction qf, bool *is_identity) {
484f04ea552SJeremy L Thompson   *is_identity = qf->is_identity;
485e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4867a982d89SJeremy L. Thompson }
4877a982d89SJeremy L. Thompson 
4887a982d89SJeremy L. Thompson /**
489ca94c3ddSJeremy L Thompson   @brief Determine if `CeedQFunctionContext` is writable
490441428dfSJeremy L Thompson 
491ca94c3ddSJeremy L Thompson   @param[in]  qf          `CeedQFunction`
492ea61e9acSJeremy L Thompson   @param[out] is_writable Variable to store context writeable status
493441428dfSJeremy L Thompson 
494441428dfSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
495441428dfSJeremy L Thompson 
496441428dfSJeremy L Thompson   @ref Backend
497441428dfSJeremy L Thompson **/
498441428dfSJeremy L Thompson int CeedQFunctionIsContextWritable(CeedQFunction qf, bool *is_writable) {
499441428dfSJeremy L Thompson   *is_writable = qf->is_context_writable;
500441428dfSJeremy L Thompson   return CEED_ERROR_SUCCESS;
501441428dfSJeremy L Thompson }
502441428dfSJeremy L Thompson 
503441428dfSJeremy L Thompson /**
504ca94c3ddSJeremy L Thompson   @brief Get backend data of a `CeedQFunction`
5057a982d89SJeremy L. Thompson 
506ca94c3ddSJeremy L Thompson   @param[in]  qf   `CeedQFunction`
5077a982d89SJeremy L. Thompson   @param[out] data Variable to store data
5087a982d89SJeremy L. Thompson 
5097a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
5107a982d89SJeremy L. Thompson 
5117a982d89SJeremy L. Thompson   @ref Backend
5127a982d89SJeremy L. Thompson **/
513777ff853SJeremy L Thompson int CeedQFunctionGetData(CeedQFunction qf, void *data) {
514777ff853SJeremy L Thompson   *(void **)data = qf->data;
515e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5167a982d89SJeremy L. Thompson }
5177a982d89SJeremy L. Thompson 
5187a982d89SJeremy L. Thompson /**
519ca94c3ddSJeremy L Thompson   @brief Set backend data of a `CeedQFunction`
5207a982d89SJeremy L. Thompson 
521ca94c3ddSJeremy L Thompson   @param[in,out] qf   `CeedQFunction`
522ea61e9acSJeremy L Thompson   @param[in]     data Data to set
5237a982d89SJeremy L. Thompson 
5247a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
5257a982d89SJeremy L. Thompson 
5267a982d89SJeremy L. Thompson   @ref Backend
5277a982d89SJeremy L. Thompson **/
528777ff853SJeremy L Thompson int CeedQFunctionSetData(CeedQFunction qf, void *data) {
529777ff853SJeremy L Thompson   qf->data = data;
530e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5317a982d89SJeremy L. Thompson }
5327a982d89SJeremy L. Thompson 
5337a982d89SJeremy L. Thompson /**
534*1203703bSJeremy L Thompson   @brief Get a boolean value indicating if the `CeedQFunction` is immutable
535*1203703bSJeremy L Thompson 
536*1203703bSJeremy L Thompson   @param[in]  qf           `CeedOperator`
537*1203703bSJeremy L Thompson   @param[out] is_immutable Variable to store immutability status
538*1203703bSJeremy L Thompson 
539*1203703bSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
540*1203703bSJeremy L Thompson 
541*1203703bSJeremy L Thompson   @ref Backend
542*1203703bSJeremy L Thompson **/
543*1203703bSJeremy L Thompson int CeedQFunctionIsImmutable(CeedQFunction qf, bool *is_immutable) {
544*1203703bSJeremy L Thompson   *is_immutable = qf->is_immutable;
545*1203703bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
546*1203703bSJeremy L Thompson }
547*1203703bSJeremy L Thompson 
548*1203703bSJeremy L Thompson /**
549*1203703bSJeremy L Thompson   @brief Set the immutable flag of a `CeedQFunction` to `true`
550*1203703bSJeremy L Thompson 
551*1203703bSJeremy L Thompson   @param[in,out] qf `CeedQFunction`
552*1203703bSJeremy L Thompson 
553*1203703bSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
554*1203703bSJeremy L Thompson 
555*1203703bSJeremy L Thompson   @ref Backend
556*1203703bSJeremy L Thompson **/
557*1203703bSJeremy L Thompson int CeedQFunctionSetImmutable(CeedQFunction qf) {
558*1203703bSJeremy L Thompson   qf->is_immutable = true;
559*1203703bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
560*1203703bSJeremy L Thompson }
561*1203703bSJeremy L Thompson 
562*1203703bSJeremy L Thompson /**
563ca94c3ddSJeremy L Thompson   @brief Increment the reference counter for a `CeedQFunction`
56434359f16Sjeremylt 
565ca94c3ddSJeremy L Thompson   @param[in,out] qf `CeedQFunction` to increment the reference counter
56634359f16Sjeremylt 
56734359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
56834359f16Sjeremylt 
56934359f16Sjeremylt   @ref Backend
57034359f16Sjeremylt **/
5719560d06aSjeremylt int CeedQFunctionReference(CeedQFunction qf) {
57234359f16Sjeremylt   qf->ref_count++;
57334359f16Sjeremylt   return CEED_ERROR_SUCCESS;
57434359f16Sjeremylt }
57534359f16Sjeremylt 
5766e15d496SJeremy L Thompson /**
577ca94c3ddSJeremy L Thompson   @brief Estimate number of FLOPs per quadrature required to apply `CeedQFunction`
5786e15d496SJeremy L Thompson 
579ca94c3ddSJeremy L Thompson   @param[in]  qf    `CeedQFunction` to estimate FLOPs for
580ea61e9acSJeremy L Thompson   @param[out] flops Address of variable to hold FLOPs estimate
5816e15d496SJeremy L Thompson 
5826e15d496SJeremy L Thompson   @ref Backend
5836e15d496SJeremy L Thompson **/
5849d36ca50SJeremy L Thompson int CeedQFunctionGetFlopsEstimate(CeedQFunction qf, CeedSize *flops) {
5856e15d496SJeremy L Thompson   *flops = qf->user_flop_estimate;
5866e15d496SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5876e15d496SJeremy L Thompson }
5886e15d496SJeremy L Thompson 
5897a982d89SJeremy L. Thompson /// @}
5907a982d89SJeremy L. Thompson 
5917a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
5927a982d89SJeremy L. Thompson /// CeedQFunction Public API
5937a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
5947a982d89SJeremy L. Thompson /// @addtogroup CeedQFunctionUser
5957a982d89SJeremy L. Thompson /// @{
5967a982d89SJeremy L. Thompson 
5977a982d89SJeremy L. Thompson /**
598ca94c3ddSJeremy L Thompson   @brief Create a `CeedQFunction` for evaluating interior (volumetric) terms
5997a982d89SJeremy L. Thompson 
600ca94c3ddSJeremy L Thompson   @param[in]  ceed       `Ceed` object used to create the `CeedQFunction`
601ca94c3ddSJeremy L Thompson   @param[in]  vec_length Vector length.
602ca94c3ddSJeremy L Thompson                            Caller must ensure that number of quadrature points is a multiple of `vec_length`.
603ea61e9acSJeremy L Thompson   @param[in]  f          Function pointer to evaluate action at quadrature points.
604ca94c3ddSJeremy L Thompson                            See `CeedQFunctionUser`.
605ca94c3ddSJeremy L Thompson   @param[in]  source     Absolute path to source of `CeedQFunctionUser`, "\abs_path\file.h:function_name".
606ca94c3ddSJeremy L Thompson                            The entire source file must only contain constructs supported by all targeted backends (i.e. CUDA for `/gpu/cuda`, OpenCL/SYCL for `/gpu/sycl`, etc.).
6074ada38baSJames Wright                            The entire contents of this file and all locally included files are used during JiT compilation for GPU backends.
6084ada38baSJames Wright                            All source files must be at the provided filepath at runtime for JiT to function.
609ca94c3ddSJeremy L Thompson   @param[out] qf         Address of the variable where the newly created `CeedQFunction` will be stored
6107a982d89SJeremy L. Thompson 
6117a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
6127a982d89SJeremy L. Thompson 
613ca94c3ddSJeremy L Thompson   See \ref CeedQFunctionUser for details on the call-back function `f` arguments.
6147a982d89SJeremy L. Thompson 
6157a982d89SJeremy L. Thompson   @ref User
6167a982d89SJeremy L. Thompson **/
6172b730f8bSJeremy L Thompson int CeedQFunctionCreateInterior(Ceed ceed, CeedInt vec_length, CeedQFunctionUser f, const char *source, CeedQFunction *qf) {
618ca5eadf8SJeremy L Thompson   char *user_source_copy;
6197a982d89SJeremy L. Thompson 
6207a982d89SJeremy L. Thompson   if (!ceed->QFunctionCreate) {
6217a982d89SJeremy L. Thompson     Ceed delegate;
6226574a04fSJeremy L Thompson 
6232b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "QFunction"));
624ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support CeedQFunctionCreateInterior");
6252b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionCreateInterior(delegate, vec_length, f, source, qf));
626e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
6277a982d89SJeremy L. Thompson   }
6287a982d89SJeremy L. Thompson 
6296574a04fSJeremy L Thompson   CeedCheck(!strlen(source) || strrchr(source, ':'), ceed, CEED_ERROR_INCOMPLETE,
6306574a04fSJeremy L Thompson             "Provided path to source does not include function name. Provided: \"%s\"\nRequired: \"\\abs_path\\file.h:function_name\"", source);
63143e1b16fSJeremy L Thompson 
6322b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, qf));
633db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*qf)->ceed));
634d1d35e2fSjeremylt   (*qf)->ref_count           = 1;
635d1d35e2fSjeremylt   (*qf)->vec_length          = vec_length;
636f04ea552SJeremy L Thompson   (*qf)->is_identity         = false;
637441428dfSJeremy L Thompson   (*qf)->is_context_writable = true;
6387a982d89SJeremy L. Thompson   (*qf)->function            = f;
6396e15d496SJeremy L Thompson   (*qf)->user_flop_estimate  = -1;
64043e1b16fSJeremy L Thompson   if (strlen(source)) {
641ca5eadf8SJeremy L Thompson     size_t user_source_len = strlen(source);
642ee5a26f2SJeremy L Thompson 
6432b730f8bSJeremy L Thompson     CeedCall(CeedCalloc(user_source_len + 1, &user_source_copy));
644ca5eadf8SJeremy L Thompson     memcpy(user_source_copy, source, user_source_len);
645ca5eadf8SJeremy L Thompson     (*qf)->user_source = user_source_copy;
64643e1b16fSJeremy L Thompson   }
6472b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(CEED_FIELD_MAX, &(*qf)->input_fields));
6482b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(CEED_FIELD_MAX, &(*qf)->output_fields));
6492b730f8bSJeremy L Thompson   CeedCall(ceed->QFunctionCreate(*qf));
650e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
6517a982d89SJeremy L. Thompson }
6527a982d89SJeremy L. Thompson 
6537a982d89SJeremy L. Thompson /**
654ca94c3ddSJeremy L Thompson   @brief Create a `CeedQFunction` for evaluating interior (volumetric) terms by name
655288c0443SJeremy L Thompson 
656ca94c3ddSJeremy L Thompson   @param[in]  ceed `Ceed` object used to create the `CeedQFunction`
657ca94c3ddSJeremy L Thompson   @param[in]  name Name of `CeedQFunction` to use from gallery
658ca94c3ddSJeremy L Thompson   @param[out] qf   Address of the variable where the newly created `CeedQFunction` will be stored
659288c0443SJeremy L Thompson 
660288c0443SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
661288c0443SJeremy L Thompson 
6627a982d89SJeremy L. Thompson   @ref User
663288c0443SJeremy L Thompson **/
6642b730f8bSJeremy L Thompson int CeedQFunctionCreateInteriorByName(Ceed ceed, const char *name, CeedQFunction *qf) {
665f7e22acaSJeremy L Thompson   size_t match_len = 0, match_index = UINT_MAX;
666288c0443SJeremy L Thompson 
6672b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionRegisterAll());
668288c0443SJeremy L Thompson   // Find matching backend
669ca94c3ddSJeremy L Thompson   CeedCheck(name, ceed, CEED_ERROR_INCOMPLETE, "No CeedQFunction name provided");
670288c0443SJeremy L Thompson   for (size_t i = 0; i < num_qfunctions; i++) {
671288c0443SJeremy L Thompson     size_t      n;
672d1d35e2fSjeremylt     const char *curr_name = gallery_qfunctions[i].name;
6732b730f8bSJeremy L Thompson     for (n = 0; curr_name[n] && curr_name[n] == name[n]; n++) {
6742b730f8bSJeremy L Thompson     }
675d1d35e2fSjeremylt     if (n > match_len) {
676d1d35e2fSjeremylt       match_len   = n;
677f7e22acaSJeremy L Thompson       match_index = i;
678288c0443SJeremy L Thompson     }
679288c0443SJeremy L Thompson   }
680ca94c3ddSJeremy L Thompson   CeedCheck(match_len > 0, ceed, CEED_ERROR_UNSUPPORTED, "No suitable gallery CeedQFunction");
681288c0443SJeremy L Thompson 
682288c0443SJeremy L Thompson   // Create QFunction
6832b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionCreateInterior(ceed, gallery_qfunctions[match_index].vec_length, gallery_qfunctions[match_index].f,
6842b730f8bSJeremy L Thompson                                        gallery_qfunctions[match_index].source, qf));
685288c0443SJeremy L Thompson 
686288c0443SJeremy L Thompson   // QFunction specific setup
6872b730f8bSJeremy L Thompson   CeedCall(gallery_qfunctions[match_index].init(ceed, name, *qf));
688288c0443SJeremy L Thompson 
68975affc3bSjeremylt   // Copy name
6902b730f8bSJeremy L Thompson   CeedCall(CeedStringAllocCopy(name, (char **)&(*qf)->gallery_name));
69143e1b16fSJeremy L Thompson   (*qf)->is_gallery = true;
692e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
693288c0443SJeremy L Thompson }
694288c0443SJeremy L Thompson 
695288c0443SJeremy L Thompson /**
696ca94c3ddSJeremy L Thompson   @brief Create an identity `CeedQFunction`.
6974385fb7fSSebastian Grimberg 
698ea61e9acSJeremy L Thompson   Inputs are written into outputs in the order given.
699ca94c3ddSJeremy L Thompson   This is useful for `CeedOperator that can be represented with only the action of a `CeedElemRestriction` and `CeedBasis`, such as restriction and prolongation operators for p-multigrid.
700ca94c3ddSJeremy L Thompson   Backends may optimize `CeedOperator` with this `CeedQFunction` to avoid the copy of input data to output fields by using the same memory location for both.
7010219ea01SJeremy L Thompson 
702ca94c3ddSJeremy L Thompson   @param[in]  ceed     `Ceed` object used to create the `CeedQFunction`
703ca94c3ddSJeremy L Thompson   @param[in]  size     Size of the `CeedQFunction` fields
704ca94c3ddSJeremy L Thompson   @param[in]  in_mode  @ref CeedEvalMode for input to `CeedQFunction`
705ca94c3ddSJeremy L Thompson   @param[in]  out_mode @ref CeedEvalMode for output to `CeedQFunction`
706ca94c3ddSJeremy L Thompson   @param[out] qf       Address of the variable where the newly created `CeedQFunction` will be stored
7070219ea01SJeremy L Thompson 
7080219ea01SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
7090219ea01SJeremy L Thompson 
7107a982d89SJeremy L. Thompson   @ref User
7110219ea01SJeremy L Thompson **/
7122b730f8bSJeremy L Thompson int CeedQFunctionCreateIdentity(Ceed ceed, CeedInt size, CeedEvalMode in_mode, CeedEvalMode out_mode, CeedQFunction *qf) {
7131c66c397SJeremy L Thompson   CeedQFunctionContext  ctx;
7141c66c397SJeremy L Thompson   CeedContextFieldLabel size_label;
7151c66c397SJeremy L Thompson 
7162b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionCreateInteriorByName(ceed, "Identity", qf));
7172b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionAddInput(*qf, "input", size, in_mode));
7182b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionAddOutput(*qf, "output", size, out_mode));
7190219ea01SJeremy L Thompson 
720f04ea552SJeremy L Thompson   (*qf)->is_identity = true;
721547dbd6fSJeremy L Thompson 
7222b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionGetContext(*qf, &ctx));
7232b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextGetFieldLabel(ctx, "size", &size_label));
7242b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextSetInt32(ctx, size_label, &size));
725e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
7260219ea01SJeremy L Thompson }
7270219ea01SJeremy L Thompson 
7280219ea01SJeremy L Thompson /**
729ca94c3ddSJeremy L Thompson   @brief Copy the pointer to a `CeedQFunction`.
7304385fb7fSSebastian Grimberg 
731ca94c3ddSJeremy L Thompson   Both pointers should be destroyed with @ref CeedQFunctionDestroy().
732512bb800SJeremy L Thompson 
733ca94c3ddSJeremy L Thompson   Note: If the value of `*qf_copy` passed to this function is non-NULL, then it is assumed that `*qf_copy` is a pointer to a `CeedQFunction`.
734ca94c3ddSJeremy L Thompson         This `CeedQFunction` will be destroyed if `*qf_copy` is the only reference to this `CeedQFunction`.
7359560d06aSjeremylt 
736ca94c3ddSJeremy L Thompson   @param[in]  qf      `CeedQFunction` to copy reference to
7379560d06aSjeremylt   @param[out] qf_copy Variable to store copied reference
7389560d06aSjeremylt 
7399560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
7409560d06aSjeremylt 
7419560d06aSjeremylt   @ref User
7429560d06aSjeremylt **/
7439560d06aSjeremylt int CeedQFunctionReferenceCopy(CeedQFunction qf, CeedQFunction *qf_copy) {
7442b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionReference(qf));
7452b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionDestroy(qf_copy));
7469560d06aSjeremylt   *qf_copy = qf;
7479560d06aSjeremylt   return CEED_ERROR_SUCCESS;
7489560d06aSjeremylt }
7499560d06aSjeremylt 
7509560d06aSjeremylt /**
751ca94c3ddSJeremy L Thompson   @brief Add a `CeedQFunction` input
752b11c1e72Sjeremylt 
753ca94c3ddSJeremy L Thompson   @param[in,out] qf         `CeedQFunction`
754ca94c3ddSJeremy L Thompson   @param[in]     field_name Name of `CeedQFunction` field
755ca94c3ddSJeremy L Thompson   @param[in]     size       Size of `CeedQFunction` field, (`num_comp * 1`) for @ref CEED_EVAL_NONE, (`num_comp * 1`) for @ref CEED_EVAL_INTERP for an \f$H^1\f$ space or (`num_comp * dim`) for an \f$H(\mathrm{div})\f$ or \f$H(\mathrm{curl})\f$ space, (`num_comp * dim`) for @ref CEED_EVAL_GRAD, or (`num_comp * 1`) for @ref CEED_EVAL_DIV, and (`num_comp * curl_dim`) with `curl_dim = 1` if `dim < 3` otherwise `curl_dim = dim` for @ref CEED_EVAL_CURL.
756ca94c3ddSJeremy L Thompson   @param[in]     eval_mode  @ref CEED_EVAL_NONE to use values directly,
757ca94c3ddSJeremy L Thompson                               @ref CEED_EVAL_INTERP to use interpolated values,
758ca94c3ddSJeremy L Thompson                               @ref CEED_EVAL_GRAD to use gradients,
759ca94c3ddSJeremy L Thompson                               @ref CEED_EVAL_DIV to use divergence,
760ca94c3ddSJeremy L Thompson                               @ref CEED_EVAL_CURL to use curl
761b11c1e72Sjeremylt 
762b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
763dfdf5a53Sjeremylt 
7647a982d89SJeremy L. Thompson   @ref User
765b11c1e72Sjeremylt **/
7662b730f8bSJeremy L Thompson int CeedQFunctionAddInput(CeedQFunction qf, const char *field_name, CeedInt size, CeedEvalMode eval_mode) {
767*1203703bSJeremy L Thompson   bool is_immutable;
768*1203703bSJeremy L Thompson   Ceed ceed;
769*1203703bSJeremy L Thompson 
770*1203703bSJeremy L Thompson   CeedCall(CeedQFunctionGetCeed(qf, &ceed));
771*1203703bSJeremy L Thompson   CeedCall(CeedQFunctionIsImmutable(qf, &is_immutable));
772*1203703bSJeremy L Thompson   CeedCheck(!is_immutable, ceed, CEED_ERROR_MAJOR, "QFunction cannot be changed after set as immutable");
773*1203703bSJeremy L Thompson   CeedCheck(eval_mode != CEED_EVAL_WEIGHT || size == 1, ceed, CEED_ERROR_DIMENSION, "CEED_EVAL_WEIGHT should have size 1");
774643fbb69SJeremy L Thompson   for (CeedInt i = 0; i < qf->num_input_fields; i++) {
775*1203703bSJeremy L Thompson     CeedCheck(strcmp(field_name, qf->input_fields[i]->field_name), ceed, CEED_ERROR_MINOR, "CeedQFunction field names must be unique");
776643fbb69SJeremy L Thompson   }
777643fbb69SJeremy L Thompson   for (CeedInt i = 0; i < qf->num_output_fields; i++) {
778*1203703bSJeremy L Thompson     CeedCheck(strcmp(field_name, qf->output_fields[i]->field_name), ceed, CEED_ERROR_MINOR, "CeedQFunction field names must be unique");
779643fbb69SJeremy L Thompson   }
7802b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionFieldSet(&qf->input_fields[qf->num_input_fields], field_name, size, eval_mode));
781d1d35e2fSjeremylt   qf->num_input_fields++;
782e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
783d7b241e6Sjeremylt }
784d7b241e6Sjeremylt 
785b11c1e72Sjeremylt /**
786ca94c3ddSJeremy L Thompson   @brief Add a `CeedQFunction` output
787b11c1e72Sjeremylt 
788ca94c3ddSJeremy L Thompson   @param[in,out] qf         `CeedQFunction`
789ca94c3ddSJeremy L Thompson   @param[in]     field_name Name of `CeedQFunction` field
790ca94c3ddSJeremy L Thompson   @param[in]     size       Size of `CeedQFunction` field, (`num_comp * 1`) for @ref CEED_EVAL_NONE, (`num_comp * 1`) for @ref CEED_EVAL_INTERP for an \f$H^1\f$ space or (`num_comp * dim`) for an \f$H(\mathrm{div})\f$ or \f$H(\mathrm{curl})\f$ space, (`num_comp * dim`) for @ref CEED_EVAL_GRAD, or (`num_comp * 1`) for @ref CEED_EVAL_DIV, and (`num_comp * curl_dim`) with `curl_dim = 1` if `dim < 3` else dim for @ref CEED_EVAL_CURL.
791ca94c3ddSJeremy L Thompson   @param[in]     eval_mode  @ref CEED_EVAL_NONE to use values directly,
792ca94c3ddSJeremy L Thompson                               @ref CEED_EVAL_INTERP to use interpolated values,
793ca94c3ddSJeremy L Thompson                               @ref CEED_EVAL_GRAD to use gradients,
794ca94c3ddSJeremy L Thompson                               @ref CEED_EVAL_DIV to use divergence,
795ca94c3ddSJeremy L Thompson                               @ref CEED_EVAL_CURL to use curl.
796b11c1e72Sjeremylt 
797b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
798dfdf5a53Sjeremylt 
7997a982d89SJeremy L. Thompson   @ref User
800b11c1e72Sjeremylt **/
8012b730f8bSJeremy L Thompson int CeedQFunctionAddOutput(CeedQFunction qf, const char *field_name, CeedInt size, CeedEvalMode eval_mode) {
802*1203703bSJeremy L Thompson   bool is_immutable;
803*1203703bSJeremy L Thompson   Ceed ceed;
804*1203703bSJeremy L Thompson 
805*1203703bSJeremy L Thompson   CeedCall(CeedQFunctionGetCeed(qf, &ceed));
806*1203703bSJeremy L Thompson   CeedCall(CeedQFunctionIsImmutable(qf, &is_immutable));
807*1203703bSJeremy L Thompson   CeedCheck(!is_immutable, ceed, CEED_ERROR_MAJOR, "CeedQFunction cannot be changed after set as immutable");
808*1203703bSJeremy L Thompson   CeedCheck(eval_mode != CEED_EVAL_WEIGHT, ceed, CEED_ERROR_DIMENSION, "Cannot create CeedQFunction output with CEED_EVAL_WEIGHT");
809643fbb69SJeremy L Thompson   for (CeedInt i = 0; i < qf->num_input_fields; i++) {
810*1203703bSJeremy L Thompson     CeedCheck(strcmp(field_name, qf->input_fields[i]->field_name), ceed, CEED_ERROR_MINOR, "CeedQFunction field names must be unique");
811643fbb69SJeremy L Thompson   }
812643fbb69SJeremy L Thompson   for (CeedInt i = 0; i < qf->num_output_fields; i++) {
813*1203703bSJeremy L Thompson     CeedCheck(strcmp(field_name, qf->output_fields[i]->field_name), ceed, CEED_ERROR_MINOR, "CeedQFunction field names must be unique");
814643fbb69SJeremy L Thompson   }
8152b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionFieldSet(&qf->output_fields[qf->num_output_fields], field_name, size, eval_mode));
816d1d35e2fSjeremylt   qf->num_output_fields++;
817e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
818d7b241e6Sjeremylt }
819d7b241e6Sjeremylt 
820dfdf5a53Sjeremylt /**
821ca94c3ddSJeremy L Thompson   @brief Get the `CeedQFunctionField` of a `CeedQFunction`
82243bbe138SJeremy L Thompson 
823ca94c3ddSJeremy L Thompson   Note: Calling this function asserts that setup is complete and sets the `CeedQFunction` as immutable.
824f04ea552SJeremy L Thompson 
825ca94c3ddSJeremy L Thompson   @param[in]  qf                `CeedQFunction`
826f74ec584SJeremy L Thompson   @param[out] num_input_fields  Variable to store number of input fields
827f74ec584SJeremy L Thompson   @param[out] input_fields      Variable to store input fields
828f74ec584SJeremy L Thompson   @param[out] num_output_fields Variable to store number of output fields
829f74ec584SJeremy L Thompson   @param[out] output_fields     Variable to store output fields
83043bbe138SJeremy L Thompson 
83143bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
83243bbe138SJeremy L Thompson 
833e9b533fbSJeremy L Thompson   @ref Advanced
83443bbe138SJeremy L Thompson **/
8352b730f8bSJeremy L Thompson int CeedQFunctionGetFields(CeedQFunction qf, CeedInt *num_input_fields, CeedQFunctionField **input_fields, CeedInt *num_output_fields,
83643bbe138SJeremy L Thompson                            CeedQFunctionField **output_fields) {
837*1203703bSJeremy L Thompson   CeedCall(CeedQFunctionSetImmutable(qf));
83843bbe138SJeremy L Thompson   if (num_input_fields) *num_input_fields = qf->num_input_fields;
83943bbe138SJeremy L Thompson   if (input_fields) *input_fields = qf->input_fields;
84043bbe138SJeremy L Thompson   if (num_output_fields) *num_output_fields = qf->num_output_fields;
84143bbe138SJeremy L Thompson   if (output_fields) *output_fields = qf->output_fields;
84243bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
84343bbe138SJeremy L Thompson }
84443bbe138SJeremy L Thompson 
84543bbe138SJeremy L Thompson /**
846ca94c3ddSJeremy L Thompson   @brief Get the name of a `CeedQFunctionField`
84743bbe138SJeremy L Thompson 
848ca94c3ddSJeremy L Thompson   @param[in]  qf_field   `CeedQFunctionField`
84943bbe138SJeremy L Thompson   @param[out] field_name Variable to store the field name
85043bbe138SJeremy L Thompson 
85143bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
85243bbe138SJeremy L Thompson 
853e9b533fbSJeremy L Thompson   @ref Advanced
85443bbe138SJeremy L Thompson **/
85543bbe138SJeremy L Thompson int CeedQFunctionFieldGetName(CeedQFunctionField qf_field, char **field_name) {
85643bbe138SJeremy L Thompson   *field_name = (char *)qf_field->field_name;
85743bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
85843bbe138SJeremy L Thompson }
85943bbe138SJeremy L Thompson 
86043bbe138SJeremy L Thompson /**
861ca94c3ddSJeremy L Thompson   @brief Get the number of components of a `CeedQFunctionField`
86243bbe138SJeremy L Thompson 
863ca94c3ddSJeremy L Thompson   @param[in]  qf_field `CeedQFunctionField`
86443bbe138SJeremy L Thompson   @param[out] size     Variable to store the size of the field
86543bbe138SJeremy L Thompson 
86643bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
86743bbe138SJeremy L Thompson 
868e9b533fbSJeremy L Thompson   @ref Advanced
86943bbe138SJeremy L Thompson **/
87043bbe138SJeremy L Thompson int CeedQFunctionFieldGetSize(CeedQFunctionField qf_field, CeedInt *size) {
87143bbe138SJeremy L Thompson   *size = qf_field->size;
87243bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
87343bbe138SJeremy L Thompson }
87443bbe138SJeremy L Thompson 
87543bbe138SJeremy L Thompson /**
876ca94c3ddSJeremy L Thompson   @brief Get the @ref CeedEvalMode of a `CeedQFunctionField`
87743bbe138SJeremy L Thompson 
878ca94c3ddSJeremy L Thompson   @param[in]  qf_field  `CeedQFunctionField`
87943bbe138SJeremy L Thompson   @param[out] eval_mode Variable to store the field evaluation mode
88043bbe138SJeremy L Thompson 
88143bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
88243bbe138SJeremy L Thompson 
883e9b533fbSJeremy L Thompson   @ref Advanced
88443bbe138SJeremy L Thompson **/
8852b730f8bSJeremy L Thompson int CeedQFunctionFieldGetEvalMode(CeedQFunctionField qf_field, CeedEvalMode *eval_mode) {
88643bbe138SJeremy L Thompson   *eval_mode = qf_field->eval_mode;
88743bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
88843bbe138SJeremy L Thompson }
88943bbe138SJeremy L Thompson 
89043bbe138SJeremy L Thompson /**
891ca94c3ddSJeremy L Thompson   @brief Set global context for a `CeedQFunction`
892b11c1e72Sjeremylt 
893ca94c3ddSJeremy L Thompson   @param[in,out] qf  `CeedQFunction`
894ea61e9acSJeremy L Thompson   @param[in]     ctx Context data to set
895b11c1e72Sjeremylt 
896b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
897dfdf5a53Sjeremylt 
8987a982d89SJeremy L. Thompson   @ref User
899b11c1e72Sjeremylt **/
900777ff853SJeremy L Thompson int CeedQFunctionSetContext(CeedQFunction qf, CeedQFunctionContext ctx) {
9012b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextDestroy(&qf->ctx));
902d7b241e6Sjeremylt   qf->ctx = ctx;
903db002c03SJeremy L Thompson   if (ctx) CeedCall(CeedQFunctionContextReference(ctx));
904e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
905d7b241e6Sjeremylt }
906d7b241e6Sjeremylt 
907b11c1e72Sjeremylt /**
908ca94c3ddSJeremy L Thompson   @brief Set writability of `CeedQFunctionContext` when calling the `CeedQFunctionUser`.
9094385fb7fSSebastian Grimberg 
910859c15bbSJames Wright   The default value is `is_writable == true`.
911441428dfSJeremy L Thompson 
912ca94c3ddSJeremy L Thompson   Setting `is_writable == true` indicates the `CeedQFunctionUser` writes into the `CeedQFunctionContext` and requires memory synchronization after calling @ref CeedQFunctionApply().
913441428dfSJeremy L Thompson 
914ca94c3ddSJeremy L Thompson   Setting 'is_writable == false' asserts that `CeedQFunctionUser` does not modify the `CeedQFunctionContext`.
915ea61e9acSJeremy L Thompson   Violating this assertion may lead to inconsistent data.
916441428dfSJeremy L Thompson 
917441428dfSJeremy L Thompson   Setting `is_writable == false` may offer a performance improvement on GPU backends.
918441428dfSJeremy L Thompson 
919ca94c3ddSJeremy L Thompson   @param[in,out] qf          `CeedQFunction`
920ca94c3ddSJeremy L Thompson   @param[in]     is_writable Boolean flag for writability status
921441428dfSJeremy L Thompson 
922441428dfSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
923441428dfSJeremy L Thompson 
924441428dfSJeremy L Thompson   @ref User
925441428dfSJeremy L Thompson **/
926441428dfSJeremy L Thompson int CeedQFunctionSetContextWritable(CeedQFunction qf, bool is_writable) {
927441428dfSJeremy L Thompson   qf->is_context_writable = is_writable;
928441428dfSJeremy L Thompson   return CEED_ERROR_SUCCESS;
929441428dfSJeremy L Thompson }
930441428dfSJeremy L Thompson 
931441428dfSJeremy L Thompson /**
932ca94c3ddSJeremy L Thompson   @brief Set estimated number of FLOPs per quadrature required to apply `CeedQFunction`
9336e15d496SJeremy L Thompson 
934ca94c3ddSJeremy L Thompson   @param[in]  qf    `CeedQFunction` to estimate FLOPs for
935ea61e9acSJeremy L Thompson   @param[out] flops FLOPs per quadrature point estimate
9366e15d496SJeremy L Thompson 
9376e15d496SJeremy L Thompson   @ref Backend
9386e15d496SJeremy L Thompson **/
9399d36ca50SJeremy L Thompson int CeedQFunctionSetUserFlopsEstimate(CeedQFunction qf, CeedSize flops) {
940*1203703bSJeremy L Thompson   Ceed ceed;
941*1203703bSJeremy L Thompson 
942*1203703bSJeremy L Thompson   CeedCall(CeedQFunctionGetCeed(qf, &ceed));
943*1203703bSJeremy L Thompson   CeedCheck(flops >= 0, ceed, CEED_ERROR_INCOMPATIBLE, "Must set non-negative FLOPs estimate");
9446e15d496SJeremy L Thompson   qf->user_flop_estimate = flops;
9456e15d496SJeremy L Thompson   return CEED_ERROR_SUCCESS;
9466e15d496SJeremy L Thompson }
9476e15d496SJeremy L Thompson 
9486e15d496SJeremy L Thompson /**
949ca94c3ddSJeremy L Thompson   @brief View a `CeedQFunction`
95075affc3bSjeremylt 
951ca94c3ddSJeremy L Thompson   @param[in] qf     `CeedQFunction` to view
952ca94c3ddSJeremy L Thompson   @param[in] stream Stream to write; typically `stdout` or a file
95375affc3bSjeremylt 
95475affc3bSjeremylt   @return Error code: 0 - success, otherwise - failure
95575affc3bSjeremylt 
9567a982d89SJeremy L. Thompson   @ref User
95775affc3bSjeremylt **/
95875affc3bSjeremylt int CeedQFunctionView(CeedQFunction qf, FILE *stream) {
959ca5eadf8SJeremy L Thompson   char *kernel_name;
96075affc3bSjeremylt 
9612b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionGetKernelName(qf, &kernel_name));
9622b730f8bSJeremy L Thompson   fprintf(stream, "%sCeedQFunction - %s\n", qf->is_gallery ? "Gallery " : "User ", qf->is_gallery ? qf->gallery_name : kernel_name);
96375affc3bSjeremylt 
9642b730f8bSJeremy L Thompson   fprintf(stream, "  %" CeedInt_FMT " input field%s:\n", qf->num_input_fields, qf->num_input_fields > 1 ? "s" : "");
965d1d35e2fSjeremylt   for (CeedInt i = 0; i < qf->num_input_fields; i++) {
9662b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionFieldView(qf->input_fields[i], i, 1, stream));
96775affc3bSjeremylt   }
96875affc3bSjeremylt 
9692b730f8bSJeremy L Thompson   fprintf(stream, "  %" CeedInt_FMT " output field%s:\n", qf->num_output_fields, qf->num_output_fields > 1 ? "s" : "");
970d1d35e2fSjeremylt   for (CeedInt i = 0; i < qf->num_output_fields; i++) {
9712b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionFieldView(qf->output_fields[i], i, 0, stream));
97275affc3bSjeremylt   }
973e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
97475affc3bSjeremylt }
97575affc3bSjeremylt 
97675affc3bSjeremylt /**
977ca94c3ddSJeremy L Thompson   @brief Get the `Ceed` associated with a `CeedQFunction`
978b7c9bbdaSJeremy L Thompson 
979ca94c3ddSJeremy L Thompson   @param[in]  qf   `CeedQFunction`
980ca94c3ddSJeremy L Thompson   @param[out] ceed Variable to store`Ceed`
981b7c9bbdaSJeremy L Thompson 
982b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
983b7c9bbdaSJeremy L Thompson 
984b7c9bbdaSJeremy L Thompson   @ref Advanced
985b7c9bbdaSJeremy L Thompson **/
986b7c9bbdaSJeremy L Thompson int CeedQFunctionGetCeed(CeedQFunction qf, Ceed *ceed) {
987b7c9bbdaSJeremy L Thompson   *ceed = qf->ceed;
988b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
989b7c9bbdaSJeremy L Thompson }
990b7c9bbdaSJeremy L Thompson 
991b7c9bbdaSJeremy L Thompson /**
992ca94c3ddSJeremy L Thompson   @brief Apply the action of a `CeedQFunction`
993b11c1e72Sjeremylt 
994ca94c3ddSJeremy L Thompson   Note: Calling this function asserts that setup is complete and sets the `CeedQFunction` as immutable.
995f04ea552SJeremy L Thompson 
996ca94c3ddSJeremy L Thompson   @param[in]  qf `CeedQFunction`
997ea61e9acSJeremy L Thompson   @param[in]  Q  Number of quadrature points
998ca94c3ddSJeremy L Thompson   @param[in]  u  Array of input `CeedVector`
999ca94c3ddSJeremy L Thompson   @param[out] v  Array of output `CeedVector`
1000b11c1e72Sjeremylt 
1001b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1002dfdf5a53Sjeremylt 
10037a982d89SJeremy L. Thompson   @ref User
1004b11c1e72Sjeremylt **/
10052b730f8bSJeremy L Thompson int CeedQFunctionApply(CeedQFunction qf, CeedInt Q, CeedVector *u, CeedVector *v) {
1006*1203703bSJeremy L Thompson   CeedInt vec_length;
1007*1203703bSJeremy L Thompson   Ceed    ceed;
1008*1203703bSJeremy L Thompson 
1009*1203703bSJeremy L Thompson   CeedCall(CeedQFunctionGetCeed(qf, &ceed));
1010*1203703bSJeremy L Thompson   CeedCheck(qf->Apply, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support CeedQFunctionApply");
1011*1203703bSJeremy L Thompson   CeedCall(CeedQFunctionGetVectorLength(qf, &vec_length));
1012*1203703bSJeremy L Thompson   CeedCheck(Q % vec_length == 0, ceed, CEED_ERROR_DIMENSION, "Number of quadrature points %" CeedInt_FMT " must be a multiple of %" CeedInt_FMT, Q,
1013*1203703bSJeremy L Thompson             qf->vec_length);
1014*1203703bSJeremy L Thompson   CeedCall(CeedQFunctionSetImmutable(qf));
10152b730f8bSJeremy L Thompson   CeedCall(qf->Apply(qf, Q, u, v));
1016e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1017d7b241e6Sjeremylt }
1018d7b241e6Sjeremylt 
1019b11c1e72Sjeremylt /**
1020ca94c3ddSJeremy L Thompson   @brief Destroy a `CeedQFunction`
1021b11c1e72Sjeremylt 
1022ca94c3ddSJeremy L Thompson   @param[in,out] qf `CeedQFunction` to destroy
1023b11c1e72Sjeremylt 
1024b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1025dfdf5a53Sjeremylt 
10267a982d89SJeremy L. Thompson   @ref User
1027b11c1e72Sjeremylt **/
1028d7b241e6Sjeremylt int CeedQFunctionDestroy(CeedQFunction *qf) {
1029ad6481ceSJeremy L Thompson   if (!*qf || --(*qf)->ref_count > 0) {
1030ad6481ceSJeremy L Thompson     *qf = NULL;
1031ad6481ceSJeremy L Thompson     return CEED_ERROR_SUCCESS;
1032ad6481ceSJeremy L Thompson   }
1033fe2413ffSjeremylt   // Backend destroy
1034d7b241e6Sjeremylt   if ((*qf)->Destroy) {
10352b730f8bSJeremy L Thompson     CeedCall((*qf)->Destroy(*qf));
1036d7b241e6Sjeremylt   }
1037fe2413ffSjeremylt   // Free fields
103892ae7e47SJeremy L Thompson   for (CeedInt i = 0; i < (*qf)->num_input_fields; i++) {
10392b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*(*qf)->input_fields[i]).field_name));
10402b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*qf)->input_fields[i]));
1041fe2413ffSjeremylt   }
104292ae7e47SJeremy L Thompson   for (CeedInt i = 0; i < (*qf)->num_output_fields; i++) {
10432b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*(*qf)->output_fields[i]).field_name));
10442b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*qf)->output_fields[i]));
1045fe2413ffSjeremylt   }
10462b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*qf)->input_fields));
10472b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*qf)->output_fields));
1048777ff853SJeremy L Thompson 
1049777ff853SJeremy L Thompson   // User context data object
10502b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextDestroy(&(*qf)->ctx));
1051fe2413ffSjeremylt 
10522b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*qf)->user_source));
10532b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*qf)->source_path));
10542b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*qf)->gallery_name));
10552b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*qf)->kernel_name));
10562b730f8bSJeremy L Thompson   CeedCall(CeedDestroy(&(*qf)->ceed));
10572b730f8bSJeremy L Thompson   CeedCall(CeedFree(qf));
1058e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1059d7b241e6Sjeremylt }
1060d7b241e6Sjeremylt 
1061d7b241e6Sjeremylt /// @}
1062