xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-operator.c (revision 783c99b3f03c04aed3140873345e25fc3bab2ee4)
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 
17d7b241e6Sjeremylt #include <ceed-impl.h>
18d7b241e6Sjeremylt #include <string.h>
19d7b241e6Sjeremylt 
20dfdf5a53Sjeremylt /// @file
21dfdf5a53Sjeremylt /// Implementation of public CeedOperator interfaces
22dfdf5a53Sjeremylt ///
23dfdf5a53Sjeremylt /// @addtogroup CeedOperator
24dfdf5a53Sjeremylt ///   @{
25d7b241e6Sjeremylt 
26d7b241e6Sjeremylt /**
27b11c1e72Sjeremylt   @brief Create an operator from element restriction, basis, and QFunction
28d7b241e6Sjeremylt 
29b11c1e72Sjeremylt   @param ceed    A Ceed object where the CeedOperator will be created
30d7b241e6Sjeremylt   @param qf      QFunction defining the action of the operator at quadrature points
31d7b241e6Sjeremylt   @param dqf     QFunction defining the action of the Jacobian of @a qf (or NULL)
32d7b241e6Sjeremylt   @param dqfT    QFunction defining the action of the transpose of the Jacobian
33d7b241e6Sjeremylt                    of @a qf (or NULL)
34b11c1e72Sjeremylt   @param[out] op Address of the variable where the newly created
35b11c1e72Sjeremylt                      CeedOperator will be stored
36b11c1e72Sjeremylt 
37b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
38dfdf5a53Sjeremylt 
39dfdf5a53Sjeremylt   @ref Basic
40d7b241e6Sjeremylt  */
41d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf,
42d7b241e6Sjeremylt                        CeedQFunction dqfT, CeedOperator *op) {
43d7b241e6Sjeremylt   int ierr;
44d7b241e6Sjeremylt 
45d7b241e6Sjeremylt   if (!ceed->OperatorCreate) return CeedError(ceed, 1,
46d7b241e6Sjeremylt                                       "Backend does not support OperatorCreate");
47d7b241e6Sjeremylt   ierr = CeedCalloc(1,op); CeedChk(ierr);
48d7b241e6Sjeremylt   (*op)->ceed = ceed;
49d7b241e6Sjeremylt   ceed->refcount++;
50d7b241e6Sjeremylt   (*op)->refcount = 1;
51d7b241e6Sjeremylt   (*op)->qf = qf;
52d7b241e6Sjeremylt   qf->refcount++;
53d7b241e6Sjeremylt   (*op)->dqf = dqf;
54d7b241e6Sjeremylt   if (dqf) dqf->refcount++;
55d7b241e6Sjeremylt   (*op)->dqfT = dqfT;
56d7b241e6Sjeremylt   if (dqfT) dqfT->refcount++;
57d7b241e6Sjeremylt   ierr = ceed->OperatorCreate(*op); CeedChk(ierr);
58d7b241e6Sjeremylt   return 0;
59d7b241e6Sjeremylt }
60d7b241e6Sjeremylt 
61d7b241e6Sjeremylt /**
62b11c1e72Sjeremylt   @brief Provide a field to a CeedOperator for use by its CeedQFunction
63d7b241e6Sjeremylt 
64d7b241e6Sjeremylt   This function is used to specify both active and passive fields to a
65d7b241e6Sjeremylt   CeedOperator.  For passive fields, a vector @arg v must be provided.  Passive
66d7b241e6Sjeremylt   fields can inputs or outputs (updated in-place when operator is applied).
67d7b241e6Sjeremylt 
68d7b241e6Sjeremylt   Active fields must be specified using this function, but their data (in a
69d7b241e6Sjeremylt   CeedVector) is passed in CeedOperatorApply().  There can be at most one active
70d7b241e6Sjeremylt   input and at most one active output.
71d7b241e6Sjeremylt 
72b11c1e72Sjeremylt   @param op         Ceedoperator on which to provide the field
73b11c1e72Sjeremylt   @param fieldname  Name of the field (to be matched with the name used by CeedQFunction)
74b11c1e72Sjeremylt   @param r          CeedElemRestriction
75*783c99b3SValeria Barra   @param b          CeedBasis in which the field resides or CEED_BASIS_COLLOCATED
76b11c1e72Sjeremylt                       if collocated with quadrature points
77b11c1e72Sjeremylt   @param v          CeedVector to be used by CeedOperator or CEED_VECTOR_ACTIVE
78b11c1e72Sjeremylt                       if field is active or CEED_VECTOR_NONE if using
79b11c1e72Sjeremylt                       CEED_EVAL_WEIGHT in the qfunction
80b11c1e72Sjeremylt 
81b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
82dfdf5a53Sjeremylt 
83dfdf5a53Sjeremylt   @ref Basic
84b11c1e72Sjeremylt **/
85d7b241e6Sjeremylt int CeedOperatorSetField(CeedOperator op, const char *fieldname,
86d7b241e6Sjeremylt                          CeedElemRestriction r, CeedBasis b,
87d7b241e6Sjeremylt                          CeedVector v) {
88d7b241e6Sjeremylt   int ierr;
89d7b241e6Sjeremylt   CeedInt numelements;
90d7b241e6Sjeremylt   ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr);
91d7b241e6Sjeremylt   if (op->numelements && op->numelements != numelements)
92d7b241e6Sjeremylt     return CeedError(op->ceed, 1,
93d7b241e6Sjeremylt                      "ElemRestriction with %d elements incompatible with prior %d elements",
94d7b241e6Sjeremylt                      numelements, op->numelements);
95d7b241e6Sjeremylt   op->numelements = numelements;
96d7b241e6Sjeremylt 
97*783c99b3SValeria Barra   if (b != CEED_BASIS_COLLOCATED) {
98d7b241e6Sjeremylt     CeedInt numqpoints;
99d7b241e6Sjeremylt     ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr);
100d7b241e6Sjeremylt     if (op->numqpoints && op->numqpoints != numqpoints)
101d7b241e6Sjeremylt       return CeedError(op->ceed, 1,
102d7b241e6Sjeremylt                        "Basis with %d quadrature points incompatible with prior %d points",
103d7b241e6Sjeremylt                        numqpoints, op->numqpoints);
104d7b241e6Sjeremylt     op->numqpoints = numqpoints;
105d7b241e6Sjeremylt   }
106d7b241e6Sjeremylt   struct CeedOperatorField *ofield;
107d7b241e6Sjeremylt   for (CeedInt i=0; i<op->qf->numinputfields; i++) {
108d7b241e6Sjeremylt     if (!strcmp(fieldname, op->qf->inputfields[i].fieldname)) {
109d7b241e6Sjeremylt       ofield = &op->inputfields[i];
110d7b241e6Sjeremylt       goto found;
111d7b241e6Sjeremylt     }
112d7b241e6Sjeremylt   }
113d7b241e6Sjeremylt   for (CeedInt i=0; i<op->qf->numoutputfields; i++) {
114d7b241e6Sjeremylt     if (!strcmp(fieldname, op->qf->outputfields[i].fieldname)) {
115d7b241e6Sjeremylt       ofield = &op->outputfields[i];
116d7b241e6Sjeremylt       goto found;
117d7b241e6Sjeremylt     }
118d7b241e6Sjeremylt   }
119d7b241e6Sjeremylt   return CeedError(op->ceed, 1, "QFunction has no knowledge of field '%s'",
120d7b241e6Sjeremylt                    fieldname);
121d7b241e6Sjeremylt found:
122d7b241e6Sjeremylt   ofield->Erestrict = r;
123d7b241e6Sjeremylt   ofield->basis = b;
124d7b241e6Sjeremylt   ofield->vec = v;
125d7b241e6Sjeremylt   op->nfields += 1;
126d7b241e6Sjeremylt   return 0;
127d7b241e6Sjeremylt }
128d7b241e6Sjeremylt 
129d7b241e6Sjeremylt /**
130b11c1e72Sjeremylt   @brief Apply CeedOperator to a vector
131d7b241e6Sjeremylt 
132d7b241e6Sjeremylt   This computes the action of the operator on the specified (active) input,
133d7b241e6Sjeremylt   yielding its (active) output.  All inputs and outputs must be specified using
134d7b241e6Sjeremylt   CeedOperatorSetField().
135d7b241e6Sjeremylt 
136d7b241e6Sjeremylt   @param op        CeedOperator to apply
137b11c1e72Sjeremylt   @param[in] in    CeedVector containing input state or NULL if there are no
138b11c1e72Sjeremylt                      active inputs
139b11c1e72Sjeremylt   @param[out] out  CeedVector to store result of applying operator (must be
140d7b241e6Sjeremylt                      distinct from @a in) or NULL if there are no active outputs
141d7b241e6Sjeremylt   @param request   Address of CeedRequest for non-blocking completion, else
142d7b241e6Sjeremylt                      CEED_REQUEST_IMMEDIATE
143b11c1e72Sjeremylt 
144b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
145dfdf5a53Sjeremylt 
146dfdf5a53Sjeremylt   @ref Basic
147b11c1e72Sjeremylt **/
148d7b241e6Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in,
149d7b241e6Sjeremylt                       CeedVector out, CeedRequest *request) {
150d7b241e6Sjeremylt   int ierr;
151d7b241e6Sjeremylt   Ceed ceed = op->ceed;
152d7b241e6Sjeremylt   CeedQFunction qf = op->qf;
153d7b241e6Sjeremylt 
154d7b241e6Sjeremylt   if (op->nfields == 0) return CeedError(ceed, 1, "No operator fields set");
155d7b241e6Sjeremylt   if (op->nfields < qf->numinputfields + qf->numoutputfields) return CeedError(
156d7b241e6Sjeremylt           ceed, 1, "Not all operator fields set");
157d7b241e6Sjeremylt   if (op->numelements == 0) return CeedError(ceed, 1,
158d7b241e6Sjeremylt                                      "At least one restriction required");
159d7b241e6Sjeremylt   if (op->numqpoints == 0) return CeedError(ceed, 1,
160*783c99b3SValeria Barra                                     "At least one non-collocated basis required");
161d7b241e6Sjeremylt   ierr = op->Apply(op, in, out, request); CeedChk(ierr);
162d7b241e6Sjeremylt   return 0;
163d7b241e6Sjeremylt }
164d7b241e6Sjeremylt 
165d7b241e6Sjeremylt /**
166b11c1e72Sjeremylt   @brief Destroy a CeedOperator
167d7b241e6Sjeremylt 
168d7b241e6Sjeremylt   @param op CeedOperator to destroy
169b11c1e72Sjeremylt 
170b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
171dfdf5a53Sjeremylt 
172dfdf5a53Sjeremylt   @ref Basic
173b11c1e72Sjeremylt **/
174d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) {
175d7b241e6Sjeremylt   int ierr;
176d7b241e6Sjeremylt 
177d7b241e6Sjeremylt   if (!*op || --(*op)->refcount > 0) return 0;
178d7b241e6Sjeremylt   if ((*op)->Destroy) {
179d7b241e6Sjeremylt     ierr = (*op)->Destroy(*op); CeedChk(ierr);
180d7b241e6Sjeremylt   }
181d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr);
182d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr);
183d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr);
184d7b241e6Sjeremylt   ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr);
185d7b241e6Sjeremylt   ierr = CeedFree(op); CeedChk(ierr);
186d7b241e6Sjeremylt   return 0;
187d7b241e6Sjeremylt }
188d7b241e6Sjeremylt 
189d7b241e6Sjeremylt /// @}
190