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> 18d863ab9bSjeremylt #include <ceed-backend.h> 19d7b241e6Sjeremylt #include <string.h> 20d7b241e6Sjeremylt 21dfdf5a53Sjeremylt /// @file 22dfdf5a53Sjeremylt /// Implementation of public CeedOperator interfaces 23dfdf5a53Sjeremylt /// 24dfdf5a53Sjeremylt /// @addtogroup CeedOperator 25dfdf5a53Sjeremylt /// @{ 26d7b241e6Sjeremylt 27d7b241e6Sjeremylt /** 28b11c1e72Sjeremylt @brief Create an operator from element restriction, basis, and QFunction 29d7b241e6Sjeremylt 30b11c1e72Sjeremylt @param ceed A Ceed object where the CeedOperator will be created 31d7b241e6Sjeremylt @param qf QFunction defining the action of the operator at quadrature points 32d7b241e6Sjeremylt @param dqf QFunction defining the action of the Jacobian of @a qf (or NULL) 33d7b241e6Sjeremylt @param dqfT QFunction defining the action of the transpose of the Jacobian 34d7b241e6Sjeremylt of @a qf (or NULL) 35b11c1e72Sjeremylt @param[out] op Address of the variable where the newly created 36b11c1e72Sjeremylt CeedOperator will be stored 37b11c1e72Sjeremylt 38b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 39dfdf5a53Sjeremylt 40dfdf5a53Sjeremylt @ref Basic 41d7b241e6Sjeremylt */ 42d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf, 43d7b241e6Sjeremylt CeedQFunction dqfT, CeedOperator *op) { 44d7b241e6Sjeremylt int ierr; 45d7b241e6Sjeremylt 465fe0d4faSjeremylt if (!ceed->OperatorCreate) { 475fe0d4faSjeremylt Ceed delegate; 485fe0d4faSjeremylt ierr = CeedGetDelegate(ceed, &delegate); CeedChk(ierr); 495fe0d4faSjeremylt 505fe0d4faSjeremylt if (!delegate) 515fe0d4faSjeremylt return CeedError(ceed, 1, "Backend does not support OperatorCreate"); 525fe0d4faSjeremylt 535fe0d4faSjeremylt ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr); 545fe0d4faSjeremylt return 0; 555fe0d4faSjeremylt } 565fe0d4faSjeremylt 57d7b241e6Sjeremylt ierr = CeedCalloc(1,op); CeedChk(ierr); 58d7b241e6Sjeremylt (*op)->ceed = ceed; 59d7b241e6Sjeremylt ceed->refcount++; 60d7b241e6Sjeremylt (*op)->refcount = 1; 61d7b241e6Sjeremylt (*op)->qf = qf; 62d7b241e6Sjeremylt qf->refcount++; 63d7b241e6Sjeremylt (*op)->dqf = dqf; 64d7b241e6Sjeremylt if (dqf) dqf->refcount++; 65d7b241e6Sjeremylt (*op)->dqfT = dqfT; 66d7b241e6Sjeremylt if (dqfT) dqfT->refcount++; 67d7b241e6Sjeremylt ierr = ceed->OperatorCreate(*op); CeedChk(ierr); 68d7b241e6Sjeremylt return 0; 69d7b241e6Sjeremylt } 70d7b241e6Sjeremylt 71d7b241e6Sjeremylt /** 72b11c1e72Sjeremylt @brief Provide a field to a CeedOperator for use by its CeedQFunction 73d7b241e6Sjeremylt 74d7b241e6Sjeremylt This function is used to specify both active and passive fields to a 75d7b241e6Sjeremylt CeedOperator. For passive fields, a vector @arg v must be provided. Passive 76d7b241e6Sjeremylt fields can inputs or outputs (updated in-place when operator is applied). 77d7b241e6Sjeremylt 78d7b241e6Sjeremylt Active fields must be specified using this function, but their data (in a 79d7b241e6Sjeremylt CeedVector) is passed in CeedOperatorApply(). There can be at most one active 80d7b241e6Sjeremylt input and at most one active output. 81d7b241e6Sjeremylt 82b11c1e72Sjeremylt @param op Ceedoperator on which to provide the field 83b11c1e72Sjeremylt @param fieldname Name of the field (to be matched with the name used by CeedQFunction) 84b11c1e72Sjeremylt @param r CeedElemRestriction 85783c99b3SValeria Barra @param b CeedBasis in which the field resides or CEED_BASIS_COLLOCATED 86b11c1e72Sjeremylt if collocated with quadrature points 87b11c1e72Sjeremylt @param v CeedVector to be used by CeedOperator or CEED_VECTOR_ACTIVE 88b11c1e72Sjeremylt if field is active or CEED_VECTOR_NONE if using 89b11c1e72Sjeremylt CEED_EVAL_WEIGHT in the qfunction 90b11c1e72Sjeremylt 91b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 92dfdf5a53Sjeremylt 93dfdf5a53Sjeremylt @ref Basic 94b11c1e72Sjeremylt **/ 95d7b241e6Sjeremylt int CeedOperatorSetField(CeedOperator op, const char *fieldname, 96*4dccadb6Sjeremylt CeedElemRestriction r, CeedTransposeMode lmode, 97*4dccadb6Sjeremylt CeedBasis b, CeedVector v) { 98d7b241e6Sjeremylt int ierr; 99d7b241e6Sjeremylt CeedInt numelements; 100d7b241e6Sjeremylt ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr); 101d7b241e6Sjeremylt if (op->numelements && op->numelements != numelements) 102d7b241e6Sjeremylt return CeedError(op->ceed, 1, 103d7b241e6Sjeremylt "ElemRestriction with %d elements incompatible with prior %d elements", 104d7b241e6Sjeremylt numelements, op->numelements); 105d7b241e6Sjeremylt op->numelements = numelements; 106d7b241e6Sjeremylt 107783c99b3SValeria Barra if (b != CEED_BASIS_COLLOCATED) { 108d7b241e6Sjeremylt CeedInt numqpoints; 109d7b241e6Sjeremylt ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr); 110d7b241e6Sjeremylt if (op->numqpoints && op->numqpoints != numqpoints) 111d7b241e6Sjeremylt return CeedError(op->ceed, 1, 112d7b241e6Sjeremylt "Basis with %d quadrature points incompatible with prior %d points", 113d7b241e6Sjeremylt numqpoints, op->numqpoints); 114d7b241e6Sjeremylt op->numqpoints = numqpoints; 115d7b241e6Sjeremylt } 116d1bcdac9Sjeremylt CeedOperatorField *ofield; 117d7b241e6Sjeremylt for (CeedInt i=0; i<op->qf->numinputfields; i++) { 118d7b241e6Sjeremylt if (!strcmp(fieldname, op->qf->inputfields[i].fieldname)) { 119d7b241e6Sjeremylt ofield = &op->inputfields[i]; 120d7b241e6Sjeremylt goto found; 121d7b241e6Sjeremylt } 122d7b241e6Sjeremylt } 123d7b241e6Sjeremylt for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 124d7b241e6Sjeremylt if (!strcmp(fieldname, op->qf->outputfields[i].fieldname)) { 125d7b241e6Sjeremylt ofield = &op->outputfields[i]; 126d7b241e6Sjeremylt goto found; 127d7b241e6Sjeremylt } 128d7b241e6Sjeremylt } 129d7b241e6Sjeremylt return CeedError(op->ceed, 1, "QFunction has no knowledge of field '%s'", 130d7b241e6Sjeremylt fieldname); 131d7b241e6Sjeremylt found: 132d7b241e6Sjeremylt ofield->Erestrict = r; 133*4dccadb6Sjeremylt ofield->lmode = lmode; 134d7b241e6Sjeremylt ofield->basis = b; 135d7b241e6Sjeremylt ofield->vec = v; 136d7b241e6Sjeremylt op->nfields += 1; 137d7b241e6Sjeremylt return 0; 138d7b241e6Sjeremylt } 139d7b241e6Sjeremylt 140d7b241e6Sjeremylt /** 141b11c1e72Sjeremylt @brief Apply CeedOperator to a vector 142d7b241e6Sjeremylt 143d7b241e6Sjeremylt This computes the action of the operator on the specified (active) input, 144d7b241e6Sjeremylt yielding its (active) output. All inputs and outputs must be specified using 145d7b241e6Sjeremylt CeedOperatorSetField(). 146d7b241e6Sjeremylt 147d7b241e6Sjeremylt @param op CeedOperator to apply 148b11c1e72Sjeremylt @param[in] in CeedVector containing input state or NULL if there are no 149b11c1e72Sjeremylt active inputs 150b11c1e72Sjeremylt @param[out] out CeedVector to store result of applying operator (must be 151d7b241e6Sjeremylt distinct from @a in) or NULL if there are no active outputs 152d7b241e6Sjeremylt @param request Address of CeedRequest for non-blocking completion, else 153d7b241e6Sjeremylt CEED_REQUEST_IMMEDIATE 154b11c1e72Sjeremylt 155b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 156dfdf5a53Sjeremylt 157dfdf5a53Sjeremylt @ref Basic 158b11c1e72Sjeremylt **/ 159d7b241e6Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, 160d7b241e6Sjeremylt CeedVector out, CeedRequest *request) { 161d7b241e6Sjeremylt int ierr; 162d7b241e6Sjeremylt Ceed ceed = op->ceed; 163d7b241e6Sjeremylt CeedQFunction qf = op->qf; 164d7b241e6Sjeremylt 165d7b241e6Sjeremylt if (op->nfields == 0) return CeedError(ceed, 1, "No operator fields set"); 166d7b241e6Sjeremylt if (op->nfields < qf->numinputfields + qf->numoutputfields) return CeedError( 167d7b241e6Sjeremylt ceed, 1, "Not all operator fields set"); 168d7b241e6Sjeremylt if (op->numelements == 0) return CeedError(ceed, 1, 169d7b241e6Sjeremylt "At least one restriction required"); 170d7b241e6Sjeremylt if (op->numqpoints == 0) return CeedError(ceed, 1, 171783c99b3SValeria Barra "At least one non-collocated basis required"); 172d7b241e6Sjeremylt ierr = op->Apply(op, in, out, request); CeedChk(ierr); 173d7b241e6Sjeremylt return 0; 174d7b241e6Sjeremylt } 175d7b241e6Sjeremylt 176d7b241e6Sjeremylt /** 1774ce2993fSjeremylt @brief Get the Ceed associated with a CeedOperator 1784ce2993fSjeremylt 1794ce2993fSjeremylt @param op CeedOperator 1804ce2993fSjeremylt @param[out] ceed Variable to store Ceed 1814ce2993fSjeremylt 1824ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 1834ce2993fSjeremylt 18423617272Sjeremylt @ref Advanced 1854ce2993fSjeremylt **/ 1864ce2993fSjeremylt 1874ce2993fSjeremylt int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 1884ce2993fSjeremylt *ceed = op->ceed; 1894ce2993fSjeremylt return 0; 1904ce2993fSjeremylt } 1914ce2993fSjeremylt 1924ce2993fSjeremylt /** 1934ce2993fSjeremylt @brief Get the number of elements associated with a CeedOperator 1944ce2993fSjeremylt 1954ce2993fSjeremylt @param op CeedOperator 1964ce2993fSjeremylt @param[out] numelem Variable to store number of elements 1974ce2993fSjeremylt 1984ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 1994ce2993fSjeremylt 20023617272Sjeremylt @ref Advanced 2014ce2993fSjeremylt **/ 2024ce2993fSjeremylt 2034ce2993fSjeremylt int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) { 2044ce2993fSjeremylt *numelem = op->numelements; 2054ce2993fSjeremylt return 0; 2064ce2993fSjeremylt } 2074ce2993fSjeremylt 2084ce2993fSjeremylt /** 2094ce2993fSjeremylt @brief Get the number of quadrature points associated with a CeedOperator 2104ce2993fSjeremylt 2114ce2993fSjeremylt @param op CeedOperator 2124ce2993fSjeremylt @param[out] numqpts Variable to store vector number of quadrature points 2134ce2993fSjeremylt 2144ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 2154ce2993fSjeremylt 21623617272Sjeremylt @ref Advanced 2174ce2993fSjeremylt **/ 2184ce2993fSjeremylt 2194ce2993fSjeremylt int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) { 2204ce2993fSjeremylt *numqpts = op->numqpoints; 2214ce2993fSjeremylt return 0; 2224ce2993fSjeremylt } 2234ce2993fSjeremylt 2244ce2993fSjeremylt /** 2254ce2993fSjeremylt @brief Get the number of arguments associated with a CeedOperator 2264ce2993fSjeremylt 2274ce2993fSjeremylt @param op CeedOperator 2284ce2993fSjeremylt @param[out] numargs Variable to store vector number of arguments 2294ce2993fSjeremylt 2304ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 2314ce2993fSjeremylt 23223617272Sjeremylt @ref Advanced 2334ce2993fSjeremylt **/ 2344ce2993fSjeremylt 2354ce2993fSjeremylt int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) { 2364ce2993fSjeremylt *numargs = op->nfields; 2374ce2993fSjeremylt return 0; 2384ce2993fSjeremylt } 2394ce2993fSjeremylt 2404ce2993fSjeremylt /** 2414ce2993fSjeremylt @brief Get the setup status of a CeedOperator 2424ce2993fSjeremylt 2434ce2993fSjeremylt @param op CeedOperator 2444ce2993fSjeremylt @param[out] numelem Variable to store setup status 2454ce2993fSjeremylt 2464ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 2474ce2993fSjeremylt 24823617272Sjeremylt @ref Advanced 2494ce2993fSjeremylt **/ 2504ce2993fSjeremylt 2514ce2993fSjeremylt int CeedOperatorGetSetupStatus(CeedOperator op, bool *setupdone) { 2524ce2993fSjeremylt *setupdone = op->setupdone; 2534ce2993fSjeremylt return 0; 2544ce2993fSjeremylt } 2554ce2993fSjeremylt 2564ce2993fSjeremylt /** 2574ce2993fSjeremylt @brief Get the QFunction associated with a CeedOperator 2584ce2993fSjeremylt 2594ce2993fSjeremylt @param op CeedOperator 2604ce2993fSjeremylt @param[out] qf Variable to store qfunction 2614ce2993fSjeremylt 2624ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 2634ce2993fSjeremylt 26423617272Sjeremylt @ref Advanced 2654ce2993fSjeremylt **/ 2664ce2993fSjeremylt 2674ce2993fSjeremylt int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 2684ce2993fSjeremylt *qf = op->qf; 2694ce2993fSjeremylt return 0; 2704ce2993fSjeremylt } 2714ce2993fSjeremylt 2724ce2993fSjeremylt /** 2734ce2993fSjeremylt @brief Get the backend data of a CeedOperator 2744ce2993fSjeremylt 2754ce2993fSjeremylt @param op CeedOperator 2764ce2993fSjeremylt @param[out] data Variable to store data 2774ce2993fSjeremylt 2784ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 2794ce2993fSjeremylt 28023617272Sjeremylt @ref Advanced 2814ce2993fSjeremylt **/ 2824ce2993fSjeremylt 2834ce2993fSjeremylt int CeedOperatorGetData(CeedOperator op, void* *data) { 2844ce2993fSjeremylt *data = op->data; 2854ce2993fSjeremylt return 0; 2864ce2993fSjeremylt } 2874ce2993fSjeremylt 2884ce2993fSjeremylt /** 2894ce2993fSjeremylt @brief Set the setup flag of a CeedOperator to True 2904ce2993fSjeremylt 2914ce2993fSjeremylt @param op CeedOperator 2924ce2993fSjeremylt 2934ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 2944ce2993fSjeremylt 29523617272Sjeremylt @ref Advanced 2964ce2993fSjeremylt **/ 2974ce2993fSjeremylt 2984ce2993fSjeremylt int CeedOperatorSetSetupDone(CeedOperator op) { 2994ce2993fSjeremylt op->setupdone = 1; 3004ce2993fSjeremylt return 0; 3014ce2993fSjeremylt } 3024ce2993fSjeremylt 3034ce2993fSjeremylt /** 304d1bcdac9Sjeremylt @brief Get the CeedOperatorFields of a CeedOperator 305d1bcdac9Sjeremylt 306d1bcdac9Sjeremylt @param op CeedOperator 307d1bcdac9Sjeremylt @param[out] inputfields Variable to store inputfields 308d1bcdac9Sjeremylt @param[out] outputfields Variable to store outputfields 309d1bcdac9Sjeremylt 310d1bcdac9Sjeremylt @return An error code: 0 - success, otherwise - failure 311d1bcdac9Sjeremylt 312d1bcdac9Sjeremylt @ref Advanced 313d1bcdac9Sjeremylt **/ 314d1bcdac9Sjeremylt 315d1bcdac9Sjeremylt int CeedOperatorGetFields(CeedOperator op, 316d1bcdac9Sjeremylt CeedOperatorField* *inputfields, 317d1bcdac9Sjeremylt CeedOperatorField* *outputfields) { 318d1bcdac9Sjeremylt if (inputfields) *inputfields = op->inputfields; 319d1bcdac9Sjeremylt if (outputfields) *outputfields = op->outputfields; 320d1bcdac9Sjeremylt return 0; 321d1bcdac9Sjeremylt } 322d1bcdac9Sjeremylt 323d1bcdac9Sjeremylt /** 324*4dccadb6Sjeremylt @brief Get the L vector CeedTransposeMode of a CeedOperatorField 325*4dccadb6Sjeremylt 326*4dccadb6Sjeremylt @param opfield CeedOperatorField 327*4dccadb6Sjeremylt @param[out] lmode Variable to store CeedTransposeMode 328*4dccadb6Sjeremylt 329*4dccadb6Sjeremylt @return An error code: 0 - success, otherwise - failure 330*4dccadb6Sjeremylt 331*4dccadb6Sjeremylt @ref Advanced 332*4dccadb6Sjeremylt **/ 333*4dccadb6Sjeremylt 334*4dccadb6Sjeremylt int CeedOperatorFieldGetLMode(CeedOperatorField opfield, 335*4dccadb6Sjeremylt CeedTransposeMode *lmode) { 336*4dccadb6Sjeremylt *lmode = (&opfield)->lmode; 337*4dccadb6Sjeremylt return 0; 338*4dccadb6Sjeremylt }/** 339d1bcdac9Sjeremylt @brief Get the CeedElemRestriction of a CeedOperatorField 340d1bcdac9Sjeremylt 341d1bcdac9Sjeremylt @param opfield CeedOperatorField 342d1bcdac9Sjeremylt @param[out] rstr Variable to store CeedElemRestriction 343d1bcdac9Sjeremylt 344d1bcdac9Sjeremylt @return An error code: 0 - success, otherwise - failure 345d1bcdac9Sjeremylt 346d1bcdac9Sjeremylt @ref Advanced 347d1bcdac9Sjeremylt **/ 348d1bcdac9Sjeremylt 349d1bcdac9Sjeremylt int CeedOperatorFieldGetElemRestriction(CeedOperatorField opfield, 350d1bcdac9Sjeremylt CeedElemRestriction *rstr) { 351d1bcdac9Sjeremylt *rstr = (&opfield)->Erestrict; 352d1bcdac9Sjeremylt return 0; 353d1bcdac9Sjeremylt } 354d1bcdac9Sjeremylt 355d1bcdac9Sjeremylt /** 356d1bcdac9Sjeremylt @brief Get the CeedBasis of a CeedOperatorField 357d1bcdac9Sjeremylt 358d1bcdac9Sjeremylt @param opfield CeedOperatorField 359d1bcdac9Sjeremylt @param[out] basis Variable to store CeedBasis 360d1bcdac9Sjeremylt 361d1bcdac9Sjeremylt @return An error code: 0 - success, otherwise - failure 362d1bcdac9Sjeremylt 363d1bcdac9Sjeremylt @ref Advanced 364d1bcdac9Sjeremylt **/ 365d1bcdac9Sjeremylt 366d1bcdac9Sjeremylt int CeedOperatorFieldGetBasis(CeedOperatorField opfield, 367d1bcdac9Sjeremylt CeedBasis *basis) { 368d1bcdac9Sjeremylt *basis = (&opfield)->basis; 369d1bcdac9Sjeremylt return 0; 370d1bcdac9Sjeremylt } 371d1bcdac9Sjeremylt 372d1bcdac9Sjeremylt /** 373d1bcdac9Sjeremylt @brief Get the CeedVector of a CeedOperatorField 374d1bcdac9Sjeremylt 375d1bcdac9Sjeremylt @param opfield CeedOperatorField 376d1bcdac9Sjeremylt @param[out] vec Variable to store CeedVector 377d1bcdac9Sjeremylt 378d1bcdac9Sjeremylt @return An error code: 0 - success, otherwise - failure 379d1bcdac9Sjeremylt 380d1bcdac9Sjeremylt @ref Advanced 381d1bcdac9Sjeremylt **/ 382d1bcdac9Sjeremylt 383d1bcdac9Sjeremylt int CeedOperatorFieldGetVector(CeedOperatorField opfield, 384d1bcdac9Sjeremylt CeedVector *vec) { 385d1bcdac9Sjeremylt *vec = (&opfield)->vec; 386d1bcdac9Sjeremylt return 0; 387d1bcdac9Sjeremylt } 388d1bcdac9Sjeremylt 389d1bcdac9Sjeremylt /** 390b11c1e72Sjeremylt @brief Destroy a CeedOperator 391d7b241e6Sjeremylt 392d7b241e6Sjeremylt @param op CeedOperator to destroy 393b11c1e72Sjeremylt 394b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 395dfdf5a53Sjeremylt 396dfdf5a53Sjeremylt @ref Basic 397b11c1e72Sjeremylt **/ 398d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) { 399d7b241e6Sjeremylt int ierr; 400d7b241e6Sjeremylt 401d7b241e6Sjeremylt if (!*op || --(*op)->refcount > 0) return 0; 402d7b241e6Sjeremylt if ((*op)->Destroy) { 403d7b241e6Sjeremylt ierr = (*op)->Destroy(*op); CeedChk(ierr); 404d7b241e6Sjeremylt } 405d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 406d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 407d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 408d7b241e6Sjeremylt ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 409d7b241e6Sjeremylt ierr = CeedFree(op); CeedChk(ierr); 410d7b241e6Sjeremylt return 0; 411d7b241e6Sjeremylt } 412d7b241e6Sjeremylt 413d7b241e6Sjeremylt /// @} 414