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