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 <ceed-backend.h> 19 #include <string.h> 20 21 /// @file 22 /// Implementation of public CeedOperator interfaces 23 /// 24 /// @addtogroup CeedOperator 25 /// @{ 26 27 /** 28 @brief Create an operator from element restriction, basis, and QFunction 29 30 @param ceed A Ceed object where the CeedOperator will be created 31 @param qf QFunction defining the action of the operator at quadrature points 32 @param dqf QFunction defining the action of the Jacobian of @a qf (or NULL) 33 @param dqfT QFunction defining the action of the transpose of the Jacobian 34 of @a qf (or NULL) 35 @param[out] op Address of the variable where the newly created 36 CeedOperator will be stored 37 38 @return An error code: 0 - success, otherwise - failure 39 40 @ref Basic 41 */ 42 int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf, 43 CeedQFunction dqfT, CeedOperator *op) { 44 int ierr; 45 46 if (!ceed->OperatorCreate) { 47 Ceed delegate; 48 ierr = CeedGetDelegate(ceed, &delegate); CeedChk(ierr); 49 50 if (!delegate) 51 return CeedError(ceed, 1, "Backend does not support OperatorCreate"); 52 53 ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr); 54 return 0; 55 } 56 57 ierr = CeedCalloc(1,op); CeedChk(ierr); 58 (*op)->ceed = ceed; 59 ceed->refcount++; 60 (*op)->refcount = 1; 61 (*op)->qf = qf; 62 qf->refcount++; 63 (*op)->dqf = dqf; 64 if (dqf) dqf->refcount++; 65 (*op)->dqfT = dqfT; 66 if (dqfT) dqfT->refcount++; 67 ierr = ceed->OperatorCreate(*op); CeedChk(ierr); 68 return 0; 69 } 70 71 /** 72 @brief Provide a field to a CeedOperator for use by its CeedQFunction 73 74 This function is used to specify both active and passive fields to a 75 CeedOperator. For passive fields, a vector @arg v must be provided. Passive 76 fields can inputs or outputs (updated in-place when operator is applied). 77 78 Active fields must be specified using this function, but their data (in a 79 CeedVector) is passed in CeedOperatorApply(). There can be at most one active 80 input and at most one active output. 81 82 @param op Ceedoperator on which to provide the field 83 @param fieldname Name of the field (to be matched with the name used by CeedQFunction) 84 @param r CeedElemRestriction 85 @param lmode CeedTransposeMode which specifies the ordering of the 86 components of the l-vector used by this CeedOperatorField, 87 CEED_NOTRANSPOSE indicates the component is the 88 outermost index and CEED_TRANSPOSE indicates the component 89 is the innermost index in ordering of the l-vector 90 @param b CeedBasis in which the field resides or CEED_BASIS_COLLOCATED 91 if collocated with quadrature points 92 @param v CeedVector to be used by CeedOperator or CEED_VECTOR_ACTIVE 93 if field is active or CEED_VECTOR_NONE if using 94 CEED_EVAL_WEIGHT in the qfunction 95 96 @return An error code: 0 - success, otherwise - failure 97 98 @ref Basic 99 **/ 100 int CeedOperatorSetField(CeedOperator op, const char *fieldname, 101 CeedElemRestriction r, CeedTransposeMode lmode, 102 CeedBasis b, CeedVector v) { 103 int ierr; 104 CeedInt numelements; 105 ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr); 106 if (op->numelements && op->numelements != numelements) 107 return CeedError(op->ceed, 1, 108 "ElemRestriction with %d elements incompatible with prior %d elements", 109 numelements, op->numelements); 110 op->numelements = numelements; 111 112 if (b != CEED_BASIS_COLLOCATED) { 113 CeedInt numqpoints; 114 ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr); 115 if (op->numqpoints && op->numqpoints != numqpoints) 116 return CeedError(op->ceed, 1, 117 "Basis with %d quadrature points incompatible with prior %d points", 118 numqpoints, op->numqpoints); 119 op->numqpoints = numqpoints; 120 } 121 CeedOperatorField *ofield; 122 for (CeedInt i=0; i<op->qf->numinputfields; i++) { 123 if (!strcmp(fieldname, op->qf->inputfields[i].fieldname)) { 124 ofield = &op->inputfields[i]; 125 goto found; 126 } 127 } 128 for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 129 if (!strcmp(fieldname, op->qf->outputfields[i].fieldname)) { 130 ofield = &op->outputfields[i]; 131 goto found; 132 } 133 } 134 return CeedError(op->ceed, 1, "QFunction has no knowledge of field '%s'", 135 fieldname); 136 found: 137 ofield->Erestrict = r; 138 ofield->lmode = lmode; 139 ofield->basis = b; 140 ofield->vec = v; 141 op->nfields += 1; 142 return 0; 143 } 144 145 /** 146 @brief Apply CeedOperator to a vector 147 148 This computes the action of the operator on the specified (active) input, 149 yielding its (active) output. All inputs and outputs must be specified using 150 CeedOperatorSetField(). 151 152 @param op CeedOperator to apply 153 @param[in] in CeedVector containing input state or NULL if there are no 154 active inputs 155 @param[out] out CeedVector to store result of applying operator (must be 156 distinct from @a in) or NULL if there are no active outputs 157 @param request Address of CeedRequest for non-blocking completion, else 158 CEED_REQUEST_IMMEDIATE 159 160 @return An error code: 0 - success, otherwise - failure 161 162 @ref Basic 163 **/ 164 int CeedOperatorApply(CeedOperator op, CeedVector in, 165 CeedVector out, CeedRequest *request) { 166 int ierr; 167 Ceed ceed = op->ceed; 168 CeedQFunction qf = op->qf; 169 170 if (op->nfields == 0) return CeedError(ceed, 1, "No operator fields set"); 171 if (op->nfields < qf->numinputfields + qf->numoutputfields) return CeedError( 172 ceed, 1, "Not all operator fields set"); 173 if (op->numelements == 0) return CeedError(ceed, 1, 174 "At least one restriction required"); 175 if (op->numqpoints == 0) return CeedError(ceed, 1, 176 "At least one non-collocated basis required"); 177 ierr = op->Apply(op, in, out, request); CeedChk(ierr); 178 return 0; 179 } 180 181 /** 182 @brief Get the Ceed associated with a CeedOperator 183 184 @param op CeedOperator 185 @param[out] ceed Variable to store Ceed 186 187 @return An error code: 0 - success, otherwise - failure 188 189 @ref Advanced 190 **/ 191 192 int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 193 *ceed = op->ceed; 194 return 0; 195 } 196 197 /** 198 @brief Get the number of elements associated with a CeedOperator 199 200 @param op CeedOperator 201 @param[out] numelem Variable to store number of elements 202 203 @return An error code: 0 - success, otherwise - failure 204 205 @ref Advanced 206 **/ 207 208 int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) { 209 *numelem = op->numelements; 210 return 0; 211 } 212 213 /** 214 @brief Get the number of quadrature points associated with a CeedOperator 215 216 @param op CeedOperator 217 @param[out] numqpts Variable to store vector number of quadrature points 218 219 @return An error code: 0 - success, otherwise - failure 220 221 @ref Advanced 222 **/ 223 224 int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) { 225 *numqpts = op->numqpoints; 226 return 0; 227 } 228 229 /** 230 @brief Get the number of arguments associated with a CeedOperator 231 232 @param op CeedOperator 233 @param[out] numargs Variable to store vector number of arguments 234 235 @return An error code: 0 - success, otherwise - failure 236 237 @ref Advanced 238 **/ 239 240 int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) { 241 *numargs = op->nfields; 242 return 0; 243 } 244 245 /** 246 @brief Get the setup status of a CeedOperator 247 248 @param op CeedOperator 249 @param[out] numelem Variable to store setup status 250 251 @return An error code: 0 - success, otherwise - failure 252 253 @ref Advanced 254 **/ 255 256 int CeedOperatorGetSetupStatus(CeedOperator op, bool *setupdone) { 257 *setupdone = op->setupdone; 258 return 0; 259 } 260 261 /** 262 @brief Get the QFunction associated with a CeedOperator 263 264 @param op CeedOperator 265 @param[out] qf Variable to store qfunction 266 267 @return An error code: 0 - success, otherwise - failure 268 269 @ref Advanced 270 **/ 271 272 int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 273 *qf = op->qf; 274 return 0; 275 } 276 277 /** 278 @brief Get the backend data of a CeedOperator 279 280 @param op CeedOperator 281 @param[out] data Variable to store data 282 283 @return An error code: 0 - success, otherwise - failure 284 285 @ref Advanced 286 **/ 287 288 int CeedOperatorGetData(CeedOperator op, void* *data) { 289 *data = op->data; 290 return 0; 291 } 292 293 /** 294 @brief Set the setup flag of a CeedOperator to True 295 296 @param op CeedOperator 297 298 @return An error code: 0 - success, otherwise - failure 299 300 @ref Advanced 301 **/ 302 303 int CeedOperatorSetSetupDone(CeedOperator op) { 304 op->setupdone = 1; 305 return 0; 306 } 307 308 /** 309 @brief Get the CeedOperatorFields of a CeedOperator 310 311 @param op CeedOperator 312 @param[out] inputfields Variable to store inputfields 313 @param[out] outputfields Variable to store outputfields 314 315 @return An error code: 0 - success, otherwise - failure 316 317 @ref Advanced 318 **/ 319 320 int CeedOperatorGetFields(CeedOperator op, 321 CeedOperatorField* *inputfields, 322 CeedOperatorField* *outputfields) { 323 if (inputfields) *inputfields = op->inputfields; 324 if (outputfields) *outputfields = op->outputfields; 325 return 0; 326 } 327 328 /** 329 @brief Get the L vector CeedTransposeMode of a CeedOperatorField 330 331 @param opfield CeedOperatorField 332 @param[out] lmode Variable to store CeedTransposeMode 333 334 @return An error code: 0 - success, otherwise - failure 335 336 @ref Advanced 337 **/ 338 339 int CeedOperatorFieldGetLMode(CeedOperatorField opfield, 340 CeedTransposeMode *lmode) { 341 *lmode = (&opfield)->lmode; 342 return 0; 343 }/** 344 @brief Get the CeedElemRestriction of a CeedOperatorField 345 346 @param opfield CeedOperatorField 347 @param[out] rstr Variable to store CeedElemRestriction 348 349 @return An error code: 0 - success, otherwise - failure 350 351 @ref Advanced 352 **/ 353 354 int CeedOperatorFieldGetElemRestriction(CeedOperatorField opfield, 355 CeedElemRestriction *rstr) { 356 *rstr = (&opfield)->Erestrict; 357 return 0; 358 } 359 360 /** 361 @brief Get the CeedBasis of a CeedOperatorField 362 363 @param opfield CeedOperatorField 364 @param[out] basis Variable to store CeedBasis 365 366 @return An error code: 0 - success, otherwise - failure 367 368 @ref Advanced 369 **/ 370 371 int CeedOperatorFieldGetBasis(CeedOperatorField opfield, 372 CeedBasis *basis) { 373 *basis = (&opfield)->basis; 374 return 0; 375 } 376 377 /** 378 @brief Get the CeedVector of a CeedOperatorField 379 380 @param opfield CeedOperatorField 381 @param[out] vec Variable to store CeedVector 382 383 @return An error code: 0 - success, otherwise - failure 384 385 @ref Advanced 386 **/ 387 388 int CeedOperatorFieldGetVector(CeedOperatorField opfield, 389 CeedVector *vec) { 390 *vec = (&opfield)->vec; 391 return 0; 392 } 393 394 /** 395 @brief Destroy a CeedOperator 396 397 @param op CeedOperator to destroy 398 399 @return An error code: 0 - success, otherwise - failure 400 401 @ref Basic 402 **/ 403 int CeedOperatorDestroy(CeedOperator *op) { 404 int ierr; 405 406 if (!*op || --(*op)->refcount > 0) return 0; 407 if ((*op)->Destroy) { 408 ierr = (*op)->Destroy(*op); CeedChk(ierr); 409 } 410 ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 411 ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 412 ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 413 ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 414 ierr = CeedFree(op); CeedChk(ierr); 415 return 0; 416 } 417 418 /// @} 419