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> 20*3bd813ffSjeremylt #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 3865107b09fSJeremy L Thompson if (op->AssembleLinearQFunction) { 3871d102b48SJeremy L Thompson ierr = op->AssembleLinearQFunction(op, assembled, rstr, request); 3881d102b48SJeremy L Thompson CeedChk(ierr); 3895107b09fSJeremy L Thompson } else { 3905107b09fSJeremy L Thompson // Fallback to reference Ceed 3915107b09fSJeremy L Thompson if (!op->opfallback) { 3925107b09fSJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 3935107b09fSJeremy L Thompson } 3945107b09fSJeremy L Thompson // Assemble 3955107b09fSJeremy L Thompson ierr = op->opfallback->AssembleLinearQFunction(op->opfallback, assembled, 3965107b09fSJeremy L Thompson rstr, request); CeedChk(ierr); 3975107b09fSJeremy L Thompson } 398250756a7Sjeremylt 3991d102b48SJeremy L Thompson return 0; 4001d102b48SJeremy L Thompson } 4011d102b48SJeremy L Thompson 4021d102b48SJeremy L Thompson /** 403b7ec98d8SJeremy L Thompson @brief Assemble the diagonal of a square linear Operator 404b7ec98d8SJeremy L Thompson 405b7ec98d8SJeremy L Thompson This returns a CeedVector containing the diagonal of a linear CeedOperator. 406b7ec98d8SJeremy L Thompson 407b7ec98d8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 408b7ec98d8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator diagonal 409b7ec98d8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 410b7ec98d8SJeremy L Thompson CEED_REQUEST_IMMEDIATE 411b7ec98d8SJeremy L Thompson 412b7ec98d8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 413b7ec98d8SJeremy L Thompson 414b7ec98d8SJeremy L Thompson @ref Basic 415b7ec98d8SJeremy L Thompson **/ 4167f823360Sjeremylt int CeedOperatorAssembleLinearDiagonal(CeedOperator op, CeedVector *assembled, 4177f823360Sjeremylt CeedRequest *request) { 418b7ec98d8SJeremy L Thompson int ierr; 419b7ec98d8SJeremy L Thompson Ceed ceed = op->ceed; 420250756a7Sjeremylt ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 421b7ec98d8SJeremy L Thompson 422b7ec98d8SJeremy L Thompson // Use backend version, if available 423b7ec98d8SJeremy L Thompson if (op->AssembleLinearDiagonal) { 424b7ec98d8SJeremy L Thompson ierr = op->AssembleLinearDiagonal(op, assembled, request); CeedChk(ierr); 425b7ec98d8SJeremy L Thompson return 0; 426b7ec98d8SJeremy L Thompson } 427b7ec98d8SJeremy L Thompson 428b7ec98d8SJeremy L Thompson // Assemble QFunction 429250756a7Sjeremylt CeedQFunction qf = op->qf; 430b7ec98d8SJeremy L Thompson CeedVector assembledqf; 431b7ec98d8SJeremy L Thompson CeedElemRestriction rstr; 432b7ec98d8SJeremy L Thompson ierr = CeedOperatorAssembleLinearQFunction(op, &assembledqf, &rstr, request); 433b7ec98d8SJeremy L Thompson CeedChk(ierr); 434b7ec98d8SJeremy L Thompson ierr = CeedElemRestrictionDestroy(&rstr); CeedChk(ierr); 435b7ec98d8SJeremy L Thompson 436b7ec98d8SJeremy L Thompson // Determine active input basis 437112e3f70Sjeremylt CeedInt numemodein = 0, ncomp, dim = 1; 438b7ec98d8SJeremy L Thompson CeedEvalMode *emodein = NULL; 439112e3f70Sjeremylt CeedBasis basisin = NULL; 440112e3f70Sjeremylt CeedElemRestriction rstrin = NULL; 441b7ec98d8SJeremy L Thompson for (CeedInt i=0; i<qf->numinputfields; i++) 442b7ec98d8SJeremy L Thompson if (op->inputfields[i]->vec == CEED_VECTOR_ACTIVE) { 443b7ec98d8SJeremy L Thompson ierr = CeedOperatorFieldGetBasis(op->inputfields[i], &basisin); 444b7ec98d8SJeremy L Thompson CeedChk(ierr); 445b7ec98d8SJeremy L Thompson ierr = CeedBasisGetNumComponents(basisin, &ncomp); CeedChk(ierr); 446b7ec98d8SJeremy L Thompson ierr = CeedBasisGetDimension(basisin, &dim); CeedChk(ierr); 447b7ec98d8SJeremy L Thompson ierr = CeedOperatorFieldGetElemRestriction(op->inputfields[i], &rstrin); 448b7ec98d8SJeremy L Thompson CeedChk(ierr); 449b7ec98d8SJeremy L Thompson CeedEvalMode emode; 450b7ec98d8SJeremy L Thompson ierr = CeedQFunctionFieldGetEvalMode(qf->inputfields[i], &emode); 451b7ec98d8SJeremy L Thompson CeedChk(ierr); 452b7ec98d8SJeremy L Thompson switch (emode) { 453b7ec98d8SJeremy L Thompson case CEED_EVAL_NONE: 454b7ec98d8SJeremy L Thompson case CEED_EVAL_INTERP: 455b7ec98d8SJeremy L Thompson ierr = CeedRealloc(numemodein + 1, &emodein); CeedChk(ierr); 456b7ec98d8SJeremy L Thompson emodein[numemodein] = emode; 457b7ec98d8SJeremy L Thompson numemodein += 1; 458b7ec98d8SJeremy L Thompson break; 459b7ec98d8SJeremy L Thompson case CEED_EVAL_GRAD: 460b7ec98d8SJeremy L Thompson ierr = CeedRealloc(numemodein + dim, &emodein); CeedChk(ierr); 461b7ec98d8SJeremy L Thompson for (CeedInt d=0; d<dim; d++) 462b7ec98d8SJeremy L Thompson emodein[numemodein+d] = emode; 463b7ec98d8SJeremy L Thompson numemodein += dim; 464b7ec98d8SJeremy L Thompson break; 465b7ec98d8SJeremy L Thompson case CEED_EVAL_WEIGHT: 466b7ec98d8SJeremy L Thompson case CEED_EVAL_DIV: 467b7ec98d8SJeremy L Thompson case CEED_EVAL_CURL: 468b7ec98d8SJeremy L Thompson break; // Caught by QF Assembly 469b7ec98d8SJeremy L Thompson } 470b7ec98d8SJeremy L Thompson } 471b7ec98d8SJeremy L Thompson 472b7ec98d8SJeremy L Thompson // Determine active output basis 473b7ec98d8SJeremy L Thompson CeedInt numemodeout = 0; 474b7ec98d8SJeremy L Thompson CeedEvalMode *emodeout = NULL; 475112e3f70Sjeremylt CeedBasis basisout = NULL; 476112e3f70Sjeremylt CeedElemRestriction rstrout = NULL; 477112e3f70Sjeremylt CeedTransposeMode lmodeout = CEED_NOTRANSPOSE; 478b7ec98d8SJeremy L Thompson for (CeedInt i=0; i<qf->numoutputfields; i++) 479b7ec98d8SJeremy L Thompson if (op->outputfields[i]->vec == CEED_VECTOR_ACTIVE) { 480b7ec98d8SJeremy L Thompson ierr = CeedOperatorFieldGetBasis(op->outputfields[i], &basisout); 481b7ec98d8SJeremy L Thompson CeedChk(ierr); 482b7ec98d8SJeremy L Thompson ierr = CeedOperatorFieldGetElemRestriction(op->outputfields[i], &rstrout); 483b7ec98d8SJeremy L Thompson CeedChk(ierr); 484b7ec98d8SJeremy L Thompson ierr = CeedOperatorFieldGetLMode(op->outputfields[i], &lmodeout); 485b7ec98d8SJeremy L Thompson CeedChk(ierr); 486b7ec98d8SJeremy L Thompson CeedEvalMode emode; 487b7ec98d8SJeremy L Thompson ierr = CeedQFunctionFieldGetEvalMode(qf->outputfields[i], &emode); 488b7ec98d8SJeremy L Thompson CeedChk(ierr); 489b7ec98d8SJeremy L Thompson switch (emode) { 490b7ec98d8SJeremy L Thompson case CEED_EVAL_NONE: 491b7ec98d8SJeremy L Thompson case CEED_EVAL_INTERP: 492b7ec98d8SJeremy L Thompson ierr = CeedRealloc(numemodeout + 1, &emodeout); CeedChk(ierr); 493b7ec98d8SJeremy L Thompson emodeout[numemodeout] = emode; 494b7ec98d8SJeremy L Thompson numemodeout += 1; 495b7ec98d8SJeremy L Thompson break; 496b7ec98d8SJeremy L Thompson case CEED_EVAL_GRAD: 497b7ec98d8SJeremy L Thompson ierr = CeedRealloc(numemodeout + dim, &emodeout); CeedChk(ierr); 498b7ec98d8SJeremy L Thompson for (CeedInt d=0; d<dim; d++) 499b7ec98d8SJeremy L Thompson emodeout[numemodeout+d] = emode; 500b7ec98d8SJeremy L Thompson numemodeout += dim; 501b7ec98d8SJeremy L Thompson break; 502b7ec98d8SJeremy L Thompson case CEED_EVAL_WEIGHT: 503b7ec98d8SJeremy L Thompson case CEED_EVAL_DIV: 504b7ec98d8SJeremy L Thompson case CEED_EVAL_CURL: 505b7ec98d8SJeremy L Thompson break; // Caught by QF Assembly 506b7ec98d8SJeremy L Thompson } 507b7ec98d8SJeremy L Thompson } 508b7ec98d8SJeremy L Thompson 509b7ec98d8SJeremy L Thompson // Create diagonal vector 510b7ec98d8SJeremy L Thompson CeedVector elemdiag; 511b7ec98d8SJeremy L Thompson ierr = CeedElemRestrictionCreateVector(rstrin, assembled, &elemdiag); 512b7ec98d8SJeremy L Thompson CeedChk(ierr); 513b7ec98d8SJeremy L Thompson 514b7ec98d8SJeremy L Thompson // Assemble element operator diagonals 515b7ec98d8SJeremy L Thompson CeedScalar *elemdiagarray, *assembledqfarray; 516b7ec98d8SJeremy L Thompson ierr = CeedVectorSetValue(elemdiag, 0.0); CeedChk(ierr); 517b7ec98d8SJeremy L Thompson ierr = CeedVectorGetArray(elemdiag, CEED_MEM_HOST, &elemdiagarray); 518b7ec98d8SJeremy L Thompson CeedChk(ierr); 519b7ec98d8SJeremy L Thompson ierr = CeedVectorGetArray(assembledqf, CEED_MEM_HOST, &assembledqfarray); 520b7ec98d8SJeremy L Thompson CeedChk(ierr); 521b7ec98d8SJeremy L Thompson CeedInt nelem, nnodes, nqpts; 522b7ec98d8SJeremy L Thompson ierr = CeedElemRestrictionGetNumElements(rstrin, &nelem); CeedChk(ierr); 523b7ec98d8SJeremy L Thompson ierr = CeedBasisGetNumNodes(basisin, &nnodes); CeedChk(ierr); 524b7ec98d8SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisin, &nqpts); CeedChk(ierr); 525b7ec98d8SJeremy L Thompson // Compute the diagonal of B^T D B 526b7ec98d8SJeremy L Thompson // Each node, qpt pair 527b7ec98d8SJeremy L Thompson for (CeedInt n=0; n<nnodes; n++) 528b7ec98d8SJeremy L Thompson for (CeedInt q=0; q<nqpts; q++) { 529b7ec98d8SJeremy L Thompson CeedInt dout = -1; 530b7ec98d8SJeremy L Thompson // Each basis eval mode pair 531b7ec98d8SJeremy L Thompson for (CeedInt eout=0; eout<numemodeout; eout++) { 532b7ec98d8SJeremy L Thompson CeedScalar bt = 1.0; 533b7ec98d8SJeremy L Thompson if (emodeout[eout] == CEED_EVAL_GRAD) 534b7ec98d8SJeremy L Thompson dout += 1; 535b7ec98d8SJeremy L Thompson ierr = CeedBasisGetValue(basisout, emodeout[eout], q, n, dout, &bt); 536b7ec98d8SJeremy L Thompson CeedChk(ierr); 537b7ec98d8SJeremy L Thompson CeedInt din = -1; 538b7ec98d8SJeremy L Thompson for (CeedInt ein=0; ein<numemodein; ein++) { 539b7ec98d8SJeremy L Thompson CeedScalar b = 0.0; 540b7ec98d8SJeremy L Thompson if (emodein[ein] == CEED_EVAL_GRAD) 541b7ec98d8SJeremy L Thompson din += 1; 542b7ec98d8SJeremy L Thompson ierr = CeedBasisGetValue(basisin, emodein[ein], q, n, din, &b); 543b7ec98d8SJeremy L Thompson CeedChk(ierr); 544b7ec98d8SJeremy L Thompson // Each element and component 545b7ec98d8SJeremy L Thompson for (CeedInt e=0; e<nelem; e++) 546b7ec98d8SJeremy L Thompson for (CeedInt cout=0; cout<ncomp; cout++) { 547b7ec98d8SJeremy L Thompson CeedScalar db = 0.0; 548b7ec98d8SJeremy L Thompson for (CeedInt cin=0; cin<ncomp; cin++) 549b7ec98d8SJeremy L Thompson db += assembledqfarray[((((e*numemodein+ein)*ncomp+cin)* 550b7ec98d8SJeremy L Thompson numemodeout+eout)*ncomp+cout)*nqpts+q]*b; 551b7ec98d8SJeremy L Thompson elemdiagarray[(e*ncomp+cout)*nnodes+n] += bt * db; 552b7ec98d8SJeremy L Thompson } 553b7ec98d8SJeremy L Thompson } 554b7ec98d8SJeremy L Thompson } 555b7ec98d8SJeremy L Thompson } 556b7ec98d8SJeremy L Thompson 557b7ec98d8SJeremy L Thompson ierr = CeedVectorRestoreArray(elemdiag, &elemdiagarray); CeedChk(ierr); 558b7ec98d8SJeremy L Thompson ierr = CeedVectorRestoreArray(assembledqf, &assembledqfarray); CeedChk(ierr); 559b7ec98d8SJeremy L Thompson 560b7ec98d8SJeremy L Thompson // Assemble local operator diagonal 561b7ec98d8SJeremy L Thompson ierr = CeedVectorSetValue(*assembled, 0.0); CeedChk(ierr); 562b7ec98d8SJeremy L Thompson ierr = CeedElemRestrictionApply(rstrout, CEED_TRANSPOSE, lmodeout, elemdiag, 563b7ec98d8SJeremy L Thompson *assembled, request); CeedChk(ierr); 564b7ec98d8SJeremy L Thompson 565b7ec98d8SJeremy L Thompson // Cleanup 566b7ec98d8SJeremy L Thompson ierr = CeedVectorDestroy(&assembledqf); CeedChk(ierr); 567b7ec98d8SJeremy L Thompson ierr = CeedVectorDestroy(&elemdiag); CeedChk(ierr); 568b7ec98d8SJeremy L Thompson ierr = CeedFree(&emodein); CeedChk(ierr); 569b7ec98d8SJeremy L Thompson ierr = CeedFree(&emodeout); CeedChk(ierr); 570b7ec98d8SJeremy L Thompson 571b7ec98d8SJeremy L Thompson return 0; 572b7ec98d8SJeremy L Thompson } 573b7ec98d8SJeremy L Thompson 574b7ec98d8SJeremy L Thompson /** 575*3bd813ffSjeremylt @brief Build a FDM based approximate inverse for each element for a 576*3bd813ffSjeremylt CeedOperator 577*3bd813ffSjeremylt 578*3bd813ffSjeremylt This returns a CeedOperator and CeedVector to apply a Fast Diagonalization 579*3bd813ffSjeremylt Method based approximate inverse. This function obtains the simultaneous 580*3bd813ffSjeremylt diagonalization for the 1D mass and Laplacian operators, 581*3bd813ffSjeremylt M = V^T V, K = V^T S V. 582*3bd813ffSjeremylt The assembled QFunction is used to modify the eigenvalues from simultaneous 583*3bd813ffSjeremylt diagonalization and obtain an approximate inverse of the form 584*3bd813ffSjeremylt V^T S^hat V. The CeedOperator must be linear and non-composite. The 585*3bd813ffSjeremylt associated CeedQFunction must therefore also be linear. 586*3bd813ffSjeremylt 587*3bd813ffSjeremylt @param op CeedOperator to create element inverses 588*3bd813ffSjeremylt @param[out] fdminv CeedOperator to apply the action of a FDM based inverse 589*3bd813ffSjeremylt for each element 590*3bd813ffSjeremylt @param[out] qdata CeedVector to hold qdata for fdminv 591*3bd813ffSjeremylt @param request Address of CeedRequest for non-blocking completion, else 592*3bd813ffSjeremylt CEED_REQUEST_IMMEDIATE 593*3bd813ffSjeremylt 594*3bd813ffSjeremylt @return An error code: 0 - success, otherwise - failure 595*3bd813ffSjeremylt 596*3bd813ffSjeremylt @ref Advanced 597*3bd813ffSjeremylt **/ 598*3bd813ffSjeremylt int CeedOperatorCreateFDMElementInverse(CeedOperator op, CeedOperator *fdminv, 599*3bd813ffSjeremylt CeedRequest *request) { 600*3bd813ffSjeremylt int ierr; 601*3bd813ffSjeremylt Ceed ceed = op->ceed; 602*3bd813ffSjeremylt 603*3bd813ffSjeremylt // Determine active input basis 604*3bd813ffSjeremylt bool interp = false, grad = false; 605*3bd813ffSjeremylt CeedBasis basis = NULL; 606*3bd813ffSjeremylt CeedElemRestriction rstr = NULL; 607*3bd813ffSjeremylt for (CeedInt i=0; i<op->qf->numinputfields; i++) 608*3bd813ffSjeremylt if (op->inputfields[i] && op->inputfields[i]->vec == CEED_VECTOR_ACTIVE) { 609*3bd813ffSjeremylt basis = op->inputfields[i]->basis; 610*3bd813ffSjeremylt interp = interp || op->qf->inputfields[i]->emode == CEED_EVAL_INTERP; 611*3bd813ffSjeremylt grad = grad || op->qf->inputfields[i]->emode == CEED_EVAL_GRAD; 612*3bd813ffSjeremylt rstr = op->inputfields[i]->Erestrict; 613*3bd813ffSjeremylt } 614*3bd813ffSjeremylt if (!basis) 615*3bd813ffSjeremylt return CeedError(ceed, 1, "No active field set"); 616*3bd813ffSjeremylt CeedInt P1d, Q1d, elemsize, nqpts, dim, ncomp = 1, nelem = 1, nnodes = 1; 617*3bd813ffSjeremylt ierr = CeedBasisGetNumNodes1D(basis, &P1d); CeedChk(ierr); 618*3bd813ffSjeremylt ierr = CeedBasisGetNumNodes(basis, &elemsize); CeedChk(ierr); 619*3bd813ffSjeremylt ierr = CeedBasisGetNumQuadraturePoints1D(basis, &Q1d); CeedChk(ierr); 620*3bd813ffSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis, &nqpts); CeedChk(ierr); 621*3bd813ffSjeremylt ierr = CeedBasisGetDimension(basis, &dim); CeedChk(ierr); 622*3bd813ffSjeremylt ierr = CeedBasisGetNumComponents(basis, &ncomp); CeedChk(ierr); 623*3bd813ffSjeremylt ierr = CeedElemRestrictionGetNumElements(rstr, &nelem); CeedChk(ierr); 624*3bd813ffSjeremylt ierr = CeedElemRestrictionGetNumNodes(rstr, &nnodes); CeedChk(ierr); 625*3bd813ffSjeremylt 626*3bd813ffSjeremylt // Build and diagonalize 1D Mass and Laplacian 627*3bd813ffSjeremylt if (!basis->tensorbasis) 628*3bd813ffSjeremylt return CeedError(ceed, 1, "FDMElementInverse only supported for tensor " 629*3bd813ffSjeremylt "bases"); 630*3bd813ffSjeremylt CeedScalar *work, *mass, *laplace, *x, *x2, *lambda; 631*3bd813ffSjeremylt ierr = CeedMalloc(Q1d*P1d, &work); CeedChk(ierr); 632*3bd813ffSjeremylt ierr = CeedMalloc(P1d*P1d, &mass); CeedChk(ierr); 633*3bd813ffSjeremylt ierr = CeedMalloc(P1d*P1d, &laplace); CeedChk(ierr); 634*3bd813ffSjeremylt ierr = CeedMalloc(P1d*P1d, &x); CeedChk(ierr); 635*3bd813ffSjeremylt ierr = CeedMalloc(P1d*P1d, &x2); CeedChk(ierr); 636*3bd813ffSjeremylt ierr = CeedMalloc(P1d, &lambda); CeedChk(ierr); 637*3bd813ffSjeremylt // -- Mass 638*3bd813ffSjeremylt for (CeedInt i=0; i<Q1d; i++) 639*3bd813ffSjeremylt for (CeedInt j=0; j<P1d; j++) 640*3bd813ffSjeremylt work[i+j*Q1d] = basis->interp1d[i*P1d+j]*basis->qweight1d[i]; 641*3bd813ffSjeremylt ierr = CeedMatrixMultiply(ceed, work, basis->interp1d, mass, P1d, P1d, Q1d); 642*3bd813ffSjeremylt CeedChk(ierr); 643*3bd813ffSjeremylt // -- Laplacian 644*3bd813ffSjeremylt for (CeedInt i=0; i<Q1d; i++) 645*3bd813ffSjeremylt for (CeedInt j=0; j<P1d; j++) 646*3bd813ffSjeremylt work[i+j*Q1d] = basis->grad1d[i*P1d+j]*basis->qweight1d[i]; 647*3bd813ffSjeremylt ierr = CeedMatrixMultiply(ceed, work, basis->grad1d, laplace, P1d, P1d, Q1d); 648*3bd813ffSjeremylt CeedChk(ierr); 649*3bd813ffSjeremylt // -- Diagonalize 650*3bd813ffSjeremylt ierr = CeedSimultaneousDiagonalization(ceed, laplace, mass, x, lambda, P1d); 651*3bd813ffSjeremylt CeedChk(ierr); 652*3bd813ffSjeremylt ierr = CeedFree(&work); CeedChk(ierr); 653*3bd813ffSjeremylt ierr = CeedFree(&mass); CeedChk(ierr); 654*3bd813ffSjeremylt ierr = CeedFree(&laplace); CeedChk(ierr); 655*3bd813ffSjeremylt for (CeedInt i=0; i<P1d; i++) 656*3bd813ffSjeremylt for (CeedInt j=0; j<P1d; j++) 657*3bd813ffSjeremylt x2[i+j*P1d] = x[j+i*P1d]; 658*3bd813ffSjeremylt ierr = CeedFree(&x); CeedChk(ierr); 659*3bd813ffSjeremylt 660*3bd813ffSjeremylt // Assemble QFunction 661*3bd813ffSjeremylt CeedVector assembled; 662*3bd813ffSjeremylt CeedElemRestriction rstr_qf; 663*3bd813ffSjeremylt ierr = CeedOperatorAssembleLinearQFunction(op, &assembled, &rstr_qf, 664*3bd813ffSjeremylt request); CeedChk(ierr); 665*3bd813ffSjeremylt ierr = CeedElemRestrictionDestroy(&rstr_qf); CeedChk(ierr); 666*3bd813ffSjeremylt 667*3bd813ffSjeremylt // Calculate element averages 668*3bd813ffSjeremylt CeedInt nfields = ((interp?1:0) + (grad?dim:0))*((interp?1:0) + (grad?dim:0)); 669*3bd813ffSjeremylt CeedScalar *elemavg; 670*3bd813ffSjeremylt const CeedScalar *assembledarray, *qweightsarray; 671*3bd813ffSjeremylt CeedVector qweights; 672*3bd813ffSjeremylt ierr = CeedVectorCreate(ceed, nqpts, &qweights); CeedChk(ierr); 673*3bd813ffSjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, CEED_EVAL_WEIGHT, 674*3bd813ffSjeremylt CEED_VECTOR_NONE, qweights); CeedChk(ierr); 675*3bd813ffSjeremylt ierr = CeedVectorGetArrayRead(assembled, CEED_MEM_HOST, &assembledarray); 676*3bd813ffSjeremylt CeedChk(ierr); 677*3bd813ffSjeremylt ierr = CeedVectorGetArrayRead(qweights, CEED_MEM_HOST, &qweightsarray); 678*3bd813ffSjeremylt CeedChk(ierr); 679*3bd813ffSjeremylt ierr = CeedCalloc(nelem, &elemavg); CeedChk(ierr); 680*3bd813ffSjeremylt for (CeedInt e=0; e<nelem; e++) { 681*3bd813ffSjeremylt CeedInt count = 0; 682*3bd813ffSjeremylt for (CeedInt q=0; q<nqpts; q++) 683*3bd813ffSjeremylt for (CeedInt i=0; i<ncomp*ncomp*nfields; i++) 684*3bd813ffSjeremylt if (fabs(assembledarray[e*nelem*nqpts*ncomp*ncomp*nfields + 685*3bd813ffSjeremylt i*nqpts + q]) > 1e-15) { 686*3bd813ffSjeremylt elemavg[e] += assembledarray[e*nelem*nqpts*ncomp*ncomp*nfields + 687*3bd813ffSjeremylt i*nqpts + q] / qweightsarray[q]; 688*3bd813ffSjeremylt count++; 689*3bd813ffSjeremylt } 690*3bd813ffSjeremylt if (count) 691*3bd813ffSjeremylt elemavg[e] /= count; 692*3bd813ffSjeremylt } 693*3bd813ffSjeremylt ierr = CeedVectorRestoreArrayRead(assembled, &assembledarray); CeedChk(ierr); 694*3bd813ffSjeremylt ierr = CeedVectorDestroy(&assembled); CeedChk(ierr); 695*3bd813ffSjeremylt ierr = CeedVectorRestoreArrayRead(qweights, &qweightsarray); CeedChk(ierr); 696*3bd813ffSjeremylt ierr = CeedVectorDestroy(&qweights); CeedChk(ierr); 697*3bd813ffSjeremylt 698*3bd813ffSjeremylt // Build FDM diagonal 699*3bd813ffSjeremylt CeedVector qdata; 700*3bd813ffSjeremylt CeedScalar *qdataarray; 701*3bd813ffSjeremylt ierr = CeedVectorCreate(ceed, nelem*ncomp*nnodes, &qdata); CeedChk(ierr); 702*3bd813ffSjeremylt ierr = CeedVectorSetArray(qdata, CEED_MEM_HOST, CEED_COPY_VALUES, NULL); 703*3bd813ffSjeremylt CeedChk(ierr); 704*3bd813ffSjeremylt ierr = CeedVectorGetArray(qdata, CEED_MEM_HOST, &qdataarray); CeedChk(ierr); 705*3bd813ffSjeremylt for (CeedInt e=0; e<nelem; e++) 706*3bd813ffSjeremylt for (CeedInt c=0; c<ncomp; c++) 707*3bd813ffSjeremylt for (CeedInt n=0; n<nnodes; n++) { 708*3bd813ffSjeremylt if (interp) 709*3bd813ffSjeremylt qdataarray[(e*ncomp+c)*nnodes+n] = 1; 710*3bd813ffSjeremylt if (grad) 711*3bd813ffSjeremylt for (CeedInt d=0; d<dim; d++) { 712*3bd813ffSjeremylt CeedInt i = (n / CeedIntPow(P1d, d)) % P1d; 713*3bd813ffSjeremylt qdataarray[(e*ncomp+c)*nnodes+n] += lambda[i]; 714*3bd813ffSjeremylt } 715*3bd813ffSjeremylt qdataarray[(e*ncomp+c)*nnodes+n] = 1 / (elemavg[e] * 716*3bd813ffSjeremylt qdataarray[(e*ncomp+c)*nnodes+n]); 717*3bd813ffSjeremylt } 718*3bd813ffSjeremylt ierr = CeedFree(&elemavg); CeedChk(ierr); 719*3bd813ffSjeremylt ierr = CeedVectorRestoreArray(qdata, &qdataarray); CeedChk(ierr); 720*3bd813ffSjeremylt 721*3bd813ffSjeremylt // Setup FDM operator 722*3bd813ffSjeremylt // -- Basis 723*3bd813ffSjeremylt CeedBasis fdm_basis; 724*3bd813ffSjeremylt CeedScalar *graddummy, *qrefdummy, *qweightdummy; 725*3bd813ffSjeremylt ierr = CeedCalloc(P1d*P1d, &graddummy); CeedChk(ierr); 726*3bd813ffSjeremylt ierr = CeedCalloc(P1d, &qrefdummy); CeedChk(ierr); 727*3bd813ffSjeremylt ierr = CeedCalloc(P1d, &qweightdummy); CeedChk(ierr); 728*3bd813ffSjeremylt ierr = CeedBasisCreateTensorH1(ceed, dim, ncomp, P1d, P1d, x2, graddummy, 729*3bd813ffSjeremylt qrefdummy, qweightdummy, &fdm_basis); 730*3bd813ffSjeremylt CeedChk(ierr); 731*3bd813ffSjeremylt ierr = CeedFree(&graddummy); CeedChk(ierr); 732*3bd813ffSjeremylt ierr = CeedFree(&qrefdummy); CeedChk(ierr); 733*3bd813ffSjeremylt ierr = CeedFree(&qweightdummy); CeedChk(ierr); 734*3bd813ffSjeremylt ierr = CeedFree(&x2); CeedChk(ierr); 735*3bd813ffSjeremylt ierr = CeedFree(&lambda); CeedChk(ierr); 736*3bd813ffSjeremylt 737*3bd813ffSjeremylt // -- Restriction 738*3bd813ffSjeremylt CeedElemRestriction rstr_i; 739*3bd813ffSjeremylt ierr = CeedElemRestrictionCreateIdentity(ceed, nelem, nnodes, nnodes*nelem, 740*3bd813ffSjeremylt ncomp, &rstr_i); CeedChk(ierr); 741*3bd813ffSjeremylt // -- QFunction 742*3bd813ffSjeremylt CeedQFunction mass_qf; 743*3bd813ffSjeremylt ierr = CeedQFunctionCreateInteriorByName(ceed, "MassApply", &mass_qf); 744*3bd813ffSjeremylt CeedChk(ierr); 745*3bd813ffSjeremylt // -- Operator 746*3bd813ffSjeremylt ierr = CeedOperatorCreate(ceed, mass_qf, NULL, NULL, fdminv); CeedChk(ierr); 747*3bd813ffSjeremylt CeedOperatorSetField(*fdminv, "u", rstr_i, CEED_NOTRANSPOSE, 748*3bd813ffSjeremylt fdm_basis, CEED_VECTOR_ACTIVE); CeedChk(ierr); 749*3bd813ffSjeremylt CeedOperatorSetField(*fdminv, "qdata", rstr_i, CEED_NOTRANSPOSE, 750*3bd813ffSjeremylt CEED_BASIS_COLLOCATED, qdata); CeedChk(ierr); 751*3bd813ffSjeremylt CeedOperatorSetField(*fdminv, "v", rstr_i, CEED_NOTRANSPOSE, 752*3bd813ffSjeremylt fdm_basis, CEED_VECTOR_ACTIVE); CeedChk(ierr); 753*3bd813ffSjeremylt 754*3bd813ffSjeremylt // Cleanup 755*3bd813ffSjeremylt ierr = CeedVectorDestroy(&qdata); CeedChk(ierr); 756*3bd813ffSjeremylt ierr = CeedBasisDestroy(&fdm_basis); CeedChk(ierr); 757*3bd813ffSjeremylt ierr = CeedElemRestrictionDestroy(&rstr_i); CeedChk(ierr); 758*3bd813ffSjeremylt ierr = CeedQFunctionDestroy(&mass_qf); CeedChk(ierr); 759*3bd813ffSjeremylt 760*3bd813ffSjeremylt return 0; 761*3bd813ffSjeremylt } 762*3bd813ffSjeremylt 763*3bd813ffSjeremylt 764*3bd813ffSjeremylt /** 765*3bd813ffSjeremylt @brief Apply CeedOperator to a vector 766d7b241e6Sjeremylt 767d7b241e6Sjeremylt This computes the action of the operator on the specified (active) input, 768d7b241e6Sjeremylt yielding its (active) output. All inputs and outputs must be specified using 769d7b241e6Sjeremylt CeedOperatorSetField(). 770d7b241e6Sjeremylt 771d7b241e6Sjeremylt @param op CeedOperator to apply 77234138859Sjeremylt @param[in] in CeedVector containing input state or CEED_VECTOR_NONE if 77334138859Sjeremylt there are no active inputs 774b11c1e72Sjeremylt @param[out] out CeedVector to store result of applying operator (must be 77534138859Sjeremylt distinct from @a in) or CEED_VECTOR_NONE if there are no 77634138859Sjeremylt active outputs 777d7b241e6Sjeremylt @param request Address of CeedRequest for non-blocking completion, else 778d7b241e6Sjeremylt CEED_REQUEST_IMMEDIATE 779b11c1e72Sjeremylt 780b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 781dfdf5a53Sjeremylt 782dfdf5a53Sjeremylt @ref Basic 783b11c1e72Sjeremylt **/ 784692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out, 785692c2638Sjeremylt CeedRequest *request) { 786d7b241e6Sjeremylt int ierr; 787d7b241e6Sjeremylt Ceed ceed = op->ceed; 788250756a7Sjeremylt ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 789d7b241e6Sjeremylt 790250756a7Sjeremylt if (op->numelements) { 791250756a7Sjeremylt // Standard Operator 792cae8b89aSjeremylt if (op->Apply) { 793250756a7Sjeremylt ierr = op->Apply(op, in, out, request); CeedChk(ierr); 794cae8b89aSjeremylt } else { 795cae8b89aSjeremylt // Zero all output vectors 796250756a7Sjeremylt CeedQFunction qf = op->qf; 797cae8b89aSjeremylt for (CeedInt i=0; i<qf->numoutputfields; i++) { 798cae8b89aSjeremylt CeedVector vec = op->outputfields[i]->vec; 799cae8b89aSjeremylt if (vec == CEED_VECTOR_ACTIVE) 800cae8b89aSjeremylt vec = out; 801cae8b89aSjeremylt if (vec != CEED_VECTOR_NONE) { 802cae8b89aSjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 803cae8b89aSjeremylt } 804cae8b89aSjeremylt } 805250756a7Sjeremylt // Apply 806250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 807250756a7Sjeremylt } 808250756a7Sjeremylt } else if (op->composite) { 809250756a7Sjeremylt // Composite Operator 810250756a7Sjeremylt if (op->ApplyComposite) { 811250756a7Sjeremylt ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr); 812250756a7Sjeremylt } else { 813250756a7Sjeremylt CeedInt numsub; 814250756a7Sjeremylt ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 815250756a7Sjeremylt CeedOperator *suboperators; 816250756a7Sjeremylt ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 817250756a7Sjeremylt 818250756a7Sjeremylt // Zero all output vectors 819250756a7Sjeremylt if (out != CEED_VECTOR_NONE) { 820cae8b89aSjeremylt ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr); 821cae8b89aSjeremylt } 822250756a7Sjeremylt for (CeedInt i=0; i<numsub; i++) { 823250756a7Sjeremylt for (CeedInt j=0; j<suboperators[i]->qf->numoutputfields; j++) { 824250756a7Sjeremylt CeedVector vec = suboperators[i]->outputfields[j]->vec; 825250756a7Sjeremylt if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) { 826250756a7Sjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 827250756a7Sjeremylt } 828250756a7Sjeremylt } 829250756a7Sjeremylt } 830250756a7Sjeremylt // Apply 831250756a7Sjeremylt for (CeedInt i=0; i<op->numsub; i++) { 832250756a7Sjeremylt ierr = CeedOperatorApplyAdd(op->suboperators[i], in, out, request); 833cae8b89aSjeremylt CeedChk(ierr); 834cae8b89aSjeremylt } 835cae8b89aSjeremylt } 836250756a7Sjeremylt } 837250756a7Sjeremylt 838cae8b89aSjeremylt return 0; 839cae8b89aSjeremylt } 840cae8b89aSjeremylt 841cae8b89aSjeremylt /** 842cae8b89aSjeremylt @brief Apply CeedOperator to a vector and add result to output vector 843cae8b89aSjeremylt 844cae8b89aSjeremylt This computes the action of the operator on the specified (active) input, 845cae8b89aSjeremylt yielding its (active) output. All inputs and outputs must be specified using 846cae8b89aSjeremylt CeedOperatorSetField(). 847cae8b89aSjeremylt 848cae8b89aSjeremylt @param op CeedOperator to apply 849cae8b89aSjeremylt @param[in] in CeedVector containing input state or NULL if there are no 850cae8b89aSjeremylt active inputs 851cae8b89aSjeremylt @param[out] out CeedVector to sum in result of applying operator (must be 852cae8b89aSjeremylt distinct from @a in) or NULL if there are no active outputs 853cae8b89aSjeremylt @param request Address of CeedRequest for non-blocking completion, else 854cae8b89aSjeremylt CEED_REQUEST_IMMEDIATE 855cae8b89aSjeremylt 856cae8b89aSjeremylt @return An error code: 0 - success, otherwise - failure 857cae8b89aSjeremylt 858cae8b89aSjeremylt @ref Basic 859cae8b89aSjeremylt **/ 860cae8b89aSjeremylt int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out, 861cae8b89aSjeremylt CeedRequest *request) { 862cae8b89aSjeremylt int ierr; 863cae8b89aSjeremylt Ceed ceed = op->ceed; 864250756a7Sjeremylt ierr = CeedOperatorCheckReady(ceed, op); CeedChk(ierr); 865cae8b89aSjeremylt 866250756a7Sjeremylt if (op->numelements) { 867250756a7Sjeremylt // Standard Operator 868250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 869250756a7Sjeremylt } else if (op->composite) { 870250756a7Sjeremylt // Composite Operator 871250756a7Sjeremylt if (op->ApplyAddComposite) { 872250756a7Sjeremylt ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr); 873cae8b89aSjeremylt } else { 874250756a7Sjeremylt CeedInt numsub; 875250756a7Sjeremylt ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 876250756a7Sjeremylt CeedOperator *suboperators; 877250756a7Sjeremylt ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 878250756a7Sjeremylt 879250756a7Sjeremylt for (CeedInt i=0; i<numsub; i++) { 880250756a7Sjeremylt ierr = CeedOperatorApplyAdd(suboperators[i], in, out, request); 881cae8b89aSjeremylt CeedChk(ierr); 8821d7d2407SJeremy L Thompson } 883250756a7Sjeremylt } 884250756a7Sjeremylt } 885250756a7Sjeremylt 886d7b241e6Sjeremylt return 0; 887d7b241e6Sjeremylt } 888d7b241e6Sjeremylt 889d7b241e6Sjeremylt /** 8904ce2993fSjeremylt @brief Get the Ceed associated with a CeedOperator 8914ce2993fSjeremylt 8924ce2993fSjeremylt @param op CeedOperator 8934ce2993fSjeremylt @param[out] ceed Variable to store Ceed 8944ce2993fSjeremylt 8954ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 8964ce2993fSjeremylt 89723617272Sjeremylt @ref Advanced 8984ce2993fSjeremylt **/ 8994ce2993fSjeremylt 9004ce2993fSjeremylt int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 9014ce2993fSjeremylt *ceed = op->ceed; 9024ce2993fSjeremylt return 0; 9034ce2993fSjeremylt } 9044ce2993fSjeremylt 9054ce2993fSjeremylt /** 9064ce2993fSjeremylt @brief Get the number of elements associated with a CeedOperator 9074ce2993fSjeremylt 9084ce2993fSjeremylt @param op CeedOperator 9094ce2993fSjeremylt @param[out] numelem Variable to store number of elements 9104ce2993fSjeremylt 9114ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 9124ce2993fSjeremylt 91323617272Sjeremylt @ref Advanced 9144ce2993fSjeremylt **/ 9154ce2993fSjeremylt 9164ce2993fSjeremylt int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) { 91752d6035fSJeremy L Thompson if (op->composite) 918c042f62fSJeremy L Thompson // LCOV_EXCL_START 91952d6035fSJeremy L Thompson return CeedError(op->ceed, 1, "Not defined for composite operator"); 920c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 92152d6035fSJeremy L Thompson 9224ce2993fSjeremylt *numelem = op->numelements; 9234ce2993fSjeremylt return 0; 9244ce2993fSjeremylt } 9254ce2993fSjeremylt 9264ce2993fSjeremylt /** 9274ce2993fSjeremylt @brief Get the number of quadrature points associated with a CeedOperator 9284ce2993fSjeremylt 9294ce2993fSjeremylt @param op CeedOperator 9304ce2993fSjeremylt @param[out] numqpts Variable to store vector number of quadrature points 9314ce2993fSjeremylt 9324ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 9334ce2993fSjeremylt 93423617272Sjeremylt @ref Advanced 9354ce2993fSjeremylt **/ 9364ce2993fSjeremylt 9374ce2993fSjeremylt int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) { 93852d6035fSJeremy L Thompson if (op->composite) 939c042f62fSJeremy L Thompson // LCOV_EXCL_START 94052d6035fSJeremy L Thompson return CeedError(op->ceed, 1, "Not defined for composite operator"); 941c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 94252d6035fSJeremy L Thompson 9434ce2993fSjeremylt *numqpts = op->numqpoints; 9444ce2993fSjeremylt return 0; 9454ce2993fSjeremylt } 9464ce2993fSjeremylt 9474ce2993fSjeremylt /** 9484ce2993fSjeremylt @brief Get the number of arguments associated with a CeedOperator 9494ce2993fSjeremylt 9504ce2993fSjeremylt @param op CeedOperator 9514ce2993fSjeremylt @param[out] numargs Variable to store vector number of arguments 9524ce2993fSjeremylt 9534ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 9544ce2993fSjeremylt 95523617272Sjeremylt @ref Advanced 9564ce2993fSjeremylt **/ 9574ce2993fSjeremylt 9584ce2993fSjeremylt int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) { 95952d6035fSJeremy L Thompson if (op->composite) 960c042f62fSJeremy L Thompson // LCOV_EXCL_START 96152d6035fSJeremy L Thompson return CeedError(op->ceed, 1, "Not defined for composite operators"); 962c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 963c042f62fSJeremy L Thompson 9644ce2993fSjeremylt *numargs = op->nfields; 9654ce2993fSjeremylt return 0; 9664ce2993fSjeremylt } 9674ce2993fSjeremylt 9684ce2993fSjeremylt /** 9694ce2993fSjeremylt @brief Get the setup status of a CeedOperator 9704ce2993fSjeremylt 9714ce2993fSjeremylt @param op CeedOperator 972288c0443SJeremy L Thompson @param[out] setupdone Variable to store setup status 9734ce2993fSjeremylt 9744ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 9754ce2993fSjeremylt 97623617272Sjeremylt @ref Advanced 9774ce2993fSjeremylt **/ 9784ce2993fSjeremylt 9794ce2993fSjeremylt int CeedOperatorGetSetupStatus(CeedOperator op, bool *setupdone) { 9804ce2993fSjeremylt *setupdone = op->setupdone; 9814ce2993fSjeremylt return 0; 9824ce2993fSjeremylt } 9834ce2993fSjeremylt 9844ce2993fSjeremylt /** 9854ce2993fSjeremylt @brief Get the QFunction associated with a CeedOperator 9864ce2993fSjeremylt 9874ce2993fSjeremylt @param op CeedOperator 9888c91a0c9SJeremy L Thompson @param[out] qf Variable to store QFunction 9894ce2993fSjeremylt 9904ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 9914ce2993fSjeremylt 99223617272Sjeremylt @ref Advanced 9934ce2993fSjeremylt **/ 9944ce2993fSjeremylt 9954ce2993fSjeremylt int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 99652d6035fSJeremy L Thompson if (op->composite) 997c042f62fSJeremy L Thompson // LCOV_EXCL_START 99852d6035fSJeremy L Thompson return CeedError(op->ceed, 1, "Not defined for composite operator"); 999c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 100052d6035fSJeremy L Thompson 10014ce2993fSjeremylt *qf = op->qf; 10024ce2993fSjeremylt return 0; 10034ce2993fSjeremylt } 10044ce2993fSjeremylt 10054ce2993fSjeremylt /** 100652d6035fSJeremy L Thompson @brief Get the number of suboperators associated with a CeedOperator 100752d6035fSJeremy L Thompson 100852d6035fSJeremy L Thompson @param op CeedOperator 100952d6035fSJeremy L Thompson @param[out] numsub Variable to store number of suboperators 101052d6035fSJeremy L Thompson 101152d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 101252d6035fSJeremy L Thompson 101352d6035fSJeremy L Thompson @ref Advanced 101452d6035fSJeremy L Thompson **/ 101552d6035fSJeremy L Thompson 101652d6035fSJeremy L Thompson int CeedOperatorGetNumSub(CeedOperator op, CeedInt *numsub) { 1017c042f62fSJeremy L Thompson if (!op->composite) 1018c042f62fSJeremy L Thompson // LCOV_EXCL_START 1019c042f62fSJeremy L Thompson return CeedError(op->ceed, 1, "Not a composite operator"); 1020c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 102152d6035fSJeremy L Thompson 102252d6035fSJeremy L Thompson *numsub = op->numsub; 102352d6035fSJeremy L Thompson return 0; 102452d6035fSJeremy L Thompson } 102552d6035fSJeremy L Thompson 102652d6035fSJeremy L Thompson /** 102752d6035fSJeremy L Thompson @brief Get the list of suboperators associated with a CeedOperator 102852d6035fSJeremy L Thompson 102952d6035fSJeremy L Thompson @param op CeedOperator 103052d6035fSJeremy L Thompson @param[out] suboperators Variable to store list of suboperators 103152d6035fSJeremy L Thompson 103252d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 103352d6035fSJeremy L Thompson 103452d6035fSJeremy L Thompson @ref Advanced 103552d6035fSJeremy L Thompson **/ 103652d6035fSJeremy L Thompson 103752d6035fSJeremy L Thompson int CeedOperatorGetSubList(CeedOperator op, CeedOperator **suboperators) { 1038c042f62fSJeremy L Thompson if (!op->composite) 1039c042f62fSJeremy L Thompson // LCOV_EXCL_START 1040c042f62fSJeremy L Thompson return CeedError(op->ceed, 1, "Not a composite operator"); 1041c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 104252d6035fSJeremy L Thompson 104352d6035fSJeremy L Thompson *suboperators = op->suboperators; 104452d6035fSJeremy L Thompson return 0; 104552d6035fSJeremy L Thompson } 104652d6035fSJeremy L Thompson 104752d6035fSJeremy L Thompson /** 1048fe2413ffSjeremylt @brief Set the backend data of a CeedOperator 1049fe2413ffSjeremylt 1050fe2413ffSjeremylt @param[out] op CeedOperator 1051fe2413ffSjeremylt @param data Data to set 1052fe2413ffSjeremylt 1053fe2413ffSjeremylt @return An error code: 0 - success, otherwise - failure 1054fe2413ffSjeremylt 1055fe2413ffSjeremylt @ref Advanced 1056fe2413ffSjeremylt **/ 1057fe2413ffSjeremylt 1058fe2413ffSjeremylt int CeedOperatorSetData(CeedOperator op, void **data) { 1059fe2413ffSjeremylt op->data = *data; 1060fe2413ffSjeremylt return 0; 1061fe2413ffSjeremylt } 1062fe2413ffSjeremylt 1063fe2413ffSjeremylt /** 10644ce2993fSjeremylt @brief Get the backend data of a CeedOperator 10654ce2993fSjeremylt 10664ce2993fSjeremylt @param op CeedOperator 10674ce2993fSjeremylt @param[out] data Variable to store data 10684ce2993fSjeremylt 10694ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 10704ce2993fSjeremylt 107123617272Sjeremylt @ref Advanced 10724ce2993fSjeremylt **/ 10734ce2993fSjeremylt 10744ce2993fSjeremylt int CeedOperatorGetData(CeedOperator op, void **data) { 10754ce2993fSjeremylt *data = op->data; 10764ce2993fSjeremylt return 0; 10774ce2993fSjeremylt } 10784ce2993fSjeremylt 10794ce2993fSjeremylt /** 10804ce2993fSjeremylt @brief Set the setup flag of a CeedOperator to True 10814ce2993fSjeremylt 10824ce2993fSjeremylt @param op CeedOperator 10834ce2993fSjeremylt 10844ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 10854ce2993fSjeremylt 108623617272Sjeremylt @ref Advanced 10874ce2993fSjeremylt **/ 10884ce2993fSjeremylt 10894ce2993fSjeremylt int CeedOperatorSetSetupDone(CeedOperator op) { 10904ce2993fSjeremylt op->setupdone = 1; 10914ce2993fSjeremylt return 0; 10924ce2993fSjeremylt } 10934ce2993fSjeremylt 10944ce2993fSjeremylt /** 10952ebaca42Sjeremylt @brief View a field of a CeedOperator 10962ebaca42Sjeremylt 10972ebaca42Sjeremylt @param[in] field Operator field to view 10982ebaca42Sjeremylt @param[in] fieldnumber Number of field being viewed 10992ebaca42Sjeremylt @param[in] stream Stream to view to, e.g., stdout 11002ebaca42Sjeremylt 11012ebaca42Sjeremylt @return An error code: 0 - success, otherwise - failure 11022ebaca42Sjeremylt 11032ebaca42Sjeremylt @ref Utility 11042ebaca42Sjeremylt **/ 11052ebaca42Sjeremylt static int CeedOperatorFieldView(CeedOperatorField field, 11062ebaca42Sjeremylt CeedQFunctionField qffield, 11072da88da5Sjeremylt CeedInt fieldnumber, bool sub, bool in, 11082da88da5Sjeremylt FILE *stream) { 11092ebaca42Sjeremylt const char *pre = sub ? " " : ""; 11102da88da5Sjeremylt const char *inout = in ? "Input" : "Output"; 11112ebaca42Sjeremylt 11122da88da5Sjeremylt fprintf(stream, "%s %s Field [%d]:\n" 11132da88da5Sjeremylt "%s Name: \"%s\"\n" 11142da88da5Sjeremylt "%s Lmode: \"%s\"\n", 11152da88da5Sjeremylt pre, inout, fieldnumber, pre, qffield->fieldname, 11162ebaca42Sjeremylt pre, CeedTransposeModes[field->lmode]); 11172ebaca42Sjeremylt 11182ebaca42Sjeremylt if (field->basis == CEED_BASIS_COLLOCATED) 11192ebaca42Sjeremylt fprintf(stream, "%s Collocated basis\n", pre); 11202ebaca42Sjeremylt 11212ebaca42Sjeremylt if (field->vec == CEED_VECTOR_ACTIVE) 11222ebaca42Sjeremylt fprintf(stream, "%s Active vector\n", pre); 11232ebaca42Sjeremylt else if (field->vec == CEED_VECTOR_NONE) 11242ebaca42Sjeremylt fprintf(stream, "%s No vector\n", pre); 11252ebaca42Sjeremylt 11262ebaca42Sjeremylt return 0; 11272ebaca42Sjeremylt } 11282ebaca42Sjeremylt 11292ebaca42Sjeremylt /** 11302ebaca42Sjeremylt @brief View a single CeedOperator 11312ebaca42Sjeremylt 11322ebaca42Sjeremylt @param[in] op CeedOperator to view 11332ebaca42Sjeremylt @param[in] stream Stream to write; typically stdout/stderr or a file 11342ebaca42Sjeremylt 11352ebaca42Sjeremylt @return Error code: 0 - success, otherwise - failure 11362ebaca42Sjeremylt 11372ebaca42Sjeremylt @ref Utility 11382ebaca42Sjeremylt **/ 11392ebaca42Sjeremylt int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) { 11402ebaca42Sjeremylt int ierr; 11412ebaca42Sjeremylt const char *pre = sub ? " " : ""; 11422ebaca42Sjeremylt 11432ebaca42Sjeremylt CeedInt totalfields; 11442ebaca42Sjeremylt ierr = CeedOperatorGetNumArgs(op, &totalfields); CeedChk(ierr); 11452da88da5Sjeremylt 11462ebaca42Sjeremylt fprintf(stream, "%s %d Field%s\n", pre, totalfields, totalfields>1 ? "s" : ""); 11472ebaca42Sjeremylt 11482da88da5Sjeremylt fprintf(stream, "%s %d Input Field%s:\n", pre, op->qf->numinputfields, 11492ebaca42Sjeremylt op->qf->numinputfields>1 ? "s" : ""); 11502ebaca42Sjeremylt for (CeedInt i=0; i<op->qf->numinputfields; i++) { 11512ebaca42Sjeremylt ierr = CeedOperatorFieldView(op->inputfields[i], op->qf->inputfields[i], 11522da88da5Sjeremylt i, sub, 1, stream); CeedChk(ierr); 11532ebaca42Sjeremylt } 11542ebaca42Sjeremylt 11552da88da5Sjeremylt fprintf(stream, "%s %d Output Field%s:\n", pre, op->qf->numoutputfields, 11562ebaca42Sjeremylt op->qf->numoutputfields>1 ? "s" : ""); 11572ebaca42Sjeremylt for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 11582ebaca42Sjeremylt ierr = CeedOperatorFieldView(op->outputfields[i], op->qf->inputfields[i], 11592da88da5Sjeremylt i, sub, 0, stream); CeedChk(ierr); 11602ebaca42Sjeremylt } 11612ebaca42Sjeremylt 11622ebaca42Sjeremylt return 0; 11632ebaca42Sjeremylt } 11642ebaca42Sjeremylt 11652ebaca42Sjeremylt /** 11662ebaca42Sjeremylt @brief View a CeedOperator 11672ebaca42Sjeremylt 11682ebaca42Sjeremylt @param[in] op CeedOperator to view 11692ebaca42Sjeremylt @param[in] stream Stream to write; typically stdout/stderr or a file 11702ebaca42Sjeremylt 11712ebaca42Sjeremylt @return Error code: 0 - success, otherwise - failure 11722ebaca42Sjeremylt 11732ebaca42Sjeremylt @ref Utility 11742ebaca42Sjeremylt **/ 11752ebaca42Sjeremylt int CeedOperatorView(CeedOperator op, FILE *stream) { 11762ebaca42Sjeremylt int ierr; 11772ebaca42Sjeremylt 11782ebaca42Sjeremylt if (op->composite) { 11792ebaca42Sjeremylt fprintf(stream, "Composite CeedOperator\n"); 11802ebaca42Sjeremylt 11812ebaca42Sjeremylt for (CeedInt i=0; i<op->numsub; i++) { 11822da88da5Sjeremylt fprintf(stream, " SubOperator [%d]:\n", i); 11832ebaca42Sjeremylt ierr = CeedOperatorSingleView(op->suboperators[i], 1, stream); 11842ebaca42Sjeremylt CeedChk(ierr); 11852ebaca42Sjeremylt } 11862ebaca42Sjeremylt } else { 11872ebaca42Sjeremylt fprintf(stream, "CeedOperator\n"); 11882ebaca42Sjeremylt ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr); 11892ebaca42Sjeremylt } 11902ebaca42Sjeremylt 11912ebaca42Sjeremylt return 0; 11922ebaca42Sjeremylt } 11932ebaca42Sjeremylt 11942ebaca42Sjeremylt /** 1195d1bcdac9Sjeremylt @brief Get the CeedOperatorFields of a CeedOperator 1196d1bcdac9Sjeremylt 1197d1bcdac9Sjeremylt @param op CeedOperator 1198d1bcdac9Sjeremylt @param[out] inputfields Variable to store inputfields 1199d1bcdac9Sjeremylt @param[out] outputfields Variable to store outputfields 1200d1bcdac9Sjeremylt 1201d1bcdac9Sjeremylt @return An error code: 0 - success, otherwise - failure 1202d1bcdac9Sjeremylt 1203d1bcdac9Sjeremylt @ref Advanced 1204d1bcdac9Sjeremylt **/ 1205d1bcdac9Sjeremylt 1206692c2638Sjeremylt int CeedOperatorGetFields(CeedOperator op, CeedOperatorField **inputfields, 1207d1bcdac9Sjeremylt CeedOperatorField **outputfields) { 120852d6035fSJeremy L Thompson if (op->composite) 1209c042f62fSJeremy L Thompson // LCOV_EXCL_START 121052d6035fSJeremy L Thompson return CeedError(op->ceed, 1, "Not defined for composite operator"); 1211c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 121252d6035fSJeremy L Thompson 1213d1bcdac9Sjeremylt if (inputfields) *inputfields = op->inputfields; 1214d1bcdac9Sjeremylt if (outputfields) *outputfields = op->outputfields; 1215d1bcdac9Sjeremylt return 0; 1216d1bcdac9Sjeremylt } 1217d1bcdac9Sjeremylt 1218d1bcdac9Sjeremylt /** 12194dccadb6Sjeremylt @brief Get the L vector CeedTransposeMode of a CeedOperatorField 12204dccadb6Sjeremylt 12214dccadb6Sjeremylt @param opfield CeedOperatorField 12224dccadb6Sjeremylt @param[out] lmode Variable to store CeedTransposeMode 12234dccadb6Sjeremylt 12244dccadb6Sjeremylt @return An error code: 0 - success, otherwise - failure 12254dccadb6Sjeremylt 12264dccadb6Sjeremylt @ref Advanced 12274dccadb6Sjeremylt **/ 12284dccadb6Sjeremylt 12294dccadb6Sjeremylt int CeedOperatorFieldGetLMode(CeedOperatorField opfield, 12304dccadb6Sjeremylt CeedTransposeMode *lmode) { 1231fe2413ffSjeremylt *lmode = opfield->lmode; 12324dccadb6Sjeremylt return 0; 12332b8e417aSjeremylt } 12342b8e417aSjeremylt 12352b8e417aSjeremylt /** 1236d1bcdac9Sjeremylt @brief Get the CeedElemRestriction of a CeedOperatorField 1237d1bcdac9Sjeremylt 1238d1bcdac9Sjeremylt @param opfield CeedOperatorField 1239d1bcdac9Sjeremylt @param[out] rstr Variable to store CeedElemRestriction 1240d1bcdac9Sjeremylt 1241d1bcdac9Sjeremylt @return An error code: 0 - success, otherwise - failure 1242d1bcdac9Sjeremylt 1243d1bcdac9Sjeremylt @ref Advanced 1244d1bcdac9Sjeremylt **/ 1245d1bcdac9Sjeremylt 1246d1bcdac9Sjeremylt int CeedOperatorFieldGetElemRestriction(CeedOperatorField opfield, 1247d1bcdac9Sjeremylt CeedElemRestriction *rstr) { 1248fe2413ffSjeremylt *rstr = opfield->Erestrict; 1249d1bcdac9Sjeremylt return 0; 1250d1bcdac9Sjeremylt } 1251d1bcdac9Sjeremylt 1252d1bcdac9Sjeremylt /** 1253d1bcdac9Sjeremylt @brief Get the CeedBasis of a CeedOperatorField 1254d1bcdac9Sjeremylt 1255d1bcdac9Sjeremylt @param opfield CeedOperatorField 1256d1bcdac9Sjeremylt @param[out] basis Variable to store CeedBasis 1257d1bcdac9Sjeremylt 1258d1bcdac9Sjeremylt @return An error code: 0 - success, otherwise - failure 1259d1bcdac9Sjeremylt 1260d1bcdac9Sjeremylt @ref Advanced 1261d1bcdac9Sjeremylt **/ 1262d1bcdac9Sjeremylt 1263692c2638Sjeremylt int CeedOperatorFieldGetBasis(CeedOperatorField opfield, CeedBasis *basis) { 1264fe2413ffSjeremylt *basis = opfield->basis; 1265d1bcdac9Sjeremylt return 0; 1266d1bcdac9Sjeremylt } 1267d1bcdac9Sjeremylt 1268d1bcdac9Sjeremylt /** 1269d1bcdac9Sjeremylt @brief Get the CeedVector of a CeedOperatorField 1270d1bcdac9Sjeremylt 1271d1bcdac9Sjeremylt @param opfield CeedOperatorField 1272d1bcdac9Sjeremylt @param[out] vec Variable to store CeedVector 1273d1bcdac9Sjeremylt 1274d1bcdac9Sjeremylt @return An error code: 0 - success, otherwise - failure 1275d1bcdac9Sjeremylt 1276d1bcdac9Sjeremylt @ref Advanced 1277d1bcdac9Sjeremylt **/ 1278d1bcdac9Sjeremylt 1279692c2638Sjeremylt int CeedOperatorFieldGetVector(CeedOperatorField opfield, CeedVector *vec) { 1280fe2413ffSjeremylt *vec = opfield->vec; 1281d1bcdac9Sjeremylt return 0; 1282d1bcdac9Sjeremylt } 1283d1bcdac9Sjeremylt 1284d1bcdac9Sjeremylt /** 1285b11c1e72Sjeremylt @brief Destroy a CeedOperator 1286d7b241e6Sjeremylt 1287d7b241e6Sjeremylt @param op CeedOperator to destroy 1288b11c1e72Sjeremylt 1289b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 1290dfdf5a53Sjeremylt 1291dfdf5a53Sjeremylt @ref Basic 1292b11c1e72Sjeremylt **/ 1293d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) { 1294d7b241e6Sjeremylt int ierr; 1295d7b241e6Sjeremylt 1296d7b241e6Sjeremylt if (!*op || --(*op)->refcount > 0) return 0; 1297d7b241e6Sjeremylt if ((*op)->Destroy) { 1298d7b241e6Sjeremylt ierr = (*op)->Destroy(*op); CeedChk(ierr); 1299d7b241e6Sjeremylt } 1300fe2413ffSjeremylt ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 1301fe2413ffSjeremylt // Free fields 13021d102b48SJeremy L Thompson for (int i=0; i<(*op)->nfields; i++) 130352d6035fSJeremy L Thompson if ((*op)->inputfields[i]) { 130471352a93Sjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->inputfields[i]->Erestrict); 130571352a93Sjeremylt CeedChk(ierr); 130671352a93Sjeremylt if ((*op)->inputfields[i]->basis != CEED_BASIS_COLLOCATED) { 130771352a93Sjeremylt ierr = CeedBasisDestroy(&(*op)->inputfields[i]->basis); CeedChk(ierr); 130871352a93Sjeremylt } 130971352a93Sjeremylt if ((*op)->inputfields[i]->vec != CEED_VECTOR_ACTIVE && 131071352a93Sjeremylt (*op)->inputfields[i]->vec != CEED_VECTOR_NONE ) { 131171352a93Sjeremylt ierr = CeedVectorDestroy(&(*op)->inputfields[i]->vec); CeedChk(ierr); 131271352a93Sjeremylt } 1313fe2413ffSjeremylt ierr = CeedFree(&(*op)->inputfields[i]); CeedChk(ierr); 1314fe2413ffSjeremylt } 13151d102b48SJeremy L Thompson for (int i=0; i<(*op)->nfields; i++) 1316d0eb30a5Sjeremylt if ((*op)->outputfields[i]) { 131771352a93Sjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->outputfields[i]->Erestrict); 131871352a93Sjeremylt CeedChk(ierr); 131971352a93Sjeremylt if ((*op)->outputfields[i]->basis != CEED_BASIS_COLLOCATED) { 132071352a93Sjeremylt ierr = CeedBasisDestroy(&(*op)->outputfields[i]->basis); CeedChk(ierr); 132171352a93Sjeremylt } 132271352a93Sjeremylt if ((*op)->outputfields[i]->vec != CEED_VECTOR_ACTIVE && 132371352a93Sjeremylt (*op)->outputfields[i]->vec != CEED_VECTOR_NONE ) { 132471352a93Sjeremylt ierr = CeedVectorDestroy(&(*op)->outputfields[i]->vec); CeedChk(ierr); 132571352a93Sjeremylt } 1326fe2413ffSjeremylt ierr = CeedFree(&(*op)->outputfields[i]); CeedChk(ierr); 1327fe2413ffSjeremylt } 132852d6035fSJeremy L Thompson // Destroy suboperators 13291d102b48SJeremy L Thompson for (int i=0; i<(*op)->numsub; i++) 133052d6035fSJeremy L Thompson if ((*op)->suboperators[i]) { 133152d6035fSJeremy L Thompson ierr = CeedOperatorDestroy(&(*op)->suboperators[i]); CeedChk(ierr); 133252d6035fSJeremy L Thompson } 1333d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 1334d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 1335d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 1336fe2413ffSjeremylt 13375107b09fSJeremy L Thompson // Destroy fallback 13385107b09fSJeremy L Thompson if ((*op)->opfallback) { 13395107b09fSJeremy L Thompson ierr = (*op)->qffallback->Destroy((*op)->qffallback); CeedChk(ierr); 13405107b09fSJeremy L Thompson ierr = CeedFree(&(*op)->qffallback); CeedChk(ierr); 13415107b09fSJeremy L Thompson ierr = (*op)->opfallback->Destroy((*op)->opfallback); CeedChk(ierr); 13425107b09fSJeremy L Thompson ierr = CeedFree(&(*op)->opfallback); CeedChk(ierr); 13435107b09fSJeremy L Thompson } 13445107b09fSJeremy L Thompson 1345fe2413ffSjeremylt ierr = CeedFree(&(*op)->inputfields); CeedChk(ierr); 1346fe2413ffSjeremylt ierr = CeedFree(&(*op)->outputfields); CeedChk(ierr); 134752d6035fSJeremy L Thompson ierr = CeedFree(&(*op)->suboperators); CeedChk(ierr); 1348d7b241e6Sjeremylt ierr = CeedFree(op); CeedChk(ierr); 1349d7b241e6Sjeremylt return 0; 1350d7b241e6Sjeremylt } 1351d7b241e6Sjeremylt 1352d7b241e6Sjeremylt /// @} 1353