1d7b241e6Sjeremylt // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at 2d7b241e6Sjeremylt // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights 3d7b241e6Sjeremylt // reserved. See files LICENSE and NOTICE for details. 4d7b241e6Sjeremylt // 5d7b241e6Sjeremylt // This file is part of CEED, a collection of benchmarks, miniapps, software 6d7b241e6Sjeremylt // libraries and APIs for efficient high-order finite element and spectral 7d7b241e6Sjeremylt // element discretizations for exascale applications. For more information and 8d7b241e6Sjeremylt // source code availability see http://github.com/ceed. 9d7b241e6Sjeremylt // 10d7b241e6Sjeremylt // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 11d7b241e6Sjeremylt // a collaborative effort of two U.S. Department of Energy organizations (Office 12d7b241e6Sjeremylt // of Science and the National Nuclear Security Administration) responsible for 13d7b241e6Sjeremylt // the planning and preparation of a capable exascale ecosystem, including 14d7b241e6Sjeremylt // software, applications, hardware, advanced system engineering and early 15d7b241e6Sjeremylt // testbed platforms, in support of the nation's exascale computing imperative. 16d7b241e6Sjeremylt 17d7b241e6Sjeremylt #include <ceed-impl.h> 18d7b241e6Sjeremylt #include <string.h> 19d7b241e6Sjeremylt 20dfdf5a53Sjeremylt /// @file 21dfdf5a53Sjeremylt /// Implementation of public CeedOperator interfaces 22dfdf5a53Sjeremylt /// 23dfdf5a53Sjeremylt /// @addtogroup CeedOperator 24dfdf5a53Sjeremylt /// @{ 25d7b241e6Sjeremylt 26d7b241e6Sjeremylt /** 27b11c1e72Sjeremylt @brief Create an operator from element restriction, basis, and QFunction 28d7b241e6Sjeremylt 29b11c1e72Sjeremylt @param ceed A Ceed object where the CeedOperator will be created 30d7b241e6Sjeremylt @param qf QFunction defining the action of the operator at quadrature points 31d7b241e6Sjeremylt @param dqf QFunction defining the action of the Jacobian of @a qf (or NULL) 32d7b241e6Sjeremylt @param dqfT QFunction defining the action of the transpose of the Jacobian 33d7b241e6Sjeremylt of @a qf (or NULL) 34b11c1e72Sjeremylt @param[out] op Address of the variable where the newly created 35b11c1e72Sjeremylt CeedOperator will be stored 36b11c1e72Sjeremylt 37b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 38dfdf5a53Sjeremylt 39dfdf5a53Sjeremylt @ref Basic 40d7b241e6Sjeremylt */ 41d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf, 42d7b241e6Sjeremylt CeedQFunction dqfT, CeedOperator *op) { 43d7b241e6Sjeremylt int ierr; 44d7b241e6Sjeremylt 455fe0d4faSjeremylt if (!ceed->OperatorCreate) { 465fe0d4faSjeremylt Ceed delegate; 475fe0d4faSjeremylt ierr = CeedGetDelegate(ceed, &delegate); CeedChk(ierr); 485fe0d4faSjeremylt 495fe0d4faSjeremylt if (!delegate) 505fe0d4faSjeremylt return CeedError(ceed, 1, "Backend does not support OperatorCreate"); 515fe0d4faSjeremylt 525fe0d4faSjeremylt ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr); 535fe0d4faSjeremylt return 0; 545fe0d4faSjeremylt } 555fe0d4faSjeremylt 56d7b241e6Sjeremylt ierr = CeedCalloc(1,op); CeedChk(ierr); 57d7b241e6Sjeremylt (*op)->ceed = ceed; 58d7b241e6Sjeremylt ceed->refcount++; 59d7b241e6Sjeremylt (*op)->refcount = 1; 60d7b241e6Sjeremylt (*op)->qf = qf; 61d7b241e6Sjeremylt qf->refcount++; 62d7b241e6Sjeremylt (*op)->dqf = dqf; 63d7b241e6Sjeremylt if (dqf) dqf->refcount++; 64d7b241e6Sjeremylt (*op)->dqfT = dqfT; 65d7b241e6Sjeremylt if (dqfT) dqfT->refcount++; 66d7b241e6Sjeremylt ierr = ceed->OperatorCreate(*op); CeedChk(ierr); 67d7b241e6Sjeremylt return 0; 68d7b241e6Sjeremylt } 69d7b241e6Sjeremylt 70d7b241e6Sjeremylt /** 71b11c1e72Sjeremylt @brief Provide a field to a CeedOperator for use by its CeedQFunction 72d7b241e6Sjeremylt 73d7b241e6Sjeremylt This function is used to specify both active and passive fields to a 74d7b241e6Sjeremylt CeedOperator. For passive fields, a vector @arg v must be provided. Passive 75d7b241e6Sjeremylt fields can inputs or outputs (updated in-place when operator is applied). 76d7b241e6Sjeremylt 77d7b241e6Sjeremylt Active fields must be specified using this function, but their data (in a 78d7b241e6Sjeremylt CeedVector) is passed in CeedOperatorApply(). There can be at most one active 79d7b241e6Sjeremylt input and at most one active output. 80d7b241e6Sjeremylt 81b11c1e72Sjeremylt @param op Ceedoperator on which to provide the field 82b11c1e72Sjeremylt @param fieldname Name of the field (to be matched with the name used by CeedQFunction) 83b11c1e72Sjeremylt @param r CeedElemRestriction 84783c99b3SValeria Barra @param b CeedBasis in which the field resides or CEED_BASIS_COLLOCATED 85b11c1e72Sjeremylt if collocated with quadrature points 86b11c1e72Sjeremylt @param v CeedVector to be used by CeedOperator or CEED_VECTOR_ACTIVE 87b11c1e72Sjeremylt if field is active or CEED_VECTOR_NONE if using 88b11c1e72Sjeremylt CEED_EVAL_WEIGHT in the qfunction 89b11c1e72Sjeremylt 90b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 91dfdf5a53Sjeremylt 92dfdf5a53Sjeremylt @ref Basic 93b11c1e72Sjeremylt **/ 94d7b241e6Sjeremylt int CeedOperatorSetField(CeedOperator op, const char *fieldname, 95d7b241e6Sjeremylt CeedElemRestriction r, CeedBasis b, 96d7b241e6Sjeremylt CeedVector v) { 97d7b241e6Sjeremylt int ierr; 98d7b241e6Sjeremylt CeedInt numelements; 99d7b241e6Sjeremylt ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr); 100d7b241e6Sjeremylt if (op->numelements && op->numelements != numelements) 101d7b241e6Sjeremylt return CeedError(op->ceed, 1, 102d7b241e6Sjeremylt "ElemRestriction with %d elements incompatible with prior %d elements", 103d7b241e6Sjeremylt numelements, op->numelements); 104d7b241e6Sjeremylt op->numelements = numelements; 105d7b241e6Sjeremylt 106783c99b3SValeria Barra if (b != CEED_BASIS_COLLOCATED) { 107d7b241e6Sjeremylt CeedInt numqpoints; 108d7b241e6Sjeremylt ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr); 109d7b241e6Sjeremylt if (op->numqpoints && op->numqpoints != numqpoints) 110d7b241e6Sjeremylt return CeedError(op->ceed, 1, 111d7b241e6Sjeremylt "Basis with %d quadrature points incompatible with prior %d points", 112d7b241e6Sjeremylt numqpoints, op->numqpoints); 113d7b241e6Sjeremylt op->numqpoints = numqpoints; 114d7b241e6Sjeremylt } 115d7b241e6Sjeremylt struct CeedOperatorField *ofield; 116d7b241e6Sjeremylt for (CeedInt i=0; i<op->qf->numinputfields; i++) { 117d7b241e6Sjeremylt if (!strcmp(fieldname, op->qf->inputfields[i].fieldname)) { 118d7b241e6Sjeremylt ofield = &op->inputfields[i]; 119d7b241e6Sjeremylt goto found; 120d7b241e6Sjeremylt } 121d7b241e6Sjeremylt } 122d7b241e6Sjeremylt for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 123d7b241e6Sjeremylt if (!strcmp(fieldname, op->qf->outputfields[i].fieldname)) { 124d7b241e6Sjeremylt ofield = &op->outputfields[i]; 125d7b241e6Sjeremylt goto found; 126d7b241e6Sjeremylt } 127d7b241e6Sjeremylt } 128d7b241e6Sjeremylt return CeedError(op->ceed, 1, "QFunction has no knowledge of field '%s'", 129d7b241e6Sjeremylt fieldname); 130d7b241e6Sjeremylt found: 131d7b241e6Sjeremylt ofield->Erestrict = r; 132d7b241e6Sjeremylt ofield->basis = b; 133d7b241e6Sjeremylt ofield->vec = v; 134d7b241e6Sjeremylt op->nfields += 1; 135d7b241e6Sjeremylt return 0; 136d7b241e6Sjeremylt } 137d7b241e6Sjeremylt 138d7b241e6Sjeremylt /** 139b11c1e72Sjeremylt @brief Apply CeedOperator to a vector 140d7b241e6Sjeremylt 141d7b241e6Sjeremylt This computes the action of the operator on the specified (active) input, 142d7b241e6Sjeremylt yielding its (active) output. All inputs and outputs must be specified using 143d7b241e6Sjeremylt CeedOperatorSetField(). 144d7b241e6Sjeremylt 145d7b241e6Sjeremylt @param op CeedOperator to apply 146b11c1e72Sjeremylt @param[in] in CeedVector containing input state or NULL if there are no 147b11c1e72Sjeremylt active inputs 148b11c1e72Sjeremylt @param[out] out CeedVector to store result of applying operator (must be 149d7b241e6Sjeremylt distinct from @a in) or NULL if there are no active outputs 150d7b241e6Sjeremylt @param request Address of CeedRequest for non-blocking completion, else 151d7b241e6Sjeremylt CEED_REQUEST_IMMEDIATE 152b11c1e72Sjeremylt 153b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 154dfdf5a53Sjeremylt 155dfdf5a53Sjeremylt @ref Basic 156b11c1e72Sjeremylt **/ 157d7b241e6Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, 158d7b241e6Sjeremylt CeedVector out, CeedRequest *request) { 159d7b241e6Sjeremylt int ierr; 160d7b241e6Sjeremylt Ceed ceed = op->ceed; 161d7b241e6Sjeremylt CeedQFunction qf = op->qf; 162d7b241e6Sjeremylt 163d7b241e6Sjeremylt if (op->nfields == 0) return CeedError(ceed, 1, "No operator fields set"); 164d7b241e6Sjeremylt if (op->nfields < qf->numinputfields + qf->numoutputfields) return CeedError( 165d7b241e6Sjeremylt ceed, 1, "Not all operator fields set"); 166d7b241e6Sjeremylt if (op->numelements == 0) return CeedError(ceed, 1, 167d7b241e6Sjeremylt "At least one restriction required"); 168d7b241e6Sjeremylt if (op->numqpoints == 0) return CeedError(ceed, 1, 169783c99b3SValeria Barra "At least one non-collocated basis required"); 170d7b241e6Sjeremylt ierr = op->Apply(op, in, out, request); CeedChk(ierr); 171d7b241e6Sjeremylt return 0; 172d7b241e6Sjeremylt } 173d7b241e6Sjeremylt 174d7b241e6Sjeremylt /** 175*4ce2993fSjeremylt @brief Get the Ceed associated with a CeedOperator 176*4ce2993fSjeremylt 177*4ce2993fSjeremylt @param op CeedOperator 178*4ce2993fSjeremylt @param[out] ceed Variable to store Ceed 179*4ce2993fSjeremylt 180*4ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 181*4ce2993fSjeremylt 182*4ce2993fSjeremylt @ref Utility 183*4ce2993fSjeremylt **/ 184*4ce2993fSjeremylt 185*4ce2993fSjeremylt int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 186*4ce2993fSjeremylt *ceed = op->ceed; 187*4ce2993fSjeremylt return 0; 188*4ce2993fSjeremylt } 189*4ce2993fSjeremylt 190*4ce2993fSjeremylt /** 191*4ce2993fSjeremylt @brief Get the number of elements associated with a CeedOperator 192*4ce2993fSjeremylt 193*4ce2993fSjeremylt @param op CeedOperator 194*4ce2993fSjeremylt @param[out] numelem Variable to store number of elements 195*4ce2993fSjeremylt 196*4ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 197*4ce2993fSjeremylt 198*4ce2993fSjeremylt @ref Utility 199*4ce2993fSjeremylt **/ 200*4ce2993fSjeremylt 201*4ce2993fSjeremylt int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) { 202*4ce2993fSjeremylt *numelem = op->numelements; 203*4ce2993fSjeremylt return 0; 204*4ce2993fSjeremylt } 205*4ce2993fSjeremylt 206*4ce2993fSjeremylt /** 207*4ce2993fSjeremylt @brief Get the number of quadrature points associated with a CeedOperator 208*4ce2993fSjeremylt 209*4ce2993fSjeremylt @param op CeedOperator 210*4ce2993fSjeremylt @param[out] numqpts Variable to store vector number of quadrature points 211*4ce2993fSjeremylt 212*4ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 213*4ce2993fSjeremylt 214*4ce2993fSjeremylt @ref Utility 215*4ce2993fSjeremylt **/ 216*4ce2993fSjeremylt 217*4ce2993fSjeremylt int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) { 218*4ce2993fSjeremylt *numqpts = op->numqpoints; 219*4ce2993fSjeremylt return 0; 220*4ce2993fSjeremylt } 221*4ce2993fSjeremylt 222*4ce2993fSjeremylt /** 223*4ce2993fSjeremylt @brief Get the number of arguments associated with a CeedOperator 224*4ce2993fSjeremylt 225*4ce2993fSjeremylt @param op CeedOperator 226*4ce2993fSjeremylt @param[out] numargs Variable to store vector number of arguments 227*4ce2993fSjeremylt 228*4ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 229*4ce2993fSjeremylt 230*4ce2993fSjeremylt @ref Utility 231*4ce2993fSjeremylt **/ 232*4ce2993fSjeremylt 233*4ce2993fSjeremylt int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) { 234*4ce2993fSjeremylt *numargs = op->nfields; 235*4ce2993fSjeremylt return 0; 236*4ce2993fSjeremylt } 237*4ce2993fSjeremylt 238*4ce2993fSjeremylt /** 239*4ce2993fSjeremylt @brief Get the setup status of a CeedOperator 240*4ce2993fSjeremylt 241*4ce2993fSjeremylt @param op CeedOperator 242*4ce2993fSjeremylt @param[out] numelem Variable to store setup status 243*4ce2993fSjeremylt 244*4ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 245*4ce2993fSjeremylt 246*4ce2993fSjeremylt @ref Utility 247*4ce2993fSjeremylt **/ 248*4ce2993fSjeremylt 249*4ce2993fSjeremylt int CeedOperatorGetSetupStatus(CeedOperator op, bool *setupdone) { 250*4ce2993fSjeremylt *setupdone = op->setupdone; 251*4ce2993fSjeremylt return 0; 252*4ce2993fSjeremylt } 253*4ce2993fSjeremylt 254*4ce2993fSjeremylt /** 255*4ce2993fSjeremylt @brief Get the QFunction associated with a CeedOperator 256*4ce2993fSjeremylt 257*4ce2993fSjeremylt @param op CeedOperator 258*4ce2993fSjeremylt @param[out] qf Variable to store qfunction 259*4ce2993fSjeremylt 260*4ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 261*4ce2993fSjeremylt 262*4ce2993fSjeremylt @ref Utility 263*4ce2993fSjeremylt **/ 264*4ce2993fSjeremylt 265*4ce2993fSjeremylt int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 266*4ce2993fSjeremylt *qf = op->qf; 267*4ce2993fSjeremylt return 0; 268*4ce2993fSjeremylt } 269*4ce2993fSjeremylt 270*4ce2993fSjeremylt /** 271*4ce2993fSjeremylt @brief Get the backend data of a CeedOperator 272*4ce2993fSjeremylt 273*4ce2993fSjeremylt @param op CeedOperator 274*4ce2993fSjeremylt @param[out] data Variable to store data 275*4ce2993fSjeremylt 276*4ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 277*4ce2993fSjeremylt 278*4ce2993fSjeremylt @ref Utility 279*4ce2993fSjeremylt **/ 280*4ce2993fSjeremylt 281*4ce2993fSjeremylt int CeedOperatorGetData(CeedOperator op, void* *data) { 282*4ce2993fSjeremylt *data = op->data; 283*4ce2993fSjeremylt return 0; 284*4ce2993fSjeremylt } 285*4ce2993fSjeremylt 286*4ce2993fSjeremylt /** 287*4ce2993fSjeremylt @brief Set the setup flag of a CeedOperator to True 288*4ce2993fSjeremylt 289*4ce2993fSjeremylt @param op CeedOperator 290*4ce2993fSjeremylt 291*4ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 292*4ce2993fSjeremylt 293*4ce2993fSjeremylt @ref Utility 294*4ce2993fSjeremylt **/ 295*4ce2993fSjeremylt 296*4ce2993fSjeremylt int CeedOperatorSetSetupDone(CeedOperator op) { 297*4ce2993fSjeremylt op->setupdone = 1; 298*4ce2993fSjeremylt return 0; 299*4ce2993fSjeremylt } 300*4ce2993fSjeremylt 301*4ce2993fSjeremylt /** 302b11c1e72Sjeremylt @brief Destroy a CeedOperator 303d7b241e6Sjeremylt 304d7b241e6Sjeremylt @param op CeedOperator to destroy 305b11c1e72Sjeremylt 306b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 307dfdf5a53Sjeremylt 308dfdf5a53Sjeremylt @ref Basic 309b11c1e72Sjeremylt **/ 310d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) { 311d7b241e6Sjeremylt int ierr; 312d7b241e6Sjeremylt 313d7b241e6Sjeremylt if (!*op || --(*op)->refcount > 0) return 0; 314d7b241e6Sjeremylt if ((*op)->Destroy) { 315d7b241e6Sjeremylt ierr = (*op)->Destroy(*op); CeedChk(ierr); 316d7b241e6Sjeremylt } 317d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 318d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 319d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 320d7b241e6Sjeremylt ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 321d7b241e6Sjeremylt ierr = CeedFree(op); CeedChk(ierr); 322d7b241e6Sjeremylt return 0; 323d7b241e6Sjeremylt } 324d7b241e6Sjeremylt 325d7b241e6Sjeremylt /// @} 326