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> 203bd813ffSjeremylt #include <math.h> 21d7b241e6Sjeremylt 22dfdf5a53Sjeremylt /// @file 23dfdf5a53Sjeremylt /// Implementation of public CeedOperator interfaces 24dfdf5a53Sjeremylt /// 25dfdf5a53Sjeremylt /// @addtogroup CeedOperator 26dfdf5a53Sjeremylt /// @{ 27d7b241e6Sjeremylt 28d7b241e6Sjeremylt /** 290219ea01SJeremy L Thompson @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and 300219ea01SJeremy L Thompson CeedElemRestriction can be associated with CeedQFunction fields with 310219ea01SJeremy L Thompson \ref CeedOperatorSetField. 32d7b241e6Sjeremylt 33b11c1e72Sjeremylt @param ceed A Ceed object where the CeedOperator will be created 34d7b241e6Sjeremylt @param qf QFunction defining the action of the operator at quadrature points 3534138859Sjeremylt @param dqf QFunction defining the action of the Jacobian of @a qf (or 3634138859Sjeremylt CEED_QFUNCTION_NONE) 37d7b241e6Sjeremylt @param dqfT QFunction defining the action of the transpose of the Jacobian 3834138859Sjeremylt of @a qf (or CEED_QFUNCTION_NONE) 39b11c1e72Sjeremylt @param[out] op Address of the variable where the newly created 40b11c1e72Sjeremylt CeedOperator will be stored 41b11c1e72Sjeremylt 42b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 43dfdf5a53Sjeremylt 44dfdf5a53Sjeremylt @ref Basic 45d7b241e6Sjeremylt */ 46d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf, 47d7b241e6Sjeremylt CeedQFunction dqfT, CeedOperator *op) { 48d7b241e6Sjeremylt int ierr; 49d7b241e6Sjeremylt 505fe0d4faSjeremylt if (!ceed->OperatorCreate) { 515fe0d4faSjeremylt Ceed delegate; 52aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 535fe0d4faSjeremylt 545fe0d4faSjeremylt if (!delegate) 55c042f62fSJeremy L Thompson // LCOV_EXCL_START 565fe0d4faSjeremylt return CeedError(ceed, 1, "Backend does not support OperatorCreate"); 57c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 585fe0d4faSjeremylt 595fe0d4faSjeremylt ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr); 605fe0d4faSjeremylt return 0; 615fe0d4faSjeremylt } 625fe0d4faSjeremylt 63d7b241e6Sjeremylt ierr = CeedCalloc(1, op); CeedChk(ierr); 64d7b241e6Sjeremylt (*op)->ceed = ceed; 65d7b241e6Sjeremylt ceed->refcount++; 66d7b241e6Sjeremylt (*op)->refcount = 1; 67442e7f0bSjeremylt if (qf == CEED_QFUNCTION_NONE) 68442e7f0bSjeremylt // LCOV_EXCL_START 69442e7f0bSjeremylt return CeedError(ceed, 1, "Operator must have a valid QFunction."); 70442e7f0bSjeremylt // LCOV_EXCL_STOP 71d7b241e6Sjeremylt (*op)->qf = qf; 72d7b241e6Sjeremylt qf->refcount++; 73442e7f0bSjeremylt if (dqf && dqf != CEED_QFUNCTION_NONE) { 74d7b241e6Sjeremylt (*op)->dqf = dqf; 75442e7f0bSjeremylt dqf->refcount++; 76442e7f0bSjeremylt } 77442e7f0bSjeremylt if (dqfT && dqfT != CEED_QFUNCTION_NONE) { 78d7b241e6Sjeremylt (*op)->dqfT = dqfT; 79442e7f0bSjeremylt dqfT->refcount++; 80442e7f0bSjeremylt } 81fe2413ffSjeremylt ierr = CeedCalloc(16, &(*op)->inputfields); CeedChk(ierr); 82fe2413ffSjeremylt ierr = CeedCalloc(16, &(*op)->outputfields); CeedChk(ierr); 83d7b241e6Sjeremylt ierr = ceed->OperatorCreate(*op); CeedChk(ierr); 84d7b241e6Sjeremylt return 0; 85d7b241e6Sjeremylt } 86d7b241e6Sjeremylt 87d7b241e6Sjeremylt /** 8852d6035fSJeremy L Thompson @brief Create an operator that composes the action of several operators 8952d6035fSJeremy L Thompson 9052d6035fSJeremy L Thompson @param ceed A Ceed object where the CeedOperator will be created 9152d6035fSJeremy L Thompson @param[out] op Address of the variable where the newly created 9252d6035fSJeremy L Thompson Composite CeedOperator will be stored 9352d6035fSJeremy L Thompson 9452d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 9552d6035fSJeremy L Thompson 9652d6035fSJeremy L Thompson @ref Basic 9752d6035fSJeremy L Thompson */ 9852d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) { 9952d6035fSJeremy L Thompson int ierr; 10052d6035fSJeremy L Thompson 10152d6035fSJeremy L Thompson if (!ceed->CompositeOperatorCreate) { 10252d6035fSJeremy L Thompson Ceed delegate; 103aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 10452d6035fSJeremy L Thompson 105250756a7Sjeremylt if (delegate) { 10652d6035fSJeremy L Thompson ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr); 10752d6035fSJeremy L Thompson return 0; 10852d6035fSJeremy L Thompson } 109250756a7Sjeremylt } 11052d6035fSJeremy L Thompson 11152d6035fSJeremy L Thompson ierr = CeedCalloc(1, op); CeedChk(ierr); 11252d6035fSJeremy L Thompson (*op)->ceed = ceed; 11352d6035fSJeremy L Thompson ceed->refcount++; 11452d6035fSJeremy L Thompson (*op)->composite = true; 11552d6035fSJeremy L Thompson ierr = CeedCalloc(16, &(*op)->suboperators); CeedChk(ierr); 116250756a7Sjeremylt 117250756a7Sjeremylt if (ceed->CompositeOperatorCreate) { 11852d6035fSJeremy L Thompson ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr); 119250756a7Sjeremylt } 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 23534138859Sjeremylt @param[out] compositeop Composite CeedOperator 23634138859Sjeremylt @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 /** 313250756a7Sjeremylt @brief Check if a CeedOperator is ready to be used. 314250756a7Sjeremylt 315250756a7Sjeremylt @param[in] ceed Ceed object for error handling 316250756a7Sjeremylt @param[in] op CeedOperator to check 317250756a7Sjeremylt 318250756a7Sjeremylt @return An error code: 0 - success, otherwise - failure 319250756a7Sjeremylt 320250756a7Sjeremylt @ref Basic 321250756a7Sjeremylt **/ 322250756a7Sjeremylt static int CeedOperatorCheckReady(Ceed ceed, CeedOperator op) { 323250756a7Sjeremylt CeedQFunction qf = op->qf; 324250756a7Sjeremylt 325250756a7Sjeremylt if (op->composite) { 326250756a7Sjeremylt if (!op->numsub) 327250756a7Sjeremylt // LCOV_EXCL_START 328250756a7Sjeremylt return CeedError(ceed, 1, "No suboperators set"); 329250756a7Sjeremylt // LCOV_EXCL_STOP 330250756a7Sjeremylt } else { 331250756a7Sjeremylt if (op->nfields == 0) 332250756a7Sjeremylt // LCOV_EXCL_START 333250756a7Sjeremylt return CeedError(ceed, 1, "No operator fields set"); 334250756a7Sjeremylt // LCOV_EXCL_STOP 335250756a7Sjeremylt if (op->nfields < qf->numinputfields + qf->numoutputfields) 336250756a7Sjeremylt // LCOV_EXCL_START 337250756a7Sjeremylt return CeedError(ceed, 1, "Not all operator fields set"); 338250756a7Sjeremylt // LCOV_EXCL_STOP 339250756a7Sjeremylt if (!op->hasrestriction) 340250756a7Sjeremylt // LCOV_EXCL_START 341250756a7Sjeremylt return CeedError(ceed, 1,"At least one restriction required"); 342250756a7Sjeremylt // LCOV_EXCL_STOP 343250756a7Sjeremylt if (op->numqpoints == 0) 344250756a7Sjeremylt // LCOV_EXCL_START 345250756a7Sjeremylt return CeedError(ceed, 1,"At least one non-collocated basis required"); 346250756a7Sjeremylt // LCOV_EXCL_STOP 347250756a7Sjeremylt } 348250756a7Sjeremylt 349250756a7Sjeremylt return 0; 350250756a7Sjeremylt } 351250756a7Sjeremylt 352250756a7Sjeremylt /** 3531d102b48SJeremy L Thompson @brief Assemble a linear CeedQFunction associated with a CeedOperator 3541d102b48SJeremy L Thompson 3551d102b48SJeremy L Thompson This returns a CeedVector containing a matrix at each quadrature point 3561d102b48SJeremy L Thompson providing the action of the CeedQFunction associated with the CeedOperator. 3571d102b48SJeremy L Thompson The vector 'assembled' is of shape 3581d102b48SJeremy L Thompson [num_elements, num_input_fields, num_output_fields, num_quad_points] 3591d102b48SJeremy L Thompson and contains column-major matrices representing the action of the 3601d102b48SJeremy L Thompson CeedQFunction for a corresponding quadrature point on an element. Inputs and 3611d102b48SJeremy L Thompson outputs are in the order provided by the user when adding CeedOperator fields. 3621d102b48SJeremy L Thompson For example, a QFunction with inputs 'u' and 'gradu' and outputs 'gradv' and 3631d102b48SJeremy L Thompson 'v', provided in that order, would result in an assembled QFunction that 3641d102b48SJeremy L Thompson consists of (1 + dim) x (dim + 1) matrices at each quadrature point acting 3651d102b48SJeremy L Thompson on the input [u, du_0, du_1] and producing the output [dv_0, dv_1, v]. 3661d102b48SJeremy L Thompson 3671d102b48SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 3681d102b48SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedQFunction at 3691d102b48SJeremy L Thompson quadrature points 3701d102b48SJeremy L Thompson @param[out] rstr CeedElemRestriction for CeedVector containing assembled 3711d102b48SJeremy L Thompson CeedQFunction 3721d102b48SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 3731d102b48SJeremy L Thompson CEED_REQUEST_IMMEDIATE 3741d102b48SJeremy L Thompson 3751d102b48SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 3761d102b48SJeremy L Thompson 377b7ec98d8SJeremy L Thompson @ref Basic 3781d102b48SJeremy L Thompson **/ 3791d102b48SJeremy L Thompson int CeedOperatorAssembleLinearQFunction(CeedOperator op, CeedVector *assembled, 3807f823360Sjeremylt CeedElemRestriction *rstr, 3817f823360Sjeremylt CeedRequest *request) { 3821d102b48SJeremy L Thompson int ierr; 3831d102b48SJeremy L Thompson Ceed ceed = op->ceed; 384250756a7Sjeremylt ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 3851d102b48SJeremy L Thompson 386*7172caadSjeremylt // Backend version 3875107b09fSJeremy L Thompson if (op->AssembleLinearQFunction) { 3881d102b48SJeremy L Thompson ierr = op->AssembleLinearQFunction(op, assembled, rstr, request); 3891d102b48SJeremy L Thompson CeedChk(ierr); 3905107b09fSJeremy L Thompson } else { 3915107b09fSJeremy L Thompson // Fallback to reference Ceed 3925107b09fSJeremy L Thompson if (!op->opfallback) { 3935107b09fSJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 3945107b09fSJeremy L Thompson } 3955107b09fSJeremy L Thompson // Assemble 3965107b09fSJeremy L Thompson ierr = op->opfallback->AssembleLinearQFunction(op->opfallback, assembled, 3975107b09fSJeremy L Thompson rstr, request); CeedChk(ierr); 3985107b09fSJeremy L Thompson } 399250756a7Sjeremylt 4001d102b48SJeremy L Thompson return 0; 4011d102b48SJeremy L Thompson } 4021d102b48SJeremy L Thompson 4031d102b48SJeremy L Thompson /** 404b7ec98d8SJeremy L Thompson @brief Assemble the diagonal of a square linear Operator 405b7ec98d8SJeremy L Thompson 406b7ec98d8SJeremy L Thompson This returns a CeedVector containing the diagonal of a linear CeedOperator. 407b7ec98d8SJeremy L Thompson 408b7ec98d8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 409b7ec98d8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator diagonal 410b7ec98d8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 411b7ec98d8SJeremy L Thompson CEED_REQUEST_IMMEDIATE 412b7ec98d8SJeremy L Thompson 413b7ec98d8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 414b7ec98d8SJeremy L Thompson 415b7ec98d8SJeremy L Thompson @ref Basic 416b7ec98d8SJeremy L Thompson **/ 4177f823360Sjeremylt int CeedOperatorAssembleLinearDiagonal(CeedOperator op, CeedVector *assembled, 4187f823360Sjeremylt CeedRequest *request) { 419b7ec98d8SJeremy L Thompson int ierr; 420b7ec98d8SJeremy L Thompson Ceed ceed = op->ceed; 421250756a7Sjeremylt ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 422b7ec98d8SJeremy L Thompson 423b7ec98d8SJeremy L Thompson // Use backend version, if available 424b7ec98d8SJeremy L Thompson if (op->AssembleLinearDiagonal) { 425b7ec98d8SJeremy L Thompson ierr = op->AssembleLinearDiagonal(op, assembled, request); CeedChk(ierr); 426*7172caadSjeremylt } else { 427*7172caadSjeremylt // Fallback to reference Ceed 428*7172caadSjeremylt if (!op->opfallback) { 429*7172caadSjeremylt ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 430b7ec98d8SJeremy L Thompson } 431*7172caadSjeremylt // Assemble 432*7172caadSjeremylt ierr = op->opfallback->AssembleLinearDiagonal(op->opfallback, assembled, 433*7172caadSjeremylt request); CeedChk(ierr); 434b7ec98d8SJeremy L Thompson } 435b7ec98d8SJeremy L Thompson 436b7ec98d8SJeremy L Thompson return 0; 437b7ec98d8SJeremy L Thompson } 438b7ec98d8SJeremy L Thompson 439b7ec98d8SJeremy L Thompson /** 4403bd813ffSjeremylt @brief Build a FDM based approximate inverse for each element for a 4413bd813ffSjeremylt CeedOperator 4423bd813ffSjeremylt 4433bd813ffSjeremylt This returns a CeedOperator and CeedVector to apply a Fast Diagonalization 4443bd813ffSjeremylt Method based approximate inverse. This function obtains the simultaneous 4453bd813ffSjeremylt diagonalization for the 1D mass and Laplacian operators, 4463bd813ffSjeremylt M = V^T V, K = V^T S V. 4473bd813ffSjeremylt The assembled QFunction is used to modify the eigenvalues from simultaneous 4483bd813ffSjeremylt diagonalization and obtain an approximate inverse of the form 4493bd813ffSjeremylt V^T S^hat V. The CeedOperator must be linear and non-composite. The 4503bd813ffSjeremylt associated CeedQFunction must therefore also be linear. 4513bd813ffSjeremylt 4523bd813ffSjeremylt @param op CeedOperator to create element inverses 4533bd813ffSjeremylt @param[out] fdminv CeedOperator to apply the action of a FDM based inverse 4543bd813ffSjeremylt for each element 4553bd813ffSjeremylt @param[out] qdata CeedVector to hold qdata for fdminv 4563bd813ffSjeremylt @param request Address of CeedRequest for non-blocking completion, else 4573bd813ffSjeremylt CEED_REQUEST_IMMEDIATE 4583bd813ffSjeremylt 4593bd813ffSjeremylt @return An error code: 0 - success, otherwise - failure 4603bd813ffSjeremylt 4613bd813ffSjeremylt @ref Advanced 4623bd813ffSjeremylt **/ 4633bd813ffSjeremylt int CeedOperatorCreateFDMElementInverse(CeedOperator op, CeedOperator *fdminv, 4643bd813ffSjeremylt CeedRequest *request) { 4653bd813ffSjeremylt int ierr; 4663bd813ffSjeremylt Ceed ceed = op->ceed; 4673bd813ffSjeremylt 4683bd813ffSjeremylt // Determine active input basis 4693bd813ffSjeremylt bool interp = false, grad = false; 4703bd813ffSjeremylt CeedBasis basis = NULL; 4713bd813ffSjeremylt CeedElemRestriction rstr = NULL; 4723bd813ffSjeremylt for (CeedInt i=0; i<op->qf->numinputfields; i++) 4733bd813ffSjeremylt if (op->inputfields[i] && op->inputfields[i]->vec == CEED_VECTOR_ACTIVE) { 4743bd813ffSjeremylt basis = op->inputfields[i]->basis; 4753bd813ffSjeremylt interp = interp || op->qf->inputfields[i]->emode == CEED_EVAL_INTERP; 4763bd813ffSjeremylt grad = grad || op->qf->inputfields[i]->emode == CEED_EVAL_GRAD; 4773bd813ffSjeremylt rstr = op->inputfields[i]->Erestrict; 4783bd813ffSjeremylt } 4793bd813ffSjeremylt if (!basis) 4803bd813ffSjeremylt return CeedError(ceed, 1, "No active field set"); 4813bd813ffSjeremylt CeedInt P1d, Q1d, elemsize, nqpts, dim, ncomp = 1, nelem = 1, nnodes = 1; 4823bd813ffSjeremylt ierr = CeedBasisGetNumNodes1D(basis, &P1d); CeedChk(ierr); 4833bd813ffSjeremylt ierr = CeedBasisGetNumNodes(basis, &elemsize); CeedChk(ierr); 4843bd813ffSjeremylt ierr = CeedBasisGetNumQuadraturePoints1D(basis, &Q1d); CeedChk(ierr); 4853bd813ffSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis, &nqpts); CeedChk(ierr); 4863bd813ffSjeremylt ierr = CeedBasisGetDimension(basis, &dim); CeedChk(ierr); 4873bd813ffSjeremylt ierr = CeedBasisGetNumComponents(basis, &ncomp); CeedChk(ierr); 4883bd813ffSjeremylt ierr = CeedElemRestrictionGetNumElements(rstr, &nelem); CeedChk(ierr); 4893bd813ffSjeremylt ierr = CeedElemRestrictionGetNumNodes(rstr, &nnodes); CeedChk(ierr); 4903bd813ffSjeremylt 4913bd813ffSjeremylt // Build and diagonalize 1D Mass and Laplacian 4923bd813ffSjeremylt if (!basis->tensorbasis) 4933bd813ffSjeremylt return CeedError(ceed, 1, "FDMElementInverse only supported for tensor " 4943bd813ffSjeremylt "bases"); 4953bd813ffSjeremylt CeedScalar *work, *mass, *laplace, *x, *x2, *lambda; 4963bd813ffSjeremylt ierr = CeedMalloc(Q1d*P1d, &work); CeedChk(ierr); 4973bd813ffSjeremylt ierr = CeedMalloc(P1d*P1d, &mass); CeedChk(ierr); 4983bd813ffSjeremylt ierr = CeedMalloc(P1d*P1d, &laplace); CeedChk(ierr); 4993bd813ffSjeremylt ierr = CeedMalloc(P1d*P1d, &x); CeedChk(ierr); 5003bd813ffSjeremylt ierr = CeedMalloc(P1d*P1d, &x2); CeedChk(ierr); 5013bd813ffSjeremylt ierr = CeedMalloc(P1d, &lambda); CeedChk(ierr); 5023bd813ffSjeremylt // -- Mass 5033bd813ffSjeremylt for (CeedInt i=0; i<Q1d; i++) 5043bd813ffSjeremylt for (CeedInt j=0; j<P1d; j++) 5053bd813ffSjeremylt work[i+j*Q1d] = basis->interp1d[i*P1d+j]*basis->qweight1d[i]; 5063bd813ffSjeremylt ierr = CeedMatrixMultiply(ceed, work, basis->interp1d, mass, P1d, P1d, Q1d); 5073bd813ffSjeremylt CeedChk(ierr); 5083bd813ffSjeremylt // -- Laplacian 5093bd813ffSjeremylt for (CeedInt i=0; i<Q1d; i++) 5103bd813ffSjeremylt for (CeedInt j=0; j<P1d; j++) 5113bd813ffSjeremylt work[i+j*Q1d] = basis->grad1d[i*P1d+j]*basis->qweight1d[i]; 5123bd813ffSjeremylt ierr = CeedMatrixMultiply(ceed, work, basis->grad1d, laplace, P1d, P1d, Q1d); 5133bd813ffSjeremylt CeedChk(ierr); 5143bd813ffSjeremylt // -- Diagonalize 5153bd813ffSjeremylt ierr = CeedSimultaneousDiagonalization(ceed, laplace, mass, x, lambda, P1d); 5163bd813ffSjeremylt CeedChk(ierr); 5173bd813ffSjeremylt ierr = CeedFree(&work); CeedChk(ierr); 5183bd813ffSjeremylt ierr = CeedFree(&mass); CeedChk(ierr); 5193bd813ffSjeremylt ierr = CeedFree(&laplace); CeedChk(ierr); 5203bd813ffSjeremylt for (CeedInt i=0; i<P1d; i++) 5213bd813ffSjeremylt for (CeedInt j=0; j<P1d; j++) 5223bd813ffSjeremylt x2[i+j*P1d] = x[j+i*P1d]; 5233bd813ffSjeremylt ierr = CeedFree(&x); CeedChk(ierr); 5243bd813ffSjeremylt 5253bd813ffSjeremylt // Assemble QFunction 5263bd813ffSjeremylt CeedVector assembled; 5273bd813ffSjeremylt CeedElemRestriction rstr_qf; 5283bd813ffSjeremylt ierr = CeedOperatorAssembleLinearQFunction(op, &assembled, &rstr_qf, 5293bd813ffSjeremylt request); CeedChk(ierr); 5303bd813ffSjeremylt ierr = CeedElemRestrictionDestroy(&rstr_qf); CeedChk(ierr); 5313bd813ffSjeremylt 5323bd813ffSjeremylt // Calculate element averages 5333bd813ffSjeremylt CeedInt nfields = ((interp?1:0) + (grad?dim:0))*((interp?1:0) + (grad?dim:0)); 5343bd813ffSjeremylt CeedScalar *elemavg; 5353bd813ffSjeremylt const CeedScalar *assembledarray, *qweightsarray; 5363bd813ffSjeremylt CeedVector qweights; 5373bd813ffSjeremylt ierr = CeedVectorCreate(ceed, nqpts, &qweights); CeedChk(ierr); 5383bd813ffSjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, CEED_EVAL_WEIGHT, 5393bd813ffSjeremylt CEED_VECTOR_NONE, qweights); CeedChk(ierr); 5403bd813ffSjeremylt ierr = CeedVectorGetArrayRead(assembled, CEED_MEM_HOST, &assembledarray); 5413bd813ffSjeremylt CeedChk(ierr); 5423bd813ffSjeremylt ierr = CeedVectorGetArrayRead(qweights, CEED_MEM_HOST, &qweightsarray); 5433bd813ffSjeremylt CeedChk(ierr); 5443bd813ffSjeremylt ierr = CeedCalloc(nelem, &elemavg); CeedChk(ierr); 5453bd813ffSjeremylt for (CeedInt e=0; e<nelem; e++) { 5463bd813ffSjeremylt CeedInt count = 0; 5473bd813ffSjeremylt for (CeedInt q=0; q<nqpts; q++) 5483bd813ffSjeremylt for (CeedInt i=0; i<ncomp*ncomp*nfields; i++) 5493bd813ffSjeremylt if (fabs(assembledarray[e*nelem*nqpts*ncomp*ncomp*nfields + 5500e4d4210Sjeremylt i*nqpts + q]) > CEED_EPSILON) { 5513bd813ffSjeremylt elemavg[e] += assembledarray[e*nelem*nqpts*ncomp*ncomp*nfields + 5523bd813ffSjeremylt i*nqpts + q] / qweightsarray[q]; 5533bd813ffSjeremylt count++; 5543bd813ffSjeremylt } 5553bd813ffSjeremylt if (count) 5563bd813ffSjeremylt elemavg[e] /= count; 5573bd813ffSjeremylt } 5583bd813ffSjeremylt ierr = CeedVectorRestoreArrayRead(assembled, &assembledarray); CeedChk(ierr); 5593bd813ffSjeremylt ierr = CeedVectorDestroy(&assembled); CeedChk(ierr); 5603bd813ffSjeremylt ierr = CeedVectorRestoreArrayRead(qweights, &qweightsarray); CeedChk(ierr); 5613bd813ffSjeremylt ierr = CeedVectorDestroy(&qweights); CeedChk(ierr); 5623bd813ffSjeremylt 5633bd813ffSjeremylt // Build FDM diagonal 5643bd813ffSjeremylt CeedVector qdata; 5653bd813ffSjeremylt CeedScalar *qdataarray; 5663bd813ffSjeremylt ierr = CeedVectorCreate(ceed, nelem*ncomp*nnodes, &qdata); CeedChk(ierr); 5673bd813ffSjeremylt ierr = CeedVectorSetArray(qdata, CEED_MEM_HOST, CEED_COPY_VALUES, NULL); 5683bd813ffSjeremylt CeedChk(ierr); 5693bd813ffSjeremylt ierr = CeedVectorGetArray(qdata, CEED_MEM_HOST, &qdataarray); CeedChk(ierr); 5703bd813ffSjeremylt for (CeedInt e=0; e<nelem; e++) 5713bd813ffSjeremylt for (CeedInt c=0; c<ncomp; c++) 5723bd813ffSjeremylt for (CeedInt n=0; n<nnodes; n++) { 5733bd813ffSjeremylt if (interp) 5743bd813ffSjeremylt qdataarray[(e*ncomp+c)*nnodes+n] = 1; 5753bd813ffSjeremylt if (grad) 5763bd813ffSjeremylt for (CeedInt d=0; d<dim; d++) { 5773bd813ffSjeremylt CeedInt i = (n / CeedIntPow(P1d, d)) % P1d; 5783bd813ffSjeremylt qdataarray[(e*ncomp+c)*nnodes+n] += lambda[i]; 5793bd813ffSjeremylt } 5803bd813ffSjeremylt qdataarray[(e*ncomp+c)*nnodes+n] = 1 / (elemavg[e] * 5813bd813ffSjeremylt qdataarray[(e*ncomp+c)*nnodes+n]); 5823bd813ffSjeremylt } 5833bd813ffSjeremylt ierr = CeedFree(&elemavg); CeedChk(ierr); 5843bd813ffSjeremylt ierr = CeedVectorRestoreArray(qdata, &qdataarray); CeedChk(ierr); 5853bd813ffSjeremylt 5863bd813ffSjeremylt // Setup FDM operator 5873bd813ffSjeremylt // -- Basis 5883bd813ffSjeremylt CeedBasis fdm_basis; 5893bd813ffSjeremylt CeedScalar *graddummy, *qrefdummy, *qweightdummy; 5903bd813ffSjeremylt ierr = CeedCalloc(P1d*P1d, &graddummy); CeedChk(ierr); 5913bd813ffSjeremylt ierr = CeedCalloc(P1d, &qrefdummy); CeedChk(ierr); 5923bd813ffSjeremylt ierr = CeedCalloc(P1d, &qweightdummy); CeedChk(ierr); 5933bd813ffSjeremylt ierr = CeedBasisCreateTensorH1(ceed, dim, ncomp, P1d, P1d, x2, graddummy, 5943bd813ffSjeremylt qrefdummy, qweightdummy, &fdm_basis); 5953bd813ffSjeremylt CeedChk(ierr); 5963bd813ffSjeremylt ierr = CeedFree(&graddummy); CeedChk(ierr); 5973bd813ffSjeremylt ierr = CeedFree(&qrefdummy); CeedChk(ierr); 5983bd813ffSjeremylt ierr = CeedFree(&qweightdummy); CeedChk(ierr); 5993bd813ffSjeremylt ierr = CeedFree(&x2); CeedChk(ierr); 6003bd813ffSjeremylt ierr = CeedFree(&lambda); CeedChk(ierr); 6013bd813ffSjeremylt 6023bd813ffSjeremylt // -- Restriction 6033bd813ffSjeremylt CeedElemRestriction rstr_i; 6043bd813ffSjeremylt ierr = CeedElemRestrictionCreateIdentity(ceed, nelem, nnodes, nnodes*nelem, 6053bd813ffSjeremylt ncomp, &rstr_i); CeedChk(ierr); 6063bd813ffSjeremylt // -- QFunction 6073bd813ffSjeremylt CeedQFunction mass_qf; 6083bd813ffSjeremylt ierr = CeedQFunctionCreateInteriorByName(ceed, "MassApply", &mass_qf); 6093bd813ffSjeremylt CeedChk(ierr); 6103bd813ffSjeremylt // -- Operator 6113bd813ffSjeremylt ierr = CeedOperatorCreate(ceed, mass_qf, NULL, NULL, fdminv); CeedChk(ierr); 6123bd813ffSjeremylt CeedOperatorSetField(*fdminv, "u", rstr_i, CEED_NOTRANSPOSE, 6133bd813ffSjeremylt fdm_basis, CEED_VECTOR_ACTIVE); CeedChk(ierr); 6143bd813ffSjeremylt CeedOperatorSetField(*fdminv, "qdata", rstr_i, CEED_NOTRANSPOSE, 6153bd813ffSjeremylt CEED_BASIS_COLLOCATED, qdata); CeedChk(ierr); 6163bd813ffSjeremylt CeedOperatorSetField(*fdminv, "v", rstr_i, CEED_NOTRANSPOSE, 6173bd813ffSjeremylt fdm_basis, CEED_VECTOR_ACTIVE); CeedChk(ierr); 6183bd813ffSjeremylt 6193bd813ffSjeremylt // Cleanup 6203bd813ffSjeremylt ierr = CeedVectorDestroy(&qdata); CeedChk(ierr); 6213bd813ffSjeremylt ierr = CeedBasisDestroy(&fdm_basis); CeedChk(ierr); 6223bd813ffSjeremylt ierr = CeedElemRestrictionDestroy(&rstr_i); CeedChk(ierr); 6233bd813ffSjeremylt ierr = CeedQFunctionDestroy(&mass_qf); CeedChk(ierr); 6243bd813ffSjeremylt 6253bd813ffSjeremylt return 0; 6263bd813ffSjeremylt } 6273bd813ffSjeremylt 6283bd813ffSjeremylt 6293bd813ffSjeremylt /** 6303bd813ffSjeremylt @brief Apply CeedOperator to a vector 631d7b241e6Sjeremylt 632d7b241e6Sjeremylt This computes the action of the operator on the specified (active) input, 633d7b241e6Sjeremylt yielding its (active) output. All inputs and outputs must be specified using 634d7b241e6Sjeremylt CeedOperatorSetField(). 635d7b241e6Sjeremylt 636d7b241e6Sjeremylt @param op CeedOperator to apply 63734138859Sjeremylt @param[in] in CeedVector containing input state or CEED_VECTOR_NONE if 63834138859Sjeremylt there are no active inputs 639b11c1e72Sjeremylt @param[out] out CeedVector to store result of applying operator (must be 64034138859Sjeremylt distinct from @a in) or CEED_VECTOR_NONE if there are no 64134138859Sjeremylt active outputs 642d7b241e6Sjeremylt @param request Address of CeedRequest for non-blocking completion, else 643d7b241e6Sjeremylt CEED_REQUEST_IMMEDIATE 644b11c1e72Sjeremylt 645b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 646dfdf5a53Sjeremylt 647dfdf5a53Sjeremylt @ref Basic 648b11c1e72Sjeremylt **/ 649692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out, 650692c2638Sjeremylt CeedRequest *request) { 651d7b241e6Sjeremylt int ierr; 652d7b241e6Sjeremylt Ceed ceed = op->ceed; 653250756a7Sjeremylt ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 654d7b241e6Sjeremylt 655250756a7Sjeremylt if (op->numelements) { 656250756a7Sjeremylt // Standard Operator 657cae8b89aSjeremylt if (op->Apply) { 658250756a7Sjeremylt ierr = op->Apply(op, in, out, request); CeedChk(ierr); 659cae8b89aSjeremylt } else { 660cae8b89aSjeremylt // Zero all output vectors 661250756a7Sjeremylt CeedQFunction qf = op->qf; 662cae8b89aSjeremylt for (CeedInt i=0; i<qf->numoutputfields; i++) { 663cae8b89aSjeremylt CeedVector vec = op->outputfields[i]->vec; 664cae8b89aSjeremylt if (vec == CEED_VECTOR_ACTIVE) 665cae8b89aSjeremylt vec = out; 666cae8b89aSjeremylt if (vec != CEED_VECTOR_NONE) { 667cae8b89aSjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 668cae8b89aSjeremylt } 669cae8b89aSjeremylt } 670250756a7Sjeremylt // Apply 671250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 672250756a7Sjeremylt } 673250756a7Sjeremylt } else if (op->composite) { 674250756a7Sjeremylt // Composite Operator 675250756a7Sjeremylt if (op->ApplyComposite) { 676250756a7Sjeremylt ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr); 677250756a7Sjeremylt } else { 678250756a7Sjeremylt CeedInt numsub; 679250756a7Sjeremylt ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 680250756a7Sjeremylt CeedOperator *suboperators; 681250756a7Sjeremylt ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 682250756a7Sjeremylt 683250756a7Sjeremylt // Zero all output vectors 684250756a7Sjeremylt if (out != CEED_VECTOR_NONE) { 685cae8b89aSjeremylt ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr); 686cae8b89aSjeremylt } 687250756a7Sjeremylt for (CeedInt i=0; i<numsub; i++) { 688250756a7Sjeremylt for (CeedInt j=0; j<suboperators[i]->qf->numoutputfields; j++) { 689250756a7Sjeremylt CeedVector vec = suboperators[i]->outputfields[j]->vec; 690250756a7Sjeremylt if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) { 691250756a7Sjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 692250756a7Sjeremylt } 693250756a7Sjeremylt } 694250756a7Sjeremylt } 695250756a7Sjeremylt // Apply 696250756a7Sjeremylt for (CeedInt i=0; i<op->numsub; i++) { 697250756a7Sjeremylt ierr = CeedOperatorApplyAdd(op->suboperators[i], in, out, request); 698cae8b89aSjeremylt CeedChk(ierr); 699cae8b89aSjeremylt } 700cae8b89aSjeremylt } 701250756a7Sjeremylt } 702250756a7Sjeremylt 703cae8b89aSjeremylt return 0; 704cae8b89aSjeremylt } 705cae8b89aSjeremylt 706cae8b89aSjeremylt /** 707cae8b89aSjeremylt @brief Apply CeedOperator to a vector and add result to output vector 708cae8b89aSjeremylt 709cae8b89aSjeremylt This computes the action of the operator on the specified (active) input, 710cae8b89aSjeremylt yielding its (active) output. All inputs and outputs must be specified using 711cae8b89aSjeremylt CeedOperatorSetField(). 712cae8b89aSjeremylt 713cae8b89aSjeremylt @param op CeedOperator to apply 714cae8b89aSjeremylt @param[in] in CeedVector containing input state or NULL if there are no 715cae8b89aSjeremylt active inputs 716cae8b89aSjeremylt @param[out] out CeedVector to sum in result of applying operator (must be 717cae8b89aSjeremylt distinct from @a in) or NULL if there are no active outputs 718cae8b89aSjeremylt @param request Address of CeedRequest for non-blocking completion, else 719cae8b89aSjeremylt CEED_REQUEST_IMMEDIATE 720cae8b89aSjeremylt 721cae8b89aSjeremylt @return An error code: 0 - success, otherwise - failure 722cae8b89aSjeremylt 723cae8b89aSjeremylt @ref Basic 724cae8b89aSjeremylt **/ 725cae8b89aSjeremylt int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out, 726cae8b89aSjeremylt CeedRequest *request) { 727cae8b89aSjeremylt int ierr; 728cae8b89aSjeremylt Ceed ceed = op->ceed; 729250756a7Sjeremylt ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 730cae8b89aSjeremylt 731250756a7Sjeremylt if (op->numelements) { 732250756a7Sjeremylt // Standard Operator 733250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 734250756a7Sjeremylt } else if (op->composite) { 735250756a7Sjeremylt // Composite Operator 736250756a7Sjeremylt if (op->ApplyAddComposite) { 737250756a7Sjeremylt ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr); 738cae8b89aSjeremylt } else { 739250756a7Sjeremylt CeedInt numsub; 740250756a7Sjeremylt ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 741250756a7Sjeremylt CeedOperator *suboperators; 742250756a7Sjeremylt ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 743250756a7Sjeremylt 744250756a7Sjeremylt for (CeedInt i=0; i<numsub; i++) { 745250756a7Sjeremylt ierr = CeedOperatorApplyAdd(suboperators[i], in, out, request); 746cae8b89aSjeremylt CeedChk(ierr); 7471d7d2407SJeremy L Thompson } 748250756a7Sjeremylt } 749250756a7Sjeremylt } 750250756a7Sjeremylt 751d7b241e6Sjeremylt return 0; 752d7b241e6Sjeremylt } 753d7b241e6Sjeremylt 754d7b241e6Sjeremylt /** 7554ce2993fSjeremylt @brief Get the Ceed associated with a CeedOperator 7564ce2993fSjeremylt 7574ce2993fSjeremylt @param op CeedOperator 7584ce2993fSjeremylt @param[out] ceed Variable to store Ceed 7594ce2993fSjeremylt 7604ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 7614ce2993fSjeremylt 76223617272Sjeremylt @ref Advanced 7634ce2993fSjeremylt **/ 7644ce2993fSjeremylt 7654ce2993fSjeremylt int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 7664ce2993fSjeremylt *ceed = op->ceed; 7674ce2993fSjeremylt return 0; 7684ce2993fSjeremylt } 7694ce2993fSjeremylt 7704ce2993fSjeremylt /** 7714ce2993fSjeremylt @brief Get the number of elements associated with a CeedOperator 7724ce2993fSjeremylt 7734ce2993fSjeremylt @param op CeedOperator 7744ce2993fSjeremylt @param[out] numelem Variable to store number of elements 7754ce2993fSjeremylt 7764ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 7774ce2993fSjeremylt 77823617272Sjeremylt @ref Advanced 7794ce2993fSjeremylt **/ 7804ce2993fSjeremylt 7814ce2993fSjeremylt int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) { 78252d6035fSJeremy L Thompson if (op->composite) 783c042f62fSJeremy L Thompson // LCOV_EXCL_START 78452d6035fSJeremy L Thompson return CeedError(op->ceed, 1, "Not defined for composite operator"); 785c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 78652d6035fSJeremy L Thompson 7874ce2993fSjeremylt *numelem = op->numelements; 7884ce2993fSjeremylt return 0; 7894ce2993fSjeremylt } 7904ce2993fSjeremylt 7914ce2993fSjeremylt /** 7924ce2993fSjeremylt @brief Get the number of quadrature points associated with a CeedOperator 7934ce2993fSjeremylt 7944ce2993fSjeremylt @param op CeedOperator 7954ce2993fSjeremylt @param[out] numqpts Variable to store vector number of quadrature points 7964ce2993fSjeremylt 7974ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 7984ce2993fSjeremylt 79923617272Sjeremylt @ref Advanced 8004ce2993fSjeremylt **/ 8014ce2993fSjeremylt 8024ce2993fSjeremylt int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) { 80352d6035fSJeremy L Thompson if (op->composite) 804c042f62fSJeremy L Thompson // LCOV_EXCL_START 80552d6035fSJeremy L Thompson return CeedError(op->ceed, 1, "Not defined for composite operator"); 806c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 80752d6035fSJeremy L Thompson 8084ce2993fSjeremylt *numqpts = op->numqpoints; 8094ce2993fSjeremylt return 0; 8104ce2993fSjeremylt } 8114ce2993fSjeremylt 8124ce2993fSjeremylt /** 8134ce2993fSjeremylt @brief Get the number of arguments associated with a CeedOperator 8144ce2993fSjeremylt 8154ce2993fSjeremylt @param op CeedOperator 8164ce2993fSjeremylt @param[out] numargs Variable to store vector number of arguments 8174ce2993fSjeremylt 8184ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 8194ce2993fSjeremylt 82023617272Sjeremylt @ref Advanced 8214ce2993fSjeremylt **/ 8224ce2993fSjeremylt 8234ce2993fSjeremylt int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) { 82452d6035fSJeremy L Thompson if (op->composite) 825c042f62fSJeremy L Thompson // LCOV_EXCL_START 82652d6035fSJeremy L Thompson return CeedError(op->ceed, 1, "Not defined for composite operators"); 827c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 828c042f62fSJeremy L Thompson 8294ce2993fSjeremylt *numargs = op->nfields; 8304ce2993fSjeremylt return 0; 8314ce2993fSjeremylt } 8324ce2993fSjeremylt 8334ce2993fSjeremylt /** 8344ce2993fSjeremylt @brief Get the setup status of a CeedOperator 8354ce2993fSjeremylt 8364ce2993fSjeremylt @param op CeedOperator 837288c0443SJeremy L Thompson @param[out] setupdone Variable to store setup status 8384ce2993fSjeremylt 8394ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 8404ce2993fSjeremylt 84123617272Sjeremylt @ref Advanced 8424ce2993fSjeremylt **/ 8434ce2993fSjeremylt 8444ce2993fSjeremylt int CeedOperatorGetSetupStatus(CeedOperator op, bool *setupdone) { 8454ce2993fSjeremylt *setupdone = op->setupdone; 8464ce2993fSjeremylt return 0; 8474ce2993fSjeremylt } 8484ce2993fSjeremylt 8494ce2993fSjeremylt /** 8504ce2993fSjeremylt @brief Get the QFunction associated with a CeedOperator 8514ce2993fSjeremylt 8524ce2993fSjeremylt @param op CeedOperator 8538c91a0c9SJeremy L Thompson @param[out] qf Variable to store QFunction 8544ce2993fSjeremylt 8554ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 8564ce2993fSjeremylt 85723617272Sjeremylt @ref Advanced 8584ce2993fSjeremylt **/ 8594ce2993fSjeremylt 8604ce2993fSjeremylt int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 86152d6035fSJeremy L Thompson if (op->composite) 862c042f62fSJeremy L Thompson // LCOV_EXCL_START 86352d6035fSJeremy L Thompson return CeedError(op->ceed, 1, "Not defined for composite operator"); 864c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 86552d6035fSJeremy L Thompson 8664ce2993fSjeremylt *qf = op->qf; 8674ce2993fSjeremylt return 0; 8684ce2993fSjeremylt } 8694ce2993fSjeremylt 8704ce2993fSjeremylt /** 87152d6035fSJeremy L Thompson @brief Get the number of suboperators associated with a CeedOperator 87252d6035fSJeremy L Thompson 87352d6035fSJeremy L Thompson @param op CeedOperator 87452d6035fSJeremy L Thompson @param[out] numsub Variable to store number of suboperators 87552d6035fSJeremy L Thompson 87652d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 87752d6035fSJeremy L Thompson 87852d6035fSJeremy L Thompson @ref Advanced 87952d6035fSJeremy L Thompson **/ 88052d6035fSJeremy L Thompson 88152d6035fSJeremy L Thompson int CeedOperatorGetNumSub(CeedOperator op, CeedInt *numsub) { 882c042f62fSJeremy L Thompson if (!op->composite) 883c042f62fSJeremy L Thompson // LCOV_EXCL_START 884c042f62fSJeremy L Thompson return CeedError(op->ceed, 1, "Not a composite operator"); 885c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 88652d6035fSJeremy L Thompson 88752d6035fSJeremy L Thompson *numsub = op->numsub; 88852d6035fSJeremy L Thompson return 0; 88952d6035fSJeremy L Thompson } 89052d6035fSJeremy L Thompson 89152d6035fSJeremy L Thompson /** 89252d6035fSJeremy L Thompson @brief Get the list of suboperators associated with a CeedOperator 89352d6035fSJeremy L Thompson 89452d6035fSJeremy L Thompson @param op CeedOperator 89552d6035fSJeremy L Thompson @param[out] suboperators Variable to store list of suboperators 89652d6035fSJeremy L Thompson 89752d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 89852d6035fSJeremy L Thompson 89952d6035fSJeremy L Thompson @ref Advanced 90052d6035fSJeremy L Thompson **/ 90152d6035fSJeremy L Thompson 90252d6035fSJeremy L Thompson int CeedOperatorGetSubList(CeedOperator op, CeedOperator **suboperators) { 903c042f62fSJeremy L Thompson if (!op->composite) 904c042f62fSJeremy L Thompson // LCOV_EXCL_START 905c042f62fSJeremy L Thompson return CeedError(op->ceed, 1, "Not a composite operator"); 906c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 90752d6035fSJeremy L Thompson 90852d6035fSJeremy L Thompson *suboperators = op->suboperators; 90952d6035fSJeremy L Thompson return 0; 91052d6035fSJeremy L Thompson } 91152d6035fSJeremy L Thompson 91252d6035fSJeremy L Thompson /** 913fe2413ffSjeremylt @brief Set the backend data of a CeedOperator 914fe2413ffSjeremylt 915fe2413ffSjeremylt @param[out] op CeedOperator 916fe2413ffSjeremylt @param data Data to set 917fe2413ffSjeremylt 918fe2413ffSjeremylt @return An error code: 0 - success, otherwise - failure 919fe2413ffSjeremylt 920fe2413ffSjeremylt @ref Advanced 921fe2413ffSjeremylt **/ 922fe2413ffSjeremylt 923fe2413ffSjeremylt int CeedOperatorSetData(CeedOperator op, void **data) { 924fe2413ffSjeremylt op->data = *data; 925fe2413ffSjeremylt return 0; 926fe2413ffSjeremylt } 927fe2413ffSjeremylt 928fe2413ffSjeremylt /** 9294ce2993fSjeremylt @brief Get the backend data of a CeedOperator 9304ce2993fSjeremylt 9314ce2993fSjeremylt @param op CeedOperator 9324ce2993fSjeremylt @param[out] data Variable to store data 9334ce2993fSjeremylt 9344ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 9354ce2993fSjeremylt 93623617272Sjeremylt @ref Advanced 9374ce2993fSjeremylt **/ 9384ce2993fSjeremylt 9394ce2993fSjeremylt int CeedOperatorGetData(CeedOperator op, void **data) { 9404ce2993fSjeremylt *data = op->data; 9414ce2993fSjeremylt return 0; 9424ce2993fSjeremylt } 9434ce2993fSjeremylt 9444ce2993fSjeremylt /** 9454ce2993fSjeremylt @brief Set the setup flag of a CeedOperator to True 9464ce2993fSjeremylt 9474ce2993fSjeremylt @param op CeedOperator 9484ce2993fSjeremylt 9494ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 9504ce2993fSjeremylt 95123617272Sjeremylt @ref Advanced 9524ce2993fSjeremylt **/ 9534ce2993fSjeremylt 9544ce2993fSjeremylt int CeedOperatorSetSetupDone(CeedOperator op) { 9554ce2993fSjeremylt op->setupdone = 1; 9564ce2993fSjeremylt return 0; 9574ce2993fSjeremylt } 9584ce2993fSjeremylt 9594ce2993fSjeremylt /** 9602ebaca42Sjeremylt @brief View a field of a CeedOperator 9612ebaca42Sjeremylt 9622ebaca42Sjeremylt @param[in] field Operator field to view 9632ebaca42Sjeremylt @param[in] fieldnumber Number of field being viewed 9642ebaca42Sjeremylt @param[in] stream Stream to view to, e.g., stdout 9652ebaca42Sjeremylt 9662ebaca42Sjeremylt @return An error code: 0 - success, otherwise - failure 9672ebaca42Sjeremylt 9682ebaca42Sjeremylt @ref Utility 9692ebaca42Sjeremylt **/ 9702ebaca42Sjeremylt static int CeedOperatorFieldView(CeedOperatorField field, 9712ebaca42Sjeremylt CeedQFunctionField qffield, 9722da88da5Sjeremylt CeedInt fieldnumber, bool sub, bool in, 9732da88da5Sjeremylt FILE *stream) { 9742ebaca42Sjeremylt const char *pre = sub ? " " : ""; 9752da88da5Sjeremylt const char *inout = in ? "Input" : "Output"; 9762ebaca42Sjeremylt 9772da88da5Sjeremylt fprintf(stream, "%s %s Field [%d]:\n" 9782da88da5Sjeremylt "%s Name: \"%s\"\n" 9792da88da5Sjeremylt "%s Lmode: \"%s\"\n", 9802da88da5Sjeremylt pre, inout, fieldnumber, pre, qffield->fieldname, 9812ebaca42Sjeremylt pre, CeedTransposeModes[field->lmode]); 9822ebaca42Sjeremylt 9832ebaca42Sjeremylt if (field->basis == CEED_BASIS_COLLOCATED) 9842ebaca42Sjeremylt fprintf(stream, "%s Collocated basis\n", pre); 9852ebaca42Sjeremylt 9862ebaca42Sjeremylt if (field->vec == CEED_VECTOR_ACTIVE) 9872ebaca42Sjeremylt fprintf(stream, "%s Active vector\n", pre); 9882ebaca42Sjeremylt else if (field->vec == CEED_VECTOR_NONE) 9892ebaca42Sjeremylt fprintf(stream, "%s No vector\n", pre); 9902ebaca42Sjeremylt 9912ebaca42Sjeremylt return 0; 9922ebaca42Sjeremylt } 9932ebaca42Sjeremylt 9942ebaca42Sjeremylt /** 9952ebaca42Sjeremylt @brief View a single CeedOperator 9962ebaca42Sjeremylt 9972ebaca42Sjeremylt @param[in] op CeedOperator to view 9982ebaca42Sjeremylt @param[in] stream Stream to write; typically stdout/stderr or a file 9992ebaca42Sjeremylt 10002ebaca42Sjeremylt @return Error code: 0 - success, otherwise - failure 10012ebaca42Sjeremylt 10022ebaca42Sjeremylt @ref Utility 10032ebaca42Sjeremylt **/ 10042ebaca42Sjeremylt int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) { 10052ebaca42Sjeremylt int ierr; 10062ebaca42Sjeremylt const char *pre = sub ? " " : ""; 10072ebaca42Sjeremylt 10082ebaca42Sjeremylt CeedInt totalfields; 10092ebaca42Sjeremylt ierr = CeedOperatorGetNumArgs(op, &totalfields); CeedChk(ierr); 10102da88da5Sjeremylt 10112ebaca42Sjeremylt fprintf(stream, "%s %d Field%s\n", pre, totalfields, totalfields>1 ? "s" : ""); 10122ebaca42Sjeremylt 10132da88da5Sjeremylt fprintf(stream, "%s %d Input Field%s:\n", pre, op->qf->numinputfields, 10142ebaca42Sjeremylt op->qf->numinputfields>1 ? "s" : ""); 10152ebaca42Sjeremylt for (CeedInt i=0; i<op->qf->numinputfields; i++) { 10162ebaca42Sjeremylt ierr = CeedOperatorFieldView(op->inputfields[i], op->qf->inputfields[i], 10172da88da5Sjeremylt i, sub, 1, stream); CeedChk(ierr); 10182ebaca42Sjeremylt } 10192ebaca42Sjeremylt 10202da88da5Sjeremylt fprintf(stream, "%s %d Output Field%s:\n", pre, op->qf->numoutputfields, 10212ebaca42Sjeremylt op->qf->numoutputfields>1 ? "s" : ""); 10222ebaca42Sjeremylt for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 10232ebaca42Sjeremylt ierr = CeedOperatorFieldView(op->outputfields[i], op->qf->inputfields[i], 10242da88da5Sjeremylt i, sub, 0, stream); CeedChk(ierr); 10252ebaca42Sjeremylt } 10262ebaca42Sjeremylt 10272ebaca42Sjeremylt return 0; 10282ebaca42Sjeremylt } 10292ebaca42Sjeremylt 10302ebaca42Sjeremylt /** 10312ebaca42Sjeremylt @brief View a CeedOperator 10322ebaca42Sjeremylt 10332ebaca42Sjeremylt @param[in] op CeedOperator to view 10342ebaca42Sjeremylt @param[in] stream Stream to write; typically stdout/stderr or a file 10352ebaca42Sjeremylt 10362ebaca42Sjeremylt @return Error code: 0 - success, otherwise - failure 10372ebaca42Sjeremylt 10382ebaca42Sjeremylt @ref Utility 10392ebaca42Sjeremylt **/ 10402ebaca42Sjeremylt int CeedOperatorView(CeedOperator op, FILE *stream) { 10412ebaca42Sjeremylt int ierr; 10422ebaca42Sjeremylt 10432ebaca42Sjeremylt if (op->composite) { 10442ebaca42Sjeremylt fprintf(stream, "Composite CeedOperator\n"); 10452ebaca42Sjeremylt 10462ebaca42Sjeremylt for (CeedInt i=0; i<op->numsub; i++) { 10472da88da5Sjeremylt fprintf(stream, " SubOperator [%d]:\n", i); 10482ebaca42Sjeremylt ierr = CeedOperatorSingleView(op->suboperators[i], 1, stream); 10492ebaca42Sjeremylt CeedChk(ierr); 10502ebaca42Sjeremylt } 10512ebaca42Sjeremylt } else { 10522ebaca42Sjeremylt fprintf(stream, "CeedOperator\n"); 10532ebaca42Sjeremylt ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr); 10542ebaca42Sjeremylt } 10552ebaca42Sjeremylt 10562ebaca42Sjeremylt return 0; 10572ebaca42Sjeremylt } 10582ebaca42Sjeremylt 10592ebaca42Sjeremylt /** 1060d1bcdac9Sjeremylt @brief Get the CeedOperatorFields of a CeedOperator 1061d1bcdac9Sjeremylt 1062d1bcdac9Sjeremylt @param op CeedOperator 1063d1bcdac9Sjeremylt @param[out] inputfields Variable to store inputfields 1064d1bcdac9Sjeremylt @param[out] outputfields Variable to store outputfields 1065d1bcdac9Sjeremylt 1066d1bcdac9Sjeremylt @return An error code: 0 - success, otherwise - failure 1067d1bcdac9Sjeremylt 1068d1bcdac9Sjeremylt @ref Advanced 1069d1bcdac9Sjeremylt **/ 1070d1bcdac9Sjeremylt 1071692c2638Sjeremylt int CeedOperatorGetFields(CeedOperator op, CeedOperatorField **inputfields, 1072d1bcdac9Sjeremylt CeedOperatorField **outputfields) { 107352d6035fSJeremy L Thompson if (op->composite) 1074c042f62fSJeremy L Thompson // LCOV_EXCL_START 107552d6035fSJeremy L Thompson return CeedError(op->ceed, 1, "Not defined for composite operator"); 1076c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 107752d6035fSJeremy L Thompson 1078d1bcdac9Sjeremylt if (inputfields) *inputfields = op->inputfields; 1079d1bcdac9Sjeremylt if (outputfields) *outputfields = op->outputfields; 1080d1bcdac9Sjeremylt return 0; 1081d1bcdac9Sjeremylt } 1082d1bcdac9Sjeremylt 1083d1bcdac9Sjeremylt /** 10844dccadb6Sjeremylt @brief Get the L vector CeedTransposeMode of a CeedOperatorField 10854dccadb6Sjeremylt 10864dccadb6Sjeremylt @param opfield CeedOperatorField 10874dccadb6Sjeremylt @param[out] lmode Variable to store CeedTransposeMode 10884dccadb6Sjeremylt 10894dccadb6Sjeremylt @return An error code: 0 - success, otherwise - failure 10904dccadb6Sjeremylt 10914dccadb6Sjeremylt @ref Advanced 10924dccadb6Sjeremylt **/ 10934dccadb6Sjeremylt 10944dccadb6Sjeremylt int CeedOperatorFieldGetLMode(CeedOperatorField opfield, 10954dccadb6Sjeremylt CeedTransposeMode *lmode) { 1096fe2413ffSjeremylt *lmode = opfield->lmode; 10974dccadb6Sjeremylt return 0; 10982b8e417aSjeremylt } 10992b8e417aSjeremylt 11002b8e417aSjeremylt /** 1101d1bcdac9Sjeremylt @brief Get the CeedElemRestriction of a CeedOperatorField 1102d1bcdac9Sjeremylt 1103d1bcdac9Sjeremylt @param opfield CeedOperatorField 1104d1bcdac9Sjeremylt @param[out] rstr Variable to store CeedElemRestriction 1105d1bcdac9Sjeremylt 1106d1bcdac9Sjeremylt @return An error code: 0 - success, otherwise - failure 1107d1bcdac9Sjeremylt 1108d1bcdac9Sjeremylt @ref Advanced 1109d1bcdac9Sjeremylt **/ 1110d1bcdac9Sjeremylt 1111d1bcdac9Sjeremylt int CeedOperatorFieldGetElemRestriction(CeedOperatorField opfield, 1112d1bcdac9Sjeremylt CeedElemRestriction *rstr) { 1113fe2413ffSjeremylt *rstr = opfield->Erestrict; 1114d1bcdac9Sjeremylt return 0; 1115d1bcdac9Sjeremylt } 1116d1bcdac9Sjeremylt 1117d1bcdac9Sjeremylt /** 1118d1bcdac9Sjeremylt @brief Get the CeedBasis of a CeedOperatorField 1119d1bcdac9Sjeremylt 1120d1bcdac9Sjeremylt @param opfield CeedOperatorField 1121d1bcdac9Sjeremylt @param[out] basis Variable to store CeedBasis 1122d1bcdac9Sjeremylt 1123d1bcdac9Sjeremylt @return An error code: 0 - success, otherwise - failure 1124d1bcdac9Sjeremylt 1125d1bcdac9Sjeremylt @ref Advanced 1126d1bcdac9Sjeremylt **/ 1127d1bcdac9Sjeremylt 1128692c2638Sjeremylt int CeedOperatorFieldGetBasis(CeedOperatorField opfield, CeedBasis *basis) { 1129fe2413ffSjeremylt *basis = opfield->basis; 1130d1bcdac9Sjeremylt return 0; 1131d1bcdac9Sjeremylt } 1132d1bcdac9Sjeremylt 1133d1bcdac9Sjeremylt /** 1134d1bcdac9Sjeremylt @brief Get the CeedVector of a CeedOperatorField 1135d1bcdac9Sjeremylt 1136d1bcdac9Sjeremylt @param opfield CeedOperatorField 1137d1bcdac9Sjeremylt @param[out] vec Variable to store CeedVector 1138d1bcdac9Sjeremylt 1139d1bcdac9Sjeremylt @return An error code: 0 - success, otherwise - failure 1140d1bcdac9Sjeremylt 1141d1bcdac9Sjeremylt @ref Advanced 1142d1bcdac9Sjeremylt **/ 1143d1bcdac9Sjeremylt 1144692c2638Sjeremylt int CeedOperatorFieldGetVector(CeedOperatorField opfield, CeedVector *vec) { 1145fe2413ffSjeremylt *vec = opfield->vec; 1146d1bcdac9Sjeremylt return 0; 1147d1bcdac9Sjeremylt } 1148d1bcdac9Sjeremylt 1149d1bcdac9Sjeremylt /** 1150b11c1e72Sjeremylt @brief Destroy a CeedOperator 1151d7b241e6Sjeremylt 1152d7b241e6Sjeremylt @param op CeedOperator to destroy 1153b11c1e72Sjeremylt 1154b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1155dfdf5a53Sjeremylt 1156dfdf5a53Sjeremylt @ref Basic 1157b11c1e72Sjeremylt **/ 1158d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) { 1159d7b241e6Sjeremylt int ierr; 1160d7b241e6Sjeremylt 1161d7b241e6Sjeremylt if (!*op || --(*op)->refcount > 0) return 0; 1162d7b241e6Sjeremylt if ((*op)->Destroy) { 1163d7b241e6Sjeremylt ierr = (*op)->Destroy(*op); CeedChk(ierr); 1164d7b241e6Sjeremylt } 1165fe2413ffSjeremylt ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 1166fe2413ffSjeremylt // Free fields 11671d102b48SJeremy L Thompson for (int i=0; i<(*op)->nfields; i++) 116852d6035fSJeremy L Thompson if ((*op)->inputfields[i]) { 116971352a93Sjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->inputfields[i]->Erestrict); 117071352a93Sjeremylt CeedChk(ierr); 117171352a93Sjeremylt if ((*op)->inputfields[i]->basis != CEED_BASIS_COLLOCATED) { 117271352a93Sjeremylt ierr = CeedBasisDestroy(&(*op)->inputfields[i]->basis); CeedChk(ierr); 117371352a93Sjeremylt } 117471352a93Sjeremylt if ((*op)->inputfields[i]->vec != CEED_VECTOR_ACTIVE && 117571352a93Sjeremylt (*op)->inputfields[i]->vec != CEED_VECTOR_NONE ) { 117671352a93Sjeremylt ierr = CeedVectorDestroy(&(*op)->inputfields[i]->vec); CeedChk(ierr); 117771352a93Sjeremylt } 1178fe2413ffSjeremylt ierr = CeedFree(&(*op)->inputfields[i]); CeedChk(ierr); 1179fe2413ffSjeremylt } 11801d102b48SJeremy L Thompson for (int i=0; i<(*op)->nfields; i++) 1181d0eb30a5Sjeremylt if ((*op)->outputfields[i]) { 118271352a93Sjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->outputfields[i]->Erestrict); 118371352a93Sjeremylt CeedChk(ierr); 118471352a93Sjeremylt if ((*op)->outputfields[i]->basis != CEED_BASIS_COLLOCATED) { 118571352a93Sjeremylt ierr = CeedBasisDestroy(&(*op)->outputfields[i]->basis); CeedChk(ierr); 118671352a93Sjeremylt } 118771352a93Sjeremylt if ((*op)->outputfields[i]->vec != CEED_VECTOR_ACTIVE && 118871352a93Sjeremylt (*op)->outputfields[i]->vec != CEED_VECTOR_NONE ) { 118971352a93Sjeremylt ierr = CeedVectorDestroy(&(*op)->outputfields[i]->vec); CeedChk(ierr); 119071352a93Sjeremylt } 1191fe2413ffSjeremylt ierr = CeedFree(&(*op)->outputfields[i]); CeedChk(ierr); 1192fe2413ffSjeremylt } 119352d6035fSJeremy L Thompson // Destroy suboperators 11941d102b48SJeremy L Thompson for (int i=0; i<(*op)->numsub; i++) 119552d6035fSJeremy L Thompson if ((*op)->suboperators[i]) { 119652d6035fSJeremy L Thompson ierr = CeedOperatorDestroy(&(*op)->suboperators[i]); CeedChk(ierr); 119752d6035fSJeremy L Thompson } 1198d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 1199d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 1200d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 1201fe2413ffSjeremylt 12025107b09fSJeremy L Thompson // Destroy fallback 12035107b09fSJeremy L Thompson if ((*op)->opfallback) { 12045107b09fSJeremy L Thompson ierr = (*op)->qffallback->Destroy((*op)->qffallback); CeedChk(ierr); 12055107b09fSJeremy L Thompson ierr = CeedFree(&(*op)->qffallback); CeedChk(ierr); 12065107b09fSJeremy L Thompson ierr = (*op)->opfallback->Destroy((*op)->opfallback); CeedChk(ierr); 12075107b09fSJeremy L Thompson ierr = CeedFree(&(*op)->opfallback); CeedChk(ierr); 12085107b09fSJeremy L Thompson } 12095107b09fSJeremy L Thompson 1210fe2413ffSjeremylt ierr = CeedFree(&(*op)->inputfields); CeedChk(ierr); 1211fe2413ffSjeremylt ierr = CeedFree(&(*op)->outputfields); CeedChk(ierr); 121252d6035fSJeremy L Thompson ierr = CeedFree(&(*op)->suboperators); CeedChk(ierr); 1213d7b241e6Sjeremylt ierr = CeedFree(op); CeedChk(ierr); 1214d7b241e6Sjeremylt return 0; 1215d7b241e6Sjeremylt } 1216d7b241e6Sjeremylt 1217d7b241e6Sjeremylt /// @} 1218