xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-operator.c (revision 70a7ffb32f2ac8f6de27898459ba6016395fdb67)
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 Check if a CeedOperator is ready to be used.
1377a982d89SJeremy L. Thompson 
1387a982d89SJeremy L. Thompson   @param[in] op  CeedOperator to check
1397a982d89SJeremy L. Thompson 
1407a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
1417a982d89SJeremy L. Thompson 
1427a982d89SJeremy L. Thompson   @ref Developer
1437a982d89SJeremy L. Thompson **/
144eaf62fffSJeremy L Thompson int CeedOperatorCheckReady(CeedOperator op) {
145e2f04181SAndrew T. Barker   int ierr;
146e2f04181SAndrew T. Barker   Ceed ceed;
147e2f04181SAndrew T. Barker   ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr);
148e2f04181SAndrew T. Barker 
149f04ea552SJeremy L Thompson   if (op->is_interface_setup)
150e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
1517a982d89SJeremy L. Thompson 
152e15f9bd0SJeremy L Thompson   CeedQFunction qf = op->qf;
153f04ea552SJeremy L Thompson   if (op->is_composite) {
154d1d35e2fSjeremylt     if (!op->num_suboperators)
1557a982d89SJeremy L. Thompson       // LCOV_EXCL_START
156d1d35e2fSjeremylt       return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No sub_operators set");
1577a982d89SJeremy L. Thompson     // LCOV_EXCL_STOP
1587a982d89SJeremy L. Thompson   } else {
159d1d35e2fSjeremylt     if (op->num_fields == 0)
1607a982d89SJeremy L. Thompson       // LCOV_EXCL_START
161e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No operator fields set");
1627a982d89SJeremy L. Thompson     // LCOV_EXCL_STOP
163d1d35e2fSjeremylt     if (op->num_fields < qf->num_input_fields + qf->num_output_fields)
1647a982d89SJeremy L. Thompson       // LCOV_EXCL_START
165e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE, "Not all operator fields set");
1667a982d89SJeremy L. Thompson     // LCOV_EXCL_STOP
167d1d35e2fSjeremylt     if (!op->has_restriction)
1687a982d89SJeremy L. Thompson       // LCOV_EXCL_START
169e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE,
170e15f9bd0SJeremy L Thompson                        "At least one restriction required");
1717a982d89SJeremy L. Thompson     // LCOV_EXCL_STOP
172d1d35e2fSjeremylt     if (op->num_qpts == 0)
1737a982d89SJeremy L. Thompson       // LCOV_EXCL_START
174e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_INCOMPLETE,
175cd4dfc48Sjeremylt                        "At least one non-collocated basis is required "
176cd4dfc48Sjeremylt                        "or the number of quadrature points must be set");
1777a982d89SJeremy L. Thompson     // LCOV_EXCL_STOP
1787a982d89SJeremy L. Thompson   }
1797a982d89SJeremy L. Thompson 
180e15f9bd0SJeremy L Thompson   // Flag as immutable and ready
181f04ea552SJeremy L Thompson   op->is_interface_setup = true;
182e15f9bd0SJeremy L Thompson   if (op->qf && op->qf != CEED_QFUNCTION_NONE)
183e15f9bd0SJeremy L Thompson     // LCOV_EXCL_START
184f04ea552SJeremy L Thompson     op->qf->is_immutable = true;
185e15f9bd0SJeremy L Thompson   // LCOV_EXCL_STOP
186e15f9bd0SJeremy L Thompson   if (op->dqf && op->dqf != CEED_QFUNCTION_NONE)
187e15f9bd0SJeremy L Thompson     // LCOV_EXCL_START
188f04ea552SJeremy L Thompson     op->dqf->is_immutable = true;
189e15f9bd0SJeremy L Thompson   // LCOV_EXCL_STOP
190e15f9bd0SJeremy L Thompson   if (op->dqfT && op->dqfT != CEED_QFUNCTION_NONE)
191e15f9bd0SJeremy L Thompson     // LCOV_EXCL_START
192f04ea552SJeremy L Thompson     op->dqfT->is_immutable = true;
193e15f9bd0SJeremy L Thompson   // LCOV_EXCL_STOP
194e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1957a982d89SJeremy L. Thompson }
1967a982d89SJeremy L. Thompson 
1977a982d89SJeremy L. Thompson /**
1987a982d89SJeremy L. Thompson   @brief View a field of a CeedOperator
1997a982d89SJeremy L. Thompson 
2007a982d89SJeremy L. Thompson   @param[in] field         Operator field to view
201d1d35e2fSjeremylt   @param[in] qf_field      QFunction field (carries field name)
202d1d35e2fSjeremylt   @param[in] field_number  Number of field being viewed
2034c4400c7SValeria Barra   @param[in] sub           true indicates sub-operator, which increases indentation; false for top-level operator
204d1d35e2fSjeremylt   @param[in] input         true for an input field; false for output field
2057a982d89SJeremy L. Thompson   @param[in] stream        Stream to view to, e.g., stdout
2067a982d89SJeremy L. Thompson 
2077a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
2087a982d89SJeremy L. Thompson 
2097a982d89SJeremy L. Thompson   @ref Utility
2107a982d89SJeremy L. Thompson **/
2117a982d89SJeremy L. Thompson static int CeedOperatorFieldView(CeedOperatorField field,
212d1d35e2fSjeremylt                                  CeedQFunctionField qf_field,
213d1d35e2fSjeremylt                                  CeedInt field_number, bool sub, bool input,
2147a982d89SJeremy L. Thompson                                  FILE *stream) {
2157a982d89SJeremy L. Thompson   const char *pre = sub ? "  " : "";
216d1d35e2fSjeremylt   const char *in_out = input ? "Input" : "Output";
2177a982d89SJeremy L. Thompson 
2187a982d89SJeremy L. Thompson   fprintf(stream, "%s    %s Field [%d]:\n"
2197a982d89SJeremy L. Thompson           "%s      Name: \"%s\"\n",
220d1d35e2fSjeremylt           pre, in_out, field_number, pre, qf_field->field_name);
2217a982d89SJeremy L. Thompson 
2227a982d89SJeremy L. Thompson   if (field->basis == CEED_BASIS_COLLOCATED)
2237a982d89SJeremy L. Thompson     fprintf(stream, "%s      Collocated basis\n", pre);
2247a982d89SJeremy L. Thompson 
2257a982d89SJeremy L. Thompson   if (field->vec == CEED_VECTOR_ACTIVE)
2267a982d89SJeremy L. Thompson     fprintf(stream, "%s      Active vector\n", pre);
2277a982d89SJeremy L. Thompson   else if (field->vec == CEED_VECTOR_NONE)
2287a982d89SJeremy L. Thompson     fprintf(stream, "%s      No vector\n", pre);
229e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2307a982d89SJeremy L. Thompson }
2317a982d89SJeremy L. Thompson 
2327a982d89SJeremy L. Thompson /**
2337a982d89SJeremy L. Thompson   @brief View a single CeedOperator
2347a982d89SJeremy L. Thompson 
2357a982d89SJeremy L. Thompson   @param[in] op      CeedOperator to view
2367a982d89SJeremy L. Thompson   @param[in] sub     Boolean flag for sub-operator
2377a982d89SJeremy L. Thompson   @param[in] stream  Stream to write; typically stdout/stderr or a file
2387a982d89SJeremy L. Thompson 
2397a982d89SJeremy L. Thompson   @return Error code: 0 - success, otherwise - failure
2407a982d89SJeremy L. Thompson 
2417a982d89SJeremy L. Thompson   @ref Utility
2427a982d89SJeremy L. Thompson **/
2437a982d89SJeremy L. Thompson int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) {
2447a982d89SJeremy L. Thompson   int ierr;
2457a982d89SJeremy L. Thompson   const char *pre = sub ? "  " : "";
2467a982d89SJeremy L. Thompson 
24778464608Sjeremylt   CeedInt total_fields = 0;
24878464608Sjeremylt   ierr = CeedOperatorGetNumArgs(op, &total_fields); CeedChk(ierr);
2497a982d89SJeremy L. Thompson 
25078464608Sjeremylt   fprintf(stream, "%s  %d Field%s\n", pre, total_fields,
25178464608Sjeremylt           total_fields>1 ? "s" : "");
2527a982d89SJeremy L. Thompson 
253d1d35e2fSjeremylt   fprintf(stream, "%s  %d Input Field%s:\n", pre, op->qf->num_input_fields,
254d1d35e2fSjeremylt           op->qf->num_input_fields>1 ? "s" : "");
255d1d35e2fSjeremylt   for (CeedInt i=0; i<op->qf->num_input_fields; i++) {
256d1d35e2fSjeremylt     ierr = CeedOperatorFieldView(op->input_fields[i], op->qf->input_fields[i],
2577a982d89SJeremy L. Thompson                                  i, sub, 1, stream); CeedChk(ierr);
2587a982d89SJeremy L. Thompson   }
2597a982d89SJeremy L. Thompson 
260d1d35e2fSjeremylt   fprintf(stream, "%s  %d Output Field%s:\n", pre, op->qf->num_output_fields,
261d1d35e2fSjeremylt           op->qf->num_output_fields>1 ? "s" : "");
262d1d35e2fSjeremylt   for (CeedInt i=0; i<op->qf->num_output_fields; i++) {
263d1d35e2fSjeremylt     ierr = CeedOperatorFieldView(op->output_fields[i], op->qf->output_fields[i],
2647a982d89SJeremy L. Thompson                                  i, sub, 0, stream); CeedChk(ierr);
2657a982d89SJeremy L. Thompson   }
266e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
2677a982d89SJeremy L. Thompson }
2687a982d89SJeremy L. Thompson 
269d99fa3c5SJeremy L Thompson /**
270eaf62fffSJeremy L Thompson   @brief Find the active vector basis for a CeedOperator
271eaf62fffSJeremy L Thompson 
272eaf62fffSJeremy L Thompson   @param[in] op             CeedOperator to find active basis for
273eaf62fffSJeremy L Thompson   @param[out] active_basis  Basis for active input vector
274eaf62fffSJeremy L Thompson 
275eaf62fffSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
276eaf62fffSJeremy L Thompson 
277eaf62fffSJeremy L Thompson   @ ref Developer
278eaf62fffSJeremy L Thompson **/
279eaf62fffSJeremy L Thompson int CeedOperatorGetActiveBasis(CeedOperator op, CeedBasis *active_basis) {
280eaf62fffSJeremy L Thompson   *active_basis = NULL;
281eaf62fffSJeremy L Thompson   for (int i = 0; i < op->qf->num_input_fields; i++)
282eaf62fffSJeremy L Thompson     if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) {
283eaf62fffSJeremy L Thompson       *active_basis = op->input_fields[i]->basis;
284eaf62fffSJeremy L Thompson       break;
285eaf62fffSJeremy L Thompson     }
286eaf62fffSJeremy L Thompson 
287eaf62fffSJeremy L Thompson   if (!*active_basis) {
288eaf62fffSJeremy L Thompson     // LCOV_EXCL_START
289eaf62fffSJeremy L Thompson     int ierr;
290eaf62fffSJeremy L Thompson     Ceed ceed;
291eaf62fffSJeremy L Thompson     ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr);
292eaf62fffSJeremy L Thompson     return CeedError(ceed, CEED_ERROR_MINOR,
293eaf62fffSJeremy L Thompson                      "No active CeedBasis found");
294eaf62fffSJeremy L Thompson     // LCOV_EXCL_STOP
295eaf62fffSJeremy L Thompson   }
296eaf62fffSJeremy L Thompson   return CEED_ERROR_SUCCESS;
297eaf62fffSJeremy L Thompson }
298eaf62fffSJeremy L Thompson 
299eaf62fffSJeremy L Thompson /**
300e2f04181SAndrew T. Barker   @brief Find the active vector ElemRestriction for a CeedOperator
301e2f04181SAndrew T. Barker 
302e2f04181SAndrew T. Barker   @param[in] op            CeedOperator to find active basis for
303d1d35e2fSjeremylt   @param[out] active_rstr  ElemRestriction for active input vector
304e2f04181SAndrew T. Barker 
305e2f04181SAndrew T. Barker   @return An error code: 0 - success, otherwise - failure
306e2f04181SAndrew T. Barker 
307e2f04181SAndrew T. Barker   @ref Utility
308e2f04181SAndrew T. Barker **/
309eaf62fffSJeremy L Thompson int CeedOperatorGetActiveElemRestriction(CeedOperator op,
310d1d35e2fSjeremylt     CeedElemRestriction *active_rstr) {
311d1d35e2fSjeremylt   *active_rstr = NULL;
312d1d35e2fSjeremylt   for (int i = 0; i < op->qf->num_input_fields; i++)
313d1d35e2fSjeremylt     if (op->input_fields[i]->vec == CEED_VECTOR_ACTIVE) {
314d1d35e2fSjeremylt       *active_rstr = op->input_fields[i]->elem_restr;
315e2f04181SAndrew T. Barker       break;
316e2f04181SAndrew T. Barker     }
317e2f04181SAndrew T. Barker 
318d1d35e2fSjeremylt   if (!*active_rstr) {
319e2f04181SAndrew T. Barker     // LCOV_EXCL_START
320e2f04181SAndrew T. Barker     int ierr;
321e2f04181SAndrew T. Barker     Ceed ceed;
322e2f04181SAndrew T. Barker     ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr);
323e2f04181SAndrew T. Barker     return CeedError(ceed, CEED_ERROR_INCOMPLETE,
324eaf62fffSJeremy L Thompson                      "No active CeedElemRestriction found");
325e2f04181SAndrew T. Barker     // LCOV_EXCL_STOP
326e2f04181SAndrew T. Barker   }
327e2f04181SAndrew T. Barker   return CEED_ERROR_SUCCESS;
328e2f04181SAndrew T. Barker }
329e2f04181SAndrew T. Barker 
3307a982d89SJeremy L. Thompson /// @}
3317a982d89SJeremy L. Thompson 
3327a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
3337a982d89SJeremy L. Thompson /// CeedOperator Backend API
3347a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
3357a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorBackend
3367a982d89SJeremy L. Thompson /// @{
3377a982d89SJeremy L. Thompson 
3387a982d89SJeremy L. Thompson /**
3397a982d89SJeremy L. Thompson   @brief Get the number of arguments associated with a CeedOperator
3407a982d89SJeremy L. Thompson 
3417a982d89SJeremy L. Thompson   @param op             CeedOperator
342d1d35e2fSjeremylt   @param[out] num_args  Variable to store vector number of arguments
3437a982d89SJeremy L. Thompson 
3447a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3457a982d89SJeremy L. Thompson 
3467a982d89SJeremy L. Thompson   @ref Backend
3477a982d89SJeremy L. Thompson **/
3487a982d89SJeremy L. Thompson 
349d1d35e2fSjeremylt int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *num_args) {
350f04ea552SJeremy L Thompson   if (op->is_composite)
3517a982d89SJeremy L. Thompson     // LCOV_EXCL_START
352e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
353e15f9bd0SJeremy L Thompson                      "Not defined for composite operators");
3547a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
3557a982d89SJeremy L. Thompson 
356d1d35e2fSjeremylt   *num_args = op->num_fields;
357e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3587a982d89SJeremy L. Thompson }
3597a982d89SJeremy L. Thompson 
3607a982d89SJeremy L. Thompson /**
3617a982d89SJeremy L. Thompson   @brief Get the setup status of a CeedOperator
3627a982d89SJeremy L. Thompson 
3637a982d89SJeremy L. Thompson   @param op                  CeedOperator
364d1d35e2fSjeremylt   @param[out] is_setup_done  Variable to store setup status
3657a982d89SJeremy L. Thompson 
3667a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3677a982d89SJeremy L. Thompson 
3687a982d89SJeremy L. Thompson   @ref Backend
3697a982d89SJeremy L. Thompson **/
3707a982d89SJeremy L. Thompson 
371d1d35e2fSjeremylt int CeedOperatorIsSetupDone(CeedOperator op, bool *is_setup_done) {
372f04ea552SJeremy L Thompson   *is_setup_done = op->is_backend_setup;
373e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3747a982d89SJeremy L. Thompson }
3757a982d89SJeremy L. Thompson 
3767a982d89SJeremy L. Thompson /**
3777a982d89SJeremy L. Thompson   @brief Get the QFunction associated with a CeedOperator
3787a982d89SJeremy L. Thompson 
3797a982d89SJeremy L. Thompson   @param op       CeedOperator
3807a982d89SJeremy L. Thompson   @param[out] qf  Variable to store QFunction
3817a982d89SJeremy L. Thompson 
3827a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
3837a982d89SJeremy L. Thompson 
3847a982d89SJeremy L. Thompson   @ref Backend
3857a982d89SJeremy L. Thompson **/
3867a982d89SJeremy L. Thompson 
3877a982d89SJeremy L. Thompson int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) {
388f04ea552SJeremy L Thompson   if (op->is_composite)
3897a982d89SJeremy L. Thompson     // LCOV_EXCL_START
390e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
391e15f9bd0SJeremy L Thompson                      "Not defined for composite operator");
3927a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
3937a982d89SJeremy L. Thompson 
3947a982d89SJeremy L. Thompson   *qf = op->qf;
395e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
3967a982d89SJeremy L. Thompson }
3977a982d89SJeremy L. Thompson 
3987a982d89SJeremy L. Thompson /**
399c04a41a7SJeremy L Thompson   @brief Get a boolean value indicating if the CeedOperator is composite
400c04a41a7SJeremy L Thompson 
401c04a41a7SJeremy L Thompson   @param op                 CeedOperator
402d1d35e2fSjeremylt   @param[out] is_composite  Variable to store composite status
403c04a41a7SJeremy L Thompson 
404c04a41a7SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
405c04a41a7SJeremy L Thompson 
406c04a41a7SJeremy L Thompson   @ref Backend
407c04a41a7SJeremy L Thompson **/
408c04a41a7SJeremy L Thompson 
409d1d35e2fSjeremylt int CeedOperatorIsComposite(CeedOperator op, bool *is_composite) {
410f04ea552SJeremy L Thompson   *is_composite = op->is_composite;
411e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
412c04a41a7SJeremy L Thompson }
413c04a41a7SJeremy L Thompson 
414c04a41a7SJeremy L Thompson /**
415d1d35e2fSjeremylt   @brief Get the number of sub_operators associated with a CeedOperator
4167a982d89SJeremy L. Thompson 
4177a982d89SJeremy L. Thompson   @param op                     CeedOperator
418d1d35e2fSjeremylt   @param[out] num_suboperators  Variable to store number of sub_operators
4197a982d89SJeremy L. Thompson 
4207a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4217a982d89SJeremy L. Thompson 
4227a982d89SJeremy L. Thompson   @ref Backend
4237a982d89SJeremy L. Thompson **/
4247a982d89SJeremy L. Thompson 
425d1d35e2fSjeremylt int CeedOperatorGetNumSub(CeedOperator op, CeedInt *num_suboperators) {
426f04ea552SJeremy L Thompson   if (!op->is_composite)
4277a982d89SJeremy L. Thompson     // LCOV_EXCL_START
428e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator");
4297a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
4307a982d89SJeremy L. Thompson 
431d1d35e2fSjeremylt   *num_suboperators = op->num_suboperators;
432e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4337a982d89SJeremy L. Thompson }
4347a982d89SJeremy L. Thompson 
4357a982d89SJeremy L. Thompson /**
436d1d35e2fSjeremylt   @brief Get the list of sub_operators associated with a CeedOperator
4377a982d89SJeremy L. Thompson 
4387a982d89SJeremy L. Thompson   @param op                  CeedOperator
439d1d35e2fSjeremylt   @param[out] sub_operators  Variable to store list of sub_operators
4407a982d89SJeremy L. Thompson 
4417a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4427a982d89SJeremy L. Thompson 
4437a982d89SJeremy L. Thompson   @ref Backend
4447a982d89SJeremy L. Thompson **/
4457a982d89SJeremy L. Thompson 
446d1d35e2fSjeremylt int CeedOperatorGetSubList(CeedOperator op, CeedOperator **sub_operators) {
447f04ea552SJeremy L Thompson   if (!op->is_composite)
4487a982d89SJeremy L. Thompson     // LCOV_EXCL_START
449e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator");
4507a982d89SJeremy L. Thompson   // LCOV_EXCL_STOP
4517a982d89SJeremy L. Thompson 
452d1d35e2fSjeremylt   *sub_operators = op->sub_operators;
453e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4547a982d89SJeremy L. Thompson }
4557a982d89SJeremy L. Thompson 
4567a982d89SJeremy L. Thompson /**
4577a982d89SJeremy L. Thompson   @brief Get the backend data of a CeedOperator
4587a982d89SJeremy L. Thompson 
4597a982d89SJeremy L. Thompson   @param op         CeedOperator
4607a982d89SJeremy L. Thompson   @param[out] data  Variable to store data
4617a982d89SJeremy L. Thompson 
4627a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4637a982d89SJeremy L. Thompson 
4647a982d89SJeremy L. Thompson   @ref Backend
4657a982d89SJeremy L. Thompson **/
4667a982d89SJeremy L. Thompson 
467777ff853SJeremy L Thompson int CeedOperatorGetData(CeedOperator op, void *data) {
468777ff853SJeremy L Thompson   *(void **)data = op->data;
469e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4707a982d89SJeremy L. Thompson }
4717a982d89SJeremy L. Thompson 
4727a982d89SJeremy L. Thompson /**
4737a982d89SJeremy L. Thompson   @brief Set the backend data of a CeedOperator
4747a982d89SJeremy L. Thompson 
4757a982d89SJeremy L. Thompson   @param[out] op  CeedOperator
4767a982d89SJeremy L. Thompson   @param data     Data to set
4777a982d89SJeremy L. Thompson 
4787a982d89SJeremy L. Thompson   @return An error code: 0 - success, otherwise - failure
4797a982d89SJeremy L. Thompson 
4807a982d89SJeremy L. Thompson   @ref Backend
4817a982d89SJeremy L. Thompson **/
4827a982d89SJeremy L. Thompson 
483777ff853SJeremy L Thompson int CeedOperatorSetData(CeedOperator op, void *data) {
484777ff853SJeremy L Thompson   op->data = data;
485e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
4867a982d89SJeremy L. Thompson }
4877a982d89SJeremy L. Thompson 
4887a982d89SJeremy L. Thompson /**
48934359f16Sjeremylt   @brief Increment the reference counter for a CeedOperator
49034359f16Sjeremylt 
49134359f16Sjeremylt   @param op  CeedOperator to increment the reference counter
49234359f16Sjeremylt 
49334359f16Sjeremylt   @return An error code: 0 - success, otherwise - failure
49434359f16Sjeremylt 
49534359f16Sjeremylt   @ref Backend
49634359f16Sjeremylt **/
4979560d06aSjeremylt int CeedOperatorReference(CeedOperator op) {
49834359f16Sjeremylt   op->ref_count++;
49934359f16Sjeremylt   return CEED_ERROR_SUCCESS;
50034359f16Sjeremylt }
50134359f16Sjeremylt 
50234359f16Sjeremylt /**
5037a982d89SJeremy L. Thompson   @brief Set the setup flag of a CeedOperator to True
5047a982d89SJeremy L. Thompson 
5057a982d89SJeremy L. Thompson   @param op  CeedOperator
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 **/
5117a982d89SJeremy L. Thompson 
5127a982d89SJeremy L. Thompson int CeedOperatorSetSetupDone(CeedOperator op) {
513f04ea552SJeremy L Thompson   op->is_backend_setup = true;
514e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
5157a982d89SJeremy L. Thompson }
5167a982d89SJeremy L. Thompson 
5177a982d89SJeremy L. Thompson /// @}
5187a982d89SJeremy L. Thompson 
5197a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
5207a982d89SJeremy L. Thompson /// CeedOperator Public API
5217a982d89SJeremy L. Thompson /// ----------------------------------------------------------------------------
5227a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorUser
523dfdf5a53Sjeremylt /// @{
524d7b241e6Sjeremylt 
525d7b241e6Sjeremylt /**
5260219ea01SJeremy L Thompson   @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and
5270219ea01SJeremy L Thompson            CeedElemRestriction can be associated with CeedQFunction fields with
5280219ea01SJeremy L Thompson            \ref CeedOperatorSetField.
529d7b241e6Sjeremylt 
530b11c1e72Sjeremylt   @param ceed     A Ceed object where the CeedOperator will be created
531d7b241e6Sjeremylt   @param qf       QFunction defining the action of the operator at quadrature points
53234138859Sjeremylt   @param dqf      QFunction defining the action of the Jacobian of @a qf (or
5334cc79fe7SJed Brown                     @ref CEED_QFUNCTION_NONE)
534d7b241e6Sjeremylt   @param dqfT     QFunction defining the action of the transpose of the Jacobian
5354cc79fe7SJed Brown                     of @a qf (or @ref CEED_QFUNCTION_NONE)
536b11c1e72Sjeremylt   @param[out] op  Address of the variable where the newly created
537b11c1e72Sjeremylt                     CeedOperator will be stored
538b11c1e72Sjeremylt 
539b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
540dfdf5a53Sjeremylt 
5417a982d89SJeremy L. Thompson   @ref User
542d7b241e6Sjeremylt  */
543d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf,
544d7b241e6Sjeremylt                        CeedQFunction dqfT, CeedOperator *op) {
545d7b241e6Sjeremylt   int ierr;
546d7b241e6Sjeremylt 
5475fe0d4faSjeremylt   if (!ceed->OperatorCreate) {
5485fe0d4faSjeremylt     Ceed delegate;
549aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr);
5505fe0d4faSjeremylt 
5515fe0d4faSjeremylt     if (!delegate)
552c042f62fSJeremy L Thompson       // LCOV_EXCL_START
553e15f9bd0SJeremy L Thompson       return CeedError(ceed, CEED_ERROR_UNSUPPORTED,
554e15f9bd0SJeremy L Thompson                        "Backend does not support OperatorCreate");
555c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
5565fe0d4faSjeremylt 
5575fe0d4faSjeremylt     ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr);
558e15f9bd0SJeremy L Thompson     return CEED_ERROR_SUCCESS;
5595fe0d4faSjeremylt   }
5605fe0d4faSjeremylt 
561b3b7035fSJeremy L Thompson   if (!qf || qf == CEED_QFUNCTION_NONE)
562b3b7035fSJeremy L Thompson     // LCOV_EXCL_START
563e15f9bd0SJeremy L Thompson     return CeedError(ceed, CEED_ERROR_MINOR,
564e15f9bd0SJeremy L Thompson                      "Operator must have a valid QFunction.");
565b3b7035fSJeremy L Thompson   // LCOV_EXCL_STOP
566d7b241e6Sjeremylt   ierr = CeedCalloc(1, op); CeedChk(ierr);
567d7b241e6Sjeremylt   (*op)->ceed = ceed;
5689560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
569d1d35e2fSjeremylt   (*op)->ref_count = 1;
570d7b241e6Sjeremylt   (*op)->qf = qf;
5719560d06aSjeremylt   ierr = CeedQFunctionReference(qf); CeedChk(ierr);
572442e7f0bSjeremylt   if (dqf && dqf != CEED_QFUNCTION_NONE) {
573d7b241e6Sjeremylt     (*op)->dqf = dqf;
5749560d06aSjeremylt     ierr = CeedQFunctionReference(dqf); CeedChk(ierr);
575442e7f0bSjeremylt   }
576442e7f0bSjeremylt   if (dqfT && dqfT != CEED_QFUNCTION_NONE) {
577d7b241e6Sjeremylt     (*op)->dqfT = dqfT;
5789560d06aSjeremylt     ierr = CeedQFunctionReference(dqfT); CeedChk(ierr);
579442e7f0bSjeremylt   }
580d1d35e2fSjeremylt   ierr = CeedCalloc(16, &(*op)->input_fields); CeedChk(ierr);
581d1d35e2fSjeremylt   ierr = CeedCalloc(16, &(*op)->output_fields); CeedChk(ierr);
582d7b241e6Sjeremylt   ierr = ceed->OperatorCreate(*op); CeedChk(ierr);
583e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
584d7b241e6Sjeremylt }
585d7b241e6Sjeremylt 
586d7b241e6Sjeremylt /**
58752d6035fSJeremy L Thompson   @brief Create an operator that composes the action of several operators
58852d6035fSJeremy L Thompson 
58952d6035fSJeremy L Thompson   @param ceed     A Ceed object where the CeedOperator will be created
59052d6035fSJeremy L Thompson   @param[out] op  Address of the variable where the newly created
59152d6035fSJeremy L Thompson                     Composite CeedOperator will be stored
59252d6035fSJeremy L Thompson 
59352d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
59452d6035fSJeremy L Thompson 
5957a982d89SJeremy L. Thompson   @ref User
59652d6035fSJeremy L Thompson  */
59752d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) {
59852d6035fSJeremy L Thompson   int ierr;
59952d6035fSJeremy L Thompson 
60052d6035fSJeremy L Thompson   if (!ceed->CompositeOperatorCreate) {
60152d6035fSJeremy L Thompson     Ceed delegate;
602aefd8378Sjeremylt     ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr);
60352d6035fSJeremy L Thompson 
604250756a7Sjeremylt     if (delegate) {
60552d6035fSJeremy L Thompson       ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr);
606e15f9bd0SJeremy L Thompson       return CEED_ERROR_SUCCESS;
60752d6035fSJeremy L Thompson     }
608250756a7Sjeremylt   }
60952d6035fSJeremy L Thompson 
61052d6035fSJeremy L Thompson   ierr = CeedCalloc(1, op); CeedChk(ierr);
61152d6035fSJeremy L Thompson   (*op)->ceed = ceed;
6129560d06aSjeremylt   ierr = CeedReference(ceed); CeedChk(ierr);
613f04ea552SJeremy L Thompson   (*op)->is_composite = true;
614d1d35e2fSjeremylt   ierr = CeedCalloc(16, &(*op)->sub_operators); CeedChk(ierr);
615250756a7Sjeremylt 
616250756a7Sjeremylt   if (ceed->CompositeOperatorCreate) {
61752d6035fSJeremy L Thompson     ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr);
618250756a7Sjeremylt   }
619e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
62052d6035fSJeremy L Thompson }
62152d6035fSJeremy L Thompson 
62252d6035fSJeremy L Thompson /**
6239560d06aSjeremylt   @brief Copy the pointer to a CeedOperator. Both pointers should
6249560d06aSjeremylt            be destroyed with `CeedOperatorDestroy()`;
6259560d06aSjeremylt            Note: If `*op_copy` is non-NULL, then it is assumed that
6269560d06aSjeremylt            `*op_copy` is a pointer to a CeedOperator. This
6279560d06aSjeremylt            CeedOperator will be destroyed if `*op_copy` is the only
6289560d06aSjeremylt            reference to this CeedOperator.
6299560d06aSjeremylt 
6309560d06aSjeremylt   @param op            CeedOperator to copy reference to
6319560d06aSjeremylt   @param[out] op_copy  Variable to store copied reference
6329560d06aSjeremylt 
6339560d06aSjeremylt   @return An error code: 0 - success, otherwise - failure
6349560d06aSjeremylt 
6359560d06aSjeremylt   @ref User
6369560d06aSjeremylt **/
6379560d06aSjeremylt int CeedOperatorReferenceCopy(CeedOperator op, CeedOperator *op_copy) {
6389560d06aSjeremylt   int ierr;
6399560d06aSjeremylt 
6409560d06aSjeremylt   ierr = CeedOperatorReference(op); CeedChk(ierr);
6419560d06aSjeremylt   ierr = CeedOperatorDestroy(op_copy); CeedChk(ierr);
6429560d06aSjeremylt   *op_copy = op;
6439560d06aSjeremylt   return CEED_ERROR_SUCCESS;
6449560d06aSjeremylt }
6459560d06aSjeremylt 
6469560d06aSjeremylt /**
647b11c1e72Sjeremylt   @brief Provide a field to a CeedOperator for use by its CeedQFunction
648d7b241e6Sjeremylt 
649d7b241e6Sjeremylt   This function is used to specify both active and passive fields to a
650d7b241e6Sjeremylt   CeedOperator.  For passive fields, a vector @arg v must be provided.  Passive
651d7b241e6Sjeremylt   fields can inputs or outputs (updated in-place when operator is applied).
652d7b241e6Sjeremylt 
653d7b241e6Sjeremylt   Active fields must be specified using this function, but their data (in a
654d7b241e6Sjeremylt   CeedVector) is passed in CeedOperatorApply().  There can be at most one active
655d7b241e6Sjeremylt   input and at most one active output.
656d7b241e6Sjeremylt 
6578c91a0c9SJeremy L Thompson   @param op          CeedOperator on which to provide the field
658d1d35e2fSjeremylt   @param field_name  Name of the field (to be matched with the name used by
6598795c945Sjeremylt                        CeedQFunction)
660b11c1e72Sjeremylt   @param r           CeedElemRestriction
6614cc79fe7SJed Brown   @param b           CeedBasis in which the field resides or @ref CEED_BASIS_COLLOCATED
662b11c1e72Sjeremylt                        if collocated with quadrature points
6634cc79fe7SJed Brown   @param v           CeedVector to be used by CeedOperator or @ref CEED_VECTOR_ACTIVE
6644cc79fe7SJed Brown                        if field is active or @ref CEED_VECTOR_NONE if using
6654cc79fe7SJed Brown                        @ref CEED_EVAL_WEIGHT in the QFunction
666b11c1e72Sjeremylt 
667b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
668dfdf5a53Sjeremylt 
6697a982d89SJeremy L. Thompson   @ref User
670b11c1e72Sjeremylt **/
671d1d35e2fSjeremylt int CeedOperatorSetField(CeedOperator op, const char *field_name,
672a8d32208Sjeremylt                          CeedElemRestriction r, CeedBasis b, CeedVector v) {
673d7b241e6Sjeremylt   int ierr;
674f04ea552SJeremy L Thompson   if (op->is_composite)
675c042f62fSJeremy L Thompson     // LCOV_EXCL_START
676e1e9e29dSJed Brown     return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
677e15f9bd0SJeremy L Thompson                      "Cannot add field to composite operator.");
678c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
679f04ea552SJeremy L Thompson   if (op->is_immutable)
680f04ea552SJeremy L Thompson     // LCOV_EXCL_START
681f04ea552SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MAJOR,
682f04ea552SJeremy L Thompson                      "Operator cannot be changed after set as immutable");
683f04ea552SJeremy L Thompson   // LCOV_EXCL_STOP
6848b067b84SJed Brown   if (!r)
685c042f62fSJeremy L Thompson     // LCOV_EXCL_START
686e1e9e29dSJed Brown     return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
687c042f62fSJeremy L Thompson                      "ElemRestriction r for field \"%s\" must be non-NULL.",
688d1d35e2fSjeremylt                      field_name);
689c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
6908b067b84SJed Brown   if (!b)
691c042f62fSJeremy L Thompson     // LCOV_EXCL_START
692e1e9e29dSJed Brown     return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
693e15f9bd0SJeremy L Thompson                      "Basis b for field \"%s\" must be non-NULL.",
694d1d35e2fSjeremylt                      field_name);
695c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
6968b067b84SJed Brown   if (!v)
697c042f62fSJeremy L Thompson     // LCOV_EXCL_START
698e1e9e29dSJed Brown     return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE,
699e15f9bd0SJeremy L Thompson                      "Vector v for field \"%s\" must be non-NULL.",
700d1d35e2fSjeremylt                      field_name);
701c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
70252d6035fSJeremy L Thompson 
703d1d35e2fSjeremylt   CeedInt num_elem;
704d1d35e2fSjeremylt   ierr = CeedElemRestrictionGetNumElements(r, &num_elem); CeedChk(ierr);
705d1d35e2fSjeremylt   if (r != CEED_ELEMRESTRICTION_NONE && op->has_restriction &&
706d1d35e2fSjeremylt       op->num_elem != num_elem)
707c042f62fSJeremy L Thompson     // LCOV_EXCL_START
708e15f9bd0SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_DIMENSION,
7091d102b48SJeremy L Thompson                      "ElemRestriction with %d elements incompatible with prior "
710d1d35e2fSjeremylt                      "%d elements", num_elem, op->num_elem);
711c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
712d7b241e6Sjeremylt 
71378464608Sjeremylt   CeedInt num_qpts = 0;
714e15f9bd0SJeremy L Thompson   if (b != CEED_BASIS_COLLOCATED) {
715d1d35e2fSjeremylt     ierr = CeedBasisGetNumQuadraturePoints(b, &num_qpts); CeedChk(ierr);
716d1d35e2fSjeremylt     if (op->num_qpts && op->num_qpts != num_qpts)
717c042f62fSJeremy L Thompson       // LCOV_EXCL_START
718e15f9bd0SJeremy L Thompson       return CeedError(op->ceed, CEED_ERROR_DIMENSION,
719e15f9bd0SJeremy L Thompson                        "Basis with %d quadrature points "
720d1d35e2fSjeremylt                        "incompatible with prior %d points", num_qpts,
721d1d35e2fSjeremylt                        op->num_qpts);
722c042f62fSJeremy L Thompson     // LCOV_EXCL_STOP
723d7b241e6Sjeremylt   }
724d1d35e2fSjeremylt   CeedQFunctionField qf_field;
725d1d35e2fSjeremylt   CeedOperatorField *op_field;
726d1d35e2fSjeremylt   for (CeedInt i=0; i<op->qf->num_input_fields; i++) {
727d1d35e2fSjeremylt     if (!strcmp(field_name, (*op->qf->input_fields[i]).field_name)) {
728d1d35e2fSjeremylt       qf_field = op->qf->input_fields[i];
729d1d35e2fSjeremylt       op_field = &op->input_fields[i];
730d7b241e6Sjeremylt       goto found;
731d7b241e6Sjeremylt     }
732d7b241e6Sjeremylt   }
733d1d35e2fSjeremylt   for (CeedInt i=0; i<op->qf->num_output_fields; i++) {
734d1d35e2fSjeremylt     if (!strcmp(field_name, (*op->qf->output_fields[i]).field_name)) {
735d1d35e2fSjeremylt       qf_field = op->qf->output_fields[i];
736d1d35e2fSjeremylt       op_field = &op->output_fields[i];
737d7b241e6Sjeremylt       goto found;
738d7b241e6Sjeremylt     }
739d7b241e6Sjeremylt   }
740c042f62fSJeremy L Thompson   // LCOV_EXCL_START
741e15f9bd0SJeremy L Thompson   return CeedError(op->ceed, CEED_ERROR_INCOMPLETE,
742e15f9bd0SJeremy L Thompson                    "QFunction has no knowledge of field '%s'",
743d1d35e2fSjeremylt                    field_name);
744c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
745d7b241e6Sjeremylt found:
746d1d35e2fSjeremylt   ierr = CeedOperatorCheckField(op->ceed, qf_field, r, b); CeedChk(ierr);
747d1d35e2fSjeremylt   ierr = CeedCalloc(1, op_field); CeedChk(ierr);
748e15f9bd0SJeremy L Thompson 
749d1d35e2fSjeremylt   (*op_field)->vec = v;
750e15f9bd0SJeremy L Thompson   if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) {
7519560d06aSjeremylt     ierr = CeedVectorReference(v); CeedChk(ierr);
752e15f9bd0SJeremy L Thompson   }
753e15f9bd0SJeremy L Thompson 
754d1d35e2fSjeremylt   (*op_field)->elem_restr = r;
7559560d06aSjeremylt   ierr = CeedElemRestrictionReference(r); CeedChk(ierr);
756e15f9bd0SJeremy L Thompson   if (r != CEED_ELEMRESTRICTION_NONE) {
757d1d35e2fSjeremylt     op->num_elem = num_elem;
758d1d35e2fSjeremylt     op->has_restriction = true; // Restriction set, but num_elem may be 0
759e15f9bd0SJeremy L Thompson   }
760d99fa3c5SJeremy L Thompson 
761d1d35e2fSjeremylt   (*op_field)->basis = b;
762e15f9bd0SJeremy L Thompson   if (b != CEED_BASIS_COLLOCATED) {
763cd4dfc48Sjeremylt     if (!op->num_qpts) {
764cd4dfc48Sjeremylt       ierr = CeedOperatorSetNumQuadraturePoints(op, num_qpts); CeedChk(ierr);
765cd4dfc48Sjeremylt     }
7669560d06aSjeremylt     ierr = CeedBasisReference(b); CeedChk(ierr);
767e15f9bd0SJeremy L Thompson   }
768e15f9bd0SJeremy L Thompson 
769d1d35e2fSjeremylt   op->num_fields += 1;
770d1d35e2fSjeremylt   size_t len = strlen(field_name);
771d99fa3c5SJeremy L Thompson   char *tmp;
772d99fa3c5SJeremy L Thompson   ierr = CeedCalloc(len+1, &tmp); CeedChk(ierr);
773d1d35e2fSjeremylt   memcpy(tmp, field_name, len+1);
774d1d35e2fSjeremylt   (*op_field)->field_name = tmp;
775e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
776d7b241e6Sjeremylt }
777d7b241e6Sjeremylt 
778d7b241e6Sjeremylt /**
77943bbe138SJeremy L Thompson   @brief Get the CeedOperatorFields of a CeedOperator
78043bbe138SJeremy L Thompson 
781f04ea552SJeremy L Thompson   Note: Calling this function asserts that setup is complete
782f04ea552SJeremy L Thompson           and sets the CeedOperator as immutable.
783f04ea552SJeremy L Thompson 
78443bbe138SJeremy L Thompson   @param op                  CeedOperator
78543bbe138SJeremy L Thompson   @param[out] input_fields   Variable to store input_fields
78643bbe138SJeremy L Thompson   @param[out] output_fields  Variable to store output_fields
78743bbe138SJeremy L Thompson 
78843bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
78943bbe138SJeremy L Thompson 
790e9b533fbSJeremy L Thompson   @ref Advanced
79143bbe138SJeremy L Thompson **/
79243bbe138SJeremy L Thompson int CeedOperatorGetFields(CeedOperator op, CeedInt *num_input_fields,
79343bbe138SJeremy L Thompson                           CeedOperatorField **input_fields,
79443bbe138SJeremy L Thompson                           CeedInt *num_output_fields,
79543bbe138SJeremy L Thompson                           CeedOperatorField **output_fields) {
796f04ea552SJeremy L Thompson   int ierr;
797f04ea552SJeremy L Thompson 
798f04ea552SJeremy L Thompson   if (op->is_composite)
79943bbe138SJeremy L Thompson     // LCOV_EXCL_START
80043bbe138SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
80143bbe138SJeremy L Thompson                      "Not defined for composite operator");
80243bbe138SJeremy L Thompson   // LCOV_EXCL_STOP
803f04ea552SJeremy L Thompson   ierr = CeedOperatorCheckReady(op); CeedChk(ierr);
80443bbe138SJeremy L Thompson 
80543bbe138SJeremy L Thompson   if (num_input_fields) *num_input_fields = op->qf->num_input_fields;
80643bbe138SJeremy L Thompson   if (input_fields) *input_fields = op->input_fields;
80743bbe138SJeremy L Thompson   if (num_output_fields) *num_output_fields = op->qf->num_output_fields;
80843bbe138SJeremy L Thompson   if (output_fields) *output_fields = op->output_fields;
80943bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
81043bbe138SJeremy L Thompson }
81143bbe138SJeremy L Thompson 
81243bbe138SJeremy L Thompson /**
81328567f8fSJeremy L Thompson   @brief Get the name of a CeedOperatorField
81428567f8fSJeremy L Thompson 
81528567f8fSJeremy L Thompson   @param op_field         CeedOperatorField
81628567f8fSJeremy L Thompson   @param[out] field_name  Variable to store the field name
81728567f8fSJeremy L Thompson 
81828567f8fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
81928567f8fSJeremy L Thompson 
820e9b533fbSJeremy L Thompson   @ref Advanced
82128567f8fSJeremy L Thompson **/
82228567f8fSJeremy L Thompson int CeedOperatorFieldGetName(CeedOperatorField op_field, char **field_name) {
82328567f8fSJeremy L Thompson   *field_name = (char *)op_field->field_name;
82428567f8fSJeremy L Thompson   return CEED_ERROR_SUCCESS;
82528567f8fSJeremy L Thompson }
82628567f8fSJeremy L Thompson 
82728567f8fSJeremy L Thompson /**
82843bbe138SJeremy L Thompson   @brief Get the CeedElemRestriction of a CeedOperatorField
82943bbe138SJeremy L Thompson 
83043bbe138SJeremy L Thompson   @param op_field   CeedOperatorField
83143bbe138SJeremy L Thompson   @param[out] rstr  Variable to store CeedElemRestriction
83243bbe138SJeremy L Thompson 
83343bbe138SJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
83443bbe138SJeremy L Thompson 
835e9b533fbSJeremy L Thompson   @ref Advanced
83643bbe138SJeremy L Thompson **/
83743bbe138SJeremy L Thompson int CeedOperatorFieldGetElemRestriction(CeedOperatorField op_field,
83843bbe138SJeremy L Thompson                                         CeedElemRestriction *rstr) {
83943bbe138SJeremy L Thompson   *rstr = op_field->elem_restr;
84043bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
84143bbe138SJeremy L Thompson }
84243bbe138SJeremy L Thompson 
84343bbe138SJeremy L Thompson /**
84443bbe138SJeremy L Thompson   @brief Get the CeedBasis of a CeedOperatorField
84543bbe138SJeremy L Thompson 
84643bbe138SJeremy L Thompson   @param op_field    CeedOperatorField
84743bbe138SJeremy L Thompson   @param[out] basis  Variable to store CeedBasis
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 CeedOperatorFieldGetBasis(CeedOperatorField op_field, CeedBasis *basis) {
85443bbe138SJeremy L Thompson   *basis = op_field->basis;
85543bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
85643bbe138SJeremy L Thompson }
85743bbe138SJeremy L Thompson 
85843bbe138SJeremy L Thompson /**
85943bbe138SJeremy L Thompson   @brief Get the CeedVector of a CeedOperatorField
86043bbe138SJeremy L Thompson 
86143bbe138SJeremy L Thompson   @param op_field  CeedOperatorField
86243bbe138SJeremy L Thompson   @param[out] vec  Variable to store CeedVector
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 CeedOperatorFieldGetVector(CeedOperatorField op_field, CeedVector *vec) {
86943bbe138SJeremy L Thompson   *vec = op_field->vec;
87043bbe138SJeremy L Thompson   return CEED_ERROR_SUCCESS;
87143bbe138SJeremy L Thompson }
87243bbe138SJeremy L Thompson 
87343bbe138SJeremy L Thompson /**
87452d6035fSJeremy L Thompson   @brief Add a sub-operator to a composite CeedOperator
875288c0443SJeremy L Thompson 
876d1d35e2fSjeremylt   @param[out] composite_op  Composite CeedOperator
877d1d35e2fSjeremylt   @param      sub_op        Sub-operator CeedOperator
87852d6035fSJeremy L Thompson 
87952d6035fSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
88052d6035fSJeremy L Thompson 
8817a982d89SJeremy L. Thompson   @ref User
88252d6035fSJeremy L Thompson  */
883d1d35e2fSjeremylt int CeedCompositeOperatorAddSub(CeedOperator composite_op,
884d1d35e2fSjeremylt                                 CeedOperator sub_op) {
88534359f16Sjeremylt   int ierr;
88634359f16Sjeremylt 
887f04ea552SJeremy L Thompson   if (!composite_op->is_composite)
888c042f62fSJeremy L Thompson     // LCOV_EXCL_START
889d1d35e2fSjeremylt     return CeedError(composite_op->ceed, CEED_ERROR_MINOR,
890e2f04181SAndrew T. Barker                      "CeedOperator is not a composite operator");
891c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
89252d6035fSJeremy L Thompson 
893d1d35e2fSjeremylt   if (composite_op->num_suboperators == CEED_COMPOSITE_MAX)
894c042f62fSJeremy L Thompson     // LCOV_EXCL_START
895d1d35e2fSjeremylt     return CeedError(composite_op->ceed, CEED_ERROR_UNSUPPORTED,
896d1d35e2fSjeremylt                      "Cannot add additional sub_operators");
897c042f62fSJeremy L Thompson   // LCOV_EXCL_STOP
898f04ea552SJeremy L Thompson   if (composite_op->is_immutable)
899f04ea552SJeremy L Thompson     // LCOV_EXCL_START
900f04ea552SJeremy L Thompson     return CeedError(composite_op->ceed, CEED_ERROR_MAJOR,
901f04ea552SJeremy L Thompson                      "Operator cannot be changed after set as immutable");
902f04ea552SJeremy L Thompson   // LCOV_EXCL_STOP
90352d6035fSJeremy L Thompson 
904d1d35e2fSjeremylt   composite_op->sub_operators[composite_op->num_suboperators] = sub_op;
9059560d06aSjeremylt   ierr = CeedOperatorReference(sub_op); CeedChk(ierr);
906d1d35e2fSjeremylt   composite_op->num_suboperators++;
907e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
90852d6035fSJeremy L Thompson }
90952d6035fSJeremy L Thompson 
91052d6035fSJeremy L Thompson /**
911cd4dfc48Sjeremylt   @brief Set the number of quadrature points associated with a CeedOperator.
912cd4dfc48Sjeremylt            This should be used when creating a CeedOperator where every
913cd4dfc48Sjeremylt            field has a collocated basis. This function cannot be used for
914cd4dfc48Sjeremylt            composite CeedOperators.
915cd4dfc48Sjeremylt 
916cd4dfc48Sjeremylt   @param op        CeedOperator
917cd4dfc48Sjeremylt   @param num_qpts  Number of quadrature points to set
918cd4dfc48Sjeremylt 
919cd4dfc48Sjeremylt   @return An error code: 0 - success, otherwise - failure
920cd4dfc48Sjeremylt 
921e9b533fbSJeremy L Thompson   @ref Advanced
922cd4dfc48Sjeremylt **/
923cd4dfc48Sjeremylt 
924cd4dfc48Sjeremylt int CeedOperatorSetNumQuadraturePoints(CeedOperator op, CeedInt num_qpts) {
925f04ea552SJeremy L Thompson   if (op->is_composite)
926cd4dfc48Sjeremylt     // LCOV_EXCL_START
927cd4dfc48Sjeremylt     return CeedError(op->ceed, CEED_ERROR_MINOR,
928cd4dfc48Sjeremylt                      "Not defined for composite operator");
929cd4dfc48Sjeremylt   // LCOV_EXCL_STOP
930cd4dfc48Sjeremylt   if (op->num_qpts)
931cd4dfc48Sjeremylt     // LCOV_EXCL_START
932cd4dfc48Sjeremylt     return CeedError(op->ceed, CEED_ERROR_MINOR,
933cd4dfc48Sjeremylt                      "Number of quadrature points already defined");
934cd4dfc48Sjeremylt   // LCOV_EXCL_STOP
935f04ea552SJeremy L Thompson   if (op->is_immutable)
936f04ea552SJeremy L Thompson     // LCOV_EXCL_START
937f04ea552SJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MAJOR,
938f04ea552SJeremy L Thompson                      "Operator cannot be changed after set as immutable");
939f04ea552SJeremy L Thompson   // LCOV_EXCL_STOP
940cd4dfc48Sjeremylt 
941cd4dfc48Sjeremylt   op->num_qpts = num_qpts;
942cd4dfc48Sjeremylt   return CEED_ERROR_SUCCESS;
943cd4dfc48Sjeremylt }
944cd4dfc48Sjeremylt 
945cd4dfc48Sjeremylt /**
9467a982d89SJeremy L. Thompson   @brief View a CeedOperator
9477a982d89SJeremy L. Thompson 
9487a982d89SJeremy L. Thompson   @param[in] op      CeedOperator to view
9497a982d89SJeremy L. Thompson   @param[in] stream  Stream to write; typically stdout/stderr or a file
9507a982d89SJeremy L. Thompson 
9517a982d89SJeremy L. Thompson   @return Error code: 0 - success, otherwise - failure
9527a982d89SJeremy L. Thompson 
9537a982d89SJeremy L. Thompson   @ref User
9547a982d89SJeremy L. Thompson **/
9557a982d89SJeremy L. Thompson int CeedOperatorView(CeedOperator op, FILE *stream) {
9567a982d89SJeremy L. Thompson   int ierr;
9577a982d89SJeremy L. Thompson 
958f04ea552SJeremy L Thompson   if (op->is_composite) {
9597a982d89SJeremy L. Thompson     fprintf(stream, "Composite CeedOperator\n");
9607a982d89SJeremy L. Thompson 
961d1d35e2fSjeremylt     for (CeedInt i=0; i<op->num_suboperators; i++) {
9627a982d89SJeremy L. Thompson       fprintf(stream, "  SubOperator [%d]:\n", i);
963d1d35e2fSjeremylt       ierr = CeedOperatorSingleView(op->sub_operators[i], 1, stream);
9647a982d89SJeremy L. Thompson       CeedChk(ierr);
9657a982d89SJeremy L. Thompson     }
9667a982d89SJeremy L. Thompson   } else {
9677a982d89SJeremy L. Thompson     fprintf(stream, "CeedOperator\n");
9687a982d89SJeremy L. Thompson     ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr);
9697a982d89SJeremy L. Thompson   }
970e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
9717a982d89SJeremy L. Thompson }
9723bd813ffSjeremylt 
9733bd813ffSjeremylt /**
974b7c9bbdaSJeremy L Thompson   @brief Get the Ceed associated with a CeedOperator
975b7c9bbdaSJeremy L Thompson 
976b7c9bbdaSJeremy L Thompson   @param op         CeedOperator
977b7c9bbdaSJeremy L Thompson   @param[out] ceed  Variable to store Ceed
978b7c9bbdaSJeremy L Thompson 
979b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
980b7c9bbdaSJeremy L Thompson 
981b7c9bbdaSJeremy L Thompson   @ref Advanced
982b7c9bbdaSJeremy L Thompson **/
983b7c9bbdaSJeremy L Thompson int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) {
984b7c9bbdaSJeremy L Thompson   *ceed = op->ceed;
985b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
986b7c9bbdaSJeremy L Thompson }
987b7c9bbdaSJeremy L Thompson 
988b7c9bbdaSJeremy L Thompson /**
989b7c9bbdaSJeremy L Thompson   @brief Get the number of elements associated with a CeedOperator
990b7c9bbdaSJeremy L Thompson 
991b7c9bbdaSJeremy L Thompson   @param op             CeedOperator
992b7c9bbdaSJeremy L Thompson   @param[out] num_elem  Variable to store number of elements
993b7c9bbdaSJeremy L Thompson 
994b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
995b7c9bbdaSJeremy L Thompson 
996b7c9bbdaSJeremy L Thompson   @ref Advanced
997b7c9bbdaSJeremy L Thompson **/
998b7c9bbdaSJeremy L Thompson int CeedOperatorGetNumElements(CeedOperator op, CeedInt *num_elem) {
999b7c9bbdaSJeremy L Thompson   if (op->is_composite)
1000b7c9bbdaSJeremy L Thompson     // LCOV_EXCL_START
1001b7c9bbdaSJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
1002b7c9bbdaSJeremy L Thompson                      "Not defined for composite operator");
1003b7c9bbdaSJeremy L Thompson   // LCOV_EXCL_STOP
1004b7c9bbdaSJeremy L Thompson 
1005b7c9bbdaSJeremy L Thompson   *num_elem = op->num_elem;
1006b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1007b7c9bbdaSJeremy L Thompson }
1008b7c9bbdaSJeremy L Thompson 
1009b7c9bbdaSJeremy L Thompson /**
1010b7c9bbdaSJeremy L Thompson   @brief Get the number of quadrature points associated with a CeedOperator
1011b7c9bbdaSJeremy L Thompson 
1012b7c9bbdaSJeremy L Thompson   @param op             CeedOperator
1013b7c9bbdaSJeremy L Thompson   @param[out] num_qpts  Variable to store vector number of quadrature points
1014b7c9bbdaSJeremy L Thompson 
1015b7c9bbdaSJeremy L Thompson   @return An error code: 0 - success, otherwise - failure
1016b7c9bbdaSJeremy L Thompson 
1017b7c9bbdaSJeremy L Thompson   @ref Advanced
1018b7c9bbdaSJeremy L Thompson **/
1019b7c9bbdaSJeremy L Thompson int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *num_qpts) {
1020b7c9bbdaSJeremy L Thompson   if (op->is_composite)
1021b7c9bbdaSJeremy L Thompson     // LCOV_EXCL_START
1022b7c9bbdaSJeremy L Thompson     return CeedError(op->ceed, CEED_ERROR_MINOR,
1023b7c9bbdaSJeremy L Thompson                      "Not defined for composite operator");
1024b7c9bbdaSJeremy L Thompson   // LCOV_EXCL_STOP
1025b7c9bbdaSJeremy L Thompson 
1026b7c9bbdaSJeremy L Thompson   *num_qpts = op->num_qpts;
1027b7c9bbdaSJeremy L Thompson   return CEED_ERROR_SUCCESS;
1028b7c9bbdaSJeremy L Thompson }
1029b7c9bbdaSJeremy L Thompson 
1030b7c9bbdaSJeremy L Thompson /**
10313bd813ffSjeremylt   @brief Apply CeedOperator to a vector
1032d7b241e6Sjeremylt 
1033d7b241e6Sjeremylt   This computes the action of the operator on the specified (active) input,
1034d7b241e6Sjeremylt   yielding its (active) output.  All inputs and outputs must be specified using
1035d7b241e6Sjeremylt   CeedOperatorSetField().
1036d7b241e6Sjeremylt 
1037f04ea552SJeremy L Thompson   Note: Calling this function asserts that setup is complete
1038f04ea552SJeremy L Thompson           and sets the CeedOperator as immutable.
1039f04ea552SJeremy L Thompson 
1040d7b241e6Sjeremylt   @param op        CeedOperator to apply
10414cc79fe7SJed Brown   @param[in] in    CeedVector containing input state or @ref CEED_VECTOR_NONE if
104234138859Sjeremylt                      there are no active inputs
1043b11c1e72Sjeremylt   @param[out] out  CeedVector to store result of applying operator (must be
10444cc79fe7SJed Brown                      distinct from @a in) or @ref CEED_VECTOR_NONE if there are no
104534138859Sjeremylt                      active outputs
1046d7b241e6Sjeremylt   @param request   Address of CeedRequest for non-blocking completion, else
10474cc79fe7SJed Brown                      @ref CEED_REQUEST_IMMEDIATE
1048b11c1e72Sjeremylt 
1049b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1050dfdf5a53Sjeremylt 
10517a982d89SJeremy L. Thompson   @ref User
1052b11c1e72Sjeremylt **/
1053692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out,
1054692c2638Sjeremylt                       CeedRequest *request) {
1055d7b241e6Sjeremylt   int ierr;
1056e2f04181SAndrew T. Barker   ierr = CeedOperatorCheckReady(op); CeedChk(ierr);
1057d7b241e6Sjeremylt 
1058d1d35e2fSjeremylt   if (op->num_elem)  {
1059250756a7Sjeremylt     // Standard Operator
1060cae8b89aSjeremylt     if (op->Apply) {
1061250756a7Sjeremylt       ierr = op->Apply(op, in, out, request); CeedChk(ierr);
1062cae8b89aSjeremylt     } else {
1063cae8b89aSjeremylt       // Zero all output vectors
1064250756a7Sjeremylt       CeedQFunction qf = op->qf;
1065d1d35e2fSjeremylt       for (CeedInt i=0; i<qf->num_output_fields; i++) {
1066d1d35e2fSjeremylt         CeedVector vec = op->output_fields[i]->vec;
1067cae8b89aSjeremylt         if (vec == CEED_VECTOR_ACTIVE)
1068cae8b89aSjeremylt           vec = out;
1069cae8b89aSjeremylt         if (vec != CEED_VECTOR_NONE) {
1070cae8b89aSjeremylt           ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr);
1071cae8b89aSjeremylt         }
1072cae8b89aSjeremylt       }
1073250756a7Sjeremylt       // Apply
1074250756a7Sjeremylt       ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr);
1075250756a7Sjeremylt     }
1076f04ea552SJeremy L Thompson   } else if (op->is_composite) {
1077250756a7Sjeremylt     // Composite Operator
1078250756a7Sjeremylt     if (op->ApplyComposite) {
1079250756a7Sjeremylt       ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr);
1080250756a7Sjeremylt     } else {
1081d1d35e2fSjeremylt       CeedInt num_suboperators;
1082d1d35e2fSjeremylt       ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr);
1083d1d35e2fSjeremylt       CeedOperator *sub_operators;
1084d1d35e2fSjeremylt       ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr);
1085250756a7Sjeremylt 
1086250756a7Sjeremylt       // Zero all output vectors
1087250756a7Sjeremylt       if (out != CEED_VECTOR_NONE) {
1088cae8b89aSjeremylt         ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr);
1089cae8b89aSjeremylt       }
1090d1d35e2fSjeremylt       for (CeedInt i=0; i<num_suboperators; i++) {
1091d1d35e2fSjeremylt         for (CeedInt j=0; j<sub_operators[i]->qf->num_output_fields; j++) {
1092d1d35e2fSjeremylt           CeedVector vec = sub_operators[i]->output_fields[j]->vec;
1093250756a7Sjeremylt           if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) {
1094250756a7Sjeremylt             ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr);
1095250756a7Sjeremylt           }
1096250756a7Sjeremylt         }
1097250756a7Sjeremylt       }
1098250756a7Sjeremylt       // Apply
1099d1d35e2fSjeremylt       for (CeedInt i=0; i<op->num_suboperators; i++) {
1100d1d35e2fSjeremylt         ierr = CeedOperatorApplyAdd(op->sub_operators[i], in, out, request);
1101cae8b89aSjeremylt         CeedChk(ierr);
1102cae8b89aSjeremylt       }
1103cae8b89aSjeremylt     }
1104250756a7Sjeremylt   }
1105e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1106cae8b89aSjeremylt }
1107cae8b89aSjeremylt 
1108cae8b89aSjeremylt /**
1109cae8b89aSjeremylt   @brief Apply CeedOperator to a vector and add result to output vector
1110cae8b89aSjeremylt 
1111cae8b89aSjeremylt   This computes the action of the operator on the specified (active) input,
1112cae8b89aSjeremylt   yielding its (active) output.  All inputs and outputs must be specified using
1113cae8b89aSjeremylt   CeedOperatorSetField().
1114cae8b89aSjeremylt 
1115cae8b89aSjeremylt   @param op        CeedOperator to apply
1116cae8b89aSjeremylt   @param[in] in    CeedVector containing input state or NULL if there are no
1117cae8b89aSjeremylt                      active inputs
1118cae8b89aSjeremylt   @param[out] out  CeedVector to sum in result of applying operator (must be
1119cae8b89aSjeremylt                      distinct from @a in) or NULL if there are no active outputs
1120cae8b89aSjeremylt   @param request   Address of CeedRequest for non-blocking completion, else
11214cc79fe7SJed Brown                      @ref CEED_REQUEST_IMMEDIATE
1122cae8b89aSjeremylt 
1123cae8b89aSjeremylt   @return An error code: 0 - success, otherwise - failure
1124cae8b89aSjeremylt 
11257a982d89SJeremy L. Thompson   @ref User
1126cae8b89aSjeremylt **/
1127cae8b89aSjeremylt int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out,
1128cae8b89aSjeremylt                          CeedRequest *request) {
1129cae8b89aSjeremylt   int ierr;
1130e2f04181SAndrew T. Barker   ierr = CeedOperatorCheckReady(op); CeedChk(ierr);
1131cae8b89aSjeremylt 
1132d1d35e2fSjeremylt   if (op->num_elem)  {
1133250756a7Sjeremylt     // Standard Operator
1134250756a7Sjeremylt     ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr);
1135f04ea552SJeremy L Thompson   } else if (op->is_composite) {
1136250756a7Sjeremylt     // Composite Operator
1137250756a7Sjeremylt     if (op->ApplyAddComposite) {
1138250756a7Sjeremylt       ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr);
1139cae8b89aSjeremylt     } else {
1140d1d35e2fSjeremylt       CeedInt num_suboperators;
1141d1d35e2fSjeremylt       ierr = CeedOperatorGetNumSub(op, &num_suboperators); CeedChk(ierr);
1142d1d35e2fSjeremylt       CeedOperator *sub_operators;
1143d1d35e2fSjeremylt       ierr = CeedOperatorGetSubList(op, &sub_operators); CeedChk(ierr);
1144250756a7Sjeremylt 
1145d1d35e2fSjeremylt       for (CeedInt i=0; i<num_suboperators; i++) {
1146d1d35e2fSjeremylt         ierr = CeedOperatorApplyAdd(sub_operators[i], in, out, request);
1147cae8b89aSjeremylt         CeedChk(ierr);
11481d7d2407SJeremy L Thompson       }
1149250756a7Sjeremylt     }
1150250756a7Sjeremylt   }
1151e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1152d7b241e6Sjeremylt }
1153d7b241e6Sjeremylt 
1154d7b241e6Sjeremylt /**
1155b11c1e72Sjeremylt   @brief Destroy a CeedOperator
1156d7b241e6Sjeremylt 
1157d7b241e6Sjeremylt   @param op  CeedOperator to destroy
1158b11c1e72Sjeremylt 
1159b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
1160dfdf5a53Sjeremylt 
11617a982d89SJeremy L. Thompson   @ref User
1162b11c1e72Sjeremylt **/
1163d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) {
1164d7b241e6Sjeremylt   int ierr;
1165d7b241e6Sjeremylt 
1166d1d35e2fSjeremylt   if (!*op || --(*op)->ref_count > 0) return CEED_ERROR_SUCCESS;
1167d7b241e6Sjeremylt   if ((*op)->Destroy) {
1168d7b241e6Sjeremylt     ierr = (*op)->Destroy(*op); CeedChk(ierr);
1169d7b241e6Sjeremylt   }
1170fe2413ffSjeremylt   ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr);
1171fe2413ffSjeremylt   // Free fields
1172d1d35e2fSjeremylt   for (int i=0; i<(*op)->num_fields; i++)
1173d1d35e2fSjeremylt     if ((*op)->input_fields[i]) {
1174d1d35e2fSjeremylt       if ((*op)->input_fields[i]->elem_restr != CEED_ELEMRESTRICTION_NONE) {
1175d1d35e2fSjeremylt         ierr = CeedElemRestrictionDestroy(&(*op)->input_fields[i]->elem_restr);
117671352a93Sjeremylt         CeedChk(ierr);
117715910d16Sjeremylt       }
1178d1d35e2fSjeremylt       if ((*op)->input_fields[i]->basis != CEED_BASIS_COLLOCATED) {
1179d1d35e2fSjeremylt         ierr = CeedBasisDestroy(&(*op)->input_fields[i]->basis); CeedChk(ierr);
118071352a93Sjeremylt       }
1181d1d35e2fSjeremylt       if ((*op)->input_fields[i]->vec != CEED_VECTOR_ACTIVE &&
1182d1d35e2fSjeremylt           (*op)->input_fields[i]->vec != CEED_VECTOR_NONE ) {
1183d1d35e2fSjeremylt         ierr = CeedVectorDestroy(&(*op)->input_fields[i]->vec); CeedChk(ierr);
118471352a93Sjeremylt       }
1185d1d35e2fSjeremylt       ierr = CeedFree(&(*op)->input_fields[i]->field_name); CeedChk(ierr);
1186d1d35e2fSjeremylt       ierr = CeedFree(&(*op)->input_fields[i]); CeedChk(ierr);
1187fe2413ffSjeremylt     }
1188d1d35e2fSjeremylt   for (int i=0; i<(*op)->num_fields; i++)
1189d1d35e2fSjeremylt     if ((*op)->output_fields[i]) {
1190d1d35e2fSjeremylt       ierr = CeedElemRestrictionDestroy(&(*op)->output_fields[i]->elem_restr);
119171352a93Sjeremylt       CeedChk(ierr);
1192d1d35e2fSjeremylt       if ((*op)->output_fields[i]->basis != CEED_BASIS_COLLOCATED) {
1193d1d35e2fSjeremylt         ierr = CeedBasisDestroy(&(*op)->output_fields[i]->basis); CeedChk(ierr);
119471352a93Sjeremylt       }
1195d1d35e2fSjeremylt       if ((*op)->output_fields[i]->vec != CEED_VECTOR_ACTIVE &&
1196d1d35e2fSjeremylt           (*op)->output_fields[i]->vec != CEED_VECTOR_NONE ) {
1197d1d35e2fSjeremylt         ierr = CeedVectorDestroy(&(*op)->output_fields[i]->vec); CeedChk(ierr);
119871352a93Sjeremylt       }
1199d1d35e2fSjeremylt       ierr = CeedFree(&(*op)->output_fields[i]->field_name); CeedChk(ierr);
1200d1d35e2fSjeremylt       ierr = CeedFree(&(*op)->output_fields[i]); CeedChk(ierr);
1201fe2413ffSjeremylt     }
1202d1d35e2fSjeremylt   // Destroy sub_operators
1203d1d35e2fSjeremylt   for (int i=0; i<(*op)->num_suboperators; i++)
1204d1d35e2fSjeremylt     if ((*op)->sub_operators[i]) {
1205d1d35e2fSjeremylt       ierr = CeedOperatorDestroy(&(*op)->sub_operators[i]); CeedChk(ierr);
120652d6035fSJeremy L Thompson     }
1207d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr);
1208d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr);
1209d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr);
1210fe2413ffSjeremylt 
12115107b09fSJeremy L Thompson   // Destroy fallback
1212d1d35e2fSjeremylt   if ((*op)->op_fallback) {
1213d1d35e2fSjeremylt     ierr = (*op)->qf_fallback->Destroy((*op)->qf_fallback); CeedChk(ierr);
1214d1d35e2fSjeremylt     ierr = CeedFree(&(*op)->qf_fallback); CeedChk(ierr);
1215*70a7ffb3SJeremy L Thompson     ierr = CeedVectorDestroy(&(*op)->op_fallback->qf_assembled); CeedChk(ierr);
1216*70a7ffb3SJeremy L Thompson     ierr = CeedElemRestrictionDestroy(&(*op)->op_fallback->qf_assembled_rstr);
1217*70a7ffb3SJeremy L Thompson     CeedChk(ierr);
1218d1d35e2fSjeremylt     ierr = (*op)->op_fallback->Destroy((*op)->op_fallback); CeedChk(ierr);
1219d1d35e2fSjeremylt     ierr = CeedFree(&(*op)->op_fallback); CeedChk(ierr);
12205107b09fSJeremy L Thompson   }
12215107b09fSJeremy L Thompson 
1222*70a7ffb3SJeremy L Thompson   // Destroy QF assembly cache
1223*70a7ffb3SJeremy L Thompson   ierr = CeedVectorDestroy(&(*op)->qf_assembled); CeedChk(ierr);
1224*70a7ffb3SJeremy L Thompson   ierr = CeedElemRestrictionDestroy(&(*op)->qf_assembled_rstr); CeedChk(ierr);
1225*70a7ffb3SJeremy L Thompson 
1226d1d35e2fSjeremylt   ierr = CeedFree(&(*op)->input_fields); CeedChk(ierr);
1227d1d35e2fSjeremylt   ierr = CeedFree(&(*op)->output_fields); CeedChk(ierr);
1228d1d35e2fSjeremylt   ierr = CeedFree(&(*op)->sub_operators); CeedChk(ierr);
1229d7b241e6Sjeremylt   ierr = CeedFree(op); CeedChk(ierr);
1230e15f9bd0SJeremy L Thompson   return CEED_ERROR_SUCCESS;
1231d7b241e6Sjeremylt }
1232d7b241e6Sjeremylt 
1233d7b241e6Sjeremylt /// @}
1234