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 45*5fe0d4faSjeremylt if (!ceed->OperatorCreate) { 46*5fe0d4faSjeremylt Ceed delegate; 47*5fe0d4faSjeremylt ierr = CeedGetDelegate(ceed, &delegate); CeedChk(ierr); 48*5fe0d4faSjeremylt 49*5fe0d4faSjeremylt if (!delegate) 50*5fe0d4faSjeremylt return CeedError(ceed, 1, "Backend does not support OperatorCreate"); 51*5fe0d4faSjeremylt 52*5fe0d4faSjeremylt ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr); 53*5fe0d4faSjeremylt return 0; 54*5fe0d4faSjeremylt } 55*5fe0d4faSjeremylt 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 /** 175b11c1e72Sjeremylt @brief Destroy a CeedOperator 176d7b241e6Sjeremylt 177d7b241e6Sjeremylt @param op CeedOperator to destroy 178b11c1e72Sjeremylt 179b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 180dfdf5a53Sjeremylt 181dfdf5a53Sjeremylt @ref Basic 182b11c1e72Sjeremylt **/ 183d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) { 184d7b241e6Sjeremylt int ierr; 185d7b241e6Sjeremylt 186d7b241e6Sjeremylt if (!*op || --(*op)->refcount > 0) return 0; 187d7b241e6Sjeremylt if ((*op)->Destroy) { 188d7b241e6Sjeremylt ierr = (*op)->Destroy(*op); CeedChk(ierr); 189d7b241e6Sjeremylt } 190d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 191d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 192d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 193d7b241e6Sjeremylt ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 194d7b241e6Sjeremylt ierr = CeedFree(op); CeedChk(ierr); 195d7b241e6Sjeremylt return 0; 196d7b241e6Sjeremylt } 197d7b241e6Sjeremylt 198d7b241e6Sjeremylt /// @} 199