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