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