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 Get the Ceed associated with a CeedOperator 176 177 @param op CeedOperator 178 @param[out] ceed Variable to store Ceed 179 180 @return An error code: 0 - success, otherwise - failure 181 182 @ref Utility 183 **/ 184 185 int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 186 *ceed = op->ceed; 187 return 0; 188 } 189 190 /** 191 @brief Get the number of elements associated with a CeedOperator 192 193 @param op CeedOperator 194 @param[out] numelem Variable to store number of elements 195 196 @return An error code: 0 - success, otherwise - failure 197 198 @ref Utility 199 **/ 200 201 int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) { 202 *numelem = op->numelements; 203 return 0; 204 } 205 206 /** 207 @brief Get the number of quadrature points associated with a CeedOperator 208 209 @param op CeedOperator 210 @param[out] numqpts Variable to store vector number of quadrature points 211 212 @return An error code: 0 - success, otherwise - failure 213 214 @ref Utility 215 **/ 216 217 int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) { 218 *numqpts = op->numqpoints; 219 return 0; 220 } 221 222 /** 223 @brief Get the number of arguments associated with a CeedOperator 224 225 @param op CeedOperator 226 @param[out] numargs Variable to store vector number of arguments 227 228 @return An error code: 0 - success, otherwise - failure 229 230 @ref Utility 231 **/ 232 233 int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) { 234 *numargs = op->nfields; 235 return 0; 236 } 237 238 /** 239 @brief Get the setup status of a CeedOperator 240 241 @param op CeedOperator 242 @param[out] numelem Variable to store setup status 243 244 @return An error code: 0 - success, otherwise - failure 245 246 @ref Utility 247 **/ 248 249 int CeedOperatorGetSetupStatus(CeedOperator op, bool *setupdone) { 250 *setupdone = op->setupdone; 251 return 0; 252 } 253 254 /** 255 @brief Get the QFunction associated with a CeedOperator 256 257 @param op CeedOperator 258 @param[out] qf Variable to store qfunction 259 260 @return An error code: 0 - success, otherwise - failure 261 262 @ref Utility 263 **/ 264 265 int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 266 *qf = op->qf; 267 return 0; 268 } 269 270 /** 271 @brief Get the backend data of a CeedOperator 272 273 @param op CeedOperator 274 @param[out] data Variable to store data 275 276 @return An error code: 0 - success, otherwise - failure 277 278 @ref Utility 279 **/ 280 281 int CeedOperatorGetData(CeedOperator op, void* *data) { 282 *data = op->data; 283 return 0; 284 } 285 286 /** 287 @brief Set the setup flag of a CeedOperator to True 288 289 @param op CeedOperator 290 291 @return An error code: 0 - success, otherwise - failure 292 293 @ref Utility 294 **/ 295 296 int CeedOperatorSetSetupDone(CeedOperator op) { 297 op->setupdone = 1; 298 return 0; 299 } 300 301 /** 302 @brief Destroy a CeedOperator 303 304 @param op CeedOperator to destroy 305 306 @return An error code: 0 - success, otherwise - failure 307 308 @ref Basic 309 **/ 310 int CeedOperatorDestroy(CeedOperator *op) { 311 int ierr; 312 313 if (!*op || --(*op)->refcount > 0) return 0; 314 if ((*op)->Destroy) { 315 ierr = (*op)->Destroy(*op); CeedChk(ierr); 316 } 317 ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 318 ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 319 ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 320 ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 321 ierr = CeedFree(op); CeedChk(ierr); 322 return 0; 323 } 324 325 /// @} 326