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