xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-operator.c (revision 4db537f9c218544ffa68e9d17bd8145043aa541b)
1d7b241e6Sjeremylt // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2d7b241e6Sjeremylt // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3d7b241e6Sjeremylt // reserved. See files LICENSE and NOTICE for details.
4d7b241e6Sjeremylt //
5d7b241e6Sjeremylt // This file is part of CEED, a collection of benchmarks, miniapps, software
6d7b241e6Sjeremylt // libraries and APIs for efficient high-order finite element and spectral
7d7b241e6Sjeremylt // element discretizations for exascale applications. For more information and
8d7b241e6Sjeremylt // source code availability see http://github.com/ceed.
9d7b241e6Sjeremylt //
10d7b241e6Sjeremylt // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11d7b241e6Sjeremylt // a collaborative effort of two U.S. Department of Energy organizations (Office
12d7b241e6Sjeremylt // of Science and the National Nuclear Security Administration) responsible for
13d7b241e6Sjeremylt // the planning and preparation of a capable exascale ecosystem, including
14d7b241e6Sjeremylt // software, applications, hardware, advanced system engineering and early
15d7b241e6Sjeremylt // testbed platforms, in support of the nation's exascale computing imperative.
16d7b241e6Sjeremylt 
17ec3da8bcSJed Brown #include <ceed/ceed.h>
18ec3da8bcSJed Brown #include <ceed/backend.h>
193d576824SJeremy L Thompson #include <ceed-impl.h>
203bd813ffSjeremylt #include <math.h>
213d576824SJeremy L Thompson #include <stdbool.h>
223d576824SJeremy L Thompson #include <stdio.h>
233d576824SJeremy L Thompson #include <string.h>
24d7b241e6Sjeremylt 
25dfdf5a53Sjeremylt /// @file
267a982d89SJeremy L. Thompson /// Implementation of CeedOperator interfaces
277a982d89SJeremy L. Thompson 
287a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
297a982d89SJeremy L. Thompson /// CeedOperator Library Internal Functions
307a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
317a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorDeveloper
327a982d89SJeremy L. Thompson /// @{
337a982d89SJeremy L. Thompson 
347a982d89SJeremy L. Thompson /**
35e15f9bd0SJeremy L Thompson   @brief Check if a CeedOperator Field matches the QFunction Field
36e15f9bd0SJeremy L Thompson 
37e15f9bd0SJeremy L Thompson   @param[in] ceed      Ceed object for error handling
38d1d35e2fSjeremylt   @param[in] qf_field  QFunction Field matching Operator Field
39e15f9bd0SJeremy L Thompson   @param[in] r         Operator Field ElemRestriction
40e15f9bd0SJeremy L Thompson   @param[in] b         Operator Field Basis
41e15f9bd0SJeremy L Thompson 
42e15f9bd0SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
43e15f9bd0SJeremy L Thompson 
44e15f9bd0SJeremy L Thompson   @ref Developer
45e15f9bd0SJeremy L Thompson **/
46d1d35e2fSjeremylt static int CeedOperatorCheckField(Ceed ceed, CeedQFunctionField qf_field,
47e15f9bd0SJeremy L Thompson                                   CeedElemRestriction r, CeedBasis b) {
48e15f9bd0SJeremy L Thompson   int ierr;
49d1d35e2fSjeremylt   CeedEvalMode eval_mode = qf_field->eval_mode;
50d1d35e2fSjeremylt   CeedInt dim = 1, num_comp = 1, restr_num_comp = 1, size = qf_field->size;
51e15f9bd0SJeremy L Thompson   // Restriction
52e15f9bd0SJeremy L Thompson   if (r != CEED_ELEMRESTRICTION_NONE) {
53d1d35e2fSjeremylt     if (eval_mode == CEED_EVAL_WEIGHT) {
54e15f9bd0SJeremy L Thompson       // LCOV_EXCL_START
55e1e9e29dSJed Brown       return CeedError(ceed, CEED_ERROR_INCOMPATIBLE,
56e1e9e29dSJed Brown                        "CEED_ELEMRESTRICTION_NONE should be used "
57e15f9bd0SJeremy L Thompson                        "for a field with eval mode CEED_EVAL_WEIGHT");
58e15f9bd0SJeremy L Thompson       // LCOV_EXCL_STOP
59e15f9bd0SJeremy L Thompson     }
60d1d35e2fSjeremylt     ierr = CeedElemRestrictionGetNumComponents(r, &restr_num_comp);
6178464608Sjeremylt     CeedChk(ierr);
62e1e9e29dSJed Brown   }
63d1d35e2fSjeremylt   if ((r == CEED_ELEMRESTRICTION_NONE) != (eval_mode == CEED_EVAL_WEIGHT)) {
64e1e9e29dSJed Brown     // LCOV_EXCL_START
65e1e9e29dSJed Brown     return CeedError(ceed, CEED_ERROR_INCOMPATIBLE,
66e1e9e29dSJed Brown                      "CEED_ELEMRESTRICTION_NONE and CEED_EVAL_WEIGHT "
67e1e9e29dSJed Brown                      "must be used together.");
68e1e9e29dSJed Brown     // LCOV_EXCL_STOP
69e1e9e29dSJed Brown   }
70e15f9bd0SJeremy L Thompson   // Basis
71e15f9bd0SJeremy L Thompson   if (b != CEED_BASIS_COLLOCATED) {
72d1d35e2fSjeremylt     if (eval_mode == CEED_EVAL_NONE)
738229195eSjeremylt       // LCOV_EXCL_START
74e1e9e29dSJed Brown       return CeedError(ceed, CEED_ERROR_INCOMPATIBLE,
75d1d35e2fSjeremylt                        "Field '%s' configured with CEED_EVAL_NONE must "
76d1d35e2fSjeremylt                        "be used with CEED_BASIS_COLLOCATED",
778229195eSjeremylt                        // LCOV_EXCL_STOP
78d1d35e2fSjeremylt                        qf_field->field_name);
79e15f9bd0SJeremy L Thompson     ierr = CeedBasisGetDimension(b, &dim); CeedChk(ierr);
80d1d35e2fSjeremylt     ierr = CeedBasisGetNumComponents(b, &num_comp); CeedChk(ierr);
81d1d35e2fSjeremylt     if (r != CEED_ELEMRESTRICTION_NONE && restr_num_comp != num_comp) {
82e15f9bd0SJeremy L Thompson       // LCOV_EXCL_START
83e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_DIMENSION,
84d1d35e2fSjeremylt                        "Field '%s' of size %d and EvalMode %s: ElemRestriction "
85d1d35e2fSjeremylt                        "has %d components, but Basis has %d components",
86d1d35e2fSjeremylt                        qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode],
87d1d35e2fSjeremylt                        restr_num_comp,
88d1d35e2fSjeremylt                        num_comp);
89e15f9bd0SJeremy L Thompson       // LCOV_EXCL_STOP
90e15f9bd0SJeremy L Thompson     }
91e15f9bd0SJeremy L Thompson   }
92e15f9bd0SJeremy L Thompson   // Field size
93d1d35e2fSjeremylt   switch(eval_mode) {
94e15f9bd0SJeremy L Thompson   case CEED_EVAL_NONE:
95d1d35e2fSjeremylt     if (size != restr_num_comp)
96e15f9bd0SJeremy L Thompson       // LCOV_EXCL_START
97e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_DIMENSION,
98e1e9e29dSJed Brown                        "Field '%s' of size %d and EvalMode %s: ElemRestriction has %d components",
99d1d35e2fSjeremylt                        qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode],
100d1d35e2fSjeremylt                        restr_num_comp);
101e15f9bd0SJeremy L Thompson     // LCOV_EXCL_STOP
102e15f9bd0SJeremy L Thompson     break;
103e15f9bd0SJeremy L Thompson   case CEED_EVAL_INTERP:
104d1d35e2fSjeremylt     if (size != num_comp)
105e15f9bd0SJeremy L Thompson       // LCOV_EXCL_START
106e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_DIMENSION,
107e1e9e29dSJed Brown                        "Field '%s' of size %d and EvalMode %s: ElemRestriction/Basis has %d components",
108d1d35e2fSjeremylt                        qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode],
109d1d35e2fSjeremylt                        num_comp);
110e15f9bd0SJeremy L Thompson     // LCOV_EXCL_STOP
111e15f9bd0SJeremy L Thompson     break;
112e15f9bd0SJeremy L Thompson   case CEED_EVAL_GRAD:
113d1d35e2fSjeremylt     if (size != num_comp * dim)
114e15f9bd0SJeremy L Thompson       // LCOV_EXCL_START
115e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_DIMENSION,
116d1d35e2fSjeremylt                        "Field '%s' of size %d and EvalMode %s in %d dimensions: "
117d1d35e2fSjeremylt                        "ElemRestriction/Basis has %d components",
118d1d35e2fSjeremylt                        qf_field->field_name, qf_field->size, CeedEvalModes[qf_field->eval_mode], dim,
119d1d35e2fSjeremylt                        num_comp);
120e15f9bd0SJeremy L Thompson     // LCOV_EXCL_STOP
121e15f9bd0SJeremy L Thompson     break;
122e15f9bd0SJeremy L Thompson   case CEED_EVAL_WEIGHT:
123d1d35e2fSjeremylt     // No additional checks required
124e15f9bd0SJeremy L Thompson     break;
125e15f9bd0SJeremy L Thompson   case CEED_EVAL_DIV:
126e15f9bd0SJeremy L Thompson     // Not implemented
127e15f9bd0SJeremy L Thompson     break;
128e15f9bd0SJeremy L Thompson   case CEED_EVAL_CURL:
129e15f9bd0SJeremy L Thompson     // Not implemented
130e15f9bd0SJeremy L Thompson     break;
131e15f9bd0SJeremy L Thompson   }
132e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1337a982d89SJeremy L. Thompson }
1347a982d89SJeremy L. Thompson 
1357a982d89SJeremy L. Thompson /**
1367a982d89SJeremy L. Thompson   @brief View a field of a CeedOperator
1377a982d89SJeremy L. Thompson 
1387a982d89SJeremy L. Thompson   @param[in] field         Operator field to view
139d1d35e2fSjeremylt   @param[in] qf_field      QFunction field (carries field name)
140d1d35e2fSjeremylt   @param[in] field_number  Number of field being viewed
1414c4400c7SValeria Barra   @param[in] sub           true indicates sub-operator, which increases indentation; false for top-level operator
142d1d35e2fSjeremylt   @param[in] input         true for an input field; false for output field
1437a982d89SJeremy L. Thompson   @param[in] stream        Stream to view to, e.g., stdout
1447a982d89SJeremy L. Thompson 
1457a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1467a982d89SJeremy L. Thompson 
1477a982d89SJeremy L. Thompson   @ref Utility
1487a982d89SJeremy L. Thompson **/
1497a982d89SJeremy L. Thompson static int CeedOperatorFieldView(CeedOperatorField field,
150d1d35e2fSjeremylt                                  CeedQFunctionField qf_field,
151d1d35e2fSjeremylt                                  CeedInt field_number, bool sub, bool input,
1527a982d89SJeremy L. Thompson                                  FILE *stream) {
1537a982d89SJeremy L. Thompson   const char *pre = sub ? "  " : "";
154d1d35e2fSjeremylt   const char *in_out = input ? "Input" : "Output";
1557a982d89SJeremy L. Thompson 
1567a982d89SJeremy L. Thompson   fprintf(stream, "%s    %s Field [%d]:\n"
1577a982d89SJeremy L. Thompson           "%s      Name: \"%s\"\n",
158d1d35e2fSjeremylt           pre, in_out, field_number, pre, qf_field->field_name);
1597a982d89SJeremy L. Thompson 
1607a982d89SJeremy L. Thompson   if (field->basis == CEED_BASIS_COLLOCATED)
1617a982d89SJeremy L. Thompson     fprintf(stream, "%s      Collocated basis\n", pre);
1627a982d89SJeremy L. Thompson 
1637a982d89SJeremy L. Thompson   if (field->vec == CEED_VECTOR_ACTIVE)
1647a982d89SJeremy L. Thompson     fprintf(stream, "%s      Active vector\n", pre);
1657a982d89SJeremy L. Thompson   else if (field->vec == CEED_VECTOR_NONE)
1667a982d89SJeremy L. Thompson     fprintf(stream, "%s      No vector\n", pre);
167e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1687a982d89SJeremy L. Thompson }
1697a982d89SJeremy L. Thompson 
1707a982d89SJeremy L. Thompson /**
1717a982d89SJeremy L. Thompson   @brief View a single CeedOperator
1727a982d89SJeremy L. Thompson 
1737a982d89SJeremy L. Thompson   @param[in] op      CeedOperator to view
1747a982d89SJeremy L. Thompson   @param[in] sub     Boolean flag for sub-operator
1757a982d89SJeremy L. Thompson   @param[in] stream  Stream to write; typically stdout/stderr or a file
1767a982d89SJeremy L. Thompson 
1777a982d89SJeremy L. Thompson   @return Error code: 0 - success, otherwise - failure
1787a982d89SJeremy L. Thompson 
1797a982d89SJeremy L. Thompson   @ref Utility
1807a982d89SJeremy L. Thompson **/
1817a982d89SJeremy L. Thompson int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) {
1827a982d89SJeremy L. Thompson   int ierr;
1837a982d89SJeremy L. Thompson   const char *pre = sub ? "  " : "";
1847a982d89SJeremy L. Thompson 
18578464608Sjeremylt   CeedInt total_fields = 0;
18678464608Sjeremylt   ierr = CeedOperatorGetNumArgs(op, &total_fields); CeedChk(ierr);
1877a982d89SJeremy L. Thompson 
18878464608Sjeremylt   fprintf(stream, "%s  %d Field%s\n", pre, total_fields,
18978464608Sjeremylt           total_fields>1 ? "s" : "");
1907a982d89SJeremy L. Thompson 
191d1d35e2fSjeremylt   fprintf(stream, "%s  %d Input Field%s:\n", pre, op->qf->num_input_fields,
192d1d35e2fSjeremylt           op->qf->num_input_fields>1 ? "s" : "");
193d1d35e2fSjeremylt   for (CeedInt i=0; i<op->qf->num_input_fields; i++) {
194d1d35e2fSjeremylt     ierr = CeedOperatorFieldView(op->input_fields[i], op->qf->input_fields[i],
1957a982d89SJeremy L. Thompson                                  i, sub, 1, stream); CeedChk(ierr);
1967a982d89SJeremy L. Thompson   }
1977a982d89SJeremy L. Thompson 
198d1d35e2fSjeremylt   fprintf(stream, "%s  %d Output Field%s:\n", pre, op->qf->num_output_fields,
199d1d35e2fSjeremylt           op->qf->num_output_fields>1 ? "s" : "");
200d1d35e2fSjeremylt   for (CeedInt i=0; i<op->qf->num_output_fields; i++) {
201d1d35e2fSjeremylt     ierr = CeedOperatorFieldView(op->output_fields[i], op->qf->output_fields[i],
2027a982d89SJeremy L. Thompson                                  i, sub, 0, stream); CeedChk(ierr);
2037a982d89SJeremy L. Thompson   }
204e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2057a982d89SJeremy L. Thompson }
2067a982d89SJeremy L. Thompson 
207d99fa3c5SJeremy L Thompson /**
208eaf62fffSJeremy L Thompson   @brief Find the active vector basis for a CeedOperator
209eaf62fffSJeremy L Thompson 
210eaf62fffSJeremy L Thompson   @param[in] op             CeedOperator to find active basis for
211eaf62fffSJeremy L Thompson   @param[out] active_basis  Basis for active input vector
212eaf62fffSJeremy L Thompson 
213eaf62fffSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
214eaf62fffSJeremy L Thompson 
215eaf62fffSJeremy L Thompson   @ ref Developer
216eaf62fffSJeremy L Thompson **/
217eaf62fffSJeremy L Thompson int CeedOperatorGetActiveBasis(CeedOperator op, CeedBasis *active_basis) {
218eaf62fffSJeremy L Thompson   *active_basis = NULL;
219eaf62fffSJeremy L Thompson   for (int i = 0; i < op->qf->num_input_fields; i++)
220eaf62fffSJeremy L Thompson     if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) {
221eaf62fffSJeremy L Thompson       *active_basis = op->input_fields[i]->basis;
222eaf62fffSJeremy L Thompson       break;
223eaf62fffSJeremy L Thompson     }
224eaf62fffSJeremy L Thompson 
225eaf62fffSJeremy L Thompson   if (!*active_basis) {
226eaf62fffSJeremy L Thompson     // LCOV_EXCL_START
227eaf62fffSJeremy L Thompson     int ierr;
228eaf62fffSJeremy L Thompson     Ceed ceed;
229eaf62fffSJeremy L Thompson     ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr);
230eaf62fffSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_MINOR,
231eaf62fffSJeremy L Thompson                      "No active CeedBasis found");
232eaf62fffSJeremy L Thompson     // LCOV_EXCL_STOP
233eaf62fffSJeremy L Thompson   }
234eaf62fffSJeremy L Thompson   return CEED_ERROR_SUCCESS;
235eaf62fffSJeremy L Thompson }
236eaf62fffSJeremy L Thompson 
237eaf62fffSJeremy L Thompson /**
238e2f04181SAndrew T. Barker   @brief Find the active vector ElemRestriction for a CeedOperator
239e2f04181SAndrew T. Barker 
240e2f04181SAndrew T. Barker   @param[in] op            CeedOperator to find active basis for
241d1d35e2fSjeremylt   @param[out] active_rstr  ElemRestriction for active input vector
242e2f04181SAndrew T. Barker 
243e2f04181SAndrew T. Barker   @return An error code: 0 - success, otherwise - failure
244e2f04181SAndrew T. Barker 
245e2f04181SAndrew T. Barker   @ref Utility
246e2f04181SAndrew T. Barker **/
247eaf62fffSJeremy L Thompson int CeedOperatorGetActiveElemRestriction(CeedOperator op,
248d1d35e2fSjeremylt     CeedElemRestriction *active_rstr) {
249d1d35e2fSjeremylt   *active_rstr = NULL;
250d1d35e2fSjeremylt   for (int i = 0; i < op->qf->num_input_fields; i++)
251d1d35e2fSjeremylt     if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) {
252d1d35e2fSjeremylt       *active_rstr = op->input_fields[i]->elem_restr;
253e2f04181SAndrew T. Barker       break;
254e2f04181SAndrew T. Barker     }
255e2f04181SAndrew T. Barker 
256d1d35e2fSjeremylt   if (!*active_rstr) {
257e2f04181SAndrew T. Barker     // LCOV_EXCL_START
258e2f04181SAndrew T. Barker     int ierr;
259e2f04181SAndrew T. Barker     Ceed ceed;
260e2f04181SAndrew T. Barker     ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr);
261e2f04181SAndrew T. Barker     return CeedError(ceed, CEED_ERROR_INCOMPLETE,
262eaf62fffSJeremy L Thompson                      "No active CeedElemRestriction found");
263e2f04181SAndrew T. Barker     // LCOV_EXCL_STOP
264e2f04181SAndrew T. Barker   }
265e2f04181SAndrew T. Barker   return CEED_ERROR_SUCCESS;
266e2f04181SAndrew T. Barker }
267e2f04181SAndrew T. Barker 
2687a982d89SJeremy L. Thompson /// @}
2697a982d89SJeremy L. Thompson 
2707a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
2717a982d89SJeremy L. Thompson /// CeedOperator Backend API
2727a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
2737a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorBackend
2747a982d89SJeremy L. Thompson /// @{
2757a982d89SJeremy L. Thompson 
2767a982d89SJeremy L. Thompson /**
2777a982d89SJeremy L. Thompson   @brief Get the number of arguments associated with a CeedOperator
2787a982d89SJeremy L. Thompson 
2797a982d89SJeremy L. Thompson   @param op             CeedOperator
280d1d35e2fSjeremylt   @param[out] num_args  Variable to store vector number of arguments
2817a982d89SJeremy L. Thompson 
2827a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2837a982d89SJeremy L. Thompson 
2847a982d89SJeremy L. Thompson   @ref Backend
2857a982d89SJeremy L. Thompson **/
2867a982d89SJeremy L. Thompson 
287d1d35e2fSjeremylt int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *num_args) {
288f04ea552SJeremy L Thompson   if (op->is_composite)
2897a982d89SJeremy L. Thompson     // LCOV_EXCL_START
290e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
291e15f9bd0SJeremy L Thompson                      "Not defined for composite operators");
2927a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
2937a982d89SJeremy L. Thompson 
294d1d35e2fSjeremylt   *num_args = op->num_fields;
295e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2967a982d89SJeremy L. Thompson }
2977a982d89SJeremy L. Thompson 
2987a982d89SJeremy L. Thompson /**
2997a982d89SJeremy L. Thompson   @brief Get the setup status of a CeedOperator
3007a982d89SJeremy L. Thompson 
3017a982d89SJeremy L. Thompson   @param op                  CeedOperator
302d1d35e2fSjeremylt   @param[out] is_setup_done  Variable to store setup status
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 
309d1d35e2fSjeremylt int CeedOperatorIsSetupDone(CeedOperator op, bool *is_setup_done) {
310f04ea552SJeremy L Thompson   *is_setup_done = op->is_backend_setup;
311e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3127a982d89SJeremy L. Thompson }
3137a982d89SJeremy L. Thompson 
3147a982d89SJeremy L. Thompson /**
3157a982d89SJeremy L. Thompson   @brief Get the QFunction associated with a CeedOperator
3167a982d89SJeremy L. Thompson 
3177a982d89SJeremy L. Thompson   @param op       CeedOperator
3187a982d89SJeremy L. Thompson   @param[out] qf  Variable to store QFunction
3197a982d89SJeremy L. Thompson 
3207a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3217a982d89SJeremy L. Thompson 
3227a982d89SJeremy L. Thompson   @ref Backend
3237a982d89SJeremy L. Thompson **/
3247a982d89SJeremy L. Thompson 
3257a982d89SJeremy L. Thompson int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) {
326f04ea552SJeremy L Thompson   if (op->is_composite)
3277a982d89SJeremy L. Thompson     // LCOV_EXCL_START
328e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
329e15f9bd0SJeremy L Thompson                      "Not defined for composite operator");
3307a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
3317a982d89SJeremy L. Thompson 
3327a982d89SJeremy L. Thompson   *qf = op->qf;
333e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3347a982d89SJeremy L. Thompson }
3357a982d89SJeremy L. Thompson 
3367a982d89SJeremy L. Thompson /**
337c04a41a7SJeremy L Thompson   @brief Get a boolean value indicating if the CeedOperator is composite
338c04a41a7SJeremy L Thompson 
339c04a41a7SJeremy L Thompson   @param op                 CeedOperator
340d1d35e2fSjeremylt   @param[out] is_composite  Variable to store composite status
341c04a41a7SJeremy L Thompson 
342c04a41a7SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
343c04a41a7SJeremy L Thompson 
344c04a41a7SJeremy L Thompson   @ref Backend
345c04a41a7SJeremy L Thompson **/
346c04a41a7SJeremy L Thompson 
347d1d35e2fSjeremylt int CeedOperatorIsComposite(CeedOperator op, bool *is_composite) {
348f04ea552SJeremy L Thompson   *is_composite = op->is_composite;
349e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
350c04a41a7SJeremy L Thompson }
351c04a41a7SJeremy L Thompson 
352c04a41a7SJeremy L Thompson /**
353d1d35e2fSjeremylt   @brief Get the number of sub_operators associated with a CeedOperator
3547a982d89SJeremy L. Thompson 
3557a982d89SJeremy L. Thompson   @param op                     CeedOperator
356d1d35e2fSjeremylt   @param[out] num_suboperators  Variable to store number of sub_operators
3577a982d89SJeremy L. Thompson 
3587a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3597a982d89SJeremy L. Thompson 
3607a982d89SJeremy L. Thompson   @ref Backend
3617a982d89SJeremy L. Thompson **/
3627a982d89SJeremy L. Thompson 
363d1d35e2fSjeremylt int CeedOperatorGetNumSub(CeedOperator op, CeedInt *num_suboperators) {
364f04ea552SJeremy L Thompson   if (!op->is_composite)
3657a982d89SJeremy L. Thompson     // LCOV_EXCL_START
366e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator");
3677a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
3687a982d89SJeremy L. Thompson 
369d1d35e2fSjeremylt   *num_suboperators = op->num_suboperators;
370e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3717a982d89SJeremy L. Thompson }
3727a982d89SJeremy L. Thompson 
3737a982d89SJeremy L. Thompson /**
374d1d35e2fSjeremylt   @brief Get the list of sub_operators associated with a CeedOperator
3757a982d89SJeremy L. Thompson 
3767a982d89SJeremy L. Thompson   @param op                  CeedOperator
377d1d35e2fSjeremylt   @param[out] sub_operators  Variable to store list of sub_operators
3787a982d89SJeremy L. Thompson 
3797a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3807a982d89SJeremy L. Thompson 
3817a982d89SJeremy L. Thompson   @ref Backend
3827a982d89SJeremy L. Thompson **/
3837a982d89SJeremy L. Thompson 
384d1d35e2fSjeremylt int CeedOperatorGetSubList(CeedOperator op, CeedOperator **sub_operators) {
385f04ea552SJeremy L Thompson   if (!op->is_composite)
3867a982d89SJeremy L. Thompson     // LCOV_EXCL_START
387e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator");
3887a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
3897a982d89SJeremy L. Thompson 
390d1d35e2fSjeremylt   *sub_operators = op->sub_operators;
391e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3927a982d89SJeremy L. Thompson }
3937a982d89SJeremy L. Thompson 
3947a982d89SJeremy L. Thompson /**
3957a982d89SJeremy L. Thompson   @brief Get the backend data of a CeedOperator
3967a982d89SJeremy L. Thompson 
3977a982d89SJeremy L. Thompson   @param op         CeedOperator
3987a982d89SJeremy L. Thompson   @param[out] data  Variable to store data
3997a982d89SJeremy L. Thompson 
4007a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4017a982d89SJeremy L. Thompson 
4027a982d89SJeremy L. Thompson   @ref Backend
4037a982d89SJeremy L. Thompson **/
4047a982d89SJeremy L. Thompson 
405777ff853SJeremy L Thompson int CeedOperatorGetData(CeedOperator op, void *data) {
406777ff853SJeremy L Thompson   *(void **)data = op->data;
407e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4087a982d89SJeremy L. Thompson }
4097a982d89SJeremy L. Thompson 
4107a982d89SJeremy L. Thompson /**
4117a982d89SJeremy L. Thompson   @brief Set the backend data of a CeedOperator
4127a982d89SJeremy L. Thompson 
4137a982d89SJeremy L. Thompson   @param[out] op  CeedOperator
4147a982d89SJeremy L. Thompson   @param data     Data to set
4157a982d89SJeremy L. Thompson 
4167a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4177a982d89SJeremy L. Thompson 
4187a982d89SJeremy L. Thompson   @ref Backend
4197a982d89SJeremy L. Thompson **/
4207a982d89SJeremy L. Thompson 
421777ff853SJeremy L Thompson int CeedOperatorSetData(CeedOperator op, void *data) {
422777ff853SJeremy L Thompson   op->data = data;
423e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4247a982d89SJeremy L. Thompson }
4257a982d89SJeremy L. Thompson 
4267a982d89SJeremy L. Thompson /**
42734359f16Sjeremylt   @brief Increment the reference counter for a CeedOperator
42834359f16Sjeremylt 
42934359f16Sjeremylt   @param op  CeedOperator to increment the reference counter
43034359f16Sjeremylt 
43134359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
43234359f16Sjeremylt 
43334359f16Sjeremylt   @ref Backend
43434359f16Sjeremylt **/
4359560d06aSjeremylt int CeedOperatorReference(CeedOperator op) {
43634359f16Sjeremylt   op->ref_count++;
43734359f16Sjeremylt   return CEED_ERROR_SUCCESS;
43834359f16Sjeremylt }
43934359f16Sjeremylt 
44034359f16Sjeremylt /**
4417a982d89SJeremy L. Thompson   @brief Set the setup flag of a CeedOperator to True
4427a982d89SJeremy L. Thompson 
4437a982d89SJeremy L. Thompson   @param op  CeedOperator
4447a982d89SJeremy L. Thompson 
4457a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4467a982d89SJeremy L. Thompson 
4477a982d89SJeremy L. Thompson   @ref Backend
4487a982d89SJeremy L. Thompson **/
4497a982d89SJeremy L. Thompson 
4507a982d89SJeremy L. Thompson int CeedOperatorSetSetupDone(CeedOperator op) {
451f04ea552SJeremy L Thompson   op->is_backend_setup = true;
452e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4537a982d89SJeremy L. Thompson }
4547a982d89SJeremy L. Thompson 
4557a982d89SJeremy L. Thompson /// @}
4567a982d89SJeremy L. Thompson 
4577a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
4587a982d89SJeremy L. Thompson /// CeedOperator Public API
4597a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
4607a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorUser
461dfdf5a53Sjeremylt /// @{
462d7b241e6Sjeremylt 
463d7b241e6Sjeremylt /**
4640219ea01SJeremy L Thompson   @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and
4650219ea01SJeremy L Thompson            CeedElemRestriction can be associated with CeedQFunction fields with
4660219ea01SJeremy L Thompson            \ref CeedOperatorSetField.
467d7b241e6Sjeremylt 
468b11c1e72Sjeremylt   @param ceed     A Ceed object where the CeedOperator will be created
469d7b241e6Sjeremylt   @param qf       QFunction defining the action of the operator at quadrature points
47034138859Sjeremylt   @param dqf      QFunction defining the action of the Jacobian of @a qf (or
4714cc79fe7SJed Brown                     @ref CEED_QFUNCTION_NONE)
472d7b241e6Sjeremylt   @param dqfT     QFunction defining the action of the transpose of the Jacobian
4734cc79fe7SJed Brown                     of @a qf (or @ref CEED_QFUNCTION_NONE)
474b11c1e72Sjeremylt   @param[out] op  Address of the variable where the newly created
475b11c1e72Sjeremylt                     CeedOperator will be stored
476b11c1e72Sjeremylt 
477b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
478dfdf5a53Sjeremylt 
4797a982d89SJeremy L. Thompson   @ref User
480d7b241e6Sjeremylt  */
481d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf,
482d7b241e6Sjeremylt                        CeedQFunction dqfT, CeedOperator *op) {
483d7b241e6Sjeremylt   int ierr;
484d7b241e6Sjeremylt 
4855fe0d4faSjeremylt   if (!ceed->OperatorCreate) {
4865fe0d4faSjeremylt     Ceed delegate;
487aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr);
4885fe0d4faSjeremylt 
4895fe0d4faSjeremylt     if (!delegate)
490c042f62fSJeremy L Thompson       // LCOV_EXCL_START
491e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED,
492e15f9bd0SJeremy L Thompson                        "Backend does not support OperatorCreate");
493c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
4945fe0d4faSjeremylt 
4955fe0d4faSjeremylt     ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr);
496e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
4975fe0d4faSjeremylt   }
4985fe0d4faSjeremylt 
499b3b7035fSJeremy L Thompson   if (!qf || qf == CEED_QFUNCTION_NONE)
500b3b7035fSJeremy L Thompson     // LCOV_EXCL_START
501e15f9bd0SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_MINOR,
502e15f9bd0SJeremy L Thompson                      "Operator must have a valid QFunction.");
503b3b7035fSJeremy L Thompson   // LCOV_EXCL_STOP
504d7b241e6Sjeremylt   ierr = CeedCalloc(1, op); CeedChk(ierr);
505d7b241e6Sjeremylt   (*op)->ceed = ceed;
5069560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
507d1d35e2fSjeremylt   (*op)->ref_count = 1;
508d7b241e6Sjeremylt   (*op)->qf = qf;
5099560d06aSjeremylt   ierr = CeedQFunctionReference(qf); CeedChk(ierr);
510442e7f0bSjeremylt   if (dqf && dqf != CEED_QFUNCTION_NONE) {
511d7b241e6Sjeremylt     (*op)->dqf = dqf;
5129560d06aSjeremylt     ierr = CeedQFunctionReference(dqf); CeedChk(ierr);
513442e7f0bSjeremylt   }
514442e7f0bSjeremylt   if (dqfT && dqfT != CEED_QFUNCTION_NONE) {
515d7b241e6Sjeremylt     (*op)->dqfT = dqfT;
5169560d06aSjeremylt     ierr = CeedQFunctionReference(dqfT); CeedChk(ierr);
517442e7f0bSjeremylt   }
518d1d35e2fSjeremylt   ierr = CeedCalloc(16, &(*op)->input_fields); CeedChk(ierr);
519d1d35e2fSjeremylt   ierr = CeedCalloc(16, &(*op)->output_fields); CeedChk(ierr);
520d7b241e6Sjeremylt   ierr = ceed->OperatorCreate(*op); CeedChk(ierr);
521e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
522d7b241e6Sjeremylt }
523d7b241e6Sjeremylt 
524d7b241e6Sjeremylt /**
52552d6035fSJeremy L Thompson   @brief Create an operator that composes the action of several operators
52652d6035fSJeremy L Thompson 
52752d6035fSJeremy L Thompson   @param ceed     A Ceed object where the CeedOperator will be created
52852d6035fSJeremy L Thompson   @param[out] op  Address of the variable where the newly created
52952d6035fSJeremy L Thompson                     Composite CeedOperator will be stored
53052d6035fSJeremy L Thompson 
53152d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
53252d6035fSJeremy L Thompson 
5337a982d89SJeremy L. Thompson   @ref User
53452d6035fSJeremy L Thompson  */
53552d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) {
53652d6035fSJeremy L Thompson   int ierr;
53752d6035fSJeremy L Thompson 
53852d6035fSJeremy L Thompson   if (!ceed->CompositeOperatorCreate) {
53952d6035fSJeremy L Thompson     Ceed delegate;
540aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr);
54152d6035fSJeremy L Thompson 
542250756a7Sjeremylt     if (delegate) {
54352d6035fSJeremy L Thompson       ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr);
544e15f9bd0SJeremy L Thompson       return CEED_ERROR_SUCCESS;
54552d6035fSJeremy L Thompson     }
546250756a7Sjeremylt   }
54752d6035fSJeremy L Thompson 
54852d6035fSJeremy L Thompson   ierr = CeedCalloc(1, op); CeedChk(ierr);
54952d6035fSJeremy L Thompson   (*op)->ceed = ceed;
5509560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
551f04ea552SJeremy L Thompson   (*op)->is_composite = true;
552d1d35e2fSjeremylt   ierr = CeedCalloc(16, &(*op)->sub_operators); CeedChk(ierr);
553250756a7Sjeremylt 
554250756a7Sjeremylt   if (ceed->CompositeOperatorCreate) {
55552d6035fSJeremy L Thompson     ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr);
556250756a7Sjeremylt   }
557e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
55852d6035fSJeremy L Thompson }
55952d6035fSJeremy L Thompson 
56052d6035fSJeremy L Thompson /**
5619560d06aSjeremylt   @brief Copy the pointer to a CeedOperator. Both pointers should
5629560d06aSjeremylt            be destroyed with `CeedOperatorDestroy()`;
5639560d06aSjeremylt            Note: If `*op_copy` is non-NULL, then it is assumed that
5649560d06aSjeremylt            `*op_copy` is a pointer to a CeedOperator. This
5659560d06aSjeremylt            CeedOperator will be destroyed if `*op_copy` is the only
5669560d06aSjeremylt            reference to this CeedOperator.
5679560d06aSjeremylt 
5689560d06aSjeremylt   @param op            CeedOperator to copy reference to
5699560d06aSjeremylt   @param[out] op_copy  Variable to store copied reference
5709560d06aSjeremylt 
5719560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
5729560d06aSjeremylt 
5739560d06aSjeremylt   @ref User
5749560d06aSjeremylt **/
5759560d06aSjeremylt int CeedOperatorReferenceCopy(CeedOperator op, CeedOperator *op_copy) {
5769560d06aSjeremylt   int ierr;
5779560d06aSjeremylt 
5789560d06aSjeremylt   ierr = CeedOperatorReference(op); CeedChk(ierr);
5799560d06aSjeremylt   ierr = CeedOperatorDestroy(op_copy); CeedChk(ierr);
5809560d06aSjeremylt   *op_copy = op;
5819560d06aSjeremylt   return CEED_ERROR_SUCCESS;
5829560d06aSjeremylt }
5839560d06aSjeremylt 
5849560d06aSjeremylt /**
585b11c1e72Sjeremylt   @brief Provide a field to a CeedOperator for use by its CeedQFunction
586d7b241e6Sjeremylt 
587d7b241e6Sjeremylt   This function is used to specify both active and passive fields to a
588d7b241e6Sjeremylt   CeedOperator.  For passive fields, a vector @arg v must be provided.  Passive
589d7b241e6Sjeremylt   fields can inputs or outputs (updated in-place when operator is applied).
590d7b241e6Sjeremylt 
591d7b241e6Sjeremylt   Active fields must be specified using this function, but their data (in a
592d7b241e6Sjeremylt   CeedVector) is passed in CeedOperatorApply().  There can be at most one active
593d7b241e6Sjeremylt   input and at most one active output.
594d7b241e6Sjeremylt 
5958c91a0c9SJeremy L Thompson   @param op          CeedOperator on which to provide the field
596d1d35e2fSjeremylt   @param field_name  Name of the field (to be matched with the name used by
5978795c945Sjeremylt                        CeedQFunction)
598b11c1e72Sjeremylt   @param r           CeedElemRestriction
5994cc79fe7SJed Brown   @param b           CeedBasis in which the field resides or @ref CEED_BASIS_COLLOCATED
600b11c1e72Sjeremylt                        if collocated with quadrature points
6014cc79fe7SJed Brown   @param v           CeedVector to be used by CeedOperator or @ref CEED_VECTOR_ACTIVE
6024cc79fe7SJed Brown                        if field is active or @ref CEED_VECTOR_NONE if using
6034cc79fe7SJed Brown                        @ref CEED_EVAL_WEIGHT in the QFunction
604b11c1e72Sjeremylt 
605b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
606dfdf5a53Sjeremylt 
6077a982d89SJeremy L. Thompson   @ref User
608b11c1e72Sjeremylt **/
609d1d35e2fSjeremylt int CeedOperatorSetField(CeedOperator op, const char *field_name,
610a8d32208Sjeremylt                          CeedElemRestriction r, CeedBasis b, CeedVector v) {
611d7b241e6Sjeremylt   int ierr;
612f04ea552SJeremy L Thompson   if (op->is_composite)
613c042f62fSJeremy L Thompson     // LCOV_EXCL_START
614e1e9e29dSJed Brown     return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
615e15f9bd0SJeremy L Thompson                      "Cannot add field to composite operator.");
616c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
617f04ea552SJeremy L Thompson   if (op->is_immutable)
618f04ea552SJeremy L Thompson     // LCOV_EXCL_START
619f04ea552SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MAJOR,
620f04ea552SJeremy L Thompson                      "Operator cannot be changed after set as immutable");
621f04ea552SJeremy L Thompson   // LCOV_EXCL_STOP
6228b067b84SJed Brown   if (!r)
623c042f62fSJeremy L Thompson     // LCOV_EXCL_START
624e1e9e29dSJed Brown     return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
625c042f62fSJeremy L Thompson                      "ElemRestriction r for field \"%s\" must be non-NULL.",
626d1d35e2fSjeremylt                      field_name);
627c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
6288b067b84SJed Brown   if (!b)
629c042f62fSJeremy L Thompson     // LCOV_EXCL_START
630e1e9e29dSJed Brown     return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
631e15f9bd0SJeremy L Thompson                      "Basis b for field \"%s\" must be non-NULL.",
632d1d35e2fSjeremylt                      field_name);
633c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
6348b067b84SJed Brown   if (!v)
635c042f62fSJeremy L Thompson     // LCOV_EXCL_START
636e1e9e29dSJed Brown     return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
637e15f9bd0SJeremy L Thompson                      "Vector v for field \"%s\" must be non-NULL.",
638d1d35e2fSjeremylt                      field_name);
639c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
64052d6035fSJeremy L Thompson 
641d1d35e2fSjeremylt   CeedInt num_elem;
642d1d35e2fSjeremylt   ierr = CeedElemRestrictionGetNumElements(r, &num_elem); CeedChk(ierr);
643d1d35e2fSjeremylt   if (r != CEED_ELEMRESTRICTION_NONE && op->has_restriction &&
644d1d35e2fSjeremylt       op->num_elem != num_elem)
645c042f62fSJeremy L Thompson     // LCOV_EXCL_START
646e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_DIMENSION,
6471d102b48SJeremy L Thompson                      "ElemRestriction with %d elements incompatible with prior "
648d1d35e2fSjeremylt                      "%d elements", num_elem, op->num_elem);
649c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
650d7b241e6Sjeremylt 
65178464608Sjeremylt   CeedInt num_qpts = 0;
652e15f9bd0SJeremy L Thompson   if (b != CEED_BASIS_COLLOCATED) {
653d1d35e2fSjeremylt     ierr = CeedBasisGetNumQuadraturePoints(b, &num_qpts); CeedChk(ierr);
654d1d35e2fSjeremylt     if (op->num_qpts && op->num_qpts != num_qpts)
655c042f62fSJeremy L Thompson       // LCOV_EXCL_START
656e15f9bd0SJeremy L Thompson       return CeedError(op->ceed, CEED_ERROR_DIMENSION,
657e15f9bd0SJeremy L Thompson                        "Basis with %d quadrature points "
658d1d35e2fSjeremylt                        "incompatible with prior %d points", num_qpts,
659d1d35e2fSjeremylt                        op->num_qpts);
660c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
661d7b241e6Sjeremylt   }
662d1d35e2fSjeremylt   CeedQFunctionField qf_field;
663d1d35e2fSjeremylt   CeedOperatorField *op_field;
664d1d35e2fSjeremylt   for (CeedInt i=0; i<op->qf->num_input_fields; i++) {
665d1d35e2fSjeremylt     if (!strcmp(field_name, (*op->qf->input_fields[i]).field_name)) {
666d1d35e2fSjeremylt       qf_field = op->qf->input_fields[i];
667d1d35e2fSjeremylt       op_field = &op->input_fields[i];
668d7b241e6Sjeremylt       goto found;
669d7b241e6Sjeremylt     }
670d7b241e6Sjeremylt   }
671d1d35e2fSjeremylt   for (CeedInt i=0; i<op->qf->num_output_fields; i++) {
672d1d35e2fSjeremylt     if (!strcmp(field_name, (*op->qf->output_fields[i]).field_name)) {
673d1d35e2fSjeremylt       qf_field = op->qf->output_fields[i];
674d1d35e2fSjeremylt       op_field = &op->output_fields[i];
675d7b241e6Sjeremylt       goto found;
676d7b241e6Sjeremylt     }
677d7b241e6Sjeremylt   }
678c042f62fSJeremy L Thompson   // LCOV_EXCL_START
679e15f9bd0SJeremy L Thompson   return CeedError(op->ceed, CEED_ERROR_INCOMPLETE,
680e15f9bd0SJeremy L Thompson                    "QFunction has no knowledge of field '%s'",
681d1d35e2fSjeremylt                    field_name);
682c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
683d7b241e6Sjeremylt found:
684d1d35e2fSjeremylt   ierr = CeedOperatorCheckField(op->ceed, qf_field, r, b); CeedChk(ierr);
685d1d35e2fSjeremylt   ierr = CeedCalloc(1, op_field); CeedChk(ierr);
686e15f9bd0SJeremy L Thompson 
687d1d35e2fSjeremylt   (*op_field)->vec = v;
688e15f9bd0SJeremy L Thompson   if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) {
6899560d06aSjeremylt     ierr = CeedVectorReference(v); CeedChk(ierr);
690e15f9bd0SJeremy L Thompson   }
691e15f9bd0SJeremy L Thompson 
692d1d35e2fSjeremylt   (*op_field)->elem_restr = r;
6939560d06aSjeremylt   ierr = CeedElemRestrictionReference(r); CeedChk(ierr);
694e15f9bd0SJeremy L Thompson   if (r != CEED_ELEMRESTRICTION_NONE) {
695d1d35e2fSjeremylt     op->num_elem = num_elem;
696d1d35e2fSjeremylt     op->has_restriction = true; // Restriction set, but num_elem may be 0
697e15f9bd0SJeremy L Thompson   }
698d99fa3c5SJeremy L Thompson 
699d1d35e2fSjeremylt   (*op_field)->basis = b;
700e15f9bd0SJeremy L Thompson   if (b != CEED_BASIS_COLLOCATED) {
701cd4dfc48Sjeremylt     if (!op->num_qpts) {
702cd4dfc48Sjeremylt       ierr = CeedOperatorSetNumQuadraturePoints(op, num_qpts); CeedChk(ierr);
703cd4dfc48Sjeremylt     }
7049560d06aSjeremylt     ierr = CeedBasisReference(b); CeedChk(ierr);
705e15f9bd0SJeremy L Thompson   }
706e15f9bd0SJeremy L Thompson 
707d1d35e2fSjeremylt   op->num_fields += 1;
708d1d35e2fSjeremylt   size_t len = strlen(field_name);
709d99fa3c5SJeremy L Thompson   char *tmp;
710d99fa3c5SJeremy L Thompson   ierr = CeedCalloc(len+1, &tmp); CeedChk(ierr);
711d1d35e2fSjeremylt   memcpy(tmp, field_name, len+1);
712d1d35e2fSjeremylt   (*op_field)->field_name = tmp;
713e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
714d7b241e6Sjeremylt }
715d7b241e6Sjeremylt 
716d7b241e6Sjeremylt /**
71743bbe138SJeremy L Thompson   @brief Get the CeedOperatorFields of a CeedOperator
71843bbe138SJeremy L Thompson 
719f04ea552SJeremy L Thompson   Note: Calling this function asserts that setup is complete
720f04ea552SJeremy L Thompson           and sets the CeedOperator as immutable.
721f04ea552SJeremy L Thompson 
72243bbe138SJeremy L Thompson   @param op                  CeedOperator
72343bbe138SJeremy L Thompson   @param[out] input_fields   Variable to store input_fields
72443bbe138SJeremy L Thompson   @param[out] output_fields  Variable to store output_fields
72543bbe138SJeremy L Thompson 
72643bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
72743bbe138SJeremy L Thompson 
728e9b533fbSJeremy L Thompson   @ref Advanced
72943bbe138SJeremy L Thompson **/
73043bbe138SJeremy L Thompson int CeedOperatorGetFields(CeedOperator op, CeedInt *num_input_fields,
73143bbe138SJeremy L Thompson                           CeedOperatorField **input_fields,
73243bbe138SJeremy L Thompson                           CeedInt *num_output_fields,
73343bbe138SJeremy L Thompson                           CeedOperatorField **output_fields) {
734f04ea552SJeremy L Thompson   int ierr;
735f04ea552SJeremy L Thompson 
736f04ea552SJeremy L Thompson   if (op->is_composite)
73743bbe138SJeremy L Thompson     // LCOV_EXCL_START
73843bbe138SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
73943bbe138SJeremy L Thompson                      "Not defined for composite operator");
74043bbe138SJeremy L Thompson   // LCOV_EXCL_STOP
741f04ea552SJeremy L Thompson   ierr = CeedOperatorCheckReady(op); CeedChk(ierr);
74243bbe138SJeremy L Thompson 
74343bbe138SJeremy L Thompson   if (num_input_fields) *num_input_fields = op->qf->num_input_fields;
74443bbe138SJeremy L Thompson   if (input_fields) *input_fields = op->input_fields;
74543bbe138SJeremy L Thompson   if (num_output_fields) *num_output_fields = op->qf->num_output_fields;
74643bbe138SJeremy L Thompson   if (output_fields) *output_fields = op->output_fields;
74743bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
74843bbe138SJeremy L Thompson }
74943bbe138SJeremy L Thompson 
75043bbe138SJeremy L Thompson /**
75128567f8fSJeremy L Thompson   @brief Get the name of a CeedOperatorField
75228567f8fSJeremy L Thompson 
75328567f8fSJeremy L Thompson   @param op_field         CeedOperatorField
75428567f8fSJeremy L Thompson   @param[out] field_name  Variable to store the field name
75528567f8fSJeremy L Thompson 
75628567f8fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
75728567f8fSJeremy L Thompson 
758e9b533fbSJeremy L Thompson   @ref Advanced
75928567f8fSJeremy L Thompson **/
76028567f8fSJeremy L Thompson int CeedOperatorFieldGetName(CeedOperatorField op_field, char **field_name) {
76128567f8fSJeremy L Thompson   *field_name = (char *)op_field->field_name;
76228567f8fSJeremy L Thompson   return CEED_ERROR_SUCCESS;
76328567f8fSJeremy L Thompson }
76428567f8fSJeremy L Thompson 
76528567f8fSJeremy L Thompson /**
76643bbe138SJeremy L Thompson   @brief Get the CeedElemRestriction of a CeedOperatorField
76743bbe138SJeremy L Thompson 
76843bbe138SJeremy L Thompson   @param op_field   CeedOperatorField
76943bbe138SJeremy L Thompson   @param[out] rstr  Variable to store CeedElemRestriction
77043bbe138SJeremy L Thompson 
77143bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
77243bbe138SJeremy L Thompson 
773e9b533fbSJeremy L Thompson   @ref Advanced
77443bbe138SJeremy L Thompson **/
77543bbe138SJeremy L Thompson int CeedOperatorFieldGetElemRestriction(CeedOperatorField op_field,
77643bbe138SJeremy L Thompson                                         CeedElemRestriction *rstr) {
77743bbe138SJeremy L Thompson   *rstr = op_field->elem_restr;
77843bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
77943bbe138SJeremy L Thompson }
78043bbe138SJeremy L Thompson 
78143bbe138SJeremy L Thompson /**
78243bbe138SJeremy L Thompson   @brief Get the CeedBasis of a CeedOperatorField
78343bbe138SJeremy L Thompson 
78443bbe138SJeremy L Thompson   @param op_field    CeedOperatorField
78543bbe138SJeremy L Thompson   @param[out] basis  Variable to store CeedBasis
78643bbe138SJeremy L Thompson 
78743bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
78843bbe138SJeremy L Thompson 
789e9b533fbSJeremy L Thompson   @ref Advanced
79043bbe138SJeremy L Thompson **/
79143bbe138SJeremy L Thompson int CeedOperatorFieldGetBasis(CeedOperatorField op_field, CeedBasis *basis) {
79243bbe138SJeremy L Thompson   *basis = op_field->basis;
79343bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
79443bbe138SJeremy L Thompson }
79543bbe138SJeremy L Thompson 
79643bbe138SJeremy L Thompson /**
79743bbe138SJeremy L Thompson   @brief Get the CeedVector of a CeedOperatorField
79843bbe138SJeremy L Thompson 
79943bbe138SJeremy L Thompson   @param op_field  CeedOperatorField
80043bbe138SJeremy L Thompson   @param[out] vec  Variable to store CeedVector
80143bbe138SJeremy L Thompson 
80243bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
80343bbe138SJeremy L Thompson 
804e9b533fbSJeremy L Thompson   @ref Advanced
80543bbe138SJeremy L Thompson **/
80643bbe138SJeremy L Thompson int CeedOperatorFieldGetVector(CeedOperatorField op_field, CeedVector *vec) {
80743bbe138SJeremy L Thompson   *vec = op_field->vec;
80843bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
80943bbe138SJeremy L Thompson }
81043bbe138SJeremy L Thompson 
81143bbe138SJeremy L Thompson /**
81252d6035fSJeremy L Thompson   @brief Add a sub-operator to a composite CeedOperator
813288c0443SJeremy L Thompson 
814d1d35e2fSjeremylt   @param[out] composite_op  Composite CeedOperator
815d1d35e2fSjeremylt   @param      sub_op        Sub-operator CeedOperator
81652d6035fSJeremy L Thompson 
81752d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
81852d6035fSJeremy L Thompson 
8197a982d89SJeremy L. Thompson   @ref User
82052d6035fSJeremy L Thompson  */
821d1d35e2fSjeremylt int CeedCompositeOperatorAddSub(CeedOperator composite_op,
822d1d35e2fSjeremylt                                 CeedOperator sub_op) {
82334359f16Sjeremylt   int ierr;
82434359f16Sjeremylt 
825f04ea552SJeremy L Thompson   if (!composite_op->is_composite)
826c042f62fSJeremy L Thompson     // LCOV_EXCL_START
827d1d35e2fSjeremylt     return CeedError(composite_op->ceed, CEED_ERROR_MINOR,
828e2f04181SAndrew T. Barker                      "CeedOperator is not a composite operator");
829c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
83052d6035fSJeremy L Thompson 
831d1d35e2fSjeremylt   if (composite_op->num_suboperators == CEED_COMPOSITE_MAX)
832c042f62fSJeremy L Thompson     // LCOV_EXCL_START
833d1d35e2fSjeremylt     return CeedError(composite_op->ceed, CEED_ERROR_UNSUPPORTED,
834d1d35e2fSjeremylt                      "Cannot add additional sub_operators");
835c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
836f04ea552SJeremy L Thompson   if (composite_op->is_immutable)
837f04ea552SJeremy L Thompson     // LCOV_EXCL_START
838f04ea552SJeremy L Thompson     return CeedError(composite_op->ceed, CEED_ERROR_MAJOR,
839f04ea552SJeremy L Thompson                      "Operator cannot be changed after set as immutable");
840f04ea552SJeremy L Thompson   // LCOV_EXCL_STOP
84152d6035fSJeremy L Thompson 
842d1d35e2fSjeremylt   composite_op->sub_operators[composite_op->num_suboperators] = sub_op;
8439560d06aSjeremylt   ierr = CeedOperatorReference(sub_op); CeedChk(ierr);
844d1d35e2fSjeremylt   composite_op->num_suboperators++;
845e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
84652d6035fSJeremy L Thompson }
84752d6035fSJeremy L Thompson 
84852d6035fSJeremy L Thompson /**
849*4db537f9SJeremy L Thompson   @brief Check if a CeedOperator is ready to be used.
850*4db537f9SJeremy L Thompson 
851*4db537f9SJeremy L Thompson   @param[in] op  CeedOperator to check
852*4db537f9SJeremy L Thompson 
853*4db537f9SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
854*4db537f9SJeremy L Thompson 
855*4db537f9SJeremy L Thompson   @ref User
856*4db537f9SJeremy L Thompson **/
857*4db537f9SJeremy L Thompson int CeedOperatorCheckReady(CeedOperator op) {
858*4db537f9SJeremy L Thompson   int ierr;
859*4db537f9SJeremy L Thompson   Ceed ceed;
860*4db537f9SJeremy L Thompson   ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr);
861*4db537f9SJeremy L Thompson 
862*4db537f9SJeremy L Thompson   if (op->is_interface_setup)
863*4db537f9SJeremy L Thompson     return CEED_ERROR_SUCCESS;
864*4db537f9SJeremy L Thompson 
865*4db537f9SJeremy L Thompson   CeedQFunction qf = op->qf;
866*4db537f9SJeremy L Thompson   if (op->is_composite) {
867*4db537f9SJeremy L Thompson     if (!op->num_suboperators)
868*4db537f9SJeremy L Thompson       // LCOV_EXCL_START
869*4db537f9SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No sub_operators set");
870*4db537f9SJeremy L Thompson     // LCOV_EXCL_STOP
871*4db537f9SJeremy L Thompson     for (CeedInt i = 0; i < op->num_suboperators; i++) {
872*4db537f9SJeremy L Thompson       ierr = CeedOperatorCheckReady(op->sub_operators[i]); CeedChk(ierr);
873*4db537f9SJeremy L Thompson     }
874*4db537f9SJeremy L Thompson   } else {
875*4db537f9SJeremy L Thompson     if (op->num_fields == 0)
876*4db537f9SJeremy L Thompson       // LCOV_EXCL_START
877*4db537f9SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No operator fields set");
878*4db537f9SJeremy L Thompson     // LCOV_EXCL_STOP
879*4db537f9SJeremy L Thompson     if (op->num_fields < qf->num_input_fields + qf->num_output_fields)
880*4db537f9SJeremy L Thompson       // LCOV_EXCL_START
881*4db537f9SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE, "Not all operator fields set");
882*4db537f9SJeremy L Thompson     // LCOV_EXCL_STOP
883*4db537f9SJeremy L Thompson     if (!op->has_restriction)
884*4db537f9SJeremy L Thompson       // LCOV_EXCL_START
885*4db537f9SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE,
886*4db537f9SJeremy L Thompson                        "At least one restriction required");
887*4db537f9SJeremy L Thompson     // LCOV_EXCL_STOP
888*4db537f9SJeremy L Thompson     if (op->num_qpts == 0)
889*4db537f9SJeremy L Thompson       // LCOV_EXCL_START
890*4db537f9SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE,
891*4db537f9SJeremy L Thompson                        "At least one non-collocated basis is required "
892*4db537f9SJeremy L Thompson                        "or the number of quadrature points must be set");
893*4db537f9SJeremy L Thompson     // LCOV_EXCL_STOP
894*4db537f9SJeremy L Thompson   }
895*4db537f9SJeremy L Thompson 
896*4db537f9SJeremy L Thompson   // Flag as immutable and ready
897*4db537f9SJeremy L Thompson   op->is_interface_setup = true;
898*4db537f9SJeremy L Thompson   if (op->qf && op->qf != CEED_QFUNCTION_NONE)
899*4db537f9SJeremy L Thompson     // LCOV_EXCL_START
900*4db537f9SJeremy L Thompson     op->qf->is_immutable = true;
901*4db537f9SJeremy L Thompson   // LCOV_EXCL_STOP
902*4db537f9SJeremy L Thompson   if (op->dqf && op->dqf != CEED_QFUNCTION_NONE)
903*4db537f9SJeremy L Thompson     // LCOV_EXCL_START
904*4db537f9SJeremy L Thompson     op->dqf->is_immutable = true;
905*4db537f9SJeremy L Thompson   // LCOV_EXCL_STOP
906*4db537f9SJeremy L Thompson   if (op->dqfT && op->dqfT != CEED_QFUNCTION_NONE)
907*4db537f9SJeremy L Thompson     // LCOV_EXCL_START
908*4db537f9SJeremy L Thompson     op->dqfT->is_immutable = true;
909*4db537f9SJeremy L Thompson   // LCOV_EXCL_STOP
910*4db537f9SJeremy L Thompson   return CEED_ERROR_SUCCESS;
911*4db537f9SJeremy L Thompson }
912*4db537f9SJeremy L Thompson 
913*4db537f9SJeremy L Thompson /**
914cd4dfc48Sjeremylt   @brief Set the number of quadrature points associated with a CeedOperator.
915cd4dfc48Sjeremylt            This should be used when creating a CeedOperator where every
916cd4dfc48Sjeremylt            field has a collocated basis. This function cannot be used for
917cd4dfc48Sjeremylt            composite CeedOperators.
918cd4dfc48Sjeremylt 
919cd4dfc48Sjeremylt   @param op        CeedOperator
920cd4dfc48Sjeremylt   @param num_qpts  Number of quadrature points to set
921cd4dfc48Sjeremylt 
922cd4dfc48Sjeremylt   @return An error code: 0 - success, otherwise - failure
923cd4dfc48Sjeremylt 
924e9b533fbSJeremy L Thompson   @ref Advanced
925cd4dfc48Sjeremylt **/
926cd4dfc48Sjeremylt int CeedOperatorSetNumQuadraturePoints(CeedOperator op, CeedInt num_qpts) {
927f04ea552SJeremy L Thompson   if (op->is_composite)
928cd4dfc48Sjeremylt     // LCOV_EXCL_START
929cd4dfc48Sjeremylt     return CeedError(op->ceed, CEED_ERROR_MINOR,
930cd4dfc48Sjeremylt                      "Not defined for composite operator");
931cd4dfc48Sjeremylt   // LCOV_EXCL_STOP
932cd4dfc48Sjeremylt   if (op->num_qpts)
933cd4dfc48Sjeremylt     // LCOV_EXCL_START
934cd4dfc48Sjeremylt     return CeedError(op->ceed, CEED_ERROR_MINOR,
935cd4dfc48Sjeremylt                      "Number of quadrature points already defined");
936cd4dfc48Sjeremylt   // LCOV_EXCL_STOP
937f04ea552SJeremy L Thompson   if (op->is_immutable)
938f04ea552SJeremy L Thompson     // LCOV_EXCL_START
939f04ea552SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MAJOR,
940f04ea552SJeremy L Thompson                      "Operator cannot be changed after set as immutable");
941f04ea552SJeremy L Thompson   // LCOV_EXCL_STOP
942cd4dfc48Sjeremylt 
943cd4dfc48Sjeremylt   op->num_qpts = num_qpts;
944cd4dfc48Sjeremylt   return CEED_ERROR_SUCCESS;
945cd4dfc48Sjeremylt }
946cd4dfc48Sjeremylt 
947cd4dfc48Sjeremylt /**
9487a982d89SJeremy L. Thompson   @brief View a CeedOperator
9497a982d89SJeremy L. Thompson 
9507a982d89SJeremy L. Thompson   @param[in] op      CeedOperator to view
9517a982d89SJeremy L. Thompson   @param[in] stream  Stream to write; typically stdout/stderr or a file
9527a982d89SJeremy L. Thompson 
9537a982d89SJeremy L. Thompson   @return Error code: 0 - success, otherwise - failure
9547a982d89SJeremy L. Thompson 
9557a982d89SJeremy L. Thompson   @ref User
9567a982d89SJeremy L. Thompson **/
9577a982d89SJeremy L. Thompson int CeedOperatorView(CeedOperator op, FILE *stream) {
9587a982d89SJeremy L. Thompson   int ierr;
9597a982d89SJeremy L. Thompson 
960f04ea552SJeremy L Thompson   if (op->is_composite) {
9617a982d89SJeremy L. Thompson     fprintf(stream, "Composite CeedOperator\n");
9627a982d89SJeremy L. Thompson 
963d1d35e2fSjeremylt     for (CeedInt i=0; i<op->num_suboperators; i++) {
9647a982d89SJeremy L. Thompson       fprintf(stream, "  SubOperator [%d]:\n", i);
965d1d35e2fSjeremylt       ierr = CeedOperatorSingleView(op->sub_operators[i], 1, stream);
9667a982d89SJeremy L. Thompson       CeedChk(ierr);
9677a982d89SJeremy L. Thompson     }
9687a982d89SJeremy L. Thompson   } else {
9697a982d89SJeremy L. Thompson     fprintf(stream, "CeedOperator\n");
9707a982d89SJeremy L. Thompson     ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr);
9717a982d89SJeremy L. Thompson   }
972e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
9737a982d89SJeremy L. Thompson }
9743bd813ffSjeremylt 
9753bd813ffSjeremylt /**
976b7c9bbdaSJeremy L Thompson   @brief Get the Ceed associated with a CeedOperator
977b7c9bbdaSJeremy L Thompson 
978b7c9bbdaSJeremy L Thompson   @param op         CeedOperator
979b7c9bbdaSJeremy L Thompson   @param[out] ceed  Variable to store Ceed
980b7c9bbdaSJeremy L Thompson 
981b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
982b7c9bbdaSJeremy L Thompson 
983b7c9bbdaSJeremy L Thompson   @ref Advanced
984b7c9bbdaSJeremy L Thompson **/
985b7c9bbdaSJeremy L Thompson int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) {
986b7c9bbdaSJeremy L Thompson   *ceed = op->ceed;
987b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
988b7c9bbdaSJeremy L Thompson }
989b7c9bbdaSJeremy L Thompson 
990b7c9bbdaSJeremy L Thompson /**
991b7c9bbdaSJeremy L Thompson   @brief Get the number of elements associated with a CeedOperator
992b7c9bbdaSJeremy L Thompson 
993b7c9bbdaSJeremy L Thompson   @param op             CeedOperator
994b7c9bbdaSJeremy L Thompson   @param[out] num_elem  Variable to store number of elements
995b7c9bbdaSJeremy L Thompson 
996b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
997b7c9bbdaSJeremy L Thompson 
998b7c9bbdaSJeremy L Thompson   @ref Advanced
999b7c9bbdaSJeremy L Thompson **/
1000b7c9bbdaSJeremy L Thompson int CeedOperatorGetNumElements(CeedOperator op, CeedInt *num_elem) {
1001b7c9bbdaSJeremy L Thompson   if (op->is_composite)
1002b7c9bbdaSJeremy L Thompson     // LCOV_EXCL_START
1003b7c9bbdaSJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
1004b7c9bbdaSJeremy L Thompson                      "Not defined for composite operator");
1005b7c9bbdaSJeremy L Thompson   // LCOV_EXCL_STOP
1006b7c9bbdaSJeremy L Thompson 
1007b7c9bbdaSJeremy L Thompson   *num_elem = op->num_elem;
1008b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1009b7c9bbdaSJeremy L Thompson }
1010b7c9bbdaSJeremy L Thompson 
1011b7c9bbdaSJeremy L Thompson /**
1012b7c9bbdaSJeremy L Thompson   @brief Get the number of quadrature points associated with a CeedOperator
1013b7c9bbdaSJeremy L Thompson 
1014b7c9bbdaSJeremy L Thompson   @param op             CeedOperator
1015b7c9bbdaSJeremy L Thompson   @param[out] num_qpts  Variable to store vector number of quadrature points
1016b7c9bbdaSJeremy L Thompson 
1017b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1018b7c9bbdaSJeremy L Thompson 
1019b7c9bbdaSJeremy L Thompson   @ref Advanced
1020b7c9bbdaSJeremy L Thompson **/
1021b7c9bbdaSJeremy L Thompson int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *num_qpts) {
1022b7c9bbdaSJeremy L Thompson   if (op->is_composite)
1023b7c9bbdaSJeremy L Thompson     // LCOV_EXCL_START
1024b7c9bbdaSJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
1025b7c9bbdaSJeremy L Thompson                      "Not defined for composite operator");
1026b7c9bbdaSJeremy L Thompson   // LCOV_EXCL_STOP
1027b7c9bbdaSJeremy L Thompson 
1028b7c9bbdaSJeremy L Thompson   *num_qpts = op->num_qpts;
1029b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1030b7c9bbdaSJeremy L Thompson }
1031b7c9bbdaSJeremy L Thompson 
1032b7c9bbdaSJeremy L Thompson /**
10333bd813ffSjeremylt   @brief Apply CeedOperator to a vector
1034d7b241e6Sjeremylt 
1035d7b241e6Sjeremylt   This computes the action of the operator on the specified (active) input,
1036d7b241e6Sjeremylt   yielding its (active) output.  All inputs and outputs must be specified using
1037d7b241e6Sjeremylt   CeedOperatorSetField().
1038d7b241e6Sjeremylt 
1039f04ea552SJeremy L Thompson   Note: Calling this function asserts that setup is complete
1040f04ea552SJeremy L Thompson           and sets the CeedOperator as immutable.
1041f04ea552SJeremy L Thompson 
1042d7b241e6Sjeremylt   @param op        CeedOperator to apply
10434cc79fe7SJed Brown   @param[in] in    CeedVector containing input state or @ref CEED_VECTOR_NONE if
104434138859Sjeremylt                      there are no active inputs
1045b11c1e72Sjeremylt   @param[out] out  CeedVector to store result of applying operator (must be
10464cc79fe7SJed Brown                      distinct from @a in) or @ref CEED_VECTOR_NONE if there are no
104734138859Sjeremylt                      active outputs
1048d7b241e6Sjeremylt   @param request   Address of CeedRequest for non-blocking completion, else
10494cc79fe7SJed Brown                      @ref CEED_REQUEST_IMMEDIATE
1050b11c1e72Sjeremylt 
1051b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1052dfdf5a53Sjeremylt 
10537a982d89SJeremy L. Thompson   @ref User
1054b11c1e72Sjeremylt **/
1055692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out,
1056692c2638Sjeremylt                       CeedRequest *request) {
1057d7b241e6Sjeremylt   int ierr;
1058e2f04181SAndrew T. Barker   ierr = CeedOperatorCheckReady(op); CeedChk(ierr);
1059d7b241e6Sjeremylt 
1060d1d35e2fSjeremylt   if (op->num_elem)  {
1061250756a7Sjeremylt     // Standard Operator
1062cae8b89aSjeremylt     if (op->Apply) {
1063250756a7Sjeremylt       ierr = op->Apply(op, in, out, request); CeedChk(ierr);
1064cae8b89aSjeremylt     } else {
1065cae8b89aSjeremylt       // Zero all output vectors
1066250756a7Sjeremylt       CeedQFunction qf = op->qf;
1067d1d35e2fSjeremylt       for (CeedInt i=0; i<qf->num_output_fields; i++) {
1068d1d35e2fSjeremylt         CeedVector vec = op->output_fields[i]->vec;
1069cae8b89aSjeremylt         if (vec == CEED_VECTOR_ACTIVE)
1070cae8b89aSjeremylt           vec = out;
1071cae8b89aSjeremylt         if (vec != CEED_VECTOR_NONE) {
1072cae8b89aSjeremylt           ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr);
1073cae8b89aSjeremylt         }
1074cae8b89aSjeremylt       }
1075250756a7Sjeremylt       // Apply
1076250756a7Sjeremylt       ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr);
1077250756a7Sjeremylt     }
1078f04ea552SJeremy L Thompson   } else if (op->is_composite) {
1079250756a7Sjeremylt     // Composite Operator
1080250756a7Sjeremylt     if (op->ApplyComposite) {
1081250756a7Sjeremylt       ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr);
1082250756a7Sjeremylt     } else {
1083d1d35e2fSjeremylt       CeedInt num_suboperators;
1084d1d35e2fSjeremylt       ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr);
1085d1d35e2fSjeremylt       CeedOperator *sub_operators;
1086d1d35e2fSjeremylt       ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr);
1087250756a7Sjeremylt 
1088250756a7Sjeremylt       // Zero all output vectors
1089250756a7Sjeremylt       if (out != CEED_VECTOR_NONE) {
1090cae8b89aSjeremylt         ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr);
1091cae8b89aSjeremylt       }
1092d1d35e2fSjeremylt       for (CeedInt i=0; i<num_suboperators; i++) {
1093d1d35e2fSjeremylt         for (CeedInt j=0; j<sub_operators[i]->qf->num_output_fields; j++) {
1094d1d35e2fSjeremylt           CeedVector vec = sub_operators[i]->output_fields[j]->vec;
1095250756a7Sjeremylt           if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) {
1096250756a7Sjeremylt             ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr);
1097250756a7Sjeremylt           }
1098250756a7Sjeremylt         }
1099250756a7Sjeremylt       }
1100250756a7Sjeremylt       // Apply
1101d1d35e2fSjeremylt       for (CeedInt i=0; i<op->num_suboperators; i++) {
1102d1d35e2fSjeremylt         ierr = CeedOperatorApplyAdd(op->sub_operators[i], in, out, request);
1103cae8b89aSjeremylt         CeedChk(ierr);
1104cae8b89aSjeremylt       }
1105cae8b89aSjeremylt     }
1106250756a7Sjeremylt   }
1107e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1108cae8b89aSjeremylt }
1109cae8b89aSjeremylt 
1110cae8b89aSjeremylt /**
1111cae8b89aSjeremylt   @brief Apply CeedOperator to a vector and add result to output vector
1112cae8b89aSjeremylt 
1113cae8b89aSjeremylt   This computes the action of the operator on the specified (active) input,
1114cae8b89aSjeremylt   yielding its (active) output.  All inputs and outputs must be specified using
1115cae8b89aSjeremylt   CeedOperatorSetField().
1116cae8b89aSjeremylt 
1117cae8b89aSjeremylt   @param op        CeedOperator to apply
1118cae8b89aSjeremylt   @param[in] in    CeedVector containing input state or NULL if there are no
1119cae8b89aSjeremylt                      active inputs
1120cae8b89aSjeremylt   @param[out] out  CeedVector to sum in result of applying operator (must be
1121cae8b89aSjeremylt                      distinct from @a in) or NULL if there are no active outputs
1122cae8b89aSjeremylt   @param request   Address of CeedRequest for non-blocking completion, else
11234cc79fe7SJed Brown                      @ref CEED_REQUEST_IMMEDIATE
1124cae8b89aSjeremylt 
1125cae8b89aSjeremylt   @return An error code: 0 - success, otherwise - failure
1126cae8b89aSjeremylt 
11277a982d89SJeremy L. Thompson   @ref User
1128cae8b89aSjeremylt **/
1129cae8b89aSjeremylt int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out,
1130cae8b89aSjeremylt                          CeedRequest *request) {
1131cae8b89aSjeremylt   int ierr;
1132e2f04181SAndrew T. Barker   ierr = CeedOperatorCheckReady(op); CeedChk(ierr);
1133cae8b89aSjeremylt 
1134d1d35e2fSjeremylt   if (op->num_elem)  {
1135250756a7Sjeremylt     // Standard Operator
1136250756a7Sjeremylt     ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr);
1137f04ea552SJeremy L Thompson   } else if (op->is_composite) {
1138250756a7Sjeremylt     // Composite Operator
1139250756a7Sjeremylt     if (op->ApplyAddComposite) {
1140250756a7Sjeremylt       ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr);
1141cae8b89aSjeremylt     } else {
1142d1d35e2fSjeremylt       CeedInt num_suboperators;
1143d1d35e2fSjeremylt       ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr);
1144d1d35e2fSjeremylt       CeedOperator *sub_operators;
1145d1d35e2fSjeremylt       ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr);
1146250756a7Sjeremylt 
1147d1d35e2fSjeremylt       for (CeedInt i=0; i<num_suboperators; i++) {
1148d1d35e2fSjeremylt         ierr = CeedOperatorApplyAdd(sub_operators[i], in, out, request);
1149cae8b89aSjeremylt         CeedChk(ierr);
11501d7d2407SJeremy L Thompson       }
1151250756a7Sjeremylt     }
1152250756a7Sjeremylt   }
1153e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1154d7b241e6Sjeremylt }
1155d7b241e6Sjeremylt 
1156d7b241e6Sjeremylt /**
1157b11c1e72Sjeremylt   @brief Destroy a CeedOperator
1158d7b241e6Sjeremylt 
1159d7b241e6Sjeremylt   @param op  CeedOperator to destroy
1160b11c1e72Sjeremylt 
1161b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1162dfdf5a53Sjeremylt 
11637a982d89SJeremy L. Thompson   @ref User
1164b11c1e72Sjeremylt **/
1165d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) {
1166d7b241e6Sjeremylt   int ierr;
1167d7b241e6Sjeremylt 
1168d1d35e2fSjeremylt   if (!*op || --(*op)->ref_count > 0) return CEED_ERROR_SUCCESS;
1169d7b241e6Sjeremylt   if ((*op)->Destroy) {
1170d7b241e6Sjeremylt     ierr = (*op)->Destroy(*op); CeedChk(ierr);
1171d7b241e6Sjeremylt   }
1172fe2413ffSjeremylt   ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr);
1173fe2413ffSjeremylt   // Free fields
1174d1d35e2fSjeremylt   for (int i=0; i<(*op)->num_fields; i++)
1175d1d35e2fSjeremylt     if ((*op)->input_fields[i]) {
1176d1d35e2fSjeremylt       if ((*op)->input_fields[i]->elem_restr != CEED_ELEMRESTRICTION_NONE) {
1177d1d35e2fSjeremylt         ierr = CeedElemRestrictionDestroy(&(*op)->input_fields[i]->elem_restr);
117871352a93Sjeremylt         CeedChk(ierr);
117915910d16Sjeremylt       }
1180d1d35e2fSjeremylt       if ((*op)->input_fields[i]->basis != CEED_BASIS_COLLOCATED) {
1181d1d35e2fSjeremylt         ierr = CeedBasisDestroy(&(*op)->input_fields[i]->basis); CeedChk(ierr);
118271352a93Sjeremylt       }
1183d1d35e2fSjeremylt       if ((*op)->input_fields[i]->vec != CEED_VECTOR_ACTIVE &&
1184d1d35e2fSjeremylt           (*op)->input_fields[i]->vec != CEED_VECTOR_NONE ) {
1185d1d35e2fSjeremylt         ierr = CeedVectorDestroy(&(*op)->input_fields[i]->vec); CeedChk(ierr);
118671352a93Sjeremylt       }
1187d1d35e2fSjeremylt       ierr = CeedFree(&(*op)->input_fields[i]->field_name); CeedChk(ierr);
1188d1d35e2fSjeremylt       ierr = CeedFree(&(*op)->input_fields[i]); CeedChk(ierr);
1189fe2413ffSjeremylt     }
1190d1d35e2fSjeremylt   for (int i=0; i<(*op)->num_fields; i++)
1191d1d35e2fSjeremylt     if ((*op)->output_fields[i]) {
1192d1d35e2fSjeremylt       ierr = CeedElemRestrictionDestroy(&(*op)->output_fields[i]->elem_restr);
119371352a93Sjeremylt       CeedChk(ierr);
1194d1d35e2fSjeremylt       if ((*op)->output_fields[i]->basis != CEED_BASIS_COLLOCATED) {
1195d1d35e2fSjeremylt         ierr = CeedBasisDestroy(&(*op)->output_fields[i]->basis); CeedChk(ierr);
119671352a93Sjeremylt       }
1197d1d35e2fSjeremylt       if ((*op)->output_fields[i]->vec != CEED_VECTOR_ACTIVE &&
1198d1d35e2fSjeremylt           (*op)->output_fields[i]->vec != CEED_VECTOR_NONE ) {
1199d1d35e2fSjeremylt         ierr = CeedVectorDestroy(&(*op)->output_fields[i]->vec); CeedChk(ierr);
120071352a93Sjeremylt       }
1201d1d35e2fSjeremylt       ierr = CeedFree(&(*op)->output_fields[i]->field_name); CeedChk(ierr);
1202d1d35e2fSjeremylt       ierr = CeedFree(&(*op)->output_fields[i]); CeedChk(ierr);
1203fe2413ffSjeremylt     }
1204d1d35e2fSjeremylt   // Destroy sub_operators
1205d1d35e2fSjeremylt   for (int i=0; i<(*op)->num_suboperators; i++)
1206d1d35e2fSjeremylt     if ((*op)->sub_operators[i]) {
1207d1d35e2fSjeremylt       ierr = CeedOperatorDestroy(&(*op)->sub_operators[i]); CeedChk(ierr);
120852d6035fSJeremy L Thompson     }
1209d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr);
1210d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr);
1211d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr);
1212fe2413ffSjeremylt 
12135107b09fSJeremy L Thompson   // Destroy fallback
1214d1d35e2fSjeremylt   if ((*op)->op_fallback) {
1215d1d35e2fSjeremylt     ierr = (*op)->qf_fallback->Destroy((*op)->qf_fallback); CeedChk(ierr);
1216d1d35e2fSjeremylt     ierr = CeedFree(&(*op)->qf_fallback); CeedChk(ierr);
121770a7ffb3SJeremy L Thompson     ierr = CeedVectorDestroy(&(*op)->op_fallback->qf_assembled); CeedChk(ierr);
121870a7ffb3SJeremy L Thompson     ierr = CeedElemRestrictionDestroy(&(*op)->op_fallback->qf_assembled_rstr);
121970a7ffb3SJeremy L Thompson     CeedChk(ierr);
1220d1d35e2fSjeremylt     ierr = (*op)->op_fallback->Destroy((*op)->op_fallback); CeedChk(ierr);
1221d1d35e2fSjeremylt     ierr = CeedFree(&(*op)->op_fallback); CeedChk(ierr);
12225107b09fSJeremy L Thompson   }
12235107b09fSJeremy L Thompson 
122470a7ffb3SJeremy L Thompson   // Destroy QF assembly cache
122570a7ffb3SJeremy L Thompson   ierr = CeedVectorDestroy(&(*op)->qf_assembled); CeedChk(ierr);
122670a7ffb3SJeremy L Thompson   ierr = CeedElemRestrictionDestroy(&(*op)->qf_assembled_rstr); CeedChk(ierr);
122770a7ffb3SJeremy L Thompson 
1228d1d35e2fSjeremylt   ierr = CeedFree(&(*op)->input_fields); CeedChk(ierr);
1229d1d35e2fSjeremylt   ierr = CeedFree(&(*op)->output_fields); CeedChk(ierr);
1230d1d35e2fSjeremylt   ierr = CeedFree(&(*op)->sub_operators); CeedChk(ierr);
1231d7b241e6Sjeremylt   ierr = CeedFree(op); CeedChk(ierr);
1232e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1233d7b241e6Sjeremylt }
1234d7b241e6Sjeremylt 
1235d7b241e6Sjeremylt /// @}
1236