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 45d7b241e6Sjeremylt if (!ceed->OperatorCreate) return CeedError(ceed, 1, 46d7b241e6Sjeremylt "Backend does not support OperatorCreate"); 47d7b241e6Sjeremylt ierr = CeedCalloc(1,op); CeedChk(ierr); 48d7b241e6Sjeremylt (*op)->ceed = ceed; 49d7b241e6Sjeremylt ceed->refcount++; 50d7b241e6Sjeremylt (*op)->refcount = 1; 51d7b241e6Sjeremylt (*op)->qf = qf; 52d7b241e6Sjeremylt qf->refcount++; 53d7b241e6Sjeremylt (*op)->dqf = dqf; 54d7b241e6Sjeremylt if (dqf) dqf->refcount++; 55d7b241e6Sjeremylt (*op)->dqfT = dqfT; 56d7b241e6Sjeremylt if (dqfT) dqfT->refcount++; 57d7b241e6Sjeremylt ierr = ceed->OperatorCreate(*op); CeedChk(ierr); 58d7b241e6Sjeremylt return 0; 59d7b241e6Sjeremylt } 60d7b241e6Sjeremylt 61d7b241e6Sjeremylt /** 62b11c1e72Sjeremylt @brief Provide a field to a CeedOperator for use by its CeedQFunction 63d7b241e6Sjeremylt 64d7b241e6Sjeremylt This function is used to specify both active and passive fields to a 65d7b241e6Sjeremylt CeedOperator. For passive fields, a vector @arg v must be provided. Passive 66d7b241e6Sjeremylt fields can inputs or outputs (updated in-place when operator is applied). 67d7b241e6Sjeremylt 68d7b241e6Sjeremylt Active fields must be specified using this function, but their data (in a 69d7b241e6Sjeremylt CeedVector) is passed in CeedOperatorApply(). There can be at most one active 70d7b241e6Sjeremylt input and at most one active output. 71d7b241e6Sjeremylt 72b11c1e72Sjeremylt @param op Ceedoperator on which to provide the field 73b11c1e72Sjeremylt @param fieldname Name of the field (to be matched with the name used by CeedQFunction) 74b11c1e72Sjeremylt @param r CeedElemRestriction 75*783c99b3SValeria Barra @param b CeedBasis in which the field resides or CEED_BASIS_COLLOCATED 76b11c1e72Sjeremylt if collocated with quadrature points 77b11c1e72Sjeremylt @param v CeedVector to be used by CeedOperator or CEED_VECTOR_ACTIVE 78b11c1e72Sjeremylt if field is active or CEED_VECTOR_NONE if using 79b11c1e72Sjeremylt CEED_EVAL_WEIGHT in the qfunction 80b11c1e72Sjeremylt 81b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 82dfdf5a53Sjeremylt 83dfdf5a53Sjeremylt @ref Basic 84b11c1e72Sjeremylt **/ 85d7b241e6Sjeremylt int CeedOperatorSetField(CeedOperator op, const char *fieldname, 86d7b241e6Sjeremylt CeedElemRestriction r, CeedBasis b, 87d7b241e6Sjeremylt CeedVector v) { 88d7b241e6Sjeremylt int ierr; 89d7b241e6Sjeremylt CeedInt numelements; 90d7b241e6Sjeremylt ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr); 91d7b241e6Sjeremylt if (op->numelements && op->numelements != numelements) 92d7b241e6Sjeremylt return CeedError(op->ceed, 1, 93d7b241e6Sjeremylt "ElemRestriction with %d elements incompatible with prior %d elements", 94d7b241e6Sjeremylt numelements, op->numelements); 95d7b241e6Sjeremylt op->numelements = numelements; 96d7b241e6Sjeremylt 97*783c99b3SValeria Barra if (b != CEED_BASIS_COLLOCATED) { 98d7b241e6Sjeremylt CeedInt numqpoints; 99d7b241e6Sjeremylt ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr); 100d7b241e6Sjeremylt if (op->numqpoints && op->numqpoints != numqpoints) 101d7b241e6Sjeremylt return CeedError(op->ceed, 1, 102d7b241e6Sjeremylt "Basis with %d quadrature points incompatible with prior %d points", 103d7b241e6Sjeremylt numqpoints, op->numqpoints); 104d7b241e6Sjeremylt op->numqpoints = numqpoints; 105d7b241e6Sjeremylt } 106d7b241e6Sjeremylt struct CeedOperatorField *ofield; 107d7b241e6Sjeremylt for (CeedInt i=0; i<op->qf->numinputfields; i++) { 108d7b241e6Sjeremylt if (!strcmp(fieldname, op->qf->inputfields[i].fieldname)) { 109d7b241e6Sjeremylt ofield = &op->inputfields[i]; 110d7b241e6Sjeremylt goto found; 111d7b241e6Sjeremylt } 112d7b241e6Sjeremylt } 113d7b241e6Sjeremylt for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 114d7b241e6Sjeremylt if (!strcmp(fieldname, op->qf->outputfields[i].fieldname)) { 115d7b241e6Sjeremylt ofield = &op->outputfields[i]; 116d7b241e6Sjeremylt goto found; 117d7b241e6Sjeremylt } 118d7b241e6Sjeremylt } 119d7b241e6Sjeremylt return CeedError(op->ceed, 1, "QFunction has no knowledge of field '%s'", 120d7b241e6Sjeremylt fieldname); 121d7b241e6Sjeremylt found: 122d7b241e6Sjeremylt ofield->Erestrict = r; 123d7b241e6Sjeremylt ofield->basis = b; 124d7b241e6Sjeremylt ofield->vec = v; 125d7b241e6Sjeremylt op->nfields += 1; 126d7b241e6Sjeremylt return 0; 127d7b241e6Sjeremylt } 128d7b241e6Sjeremylt 129d7b241e6Sjeremylt /** 130b11c1e72Sjeremylt @brief Apply CeedOperator to a vector 131d7b241e6Sjeremylt 132d7b241e6Sjeremylt This computes the action of the operator on the specified (active) input, 133d7b241e6Sjeremylt yielding its (active) output. All inputs and outputs must be specified using 134d7b241e6Sjeremylt CeedOperatorSetField(). 135d7b241e6Sjeremylt 136d7b241e6Sjeremylt @param op CeedOperator to apply 137b11c1e72Sjeremylt @param[in] in CeedVector containing input state or NULL if there are no 138b11c1e72Sjeremylt active inputs 139b11c1e72Sjeremylt @param[out] out CeedVector to store result of applying operator (must be 140d7b241e6Sjeremylt distinct from @a in) or NULL if there are no active outputs 141d7b241e6Sjeremylt @param request Address of CeedRequest for non-blocking completion, else 142d7b241e6Sjeremylt CEED_REQUEST_IMMEDIATE 143b11c1e72Sjeremylt 144b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 145dfdf5a53Sjeremylt 146dfdf5a53Sjeremylt @ref Basic 147b11c1e72Sjeremylt **/ 148d7b241e6Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, 149d7b241e6Sjeremylt CeedVector out, CeedRequest *request) { 150d7b241e6Sjeremylt int ierr; 151d7b241e6Sjeremylt Ceed ceed = op->ceed; 152d7b241e6Sjeremylt CeedQFunction qf = op->qf; 153d7b241e6Sjeremylt 154d7b241e6Sjeremylt if (op->nfields == 0) return CeedError(ceed, 1, "No operator fields set"); 155d7b241e6Sjeremylt if (op->nfields < qf->numinputfields + qf->numoutputfields) return CeedError( 156d7b241e6Sjeremylt ceed, 1, "Not all operator fields set"); 157d7b241e6Sjeremylt if (op->numelements == 0) return CeedError(ceed, 1, 158d7b241e6Sjeremylt "At least one restriction required"); 159d7b241e6Sjeremylt if (op->numqpoints == 0) return CeedError(ceed, 1, 160*783c99b3SValeria Barra "At least one non-collocated basis required"); 161d7b241e6Sjeremylt ierr = op->Apply(op, in, out, request); CeedChk(ierr); 162d7b241e6Sjeremylt return 0; 163d7b241e6Sjeremylt } 164d7b241e6Sjeremylt 165d7b241e6Sjeremylt /** 166b11c1e72Sjeremylt @brief Destroy a CeedOperator 167d7b241e6Sjeremylt 168d7b241e6Sjeremylt @param op CeedOperator to destroy 169b11c1e72Sjeremylt 170b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 171dfdf5a53Sjeremylt 172dfdf5a53Sjeremylt @ref Basic 173b11c1e72Sjeremylt **/ 174d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) { 175d7b241e6Sjeremylt int ierr; 176d7b241e6Sjeremylt 177d7b241e6Sjeremylt if (!*op || --(*op)->refcount > 0) return 0; 178d7b241e6Sjeremylt if ((*op)->Destroy) { 179d7b241e6Sjeremylt ierr = (*op)->Destroy(*op); CeedChk(ierr); 180d7b241e6Sjeremylt } 181d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 182d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 183d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 184d7b241e6Sjeremylt ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 185d7b241e6Sjeremylt ierr = CeedFree(op); CeedChk(ierr); 186d7b241e6Sjeremylt return 0; 187d7b241e6Sjeremylt } 188d7b241e6Sjeremylt 189d7b241e6Sjeremylt /// @} 190