xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-qfunction.c (revision f8d308fa18b022a1638a735475f693446671ab36)
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";
1286f8994e9SJeremy L Thompson   const char  *field_name;
1298229195eSjeremylt   CeedInt      size;
1308229195eSjeremylt   CeedEvalMode eval_mode;
1311c66c397SJeremy L Thompson 
132ab747706SJeremy L Thompson   CeedCall(CeedQFunctionFieldGetData(field, &field_name, &size, &eval_mode));
1332b730f8bSJeremy L Thompson   fprintf(stream,
1342b730f8bSJeremy L Thompson           "    %s field %" CeedInt_FMT
1352b730f8bSJeremy L Thompson           ":\n"
1367a982d89SJeremy L. Thompson           "      Name: \"%s\"\n"
1372b730f8bSJeremy L Thompson           "      Size: %" CeedInt_FMT
1382b730f8bSJeremy L Thompson           "\n"
1397a982d89SJeremy L. Thompson           "      EvalMode: \"%s\"\n",
1408229195eSjeremylt           inout, field_number, field_name, size, CeedEvalModes[eval_mode]);
141e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1427a982d89SJeremy L. Thompson }
1437a982d89SJeremy L. Thompson 
144777ff853SJeremy L Thompson /**
145777ff853SJeremy L Thompson   @brief Set flag to determine if Fortran interface is used
146777ff853SJeremy L Thompson 
147ea61e9acSJeremy L Thompson   @param[in,out] qf     CeedQFunction
148ea61e9acSJeremy L Thompson   @param[in]     status Boolean value to set as Fortran status
149777ff853SJeremy L Thompson 
150777ff853SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
151777ff853SJeremy L Thompson 
152777ff853SJeremy L Thompson   @ref Backend
153777ff853SJeremy L Thompson **/
154777ff853SJeremy L Thompson int CeedQFunctionSetFortranStatus(CeedQFunction qf, bool status) {
155f04ea552SJeremy L Thompson   qf->is_fortran = status;
156e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
157777ff853SJeremy L Thompson }
158777ff853SJeremy L Thompson 
1597a982d89SJeremy L. Thompson /// @}
1607a982d89SJeremy L. Thompson 
1617a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
1627a982d89SJeremy L. Thompson /// CeedQFunction Backend API
1637a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
1647a982d89SJeremy L. Thompson /// @addtogroup CeedQFunctionBackend
1657a982d89SJeremy L. Thompson /// @{
1667a982d89SJeremy L. Thompson 
1677a982d89SJeremy L. Thompson /**
168ca94c3ddSJeremy L Thompson   @brief Get the vector length of a `CeedQFunction`
1697a982d89SJeremy L. Thompson 
170ca94c3ddSJeremy L Thompson   @param[in]  qf         `CeedQFunction`
171d1d35e2fSjeremylt   @param[out] vec_length Variable to store vector length
1727a982d89SJeremy L. Thompson 
1737a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1747a982d89SJeremy L. Thompson 
1757a982d89SJeremy L. Thompson   @ref Backend
1767a982d89SJeremy L. Thompson **/
177d1d35e2fSjeremylt int CeedQFunctionGetVectorLength(CeedQFunction qf, CeedInt *vec_length) {
178d1d35e2fSjeremylt   *vec_length = qf->vec_length;
179e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1807a982d89SJeremy L. Thompson }
1817a982d89SJeremy L. Thompson 
1827a982d89SJeremy L. Thompson /**
183ca94c3ddSJeremy L Thompson   @brief Get the number of inputs and outputs to a `CeedQFunction`
1847a982d89SJeremy L. Thompson 
185ca94c3ddSJeremy L Thompson   @param[in]  qf         `CeedQFunction`
186d1d35e2fSjeremylt   @param[out] num_input  Variable to store number of input fields
187d1d35e2fSjeremylt   @param[out] num_output Variable to store number of output fields
1887a982d89SJeremy L. Thompson 
1897a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1907a982d89SJeremy L. Thompson 
1917a982d89SJeremy L. Thompson   @ref Backend
1927a982d89SJeremy L. Thompson **/
1932b730f8bSJeremy L Thompson int CeedQFunctionGetNumArgs(CeedQFunction qf, CeedInt *num_input, CeedInt *num_output) {
194d1d35e2fSjeremylt   if (num_input) *num_input = qf->num_input_fields;
195d1d35e2fSjeremylt   if (num_output) *num_output = qf->num_output_fields;
196e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1977a982d89SJeremy L. Thompson }
1987a982d89SJeremy L. Thompson 
1997a982d89SJeremy L. Thompson /**
200ca94c3ddSJeremy L Thompson   @brief Get the name of the user function for a `CeedQFunction`
2017a982d89SJeremy L. Thompson 
202ca94c3ddSJeremy L Thompson   @param[in]  qf          `CeedQFunction`
20343e1b16fSJeremy L Thompson   @param[out] kernel_name Variable to store source path string
2047a982d89SJeremy L. Thompson 
2057a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2067a982d89SJeremy L. Thompson 
2077a982d89SJeremy L. Thompson   @ref Backend
2087a982d89SJeremy L. Thompson **/
2097d023984SJeremy L Thompson int CeedQFunctionGetKernelName(CeedQFunction qf, const char **kernel_name) {
210ca5eadf8SJeremy L Thompson   if (!qf->kernel_name) {
211ca5eadf8SJeremy L Thompson     Ceed  ceed;
212ca5eadf8SJeremy L Thompson     char *kernel_name_copy;
213ca5eadf8SJeremy L Thompson 
2141c66c397SJeremy L Thompson     CeedCall(CeedQFunctionGetCeed(qf, &ceed));
215ca5eadf8SJeremy L Thompson     if (qf->user_source) {
216ca5eadf8SJeremy L Thompson       const char *kernel_name     = strrchr(qf->user_source, ':') + 1;
217ca5eadf8SJeremy L Thompson       size_t      kernel_name_len = strlen(kernel_name);
218ca5eadf8SJeremy L Thompson 
2192b730f8bSJeremy L Thompson       CeedCall(CeedCalloc(kernel_name_len + 1, &kernel_name_copy));
220ca5eadf8SJeremy L Thompson       memcpy(kernel_name_copy, kernel_name, kernel_name_len);
221ca5eadf8SJeremy L Thompson     } else {
2222b730f8bSJeremy L Thompson       CeedCall(CeedCalloc(1, &kernel_name_copy));
223ca5eadf8SJeremy L Thompson     }
224ca5eadf8SJeremy L Thompson     qf->kernel_name = kernel_name_copy;
225ca5eadf8SJeremy L Thompson   }
226ca5eadf8SJeremy L Thompson 
2277d023984SJeremy L Thompson   *kernel_name = qf->kernel_name;
22843e1b16fSJeremy L Thompson   return CEED_ERROR_SUCCESS;
22943e1b16fSJeremy L Thompson }
23043e1b16fSJeremy L Thompson 
23143e1b16fSJeremy L Thompson /**
232ca94c3ddSJeremy L Thompson   @brief Get the source path string for a `CeedQFunction`
23343e1b16fSJeremy L Thompson 
234ca94c3ddSJeremy L Thompson   @param[in]  qf          `CeedQFunction`
23543e1b16fSJeremy L Thompson   @param[out] source_path Variable to store source path string
23643e1b16fSJeremy L Thompson 
23743e1b16fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
23843e1b16fSJeremy L Thompson 
23943e1b16fSJeremy L Thompson   @ref Backend
24043e1b16fSJeremy L Thompson **/
24134ffed21SJeremy L Thompson int CeedQFunctionGetSourcePath(CeedQFunction qf, const char **source_path) {
242ca5eadf8SJeremy L Thompson   if (!qf->source_path && qf->user_source) {
243ca5eadf8SJeremy L Thompson     Ceed        ceed;
244ca5eadf8SJeremy L Thompson     bool        is_absolute_path;
245ca5eadf8SJeremy L Thompson     char       *absolute_path, *source_path_copy;
246ca5eadf8SJeremy L Thompson     const char *kernel_name     = strrchr(qf->user_source, ':') + 1;
247ca5eadf8SJeremy L Thompson     size_t      kernel_name_len = strlen(kernel_name);
248ca5eadf8SJeremy L Thompson 
2492b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionGetCeed(qf, &ceed));
2502b730f8bSJeremy L Thompson     CeedCall(CeedCheckFilePath(ceed, qf->user_source, &is_absolute_path));
251ca5eadf8SJeremy L Thompson     if (is_absolute_path) {
252ca5eadf8SJeremy L Thompson       absolute_path = (char *)qf->user_source;
253ca5eadf8SJeremy L Thompson     } else {
2542b730f8bSJeremy L Thompson       CeedCall(CeedGetJitAbsolutePath(ceed, qf->user_source, &absolute_path));
255ca5eadf8SJeremy L Thompson     }
256ca5eadf8SJeremy L Thompson 
257ca5eadf8SJeremy L Thompson     size_t source_len = strlen(absolute_path) - kernel_name_len - 1;
2581c66c397SJeremy L Thompson 
2592b730f8bSJeremy L Thompson     CeedCall(CeedCalloc(source_len + 1, &source_path_copy));
260ca5eadf8SJeremy L Thompson     memcpy(source_path_copy, absolute_path, source_len);
261ca5eadf8SJeremy L Thompson     qf->source_path = source_path_copy;
262ca5eadf8SJeremy L Thompson 
2632b730f8bSJeremy L Thompson     if (!is_absolute_path) CeedCall(CeedFree(&absolute_path));
264ca5eadf8SJeremy L Thompson   }
265ca5eadf8SJeremy L Thompson 
26643e1b16fSJeremy L Thompson   *source_path = (char *)qf->source_path;
267e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2687a982d89SJeremy L. Thompson }
2697a982d89SJeremy L. Thompson 
2707a982d89SJeremy L. Thompson /**
271ca94c3ddSJeremy L Thompson   @brief Initialize and load `CeedQFunction` source file into string buffer, including full text of local files in place of `#include "local.h"`.
2724385fb7fSSebastian Grimberg 
273ca94c3ddSJeremy L Thompson   The `buffer` is set to `NULL` if there is no `CeedQFunction` source file.
2744385fb7fSSebastian Grimberg 
275*f8d308faSJed Brown   Note: This function may as well return a mutable buffer, but all current uses
276*f8d308faSJed Brown   do not modify it. (This is just a downside of `const` semantics with output
277*f8d308faSJed Brown   arguments instead of returns.)
278*f8d308faSJed Brown 
279ca94c3ddSJeremy L Thompson   Note: Caller is responsible for freeing the string buffer with @ref CeedFree().
2803d3250a0SJeremy L Thompson 
281ca94c3ddSJeremy L Thompson   @param[in]  qf            `CeedQFunction`
282f74ec584SJeremy L Thompson   @param[out] source_buffer String buffer for source file contents
2833d3250a0SJeremy L Thompson 
2843d3250a0SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
2853d3250a0SJeremy L Thompson 
2863d3250a0SJeremy L Thompson   @ref Backend
2873d3250a0SJeremy L Thompson **/
288*f8d308faSJed Brown int CeedQFunctionLoadSourceToBuffer(CeedQFunction qf, const char **source_buffer) {
28934ffed21SJeremy L Thompson   const char *source_path;
2903d3250a0SJeremy L Thompson 
2912b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionGetSourcePath(qf, &source_path));
2923d3250a0SJeremy L Thompson   *source_buffer = NULL;
2933d3250a0SJeremy L Thompson   if (source_path) {
2941203703bSJeremy L Thompson     Ceed  ceed;
295*f8d308faSJed Brown     char *buffer = NULL;
2961203703bSJeremy L Thompson 
2971203703bSJeremy L Thompson     CeedCall(CeedQFunctionGetCeed(qf, &ceed));
298*f8d308faSJed Brown     CeedCall(CeedLoadSourceToBuffer(ceed, source_path, &buffer));
299*f8d308faSJed Brown     *source_buffer = buffer;
3003d3250a0SJeremy L Thompson   }
3013d3250a0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3023d3250a0SJeremy L Thompson }
3033d3250a0SJeremy L Thompson 
3043d3250a0SJeremy L Thompson /**
305ca94c3ddSJeremy L Thompson   @brief Get the User Function for a `CeedQFunction`
3067a982d89SJeremy L. Thompson 
307ca94c3ddSJeremy L Thompson   @param[in]  qf `CeedQFunction`
3087a982d89SJeremy L. Thompson   @param[out] f  Variable to store user function
3097a982d89SJeremy L. Thompson 
3107a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3117a982d89SJeremy L. Thompson 
3127a982d89SJeremy L. Thompson   @ref Backend
3137a982d89SJeremy L. Thompson **/
3147a982d89SJeremy L. Thompson int CeedQFunctionGetUserFunction(CeedQFunction qf, CeedQFunctionUser *f) {
3157a982d89SJeremy L. Thompson   *f = qf->function;
316e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3177a982d89SJeremy L. Thompson }
3187a982d89SJeremy L. Thompson 
3197a982d89SJeremy L. Thompson /**
320ca94c3ddSJeremy L Thompson   @brief Get global context for a `CeedQFunction`.
3214385fb7fSSebastian Grimberg 
322ca94c3ddSJeremy L Thompson   Note: For `CeedQFunction` from the Fortran interface, this function will return the Fortran context `CeedQFunctionContext`.
3237a982d89SJeremy L. Thompson 
324ea61e9acSJeremy L Thompson   @param[in]  qf  CeedQFunction
325777ff853SJeremy L Thompson   @param[out] ctx Variable to store CeedQFunctionContext
3267a982d89SJeremy L. Thompson 
3277a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3287a982d89SJeremy L. Thompson 
3297a982d89SJeremy L. Thompson   @ref Backend
3307a982d89SJeremy L. Thompson **/
331777ff853SJeremy L Thompson int CeedQFunctionGetContext(CeedQFunction qf, CeedQFunctionContext *ctx) {
3327a982d89SJeremy L. Thompson   *ctx = qf->ctx;
333e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3347a982d89SJeremy L. Thompson }
3357a982d89SJeremy L. Thompson 
3367a982d89SJeremy L. Thompson /**
337ca94c3ddSJeremy L Thompson   @brief Get context data of a `CeedQFunction`
338441428dfSJeremy L Thompson 
339ca94c3ddSJeremy L Thompson   @param[in]  qf       `CeedQFunction`
340ea61e9acSJeremy L Thompson   @param[in]  mem_type Memory type on which to access the data.
341ea61e9acSJeremy L Thompson                          If the backend uses a different memory type, this will perform a copy.
342441428dfSJeremy L Thompson   @param[out] data     Data on memory type mem_type
343441428dfSJeremy L Thompson 
344441428dfSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
345441428dfSJeremy L Thompson 
346441428dfSJeremy L Thompson   @ref Backend
347441428dfSJeremy L Thompson **/
3482b730f8bSJeremy L Thompson int CeedQFunctionGetContextData(CeedQFunction qf, CeedMemType mem_type, void *data) {
349441428dfSJeremy L Thompson   bool                 is_writable;
350441428dfSJeremy L Thompson   CeedQFunctionContext ctx;
351441428dfSJeremy L Thompson 
3522b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionGetContext(qf, &ctx));
353441428dfSJeremy L Thompson   if (ctx) {
3542b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionIsContextWritable(qf, &is_writable));
355441428dfSJeremy L Thompson     if (is_writable) {
3562b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextGetData(ctx, mem_type, data));
357441428dfSJeremy L Thompson     } else {
3582b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextGetDataRead(ctx, mem_type, data));
359441428dfSJeremy L Thompson     }
360441428dfSJeremy L Thompson   } else {
361441428dfSJeremy L Thompson     *(void **)data = NULL;
362441428dfSJeremy L Thompson   }
363441428dfSJeremy L Thompson   return CEED_ERROR_SUCCESS;
364441428dfSJeremy L Thompson }
365441428dfSJeremy L Thompson 
366441428dfSJeremy L Thompson /**
367ca94c3ddSJeremy L Thompson   @brief Restore context data of a `CeedQFunction`
368441428dfSJeremy L Thompson 
369ca94c3ddSJeremy L Thompson   @param[in]     qf   `CeedQFunction`
370ea61e9acSJeremy L Thompson   @param[in,out] data Data to restore
371441428dfSJeremy L Thompson 
372441428dfSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
373441428dfSJeremy L Thompson 
374441428dfSJeremy L Thompson   @ref Backend
375441428dfSJeremy L Thompson **/
376441428dfSJeremy L Thompson int CeedQFunctionRestoreContextData(CeedQFunction qf, void *data) {
377441428dfSJeremy L Thompson   bool                 is_writable;
378441428dfSJeremy L Thompson   CeedQFunctionContext ctx;
379441428dfSJeremy L Thompson 
3802b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionGetContext(qf, &ctx));
381441428dfSJeremy L Thompson   if (ctx) {
3822b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionIsContextWritable(qf, &is_writable));
383441428dfSJeremy L Thompson     if (is_writable) {
3842b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextRestoreData(ctx, data));
385441428dfSJeremy L Thompson     } else {
3862b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextRestoreDataRead(ctx, data));
387441428dfSJeremy L Thompson     }
388441428dfSJeremy L Thompson   }
3895f249b39SJeremy L Thompson   *(void **)data = NULL;
390441428dfSJeremy L Thompson   return CEED_ERROR_SUCCESS;
391441428dfSJeremy L Thompson }
392441428dfSJeremy L Thompson 
393441428dfSJeremy L Thompson /**
394ca94c3ddSJeremy L Thompson   @brief Get true user context for a `CeedQFunction`
3954385fb7fSSebastian Grimberg 
396ca94c3ddSJeremy L Thompson   Note: For all `CeedQFunction` this function will return the user `CeedQFunctionContext` and not interface context `CeedQFunctionContext`, if any such object exists.
3977a982d89SJeremy L. Thompson 
398ca94c3ddSJeremy L Thompson   @param[in]  qf  `CeedQFunction`
399ca94c3ddSJeremy L Thompson   @param[out] ctx Variable to store `CeedQFunctionContext`
4007a982d89SJeremy L. Thompson 
4017a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4027a982d89SJeremy L. Thompson   @ref Backend
4037a982d89SJeremy L. Thompson **/
404777ff853SJeremy L Thompson int CeedQFunctionGetInnerContext(CeedQFunction qf, CeedQFunctionContext *ctx) {
4051203703bSJeremy L Thompson   CeedQFunctionContext qf_ctx;
4061203703bSJeremy L Thompson 
4071203703bSJeremy L Thompson   CeedCall(CeedQFunctionGetContext(qf, &qf_ctx));
408f04ea552SJeremy L Thompson   if (qf->is_fortran) {
409d1d35e2fSjeremylt     CeedFortranContext fortran_ctx = NULL;
4101c66c397SJeremy L Thompson 
4111203703bSJeremy L Thompson     CeedCall(CeedQFunctionContextGetData(qf_ctx, CEED_MEM_HOST, &fortran_ctx));
4128cb0412aSJeremy L Thompson     *ctx = fortran_ctx->inner_ctx;
4131203703bSJeremy L Thompson     CeedCall(CeedQFunctionContextRestoreData(qf_ctx, (void *)&fortran_ctx));
4147a982d89SJeremy L. Thompson   } else {
4151203703bSJeremy L Thompson     *ctx = qf_ctx;
4167a982d89SJeremy L. Thompson   }
417e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4187a982d89SJeremy L. Thompson }
4197a982d89SJeremy L. Thompson 
4207a982d89SJeremy L. Thompson /**
421ca94c3ddSJeremy L Thompson   @brief Get inner context data of a `CeedQFunction`
422441428dfSJeremy L Thompson 
423ca94c3ddSJeremy L Thompson   @param[in]  qf       `CeedQFunction`
424ea61e9acSJeremy L Thompson   @param[in]  mem_type Memory type on which to access the data.
425ea61e9acSJeremy L Thompson                          If the backend uses a different memory type, this will perform a copy.
426441428dfSJeremy L Thompson   @param[out] data     Data on memory type mem_type
427441428dfSJeremy L Thompson 
428441428dfSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
429441428dfSJeremy L Thompson 
430441428dfSJeremy L Thompson   @ref Backend
431441428dfSJeremy L Thompson **/
4322b730f8bSJeremy L Thompson int CeedQFunctionGetInnerContextData(CeedQFunction qf, CeedMemType mem_type, void *data) {
433441428dfSJeremy L Thompson   bool                 is_writable;
434441428dfSJeremy L Thompson   CeedQFunctionContext ctx;
435441428dfSJeremy L Thompson 
4362b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionGetInnerContext(qf, &ctx));
437441428dfSJeremy L Thompson   if (ctx) {
4382b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionIsContextWritable(qf, &is_writable));
439441428dfSJeremy L Thompson     if (is_writable) {
4402b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextGetData(ctx, mem_type, data));
441441428dfSJeremy L Thompson     } else {
4422b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextGetDataRead(ctx, mem_type, data));
443441428dfSJeremy L Thompson     }
444441428dfSJeremy L Thompson   } else {
445441428dfSJeremy L Thompson     *(void **)data = NULL;
446441428dfSJeremy L Thompson   }
447441428dfSJeremy L Thompson   return CEED_ERROR_SUCCESS;
448441428dfSJeremy L Thompson }
449441428dfSJeremy L Thompson 
450441428dfSJeremy L Thompson /**
451ca94c3ddSJeremy L Thompson   @brief Restore inner context data of a `CeedQFunction`
452441428dfSJeremy L Thompson 
453ca94c3ddSJeremy L Thompson   @param[in]     qf   `CeedQFunction`
454ea61e9acSJeremy L Thompson   @param[in,out] data Data to restore
455441428dfSJeremy L Thompson 
456441428dfSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
457441428dfSJeremy L Thompson 
458441428dfSJeremy L Thompson   @ref Backend
459441428dfSJeremy L Thompson **/
460441428dfSJeremy L Thompson int CeedQFunctionRestoreInnerContextData(CeedQFunction qf, void *data) {
461441428dfSJeremy L Thompson   bool                 is_writable;
462441428dfSJeremy L Thompson   CeedQFunctionContext ctx;
463441428dfSJeremy L Thompson 
4642b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionGetInnerContext(qf, &ctx));
465441428dfSJeremy L Thompson   if (ctx) {
4662b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionIsContextWritable(qf, &is_writable));
467441428dfSJeremy L Thompson     if (is_writable) {
4682b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextRestoreData(ctx, data));
469441428dfSJeremy L Thompson     } else {
4702b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextRestoreDataRead(ctx, data));
471441428dfSJeremy L Thompson     }
472441428dfSJeremy L Thompson   }
4735f249b39SJeremy L Thompson   *(void **)data = NULL;
474441428dfSJeremy L Thompson   return CEED_ERROR_SUCCESS;
475441428dfSJeremy L Thompson }
476441428dfSJeremy L Thompson 
477441428dfSJeremy L Thompson /**
478ca94c3ddSJeremy L Thompson   @brief Determine if `CeedQFunction` is identity
4797a982d89SJeremy L. Thompson 
480ca94c3ddSJeremy L Thompson   @param[in]  qf          `CeedQFunction`
481d1d35e2fSjeremylt   @param[out] is_identity Variable to store identity status
4827a982d89SJeremy L. Thompson 
4837a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4847a982d89SJeremy L. Thompson 
4857a982d89SJeremy L. Thompson   @ref Backend
4867a982d89SJeremy L. Thompson **/
487d1d35e2fSjeremylt int CeedQFunctionIsIdentity(CeedQFunction qf, bool *is_identity) {
488f04ea552SJeremy L Thompson   *is_identity = qf->is_identity;
489e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4907a982d89SJeremy L. Thompson }
4917a982d89SJeremy L. Thompson 
4927a982d89SJeremy L. Thompson /**
493ca94c3ddSJeremy L Thompson   @brief Determine if `CeedQFunctionContext` is writable
494441428dfSJeremy L Thompson 
495ca94c3ddSJeremy L Thompson   @param[in]  qf          `CeedQFunction`
496ea61e9acSJeremy L Thompson   @param[out] is_writable Variable to store context writeable status
497441428dfSJeremy L Thompson 
498441428dfSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
499441428dfSJeremy L Thompson 
500441428dfSJeremy L Thompson   @ref Backend
501441428dfSJeremy L Thompson **/
502441428dfSJeremy L Thompson int CeedQFunctionIsContextWritable(CeedQFunction qf, bool *is_writable) {
503441428dfSJeremy L Thompson   *is_writable = qf->is_context_writable;
504441428dfSJeremy L Thompson   return CEED_ERROR_SUCCESS;
505441428dfSJeremy L Thompson }
506441428dfSJeremy L Thompson 
507441428dfSJeremy L Thompson /**
508ca94c3ddSJeremy L Thompson   @brief Get backend data of a `CeedQFunction`
5097a982d89SJeremy L. Thompson 
510ca94c3ddSJeremy L Thompson   @param[in]  qf   `CeedQFunction`
5117a982d89SJeremy L. Thompson   @param[out] data Variable to store data
5127a982d89SJeremy L. Thompson 
5137a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
5147a982d89SJeremy L. Thompson 
5157a982d89SJeremy L. Thompson   @ref Backend
5167a982d89SJeremy L. Thompson **/
517777ff853SJeremy L Thompson int CeedQFunctionGetData(CeedQFunction qf, void *data) {
518777ff853SJeremy L Thompson   *(void **)data = qf->data;
519e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5207a982d89SJeremy L. Thompson }
5217a982d89SJeremy L. Thompson 
5227a982d89SJeremy L. Thompson /**
523ca94c3ddSJeremy L Thompson   @brief Set backend data of a `CeedQFunction`
5247a982d89SJeremy L. Thompson 
525ca94c3ddSJeremy L Thompson   @param[in,out] qf   `CeedQFunction`
526ea61e9acSJeremy L Thompson   @param[in]     data Data to set
5277a982d89SJeremy L. Thompson 
5287a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
5297a982d89SJeremy L. Thompson 
5307a982d89SJeremy L. Thompson   @ref Backend
5317a982d89SJeremy L. Thompson **/
532777ff853SJeremy L Thompson int CeedQFunctionSetData(CeedQFunction qf, void *data) {
533777ff853SJeremy L Thompson   qf->data = data;
534e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5357a982d89SJeremy L. Thompson }
5367a982d89SJeremy L. Thompson 
5377a982d89SJeremy L. Thompson /**
5381203703bSJeremy L Thompson   @brief Get a boolean value indicating if the `CeedQFunction` is immutable
5391203703bSJeremy L Thompson 
5401203703bSJeremy L Thompson   @param[in]  qf           `CeedOperator`
5411203703bSJeremy L Thompson   @param[out] is_immutable Variable to store immutability status
5421203703bSJeremy L Thompson 
5431203703bSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
5441203703bSJeremy L Thompson 
5451203703bSJeremy L Thompson   @ref Backend
5461203703bSJeremy L Thompson **/
5471203703bSJeremy L Thompson int CeedQFunctionIsImmutable(CeedQFunction qf, bool *is_immutable) {
5481203703bSJeremy L Thompson   *is_immutable = qf->is_immutable;
5491203703bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
5501203703bSJeremy L Thompson }
5511203703bSJeremy L Thompson 
5521203703bSJeremy L Thompson /**
5531203703bSJeremy L Thompson   @brief Set the immutable flag of a `CeedQFunction` to `true`
5541203703bSJeremy L Thompson 
5551203703bSJeremy L Thompson   @param[in,out] qf `CeedQFunction`
5561203703bSJeremy L Thompson 
5571203703bSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
5581203703bSJeremy L Thompson 
5591203703bSJeremy L Thompson   @ref Backend
5601203703bSJeremy L Thompson **/
5611203703bSJeremy L Thompson int CeedQFunctionSetImmutable(CeedQFunction qf) {
5621203703bSJeremy L Thompson   qf->is_immutable = true;
5631203703bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
5641203703bSJeremy L Thompson }
5651203703bSJeremy L Thompson 
5661203703bSJeremy L Thompson /**
567ca94c3ddSJeremy L Thompson   @brief Increment the reference counter for a `CeedQFunction`
56834359f16Sjeremylt 
569ca94c3ddSJeremy L Thompson   @param[in,out] qf `CeedQFunction` to increment the reference counter
57034359f16Sjeremylt 
57134359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
57234359f16Sjeremylt 
57334359f16Sjeremylt   @ref Backend
57434359f16Sjeremylt **/
5759560d06aSjeremylt int CeedQFunctionReference(CeedQFunction qf) {
57634359f16Sjeremylt   qf->ref_count++;
57734359f16Sjeremylt   return CEED_ERROR_SUCCESS;
57834359f16Sjeremylt }
57934359f16Sjeremylt 
5806e15d496SJeremy L Thompson /**
581ca94c3ddSJeremy L Thompson   @brief Estimate number of FLOPs per quadrature required to apply `CeedQFunction`
5826e15d496SJeremy L Thompson 
583ca94c3ddSJeremy L Thompson   @param[in]  qf    `CeedQFunction` to estimate FLOPs for
584ea61e9acSJeremy L Thompson   @param[out] flops Address of variable to hold FLOPs estimate
5856e15d496SJeremy L Thompson 
5866e15d496SJeremy L Thompson   @ref Backend
5876e15d496SJeremy L Thompson **/
5889d36ca50SJeremy L Thompson int CeedQFunctionGetFlopsEstimate(CeedQFunction qf, CeedSize *flops) {
5896e15d496SJeremy L Thompson   *flops = qf->user_flop_estimate;
5906e15d496SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5916e15d496SJeremy L Thompson }
5926e15d496SJeremy L Thompson 
5937a982d89SJeremy L. Thompson /// @}
5947a982d89SJeremy L. Thompson 
5957a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
5967a982d89SJeremy L. Thompson /// CeedQFunction Public API
5977a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
5987a982d89SJeremy L. Thompson /// @addtogroup CeedQFunctionUser
5997a982d89SJeremy L. Thompson /// @{
6007a982d89SJeremy L. Thompson 
6017a982d89SJeremy L. Thompson /**
602ca94c3ddSJeremy L Thompson   @brief Create a `CeedQFunction` for evaluating interior (volumetric) terms
6037a982d89SJeremy L. Thompson 
604ca94c3ddSJeremy L Thompson   @param[in]  ceed       `Ceed` object used to create the `CeedQFunction`
605ca94c3ddSJeremy L Thompson   @param[in]  vec_length Vector length.
606ca94c3ddSJeremy L Thompson                            Caller must ensure that number of quadrature points is a multiple of `vec_length`.
607ea61e9acSJeremy L Thompson   @param[in]  f          Function pointer to evaluate action at quadrature points.
608ca94c3ddSJeremy L Thompson                            See `CeedQFunctionUser`.
609ca94c3ddSJeremy L Thompson   @param[in]  source     Absolute path to source of `CeedQFunctionUser`, "\abs_path\file.h:function_name".
610ca94c3ddSJeremy 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.).
6114ada38baSJames Wright                            The entire contents of this file and all locally included files are used during JiT compilation for GPU backends.
6124ada38baSJames Wright                            All source files must be at the provided filepath at runtime for JiT to function.
613ca94c3ddSJeremy L Thompson   @param[out] qf         Address of the variable where the newly created `CeedQFunction` will be stored
6147a982d89SJeremy L. Thompson 
6157a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
6167a982d89SJeremy L. Thompson 
617ca94c3ddSJeremy L Thompson   See \ref CeedQFunctionUser for details on the call-back function `f` arguments.
6187a982d89SJeremy L. Thompson 
6197a982d89SJeremy L. Thompson   @ref User
6207a982d89SJeremy L. Thompson **/
6212b730f8bSJeremy L Thompson int CeedQFunctionCreateInterior(Ceed ceed, CeedInt vec_length, CeedQFunctionUser f, const char *source, CeedQFunction *qf) {
622ca5eadf8SJeremy L Thompson   char *user_source_copy;
6237a982d89SJeremy L. Thompson 
6247a982d89SJeremy L. Thompson   if (!ceed->QFunctionCreate) {
6257a982d89SJeremy L. Thompson     Ceed delegate;
6266574a04fSJeremy L Thompson 
6272b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "QFunction"));
628ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support CeedQFunctionCreateInterior");
6292b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionCreateInterior(delegate, vec_length, f, source, qf));
630e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
6317a982d89SJeremy L. Thompson   }
6327a982d89SJeremy L. Thompson 
6336574a04fSJeremy L Thompson   CeedCheck(!strlen(source) || strrchr(source, ':'), ceed, CEED_ERROR_INCOMPLETE,
6346574a04fSJeremy L Thompson             "Provided path to source does not include function name. Provided: \"%s\"\nRequired: \"\\abs_path\\file.h:function_name\"", source);
63543e1b16fSJeremy L Thompson 
6362b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, qf));
637db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*qf)->ceed));
638d1d35e2fSjeremylt   (*qf)->ref_count           = 1;
639d1d35e2fSjeremylt   (*qf)->vec_length          = vec_length;
640f04ea552SJeremy L Thompson   (*qf)->is_identity         = false;
641441428dfSJeremy L Thompson   (*qf)->is_context_writable = true;
6427a982d89SJeremy L. Thompson   (*qf)->function            = f;
6436e15d496SJeremy L Thompson   (*qf)->user_flop_estimate  = -1;
64443e1b16fSJeremy L Thompson   if (strlen(source)) {
645ca5eadf8SJeremy L Thompson     size_t user_source_len = strlen(source);
646ee5a26f2SJeremy L Thompson 
6472b730f8bSJeremy L Thompson     CeedCall(CeedCalloc(user_source_len + 1, &user_source_copy));
648ca5eadf8SJeremy L Thompson     memcpy(user_source_copy, source, user_source_len);
649ca5eadf8SJeremy L Thompson     (*qf)->user_source = user_source_copy;
65043e1b16fSJeremy L Thompson   }
6512b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(CEED_FIELD_MAX, &(*qf)->input_fields));
6522b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(CEED_FIELD_MAX, &(*qf)->output_fields));
6532b730f8bSJeremy L Thompson   CeedCall(ceed->QFunctionCreate(*qf));
654e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
6557a982d89SJeremy L. Thompson }
6567a982d89SJeremy L. Thompson 
6577a982d89SJeremy L. Thompson /**
658ca94c3ddSJeremy L Thompson   @brief Create a `CeedQFunction` for evaluating interior (volumetric) terms by name
659288c0443SJeremy L Thompson 
660ca94c3ddSJeremy L Thompson   @param[in]  ceed `Ceed` object used to create the `CeedQFunction`
661ca94c3ddSJeremy L Thompson   @param[in]  name Name of `CeedQFunction` to use from gallery
662ca94c3ddSJeremy L Thompson   @param[out] qf   Address of the variable where the newly created `CeedQFunction` will be stored
663288c0443SJeremy L Thompson 
664288c0443SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
665288c0443SJeremy L Thompson 
6667a982d89SJeremy L. Thompson   @ref User
667288c0443SJeremy L Thompson **/
6682b730f8bSJeremy L Thompson int CeedQFunctionCreateInteriorByName(Ceed ceed, const char *name, CeedQFunction *qf) {
669f7e22acaSJeremy L Thompson   size_t match_len = 0, match_index = UINT_MAX;
670288c0443SJeremy L Thompson 
6712b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionRegisterAll());
672288c0443SJeremy L Thompson   // Find matching backend
673ca94c3ddSJeremy L Thompson   CeedCheck(name, ceed, CEED_ERROR_INCOMPLETE, "No CeedQFunction name provided");
674288c0443SJeremy L Thompson   for (size_t i = 0; i < num_qfunctions; i++) {
675288c0443SJeremy L Thompson     size_t      n;
676d1d35e2fSjeremylt     const char *curr_name = gallery_qfunctions[i].name;
6772b730f8bSJeremy L Thompson     for (n = 0; curr_name[n] && curr_name[n] == name[n]; n++) {
6782b730f8bSJeremy L Thompson     }
679d1d35e2fSjeremylt     if (n > match_len) {
680d1d35e2fSjeremylt       match_len   = n;
681f7e22acaSJeremy L Thompson       match_index = i;
682288c0443SJeremy L Thompson     }
683288c0443SJeremy L Thompson   }
684ca94c3ddSJeremy L Thompson   CeedCheck(match_len > 0, ceed, CEED_ERROR_UNSUPPORTED, "No suitable gallery CeedQFunction");
685288c0443SJeremy L Thompson 
686288c0443SJeremy L Thompson   // Create QFunction
6872b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionCreateInterior(ceed, gallery_qfunctions[match_index].vec_length, gallery_qfunctions[match_index].f,
6882b730f8bSJeremy L Thompson                                        gallery_qfunctions[match_index].source, qf));
689288c0443SJeremy L Thompson 
690288c0443SJeremy L Thompson   // QFunction specific setup
6912b730f8bSJeremy L Thompson   CeedCall(gallery_qfunctions[match_index].init(ceed, name, *qf));
692288c0443SJeremy L Thompson 
69375affc3bSjeremylt   // Copy name
6942b730f8bSJeremy L Thompson   CeedCall(CeedStringAllocCopy(name, (char **)&(*qf)->gallery_name));
69543e1b16fSJeremy L Thompson   (*qf)->is_gallery = true;
696e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
697288c0443SJeremy L Thompson }
698288c0443SJeremy L Thompson 
699288c0443SJeremy L Thompson /**
700ca94c3ddSJeremy L Thompson   @brief Create an identity `CeedQFunction`.
7014385fb7fSSebastian Grimberg 
702ea61e9acSJeremy L Thompson   Inputs are written into outputs in the order given.
703ca94c3ddSJeremy 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.
704ca94c3ddSJeremy 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.
7050219ea01SJeremy L Thompson 
706ca94c3ddSJeremy L Thompson   @param[in]  ceed     `Ceed` object used to create the `CeedQFunction`
707ca94c3ddSJeremy L Thompson   @param[in]  size     Size of the `CeedQFunction` fields
708ca94c3ddSJeremy L Thompson   @param[in]  in_mode  @ref CeedEvalMode for input to `CeedQFunction`
709ca94c3ddSJeremy L Thompson   @param[in]  out_mode @ref CeedEvalMode for output to `CeedQFunction`
710ca94c3ddSJeremy L Thompson   @param[out] qf       Address of the variable where the newly created `CeedQFunction` will be stored
7110219ea01SJeremy L Thompson 
7120219ea01SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
7130219ea01SJeremy L Thompson 
7147a982d89SJeremy L. Thompson   @ref User
7150219ea01SJeremy L Thompson **/
7162b730f8bSJeremy L Thompson int CeedQFunctionCreateIdentity(Ceed ceed, CeedInt size, CeedEvalMode in_mode, CeedEvalMode out_mode, CeedQFunction *qf) {
7171c66c397SJeremy L Thompson   CeedQFunctionContext  ctx;
7181c66c397SJeremy L Thompson   CeedContextFieldLabel size_label;
7191c66c397SJeremy L Thompson 
7202b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionCreateInteriorByName(ceed, "Identity", qf));
7212b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionAddInput(*qf, "input", size, in_mode));
7222b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionAddOutput(*qf, "output", size, out_mode));
7230219ea01SJeremy L Thompson 
724f04ea552SJeremy L Thompson   (*qf)->is_identity = true;
725547dbd6fSJeremy L Thompson 
7262b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionGetContext(*qf, &ctx));
7272b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextGetFieldLabel(ctx, "size", &size_label));
7282b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextSetInt32(ctx, size_label, &size));
729e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
7300219ea01SJeremy L Thompson }
7310219ea01SJeremy L Thompson 
7320219ea01SJeremy L Thompson /**
733ca94c3ddSJeremy L Thompson   @brief Copy the pointer to a `CeedQFunction`.
7344385fb7fSSebastian Grimberg 
735ca94c3ddSJeremy L Thompson   Both pointers should be destroyed with @ref CeedQFunctionDestroy().
736512bb800SJeremy L Thompson 
737ca94c3ddSJeremy 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`.
738ca94c3ddSJeremy L Thompson         This `CeedQFunction` will be destroyed if `*qf_copy` is the only reference to this `CeedQFunction`.
7399560d06aSjeremylt 
740ca94c3ddSJeremy L Thompson   @param[in]  qf      `CeedQFunction` to copy reference to
7419560d06aSjeremylt   @param[out] qf_copy Variable to store copied reference
7429560d06aSjeremylt 
7439560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
7449560d06aSjeremylt 
7459560d06aSjeremylt   @ref User
7469560d06aSjeremylt **/
7479560d06aSjeremylt int CeedQFunctionReferenceCopy(CeedQFunction qf, CeedQFunction *qf_copy) {
7482b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionReference(qf));
7492b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionDestroy(qf_copy));
7509560d06aSjeremylt   *qf_copy = qf;
7519560d06aSjeremylt   return CEED_ERROR_SUCCESS;
7529560d06aSjeremylt }
7539560d06aSjeremylt 
7549560d06aSjeremylt /**
755ca94c3ddSJeremy L Thompson   @brief Add a `CeedQFunction` input
756b11c1e72Sjeremylt 
757ca94c3ddSJeremy L Thompson   @param[in,out] qf         `CeedQFunction`
758ca94c3ddSJeremy L Thompson   @param[in]     field_name Name of `CeedQFunction` field
759ca94c3ddSJeremy 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.
760ca94c3ddSJeremy L Thompson   @param[in]     eval_mode  @ref CEED_EVAL_NONE to use values directly,
761ca94c3ddSJeremy L Thompson                               @ref CEED_EVAL_INTERP to use interpolated values,
762ca94c3ddSJeremy L Thompson                               @ref CEED_EVAL_GRAD to use gradients,
763ca94c3ddSJeremy L Thompson                               @ref CEED_EVAL_DIV to use divergence,
764ca94c3ddSJeremy L Thompson                               @ref CEED_EVAL_CURL to use curl
765b11c1e72Sjeremylt 
766b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
767dfdf5a53Sjeremylt 
7687a982d89SJeremy L. Thompson   @ref User
769b11c1e72Sjeremylt **/
7702b730f8bSJeremy L Thompson int CeedQFunctionAddInput(CeedQFunction qf, const char *field_name, CeedInt size, CeedEvalMode eval_mode) {
7711203703bSJeremy L Thompson   bool is_immutable;
7721203703bSJeremy L Thompson   Ceed ceed;
7731203703bSJeremy L Thompson 
7741203703bSJeremy L Thompson   CeedCall(CeedQFunctionGetCeed(qf, &ceed));
7751203703bSJeremy L Thompson   CeedCall(CeedQFunctionIsImmutable(qf, &is_immutable));
7761203703bSJeremy L Thompson   CeedCheck(!is_immutable, ceed, CEED_ERROR_MAJOR, "QFunction cannot be changed after set as immutable");
7771203703bSJeremy L Thompson   CeedCheck(eval_mode != CEED_EVAL_WEIGHT || size == 1, ceed, CEED_ERROR_DIMENSION, "CEED_EVAL_WEIGHT should have size 1");
778643fbb69SJeremy L Thompson   for (CeedInt i = 0; i < qf->num_input_fields; i++) {
7791203703bSJeremy L Thompson     CeedCheck(strcmp(field_name, qf->input_fields[i]->field_name), ceed, CEED_ERROR_MINOR, "CeedQFunction field names must be unique");
780643fbb69SJeremy L Thompson   }
781643fbb69SJeremy L Thompson   for (CeedInt i = 0; i < qf->num_output_fields; i++) {
7821203703bSJeremy L Thompson     CeedCheck(strcmp(field_name, qf->output_fields[i]->field_name), ceed, CEED_ERROR_MINOR, "CeedQFunction field names must be unique");
783643fbb69SJeremy L Thompson   }
7842b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionFieldSet(&qf->input_fields[qf->num_input_fields], field_name, size, eval_mode));
785d1d35e2fSjeremylt   qf->num_input_fields++;
786e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
787d7b241e6Sjeremylt }
788d7b241e6Sjeremylt 
789b11c1e72Sjeremylt /**
790ca94c3ddSJeremy L Thompson   @brief Add a `CeedQFunction` output
791b11c1e72Sjeremylt 
792ca94c3ddSJeremy L Thompson   @param[in,out] qf         `CeedQFunction`
793ca94c3ddSJeremy L Thompson   @param[in]     field_name Name of `CeedQFunction` field
794ca94c3ddSJeremy 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.
795ca94c3ddSJeremy L Thompson   @param[in]     eval_mode  @ref CEED_EVAL_NONE to use values directly,
796ca94c3ddSJeremy L Thompson                               @ref CEED_EVAL_INTERP to use interpolated values,
797ca94c3ddSJeremy L Thompson                               @ref CEED_EVAL_GRAD to use gradients,
798ca94c3ddSJeremy L Thompson                               @ref CEED_EVAL_DIV to use divergence,
799ca94c3ddSJeremy L Thompson                               @ref CEED_EVAL_CURL to use curl.
800b11c1e72Sjeremylt 
801b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
802dfdf5a53Sjeremylt 
8037a982d89SJeremy L. Thompson   @ref User
804b11c1e72Sjeremylt **/
8052b730f8bSJeremy L Thompson int CeedQFunctionAddOutput(CeedQFunction qf, const char *field_name, CeedInt size, CeedEvalMode eval_mode) {
8061203703bSJeremy L Thompson   bool is_immutable;
8071203703bSJeremy L Thompson   Ceed ceed;
8081203703bSJeremy L Thompson 
8091203703bSJeremy L Thompson   CeedCall(CeedQFunctionGetCeed(qf, &ceed));
8101203703bSJeremy L Thompson   CeedCall(CeedQFunctionIsImmutable(qf, &is_immutable));
8111203703bSJeremy L Thompson   CeedCheck(!is_immutable, ceed, CEED_ERROR_MAJOR, "CeedQFunction cannot be changed after set as immutable");
8121203703bSJeremy L Thompson   CeedCheck(eval_mode != CEED_EVAL_WEIGHT, ceed, CEED_ERROR_DIMENSION, "Cannot create CeedQFunction output with CEED_EVAL_WEIGHT");
813643fbb69SJeremy L Thompson   for (CeedInt i = 0; i < qf->num_input_fields; i++) {
8141203703bSJeremy L Thompson     CeedCheck(strcmp(field_name, qf->input_fields[i]->field_name), ceed, CEED_ERROR_MINOR, "CeedQFunction field names must be unique");
815643fbb69SJeremy L Thompson   }
816643fbb69SJeremy L Thompson   for (CeedInt i = 0; i < qf->num_output_fields; i++) {
8171203703bSJeremy L Thompson     CeedCheck(strcmp(field_name, qf->output_fields[i]->field_name), ceed, CEED_ERROR_MINOR, "CeedQFunction field names must be unique");
818643fbb69SJeremy L Thompson   }
8192b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionFieldSet(&qf->output_fields[qf->num_output_fields], field_name, size, eval_mode));
820d1d35e2fSjeremylt   qf->num_output_fields++;
821e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
822d7b241e6Sjeremylt }
823d7b241e6Sjeremylt 
824dfdf5a53Sjeremylt /**
825ca94c3ddSJeremy L Thompson   @brief Get the `CeedQFunctionField` of a `CeedQFunction`
82643bbe138SJeremy L Thompson 
827ca94c3ddSJeremy L Thompson   Note: Calling this function asserts that setup is complete and sets the `CeedQFunction` as immutable.
828f04ea552SJeremy L Thompson 
829ca94c3ddSJeremy L Thompson   @param[in]  qf                `CeedQFunction`
830f74ec584SJeremy L Thompson   @param[out] num_input_fields  Variable to store number of input fields
831f74ec584SJeremy L Thompson   @param[out] input_fields      Variable to store input fields
832f74ec584SJeremy L Thompson   @param[out] num_output_fields Variable to store number of output fields
833f74ec584SJeremy L Thompson   @param[out] output_fields     Variable to store output fields
83443bbe138SJeremy L Thompson 
83543bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
83643bbe138SJeremy L Thompson 
837e9b533fbSJeremy L Thompson   @ref Advanced
83843bbe138SJeremy L Thompson **/
8392b730f8bSJeremy L Thompson int CeedQFunctionGetFields(CeedQFunction qf, CeedInt *num_input_fields, CeedQFunctionField **input_fields, CeedInt *num_output_fields,
84043bbe138SJeremy L Thompson                            CeedQFunctionField **output_fields) {
8411203703bSJeremy L Thompson   CeedCall(CeedQFunctionSetImmutable(qf));
84243bbe138SJeremy L Thompson   if (num_input_fields) *num_input_fields = qf->num_input_fields;
84343bbe138SJeremy L Thompson   if (input_fields) *input_fields = qf->input_fields;
84443bbe138SJeremy L Thompson   if (num_output_fields) *num_output_fields = qf->num_output_fields;
84543bbe138SJeremy L Thompson   if (output_fields) *output_fields = qf->output_fields;
84643bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
84743bbe138SJeremy L Thompson }
84843bbe138SJeremy L Thompson 
84943bbe138SJeremy L Thompson /**
850ca94c3ddSJeremy L Thompson   @brief Get the name of a `CeedQFunctionField`
85143bbe138SJeremy L Thompson 
852ca94c3ddSJeremy L Thompson   @param[in]  qf_field   `CeedQFunctionField`
85343bbe138SJeremy L Thompson   @param[out] field_name Variable to store the field name
85443bbe138SJeremy L Thompson 
85543bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
85643bbe138SJeremy L Thompson 
857e9b533fbSJeremy L Thompson   @ref Advanced
85843bbe138SJeremy L Thompson **/
8596f8994e9SJeremy L Thompson int CeedQFunctionFieldGetName(CeedQFunctionField qf_field, const char **field_name) {
8606f8994e9SJeremy L Thompson   *field_name = qf_field->field_name;
86143bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
86243bbe138SJeremy L Thompson }
86343bbe138SJeremy L Thompson 
86443bbe138SJeremy L Thompson /**
865ca94c3ddSJeremy L Thompson   @brief Get the number of components of a `CeedQFunctionField`
86643bbe138SJeremy L Thompson 
867ca94c3ddSJeremy L Thompson   @param[in]  qf_field `CeedQFunctionField`
86843bbe138SJeremy L Thompson   @param[out] size     Variable to store the size of the field
86943bbe138SJeremy L Thompson 
87043bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
87143bbe138SJeremy L Thompson 
872e9b533fbSJeremy L Thompson   @ref Advanced
87343bbe138SJeremy L Thompson **/
87443bbe138SJeremy L Thompson int CeedQFunctionFieldGetSize(CeedQFunctionField qf_field, CeedInt *size) {
87543bbe138SJeremy L Thompson   *size = qf_field->size;
87643bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
87743bbe138SJeremy L Thompson }
87843bbe138SJeremy L Thompson 
87943bbe138SJeremy L Thompson /**
880ca94c3ddSJeremy L Thompson   @brief Get the @ref CeedEvalMode of a `CeedQFunctionField`
88143bbe138SJeremy L Thompson 
882ca94c3ddSJeremy L Thompson   @param[in]  qf_field  `CeedQFunctionField`
88343bbe138SJeremy L Thompson   @param[out] eval_mode Variable to store the field evaluation mode
88443bbe138SJeremy L Thompson 
88543bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
88643bbe138SJeremy L Thompson 
887e9b533fbSJeremy L Thompson   @ref Advanced
88843bbe138SJeremy L Thompson **/
8892b730f8bSJeremy L Thompson int CeedQFunctionFieldGetEvalMode(CeedQFunctionField qf_field, CeedEvalMode *eval_mode) {
89043bbe138SJeremy L Thompson   *eval_mode = qf_field->eval_mode;
89143bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
89243bbe138SJeremy L Thompson }
89343bbe138SJeremy L Thompson 
89443bbe138SJeremy L Thompson /**
895ab747706SJeremy L Thompson   @brief Get the data of a `CeedQFunctionField`.
896ab747706SJeremy L Thompson 
897ab747706SJeremy L Thompson   Any arguments set as `NULL` are ignored.
898ab747706SJeremy L Thompson 
899ab747706SJeremy L Thompson   @param[in]  qf_field   `CeedQFunctionField`
900ab747706SJeremy L Thompson   @param[out] field_name Variable to store the field name
901ab747706SJeremy L Thompson   @param[out] size       Variable to store the size of the field
902ab747706SJeremy L Thompson   @param[out] eval_mode  Variable to store the field evaluation mode
903ab747706SJeremy L Thompson 
904ab747706SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
905ab747706SJeremy L Thompson 
906ab747706SJeremy L Thompson   @ref Advanced
907ab747706SJeremy L Thompson **/
9086f8994e9SJeremy L Thompson int CeedQFunctionFieldGetData(CeedQFunctionField qf_field, const char **field_name, CeedInt *size, CeedEvalMode *eval_mode) {
909ab747706SJeremy L Thompson   if (field_name) CeedCall(CeedQFunctionFieldGetName(qf_field, field_name));
910ab747706SJeremy L Thompson   if (size) CeedCall(CeedQFunctionFieldGetSize(qf_field, size));
911ab747706SJeremy L Thompson   if (eval_mode) CeedCall(CeedQFunctionFieldGetEvalMode(qf_field, eval_mode));
912ab747706SJeremy L Thompson   return CEED_ERROR_SUCCESS;
913ab747706SJeremy L Thompson }
914ab747706SJeremy L Thompson 
915ab747706SJeremy L Thompson /**
916ca94c3ddSJeremy L Thompson   @brief Set global context for a `CeedQFunction`
917b11c1e72Sjeremylt 
918ca94c3ddSJeremy L Thompson   @param[in,out] qf  `CeedQFunction`
919ea61e9acSJeremy L Thompson   @param[in]     ctx Context data to set
920b11c1e72Sjeremylt 
921b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
922dfdf5a53Sjeremylt 
9237a982d89SJeremy L. Thompson   @ref User
924b11c1e72Sjeremylt **/
925777ff853SJeremy L Thompson int CeedQFunctionSetContext(CeedQFunction qf, CeedQFunctionContext ctx) {
9262b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextDestroy(&qf->ctx));
927d7b241e6Sjeremylt   qf->ctx = ctx;
928db002c03SJeremy L Thompson   if (ctx) CeedCall(CeedQFunctionContextReference(ctx));
929e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
930d7b241e6Sjeremylt }
931d7b241e6Sjeremylt 
932b11c1e72Sjeremylt /**
933ca94c3ddSJeremy L Thompson   @brief Set writability of `CeedQFunctionContext` when calling the `CeedQFunctionUser`.
9344385fb7fSSebastian Grimberg 
935859c15bbSJames Wright   The default value is `is_writable == true`.
936441428dfSJeremy L Thompson 
937ca94c3ddSJeremy L Thompson   Setting `is_writable == true` indicates the `CeedQFunctionUser` writes into the `CeedQFunctionContext` and requires memory synchronization after calling @ref CeedQFunctionApply().
938441428dfSJeremy L Thompson 
939ca94c3ddSJeremy L Thompson   Setting 'is_writable == false' asserts that `CeedQFunctionUser` does not modify the `CeedQFunctionContext`.
940ea61e9acSJeremy L Thompson   Violating this assertion may lead to inconsistent data.
941441428dfSJeremy L Thompson 
942441428dfSJeremy L Thompson   Setting `is_writable == false` may offer a performance improvement on GPU backends.
943441428dfSJeremy L Thompson 
944ca94c3ddSJeremy L Thompson   @param[in,out] qf          `CeedQFunction`
945ca94c3ddSJeremy L Thompson   @param[in]     is_writable Boolean flag for writability status
946441428dfSJeremy L Thompson 
947441428dfSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
948441428dfSJeremy L Thompson 
949441428dfSJeremy L Thompson   @ref User
950441428dfSJeremy L Thompson **/
951441428dfSJeremy L Thompson int CeedQFunctionSetContextWritable(CeedQFunction qf, bool is_writable) {
952441428dfSJeremy L Thompson   qf->is_context_writable = is_writable;
953441428dfSJeremy L Thompson   return CEED_ERROR_SUCCESS;
954441428dfSJeremy L Thompson }
955441428dfSJeremy L Thompson 
956441428dfSJeremy L Thompson /**
957ca94c3ddSJeremy L Thompson   @brief Set estimated number of FLOPs per quadrature required to apply `CeedQFunction`
9586e15d496SJeremy L Thompson 
959ca94c3ddSJeremy L Thompson   @param[in]  qf    `CeedQFunction` to estimate FLOPs for
960ea61e9acSJeremy L Thompson   @param[out] flops FLOPs per quadrature point estimate
9616e15d496SJeremy L Thompson 
9626e15d496SJeremy L Thompson   @ref Backend
9636e15d496SJeremy L Thompson **/
9649d36ca50SJeremy L Thompson int CeedQFunctionSetUserFlopsEstimate(CeedQFunction qf, CeedSize flops) {
9651203703bSJeremy L Thompson   Ceed ceed;
9661203703bSJeremy L Thompson 
9671203703bSJeremy L Thompson   CeedCall(CeedQFunctionGetCeed(qf, &ceed));
9681203703bSJeremy L Thompson   CeedCheck(flops >= 0, ceed, CEED_ERROR_INCOMPATIBLE, "Must set non-negative FLOPs estimate");
9696e15d496SJeremy L Thompson   qf->user_flop_estimate = flops;
9706e15d496SJeremy L Thompson   return CEED_ERROR_SUCCESS;
9716e15d496SJeremy L Thompson }
9726e15d496SJeremy L Thompson 
9736e15d496SJeremy L Thompson /**
974ca94c3ddSJeremy L Thompson   @brief View a `CeedQFunction`
97575affc3bSjeremylt 
976ca94c3ddSJeremy L Thompson   @param[in] qf     `CeedQFunction` to view
977ca94c3ddSJeremy L Thompson   @param[in] stream Stream to write; typically `stdout` or a file
97875affc3bSjeremylt 
97975affc3bSjeremylt   @return Error code: 0 - success, otherwise - failure
98075affc3bSjeremylt 
9817a982d89SJeremy L. Thompson   @ref User
98275affc3bSjeremylt **/
98375affc3bSjeremylt int CeedQFunctionView(CeedQFunction qf, FILE *stream) {
9847d023984SJeremy L Thompson   const char *kernel_name;
98575affc3bSjeremylt 
9862b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionGetKernelName(qf, &kernel_name));
9872b730f8bSJeremy L Thompson   fprintf(stream, "%sCeedQFunction - %s\n", qf->is_gallery ? "Gallery " : "User ", qf->is_gallery ? qf->gallery_name : kernel_name);
98875affc3bSjeremylt 
9892b730f8bSJeremy L Thompson   fprintf(stream, "  %" CeedInt_FMT " input field%s:\n", qf->num_input_fields, qf->num_input_fields > 1 ? "s" : "");
990d1d35e2fSjeremylt   for (CeedInt i = 0; i < qf->num_input_fields; i++) {
9912b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionFieldView(qf->input_fields[i], i, 1, stream));
99275affc3bSjeremylt   }
99375affc3bSjeremylt 
9942b730f8bSJeremy L Thompson   fprintf(stream, "  %" CeedInt_FMT " output field%s:\n", qf->num_output_fields, qf->num_output_fields > 1 ? "s" : "");
995d1d35e2fSjeremylt   for (CeedInt i = 0; i < qf->num_output_fields; i++) {
9962b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionFieldView(qf->output_fields[i], i, 0, stream));
99775affc3bSjeremylt   }
998e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
99975affc3bSjeremylt }
100075affc3bSjeremylt 
100175affc3bSjeremylt /**
1002ca94c3ddSJeremy L Thompson   @brief Get the `Ceed` associated with a `CeedQFunction`
1003b7c9bbdaSJeremy L Thompson 
1004ca94c3ddSJeremy L Thompson   @param[in]  qf   `CeedQFunction`
1005ca94c3ddSJeremy L Thompson   @param[out] ceed Variable to store`Ceed`
1006b7c9bbdaSJeremy L Thompson 
1007b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1008b7c9bbdaSJeremy L Thompson 
1009b7c9bbdaSJeremy L Thompson   @ref Advanced
1010b7c9bbdaSJeremy L Thompson **/
1011b7c9bbdaSJeremy L Thompson int CeedQFunctionGetCeed(CeedQFunction qf, Ceed *ceed) {
1012b7c9bbdaSJeremy L Thompson   *ceed = qf->ceed;
1013b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1014b7c9bbdaSJeremy L Thompson }
1015b7c9bbdaSJeremy L Thompson 
1016b7c9bbdaSJeremy L Thompson /**
1017ca94c3ddSJeremy L Thompson   @brief Apply the action of a `CeedQFunction`
1018b11c1e72Sjeremylt 
1019ca94c3ddSJeremy L Thompson   Note: Calling this function asserts that setup is complete and sets the `CeedQFunction` as immutable.
1020f04ea552SJeremy L Thompson 
1021ca94c3ddSJeremy L Thompson   @param[in]  qf `CeedQFunction`
1022ea61e9acSJeremy L Thompson   @param[in]  Q  Number of quadrature points
1023ca94c3ddSJeremy L Thompson   @param[in]  u  Array of input `CeedVector`
1024ca94c3ddSJeremy L Thompson   @param[out] v  Array of output `CeedVector`
1025b11c1e72Sjeremylt 
1026b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1027dfdf5a53Sjeremylt 
10287a982d89SJeremy L. Thompson   @ref User
1029b11c1e72Sjeremylt **/
10302b730f8bSJeremy L Thompson int CeedQFunctionApply(CeedQFunction qf, CeedInt Q, CeedVector *u, CeedVector *v) {
10311203703bSJeremy L Thompson   CeedInt vec_length;
10321203703bSJeremy L Thompson   Ceed    ceed;
10331203703bSJeremy L Thompson 
10341203703bSJeremy L Thompson   CeedCall(CeedQFunctionGetCeed(qf, &ceed));
10351203703bSJeremy L Thompson   CeedCheck(qf->Apply, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support CeedQFunctionApply");
10361203703bSJeremy L Thompson   CeedCall(CeedQFunctionGetVectorLength(qf, &vec_length));
10371203703bSJeremy 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,
10381203703bSJeremy L Thompson             qf->vec_length);
10391203703bSJeremy L Thompson   CeedCall(CeedQFunctionSetImmutable(qf));
10402b730f8bSJeremy L Thompson   CeedCall(qf->Apply(qf, Q, u, v));
1041e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1042d7b241e6Sjeremylt }
1043d7b241e6Sjeremylt 
1044b11c1e72Sjeremylt /**
1045ca94c3ddSJeremy L Thompson   @brief Destroy a `CeedQFunction`
1046b11c1e72Sjeremylt 
1047ca94c3ddSJeremy L Thompson   @param[in,out] qf `CeedQFunction` to destroy
1048b11c1e72Sjeremylt 
1049b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1050dfdf5a53Sjeremylt 
10517a982d89SJeremy L. Thompson   @ref User
1052b11c1e72Sjeremylt **/
1053d7b241e6Sjeremylt int CeedQFunctionDestroy(CeedQFunction *qf) {
1054ad6481ceSJeremy L Thompson   if (!*qf || --(*qf)->ref_count > 0) {
1055ad6481ceSJeremy L Thompson     *qf = NULL;
1056ad6481ceSJeremy L Thompson     return CEED_ERROR_SUCCESS;
1057ad6481ceSJeremy L Thompson   }
1058fe2413ffSjeremylt   // Backend destroy
1059d7b241e6Sjeremylt   if ((*qf)->Destroy) {
10602b730f8bSJeremy L Thompson     CeedCall((*qf)->Destroy(*qf));
1061d7b241e6Sjeremylt   }
1062fe2413ffSjeremylt   // Free fields
106392ae7e47SJeremy L Thompson   for (CeedInt i = 0; i < (*qf)->num_input_fields; i++) {
10642b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*(*qf)->input_fields[i]).field_name));
10652b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*qf)->input_fields[i]));
1066fe2413ffSjeremylt   }
106792ae7e47SJeremy L Thompson   for (CeedInt i = 0; i < (*qf)->num_output_fields; i++) {
10682b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*(*qf)->output_fields[i]).field_name));
10692b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*qf)->output_fields[i]));
1070fe2413ffSjeremylt   }
10712b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*qf)->input_fields));
10722b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*qf)->output_fields));
1073777ff853SJeremy L Thompson 
1074777ff853SJeremy L Thompson   // User context data object
10752b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextDestroy(&(*qf)->ctx));
1076fe2413ffSjeremylt 
10772b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*qf)->user_source));
10782b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*qf)->source_path));
10792b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*qf)->gallery_name));
10802b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*qf)->kernel_name));
10812b730f8bSJeremy L Thompson   CeedCall(CeedDestroy(&(*qf)->ceed));
10822b730f8bSJeremy L Thompson   CeedCall(CeedFree(qf));
1083e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1084d7b241e6Sjeremylt }
1085d7b241e6Sjeremylt 
1086d7b241e6Sjeremylt /// @}
1087