xref: /libCEED/rust/libceed-sys/c-src/interface/ceed-operator.c (revision b11c1e72297b0dbe2250cea5be89aa8490095155)
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 
20d7b241e6Sjeremylt /**
21d7b241e6Sjeremylt   @file
22d7b241e6Sjeremylt   Implementation of public CeedOperator interfaces
23d7b241e6Sjeremylt 
24d7b241e6Sjeremylt   @defgroup CeedOperator CeedOperator: composed FE-type operations on vectors
25d7b241e6Sjeremylt   @{
26d7b241e6Sjeremylt  */
27d7b241e6Sjeremylt 
28d7b241e6Sjeremylt /**
29*b11c1e72Sjeremylt   @brief Create an operator from element restriction, basis, and QFunction
30d7b241e6Sjeremylt 
31*b11c1e72Sjeremylt   @param ceed    A Ceed object where the CeedOperator will be created
32d7b241e6Sjeremylt   @param qf      QFunction defining the action of the operator at quadrature points
33d7b241e6Sjeremylt   @param dqf     QFunction defining the action of the Jacobian of @a qf (or NULL)
34d7b241e6Sjeremylt   @param dqfT    QFunction defining the action of the transpose of the Jacobian
35d7b241e6Sjeremylt                    of @a qf (or NULL)
36*b11c1e72Sjeremylt   @param[out] op Address of the variable where the newly created
37*b11c1e72Sjeremylt                      CeedOperator will be stored
38*b11c1e72Sjeremylt 
39*b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
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 /**
62*b11c1e72Sjeremylt   @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 
72*b11c1e72Sjeremylt   @param op         Ceedoperator on which to provide the field
73*b11c1e72Sjeremylt   @param fieldname  Name of the field (to be matched with the name used by CeedQFunction)
74*b11c1e72Sjeremylt   @param r          CeedElemRestriction
75*b11c1e72Sjeremylt   @param b          CeedBasis in which the field resides or CEED_BASIS_COLOCATED
76*b11c1e72Sjeremylt                       if collocated with quadrature points
77*b11c1e72Sjeremylt   @param v          CeedVector to be used by CeedOperator or CEED_VECTOR_ACTIVE
78*b11c1e72Sjeremylt                       if field is active or CEED_VECTOR_NONE if using
79*b11c1e72Sjeremylt                       CEED_EVAL_WEIGHT in the qfunction
80*b11c1e72Sjeremylt 
81*b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
82*b11c1e72Sjeremylt **/
83d7b241e6Sjeremylt int CeedOperatorSetField(CeedOperator op, const char *fieldname,
84d7b241e6Sjeremylt                          CeedElemRestriction r, CeedBasis b,
85d7b241e6Sjeremylt                          CeedVector v) {
86d7b241e6Sjeremylt   int ierr;
87d7b241e6Sjeremylt   CeedInt numelements;
88d7b241e6Sjeremylt   ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr);
89d7b241e6Sjeremylt   if (op->numelements && op->numelements != numelements)
90d7b241e6Sjeremylt     return CeedError(op->ceed, 1,
91d7b241e6Sjeremylt                      "ElemRestriction with %d elements incompatible with prior %d elements",
92d7b241e6Sjeremylt                      numelements, op->numelements);
93d7b241e6Sjeremylt   op->numelements = numelements;
94d7b241e6Sjeremylt 
95d7b241e6Sjeremylt   if (b != CEED_BASIS_COLOCATED) {
96d7b241e6Sjeremylt     CeedInt numqpoints;
97d7b241e6Sjeremylt     ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr);
98d7b241e6Sjeremylt     if (op->numqpoints && op->numqpoints != numqpoints)
99d7b241e6Sjeremylt       return CeedError(op->ceed, 1,
100d7b241e6Sjeremylt                        "Basis with %d quadrature points incompatible with prior %d points",
101d7b241e6Sjeremylt                        numqpoints, op->numqpoints);
102d7b241e6Sjeremylt     op->numqpoints = numqpoints;
103d7b241e6Sjeremylt   }
104d7b241e6Sjeremylt   struct CeedOperatorField *ofield;
105d7b241e6Sjeremylt   for (CeedInt i=0; i<op->qf->numinputfields; i++) {
106d7b241e6Sjeremylt     if (!strcmp(fieldname, op->qf->inputfields[i].fieldname)) {
107d7b241e6Sjeremylt       ofield = &op->inputfields[i];
108d7b241e6Sjeremylt       goto found;
109d7b241e6Sjeremylt     }
110d7b241e6Sjeremylt   }
111d7b241e6Sjeremylt   for (CeedInt i=0; i<op->qf->numoutputfields; i++) {
112d7b241e6Sjeremylt     if (!strcmp(fieldname, op->qf->outputfields[i].fieldname)) {
113d7b241e6Sjeremylt       ofield = &op->outputfields[i];
114d7b241e6Sjeremylt       goto found;
115d7b241e6Sjeremylt     }
116d7b241e6Sjeremylt   }
117d7b241e6Sjeremylt   return CeedError(op->ceed, 1, "QFunction has no knowledge of field '%s'",
118d7b241e6Sjeremylt                    fieldname);
119d7b241e6Sjeremylt found:
120d7b241e6Sjeremylt   ofield->Erestrict = r;
121d7b241e6Sjeremylt   ofield->basis = b;
122d7b241e6Sjeremylt   ofield->vec = v;
123d7b241e6Sjeremylt   op->nfields += 1;
124d7b241e6Sjeremylt   return 0;
125d7b241e6Sjeremylt }
126d7b241e6Sjeremylt 
127d7b241e6Sjeremylt /**
128*b11c1e72Sjeremylt   @brief Apply CeedOperator to a vector
129d7b241e6Sjeremylt 
130d7b241e6Sjeremylt   This computes the action of the operator on the specified (active) input,
131d7b241e6Sjeremylt   yielding its (active) output.  All inputs and outputs must be specified using
132d7b241e6Sjeremylt   CeedOperatorSetField().
133d7b241e6Sjeremylt 
134d7b241e6Sjeremylt   @param op        CeedOperator to apply
135*b11c1e72Sjeremylt   @param[in] in    CeedVector containing input state or NULL if there are no
136*b11c1e72Sjeremylt                      active inputs
137*b11c1e72Sjeremylt   @param[out] out  CeedVector to store result of applying operator (must be
138d7b241e6Sjeremylt                      distinct from @a in) or NULL if there are no active outputs
139d7b241e6Sjeremylt   @param request   Address of CeedRequest for non-blocking completion, else
140d7b241e6Sjeremylt                      CEED_REQUEST_IMMEDIATE
141*b11c1e72Sjeremylt 
142*b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
143*b11c1e72Sjeremylt **/
144d7b241e6Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in,
145d7b241e6Sjeremylt                       CeedVector out, CeedRequest *request) {
146d7b241e6Sjeremylt   int ierr;
147d7b241e6Sjeremylt   Ceed ceed = op->ceed;
148d7b241e6Sjeremylt   CeedQFunction qf = op->qf;
149d7b241e6Sjeremylt 
150d7b241e6Sjeremylt   if (op->nfields == 0) return CeedError(ceed, 1, "No operator fields set");
151d7b241e6Sjeremylt   if (op->nfields < qf->numinputfields + qf->numoutputfields) return CeedError(
152d7b241e6Sjeremylt           ceed, 1, "Not all operator fields set");
153d7b241e6Sjeremylt   if (op->numelements == 0) return CeedError(ceed, 1,
154d7b241e6Sjeremylt                                      "At least one restriction required");
155d7b241e6Sjeremylt   if (op->numqpoints == 0) return CeedError(ceed, 1,
156d7b241e6Sjeremylt                                     "At least one non-colocated basis required");
157d7b241e6Sjeremylt   ierr = op->Apply(op, in, out, request); CeedChk(ierr);
158d7b241e6Sjeremylt   return 0;
159d7b241e6Sjeremylt }
160d7b241e6Sjeremylt 
161d7b241e6Sjeremylt /**
162*b11c1e72Sjeremylt   @brief Destroy a CeedOperator
163d7b241e6Sjeremylt 
164d7b241e6Sjeremylt   @param op CeedOperator to destroy
165*b11c1e72Sjeremylt 
166*b11c1e72Sjeremylt   @return An error code: 0 - success, otherwise - failure
167*b11c1e72Sjeremylt **/
168d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) {
169d7b241e6Sjeremylt   int ierr;
170d7b241e6Sjeremylt 
171d7b241e6Sjeremylt   if (!*op || --(*op)->refcount > 0) return 0;
172d7b241e6Sjeremylt   if ((*op)->Destroy) {
173d7b241e6Sjeremylt     ierr = (*op)->Destroy(*op); CeedChk(ierr);
174d7b241e6Sjeremylt   }
175d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr);
176d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr);
177d7b241e6Sjeremylt   ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr);
178d7b241e6Sjeremylt   ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr);
179d7b241e6Sjeremylt   ierr = CeedFree(op); CeedChk(ierr);
180d7b241e6Sjeremylt   return 0;
181d7b241e6Sjeremylt }
182d7b241e6Sjeremylt 
183d7b241e6Sjeremylt /// @}
184