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 /** 280219ea01SJeremy L Thompson @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and 290219ea01SJeremy L Thompson CeedElemRestriction can be associated with CeedQFunction fields with 300219ea01SJeremy L Thompson \ref CeedOperatorSetField. 31d7b241e6Sjeremylt 32b11c1e72Sjeremylt @param ceed A Ceed object where the CeedOperator will be created 33d7b241e6Sjeremylt @param qf QFunction defining the action of the operator at quadrature points 34*34138859Sjeremylt @param dqf QFunction defining the action of the Jacobian of @a qf (or 35*34138859Sjeremylt CEED_QFUNCTION_NONE) 36d7b241e6Sjeremylt @param dqfT QFunction defining the action of the transpose of the Jacobian 37*34138859Sjeremylt of @a qf (or CEED_QFUNCTION_NONE) 38b11c1e72Sjeremylt @param[out] op Address of the variable where the newly created 39b11c1e72Sjeremylt CeedOperator will be stored 40b11c1e72Sjeremylt 41b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 42dfdf5a53Sjeremylt 43dfdf5a53Sjeremylt @ref Basic 44d7b241e6Sjeremylt */ 45d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf, 46d7b241e6Sjeremylt CeedQFunction dqfT, CeedOperator *op) { 47d7b241e6Sjeremylt int ierr; 48d7b241e6Sjeremylt 495fe0d4faSjeremylt if (!ceed->OperatorCreate) { 505fe0d4faSjeremylt Ceed delegate; 51aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 525fe0d4faSjeremylt 535fe0d4faSjeremylt if (!delegate) 54c042f62fSJeremy L Thompson // LCOV_EXCL_START 555fe0d4faSjeremylt return CeedError(ceed, 1, "Backend does not support OperatorCreate"); 56c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 575fe0d4faSjeremylt 585fe0d4faSjeremylt ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr); 595fe0d4faSjeremylt return 0; 605fe0d4faSjeremylt } 615fe0d4faSjeremylt 62d7b241e6Sjeremylt ierr = CeedCalloc(1, op); CeedChk(ierr); 63d7b241e6Sjeremylt (*op)->ceed = ceed; 64d7b241e6Sjeremylt ceed->refcount++; 65d7b241e6Sjeremylt (*op)->refcount = 1; 66442e7f0bSjeremylt if (qf == CEED_QFUNCTION_NONE) 67442e7f0bSjeremylt // LCOV_EXCL_START 68442e7f0bSjeremylt return CeedError(ceed, 1, "Operator must have a valid QFunction."); 69442e7f0bSjeremylt // LCOV_EXCL_STOP 70d7b241e6Sjeremylt (*op)->qf = qf; 71d7b241e6Sjeremylt qf->refcount++; 72442e7f0bSjeremylt if (dqf && dqf != CEED_QFUNCTION_NONE) { 73d7b241e6Sjeremylt (*op)->dqf = dqf; 74442e7f0bSjeremylt dqf->refcount++; 75442e7f0bSjeremylt } 76442e7f0bSjeremylt if (dqfT && dqfT != CEED_QFUNCTION_NONE) { 77d7b241e6Sjeremylt (*op)->dqfT = dqfT; 78442e7f0bSjeremylt dqfT->refcount++; 79442e7f0bSjeremylt } 80fe2413ffSjeremylt ierr = CeedCalloc(16, &(*op)->inputfields); CeedChk(ierr); 81fe2413ffSjeremylt ierr = CeedCalloc(16, &(*op)->outputfields); CeedChk(ierr); 82d7b241e6Sjeremylt ierr = ceed->OperatorCreate(*op); CeedChk(ierr); 83d7b241e6Sjeremylt return 0; 84d7b241e6Sjeremylt } 85d7b241e6Sjeremylt 86d7b241e6Sjeremylt /** 8752d6035fSJeremy L Thompson @brief Create an operator that composes the action of several operators 8852d6035fSJeremy L Thompson 8952d6035fSJeremy L Thompson @param ceed A Ceed object where the CeedOperator will be created 9052d6035fSJeremy L Thompson @param[out] op Address of the variable where the newly created 9152d6035fSJeremy L Thompson Composite CeedOperator will be stored 9252d6035fSJeremy L Thompson 9352d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 9452d6035fSJeremy L Thompson 9552d6035fSJeremy L Thompson @ref Basic 9652d6035fSJeremy L Thompson */ 9752d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) { 9852d6035fSJeremy L Thompson int ierr; 9952d6035fSJeremy L Thompson 10052d6035fSJeremy L Thompson if (!ceed->CompositeOperatorCreate) { 10152d6035fSJeremy L Thompson Ceed delegate; 102aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 10352d6035fSJeremy L Thompson 10452d6035fSJeremy L Thompson if (!delegate) 105c042f62fSJeremy L Thompson // LCOV_EXCL_START 1061d102b48SJeremy L Thompson return CeedError(ceed, 1, "Backend does not support " 1071d102b48SJeremy L Thompson "CompositeOperatorCreate"); 108c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 10952d6035fSJeremy L Thompson 11052d6035fSJeremy L Thompson ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr); 11152d6035fSJeremy L Thompson return 0; 11252d6035fSJeremy L Thompson } 11352d6035fSJeremy L Thompson 11452d6035fSJeremy L Thompson ierr = CeedCalloc(1,op); CeedChk(ierr); 11552d6035fSJeremy L Thompson (*op)->ceed = ceed; 11652d6035fSJeremy L Thompson ceed->refcount++; 11752d6035fSJeremy L Thompson (*op)->composite = true; 11852d6035fSJeremy L Thompson ierr = CeedCalloc(16, &(*op)->suboperators); CeedChk(ierr); 11952d6035fSJeremy L Thompson ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr); 12052d6035fSJeremy L Thompson return 0; 12152d6035fSJeremy L Thompson } 12252d6035fSJeremy L Thompson 12352d6035fSJeremy L Thompson /** 124b11c1e72Sjeremylt @brief Provide a field to a CeedOperator for use by its CeedQFunction 125d7b241e6Sjeremylt 126d7b241e6Sjeremylt This function is used to specify both active and passive fields to a 127d7b241e6Sjeremylt CeedOperator. For passive fields, a vector @arg v must be provided. Passive 128d7b241e6Sjeremylt fields can inputs or outputs (updated in-place when operator is applied). 129d7b241e6Sjeremylt 130d7b241e6Sjeremylt Active fields must be specified using this function, but their data (in a 131d7b241e6Sjeremylt CeedVector) is passed in CeedOperatorApply(). There can be at most one active 132d7b241e6Sjeremylt input and at most one active output. 133d7b241e6Sjeremylt 1348c91a0c9SJeremy L Thompson @param op CeedOperator on which to provide the field 1358795c945Sjeremylt @param fieldname Name of the field (to be matched with the name used by 1368795c945Sjeremylt CeedQFunction) 137b11c1e72Sjeremylt @param r CeedElemRestriction 138b0e29e78Sjeremylt @param lmode CeedTransposeMode which specifies the ordering of the 139b0e29e78Sjeremylt components of the l-vector used by this CeedOperatorField, 140b0e29e78Sjeremylt CEED_NOTRANSPOSE indicates the component is the 141b0e29e78Sjeremylt outermost index and CEED_TRANSPOSE indicates the component 142b0e29e78Sjeremylt is the innermost index in ordering of the l-vector 143783c99b3SValeria Barra @param b CeedBasis in which the field resides or CEED_BASIS_COLLOCATED 144b11c1e72Sjeremylt if collocated with quadrature points 145b11c1e72Sjeremylt @param v CeedVector to be used by CeedOperator or CEED_VECTOR_ACTIVE 146b11c1e72Sjeremylt if field is active or CEED_VECTOR_NONE if using 1478c91a0c9SJeremy L Thompson CEED_EVAL_WEIGHT in the QFunction 148b11c1e72Sjeremylt 149b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 150dfdf5a53Sjeremylt 151dfdf5a53Sjeremylt @ref Basic 152b11c1e72Sjeremylt **/ 153d7b241e6Sjeremylt int CeedOperatorSetField(CeedOperator op, const char *fieldname, 1544dccadb6Sjeremylt CeedElemRestriction r, CeedTransposeMode lmode, 1554dccadb6Sjeremylt CeedBasis b, CeedVector v) { 156d7b241e6Sjeremylt int ierr; 15752d6035fSJeremy L Thompson if (op->composite) 158c042f62fSJeremy L Thompson // LCOV_EXCL_START 15952d6035fSJeremy L Thompson return CeedError(op->ceed, 1, "Cannot add field to composite operator."); 160c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1618b067b84SJed Brown if (!r) 162c042f62fSJeremy L Thompson // LCOV_EXCL_START 163c042f62fSJeremy L Thompson return CeedError(op->ceed, 1, 164c042f62fSJeremy L Thompson "ElemRestriction r for field \"%s\" must be non-NULL.", 165c042f62fSJeremy L Thompson fieldname); 166c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1678b067b84SJed Brown if (!b) 168c042f62fSJeremy L Thompson // LCOV_EXCL_START 169c042f62fSJeremy L Thompson return CeedError(op->ceed, 1, "Basis b for field \"%s\" must be non-NULL.", 170c042f62fSJeremy L Thompson fieldname); 171c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1728b067b84SJed Brown if (!v) 173c042f62fSJeremy L Thompson // LCOV_EXCL_START 174c042f62fSJeremy L Thompson return CeedError(op->ceed, 1, "Vector v for field \"%s\" must be non-NULL.", 175c042f62fSJeremy L Thompson fieldname); 176c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 17752d6035fSJeremy L Thompson 178d7b241e6Sjeremylt CeedInt numelements; 179d7b241e6Sjeremylt ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr); 1802cb0afc5Sjeremylt if (op->hasrestriction && op->numelements != numelements) 181c042f62fSJeremy L Thompson // LCOV_EXCL_START 182d7b241e6Sjeremylt return CeedError(op->ceed, 1, 1831d102b48SJeremy L Thompson "ElemRestriction with %d elements incompatible with prior " 1841d102b48SJeremy L Thompson "%d elements", numelements, op->numelements); 185c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 186d7b241e6Sjeremylt op->numelements = numelements; 1872cb0afc5Sjeremylt op->hasrestriction = true; // Restriction set, but numelements may be 0 188d7b241e6Sjeremylt 189783c99b3SValeria Barra if (b != CEED_BASIS_COLLOCATED) { 190d7b241e6Sjeremylt CeedInt numqpoints; 191d7b241e6Sjeremylt ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr); 192d7b241e6Sjeremylt if (op->numqpoints && op->numqpoints != numqpoints) 193c042f62fSJeremy L Thompson // LCOV_EXCL_START 1941d102b48SJeremy L Thompson return CeedError(op->ceed, 1, "Basis with %d quadrature points " 1951d102b48SJeremy L Thompson "incompatible with prior %d points", numqpoints, 1961d102b48SJeremy L Thompson op->numqpoints); 197c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 198d7b241e6Sjeremylt op->numqpoints = numqpoints; 199d7b241e6Sjeremylt } 200d1bcdac9Sjeremylt CeedOperatorField *ofield; 201d7b241e6Sjeremylt for (CeedInt i=0; i<op->qf->numinputfields; i++) { 202fe2413ffSjeremylt if (!strcmp(fieldname, (*op->qf->inputfields[i]).fieldname)) { 203d7b241e6Sjeremylt ofield = &op->inputfields[i]; 204d7b241e6Sjeremylt goto found; 205d7b241e6Sjeremylt } 206d7b241e6Sjeremylt } 207d7b241e6Sjeremylt for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 208fe2413ffSjeremylt if (!strcmp(fieldname, (*op->qf->outputfields[i]).fieldname)) { 209d7b241e6Sjeremylt ofield = &op->outputfields[i]; 210d7b241e6Sjeremylt goto found; 211d7b241e6Sjeremylt } 212d7b241e6Sjeremylt } 213c042f62fSJeremy L Thompson // LCOV_EXCL_START 214d7b241e6Sjeremylt return CeedError(op->ceed, 1, "QFunction has no knowledge of field '%s'", 215d7b241e6Sjeremylt fieldname); 216c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 217d7b241e6Sjeremylt found: 218fe2413ffSjeremylt ierr = CeedCalloc(1, ofield); CeedChk(ierr); 219fe2413ffSjeremylt (*ofield)->Erestrict = r; 22071352a93Sjeremylt r->refcount += 1; 221fe2413ffSjeremylt (*ofield)->lmode = lmode; 222fe2413ffSjeremylt (*ofield)->basis = b; 22371352a93Sjeremylt if (b != CEED_BASIS_COLLOCATED) 22471352a93Sjeremylt b->refcount += 1; 225fe2413ffSjeremylt (*ofield)->vec = v; 22671352a93Sjeremylt if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) 22771352a93Sjeremylt v->refcount += 1; 228d7b241e6Sjeremylt op->nfields += 1; 229d7b241e6Sjeremylt return 0; 230d7b241e6Sjeremylt } 231d7b241e6Sjeremylt 232d7b241e6Sjeremylt /** 23352d6035fSJeremy L Thompson @brief Add a sub-operator to a composite CeedOperator 234288c0443SJeremy L Thompson 235*34138859Sjeremylt @param[out] compositeop Composite CeedOperator 236*34138859Sjeremylt @param subop Sub-operator CeedOperator 23752d6035fSJeremy L Thompson 23852d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 23952d6035fSJeremy L Thompson 24052d6035fSJeremy L Thompson @ref Basic 24152d6035fSJeremy L Thompson */ 242692c2638Sjeremylt int CeedCompositeOperatorAddSub(CeedOperator compositeop, CeedOperator subop) { 24352d6035fSJeremy L Thompson if (!compositeop->composite) 244c042f62fSJeremy L Thompson // LCOV_EXCL_START 2451d102b48SJeremy L Thompson return CeedError(compositeop->ceed, 1, "CeedOperator is not a composite " 2461d102b48SJeremy L Thompson "operator"); 247c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 24852d6035fSJeremy L Thompson 24952d6035fSJeremy L Thompson if (compositeop->numsub == CEED_COMPOSITE_MAX) 250c042f62fSJeremy L Thompson // LCOV_EXCL_START 2511d102b48SJeremy L Thompson return CeedError(compositeop->ceed, 1, "Cannot add additional suboperators"); 252c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 25352d6035fSJeremy L Thompson 25452d6035fSJeremy L Thompson compositeop->suboperators[compositeop->numsub] = subop; 25552d6035fSJeremy L Thompson subop->refcount++; 25652d6035fSJeremy L Thompson compositeop->numsub++; 25752d6035fSJeremy L Thompson return 0; 25852d6035fSJeremy L Thompson } 25952d6035fSJeremy L Thompson 26052d6035fSJeremy L Thompson /** 2615107b09fSJeremy L Thompson @brief Duplicate a CeedOperator with a reference Ceed to fallback for advanced 2625107b09fSJeremy L Thompson CeedOperator functionality 2635107b09fSJeremy L Thompson 2645107b09fSJeremy L Thompson @param op CeedOperator to create fallback for 2655107b09fSJeremy L Thompson 2665107b09fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 2675107b09fSJeremy L Thompson 2685107b09fSJeremy L Thompson @ref Developer 2695107b09fSJeremy L Thompson **/ 2705107b09fSJeremy L Thompson int CeedOperatorCreateFallback(CeedOperator op) { 2715107b09fSJeremy L Thompson int ierr; 2725107b09fSJeremy L Thompson 2735107b09fSJeremy L Thompson // Fallback Ceed 2745107b09fSJeremy L Thompson const char *resource, *fallbackresource; 2755107b09fSJeremy L Thompson ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr); 2765107b09fSJeremy L Thompson ierr = CeedGetOperatorFallbackResource(op->ceed, &fallbackresource); 2775107b09fSJeremy L Thompson CeedChk(ierr); 2785107b09fSJeremy L Thompson if (!strcmp(resource, fallbackresource)) 2795107b09fSJeremy L Thompson // LCOV_EXCL_START 2805107b09fSJeremy L Thompson return CeedError(op->ceed, 1, "Backend %s cannot create an operator" 2815107b09fSJeremy L Thompson "fallback to resource %s", resource, fallbackresource); 2825107b09fSJeremy L Thompson // LCOV_EXCL_STOP 2835107b09fSJeremy L Thompson 2845107b09fSJeremy L Thompson Ceed ceedref; 2855107b09fSJeremy L Thompson ierr = CeedInit(fallbackresource, &ceedref); CeedChk(ierr); 2865107b09fSJeremy L Thompson ceedref->opfallbackparent = op->ceed; 2875107b09fSJeremy L Thompson op->ceed->opfallbackceed = ceedref; 2885107b09fSJeremy L Thompson 2895107b09fSJeremy L Thompson // Clone Op 2905107b09fSJeremy L Thompson CeedOperator opref; 2915107b09fSJeremy L Thompson ierr = CeedCalloc(1, &opref); CeedChk(ierr); 2925107b09fSJeremy L Thompson memcpy(opref, op, sizeof(*opref)); CeedChk(ierr); 2935107b09fSJeremy L Thompson opref->data = NULL; 2945107b09fSJeremy L Thompson opref->setupdone = 0; 2955107b09fSJeremy L Thompson opref->ceed = ceedref; 2965107b09fSJeremy L Thompson ierr = ceedref->OperatorCreate(opref); CeedChk(ierr); 2975107b09fSJeremy L Thompson op->opfallback = opref; 2985107b09fSJeremy L Thompson 2995107b09fSJeremy L Thompson // Clone QF 3005107b09fSJeremy L Thompson CeedQFunction qfref; 3015107b09fSJeremy L Thompson ierr = CeedCalloc(1, &qfref); CeedChk(ierr); 3025107b09fSJeremy L Thompson memcpy(qfref, (op->qf), sizeof(*qfref)); CeedChk(ierr); 3035107b09fSJeremy L Thompson qfref->data = NULL; 3045107b09fSJeremy L Thompson qfref->ceed = ceedref; 3055107b09fSJeremy L Thompson ierr = ceedref->QFunctionCreate(qfref); CeedChk(ierr); 3065107b09fSJeremy L Thompson opref->qf = qfref; 3075107b09fSJeremy L Thompson op->qffallback = qfref; 3085107b09fSJeremy L Thompson 3095107b09fSJeremy L Thompson return 0; 3105107b09fSJeremy L Thompson } 3115107b09fSJeremy L Thompson 3125107b09fSJeremy L Thompson /** 3131d102b48SJeremy L Thompson @brief Assemble a linear CeedQFunction associated with a CeedOperator 3141d102b48SJeremy L Thompson 3151d102b48SJeremy L Thompson This returns a CeedVector containing a matrix at each quadrature point 3161d102b48SJeremy L Thompson providing the action of the CeedQFunction associated with the CeedOperator. 3171d102b48SJeremy L Thompson The vector 'assembled' is of shape 3181d102b48SJeremy L Thompson [num_elements, num_input_fields, num_output_fields, num_quad_points] 3191d102b48SJeremy L Thompson and contains column-major matrices representing the action of the 3201d102b48SJeremy L Thompson CeedQFunction for a corresponding quadrature point on an element. Inputs and 3211d102b48SJeremy L Thompson outputs are in the order provided by the user when adding CeedOperator fields. 3221d102b48SJeremy L Thompson For example, a QFunction with inputs 'u' and 'gradu' and outputs 'gradv' and 3231d102b48SJeremy L Thompson 'v', provided in that order, would result in an assembled QFunction that 3241d102b48SJeremy L Thompson consists of (1 + dim) x (dim + 1) matrices at each quadrature point acting 3251d102b48SJeremy L Thompson on the input [u, du_0, du_1] and producing the output [dv_0, dv_1, v]. 3261d102b48SJeremy L Thompson 3271d102b48SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 3281d102b48SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedQFunction at 3291d102b48SJeremy L Thompson quadrature points 3301d102b48SJeremy L Thompson @param[out] rstr CeedElemRestriction for CeedVector containing assembled 3311d102b48SJeremy L Thompson CeedQFunction 3321d102b48SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 3331d102b48SJeremy L Thompson CEED_REQUEST_IMMEDIATE 3341d102b48SJeremy L Thompson 3351d102b48SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 3361d102b48SJeremy L Thompson 337b7ec98d8SJeremy L Thompson @ref Basic 3381d102b48SJeremy L Thompson **/ 3391d102b48SJeremy L Thompson int CeedOperatorAssembleLinearQFunction(CeedOperator op, CeedVector *assembled, 3407f823360Sjeremylt CeedElemRestriction *rstr, 3417f823360Sjeremylt CeedRequest *request) { 3421d102b48SJeremy L Thompson int ierr; 3431d102b48SJeremy L Thompson Ceed ceed = op->ceed; 3441d102b48SJeremy L Thompson CeedQFunction qf = op->qf; 3451d102b48SJeremy L Thompson 3461d102b48SJeremy L Thompson if (op->composite) { 347138d4072Sjeremylt // LCOV_EXCL_START 3481d102b48SJeremy L Thompson return CeedError(ceed, 1, "Cannot assemble QFunction for composite operator"); 349138d4072Sjeremylt // LCOV_EXCL_STOP 3501d102b48SJeremy L Thompson } else { 3511d102b48SJeremy L Thompson if (op->nfields == 0) 352138d4072Sjeremylt // LCOV_EXCL_START 3531d102b48SJeremy L Thompson return CeedError(ceed, 1, "No operator fields set"); 354138d4072Sjeremylt // LCOV_EXCL_STOP 3551d102b48SJeremy L Thompson if (op->nfields < qf->numinputfields + qf->numoutputfields) 356138d4072Sjeremylt // LCOV_EXCL_START 3571d102b48SJeremy L Thompson return CeedError( ceed, 1, "Not all operator fields set"); 358138d4072Sjeremylt // LCOV_EXCL_STOP 3592cb0afc5Sjeremylt if (!op->hasrestriction) 360138d4072Sjeremylt // LCOV_EXCL_START 3611d102b48SJeremy L Thompson return CeedError(ceed, 1, "At least one restriction required"); 362138d4072Sjeremylt // LCOV_EXCL_STOP 3631d102b48SJeremy L Thompson if (op->numqpoints == 0) 364138d4072Sjeremylt // LCOV_EXCL_START 3651d102b48SJeremy L Thompson return CeedError(ceed, 1, "At least one non-collocated basis required"); 366138d4072Sjeremylt // LCOV_EXCL_STOP 3671d102b48SJeremy L Thompson } 3685107b09fSJeremy L Thompson if (op->AssembleLinearQFunction) { 3691d102b48SJeremy L Thompson ierr = op->AssembleLinearQFunction(op, assembled, rstr, request); 3701d102b48SJeremy L Thompson CeedChk(ierr); 3715107b09fSJeremy L Thompson } else { 3725107b09fSJeremy L Thompson // Fallback to reference Ceed 3735107b09fSJeremy L Thompson if (!op->opfallback) { 3745107b09fSJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 3755107b09fSJeremy L Thompson } 3765107b09fSJeremy L Thompson // Assemble 3775107b09fSJeremy L Thompson ierr = op->opfallback->AssembleLinearQFunction(op->opfallback, assembled, 3785107b09fSJeremy L Thompson rstr, request); CeedChk(ierr); 3795107b09fSJeremy L Thompson } 3801d102b48SJeremy L Thompson return 0; 3811d102b48SJeremy L Thompson } 3821d102b48SJeremy L Thompson 3831d102b48SJeremy L Thompson /** 384b7ec98d8SJeremy L Thompson @brief Assemble the diagonal of a square linear Operator 385b7ec98d8SJeremy L Thompson 386b7ec98d8SJeremy L Thompson This returns a CeedVector containing the diagonal of a linear CeedOperator. 387b7ec98d8SJeremy L Thompson 388b7ec98d8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 389b7ec98d8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator diagonal 390b7ec98d8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 391b7ec98d8SJeremy L Thompson CEED_REQUEST_IMMEDIATE 392b7ec98d8SJeremy L Thompson 393b7ec98d8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 394b7ec98d8SJeremy L Thompson 395b7ec98d8SJeremy L Thompson @ref Basic 396b7ec98d8SJeremy L Thompson **/ 3977f823360Sjeremylt int CeedOperatorAssembleLinearDiagonal(CeedOperator op, CeedVector *assembled, 3987f823360Sjeremylt CeedRequest *request) { 399b7ec98d8SJeremy L Thompson int ierr; 400b7ec98d8SJeremy L Thompson Ceed ceed = op->ceed; 401b7ec98d8SJeremy L Thompson CeedQFunction qf = op->qf; 402b7ec98d8SJeremy L Thompson 403b7ec98d8SJeremy L Thompson if (op->composite) { 404b7ec98d8SJeremy L Thompson // LCOV_EXCL_START 405b7ec98d8SJeremy L Thompson return CeedError(ceed, 1, "Cannot assemble QFunction for composite operator"); 406b7ec98d8SJeremy L Thompson // LCOV_EXCL_STOP 407b7ec98d8SJeremy L Thompson } else { 408b7ec98d8SJeremy L Thompson if (op->nfields == 0) 409b7ec98d8SJeremy L Thompson // LCOV_EXCL_START 410b7ec98d8SJeremy L Thompson return CeedError(ceed, 1, "No operator fields set"); 411b7ec98d8SJeremy L Thompson // LCOV_EXCL_STOP 412b7ec98d8SJeremy L Thompson if (op->nfields < qf->numinputfields + qf->numoutputfields) 413b7ec98d8SJeremy L Thompson // LCOV_EXCL_START 414b7ec98d8SJeremy L Thompson return CeedError( ceed, 1, "Not all operator fields set"); 415b7ec98d8SJeremy L Thompson // LCOV_EXCL_STOP 4162cb0afc5Sjeremylt if (!op->hasrestriction) 417b7ec98d8SJeremy L Thompson // LCOV_EXCL_START 418b7ec98d8SJeremy L Thompson return CeedError(ceed, 1, "At least one restriction required"); 419b7ec98d8SJeremy L Thompson // LCOV_EXCL_STOP 420b7ec98d8SJeremy L Thompson if (op->numqpoints == 0) 421b7ec98d8SJeremy L Thompson // LCOV_EXCL_START 422b7ec98d8SJeremy L Thompson return CeedError(ceed, 1, "At least one non-collocated basis required"); 423b7ec98d8SJeremy L Thompson // LCOV_EXCL_STOP 424b7ec98d8SJeremy L Thompson } 425b7ec98d8SJeremy L Thompson 426b7ec98d8SJeremy L Thompson // Use backend version, if available 427b7ec98d8SJeremy L Thompson if (op->AssembleLinearDiagonal) { 428b7ec98d8SJeremy L Thompson ierr = op->AssembleLinearDiagonal(op, assembled, request); CeedChk(ierr); 429b7ec98d8SJeremy L Thompson return 0; 430b7ec98d8SJeremy L Thompson } 431b7ec98d8SJeremy L Thompson 432b7ec98d8SJeremy L Thompson // Assemble QFunction 433b7ec98d8SJeremy L Thompson CeedVector assembledqf; 434b7ec98d8SJeremy L Thompson CeedElemRestriction rstr; 435b7ec98d8SJeremy L Thompson ierr = CeedOperatorAssembleLinearQFunction(op, &assembledqf, &rstr, request); 436b7ec98d8SJeremy L Thompson CeedChk(ierr); 437b7ec98d8SJeremy L Thompson ierr = CeedElemRestrictionDestroy(&rstr); CeedChk(ierr); 438b7ec98d8SJeremy L Thompson 439b7ec98d8SJeremy L Thompson // Determine active input basis 440112e3f70Sjeremylt CeedInt numemodein = 0, ncomp, dim = 1; 441b7ec98d8SJeremy L Thompson CeedEvalMode *emodein = NULL; 442112e3f70Sjeremylt CeedBasis basisin = NULL; 443112e3f70Sjeremylt CeedElemRestriction rstrin = NULL; 444b7ec98d8SJeremy L Thompson for (CeedInt i=0; i<qf->numinputfields; i++) 445b7ec98d8SJeremy L Thompson if (op->inputfields[i]->vec == CEED_VECTOR_ACTIVE) { 446b7ec98d8SJeremy L Thompson ierr = CeedOperatorFieldGetBasis(op->inputfields[i], &basisin); 447b7ec98d8SJeremy L Thompson CeedChk(ierr); 448b7ec98d8SJeremy L Thompson ierr = CeedBasisGetNumComponents(basisin, &ncomp); CeedChk(ierr); 449b7ec98d8SJeremy L Thompson ierr = CeedBasisGetDimension(basisin, &dim); CeedChk(ierr); 450b7ec98d8SJeremy L Thompson ierr = CeedOperatorFieldGetElemRestriction(op->inputfields[i], &rstrin); 451b7ec98d8SJeremy L Thompson CeedChk(ierr); 452b7ec98d8SJeremy L Thompson CeedEvalMode emode; 453b7ec98d8SJeremy L Thompson ierr = CeedQFunctionFieldGetEvalMode(qf->inputfields[i], &emode); 454b7ec98d8SJeremy L Thompson CeedChk(ierr); 455b7ec98d8SJeremy L Thompson switch (emode) { 456b7ec98d8SJeremy L Thompson case CEED_EVAL_NONE: 457b7ec98d8SJeremy L Thompson case CEED_EVAL_INTERP: 458b7ec98d8SJeremy L Thompson ierr = CeedRealloc(numemodein + 1, &emodein); CeedChk(ierr); 459b7ec98d8SJeremy L Thompson emodein[numemodein] = emode; 460b7ec98d8SJeremy L Thompson numemodein += 1; 461b7ec98d8SJeremy L Thompson break; 462b7ec98d8SJeremy L Thompson case CEED_EVAL_GRAD: 463b7ec98d8SJeremy L Thompson ierr = CeedRealloc(numemodein + dim, &emodein); CeedChk(ierr); 464b7ec98d8SJeremy L Thompson for (CeedInt d=0; d<dim; d++) 465b7ec98d8SJeremy L Thompson emodein[numemodein+d] = emode; 466b7ec98d8SJeremy L Thompson numemodein += dim; 467b7ec98d8SJeremy L Thompson break; 468b7ec98d8SJeremy L Thompson case CEED_EVAL_WEIGHT: 469b7ec98d8SJeremy L Thompson case CEED_EVAL_DIV: 470b7ec98d8SJeremy L Thompson case CEED_EVAL_CURL: 471b7ec98d8SJeremy L Thompson break; // Caught by QF Assembly 472b7ec98d8SJeremy L Thompson } 473b7ec98d8SJeremy L Thompson } 474b7ec98d8SJeremy L Thompson 475b7ec98d8SJeremy L Thompson // Determine active output basis 476b7ec98d8SJeremy L Thompson CeedInt numemodeout = 0; 477b7ec98d8SJeremy L Thompson CeedEvalMode *emodeout = NULL; 478112e3f70Sjeremylt CeedBasis basisout = NULL; 479112e3f70Sjeremylt CeedElemRestriction rstrout = NULL; 480112e3f70Sjeremylt CeedTransposeMode lmodeout = CEED_NOTRANSPOSE; 481b7ec98d8SJeremy L Thompson for (CeedInt i=0; i<qf->numoutputfields; i++) 482b7ec98d8SJeremy L Thompson if (op->outputfields[i]->vec == CEED_VECTOR_ACTIVE) { 483b7ec98d8SJeremy L Thompson ierr = CeedOperatorFieldGetBasis(op->outputfields[i], &basisout); 484b7ec98d8SJeremy L Thompson CeedChk(ierr); 485b7ec98d8SJeremy L Thompson ierr = CeedOperatorFieldGetElemRestriction(op->outputfields[i], &rstrout); 486b7ec98d8SJeremy L Thompson CeedChk(ierr); 487b7ec98d8SJeremy L Thompson ierr = CeedOperatorFieldGetLMode(op->outputfields[i], &lmodeout); 488b7ec98d8SJeremy L Thompson CeedChk(ierr); 489b7ec98d8SJeremy L Thompson CeedEvalMode emode; 490b7ec98d8SJeremy L Thompson ierr = CeedQFunctionFieldGetEvalMode(qf->outputfields[i], &emode); 491b7ec98d8SJeremy L Thompson CeedChk(ierr); 492b7ec98d8SJeremy L Thompson switch (emode) { 493b7ec98d8SJeremy L Thompson case CEED_EVAL_NONE: 494b7ec98d8SJeremy L Thompson case CEED_EVAL_INTERP: 495b7ec98d8SJeremy L Thompson ierr = CeedRealloc(numemodeout + 1, &emodeout); CeedChk(ierr); 496b7ec98d8SJeremy L Thompson emodeout[numemodeout] = emode; 497b7ec98d8SJeremy L Thompson numemodeout += 1; 498b7ec98d8SJeremy L Thompson break; 499b7ec98d8SJeremy L Thompson case CEED_EVAL_GRAD: 500b7ec98d8SJeremy L Thompson ierr = CeedRealloc(numemodeout + dim, &emodeout); CeedChk(ierr); 501b7ec98d8SJeremy L Thompson for (CeedInt d=0; d<dim; d++) 502b7ec98d8SJeremy L Thompson emodeout[numemodeout+d] = emode; 503b7ec98d8SJeremy L Thompson numemodeout += dim; 504b7ec98d8SJeremy L Thompson break; 505b7ec98d8SJeremy L Thompson case CEED_EVAL_WEIGHT: 506b7ec98d8SJeremy L Thompson case CEED_EVAL_DIV: 507b7ec98d8SJeremy L Thompson case CEED_EVAL_CURL: 508b7ec98d8SJeremy L Thompson break; // Caught by QF Assembly 509b7ec98d8SJeremy L Thompson } 510b7ec98d8SJeremy L Thompson } 511b7ec98d8SJeremy L Thompson 512b7ec98d8SJeremy L Thompson // Create diagonal vector 513b7ec98d8SJeremy L Thompson CeedVector elemdiag; 514b7ec98d8SJeremy L Thompson ierr = CeedElemRestrictionCreateVector(rstrin, assembled, &elemdiag); 515b7ec98d8SJeremy L Thompson CeedChk(ierr); 516b7ec98d8SJeremy L Thompson 517b7ec98d8SJeremy L Thompson // Assemble element operator diagonals 518b7ec98d8SJeremy L Thompson CeedScalar *elemdiagarray, *assembledqfarray; 519b7ec98d8SJeremy L Thompson ierr = CeedVectorSetValue(elemdiag, 0.0); CeedChk(ierr); 520b7ec98d8SJeremy L Thompson ierr = CeedVectorGetArray(elemdiag, CEED_MEM_HOST, &elemdiagarray); 521b7ec98d8SJeremy L Thompson CeedChk(ierr); 522b7ec98d8SJeremy L Thompson ierr = CeedVectorGetArray(assembledqf, CEED_MEM_HOST, &assembledqfarray); 523b7ec98d8SJeremy L Thompson CeedChk(ierr); 524b7ec98d8SJeremy L Thompson CeedInt nelem, nnodes, nqpts; 525b7ec98d8SJeremy L Thompson ierr = CeedElemRestrictionGetNumElements(rstrin, &nelem); CeedChk(ierr); 526b7ec98d8SJeremy L Thompson ierr = CeedBasisGetNumNodes(basisin, &nnodes); CeedChk(ierr); 527b7ec98d8SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisin, &nqpts); CeedChk(ierr); 528b7ec98d8SJeremy L Thompson // Compute the diagonal of B^T D B 529b7ec98d8SJeremy L Thompson // Each node, qpt pair 530b7ec98d8SJeremy L Thompson for (CeedInt n=0; n<nnodes; n++) 531b7ec98d8SJeremy L Thompson for (CeedInt q=0; q<nqpts; q++) { 532b7ec98d8SJeremy L Thompson CeedInt dout = -1; 533b7ec98d8SJeremy L Thompson // Each basis eval mode pair 534b7ec98d8SJeremy L Thompson for (CeedInt eout=0; eout<numemodeout; eout++) { 535b7ec98d8SJeremy L Thompson CeedScalar bt = 1.0; 536b7ec98d8SJeremy L Thompson if (emodeout[eout] == CEED_EVAL_GRAD) 537b7ec98d8SJeremy L Thompson dout += 1; 538b7ec98d8SJeremy L Thompson ierr = CeedBasisGetValue(basisout, emodeout[eout], q, n, dout, &bt); 539b7ec98d8SJeremy L Thompson CeedChk(ierr); 540b7ec98d8SJeremy L Thompson CeedInt din = -1; 541b7ec98d8SJeremy L Thompson for (CeedInt ein=0; ein<numemodein; ein++) { 542b7ec98d8SJeremy L Thompson CeedScalar b = 0.0; 543b7ec98d8SJeremy L Thompson if (emodein[ein] == CEED_EVAL_GRAD) 544b7ec98d8SJeremy L Thompson din += 1; 545b7ec98d8SJeremy L Thompson ierr = CeedBasisGetValue(basisin, emodein[ein], q, n, din, &b); 546b7ec98d8SJeremy L Thompson CeedChk(ierr); 547b7ec98d8SJeremy L Thompson // Each element and component 548b7ec98d8SJeremy L Thompson for (CeedInt e=0; e<nelem; e++) 549b7ec98d8SJeremy L Thompson for (CeedInt cout=0; cout<ncomp; cout++) { 550b7ec98d8SJeremy L Thompson CeedScalar db = 0.0; 551b7ec98d8SJeremy L Thompson for (CeedInt cin=0; cin<ncomp; cin++) 552b7ec98d8SJeremy L Thompson db += assembledqfarray[((((e*numemodein+ein)*ncomp+cin)* 553b7ec98d8SJeremy L Thompson numemodeout+eout)*ncomp+cout)*nqpts+q]*b; 554b7ec98d8SJeremy L Thompson elemdiagarray[(e*ncomp+cout)*nnodes+n] += bt * db; 555b7ec98d8SJeremy L Thompson } 556b7ec98d8SJeremy L Thompson } 557b7ec98d8SJeremy L Thompson } 558b7ec98d8SJeremy L Thompson } 559b7ec98d8SJeremy L Thompson 560b7ec98d8SJeremy L Thompson ierr = CeedVectorRestoreArray(elemdiag, &elemdiagarray); CeedChk(ierr); 561b7ec98d8SJeremy L Thompson ierr = CeedVectorRestoreArray(assembledqf, &assembledqfarray); CeedChk(ierr); 562b7ec98d8SJeremy L Thompson 563b7ec98d8SJeremy L Thompson // Assemble local operator diagonal 564b7ec98d8SJeremy L Thompson ierr = CeedVectorSetValue(*assembled, 0.0); CeedChk(ierr); 565b7ec98d8SJeremy L Thompson ierr = CeedElemRestrictionApply(rstrout, CEED_TRANSPOSE, lmodeout, elemdiag, 566b7ec98d8SJeremy L Thompson *assembled, request); CeedChk(ierr); 567b7ec98d8SJeremy L Thompson 568b7ec98d8SJeremy L Thompson // Cleanup 569b7ec98d8SJeremy L Thompson ierr = CeedVectorDestroy(&assembledqf); CeedChk(ierr); 570b7ec98d8SJeremy L Thompson ierr = CeedVectorDestroy(&elemdiag); CeedChk(ierr); 571b7ec98d8SJeremy L Thompson ierr = CeedFree(&emodein); CeedChk(ierr); 572b7ec98d8SJeremy L Thompson ierr = CeedFree(&emodeout); CeedChk(ierr); 573b7ec98d8SJeremy L Thompson 574b7ec98d8SJeremy L Thompson return 0; 575b7ec98d8SJeremy L Thompson } 576b7ec98d8SJeremy L Thompson 577b7ec98d8SJeremy L Thompson /** 578b11c1e72Sjeremylt @brief Apply CeedOperator to a vector 579d7b241e6Sjeremylt 580d7b241e6Sjeremylt This computes the action of the operator on the specified (active) input, 581d7b241e6Sjeremylt yielding its (active) output. All inputs and outputs must be specified using 582d7b241e6Sjeremylt CeedOperatorSetField(). 583d7b241e6Sjeremylt 584d7b241e6Sjeremylt @param op CeedOperator to apply 585*34138859Sjeremylt @param[in] in CeedVector containing input state or CEED_VECTOR_NONE if 586*34138859Sjeremylt there are no active inputs 587b11c1e72Sjeremylt @param[out] out CeedVector to store result of applying operator (must be 588*34138859Sjeremylt distinct from @a in) or CEED_VECTOR_NONE if there are no 589*34138859Sjeremylt active outputs 590d7b241e6Sjeremylt @param request Address of CeedRequest for non-blocking completion, else 591d7b241e6Sjeremylt CEED_REQUEST_IMMEDIATE 592b11c1e72Sjeremylt 593b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 594dfdf5a53Sjeremylt 595dfdf5a53Sjeremylt @ref Basic 596b11c1e72Sjeremylt **/ 597692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out, 598692c2638Sjeremylt CeedRequest *request) { 599d7b241e6Sjeremylt int ierr; 600d7b241e6Sjeremylt Ceed ceed = op->ceed; 601d7b241e6Sjeremylt CeedQFunction qf = op->qf; 602d7b241e6Sjeremylt 60352d6035fSJeremy L Thompson if (op->composite) { 604c042f62fSJeremy L Thompson if (!op->numsub) 605c042f62fSJeremy L Thompson // LCOV_EXCL_START 606c042f62fSJeremy L Thompson return CeedError(ceed, 1, "No suboperators set"); 607c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 60852d6035fSJeremy L Thompson } else { 609c042f62fSJeremy L Thompson if (op->nfields == 0) 610c042f62fSJeremy L Thompson // LCOV_EXCL_START 611c042f62fSJeremy L Thompson return CeedError(ceed, 1, "No operator fields set"); 612c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 613c042f62fSJeremy L Thompson if (op->nfields < qf->numinputfields + qf->numoutputfields) 614c042f62fSJeremy L Thompson // LCOV_EXCL_START 615c042f62fSJeremy L Thompson return CeedError(ceed, 1, "Not all operator fields set"); 616c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 6172cb0afc5Sjeremylt if (!op->hasrestriction) 618c042f62fSJeremy L Thompson // LCOV_EXCL_START 619c042f62fSJeremy L Thompson return CeedError(ceed, 1,"At least one restriction required"); 620c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 621c042f62fSJeremy L Thompson if (op->numqpoints == 0) 622c042f62fSJeremy L Thompson // LCOV_EXCL_START 623c042f62fSJeremy L Thompson return CeedError(ceed, 1,"At least one non-collocated basis required"); 624c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 62552d6035fSJeremy L Thompson } 6261d7d2407SJeremy L Thompson if (op->numelements || op->composite) { 627e97ff134Sjeremylt ierr = op->Apply(op, in != CEED_VECTOR_NONE ? in : NULL, 628e97ff134Sjeremylt out != CEED_VECTOR_NONE ? out : NULL, request); 629e97ff134Sjeremylt CeedChk(ierr); 6301d7d2407SJeremy L Thompson } 631d7b241e6Sjeremylt return 0; 632d7b241e6Sjeremylt } 633d7b241e6Sjeremylt 634d7b241e6Sjeremylt /** 6354ce2993fSjeremylt @brief Get the Ceed associated with a CeedOperator 6364ce2993fSjeremylt 6374ce2993fSjeremylt @param op CeedOperator 6384ce2993fSjeremylt @param[out] ceed Variable to store Ceed 6394ce2993fSjeremylt 6404ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 6414ce2993fSjeremylt 64223617272Sjeremylt @ref Advanced 6434ce2993fSjeremylt **/ 6444ce2993fSjeremylt 6454ce2993fSjeremylt int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 6464ce2993fSjeremylt *ceed = op->ceed; 6474ce2993fSjeremylt return 0; 6484ce2993fSjeremylt } 6494ce2993fSjeremylt 6504ce2993fSjeremylt /** 6514ce2993fSjeremylt @brief Get the number of elements associated with a CeedOperator 6524ce2993fSjeremylt 6534ce2993fSjeremylt @param op CeedOperator 6544ce2993fSjeremylt @param[out] numelem Variable to store number of elements 6554ce2993fSjeremylt 6564ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 6574ce2993fSjeremylt 65823617272Sjeremylt @ref Advanced 6594ce2993fSjeremylt **/ 6604ce2993fSjeremylt 6614ce2993fSjeremylt int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) { 66252d6035fSJeremy L Thompson if (op->composite) 663c042f62fSJeremy L Thompson // LCOV_EXCL_START 66452d6035fSJeremy L Thompson return CeedError(op->ceed, 1, "Not defined for composite operator"); 665c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 66652d6035fSJeremy L Thompson 6674ce2993fSjeremylt *numelem = op->numelements; 6684ce2993fSjeremylt return 0; 6694ce2993fSjeremylt } 6704ce2993fSjeremylt 6714ce2993fSjeremylt /** 6724ce2993fSjeremylt @brief Get the number of quadrature points associated with a CeedOperator 6734ce2993fSjeremylt 6744ce2993fSjeremylt @param op CeedOperator 6754ce2993fSjeremylt @param[out] numqpts Variable to store vector number of quadrature points 6764ce2993fSjeremylt 6774ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 6784ce2993fSjeremylt 67923617272Sjeremylt @ref Advanced 6804ce2993fSjeremylt **/ 6814ce2993fSjeremylt 6824ce2993fSjeremylt int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) { 68352d6035fSJeremy L Thompson if (op->composite) 684c042f62fSJeremy L Thompson // LCOV_EXCL_START 68552d6035fSJeremy L Thompson return CeedError(op->ceed, 1, "Not defined for composite operator"); 686c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 68752d6035fSJeremy L Thompson 6884ce2993fSjeremylt *numqpts = op->numqpoints; 6894ce2993fSjeremylt return 0; 6904ce2993fSjeremylt } 6914ce2993fSjeremylt 6924ce2993fSjeremylt /** 6934ce2993fSjeremylt @brief Get the number of arguments associated with a CeedOperator 6944ce2993fSjeremylt 6954ce2993fSjeremylt @param op CeedOperator 6964ce2993fSjeremylt @param[out] numargs Variable to store vector number of arguments 6974ce2993fSjeremylt 6984ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 6994ce2993fSjeremylt 70023617272Sjeremylt @ref Advanced 7014ce2993fSjeremylt **/ 7024ce2993fSjeremylt 7034ce2993fSjeremylt int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) { 70452d6035fSJeremy L Thompson if (op->composite) 705c042f62fSJeremy L Thompson // LCOV_EXCL_START 70652d6035fSJeremy L Thompson return CeedError(op->ceed, 1, "Not defined for composite operators"); 707c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 708c042f62fSJeremy L Thompson 7094ce2993fSjeremylt *numargs = op->nfields; 7104ce2993fSjeremylt return 0; 7114ce2993fSjeremylt } 7124ce2993fSjeremylt 7134ce2993fSjeremylt /** 7144ce2993fSjeremylt @brief Get the setup status of a CeedOperator 7154ce2993fSjeremylt 7164ce2993fSjeremylt @param op CeedOperator 717288c0443SJeremy L Thompson @param[out] setupdone Variable to store setup status 7184ce2993fSjeremylt 7194ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 7204ce2993fSjeremylt 72123617272Sjeremylt @ref Advanced 7224ce2993fSjeremylt **/ 7234ce2993fSjeremylt 7244ce2993fSjeremylt int CeedOperatorGetSetupStatus(CeedOperator op, bool *setupdone) { 7254ce2993fSjeremylt *setupdone = op->setupdone; 7264ce2993fSjeremylt return 0; 7274ce2993fSjeremylt } 7284ce2993fSjeremylt 7294ce2993fSjeremylt /** 7304ce2993fSjeremylt @brief Get the QFunction associated with a CeedOperator 7314ce2993fSjeremylt 7324ce2993fSjeremylt @param op CeedOperator 7338c91a0c9SJeremy L Thompson @param[out] qf Variable to store QFunction 7344ce2993fSjeremylt 7354ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 7364ce2993fSjeremylt 73723617272Sjeremylt @ref Advanced 7384ce2993fSjeremylt **/ 7394ce2993fSjeremylt 7404ce2993fSjeremylt int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 74152d6035fSJeremy L Thompson if (op->composite) 742c042f62fSJeremy L Thompson // LCOV_EXCL_START 74352d6035fSJeremy L Thompson return CeedError(op->ceed, 1, "Not defined for composite operator"); 744c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 74552d6035fSJeremy L Thompson 7464ce2993fSjeremylt *qf = op->qf; 7474ce2993fSjeremylt return 0; 7484ce2993fSjeremylt } 7494ce2993fSjeremylt 7504ce2993fSjeremylt /** 75152d6035fSJeremy L Thompson @brief Get the number of suboperators associated with a CeedOperator 75252d6035fSJeremy L Thompson 75352d6035fSJeremy L Thompson @param op CeedOperator 75452d6035fSJeremy L Thompson @param[out] numsub Variable to store number of suboperators 75552d6035fSJeremy L Thompson 75652d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 75752d6035fSJeremy L Thompson 75852d6035fSJeremy L Thompson @ref Advanced 75952d6035fSJeremy L Thompson **/ 76052d6035fSJeremy L Thompson 76152d6035fSJeremy L Thompson int CeedOperatorGetNumSub(CeedOperator op, CeedInt *numsub) { 762c042f62fSJeremy L Thompson if (!op->composite) 763c042f62fSJeremy L Thompson // LCOV_EXCL_START 764c042f62fSJeremy L Thompson return CeedError(op->ceed, 1, "Not a composite operator"); 765c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 76652d6035fSJeremy L Thompson 76752d6035fSJeremy L Thompson *numsub = op->numsub; 76852d6035fSJeremy L Thompson return 0; 76952d6035fSJeremy L Thompson } 77052d6035fSJeremy L Thompson 77152d6035fSJeremy L Thompson /** 77252d6035fSJeremy L Thompson @brief Get the list of suboperators associated with a CeedOperator 77352d6035fSJeremy L Thompson 77452d6035fSJeremy L Thompson @param op CeedOperator 77552d6035fSJeremy L Thompson @param[out] suboperators Variable to store list of suboperators 77652d6035fSJeremy L Thompson 77752d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 77852d6035fSJeremy L Thompson 77952d6035fSJeremy L Thompson @ref Advanced 78052d6035fSJeremy L Thompson **/ 78152d6035fSJeremy L Thompson 78252d6035fSJeremy L Thompson int CeedOperatorGetSubList(CeedOperator op, CeedOperator **suboperators) { 783c042f62fSJeremy L Thompson if (!op->composite) 784c042f62fSJeremy L Thompson // LCOV_EXCL_START 785c042f62fSJeremy L Thompson return CeedError(op->ceed, 1, "Not a composite operator"); 786c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 78752d6035fSJeremy L Thompson 78852d6035fSJeremy L Thompson *suboperators = op->suboperators; 78952d6035fSJeremy L Thompson return 0; 79052d6035fSJeremy L Thompson } 79152d6035fSJeremy L Thompson 79252d6035fSJeremy L Thompson /** 793fe2413ffSjeremylt @brief Set the backend data of a CeedOperator 794fe2413ffSjeremylt 795fe2413ffSjeremylt @param[out] op CeedOperator 796fe2413ffSjeremylt @param data Data to set 797fe2413ffSjeremylt 798fe2413ffSjeremylt @return An error code: 0 - success, otherwise - failure 799fe2413ffSjeremylt 800fe2413ffSjeremylt @ref Advanced 801fe2413ffSjeremylt **/ 802fe2413ffSjeremylt 803fe2413ffSjeremylt int CeedOperatorSetData(CeedOperator op, void **data) { 804fe2413ffSjeremylt op->data = *data; 805fe2413ffSjeremylt return 0; 806fe2413ffSjeremylt } 807fe2413ffSjeremylt 808fe2413ffSjeremylt /** 8094ce2993fSjeremylt @brief Get the backend data of a CeedOperator 8104ce2993fSjeremylt 8114ce2993fSjeremylt @param op CeedOperator 8124ce2993fSjeremylt @param[out] data Variable to store data 8134ce2993fSjeremylt 8144ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 8154ce2993fSjeremylt 81623617272Sjeremylt @ref Advanced 8174ce2993fSjeremylt **/ 8184ce2993fSjeremylt 8194ce2993fSjeremylt int CeedOperatorGetData(CeedOperator op, void **data) { 8204ce2993fSjeremylt *data = op->data; 8214ce2993fSjeremylt return 0; 8224ce2993fSjeremylt } 8234ce2993fSjeremylt 8244ce2993fSjeremylt /** 8254ce2993fSjeremylt @brief Set the setup flag of a CeedOperator to True 8264ce2993fSjeremylt 8274ce2993fSjeremylt @param op CeedOperator 8284ce2993fSjeremylt 8294ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 8304ce2993fSjeremylt 83123617272Sjeremylt @ref Advanced 8324ce2993fSjeremylt **/ 8334ce2993fSjeremylt 8344ce2993fSjeremylt int CeedOperatorSetSetupDone(CeedOperator op) { 8354ce2993fSjeremylt op->setupdone = 1; 8364ce2993fSjeremylt return 0; 8374ce2993fSjeremylt } 8384ce2993fSjeremylt 8394ce2993fSjeremylt /** 8402ebaca42Sjeremylt @brief View a field of a CeedOperator 8412ebaca42Sjeremylt 8422ebaca42Sjeremylt @param[in] field Operator field to view 8432ebaca42Sjeremylt @param[in] fieldnumber Number of field being viewed 8442ebaca42Sjeremylt @param[in] stream Stream to view to, e.g., stdout 8452ebaca42Sjeremylt 8462ebaca42Sjeremylt @return An error code: 0 - success, otherwise - failure 8472ebaca42Sjeremylt 8482ebaca42Sjeremylt @ref Utility 8492ebaca42Sjeremylt **/ 8502ebaca42Sjeremylt static int CeedOperatorFieldView(CeedOperatorField field, 8512ebaca42Sjeremylt CeedQFunctionField qffield, 8522da88da5Sjeremylt CeedInt fieldnumber, bool sub, bool in, 8532da88da5Sjeremylt FILE *stream) { 8542ebaca42Sjeremylt const char *pre = sub ? " " : ""; 8552da88da5Sjeremylt const char *inout = in ? "Input" : "Output"; 8562ebaca42Sjeremylt 8572da88da5Sjeremylt fprintf(stream, "%s %s Field [%d]:\n" 8582da88da5Sjeremylt "%s Name: \"%s\"\n" 8592da88da5Sjeremylt "%s Lmode: \"%s\"\n", 8602da88da5Sjeremylt pre, inout, fieldnumber, pre, qffield->fieldname, 8612ebaca42Sjeremylt pre, CeedTransposeModes[field->lmode]); 8622ebaca42Sjeremylt 8632ebaca42Sjeremylt if (field->basis == CEED_BASIS_COLLOCATED) 8642ebaca42Sjeremylt fprintf(stream, "%s Collocated basis\n", pre); 8652ebaca42Sjeremylt 8662ebaca42Sjeremylt if (field->vec == CEED_VECTOR_ACTIVE) 8672ebaca42Sjeremylt fprintf(stream, "%s Active vector\n", pre); 8682ebaca42Sjeremylt else if (field->vec == CEED_VECTOR_NONE) 8692ebaca42Sjeremylt fprintf(stream, "%s No vector\n", pre); 8702ebaca42Sjeremylt 8712ebaca42Sjeremylt return 0; 8722ebaca42Sjeremylt } 8732ebaca42Sjeremylt 8742ebaca42Sjeremylt /** 8752ebaca42Sjeremylt @brief View a single CeedOperator 8762ebaca42Sjeremylt 8772ebaca42Sjeremylt @param[in] op CeedOperator to view 8782ebaca42Sjeremylt @param[in] stream Stream to write; typically stdout/stderr or a file 8792ebaca42Sjeremylt 8802ebaca42Sjeremylt @return Error code: 0 - success, otherwise - failure 8812ebaca42Sjeremylt 8822ebaca42Sjeremylt @ref Utility 8832ebaca42Sjeremylt **/ 8842ebaca42Sjeremylt int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) { 8852ebaca42Sjeremylt int ierr; 8862ebaca42Sjeremylt const char *pre = sub ? " " : ""; 8872ebaca42Sjeremylt 8882ebaca42Sjeremylt CeedInt totalfields; 8892ebaca42Sjeremylt ierr = CeedOperatorGetNumArgs(op, &totalfields); CeedChk(ierr); 8902da88da5Sjeremylt 8912ebaca42Sjeremylt fprintf(stream, "%s %d Field%s\n", pre, totalfields, totalfields>1 ? "s" : ""); 8922ebaca42Sjeremylt 8932da88da5Sjeremylt fprintf(stream, "%s %d Input Field%s:\n", pre, op->qf->numinputfields, 8942ebaca42Sjeremylt op->qf->numinputfields>1 ? "s" : ""); 8952ebaca42Sjeremylt for (CeedInt i=0; i<op->qf->numinputfields; i++) { 8962ebaca42Sjeremylt ierr = CeedOperatorFieldView(op->inputfields[i], op->qf->inputfields[i], 8972da88da5Sjeremylt i, sub, 1, stream); CeedChk(ierr); 8982ebaca42Sjeremylt } 8992ebaca42Sjeremylt 9002da88da5Sjeremylt fprintf(stream, "%s %d Output Field%s:\n", pre, op->qf->numoutputfields, 9012ebaca42Sjeremylt op->qf->numoutputfields>1 ? "s" : ""); 9022ebaca42Sjeremylt for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 9032ebaca42Sjeremylt ierr = CeedOperatorFieldView(op->outputfields[i], op->qf->inputfields[i], 9042da88da5Sjeremylt i, sub, 0, stream); CeedChk(ierr); 9052ebaca42Sjeremylt } 9062ebaca42Sjeremylt 9072ebaca42Sjeremylt return 0; 9082ebaca42Sjeremylt } 9092ebaca42Sjeremylt 9102ebaca42Sjeremylt /** 9112ebaca42Sjeremylt @brief View a CeedOperator 9122ebaca42Sjeremylt 9132ebaca42Sjeremylt @param[in] op CeedOperator to view 9142ebaca42Sjeremylt @param[in] stream Stream to write; typically stdout/stderr or a file 9152ebaca42Sjeremylt 9162ebaca42Sjeremylt @return Error code: 0 - success, otherwise - failure 9172ebaca42Sjeremylt 9182ebaca42Sjeremylt @ref Utility 9192ebaca42Sjeremylt **/ 9202ebaca42Sjeremylt int CeedOperatorView(CeedOperator op, FILE *stream) { 9212ebaca42Sjeremylt int ierr; 9222ebaca42Sjeremylt 9232ebaca42Sjeremylt if (op->composite) { 9242ebaca42Sjeremylt fprintf(stream, "Composite CeedOperator\n"); 9252ebaca42Sjeremylt 9262ebaca42Sjeremylt for (CeedInt i=0; i<op->numsub; i++) { 9272da88da5Sjeremylt fprintf(stream, " SubOperator [%d]:\n", i); 9282ebaca42Sjeremylt ierr = CeedOperatorSingleView(op->suboperators[i], 1, stream); 9292ebaca42Sjeremylt CeedChk(ierr); 9302ebaca42Sjeremylt } 9312ebaca42Sjeremylt } else { 9322ebaca42Sjeremylt fprintf(stream, "CeedOperator\n"); 9332ebaca42Sjeremylt ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr); 9342ebaca42Sjeremylt } 9352ebaca42Sjeremylt 9362ebaca42Sjeremylt return 0; 9372ebaca42Sjeremylt } 9382ebaca42Sjeremylt 9392ebaca42Sjeremylt /** 940d1bcdac9Sjeremylt @brief Get the CeedOperatorFields of a CeedOperator 941d1bcdac9Sjeremylt 942d1bcdac9Sjeremylt @param op CeedOperator 943d1bcdac9Sjeremylt @param[out] inputfields Variable to store inputfields 944d1bcdac9Sjeremylt @param[out] outputfields Variable to store outputfields 945d1bcdac9Sjeremylt 946d1bcdac9Sjeremylt @return An error code: 0 - success, otherwise - failure 947d1bcdac9Sjeremylt 948d1bcdac9Sjeremylt @ref Advanced 949d1bcdac9Sjeremylt **/ 950d1bcdac9Sjeremylt 951692c2638Sjeremylt int CeedOperatorGetFields(CeedOperator op, CeedOperatorField **inputfields, 952d1bcdac9Sjeremylt CeedOperatorField **outputfields) { 95352d6035fSJeremy L Thompson if (op->composite) 954c042f62fSJeremy L Thompson // LCOV_EXCL_START 95552d6035fSJeremy L Thompson return CeedError(op->ceed, 1, "Not defined for composite operator"); 956c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 95752d6035fSJeremy L Thompson 958d1bcdac9Sjeremylt if (inputfields) *inputfields = op->inputfields; 959d1bcdac9Sjeremylt if (outputfields) *outputfields = op->outputfields; 960d1bcdac9Sjeremylt return 0; 961d1bcdac9Sjeremylt } 962d1bcdac9Sjeremylt 963d1bcdac9Sjeremylt /** 9644dccadb6Sjeremylt @brief Get the L vector CeedTransposeMode of a CeedOperatorField 9654dccadb6Sjeremylt 9664dccadb6Sjeremylt @param opfield CeedOperatorField 9674dccadb6Sjeremylt @param[out] lmode Variable to store CeedTransposeMode 9684dccadb6Sjeremylt 9694dccadb6Sjeremylt @return An error code: 0 - success, otherwise - failure 9704dccadb6Sjeremylt 9714dccadb6Sjeremylt @ref Advanced 9724dccadb6Sjeremylt **/ 9734dccadb6Sjeremylt 9744dccadb6Sjeremylt int CeedOperatorFieldGetLMode(CeedOperatorField opfield, 9754dccadb6Sjeremylt CeedTransposeMode *lmode) { 976fe2413ffSjeremylt *lmode = opfield->lmode; 9774dccadb6Sjeremylt return 0; 9782b8e417aSjeremylt } 9792b8e417aSjeremylt 9802b8e417aSjeremylt /** 981d1bcdac9Sjeremylt @brief Get the CeedElemRestriction of a CeedOperatorField 982d1bcdac9Sjeremylt 983d1bcdac9Sjeremylt @param opfield CeedOperatorField 984d1bcdac9Sjeremylt @param[out] rstr Variable to store CeedElemRestriction 985d1bcdac9Sjeremylt 986d1bcdac9Sjeremylt @return An error code: 0 - success, otherwise - failure 987d1bcdac9Sjeremylt 988d1bcdac9Sjeremylt @ref Advanced 989d1bcdac9Sjeremylt **/ 990d1bcdac9Sjeremylt 991d1bcdac9Sjeremylt int CeedOperatorFieldGetElemRestriction(CeedOperatorField opfield, 992d1bcdac9Sjeremylt CeedElemRestriction *rstr) { 993fe2413ffSjeremylt *rstr = opfield->Erestrict; 994d1bcdac9Sjeremylt return 0; 995d1bcdac9Sjeremylt } 996d1bcdac9Sjeremylt 997d1bcdac9Sjeremylt /** 998d1bcdac9Sjeremylt @brief Get the CeedBasis of a CeedOperatorField 999d1bcdac9Sjeremylt 1000d1bcdac9Sjeremylt @param opfield CeedOperatorField 1001d1bcdac9Sjeremylt @param[out] basis Variable to store CeedBasis 1002d1bcdac9Sjeremylt 1003d1bcdac9Sjeremylt @return An error code: 0 - success, otherwise - failure 1004d1bcdac9Sjeremylt 1005d1bcdac9Sjeremylt @ref Advanced 1006d1bcdac9Sjeremylt **/ 1007d1bcdac9Sjeremylt 1008692c2638Sjeremylt int CeedOperatorFieldGetBasis(CeedOperatorField opfield, CeedBasis *basis) { 1009fe2413ffSjeremylt *basis = opfield->basis; 1010d1bcdac9Sjeremylt return 0; 1011d1bcdac9Sjeremylt } 1012d1bcdac9Sjeremylt 1013d1bcdac9Sjeremylt /** 1014d1bcdac9Sjeremylt @brief Get the CeedVector of a CeedOperatorField 1015d1bcdac9Sjeremylt 1016d1bcdac9Sjeremylt @param opfield CeedOperatorField 1017d1bcdac9Sjeremylt @param[out] vec Variable to store CeedVector 1018d1bcdac9Sjeremylt 1019d1bcdac9Sjeremylt @return An error code: 0 - success, otherwise - failure 1020d1bcdac9Sjeremylt 1021d1bcdac9Sjeremylt @ref Advanced 1022d1bcdac9Sjeremylt **/ 1023d1bcdac9Sjeremylt 1024692c2638Sjeremylt int CeedOperatorFieldGetVector(CeedOperatorField opfield, CeedVector *vec) { 1025fe2413ffSjeremylt *vec = opfield->vec; 1026d1bcdac9Sjeremylt return 0; 1027d1bcdac9Sjeremylt } 1028d1bcdac9Sjeremylt 1029d1bcdac9Sjeremylt /** 1030b11c1e72Sjeremylt @brief Destroy a CeedOperator 1031d7b241e6Sjeremylt 1032d7b241e6Sjeremylt @param op CeedOperator to destroy 1033b11c1e72Sjeremylt 1034b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1035dfdf5a53Sjeremylt 1036dfdf5a53Sjeremylt @ref Basic 1037b11c1e72Sjeremylt **/ 1038d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) { 1039d7b241e6Sjeremylt int ierr; 1040d7b241e6Sjeremylt 1041d7b241e6Sjeremylt if (!*op || --(*op)->refcount > 0) return 0; 1042d7b241e6Sjeremylt if ((*op)->Destroy) { 1043d7b241e6Sjeremylt ierr = (*op)->Destroy(*op); CeedChk(ierr); 1044d7b241e6Sjeremylt } 1045fe2413ffSjeremylt ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 1046fe2413ffSjeremylt // Free fields 10471d102b48SJeremy L Thompson for (int i=0; i<(*op)->nfields; i++) 104852d6035fSJeremy L Thompson if ((*op)->inputfields[i]) { 104971352a93Sjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->inputfields[i]->Erestrict); 105071352a93Sjeremylt CeedChk(ierr); 105171352a93Sjeremylt if ((*op)->inputfields[i]->basis != CEED_BASIS_COLLOCATED) { 105271352a93Sjeremylt ierr = CeedBasisDestroy(&(*op)->inputfields[i]->basis); CeedChk(ierr); 105371352a93Sjeremylt } 105471352a93Sjeremylt if ((*op)->inputfields[i]->vec != CEED_VECTOR_ACTIVE && 105571352a93Sjeremylt (*op)->inputfields[i]->vec != CEED_VECTOR_NONE ) { 105671352a93Sjeremylt ierr = CeedVectorDestroy(&(*op)->inputfields[i]->vec); CeedChk(ierr); 105771352a93Sjeremylt } 1058fe2413ffSjeremylt ierr = CeedFree(&(*op)->inputfields[i]); CeedChk(ierr); 1059fe2413ffSjeremylt } 10601d102b48SJeremy L Thompson for (int i=0; i<(*op)->nfields; i++) 1061d0eb30a5Sjeremylt if ((*op)->outputfields[i]) { 106271352a93Sjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->outputfields[i]->Erestrict); 106371352a93Sjeremylt CeedChk(ierr); 106471352a93Sjeremylt if ((*op)->outputfields[i]->basis != CEED_BASIS_COLLOCATED) { 106571352a93Sjeremylt ierr = CeedBasisDestroy(&(*op)->outputfields[i]->basis); CeedChk(ierr); 106671352a93Sjeremylt } 106771352a93Sjeremylt if ((*op)->outputfields[i]->vec != CEED_VECTOR_ACTIVE && 106871352a93Sjeremylt (*op)->outputfields[i]->vec != CEED_VECTOR_NONE ) { 106971352a93Sjeremylt ierr = CeedVectorDestroy(&(*op)->outputfields[i]->vec); CeedChk(ierr); 107071352a93Sjeremylt } 1071fe2413ffSjeremylt ierr = CeedFree(&(*op)->outputfields[i]); CeedChk(ierr); 1072fe2413ffSjeremylt } 107352d6035fSJeremy L Thompson // Destroy suboperators 10741d102b48SJeremy L Thompson for (int i=0; i<(*op)->numsub; i++) 107552d6035fSJeremy L Thompson if ((*op)->suboperators[i]) { 107652d6035fSJeremy L Thompson ierr = CeedOperatorDestroy(&(*op)->suboperators[i]); CeedChk(ierr); 107752d6035fSJeremy L Thompson } 1078d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 1079d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 1080d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 1081fe2413ffSjeremylt 10825107b09fSJeremy L Thompson // Destroy fallback 10835107b09fSJeremy L Thompson if ((*op)->opfallback) { 10845107b09fSJeremy L Thompson ierr = (*op)->qffallback->Destroy((*op)->qffallback); CeedChk(ierr); 10855107b09fSJeremy L Thompson ierr = CeedFree(&(*op)->qffallback); CeedChk(ierr); 10865107b09fSJeremy L Thompson ierr = (*op)->opfallback->Destroy((*op)->opfallback); CeedChk(ierr); 10875107b09fSJeremy L Thompson ierr = CeedFree(&(*op)->opfallback); CeedChk(ierr); 10885107b09fSJeremy L Thompson } 10895107b09fSJeremy L Thompson 1090fe2413ffSjeremylt ierr = CeedFree(&(*op)->inputfields); CeedChk(ierr); 1091fe2413ffSjeremylt ierr = CeedFree(&(*op)->outputfields); CeedChk(ierr); 109252d6035fSJeremy L Thompson ierr = CeedFree(&(*op)->suboperators); CeedChk(ierr); 1093d7b241e6Sjeremylt ierr = CeedFree(op); CeedChk(ierr); 1094d7b241e6Sjeremylt return 0; 1095d7b241e6Sjeremylt } 1096d7b241e6Sjeremylt 1097d7b241e6Sjeremylt /// @} 1098