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