xref: /libCEED/interface/ceed-operator.c (revision 5fe0d4fa442f339208d7656a646e69da1442c2a1)
1 // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2 // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3 // reserved. See files LICENSE and NOTICE for details.
4 //
5 // This file is part of CEED, a collection of benchmarks, miniapps, software
6 // libraries and APIs for efficient high-order finite element and spectral
7 // element discretizations for exascale applications. For more information and
8 // source code availability see http://github.com/ceed.
9 //
10 // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11 // a collaborative effort of two U.S. Department of Energy organizations (Office
12 // of Science and the National Nuclear Security Administration) responsible for
13 // the planning and preparation of a capable exascale ecosystem, including
14 // software, applications, hardware, advanced system engineering and early
15 // testbed platforms, in support of the nation's exascale computing imperative.
16 
17 #include <ceed-impl.h>
18 #include <string.h>
19 
20 /// @file
21 /// Implementation of public CeedOperator interfaces
22 ///
23 /// @addtogroup CeedOperator
24 ///   @{
25 
26 /**
27   @brief Create an operator from element restriction, basis, and QFunction
28 
29   @param ceed    A Ceed object where the CeedOperator will be created
30   @param qf      QFunction defining the action of the operator at quadrature points
31   @param dqf     QFunction defining the action of the Jacobian of @a qf (or NULL)
32   @param dqfT    QFunction defining the action of the transpose of the Jacobian
33                    of @a qf (or NULL)
34   @param[out] op Address of the variable where the newly created
35                      CeedOperator will be stored
36 
37   @return An error code: 0 - success, otherwise - failure
38 
39   @ref Basic
40  */
41 int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf,
42                        CeedQFunction dqfT, CeedOperator *op) {
43   int ierr;
44 
45   if (!ceed->OperatorCreate) {
46     Ceed delegate;
47     ierr = CeedGetDelegate(ceed, &delegate); CeedChk(ierr);
48 
49     if (!delegate)
50       return CeedError(ceed, 1, "Backend does not support OperatorCreate");
51 
52     ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr);
53     return 0;
54   }
55 
56   ierr = CeedCalloc(1,op); CeedChk(ierr);
57   (*op)->ceed = ceed;
58   ceed->refcount++;
59   (*op)->refcount = 1;
60   (*op)->qf = qf;
61   qf->refcount++;
62   (*op)->dqf = dqf;
63   if (dqf) dqf->refcount++;
64   (*op)->dqfT = dqfT;
65   if (dqfT) dqfT->refcount++;
66   ierr = ceed->OperatorCreate(*op); CeedChk(ierr);
67   return 0;
68 }
69 
70 /**
71   @brief Provide a field to a CeedOperator for use by its CeedQFunction
72 
73   This function is used to specify both active and passive fields to a
74   CeedOperator.  For passive fields, a vector @arg v must be provided.  Passive
75   fields can inputs or outputs (updated in-place when operator is applied).
76 
77   Active fields must be specified using this function, but their data (in a
78   CeedVector) is passed in CeedOperatorApply().  There can be at most one active
79   input and at most one active output.
80 
81   @param op         Ceedoperator on which to provide the field
82   @param fieldname  Name of the field (to be matched with the name used by CeedQFunction)
83   @param r          CeedElemRestriction
84   @param b          CeedBasis in which the field resides or CEED_BASIS_COLLOCATED
85                       if collocated with quadrature points
86   @param v          CeedVector to be used by CeedOperator or CEED_VECTOR_ACTIVE
87                       if field is active or CEED_VECTOR_NONE if using
88                       CEED_EVAL_WEIGHT in the qfunction
89 
90   @return An error code: 0 - success, otherwise - failure
91 
92   @ref Basic
93 **/
94 int CeedOperatorSetField(CeedOperator op, const char *fieldname,
95                          CeedElemRestriction r, CeedBasis b,
96                          CeedVector v) {
97   int ierr;
98   CeedInt numelements;
99   ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr);
100   if (op->numelements && op->numelements != numelements)
101     return CeedError(op->ceed, 1,
102                      "ElemRestriction with %d elements incompatible with prior %d elements",
103                      numelements, op->numelements);
104   op->numelements = numelements;
105 
106   if (b != CEED_BASIS_COLLOCATED) {
107     CeedInt numqpoints;
108     ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr);
109     if (op->numqpoints && op->numqpoints != numqpoints)
110       return CeedError(op->ceed, 1,
111                        "Basis with %d quadrature points incompatible with prior %d points",
112                        numqpoints, op->numqpoints);
113     op->numqpoints = numqpoints;
114   }
115   struct CeedOperatorField *ofield;
116   for (CeedInt i=0; i<op->qf->numinputfields; i++) {
117     if (!strcmp(fieldname, op->qf->inputfields[i].fieldname)) {
118       ofield = &op->inputfields[i];
119       goto found;
120     }
121   }
122   for (CeedInt i=0; i<op->qf->numoutputfields; i++) {
123     if (!strcmp(fieldname, op->qf->outputfields[i].fieldname)) {
124       ofield = &op->outputfields[i];
125       goto found;
126     }
127   }
128   return CeedError(op->ceed, 1, "QFunction has no knowledge of field '%s'",
129                    fieldname);
130 found:
131   ofield->Erestrict = r;
132   ofield->basis = b;
133   ofield->vec = v;
134   op->nfields += 1;
135   return 0;
136 }
137 
138 /**
139   @brief Apply CeedOperator to a vector
140 
141   This computes the action of the operator on the specified (active) input,
142   yielding its (active) output.  All inputs and outputs must be specified using
143   CeedOperatorSetField().
144 
145   @param op        CeedOperator to apply
146   @param[in] in    CeedVector containing input state or NULL if there are no
147                      active inputs
148   @param[out] out  CeedVector to store result of applying operator (must be
149                      distinct from @a in) or NULL if there are no active outputs
150   @param request   Address of CeedRequest for non-blocking completion, else
151                      CEED_REQUEST_IMMEDIATE
152 
153   @return An error code: 0 - success, otherwise - failure
154 
155   @ref Basic
156 **/
157 int CeedOperatorApply(CeedOperator op, CeedVector in,
158                       CeedVector out, CeedRequest *request) {
159   int ierr;
160   Ceed ceed = op->ceed;
161   CeedQFunction qf = op->qf;
162 
163   if (op->nfields == 0) return CeedError(ceed, 1, "No operator fields set");
164   if (op->nfields < qf->numinputfields + qf->numoutputfields) return CeedError(
165           ceed, 1, "Not all operator fields set");
166   if (op->numelements == 0) return CeedError(ceed, 1,
167                                      "At least one restriction required");
168   if (op->numqpoints == 0) return CeedError(ceed, 1,
169                                     "At least one non-collocated basis required");
170   ierr = op->Apply(op, in, out, request); CeedChk(ierr);
171   return 0;
172 }
173 
174 /**
175   @brief Destroy a CeedOperator
176 
177   @param op CeedOperator to destroy
178 
179   @return An error code: 0 - success, otherwise - failure
180 
181   @ref Basic
182 **/
183 int CeedOperatorDestroy(CeedOperator *op) {
184   int ierr;
185 
186   if (!*op || --(*op)->refcount > 0) return 0;
187   if ((*op)->Destroy) {
188     ierr = (*op)->Destroy(*op); CeedChk(ierr);
189   }
190   ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr);
191   ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr);
192   ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr);
193   ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr);
194   ierr = CeedFree(op); CeedChk(ierr);
195   return 0;
196 }
197 
198 /// @}
199