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