xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-qfunction.c (revision ab74770665870aeb8f4af2e1fe7995e7c4c2ce73)
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 
132*ab747706SJeremy 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 **/
20943e1b16fSJeremy L Thompson int CeedQFunctionGetKernelName(CeedQFunction qf, 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 
22743e1b16fSJeremy L Thompson   *kernel_name = (char *)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 **/
24143e1b16fSJeremy L Thompson int CeedQFunctionGetSourcePath(CeedQFunction qf, 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 
275ca94c3ddSJeremy L Thompson   Note: Caller is responsible for freeing the string buffer with @ref CeedFree().
2763d3250a0SJeremy L Thompson 
277ca94c3ddSJeremy L Thompson   @param[in]  qf            `CeedQFunction`
278f74ec584SJeremy L Thompson   @param[out] source_buffer String buffer for source file contents
2793d3250a0SJeremy L Thompson 
2803d3250a0SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
2813d3250a0SJeremy L Thompson 
2823d3250a0SJeremy L Thompson   @ref Backend
2833d3250a0SJeremy L Thompson **/
2843d3250a0SJeremy L Thompson int CeedQFunctionLoadSourceToBuffer(CeedQFunction qf, char **source_buffer) {
2853d3250a0SJeremy L Thompson   char *source_path;
2863d3250a0SJeremy L Thompson 
2872b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionGetSourcePath(qf, &source_path));
2883d3250a0SJeremy L Thompson   *source_buffer = NULL;
2893d3250a0SJeremy L Thompson   if (source_path) {
2901203703bSJeremy L Thompson     Ceed ceed;
2911203703bSJeremy L Thompson 
2921203703bSJeremy L Thompson     CeedCall(CeedQFunctionGetCeed(qf, &ceed));
2931203703bSJeremy L Thompson     CeedCall(CeedLoadSourceToBuffer(ceed, source_path, source_buffer));
2943d3250a0SJeremy L Thompson   }
2953d3250a0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2963d3250a0SJeremy L Thompson }
2973d3250a0SJeremy L Thompson 
2983d3250a0SJeremy L Thompson /**
299ca94c3ddSJeremy L Thompson   @brief Get the User Function for a `CeedQFunction`
3007a982d89SJeremy L. Thompson 
301ca94c3ddSJeremy L Thompson   @param[in]  qf `CeedQFunction`
3027a982d89SJeremy L. Thompson   @param[out] f  Variable to store user function
3037a982d89SJeremy L. Thompson 
3047a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3057a982d89SJeremy L. Thompson 
3067a982d89SJeremy L. Thompson   @ref Backend
3077a982d89SJeremy L. Thompson **/
3087a982d89SJeremy L. Thompson int CeedQFunctionGetUserFunction(CeedQFunction qf, CeedQFunctionUser *f) {
3097a982d89SJeremy L. Thompson   *f = qf->function;
310e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3117a982d89SJeremy L. Thompson }
3127a982d89SJeremy L. Thompson 
3137a982d89SJeremy L. Thompson /**
314ca94c3ddSJeremy L Thompson   @brief Get global context for a `CeedQFunction`.
3154385fb7fSSebastian Grimberg 
316ca94c3ddSJeremy L Thompson   Note: For `CeedQFunction` from the Fortran interface, this function will return the Fortran context `CeedQFunctionContext`.
3177a982d89SJeremy L. Thompson 
318ea61e9acSJeremy L Thompson   @param[in]  qf  CeedQFunction
319777ff853SJeremy L Thompson   @param[out] ctx Variable to store CeedQFunctionContext
3207a982d89SJeremy L. Thompson 
3217a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3227a982d89SJeremy L. Thompson 
3237a982d89SJeremy L. Thompson   @ref Backend
3247a982d89SJeremy L. Thompson **/
325777ff853SJeremy L Thompson int CeedQFunctionGetContext(CeedQFunction qf, CeedQFunctionContext *ctx) {
3267a982d89SJeremy L. Thompson   *ctx = qf->ctx;
327e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3287a982d89SJeremy L. Thompson }
3297a982d89SJeremy L. Thompson 
3307a982d89SJeremy L. Thompson /**
331ca94c3ddSJeremy L Thompson   @brief Get context data of a `CeedQFunction`
332441428dfSJeremy L Thompson 
333ca94c3ddSJeremy L Thompson   @param[in]  qf       `CeedQFunction`
334ea61e9acSJeremy L Thompson   @param[in]  mem_type Memory type on which to access the data.
335ea61e9acSJeremy L Thompson                          If the backend uses a different memory type, this will perform a copy.
336441428dfSJeremy L Thompson   @param[out] data     Data on memory type mem_type
337441428dfSJeremy L Thompson 
338441428dfSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
339441428dfSJeremy L Thompson 
340441428dfSJeremy L Thompson   @ref Backend
341441428dfSJeremy L Thompson **/
3422b730f8bSJeremy L Thompson int CeedQFunctionGetContextData(CeedQFunction qf, CeedMemType mem_type, void *data) {
343441428dfSJeremy L Thompson   bool                 is_writable;
344441428dfSJeremy L Thompson   CeedQFunctionContext ctx;
345441428dfSJeremy L Thompson 
3462b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionGetContext(qf, &ctx));
347441428dfSJeremy L Thompson   if (ctx) {
3482b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionIsContextWritable(qf, &is_writable));
349441428dfSJeremy L Thompson     if (is_writable) {
3502b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextGetData(ctx, mem_type, data));
351441428dfSJeremy L Thompson     } else {
3522b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextGetDataRead(ctx, mem_type, data));
353441428dfSJeremy L Thompson     }
354441428dfSJeremy L Thompson   } else {
355441428dfSJeremy L Thompson     *(void **)data = NULL;
356441428dfSJeremy L Thompson   }
357441428dfSJeremy L Thompson   return CEED_ERROR_SUCCESS;
358441428dfSJeremy L Thompson }
359441428dfSJeremy L Thompson 
360441428dfSJeremy L Thompson /**
361ca94c3ddSJeremy L Thompson   @brief Restore context data of a `CeedQFunction`
362441428dfSJeremy L Thompson 
363ca94c3ddSJeremy L Thompson   @param[in]     qf   `CeedQFunction`
364ea61e9acSJeremy L Thompson   @param[in,out] data Data to restore
365441428dfSJeremy L Thompson 
366441428dfSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
367441428dfSJeremy L Thompson 
368441428dfSJeremy L Thompson   @ref Backend
369441428dfSJeremy L Thompson **/
370441428dfSJeremy L Thompson int CeedQFunctionRestoreContextData(CeedQFunction qf, void *data) {
371441428dfSJeremy L Thompson   bool                 is_writable;
372441428dfSJeremy L Thompson   CeedQFunctionContext ctx;
373441428dfSJeremy L Thompson 
3742b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionGetContext(qf, &ctx));
375441428dfSJeremy L Thompson   if (ctx) {
3762b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionIsContextWritable(qf, &is_writable));
377441428dfSJeremy L Thompson     if (is_writable) {
3782b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextRestoreData(ctx, data));
379441428dfSJeremy L Thompson     } else {
3802b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextRestoreDataRead(ctx, data));
381441428dfSJeremy L Thompson     }
382441428dfSJeremy L Thompson   }
3835f249b39SJeremy L Thompson   *(void **)data = NULL;
384441428dfSJeremy L Thompson   return CEED_ERROR_SUCCESS;
385441428dfSJeremy L Thompson }
386441428dfSJeremy L Thompson 
387441428dfSJeremy L Thompson /**
388ca94c3ddSJeremy L Thompson   @brief Get true user context for a `CeedQFunction`
3894385fb7fSSebastian Grimberg 
390ca94c3ddSJeremy L Thompson   Note: For all `CeedQFunction` this function will return the user `CeedQFunctionContext` and not interface context `CeedQFunctionContext`, if any such object exists.
3917a982d89SJeremy L. Thompson 
392ca94c3ddSJeremy L Thompson   @param[in]  qf  `CeedQFunction`
393ca94c3ddSJeremy L Thompson   @param[out] ctx Variable to store `CeedQFunctionContext`
3947a982d89SJeremy L. Thompson 
3957a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3967a982d89SJeremy L. Thompson   @ref Backend
3977a982d89SJeremy L. Thompson **/
398777ff853SJeremy L Thompson int CeedQFunctionGetInnerContext(CeedQFunction qf, CeedQFunctionContext *ctx) {
3991203703bSJeremy L Thompson   CeedQFunctionContext qf_ctx;
4001203703bSJeremy L Thompson 
4011203703bSJeremy L Thompson   CeedCall(CeedQFunctionGetContext(qf, &qf_ctx));
402f04ea552SJeremy L Thompson   if (qf->is_fortran) {
403d1d35e2fSjeremylt     CeedFortranContext fortran_ctx = NULL;
4041c66c397SJeremy L Thompson 
4051203703bSJeremy L Thompson     CeedCall(CeedQFunctionContextGetData(qf_ctx, CEED_MEM_HOST, &fortran_ctx));
4068cb0412aSJeremy L Thompson     *ctx = fortran_ctx->inner_ctx;
4071203703bSJeremy L Thompson     CeedCall(CeedQFunctionContextRestoreData(qf_ctx, (void *)&fortran_ctx));
4087a982d89SJeremy L. Thompson   } else {
4091203703bSJeremy L Thompson     *ctx = qf_ctx;
4107a982d89SJeremy L. Thompson   }
411e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4127a982d89SJeremy L. Thompson }
4137a982d89SJeremy L. Thompson 
4147a982d89SJeremy L. Thompson /**
415ca94c3ddSJeremy L Thompson   @brief Get inner context data of a `CeedQFunction`
416441428dfSJeremy L Thompson 
417ca94c3ddSJeremy L Thompson   @param[in]  qf       `CeedQFunction`
418ea61e9acSJeremy L Thompson   @param[in]  mem_type Memory type on which to access the data.
419ea61e9acSJeremy L Thompson                          If the backend uses a different memory type, this will perform a copy.
420441428dfSJeremy L Thompson   @param[out] data     Data on memory type mem_type
421441428dfSJeremy L Thompson 
422441428dfSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
423441428dfSJeremy L Thompson 
424441428dfSJeremy L Thompson   @ref Backend
425441428dfSJeremy L Thompson **/
4262b730f8bSJeremy L Thompson int CeedQFunctionGetInnerContextData(CeedQFunction qf, CeedMemType mem_type, void *data) {
427441428dfSJeremy L Thompson   bool                 is_writable;
428441428dfSJeremy L Thompson   CeedQFunctionContext ctx;
429441428dfSJeremy L Thompson 
4302b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionGetInnerContext(qf, &ctx));
431441428dfSJeremy L Thompson   if (ctx) {
4322b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionIsContextWritable(qf, &is_writable));
433441428dfSJeremy L Thompson     if (is_writable) {
4342b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextGetData(ctx, mem_type, data));
435441428dfSJeremy L Thompson     } else {
4362b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextGetDataRead(ctx, mem_type, data));
437441428dfSJeremy L Thompson     }
438441428dfSJeremy L Thompson   } else {
439441428dfSJeremy L Thompson     *(void **)data = NULL;
440441428dfSJeremy L Thompson   }
441441428dfSJeremy L Thompson   return CEED_ERROR_SUCCESS;
442441428dfSJeremy L Thompson }
443441428dfSJeremy L Thompson 
444441428dfSJeremy L Thompson /**
445ca94c3ddSJeremy L Thompson   @brief Restore inner context data of a `CeedQFunction`
446441428dfSJeremy L Thompson 
447ca94c3ddSJeremy L Thompson   @param[in]     qf   `CeedQFunction`
448ea61e9acSJeremy L Thompson   @param[in,out] data Data to restore
449441428dfSJeremy L Thompson 
450441428dfSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
451441428dfSJeremy L Thompson 
452441428dfSJeremy L Thompson   @ref Backend
453441428dfSJeremy L Thompson **/
454441428dfSJeremy L Thompson int CeedQFunctionRestoreInnerContextData(CeedQFunction qf, void *data) {
455441428dfSJeremy L Thompson   bool                 is_writable;
456441428dfSJeremy L Thompson   CeedQFunctionContext ctx;
457441428dfSJeremy L Thompson 
4582b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionGetInnerContext(qf, &ctx));
459441428dfSJeremy L Thompson   if (ctx) {
4602b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionIsContextWritable(qf, &is_writable));
461441428dfSJeremy L Thompson     if (is_writable) {
4622b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextRestoreData(ctx, data));
463441428dfSJeremy L Thompson     } else {
4642b730f8bSJeremy L Thompson       CeedCall(CeedQFunctionContextRestoreDataRead(ctx, data));
465441428dfSJeremy L Thompson     }
466441428dfSJeremy L Thompson   }
4675f249b39SJeremy L Thompson   *(void **)data = NULL;
468441428dfSJeremy L Thompson   return CEED_ERROR_SUCCESS;
469441428dfSJeremy L Thompson }
470441428dfSJeremy L Thompson 
471441428dfSJeremy L Thompson /**
472ca94c3ddSJeremy L Thompson   @brief Determine if `CeedQFunction` is identity
4737a982d89SJeremy L. Thompson 
474ca94c3ddSJeremy L Thompson   @param[in]  qf          `CeedQFunction`
475d1d35e2fSjeremylt   @param[out] is_identity Variable to store identity status
4767a982d89SJeremy L. Thompson 
4777a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4787a982d89SJeremy L. Thompson 
4797a982d89SJeremy L. Thompson   @ref Backend
4807a982d89SJeremy L. Thompson **/
481d1d35e2fSjeremylt int CeedQFunctionIsIdentity(CeedQFunction qf, bool *is_identity) {
482f04ea552SJeremy L Thompson   *is_identity = qf->is_identity;
483e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4847a982d89SJeremy L. Thompson }
4857a982d89SJeremy L. Thompson 
4867a982d89SJeremy L. Thompson /**
487ca94c3ddSJeremy L Thompson   @brief Determine if `CeedQFunctionContext` is writable
488441428dfSJeremy L Thompson 
489ca94c3ddSJeremy L Thompson   @param[in]  qf          `CeedQFunction`
490ea61e9acSJeremy L Thompson   @param[out] is_writable Variable to store context writeable status
491441428dfSJeremy L Thompson 
492441428dfSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
493441428dfSJeremy L Thompson 
494441428dfSJeremy L Thompson   @ref Backend
495441428dfSJeremy L Thompson **/
496441428dfSJeremy L Thompson int CeedQFunctionIsContextWritable(CeedQFunction qf, bool *is_writable) {
497441428dfSJeremy L Thompson   *is_writable = qf->is_context_writable;
498441428dfSJeremy L Thompson   return CEED_ERROR_SUCCESS;
499441428dfSJeremy L Thompson }
500441428dfSJeremy L Thompson 
501441428dfSJeremy L Thompson /**
502ca94c3ddSJeremy L Thompson   @brief Get backend data of a `CeedQFunction`
5037a982d89SJeremy L. Thompson 
504ca94c3ddSJeremy L Thompson   @param[in]  qf   `CeedQFunction`
5057a982d89SJeremy L. Thompson   @param[out] data Variable to store data
5067a982d89SJeremy L. Thompson 
5077a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
5087a982d89SJeremy L. Thompson 
5097a982d89SJeremy L. Thompson   @ref Backend
5107a982d89SJeremy L. Thompson **/
511777ff853SJeremy L Thompson int CeedQFunctionGetData(CeedQFunction qf, void *data) {
512777ff853SJeremy L Thompson   *(void **)data = qf->data;
513e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5147a982d89SJeremy L. Thompson }
5157a982d89SJeremy L. Thompson 
5167a982d89SJeremy L. Thompson /**
517ca94c3ddSJeremy L Thompson   @brief Set backend data of a `CeedQFunction`
5187a982d89SJeremy L. Thompson 
519ca94c3ddSJeremy L Thompson   @param[in,out] qf   `CeedQFunction`
520ea61e9acSJeremy L Thompson   @param[in]     data Data to set
5217a982d89SJeremy L. Thompson 
5227a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
5237a982d89SJeremy L. Thompson 
5247a982d89SJeremy L. Thompson   @ref Backend
5257a982d89SJeremy L. Thompson **/
526777ff853SJeremy L Thompson int CeedQFunctionSetData(CeedQFunction qf, void *data) {
527777ff853SJeremy L Thompson   qf->data = data;
528e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5297a982d89SJeremy L. Thompson }
5307a982d89SJeremy L. Thompson 
5317a982d89SJeremy L. Thompson /**
5321203703bSJeremy L Thompson   @brief Get a boolean value indicating if the `CeedQFunction` is immutable
5331203703bSJeremy L Thompson 
5341203703bSJeremy L Thompson   @param[in]  qf           `CeedOperator`
5351203703bSJeremy L Thompson   @param[out] is_immutable Variable to store immutability status
5361203703bSJeremy L Thompson 
5371203703bSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
5381203703bSJeremy L Thompson 
5391203703bSJeremy L Thompson   @ref Backend
5401203703bSJeremy L Thompson **/
5411203703bSJeremy L Thompson int CeedQFunctionIsImmutable(CeedQFunction qf, bool *is_immutable) {
5421203703bSJeremy L Thompson   *is_immutable = qf->is_immutable;
5431203703bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
5441203703bSJeremy L Thompson }
5451203703bSJeremy L Thompson 
5461203703bSJeremy L Thompson /**
5471203703bSJeremy L Thompson   @brief Set the immutable flag of a `CeedQFunction` to `true`
5481203703bSJeremy L Thompson 
5491203703bSJeremy L Thompson   @param[in,out] qf `CeedQFunction`
5501203703bSJeremy L Thompson 
5511203703bSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
5521203703bSJeremy L Thompson 
5531203703bSJeremy L Thompson   @ref Backend
5541203703bSJeremy L Thompson **/
5551203703bSJeremy L Thompson int CeedQFunctionSetImmutable(CeedQFunction qf) {
5561203703bSJeremy L Thompson   qf->is_immutable = true;
5571203703bSJeremy L Thompson   return CEED_ERROR_SUCCESS;
5581203703bSJeremy L Thompson }
5591203703bSJeremy L Thompson 
5601203703bSJeremy L Thompson /**
561ca94c3ddSJeremy L Thompson   @brief Increment the reference counter for a `CeedQFunction`
56234359f16Sjeremylt 
563ca94c3ddSJeremy L Thompson   @param[in,out] qf `CeedQFunction` to increment the reference counter
56434359f16Sjeremylt 
56534359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
56634359f16Sjeremylt 
56734359f16Sjeremylt   @ref Backend
56834359f16Sjeremylt **/
5699560d06aSjeremylt int CeedQFunctionReference(CeedQFunction qf) {
57034359f16Sjeremylt   qf->ref_count++;
57134359f16Sjeremylt   return CEED_ERROR_SUCCESS;
57234359f16Sjeremylt }
57334359f16Sjeremylt 
5746e15d496SJeremy L Thompson /**
575ca94c3ddSJeremy L Thompson   @brief Estimate number of FLOPs per quadrature required to apply `CeedQFunction`
5766e15d496SJeremy L Thompson 
577ca94c3ddSJeremy L Thompson   @param[in]  qf    `CeedQFunction` to estimate FLOPs for
578ea61e9acSJeremy L Thompson   @param[out] flops Address of variable to hold FLOPs estimate
5796e15d496SJeremy L Thompson 
5806e15d496SJeremy L Thompson   @ref Backend
5816e15d496SJeremy L Thompson **/
5829d36ca50SJeremy L Thompson int CeedQFunctionGetFlopsEstimate(CeedQFunction qf, CeedSize *flops) {
5836e15d496SJeremy L Thompson   *flops = qf->user_flop_estimate;
5846e15d496SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5856e15d496SJeremy L Thompson }
5866e15d496SJeremy L Thompson 
5877a982d89SJeremy L. Thompson /// @}
5887a982d89SJeremy L. Thompson 
5897a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
5907a982d89SJeremy L. Thompson /// CeedQFunction Public API
5917a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
5927a982d89SJeremy L. Thompson /// @addtogroup CeedQFunctionUser
5937a982d89SJeremy L. Thompson /// @{
5947a982d89SJeremy L. Thompson 
5957a982d89SJeremy L. Thompson /**
596ca94c3ddSJeremy L Thompson   @brief Create a `CeedQFunction` for evaluating interior (volumetric) terms
5977a982d89SJeremy L. Thompson 
598ca94c3ddSJeremy L Thompson   @param[in]  ceed       `Ceed` object used to create the `CeedQFunction`
599ca94c3ddSJeremy L Thompson   @param[in]  vec_length Vector length.
600ca94c3ddSJeremy L Thompson                            Caller must ensure that number of quadrature points is a multiple of `vec_length`.
601ea61e9acSJeremy L Thompson   @param[in]  f          Function pointer to evaluate action at quadrature points.
602ca94c3ddSJeremy L Thompson                            See `CeedQFunctionUser`.
603ca94c3ddSJeremy L Thompson   @param[in]  source     Absolute path to source of `CeedQFunctionUser`, "\abs_path\file.h:function_name".
604ca94c3ddSJeremy 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.).
6054ada38baSJames Wright                            The entire contents of this file and all locally included files are used during JiT compilation for GPU backends.
6064ada38baSJames Wright                            All source files must be at the provided filepath at runtime for JiT to function.
607ca94c3ddSJeremy L Thompson   @param[out] qf         Address of the variable where the newly created `CeedQFunction` will be stored
6087a982d89SJeremy L. Thompson 
6097a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
6107a982d89SJeremy L. Thompson 
611ca94c3ddSJeremy L Thompson   See \ref CeedQFunctionUser for details on the call-back function `f` arguments.
6127a982d89SJeremy L. Thompson 
6137a982d89SJeremy L. Thompson   @ref User
6147a982d89SJeremy L. Thompson **/
6152b730f8bSJeremy L Thompson int CeedQFunctionCreateInterior(Ceed ceed, CeedInt vec_length, CeedQFunctionUser f, const char *source, CeedQFunction *qf) {
616ca5eadf8SJeremy L Thompson   char *user_source_copy;
6177a982d89SJeremy L. Thompson 
6187a982d89SJeremy L. Thompson   if (!ceed->QFunctionCreate) {
6197a982d89SJeremy L. Thompson     Ceed delegate;
6206574a04fSJeremy L Thompson 
6212b730f8bSJeremy L Thompson     CeedCall(CeedGetObjectDelegate(ceed, &delegate, "QFunction"));
622ca94c3ddSJeremy L Thompson     CeedCheck(delegate, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support CeedQFunctionCreateInterior");
6232b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionCreateInterior(delegate, vec_length, f, source, qf));
624e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
6257a982d89SJeremy L. Thompson   }
6267a982d89SJeremy L. Thompson 
6276574a04fSJeremy L Thompson   CeedCheck(!strlen(source) || strrchr(source, ':'), ceed, CEED_ERROR_INCOMPLETE,
6286574a04fSJeremy L Thompson             "Provided path to source does not include function name. Provided: \"%s\"\nRequired: \"\\abs_path\\file.h:function_name\"", source);
62943e1b16fSJeremy L Thompson 
6302b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(1, qf));
631db002c03SJeremy L Thompson   CeedCall(CeedReferenceCopy(ceed, &(*qf)->ceed));
632d1d35e2fSjeremylt   (*qf)->ref_count           = 1;
633d1d35e2fSjeremylt   (*qf)->vec_length          = vec_length;
634f04ea552SJeremy L Thompson   (*qf)->is_identity         = false;
635441428dfSJeremy L Thompson   (*qf)->is_context_writable = true;
6367a982d89SJeremy L. Thompson   (*qf)->function            = f;
6376e15d496SJeremy L Thompson   (*qf)->user_flop_estimate  = -1;
63843e1b16fSJeremy L Thompson   if (strlen(source)) {
639ca5eadf8SJeremy L Thompson     size_t user_source_len = strlen(source);
640ee5a26f2SJeremy L Thompson 
6412b730f8bSJeremy L Thompson     CeedCall(CeedCalloc(user_source_len + 1, &user_source_copy));
642ca5eadf8SJeremy L Thompson     memcpy(user_source_copy, source, user_source_len);
643ca5eadf8SJeremy L Thompson     (*qf)->user_source = user_source_copy;
64443e1b16fSJeremy L Thompson   }
6452b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(CEED_FIELD_MAX, &(*qf)->input_fields));
6462b730f8bSJeremy L Thompson   CeedCall(CeedCalloc(CEED_FIELD_MAX, &(*qf)->output_fields));
6472b730f8bSJeremy L Thompson   CeedCall(ceed->QFunctionCreate(*qf));
648e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
6497a982d89SJeremy L. Thompson }
6507a982d89SJeremy L. Thompson 
6517a982d89SJeremy L. Thompson /**
652ca94c3ddSJeremy L Thompson   @brief Create a `CeedQFunction` for evaluating interior (volumetric) terms by name
653288c0443SJeremy L Thompson 
654ca94c3ddSJeremy L Thompson   @param[in]  ceed `Ceed` object used to create the `CeedQFunction`
655ca94c3ddSJeremy L Thompson   @param[in]  name Name of `CeedQFunction` to use from gallery
656ca94c3ddSJeremy L Thompson   @param[out] qf   Address of the variable where the newly created `CeedQFunction` will be stored
657288c0443SJeremy L Thompson 
658288c0443SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
659288c0443SJeremy L Thompson 
6607a982d89SJeremy L. Thompson   @ref User
661288c0443SJeremy L Thompson **/
6622b730f8bSJeremy L Thompson int CeedQFunctionCreateInteriorByName(Ceed ceed, const char *name, CeedQFunction *qf) {
663f7e22acaSJeremy L Thompson   size_t match_len = 0, match_index = UINT_MAX;
664288c0443SJeremy L Thompson 
6652b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionRegisterAll());
666288c0443SJeremy L Thompson   // Find matching backend
667ca94c3ddSJeremy L Thompson   CeedCheck(name, ceed, CEED_ERROR_INCOMPLETE, "No CeedQFunction name provided");
668288c0443SJeremy L Thompson   for (size_t i = 0; i < num_qfunctions; i++) {
669288c0443SJeremy L Thompson     size_t      n;
670d1d35e2fSjeremylt     const char *curr_name = gallery_qfunctions[i].name;
6712b730f8bSJeremy L Thompson     for (n = 0; curr_name[n] && curr_name[n] == name[n]; n++) {
6722b730f8bSJeremy L Thompson     }
673d1d35e2fSjeremylt     if (n > match_len) {
674d1d35e2fSjeremylt       match_len   = n;
675f7e22acaSJeremy L Thompson       match_index = i;
676288c0443SJeremy L Thompson     }
677288c0443SJeremy L Thompson   }
678ca94c3ddSJeremy L Thompson   CeedCheck(match_len > 0, ceed, CEED_ERROR_UNSUPPORTED, "No suitable gallery CeedQFunction");
679288c0443SJeremy L Thompson 
680288c0443SJeremy L Thompson   // Create QFunction
6812b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionCreateInterior(ceed, gallery_qfunctions[match_index].vec_length, gallery_qfunctions[match_index].f,
6822b730f8bSJeremy L Thompson                                        gallery_qfunctions[match_index].source, qf));
683288c0443SJeremy L Thompson 
684288c0443SJeremy L Thompson   // QFunction specific setup
6852b730f8bSJeremy L Thompson   CeedCall(gallery_qfunctions[match_index].init(ceed, name, *qf));
686288c0443SJeremy L Thompson 
68775affc3bSjeremylt   // Copy name
6882b730f8bSJeremy L Thompson   CeedCall(CeedStringAllocCopy(name, (char **)&(*qf)->gallery_name));
68943e1b16fSJeremy L Thompson   (*qf)->is_gallery = true;
690e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
691288c0443SJeremy L Thompson }
692288c0443SJeremy L Thompson 
693288c0443SJeremy L Thompson /**
694ca94c3ddSJeremy L Thompson   @brief Create an identity `CeedQFunction`.
6954385fb7fSSebastian Grimberg 
696ea61e9acSJeremy L Thompson   Inputs are written into outputs in the order given.
697ca94c3ddSJeremy 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.
698ca94c3ddSJeremy 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.
6990219ea01SJeremy L Thompson 
700ca94c3ddSJeremy L Thompson   @param[in]  ceed     `Ceed` object used to create the `CeedQFunction`
701ca94c3ddSJeremy L Thompson   @param[in]  size     Size of the `CeedQFunction` fields
702ca94c3ddSJeremy L Thompson   @param[in]  in_mode  @ref CeedEvalMode for input to `CeedQFunction`
703ca94c3ddSJeremy L Thompson   @param[in]  out_mode @ref CeedEvalMode for output to `CeedQFunction`
704ca94c3ddSJeremy L Thompson   @param[out] qf       Address of the variable where the newly created `CeedQFunction` will be stored
7050219ea01SJeremy L Thompson 
7060219ea01SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
7070219ea01SJeremy L Thompson 
7087a982d89SJeremy L. Thompson   @ref User
7090219ea01SJeremy L Thompson **/
7102b730f8bSJeremy L Thompson int CeedQFunctionCreateIdentity(Ceed ceed, CeedInt size, CeedEvalMode in_mode, CeedEvalMode out_mode, CeedQFunction *qf) {
7111c66c397SJeremy L Thompson   CeedQFunctionContext  ctx;
7121c66c397SJeremy L Thompson   CeedContextFieldLabel size_label;
7131c66c397SJeremy L Thompson 
7142b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionCreateInteriorByName(ceed, "Identity", qf));
7152b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionAddInput(*qf, "input", size, in_mode));
7162b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionAddOutput(*qf, "output", size, out_mode));
7170219ea01SJeremy L Thompson 
718f04ea552SJeremy L Thompson   (*qf)->is_identity = true;
719547dbd6fSJeremy L Thompson 
7202b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionGetContext(*qf, &ctx));
7212b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextGetFieldLabel(ctx, "size", &size_label));
7222b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextSetInt32(ctx, size_label, &size));
723e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
7240219ea01SJeremy L Thompson }
7250219ea01SJeremy L Thompson 
7260219ea01SJeremy L Thompson /**
727ca94c3ddSJeremy L Thompson   @brief Copy the pointer to a `CeedQFunction`.
7284385fb7fSSebastian Grimberg 
729ca94c3ddSJeremy L Thompson   Both pointers should be destroyed with @ref CeedQFunctionDestroy().
730512bb800SJeremy L Thompson 
731ca94c3ddSJeremy 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`.
732ca94c3ddSJeremy L Thompson         This `CeedQFunction` will be destroyed if `*qf_copy` is the only reference to this `CeedQFunction`.
7339560d06aSjeremylt 
734ca94c3ddSJeremy L Thompson   @param[in]  qf      `CeedQFunction` to copy reference to
7359560d06aSjeremylt   @param[out] qf_copy Variable to store copied reference
7369560d06aSjeremylt 
7379560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
7389560d06aSjeremylt 
7399560d06aSjeremylt   @ref User
7409560d06aSjeremylt **/
7419560d06aSjeremylt int CeedQFunctionReferenceCopy(CeedQFunction qf, CeedQFunction *qf_copy) {
7422b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionReference(qf));
7432b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionDestroy(qf_copy));
7449560d06aSjeremylt   *qf_copy = qf;
7459560d06aSjeremylt   return CEED_ERROR_SUCCESS;
7469560d06aSjeremylt }
7479560d06aSjeremylt 
7489560d06aSjeremylt /**
749ca94c3ddSJeremy L Thompson   @brief Add a `CeedQFunction` input
750b11c1e72Sjeremylt 
751ca94c3ddSJeremy L Thompson   @param[in,out] qf         `CeedQFunction`
752ca94c3ddSJeremy L Thompson   @param[in]     field_name Name of `CeedQFunction` field
753ca94c3ddSJeremy 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.
754ca94c3ddSJeremy L Thompson   @param[in]     eval_mode  @ref CEED_EVAL_NONE to use values directly,
755ca94c3ddSJeremy L Thompson                               @ref CEED_EVAL_INTERP to use interpolated values,
756ca94c3ddSJeremy L Thompson                               @ref CEED_EVAL_GRAD to use gradients,
757ca94c3ddSJeremy L Thompson                               @ref CEED_EVAL_DIV to use divergence,
758ca94c3ddSJeremy L Thompson                               @ref CEED_EVAL_CURL to use curl
759b11c1e72Sjeremylt 
760b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
761dfdf5a53Sjeremylt 
7627a982d89SJeremy L. Thompson   @ref User
763b11c1e72Sjeremylt **/
7642b730f8bSJeremy L Thompson int CeedQFunctionAddInput(CeedQFunction qf, const char *field_name, CeedInt size, CeedEvalMode eval_mode) {
7651203703bSJeremy L Thompson   bool is_immutable;
7661203703bSJeremy L Thompson   Ceed ceed;
7671203703bSJeremy L Thompson 
7681203703bSJeremy L Thompson   CeedCall(CeedQFunctionGetCeed(qf, &ceed));
7691203703bSJeremy L Thompson   CeedCall(CeedQFunctionIsImmutable(qf, &is_immutable));
7701203703bSJeremy L Thompson   CeedCheck(!is_immutable, ceed, CEED_ERROR_MAJOR, "QFunction cannot be changed after set as immutable");
7711203703bSJeremy L Thompson   CeedCheck(eval_mode != CEED_EVAL_WEIGHT || size == 1, ceed, CEED_ERROR_DIMENSION, "CEED_EVAL_WEIGHT should have size 1");
772643fbb69SJeremy L Thompson   for (CeedInt i = 0; i < qf->num_input_fields; i++) {
7731203703bSJeremy L Thompson     CeedCheck(strcmp(field_name, qf->input_fields[i]->field_name), ceed, CEED_ERROR_MINOR, "CeedQFunction field names must be unique");
774643fbb69SJeremy L Thompson   }
775643fbb69SJeremy L Thompson   for (CeedInt i = 0; i < qf->num_output_fields; i++) {
7761203703bSJeremy L Thompson     CeedCheck(strcmp(field_name, qf->output_fields[i]->field_name), ceed, CEED_ERROR_MINOR, "CeedQFunction field names must be unique");
777643fbb69SJeremy L Thompson   }
7782b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionFieldSet(&qf->input_fields[qf->num_input_fields], field_name, size, eval_mode));
779d1d35e2fSjeremylt   qf->num_input_fields++;
780e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
781d7b241e6Sjeremylt }
782d7b241e6Sjeremylt 
783b11c1e72Sjeremylt /**
784ca94c3ddSJeremy L Thompson   @brief Add a `CeedQFunction` output
785b11c1e72Sjeremylt 
786ca94c3ddSJeremy L Thompson   @param[in,out] qf         `CeedQFunction`
787ca94c3ddSJeremy L Thompson   @param[in]     field_name Name of `CeedQFunction` field
788ca94c3ddSJeremy 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.
789ca94c3ddSJeremy L Thompson   @param[in]     eval_mode  @ref CEED_EVAL_NONE to use values directly,
790ca94c3ddSJeremy L Thompson                               @ref CEED_EVAL_INTERP to use interpolated values,
791ca94c3ddSJeremy L Thompson                               @ref CEED_EVAL_GRAD to use gradients,
792ca94c3ddSJeremy L Thompson                               @ref CEED_EVAL_DIV to use divergence,
793ca94c3ddSJeremy L Thompson                               @ref CEED_EVAL_CURL to use curl.
794b11c1e72Sjeremylt 
795b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
796dfdf5a53Sjeremylt 
7977a982d89SJeremy L. Thompson   @ref User
798b11c1e72Sjeremylt **/
7992b730f8bSJeremy L Thompson int CeedQFunctionAddOutput(CeedQFunction qf, const char *field_name, CeedInt size, CeedEvalMode eval_mode) {
8001203703bSJeremy L Thompson   bool is_immutable;
8011203703bSJeremy L Thompson   Ceed ceed;
8021203703bSJeremy L Thompson 
8031203703bSJeremy L Thompson   CeedCall(CeedQFunctionGetCeed(qf, &ceed));
8041203703bSJeremy L Thompson   CeedCall(CeedQFunctionIsImmutable(qf, &is_immutable));
8051203703bSJeremy L Thompson   CeedCheck(!is_immutable, ceed, CEED_ERROR_MAJOR, "CeedQFunction cannot be changed after set as immutable");
8061203703bSJeremy L Thompson   CeedCheck(eval_mode != CEED_EVAL_WEIGHT, ceed, CEED_ERROR_DIMENSION, "Cannot create CeedQFunction output with CEED_EVAL_WEIGHT");
807643fbb69SJeremy L Thompson   for (CeedInt i = 0; i < qf->num_input_fields; i++) {
8081203703bSJeremy L Thompson     CeedCheck(strcmp(field_name, qf->input_fields[i]->field_name), ceed, CEED_ERROR_MINOR, "CeedQFunction field names must be unique");
809643fbb69SJeremy L Thompson   }
810643fbb69SJeremy L Thompson   for (CeedInt i = 0; i < qf->num_output_fields; i++) {
8111203703bSJeremy L Thompson     CeedCheck(strcmp(field_name, qf->output_fields[i]->field_name), ceed, CEED_ERROR_MINOR, "CeedQFunction field names must be unique");
812643fbb69SJeremy L Thompson   }
8132b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionFieldSet(&qf->output_fields[qf->num_output_fields], field_name, size, eval_mode));
814d1d35e2fSjeremylt   qf->num_output_fields++;
815e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
816d7b241e6Sjeremylt }
817d7b241e6Sjeremylt 
818dfdf5a53Sjeremylt /**
819ca94c3ddSJeremy L Thompson   @brief Get the `CeedQFunctionField` of a `CeedQFunction`
82043bbe138SJeremy L Thompson 
821ca94c3ddSJeremy L Thompson   Note: Calling this function asserts that setup is complete and sets the `CeedQFunction` as immutable.
822f04ea552SJeremy L Thompson 
823ca94c3ddSJeremy L Thompson   @param[in]  qf                `CeedQFunction`
824f74ec584SJeremy L Thompson   @param[out] num_input_fields  Variable to store number of input fields
825f74ec584SJeremy L Thompson   @param[out] input_fields      Variable to store input fields
826f74ec584SJeremy L Thompson   @param[out] num_output_fields Variable to store number of output fields
827f74ec584SJeremy L Thompson   @param[out] output_fields     Variable to store output fields
82843bbe138SJeremy L Thompson 
82943bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
83043bbe138SJeremy L Thompson 
831e9b533fbSJeremy L Thompson   @ref Advanced
83243bbe138SJeremy L Thompson **/
8332b730f8bSJeremy L Thompson int CeedQFunctionGetFields(CeedQFunction qf, CeedInt *num_input_fields, CeedQFunctionField **input_fields, CeedInt *num_output_fields,
83443bbe138SJeremy L Thompson                            CeedQFunctionField **output_fields) {
8351203703bSJeremy L Thompson   CeedCall(CeedQFunctionSetImmutable(qf));
83643bbe138SJeremy L Thompson   if (num_input_fields) *num_input_fields = qf->num_input_fields;
83743bbe138SJeremy L Thompson   if (input_fields) *input_fields = qf->input_fields;
83843bbe138SJeremy L Thompson   if (num_output_fields) *num_output_fields = qf->num_output_fields;
83943bbe138SJeremy L Thompson   if (output_fields) *output_fields = qf->output_fields;
84043bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
84143bbe138SJeremy L Thompson }
84243bbe138SJeremy L Thompson 
84343bbe138SJeremy L Thompson /**
844ca94c3ddSJeremy L Thompson   @brief Get the name of a `CeedQFunctionField`
84543bbe138SJeremy L Thompson 
846ca94c3ddSJeremy L Thompson   @param[in]  qf_field   `CeedQFunctionField`
84743bbe138SJeremy L Thompson   @param[out] field_name Variable to store the field name
84843bbe138SJeremy L Thompson 
84943bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
85043bbe138SJeremy L Thompson 
851e9b533fbSJeremy L Thompson   @ref Advanced
85243bbe138SJeremy L Thompson **/
85343bbe138SJeremy L Thompson int CeedQFunctionFieldGetName(CeedQFunctionField qf_field, char **field_name) {
85443bbe138SJeremy L Thompson   *field_name = (char *)qf_field->field_name;
85543bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
85643bbe138SJeremy L Thompson }
85743bbe138SJeremy L Thompson 
85843bbe138SJeremy L Thompson /**
859ca94c3ddSJeremy L Thompson   @brief Get the number of components of a `CeedQFunctionField`
86043bbe138SJeremy L Thompson 
861ca94c3ddSJeremy L Thompson   @param[in]  qf_field `CeedQFunctionField`
86243bbe138SJeremy L Thompson   @param[out] size     Variable to store the size of the field
86343bbe138SJeremy L Thompson 
86443bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
86543bbe138SJeremy L Thompson 
866e9b533fbSJeremy L Thompson   @ref Advanced
86743bbe138SJeremy L Thompson **/
86843bbe138SJeremy L Thompson int CeedQFunctionFieldGetSize(CeedQFunctionField qf_field, CeedInt *size) {
86943bbe138SJeremy L Thompson   *size = qf_field->size;
87043bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
87143bbe138SJeremy L Thompson }
87243bbe138SJeremy L Thompson 
87343bbe138SJeremy L Thompson /**
874ca94c3ddSJeremy L Thompson   @brief Get the @ref CeedEvalMode of a `CeedQFunctionField`
87543bbe138SJeremy L Thompson 
876ca94c3ddSJeremy L Thompson   @param[in]  qf_field  `CeedQFunctionField`
87743bbe138SJeremy L Thompson   @param[out] eval_mode Variable to store the field evaluation mode
87843bbe138SJeremy L Thompson 
87943bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
88043bbe138SJeremy L Thompson 
881e9b533fbSJeremy L Thompson   @ref Advanced
88243bbe138SJeremy L Thompson **/
8832b730f8bSJeremy L Thompson int CeedQFunctionFieldGetEvalMode(CeedQFunctionField qf_field, CeedEvalMode *eval_mode) {
88443bbe138SJeremy L Thompson   *eval_mode = qf_field->eval_mode;
88543bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
88643bbe138SJeremy L Thompson }
88743bbe138SJeremy L Thompson 
88843bbe138SJeremy L Thompson /**
889*ab747706SJeremy L Thompson   @brief Get the data of a `CeedQFunctionField`.
890*ab747706SJeremy L Thompson 
891*ab747706SJeremy L Thompson   Any arguments set as `NULL` are ignored.
892*ab747706SJeremy L Thompson 
893*ab747706SJeremy L Thompson   @param[in]  qf_field   `CeedQFunctionField`
894*ab747706SJeremy L Thompson   @param[out] field_name Variable to store the field name
895*ab747706SJeremy L Thompson   @param[out] size       Variable to store the size of the field
896*ab747706SJeremy L Thompson   @param[out] eval_mode  Variable to store the field evaluation mode
897*ab747706SJeremy L Thompson 
898*ab747706SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
899*ab747706SJeremy L Thompson 
900*ab747706SJeremy L Thompson   @ref Advanced
901*ab747706SJeremy L Thompson **/
902*ab747706SJeremy L Thompson int CeedQFunctionFieldGetData(CeedQFunctionField qf_field, char **field_name, CeedInt *size, CeedEvalMode *eval_mode) {
903*ab747706SJeremy L Thompson   if (field_name) CeedCall(CeedQFunctionFieldGetName(qf_field, field_name));
904*ab747706SJeremy L Thompson   if (size) CeedCall(CeedQFunctionFieldGetSize(qf_field, size));
905*ab747706SJeremy L Thompson   if (eval_mode) CeedCall(CeedQFunctionFieldGetEvalMode(qf_field, eval_mode));
906*ab747706SJeremy L Thompson   return CEED_ERROR_SUCCESS;
907*ab747706SJeremy L Thompson }
908*ab747706SJeremy L Thompson 
909*ab747706SJeremy L Thompson /**
910ca94c3ddSJeremy L Thompson   @brief Set global context for a `CeedQFunction`
911b11c1e72Sjeremylt 
912ca94c3ddSJeremy L Thompson   @param[in,out] qf  `CeedQFunction`
913ea61e9acSJeremy L Thompson   @param[in]     ctx Context data to set
914b11c1e72Sjeremylt 
915b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
916dfdf5a53Sjeremylt 
9177a982d89SJeremy L. Thompson   @ref User
918b11c1e72Sjeremylt **/
919777ff853SJeremy L Thompson int CeedQFunctionSetContext(CeedQFunction qf, CeedQFunctionContext ctx) {
9202b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextDestroy(&qf->ctx));
921d7b241e6Sjeremylt   qf->ctx = ctx;
922db002c03SJeremy L Thompson   if (ctx) CeedCall(CeedQFunctionContextReference(ctx));
923e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
924d7b241e6Sjeremylt }
925d7b241e6Sjeremylt 
926b11c1e72Sjeremylt /**
927ca94c3ddSJeremy L Thompson   @brief Set writability of `CeedQFunctionContext` when calling the `CeedQFunctionUser`.
9284385fb7fSSebastian Grimberg 
929859c15bbSJames Wright   The default value is `is_writable == true`.
930441428dfSJeremy L Thompson 
931ca94c3ddSJeremy L Thompson   Setting `is_writable == true` indicates the `CeedQFunctionUser` writes into the `CeedQFunctionContext` and requires memory synchronization after calling @ref CeedQFunctionApply().
932441428dfSJeremy L Thompson 
933ca94c3ddSJeremy L Thompson   Setting 'is_writable == false' asserts that `CeedQFunctionUser` does not modify the `CeedQFunctionContext`.
934ea61e9acSJeremy L Thompson   Violating this assertion may lead to inconsistent data.
935441428dfSJeremy L Thompson 
936441428dfSJeremy L Thompson   Setting `is_writable == false` may offer a performance improvement on GPU backends.
937441428dfSJeremy L Thompson 
938ca94c3ddSJeremy L Thompson   @param[in,out] qf          `CeedQFunction`
939ca94c3ddSJeremy L Thompson   @param[in]     is_writable Boolean flag for writability status
940441428dfSJeremy L Thompson 
941441428dfSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
942441428dfSJeremy L Thompson 
943441428dfSJeremy L Thompson   @ref User
944441428dfSJeremy L Thompson **/
945441428dfSJeremy L Thompson int CeedQFunctionSetContextWritable(CeedQFunction qf, bool is_writable) {
946441428dfSJeremy L Thompson   qf->is_context_writable = is_writable;
947441428dfSJeremy L Thompson   return CEED_ERROR_SUCCESS;
948441428dfSJeremy L Thompson }
949441428dfSJeremy L Thompson 
950441428dfSJeremy L Thompson /**
951ca94c3ddSJeremy L Thompson   @brief Set estimated number of FLOPs per quadrature required to apply `CeedQFunction`
9526e15d496SJeremy L Thompson 
953ca94c3ddSJeremy L Thompson   @param[in]  qf    `CeedQFunction` to estimate FLOPs for
954ea61e9acSJeremy L Thompson   @param[out] flops FLOPs per quadrature point estimate
9556e15d496SJeremy L Thompson 
9566e15d496SJeremy L Thompson   @ref Backend
9576e15d496SJeremy L Thompson **/
9589d36ca50SJeremy L Thompson int CeedQFunctionSetUserFlopsEstimate(CeedQFunction qf, CeedSize flops) {
9591203703bSJeremy L Thompson   Ceed ceed;
9601203703bSJeremy L Thompson 
9611203703bSJeremy L Thompson   CeedCall(CeedQFunctionGetCeed(qf, &ceed));
9621203703bSJeremy L Thompson   CeedCheck(flops >= 0, ceed, CEED_ERROR_INCOMPATIBLE, "Must set non-negative FLOPs estimate");
9636e15d496SJeremy L Thompson   qf->user_flop_estimate = flops;
9646e15d496SJeremy L Thompson   return CEED_ERROR_SUCCESS;
9656e15d496SJeremy L Thompson }
9666e15d496SJeremy L Thompson 
9676e15d496SJeremy L Thompson /**
968ca94c3ddSJeremy L Thompson   @brief View a `CeedQFunction`
96975affc3bSjeremylt 
970ca94c3ddSJeremy L Thompson   @param[in] qf     `CeedQFunction` to view
971ca94c3ddSJeremy L Thompson   @param[in] stream Stream to write; typically `stdout` or a file
97275affc3bSjeremylt 
97375affc3bSjeremylt   @return Error code: 0 - success, otherwise - failure
97475affc3bSjeremylt 
9757a982d89SJeremy L. Thompson   @ref User
97675affc3bSjeremylt **/
97775affc3bSjeremylt int CeedQFunctionView(CeedQFunction qf, FILE *stream) {
978ca5eadf8SJeremy L Thompson   char *kernel_name;
97975affc3bSjeremylt 
9802b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionGetKernelName(qf, &kernel_name));
9812b730f8bSJeremy L Thompson   fprintf(stream, "%sCeedQFunction - %s\n", qf->is_gallery ? "Gallery " : "User ", qf->is_gallery ? qf->gallery_name : kernel_name);
98275affc3bSjeremylt 
9832b730f8bSJeremy L Thompson   fprintf(stream, "  %" CeedInt_FMT " input field%s:\n", qf->num_input_fields, qf->num_input_fields > 1 ? "s" : "");
984d1d35e2fSjeremylt   for (CeedInt i = 0; i < qf->num_input_fields; i++) {
9852b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionFieldView(qf->input_fields[i], i, 1, stream));
98675affc3bSjeremylt   }
98775affc3bSjeremylt 
9882b730f8bSJeremy L Thompson   fprintf(stream, "  %" CeedInt_FMT " output field%s:\n", qf->num_output_fields, qf->num_output_fields > 1 ? "s" : "");
989d1d35e2fSjeremylt   for (CeedInt i = 0; i < qf->num_output_fields; i++) {
9902b730f8bSJeremy L Thompson     CeedCall(CeedQFunctionFieldView(qf->output_fields[i], i, 0, stream));
99175affc3bSjeremylt   }
992e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
99375affc3bSjeremylt }
99475affc3bSjeremylt 
99575affc3bSjeremylt /**
996ca94c3ddSJeremy L Thompson   @brief Get the `Ceed` associated with a `CeedQFunction`
997b7c9bbdaSJeremy L Thompson 
998ca94c3ddSJeremy L Thompson   @param[in]  qf   `CeedQFunction`
999ca94c3ddSJeremy L Thompson   @param[out] ceed Variable to store`Ceed`
1000b7c9bbdaSJeremy L Thompson 
1001b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1002b7c9bbdaSJeremy L Thompson 
1003b7c9bbdaSJeremy L Thompson   @ref Advanced
1004b7c9bbdaSJeremy L Thompson **/
1005b7c9bbdaSJeremy L Thompson int CeedQFunctionGetCeed(CeedQFunction qf, Ceed *ceed) {
1006b7c9bbdaSJeremy L Thompson   *ceed = qf->ceed;
1007b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1008b7c9bbdaSJeremy L Thompson }
1009b7c9bbdaSJeremy L Thompson 
1010b7c9bbdaSJeremy L Thompson /**
1011ca94c3ddSJeremy L Thompson   @brief Apply the action of a `CeedQFunction`
1012b11c1e72Sjeremylt 
1013ca94c3ddSJeremy L Thompson   Note: Calling this function asserts that setup is complete and sets the `CeedQFunction` as immutable.
1014f04ea552SJeremy L Thompson 
1015ca94c3ddSJeremy L Thompson   @param[in]  qf `CeedQFunction`
1016ea61e9acSJeremy L Thompson   @param[in]  Q  Number of quadrature points
1017ca94c3ddSJeremy L Thompson   @param[in]  u  Array of input `CeedVector`
1018ca94c3ddSJeremy L Thompson   @param[out] v  Array of output `CeedVector`
1019b11c1e72Sjeremylt 
1020b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1021dfdf5a53Sjeremylt 
10227a982d89SJeremy L. Thompson   @ref User
1023b11c1e72Sjeremylt **/
10242b730f8bSJeremy L Thompson int CeedQFunctionApply(CeedQFunction qf, CeedInt Q, CeedVector *u, CeedVector *v) {
10251203703bSJeremy L Thompson   CeedInt vec_length;
10261203703bSJeremy L Thompson   Ceed    ceed;
10271203703bSJeremy L Thompson 
10281203703bSJeremy L Thompson   CeedCall(CeedQFunctionGetCeed(qf, &ceed));
10291203703bSJeremy L Thompson   CeedCheck(qf->Apply, ceed, CEED_ERROR_UNSUPPORTED, "Backend does not support CeedQFunctionApply");
10301203703bSJeremy L Thompson   CeedCall(CeedQFunctionGetVectorLength(qf, &vec_length));
10311203703bSJeremy 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,
10321203703bSJeremy L Thompson             qf->vec_length);
10331203703bSJeremy L Thompson   CeedCall(CeedQFunctionSetImmutable(qf));
10342b730f8bSJeremy L Thompson   CeedCall(qf->Apply(qf, Q, u, v));
1035e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1036d7b241e6Sjeremylt }
1037d7b241e6Sjeremylt 
1038b11c1e72Sjeremylt /**
1039ca94c3ddSJeremy L Thompson   @brief Destroy a `CeedQFunction`
1040b11c1e72Sjeremylt 
1041ca94c3ddSJeremy L Thompson   @param[in,out] qf `CeedQFunction` to destroy
1042b11c1e72Sjeremylt 
1043b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1044dfdf5a53Sjeremylt 
10457a982d89SJeremy L. Thompson   @ref User
1046b11c1e72Sjeremylt **/
1047d7b241e6Sjeremylt int CeedQFunctionDestroy(CeedQFunction *qf) {
1048ad6481ceSJeremy L Thompson   if (!*qf || --(*qf)->ref_count > 0) {
1049ad6481ceSJeremy L Thompson     *qf = NULL;
1050ad6481ceSJeremy L Thompson     return CEED_ERROR_SUCCESS;
1051ad6481ceSJeremy L Thompson   }
1052fe2413ffSjeremylt   // Backend destroy
1053d7b241e6Sjeremylt   if ((*qf)->Destroy) {
10542b730f8bSJeremy L Thompson     CeedCall((*qf)->Destroy(*qf));
1055d7b241e6Sjeremylt   }
1056fe2413ffSjeremylt   // Free fields
105792ae7e47SJeremy L Thompson   for (CeedInt i = 0; i < (*qf)->num_input_fields; i++) {
10582b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*(*qf)->input_fields[i]).field_name));
10592b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*qf)->input_fields[i]));
1060fe2413ffSjeremylt   }
106192ae7e47SJeremy L Thompson   for (CeedInt i = 0; i < (*qf)->num_output_fields; i++) {
10622b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*(*qf)->output_fields[i]).field_name));
10632b730f8bSJeremy L Thompson     CeedCall(CeedFree(&(*qf)->output_fields[i]));
1064fe2413ffSjeremylt   }
10652b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*qf)->input_fields));
10662b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*qf)->output_fields));
1067777ff853SJeremy L Thompson 
1068777ff853SJeremy L Thompson   // User context data object
10692b730f8bSJeremy L Thompson   CeedCall(CeedQFunctionContextDestroy(&(*qf)->ctx));
1070fe2413ffSjeremylt 
10712b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*qf)->user_source));
10722b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*qf)->source_path));
10732b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*qf)->gallery_name));
10742b730f8bSJeremy L Thompson   CeedCall(CeedFree(&(*qf)->kernel_name));
10752b730f8bSJeremy L Thompson   CeedCall(CeedDestroy(&(*qf)->ceed));
10762b730f8bSJeremy L Thompson   CeedCall(CeedFree(qf));
1077e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1078d7b241e6Sjeremylt }
1079d7b241e6Sjeremylt 
1080d7b241e6Sjeremylt /// @}
1081