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 20d7b241e6Sjeremylt /** 21d7b241e6Sjeremylt @file 22d7b241e6Sjeremylt Implementation of public CeedOperator interfaces 23d7b241e6Sjeremylt 24d7b241e6Sjeremylt @defgroup CeedOperator CeedOperator: composed FE-type operations on vectors 25d7b241e6Sjeremylt @{ 26d7b241e6Sjeremylt */ 27d7b241e6Sjeremylt 28d7b241e6Sjeremylt /** 29*b11c1e72Sjeremylt @brief Create an operator from element restriction, basis, and QFunction 30d7b241e6Sjeremylt 31*b11c1e72Sjeremylt @param ceed A Ceed object where the CeedOperator will be created 32d7b241e6Sjeremylt @param qf QFunction defining the action of the operator at quadrature points 33d7b241e6Sjeremylt @param dqf QFunction defining the action of the Jacobian of @a qf (or NULL) 34d7b241e6Sjeremylt @param dqfT QFunction defining the action of the transpose of the Jacobian 35d7b241e6Sjeremylt of @a qf (or NULL) 36*b11c1e72Sjeremylt @param[out] op Address of the variable where the newly created 37*b11c1e72Sjeremylt CeedOperator will be stored 38*b11c1e72Sjeremylt 39*b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 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 /** 62*b11c1e72Sjeremylt @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 72*b11c1e72Sjeremylt @param op Ceedoperator on which to provide the field 73*b11c1e72Sjeremylt @param fieldname Name of the field (to be matched with the name used by CeedQFunction) 74*b11c1e72Sjeremylt @param r CeedElemRestriction 75*b11c1e72Sjeremylt @param b CeedBasis in which the field resides or CEED_BASIS_COLOCATED 76*b11c1e72Sjeremylt if collocated with quadrature points 77*b11c1e72Sjeremylt @param v CeedVector to be used by CeedOperator or CEED_VECTOR_ACTIVE 78*b11c1e72Sjeremylt if field is active or CEED_VECTOR_NONE if using 79*b11c1e72Sjeremylt CEED_EVAL_WEIGHT in the qfunction 80*b11c1e72Sjeremylt 81*b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 82*b11c1e72Sjeremylt **/ 83d7b241e6Sjeremylt int CeedOperatorSetField(CeedOperator op, const char *fieldname, 84d7b241e6Sjeremylt CeedElemRestriction r, CeedBasis b, 85d7b241e6Sjeremylt CeedVector v) { 86d7b241e6Sjeremylt int ierr; 87d7b241e6Sjeremylt CeedInt numelements; 88d7b241e6Sjeremylt ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr); 89d7b241e6Sjeremylt if (op->numelements && op->numelements != numelements) 90d7b241e6Sjeremylt return CeedError(op->ceed, 1, 91d7b241e6Sjeremylt "ElemRestriction with %d elements incompatible with prior %d elements", 92d7b241e6Sjeremylt numelements, op->numelements); 93d7b241e6Sjeremylt op->numelements = numelements; 94d7b241e6Sjeremylt 95d7b241e6Sjeremylt if (b != CEED_BASIS_COLOCATED) { 96d7b241e6Sjeremylt CeedInt numqpoints; 97d7b241e6Sjeremylt ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr); 98d7b241e6Sjeremylt if (op->numqpoints && op->numqpoints != numqpoints) 99d7b241e6Sjeremylt return CeedError(op->ceed, 1, 100d7b241e6Sjeremylt "Basis with %d quadrature points incompatible with prior %d points", 101d7b241e6Sjeremylt numqpoints, op->numqpoints); 102d7b241e6Sjeremylt op->numqpoints = numqpoints; 103d7b241e6Sjeremylt } 104d7b241e6Sjeremylt struct CeedOperatorField *ofield; 105d7b241e6Sjeremylt for (CeedInt i=0; i<op->qf->numinputfields; i++) { 106d7b241e6Sjeremylt if (!strcmp(fieldname, op->qf->inputfields[i].fieldname)) { 107d7b241e6Sjeremylt ofield = &op->inputfields[i]; 108d7b241e6Sjeremylt goto found; 109d7b241e6Sjeremylt } 110d7b241e6Sjeremylt } 111d7b241e6Sjeremylt for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 112d7b241e6Sjeremylt if (!strcmp(fieldname, op->qf->outputfields[i].fieldname)) { 113d7b241e6Sjeremylt ofield = &op->outputfields[i]; 114d7b241e6Sjeremylt goto found; 115d7b241e6Sjeremylt } 116d7b241e6Sjeremylt } 117d7b241e6Sjeremylt return CeedError(op->ceed, 1, "QFunction has no knowledge of field '%s'", 118d7b241e6Sjeremylt fieldname); 119d7b241e6Sjeremylt found: 120d7b241e6Sjeremylt ofield->Erestrict = r; 121d7b241e6Sjeremylt ofield->basis = b; 122d7b241e6Sjeremylt ofield->vec = v; 123d7b241e6Sjeremylt op->nfields += 1; 124d7b241e6Sjeremylt return 0; 125d7b241e6Sjeremylt } 126d7b241e6Sjeremylt 127d7b241e6Sjeremylt /** 128*b11c1e72Sjeremylt @brief Apply CeedOperator to a vector 129d7b241e6Sjeremylt 130d7b241e6Sjeremylt This computes the action of the operator on the specified (active) input, 131d7b241e6Sjeremylt yielding its (active) output. All inputs and outputs must be specified using 132d7b241e6Sjeremylt CeedOperatorSetField(). 133d7b241e6Sjeremylt 134d7b241e6Sjeremylt @param op CeedOperator to apply 135*b11c1e72Sjeremylt @param[in] in CeedVector containing input state or NULL if there are no 136*b11c1e72Sjeremylt active inputs 137*b11c1e72Sjeremylt @param[out] out CeedVector to store result of applying operator (must be 138d7b241e6Sjeremylt distinct from @a in) or NULL if there are no active outputs 139d7b241e6Sjeremylt @param request Address of CeedRequest for non-blocking completion, else 140d7b241e6Sjeremylt CEED_REQUEST_IMMEDIATE 141*b11c1e72Sjeremylt 142*b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 143*b11c1e72Sjeremylt **/ 144d7b241e6Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, 145d7b241e6Sjeremylt CeedVector out, CeedRequest *request) { 146d7b241e6Sjeremylt int ierr; 147d7b241e6Sjeremylt Ceed ceed = op->ceed; 148d7b241e6Sjeremylt CeedQFunction qf = op->qf; 149d7b241e6Sjeremylt 150d7b241e6Sjeremylt if (op->nfields == 0) return CeedError(ceed, 1, "No operator fields set"); 151d7b241e6Sjeremylt if (op->nfields < qf->numinputfields + qf->numoutputfields) return CeedError( 152d7b241e6Sjeremylt ceed, 1, "Not all operator fields set"); 153d7b241e6Sjeremylt if (op->numelements == 0) return CeedError(ceed, 1, 154d7b241e6Sjeremylt "At least one restriction required"); 155d7b241e6Sjeremylt if (op->numqpoints == 0) return CeedError(ceed, 1, 156d7b241e6Sjeremylt "At least one non-colocated basis required"); 157d7b241e6Sjeremylt ierr = op->Apply(op, in, out, request); CeedChk(ierr); 158d7b241e6Sjeremylt return 0; 159d7b241e6Sjeremylt } 160d7b241e6Sjeremylt 161d7b241e6Sjeremylt /** 162*b11c1e72Sjeremylt @brief Destroy a CeedOperator 163d7b241e6Sjeremylt 164d7b241e6Sjeremylt @param op CeedOperator to destroy 165*b11c1e72Sjeremylt 166*b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 167*b11c1e72Sjeremylt **/ 168d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) { 169d7b241e6Sjeremylt int ierr; 170d7b241e6Sjeremylt 171d7b241e6Sjeremylt if (!*op || --(*op)->refcount > 0) return 0; 172d7b241e6Sjeremylt if ((*op)->Destroy) { 173d7b241e6Sjeremylt ierr = (*op)->Destroy(*op); CeedChk(ierr); 174d7b241e6Sjeremylt } 175d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 176d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 177d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 178d7b241e6Sjeremylt ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 179d7b241e6Sjeremylt ierr = CeedFree(op); CeedChk(ierr); 180d7b241e6Sjeremylt return 0; 181d7b241e6Sjeremylt } 182d7b241e6Sjeremylt 183d7b241e6Sjeremylt /// @} 184