1d7b241e6Sjeremylt // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at 2d7b241e6Sjeremylt // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights 3d7b241e6Sjeremylt // reserved. See files LICENSE and NOTICE for details. 4d7b241e6Sjeremylt // 5d7b241e6Sjeremylt // This file is part of CEED, a collection of benchmarks, miniapps, software 6d7b241e6Sjeremylt // libraries and APIs for efficient high-order finite element and spectral 7d7b241e6Sjeremylt // element discretizations for exascale applications. For more information and 8d7b241e6Sjeremylt // source code availability see http://github.com/ceed. 9d7b241e6Sjeremylt // 10d7b241e6Sjeremylt // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 11d7b241e6Sjeremylt // a collaborative effort of two U.S. Department of Energy organizations (Office 12d7b241e6Sjeremylt // of Science and the National Nuclear Security Administration) responsible for 13d7b241e6Sjeremylt // the planning and preparation of a capable exascale ecosystem, including 14d7b241e6Sjeremylt // software, applications, hardware, advanced system engineering and early 15d7b241e6Sjeremylt // testbed platforms, in support of the nation's exascale computing imperative. 16d7b241e6Sjeremylt 17d7b241e6Sjeremylt #include <ceed-impl.h> 18d863ab9bSjeremylt #include <ceed-backend.h> 19d7b241e6Sjeremylt #include <string.h> 20d7b241e6Sjeremylt 21dfdf5a53Sjeremylt /// @file 22dfdf5a53Sjeremylt /// Implementation of public CeedOperator interfaces 23dfdf5a53Sjeremylt /// 24dfdf5a53Sjeremylt /// @addtogroup CeedOperator 25dfdf5a53Sjeremylt /// @{ 26d7b241e6Sjeremylt 27d7b241e6Sjeremylt /** 280219ea01SJeremy L Thompson @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and 290219ea01SJeremy L Thompson CeedElemRestriction can be associated with CeedQFunction fields with 300219ea01SJeremy L Thompson \ref CeedOperatorSetField. 31d7b241e6Sjeremylt 32b11c1e72Sjeremylt @param ceed A Ceed object where the CeedOperator will be created 33d7b241e6Sjeremylt @param qf QFunction defining the action of the operator at quadrature points 34d7b241e6Sjeremylt @param dqf QFunction defining the action of the Jacobian of @a qf (or NULL) 35d7b241e6Sjeremylt @param dqfT QFunction defining the action of the transpose of the Jacobian 36d7b241e6Sjeremylt of @a qf (or NULL) 37b11c1e72Sjeremylt @param[out] op Address of the variable where the newly created 38b11c1e72Sjeremylt CeedOperator will be stored 39b11c1e72Sjeremylt 40b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 41dfdf5a53Sjeremylt 42dfdf5a53Sjeremylt @ref Basic 43d7b241e6Sjeremylt */ 44d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf, 45d7b241e6Sjeremylt CeedQFunction dqfT, CeedOperator *op) { 46d7b241e6Sjeremylt int ierr; 47d7b241e6Sjeremylt 485fe0d4faSjeremylt if (!ceed->OperatorCreate) { 495fe0d4faSjeremylt Ceed delegate; 50aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 515fe0d4faSjeremylt 525fe0d4faSjeremylt if (!delegate) 53c042f62fSJeremy L Thompson // LCOV_EXCL_START 545fe0d4faSjeremylt return CeedError(ceed, 1, "Backend does not support OperatorCreate"); 55c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 565fe0d4faSjeremylt 575fe0d4faSjeremylt ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr); 585fe0d4faSjeremylt return 0; 595fe0d4faSjeremylt } 605fe0d4faSjeremylt 61d7b241e6Sjeremylt ierr = CeedCalloc(1,op); CeedChk(ierr); 62d7b241e6Sjeremylt (*op)->ceed = ceed; 63d7b241e6Sjeremylt ceed->refcount++; 64d7b241e6Sjeremylt (*op)->refcount = 1; 65442e7f0bSjeremylt if (qf == CEED_QFUNCTION_NONE) 66442e7f0bSjeremylt // LCOV_EXCL_START 67442e7f0bSjeremylt return CeedError(ceed, 1, "Operator must have a valid QFunction."); 68442e7f0bSjeremylt // LCOV_EXCL_STOP 69d7b241e6Sjeremylt (*op)->qf = qf; 70d7b241e6Sjeremylt qf->refcount++; 71442e7f0bSjeremylt if (dqf && dqf != CEED_QFUNCTION_NONE) { 72d7b241e6Sjeremylt (*op)->dqf = dqf; 73442e7f0bSjeremylt dqf->refcount++; 74442e7f0bSjeremylt } 75442e7f0bSjeremylt if (dqfT && dqfT != CEED_QFUNCTION_NONE) { 76d7b241e6Sjeremylt (*op)->dqfT = dqfT; 77442e7f0bSjeremylt dqfT->refcount++; 78442e7f0bSjeremylt } 79fe2413ffSjeremylt ierr = CeedCalloc(16, &(*op)->inputfields); CeedChk(ierr); 80fe2413ffSjeremylt ierr = CeedCalloc(16, &(*op)->outputfields); CeedChk(ierr); 81d7b241e6Sjeremylt ierr = ceed->OperatorCreate(*op); CeedChk(ierr); 82d7b241e6Sjeremylt return 0; 83d7b241e6Sjeremylt } 84d7b241e6Sjeremylt 85d7b241e6Sjeremylt /** 8652d6035fSJeremy L Thompson @brief Create an operator that composes the action of several operators 8752d6035fSJeremy L Thompson 8852d6035fSJeremy L Thompson @param ceed A Ceed object where the CeedOperator will be created 8952d6035fSJeremy L Thompson @param[out] op Address of the variable where the newly created 9052d6035fSJeremy L Thompson Composite CeedOperator will be stored 9152d6035fSJeremy L Thompson 9252d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 9352d6035fSJeremy L Thompson 9452d6035fSJeremy L Thompson @ref Basic 9552d6035fSJeremy L Thompson */ 9652d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) { 9752d6035fSJeremy L Thompson int ierr; 9852d6035fSJeremy L Thompson 9952d6035fSJeremy L Thompson if (!ceed->CompositeOperatorCreate) { 10052d6035fSJeremy L Thompson Ceed delegate; 101aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 10252d6035fSJeremy L Thompson 10352d6035fSJeremy L Thompson if (!delegate) 104c042f62fSJeremy L Thompson // LCOV_EXCL_START 1051d102b48SJeremy L Thompson return CeedError(ceed, 1, "Backend does not support " 1061d102b48SJeremy L Thompson "CompositeOperatorCreate"); 107c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 10852d6035fSJeremy L Thompson 10952d6035fSJeremy L Thompson ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr); 11052d6035fSJeremy L Thompson return 0; 11152d6035fSJeremy L Thompson } 11252d6035fSJeremy L Thompson 11352d6035fSJeremy L Thompson ierr = CeedCalloc(1,op); CeedChk(ierr); 11452d6035fSJeremy L Thompson (*op)->ceed = ceed; 11552d6035fSJeremy L Thompson ceed->refcount++; 11652d6035fSJeremy L Thompson (*op)->composite = true; 11752d6035fSJeremy L Thompson ierr = CeedCalloc(16, &(*op)->suboperators); CeedChk(ierr); 11852d6035fSJeremy L Thompson ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr); 11952d6035fSJeremy L Thompson return 0; 12052d6035fSJeremy L Thompson } 12152d6035fSJeremy L Thompson 12252d6035fSJeremy L Thompson /** 123b11c1e72Sjeremylt @brief Provide a field to a CeedOperator for use by its CeedQFunction 124d7b241e6Sjeremylt 125d7b241e6Sjeremylt This function is used to specify both active and passive fields to a 126d7b241e6Sjeremylt CeedOperator. For passive fields, a vector @arg v must be provided. Passive 127d7b241e6Sjeremylt fields can inputs or outputs (updated in-place when operator is applied). 128d7b241e6Sjeremylt 129d7b241e6Sjeremylt Active fields must be specified using this function, but their data (in a 130d7b241e6Sjeremylt CeedVector) is passed in CeedOperatorApply(). There can be at most one active 131d7b241e6Sjeremylt input and at most one active output. 132d7b241e6Sjeremylt 1338c91a0c9SJeremy L Thompson @param op CeedOperator on which to provide the field 1348795c945Sjeremylt @param fieldname Name of the field (to be matched with the name used by 1358795c945Sjeremylt CeedQFunction) 136b11c1e72Sjeremylt @param r CeedElemRestriction 137b0e29e78Sjeremylt @param lmode CeedTransposeMode which specifies the ordering of the 138b0e29e78Sjeremylt components of the l-vector used by this CeedOperatorField, 139b0e29e78Sjeremylt CEED_NOTRANSPOSE indicates the component is the 140b0e29e78Sjeremylt outermost index and CEED_TRANSPOSE indicates the component 141b0e29e78Sjeremylt is the innermost index in ordering of the l-vector 142783c99b3SValeria Barra @param b CeedBasis in which the field resides or CEED_BASIS_COLLOCATED 143b11c1e72Sjeremylt if collocated with quadrature points 144b11c1e72Sjeremylt @param v CeedVector to be used by CeedOperator or CEED_VECTOR_ACTIVE 145b11c1e72Sjeremylt if field is active or CEED_VECTOR_NONE if using 1468c91a0c9SJeremy L Thompson CEED_EVAL_WEIGHT in the QFunction 147b11c1e72Sjeremylt 148b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 149dfdf5a53Sjeremylt 150dfdf5a53Sjeremylt @ref Basic 151b11c1e72Sjeremylt **/ 152d7b241e6Sjeremylt int CeedOperatorSetField(CeedOperator op, const char *fieldname, 1534dccadb6Sjeremylt CeedElemRestriction r, CeedTransposeMode lmode, 1544dccadb6Sjeremylt CeedBasis b, CeedVector v) { 155d7b241e6Sjeremylt int ierr; 15652d6035fSJeremy L Thompson if (op->composite) 157c042f62fSJeremy L Thompson // LCOV_EXCL_START 15852d6035fSJeremy L Thompson return CeedError(op->ceed, 1, "Cannot add field to composite operator."); 159c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1608b067b84SJed Brown if (!r) 161c042f62fSJeremy L Thompson // LCOV_EXCL_START 162c042f62fSJeremy L Thompson return CeedError(op->ceed, 1, 163c042f62fSJeremy L Thompson "ElemRestriction r for field \"%s\" must be non-NULL.", 164c042f62fSJeremy L Thompson fieldname); 165c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1668b067b84SJed Brown if (!b) 167c042f62fSJeremy L Thompson // LCOV_EXCL_START 168c042f62fSJeremy L Thompson return CeedError(op->ceed, 1, "Basis b for field \"%s\" must be non-NULL.", 169c042f62fSJeremy L Thompson fieldname); 170c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1718b067b84SJed Brown if (!v) 172c042f62fSJeremy L Thompson // LCOV_EXCL_START 173c042f62fSJeremy L Thompson return CeedError(op->ceed, 1, "Vector v for field \"%s\" must be non-NULL.", 174c042f62fSJeremy L Thompson fieldname); 175c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 17652d6035fSJeremy L Thompson 177d7b241e6Sjeremylt CeedInt numelements; 178d7b241e6Sjeremylt ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr); 1792cb0afc5Sjeremylt if (op->hasrestriction && op->numelements != numelements) 180c042f62fSJeremy L Thompson // LCOV_EXCL_START 181d7b241e6Sjeremylt return CeedError(op->ceed, 1, 1821d102b48SJeremy L Thompson "ElemRestriction with %d elements incompatible with prior " 1831d102b48SJeremy L Thompson "%d elements", numelements, op->numelements); 184c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 185d7b241e6Sjeremylt op->numelements = numelements; 1862cb0afc5Sjeremylt op->hasrestriction = true; // Restriction set, but numelements may be 0 187d7b241e6Sjeremylt 188783c99b3SValeria Barra if (b != CEED_BASIS_COLLOCATED) { 189d7b241e6Sjeremylt CeedInt numqpoints; 190d7b241e6Sjeremylt ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr); 191d7b241e6Sjeremylt if (op->numqpoints && op->numqpoints != numqpoints) 192c042f62fSJeremy L Thompson // LCOV_EXCL_START 1931d102b48SJeremy L Thompson return CeedError(op->ceed, 1, "Basis with %d quadrature points " 1941d102b48SJeremy L Thompson "incompatible with prior %d points", numqpoints, 1951d102b48SJeremy L Thompson op->numqpoints); 196c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 197d7b241e6Sjeremylt op->numqpoints = numqpoints; 198d7b241e6Sjeremylt } 199d1bcdac9Sjeremylt CeedOperatorField *ofield; 200d7b241e6Sjeremylt for (CeedInt i=0; i<op->qf->numinputfields; i++) { 201fe2413ffSjeremylt if (!strcmp(fieldname, (*op->qf->inputfields[i]).fieldname)) { 202d7b241e6Sjeremylt ofield = &op->inputfields[i]; 203d7b241e6Sjeremylt goto found; 204d7b241e6Sjeremylt } 205d7b241e6Sjeremylt } 206d7b241e6Sjeremylt for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 207fe2413ffSjeremylt if (!strcmp(fieldname, (*op->qf->outputfields[i]).fieldname)) { 208d7b241e6Sjeremylt ofield = &op->outputfields[i]; 209d7b241e6Sjeremylt goto found; 210d7b241e6Sjeremylt } 211d7b241e6Sjeremylt } 212c042f62fSJeremy L Thompson // LCOV_EXCL_START 213d7b241e6Sjeremylt return CeedError(op->ceed, 1, "QFunction has no knowledge of field '%s'", 214d7b241e6Sjeremylt fieldname); 215c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 216d7b241e6Sjeremylt found: 217fe2413ffSjeremylt ierr = CeedCalloc(1, ofield); CeedChk(ierr); 218fe2413ffSjeremylt (*ofield)->Erestrict = r; 21971352a93Sjeremylt r->refcount += 1; 220fe2413ffSjeremylt (*ofield)->lmode = lmode; 221fe2413ffSjeremylt (*ofield)->basis = b; 22271352a93Sjeremylt if (b != CEED_BASIS_COLLOCATED) 22371352a93Sjeremylt b->refcount += 1; 224fe2413ffSjeremylt (*ofield)->vec = v; 22571352a93Sjeremylt if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) 22671352a93Sjeremylt v->refcount += 1; 227d7b241e6Sjeremylt op->nfields += 1; 228d7b241e6Sjeremylt return 0; 229d7b241e6Sjeremylt } 230d7b241e6Sjeremylt 231d7b241e6Sjeremylt /** 23252d6035fSJeremy L Thompson @brief Add a sub-operator to a composite CeedOperator 233288c0443SJeremy L Thompson 234288c0443SJeremy L Thompson @param[out] compositeop Address of the composite CeedOperator 235288c0443SJeremy L Thompson @param subop Address of the sub-operator CeedOperator 23652d6035fSJeremy L Thompson 23752d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 23852d6035fSJeremy L Thompson 23952d6035fSJeremy L Thompson @ref Basic 24052d6035fSJeremy L Thompson */ 241692c2638Sjeremylt int CeedCompositeOperatorAddSub(CeedOperator compositeop, CeedOperator subop) { 24252d6035fSJeremy L Thompson if (!compositeop->composite) 243c042f62fSJeremy L Thompson // LCOV_EXCL_START 2441d102b48SJeremy L Thompson return CeedError(compositeop->ceed, 1, "CeedOperator is not a composite " 2451d102b48SJeremy L Thompson "operator"); 246c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 24752d6035fSJeremy L Thompson 24852d6035fSJeremy L Thompson if (compositeop->numsub == CEED_COMPOSITE_MAX) 249c042f62fSJeremy L Thompson // LCOV_EXCL_START 2501d102b48SJeremy L Thompson return CeedError(compositeop->ceed, 1, "Cannot add additional suboperators"); 251c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 25252d6035fSJeremy L Thompson 25352d6035fSJeremy L Thompson compositeop->suboperators[compositeop->numsub] = subop; 25452d6035fSJeremy L Thompson subop->refcount++; 25552d6035fSJeremy L Thompson compositeop->numsub++; 25652d6035fSJeremy L Thompson return 0; 25752d6035fSJeremy L Thompson } 25852d6035fSJeremy L Thompson 25952d6035fSJeremy L Thompson /** 2601d102b48SJeremy L Thompson @brief Assemble a linear CeedQFunction associated with a CeedOperator 2611d102b48SJeremy L Thompson 2621d102b48SJeremy L Thompson This returns a CeedVector containing a matrix at each quadrature point 2631d102b48SJeremy L Thompson providing the action of the CeedQFunction associated with the CeedOperator. 2641d102b48SJeremy L Thompson The vector 'assembled' is of shape 2651d102b48SJeremy L Thompson [num_elements, num_input_fields, num_output_fields, num_quad_points] 2661d102b48SJeremy L Thompson and contains column-major matrices representing the action of the 2671d102b48SJeremy L Thompson CeedQFunction for a corresponding quadrature point on an element. Inputs and 2681d102b48SJeremy L Thompson outputs are in the order provided by the user when adding CeedOperator fields. 2691d102b48SJeremy L Thompson For example, a QFunction with inputs 'u' and 'gradu' and outputs 'gradv' and 2701d102b48SJeremy L Thompson 'v', provided in that order, would result in an assembled QFunction that 2711d102b48SJeremy L Thompson consists of (1 + dim) x (dim + 1) matrices at each quadrature point acting 2721d102b48SJeremy L Thompson on the input [u, du_0, du_1] and producing the output [dv_0, dv_1, v]. 2731d102b48SJeremy L Thompson 2741d102b48SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 2751d102b48SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedQFunction at 2761d102b48SJeremy L Thompson quadrature points 2771d102b48SJeremy L Thompson @param[out] rstr CeedElemRestriction for CeedVector containing assembled 2781d102b48SJeremy L Thompson CeedQFunction 2791d102b48SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 2801d102b48SJeremy L Thompson CEED_REQUEST_IMMEDIATE 2811d102b48SJeremy L Thompson 2821d102b48SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 2831d102b48SJeremy L Thompson 284b7ec98d8SJeremy L Thompson @ref Basic 2851d102b48SJeremy L Thompson **/ 2861d102b48SJeremy L Thompson int CeedOperatorAssembleLinearQFunction(CeedOperator op, CeedVector *assembled, 2877f823360Sjeremylt CeedElemRestriction *rstr, 2887f823360Sjeremylt CeedRequest *request) { 2891d102b48SJeremy L Thompson int ierr; 2901d102b48SJeremy L Thompson Ceed ceed = op->ceed; 2911d102b48SJeremy L Thompson CeedQFunction qf = op->qf; 2921d102b48SJeremy L Thompson 2931d102b48SJeremy L Thompson if (op->composite) { 294138d4072Sjeremylt // LCOV_EXCL_START 2951d102b48SJeremy L Thompson return CeedError(ceed, 1, "Cannot assemble QFunction for composite operator"); 296138d4072Sjeremylt // LCOV_EXCL_STOP 2971d102b48SJeremy L Thompson } else { 2981d102b48SJeremy L Thompson if (op->nfields == 0) 299138d4072Sjeremylt // LCOV_EXCL_START 3001d102b48SJeremy L Thompson return CeedError(ceed, 1, "No operator fields set"); 301138d4072Sjeremylt // LCOV_EXCL_STOP 3021d102b48SJeremy L Thompson if (op->nfields < qf->numinputfields + qf->numoutputfields) 303138d4072Sjeremylt // LCOV_EXCL_START 3041d102b48SJeremy L Thompson return CeedError( ceed, 1, "Not all operator fields set"); 305138d4072Sjeremylt // LCOV_EXCL_STOP 3062cb0afc5Sjeremylt if (!op->hasrestriction) 307138d4072Sjeremylt // LCOV_EXCL_START 3081d102b48SJeremy L Thompson return CeedError(ceed, 1, "At least one restriction required"); 309138d4072Sjeremylt // LCOV_EXCL_STOP 3101d102b48SJeremy L Thompson if (op->numqpoints == 0) 311138d4072Sjeremylt // LCOV_EXCL_START 3121d102b48SJeremy L Thompson return CeedError(ceed, 1, "At least one non-collocated basis required"); 313138d4072Sjeremylt // LCOV_EXCL_STOP 3141d102b48SJeremy L Thompson } 3151d102b48SJeremy L Thompson ierr = op->AssembleLinearQFunction(op, assembled, rstr, request); 3161d102b48SJeremy L Thompson CeedChk(ierr); 3171d102b48SJeremy L Thompson return 0; 3181d102b48SJeremy L Thompson } 3191d102b48SJeremy L Thompson 3201d102b48SJeremy L Thompson /** 321b7ec98d8SJeremy L Thompson @brief Assemble the diagonal of a square linear Operator 322b7ec98d8SJeremy L Thompson 323b7ec98d8SJeremy L Thompson This returns a CeedVector containing the diagonal of a linear CeedOperator. 324b7ec98d8SJeremy L Thompson 325b7ec98d8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 326b7ec98d8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator diagonal 327b7ec98d8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 328b7ec98d8SJeremy L Thompson CEED_REQUEST_IMMEDIATE 329b7ec98d8SJeremy L Thompson 330b7ec98d8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 331b7ec98d8SJeremy L Thompson 332b7ec98d8SJeremy L Thompson @ref Basic 333b7ec98d8SJeremy L Thompson **/ 3347f823360Sjeremylt int CeedOperatorAssembleLinearDiagonal(CeedOperator op, CeedVector *assembled, 3357f823360Sjeremylt CeedRequest *request) { 336b7ec98d8SJeremy L Thompson int ierr; 337b7ec98d8SJeremy L Thompson Ceed ceed = op->ceed; 338b7ec98d8SJeremy L Thompson CeedQFunction qf = op->qf; 339b7ec98d8SJeremy L Thompson 340b7ec98d8SJeremy L Thompson if (op->composite) { 341b7ec98d8SJeremy L Thompson // LCOV_EXCL_START 342b7ec98d8SJeremy L Thompson return CeedError(ceed, 1, "Cannot assemble QFunction for composite operator"); 343b7ec98d8SJeremy L Thompson // LCOV_EXCL_STOP 344b7ec98d8SJeremy L Thompson } else { 345b7ec98d8SJeremy L Thompson if (op->nfields == 0) 346b7ec98d8SJeremy L Thompson // LCOV_EXCL_START 347b7ec98d8SJeremy L Thompson return CeedError(ceed, 1, "No operator fields set"); 348b7ec98d8SJeremy L Thompson // LCOV_EXCL_STOP 349b7ec98d8SJeremy L Thompson if (op->nfields < qf->numinputfields + qf->numoutputfields) 350b7ec98d8SJeremy L Thompson // LCOV_EXCL_START 351b7ec98d8SJeremy L Thompson return CeedError( ceed, 1, "Not all operator fields set"); 352b7ec98d8SJeremy L Thompson // LCOV_EXCL_STOP 3532cb0afc5Sjeremylt if (!op->hasrestriction) 354b7ec98d8SJeremy L Thompson // LCOV_EXCL_START 355b7ec98d8SJeremy L Thompson return CeedError(ceed, 1, "At least one restriction required"); 356b7ec98d8SJeremy L Thompson // LCOV_EXCL_STOP 357b7ec98d8SJeremy L Thompson if (op->numqpoints == 0) 358b7ec98d8SJeremy L Thompson // LCOV_EXCL_START 359b7ec98d8SJeremy L Thompson return CeedError(ceed, 1, "At least one non-collocated basis required"); 360b7ec98d8SJeremy L Thompson // LCOV_EXCL_STOP 361b7ec98d8SJeremy L Thompson } 362b7ec98d8SJeremy L Thompson 363b7ec98d8SJeremy L Thompson // Use backend version, if available 364b7ec98d8SJeremy L Thompson if (op->AssembleLinearDiagonal) { 365b7ec98d8SJeremy L Thompson ierr = op->AssembleLinearDiagonal(op, assembled, request); CeedChk(ierr); 366b7ec98d8SJeremy L Thompson return 0; 367b7ec98d8SJeremy L Thompson } 368b7ec98d8SJeremy L Thompson 369b7ec98d8SJeremy L Thompson // Assemble QFunction 370b7ec98d8SJeremy L Thompson CeedVector assembledqf; 371b7ec98d8SJeremy L Thompson CeedElemRestriction rstr; 372b7ec98d8SJeremy L Thompson ierr = CeedOperatorAssembleLinearQFunction(op, &assembledqf, &rstr, request); 373b7ec98d8SJeremy L Thompson CeedChk(ierr); 374b7ec98d8SJeremy L Thompson ierr = CeedElemRestrictionDestroy(&rstr); CeedChk(ierr); 375b7ec98d8SJeremy L Thompson 376b7ec98d8SJeremy L Thompson // Determine active input basis 377112e3f70Sjeremylt CeedInt numemodein = 0, ncomp, dim = 1; 378b7ec98d8SJeremy L Thompson CeedEvalMode *emodein = NULL; 379112e3f70Sjeremylt CeedBasis basisin = NULL; 380112e3f70Sjeremylt CeedElemRestriction rstrin = NULL; 381b7ec98d8SJeremy L Thompson for (CeedInt i=0; i<qf->numinputfields; i++) 382b7ec98d8SJeremy L Thompson if (op->inputfields[i]->vec == CEED_VECTOR_ACTIVE) { 383b7ec98d8SJeremy L Thompson ierr = CeedOperatorFieldGetBasis(op->inputfields[i], &basisin); 384b7ec98d8SJeremy L Thompson CeedChk(ierr); 385b7ec98d8SJeremy L Thompson ierr = CeedBasisGetNumComponents(basisin, &ncomp); CeedChk(ierr); 386b7ec98d8SJeremy L Thompson ierr = CeedBasisGetDimension(basisin, &dim); CeedChk(ierr); 387b7ec98d8SJeremy L Thompson ierr = CeedOperatorFieldGetElemRestriction(op->inputfields[i], &rstrin); 388b7ec98d8SJeremy L Thompson CeedChk(ierr); 389b7ec98d8SJeremy L Thompson CeedEvalMode emode; 390b7ec98d8SJeremy L Thompson ierr = CeedQFunctionFieldGetEvalMode(qf->inputfields[i], &emode); 391b7ec98d8SJeremy L Thompson CeedChk(ierr); 392b7ec98d8SJeremy L Thompson switch (emode) { 393b7ec98d8SJeremy L Thompson case CEED_EVAL_NONE: 394b7ec98d8SJeremy L Thompson case CEED_EVAL_INTERP: 395b7ec98d8SJeremy L Thompson ierr = CeedRealloc(numemodein + 1, &emodein); CeedChk(ierr); 396b7ec98d8SJeremy L Thompson emodein[numemodein] = emode; 397b7ec98d8SJeremy L Thompson numemodein += 1; 398b7ec98d8SJeremy L Thompson break; 399b7ec98d8SJeremy L Thompson case CEED_EVAL_GRAD: 400b7ec98d8SJeremy L Thompson ierr = CeedRealloc(numemodein + dim, &emodein); CeedChk(ierr); 401b7ec98d8SJeremy L Thompson for (CeedInt d=0; d<dim; d++) 402b7ec98d8SJeremy L Thompson emodein[numemodein+d] = emode; 403b7ec98d8SJeremy L Thompson numemodein += dim; 404b7ec98d8SJeremy L Thompson break; 405b7ec98d8SJeremy L Thompson case CEED_EVAL_WEIGHT: 406b7ec98d8SJeremy L Thompson case CEED_EVAL_DIV: 407b7ec98d8SJeremy L Thompson case CEED_EVAL_CURL: 408b7ec98d8SJeremy L Thompson break; // Caught by QF Assembly 409b7ec98d8SJeremy L Thompson } 410b7ec98d8SJeremy L Thompson } 411b7ec98d8SJeremy L Thompson 412b7ec98d8SJeremy L Thompson // Determine active output basis 413b7ec98d8SJeremy L Thompson CeedInt numemodeout = 0; 414b7ec98d8SJeremy L Thompson CeedEvalMode *emodeout = NULL; 415112e3f70Sjeremylt CeedBasis basisout = NULL; 416112e3f70Sjeremylt CeedElemRestriction rstrout = NULL; 417112e3f70Sjeremylt CeedTransposeMode lmodeout = CEED_NOTRANSPOSE; 418b7ec98d8SJeremy L Thompson for (CeedInt i=0; i<qf->numoutputfields; i++) 419b7ec98d8SJeremy L Thompson if (op->outputfields[i]->vec == CEED_VECTOR_ACTIVE) { 420b7ec98d8SJeremy L Thompson ierr = CeedOperatorFieldGetBasis(op->outputfields[i], &basisout); 421b7ec98d8SJeremy L Thompson CeedChk(ierr); 422b7ec98d8SJeremy L Thompson ierr = CeedOperatorFieldGetElemRestriction(op->outputfields[i], &rstrout); 423b7ec98d8SJeremy L Thompson CeedChk(ierr); 424b7ec98d8SJeremy L Thompson ierr = CeedOperatorFieldGetLMode(op->outputfields[i], &lmodeout); 425b7ec98d8SJeremy L Thompson CeedChk(ierr); 426b7ec98d8SJeremy L Thompson CeedEvalMode emode; 427b7ec98d8SJeremy L Thompson ierr = CeedQFunctionFieldGetEvalMode(qf->outputfields[i], &emode); 428b7ec98d8SJeremy L Thompson CeedChk(ierr); 429b7ec98d8SJeremy L Thompson switch (emode) { 430b7ec98d8SJeremy L Thompson case CEED_EVAL_NONE: 431b7ec98d8SJeremy L Thompson case CEED_EVAL_INTERP: 432b7ec98d8SJeremy L Thompson ierr = CeedRealloc(numemodeout + 1, &emodeout); CeedChk(ierr); 433b7ec98d8SJeremy L Thompson emodeout[numemodeout] = emode; 434b7ec98d8SJeremy L Thompson numemodeout += 1; 435b7ec98d8SJeremy L Thompson break; 436b7ec98d8SJeremy L Thompson case CEED_EVAL_GRAD: 437b7ec98d8SJeremy L Thompson ierr = CeedRealloc(numemodeout + dim, &emodeout); CeedChk(ierr); 438b7ec98d8SJeremy L Thompson for (CeedInt d=0; d<dim; d++) 439b7ec98d8SJeremy L Thompson emodeout[numemodeout+d] = emode; 440b7ec98d8SJeremy L Thompson numemodeout += dim; 441b7ec98d8SJeremy L Thompson break; 442b7ec98d8SJeremy L Thompson case CEED_EVAL_WEIGHT: 443b7ec98d8SJeremy L Thompson case CEED_EVAL_DIV: 444b7ec98d8SJeremy L Thompson case CEED_EVAL_CURL: 445b7ec98d8SJeremy L Thompson break; // Caught by QF Assembly 446b7ec98d8SJeremy L Thompson } 447b7ec98d8SJeremy L Thompson } 448b7ec98d8SJeremy L Thompson 449b7ec98d8SJeremy L Thompson // Create diagonal vector 450b7ec98d8SJeremy L Thompson CeedVector elemdiag; 451b7ec98d8SJeremy L Thompson ierr = CeedElemRestrictionCreateVector(rstrin, assembled, &elemdiag); 452b7ec98d8SJeremy L Thompson CeedChk(ierr); 453b7ec98d8SJeremy L Thompson 454b7ec98d8SJeremy L Thompson // Assemble element operator diagonals 455b7ec98d8SJeremy L Thompson CeedScalar *elemdiagarray, *assembledqfarray; 456b7ec98d8SJeremy L Thompson ierr = CeedVectorSetValue(elemdiag, 0.0); CeedChk(ierr); 457b7ec98d8SJeremy L Thompson ierr = CeedVectorGetArray(elemdiag, CEED_MEM_HOST, &elemdiagarray); 458b7ec98d8SJeremy L Thompson CeedChk(ierr); 459b7ec98d8SJeremy L Thompson ierr = CeedVectorGetArray(assembledqf, CEED_MEM_HOST, &assembledqfarray); 460b7ec98d8SJeremy L Thompson CeedChk(ierr); 461b7ec98d8SJeremy L Thompson CeedInt nelem, nnodes, nqpts; 462b7ec98d8SJeremy L Thompson ierr = CeedElemRestrictionGetNumElements(rstrin, &nelem); CeedChk(ierr); 463b7ec98d8SJeremy L Thompson ierr = CeedBasisGetNumNodes(basisin, &nnodes); CeedChk(ierr); 464b7ec98d8SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisin, &nqpts); CeedChk(ierr); 465b7ec98d8SJeremy L Thompson // Compute the diagonal of B^T D B 466b7ec98d8SJeremy L Thompson // Each node, qpt pair 467b7ec98d8SJeremy L Thompson for (CeedInt n=0; n<nnodes; n++) 468b7ec98d8SJeremy L Thompson for (CeedInt q=0; q<nqpts; q++) { 469b7ec98d8SJeremy L Thompson CeedInt dout = -1; 470b7ec98d8SJeremy L Thompson // Each basis eval mode pair 471b7ec98d8SJeremy L Thompson for (CeedInt eout=0; eout<numemodeout; eout++) { 472b7ec98d8SJeremy L Thompson CeedScalar bt = 1.0; 473b7ec98d8SJeremy L Thompson if (emodeout[eout] == CEED_EVAL_GRAD) 474b7ec98d8SJeremy L Thompson dout += 1; 475b7ec98d8SJeremy L Thompson ierr = CeedBasisGetValue(basisout, emodeout[eout], q, n, dout, &bt); 476b7ec98d8SJeremy L Thompson CeedChk(ierr); 477b7ec98d8SJeremy L Thompson CeedInt din = -1; 478b7ec98d8SJeremy L Thompson for (CeedInt ein=0; ein<numemodein; ein++) { 479b7ec98d8SJeremy L Thompson CeedScalar b = 0.0; 480b7ec98d8SJeremy L Thompson if (emodein[ein] == CEED_EVAL_GRAD) 481b7ec98d8SJeremy L Thompson din += 1; 482b7ec98d8SJeremy L Thompson ierr = CeedBasisGetValue(basisin, emodein[ein], q, n, din, &b); 483b7ec98d8SJeremy L Thompson CeedChk(ierr); 484b7ec98d8SJeremy L Thompson // Each element and component 485b7ec98d8SJeremy L Thompson for (CeedInt e=0; e<nelem; e++) 486b7ec98d8SJeremy L Thompson for (CeedInt cout=0; cout<ncomp; cout++) { 487b7ec98d8SJeremy L Thompson CeedScalar db = 0.0; 488b7ec98d8SJeremy L Thompson for (CeedInt cin=0; cin<ncomp; cin++) 489b7ec98d8SJeremy L Thompson db += assembledqfarray[((((e*numemodein+ein)*ncomp+cin)* 490b7ec98d8SJeremy L Thompson numemodeout+eout)*ncomp+cout)*nqpts+q]*b; 491b7ec98d8SJeremy L Thompson elemdiagarray[(e*ncomp+cout)*nnodes+n] += bt * db; 492b7ec98d8SJeremy L Thompson } 493b7ec98d8SJeremy L Thompson } 494b7ec98d8SJeremy L Thompson } 495b7ec98d8SJeremy L Thompson } 496b7ec98d8SJeremy L Thompson 497b7ec98d8SJeremy L Thompson ierr = CeedVectorRestoreArray(elemdiag, &elemdiagarray); CeedChk(ierr); 498b7ec98d8SJeremy L Thompson ierr = CeedVectorRestoreArray(assembledqf, &assembledqfarray); CeedChk(ierr); 499b7ec98d8SJeremy L Thompson 500b7ec98d8SJeremy L Thompson // Assemble local operator diagonal 501b7ec98d8SJeremy L Thompson ierr = CeedVectorSetValue(*assembled, 0.0); CeedChk(ierr); 502b7ec98d8SJeremy L Thompson ierr = CeedElemRestrictionApply(rstrout, CEED_TRANSPOSE, lmodeout, elemdiag, 503b7ec98d8SJeremy L Thompson *assembled, request); CeedChk(ierr); 504b7ec98d8SJeremy L Thompson 505b7ec98d8SJeremy L Thompson // Cleanup 506b7ec98d8SJeremy L Thompson ierr = CeedVectorDestroy(&assembledqf); CeedChk(ierr); 507b7ec98d8SJeremy L Thompson ierr = CeedVectorDestroy(&elemdiag); CeedChk(ierr); 508b7ec98d8SJeremy L Thompson ierr = CeedFree(&emodein); CeedChk(ierr); 509b7ec98d8SJeremy L Thompson ierr = CeedFree(&emodeout); CeedChk(ierr); 510b7ec98d8SJeremy L Thompson 511b7ec98d8SJeremy L Thompson return 0; 512b7ec98d8SJeremy L Thompson } 513b7ec98d8SJeremy L Thompson 514b7ec98d8SJeremy L Thompson /** 515b11c1e72Sjeremylt @brief Apply CeedOperator to a vector 516d7b241e6Sjeremylt 517d7b241e6Sjeremylt This computes the action of the operator on the specified (active) input, 518d7b241e6Sjeremylt yielding its (active) output. All inputs and outputs must be specified using 519d7b241e6Sjeremylt CeedOperatorSetField(). 520d7b241e6Sjeremylt 521d7b241e6Sjeremylt @param op CeedOperator to apply 522b11c1e72Sjeremylt @param[in] in CeedVector containing input state or NULL if there are no 523b11c1e72Sjeremylt active inputs 524b11c1e72Sjeremylt @param[out] out CeedVector to store result of applying operator (must be 525d7b241e6Sjeremylt distinct from @a in) or NULL if there are no active outputs 526d7b241e6Sjeremylt @param request Address of CeedRequest for non-blocking completion, else 527d7b241e6Sjeremylt CEED_REQUEST_IMMEDIATE 528b11c1e72Sjeremylt 529b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 530dfdf5a53Sjeremylt 531dfdf5a53Sjeremylt @ref Basic 532b11c1e72Sjeremylt **/ 533692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out, 534692c2638Sjeremylt CeedRequest *request) { 535d7b241e6Sjeremylt int ierr; 536d7b241e6Sjeremylt Ceed ceed = op->ceed; 537d7b241e6Sjeremylt CeedQFunction qf = op->qf; 538d7b241e6Sjeremylt 53952d6035fSJeremy L Thompson if (op->composite) { 540c042f62fSJeremy L Thompson if (!op->numsub) 541c042f62fSJeremy L Thompson // LCOV_EXCL_START 542c042f62fSJeremy L Thompson return CeedError(ceed, 1, "No suboperators set"); 543c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 54452d6035fSJeremy L Thompson } else { 545c042f62fSJeremy L Thompson if (op->nfields == 0) 546c042f62fSJeremy L Thompson // LCOV_EXCL_START 547c042f62fSJeremy L Thompson return CeedError(ceed, 1, "No operator fields set"); 548c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 549c042f62fSJeremy L Thompson if (op->nfields < qf->numinputfields + qf->numoutputfields) 550c042f62fSJeremy L Thompson // LCOV_EXCL_START 551c042f62fSJeremy L Thompson return CeedError(ceed, 1, "Not all operator fields set"); 552c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 5532cb0afc5Sjeremylt if (!op->hasrestriction) 554c042f62fSJeremy L Thompson // LCOV_EXCL_START 555c042f62fSJeremy L Thompson return CeedError(ceed, 1,"At least one restriction required"); 556c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 557c042f62fSJeremy L Thompson if (op->numqpoints == 0) 558c042f62fSJeremy L Thompson // LCOV_EXCL_START 559c042f62fSJeremy L Thompson return CeedError(ceed, 1,"At least one non-collocated basis required"); 560c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 56152d6035fSJeremy L Thompson } 5621d7d2407SJeremy L Thompson if (op->numelements || op->composite) { 563e97ff134Sjeremylt ierr = op->Apply(op, in != CEED_VECTOR_NONE ? in : NULL, 564e97ff134Sjeremylt out != CEED_VECTOR_NONE ? out : NULL, request); 565e97ff134Sjeremylt CeedChk(ierr); 5661d7d2407SJeremy L Thompson } 567d7b241e6Sjeremylt return 0; 568d7b241e6Sjeremylt } 569d7b241e6Sjeremylt 570d7b241e6Sjeremylt /** 5714ce2993fSjeremylt @brief Get the Ceed associated with a CeedOperator 5724ce2993fSjeremylt 5734ce2993fSjeremylt @param op CeedOperator 5744ce2993fSjeremylt @param[out] ceed Variable to store Ceed 5754ce2993fSjeremylt 5764ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 5774ce2993fSjeremylt 57823617272Sjeremylt @ref Advanced 5794ce2993fSjeremylt **/ 5804ce2993fSjeremylt 5814ce2993fSjeremylt int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 5824ce2993fSjeremylt *ceed = op->ceed; 5834ce2993fSjeremylt return 0; 5844ce2993fSjeremylt } 5854ce2993fSjeremylt 5864ce2993fSjeremylt /** 5874ce2993fSjeremylt @brief Get the number of elements associated with a CeedOperator 5884ce2993fSjeremylt 5894ce2993fSjeremylt @param op CeedOperator 5904ce2993fSjeremylt @param[out] numelem Variable to store number of elements 5914ce2993fSjeremylt 5924ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 5934ce2993fSjeremylt 59423617272Sjeremylt @ref Advanced 5954ce2993fSjeremylt **/ 5964ce2993fSjeremylt 5974ce2993fSjeremylt int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) { 59852d6035fSJeremy L Thompson if (op->composite) 599c042f62fSJeremy L Thompson // LCOV_EXCL_START 60052d6035fSJeremy L Thompson return CeedError(op->ceed, 1, "Not defined for composite operator"); 601c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 60252d6035fSJeremy L Thompson 6034ce2993fSjeremylt *numelem = op->numelements; 6044ce2993fSjeremylt return 0; 6054ce2993fSjeremylt } 6064ce2993fSjeremylt 6074ce2993fSjeremylt /** 6084ce2993fSjeremylt @brief Get the number of quadrature points associated with a CeedOperator 6094ce2993fSjeremylt 6104ce2993fSjeremylt @param op CeedOperator 6114ce2993fSjeremylt @param[out] numqpts Variable to store vector number of quadrature points 6124ce2993fSjeremylt 6134ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 6144ce2993fSjeremylt 61523617272Sjeremylt @ref Advanced 6164ce2993fSjeremylt **/ 6174ce2993fSjeremylt 6184ce2993fSjeremylt int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) { 61952d6035fSJeremy L Thompson if (op->composite) 620c042f62fSJeremy L Thompson // LCOV_EXCL_START 62152d6035fSJeremy L Thompson return CeedError(op->ceed, 1, "Not defined for composite operator"); 622c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 62352d6035fSJeremy L Thompson 6244ce2993fSjeremylt *numqpts = op->numqpoints; 6254ce2993fSjeremylt return 0; 6264ce2993fSjeremylt } 6274ce2993fSjeremylt 6284ce2993fSjeremylt /** 6294ce2993fSjeremylt @brief Get the number of arguments associated with a CeedOperator 6304ce2993fSjeremylt 6314ce2993fSjeremylt @param op CeedOperator 6324ce2993fSjeremylt @param[out] numargs Variable to store vector number of arguments 6334ce2993fSjeremylt 6344ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 6354ce2993fSjeremylt 63623617272Sjeremylt @ref Advanced 6374ce2993fSjeremylt **/ 6384ce2993fSjeremylt 6394ce2993fSjeremylt int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) { 64052d6035fSJeremy L Thompson if (op->composite) 641c042f62fSJeremy L Thompson // LCOV_EXCL_START 64252d6035fSJeremy L Thompson return CeedError(op->ceed, 1, "Not defined for composite operators"); 643c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 644c042f62fSJeremy L Thompson 6454ce2993fSjeremylt *numargs = op->nfields; 6464ce2993fSjeremylt return 0; 6474ce2993fSjeremylt } 6484ce2993fSjeremylt 6494ce2993fSjeremylt /** 6504ce2993fSjeremylt @brief Get the setup status of a CeedOperator 6514ce2993fSjeremylt 6524ce2993fSjeremylt @param op CeedOperator 653288c0443SJeremy L Thompson @param[out] setupdone Variable to store setup status 6544ce2993fSjeremylt 6554ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 6564ce2993fSjeremylt 65723617272Sjeremylt @ref Advanced 6584ce2993fSjeremylt **/ 6594ce2993fSjeremylt 6604ce2993fSjeremylt int CeedOperatorGetSetupStatus(CeedOperator op, bool *setupdone) { 6614ce2993fSjeremylt *setupdone = op->setupdone; 6624ce2993fSjeremylt return 0; 6634ce2993fSjeremylt } 6644ce2993fSjeremylt 6654ce2993fSjeremylt /** 6664ce2993fSjeremylt @brief Get the QFunction associated with a CeedOperator 6674ce2993fSjeremylt 6684ce2993fSjeremylt @param op CeedOperator 6698c91a0c9SJeremy L Thompson @param[out] qf Variable to store QFunction 6704ce2993fSjeremylt 6714ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 6724ce2993fSjeremylt 67323617272Sjeremylt @ref Advanced 6744ce2993fSjeremylt **/ 6754ce2993fSjeremylt 6764ce2993fSjeremylt int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 67752d6035fSJeremy L Thompson if (op->composite) 678c042f62fSJeremy L Thompson // LCOV_EXCL_START 67952d6035fSJeremy L Thompson return CeedError(op->ceed, 1, "Not defined for composite operator"); 680c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 68152d6035fSJeremy L Thompson 6824ce2993fSjeremylt *qf = op->qf; 6834ce2993fSjeremylt return 0; 6844ce2993fSjeremylt } 6854ce2993fSjeremylt 6864ce2993fSjeremylt /** 68752d6035fSJeremy L Thompson @brief Get the number of suboperators associated with a CeedOperator 68852d6035fSJeremy L Thompson 68952d6035fSJeremy L Thompson @param op CeedOperator 69052d6035fSJeremy L Thompson @param[out] numsub Variable to store number of suboperators 69152d6035fSJeremy L Thompson 69252d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 69352d6035fSJeremy L Thompson 69452d6035fSJeremy L Thompson @ref Advanced 69552d6035fSJeremy L Thompson **/ 69652d6035fSJeremy L Thompson 69752d6035fSJeremy L Thompson int CeedOperatorGetNumSub(CeedOperator op, CeedInt *numsub) { 698c042f62fSJeremy L Thompson if (!op->composite) 699c042f62fSJeremy L Thompson // LCOV_EXCL_START 700c042f62fSJeremy L Thompson return CeedError(op->ceed, 1, "Not a composite operator"); 701c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 70252d6035fSJeremy L Thompson 70352d6035fSJeremy L Thompson *numsub = op->numsub; 70452d6035fSJeremy L Thompson return 0; 70552d6035fSJeremy L Thompson } 70652d6035fSJeremy L Thompson 70752d6035fSJeremy L Thompson /** 70852d6035fSJeremy L Thompson @brief Get the list of suboperators associated with a CeedOperator 70952d6035fSJeremy L Thompson 71052d6035fSJeremy L Thompson @param op CeedOperator 71152d6035fSJeremy L Thompson @param[out] suboperators Variable to store list of suboperators 71252d6035fSJeremy L Thompson 71352d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 71452d6035fSJeremy L Thompson 71552d6035fSJeremy L Thompson @ref Advanced 71652d6035fSJeremy L Thompson **/ 71752d6035fSJeremy L Thompson 71852d6035fSJeremy L Thompson int CeedOperatorGetSubList(CeedOperator op, CeedOperator **suboperators) { 719c042f62fSJeremy L Thompson if (!op->composite) 720c042f62fSJeremy L Thompson // LCOV_EXCL_START 721c042f62fSJeremy L Thompson return CeedError(op->ceed, 1, "Not a composite operator"); 722c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 72352d6035fSJeremy L Thompson 72452d6035fSJeremy L Thompson *suboperators = op->suboperators; 72552d6035fSJeremy L Thompson return 0; 72652d6035fSJeremy L Thompson } 72752d6035fSJeremy L Thompson 72852d6035fSJeremy L Thompson /** 729fe2413ffSjeremylt @brief Set the backend data of a CeedOperator 730fe2413ffSjeremylt 731fe2413ffSjeremylt @param[out] op CeedOperator 732fe2413ffSjeremylt @param data Data to set 733fe2413ffSjeremylt 734fe2413ffSjeremylt @return An error code: 0 - success, otherwise - failure 735fe2413ffSjeremylt 736fe2413ffSjeremylt @ref Advanced 737fe2413ffSjeremylt **/ 738fe2413ffSjeremylt 739fe2413ffSjeremylt int CeedOperatorSetData(CeedOperator op, void **data) { 740fe2413ffSjeremylt op->data = *data; 741fe2413ffSjeremylt return 0; 742fe2413ffSjeremylt } 743fe2413ffSjeremylt 744fe2413ffSjeremylt /** 7454ce2993fSjeremylt @brief Get the backend data of a CeedOperator 7464ce2993fSjeremylt 7474ce2993fSjeremylt @param op CeedOperator 7484ce2993fSjeremylt @param[out] data Variable to store data 7494ce2993fSjeremylt 7504ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 7514ce2993fSjeremylt 75223617272Sjeremylt @ref Advanced 7534ce2993fSjeremylt **/ 7544ce2993fSjeremylt 7554ce2993fSjeremylt int CeedOperatorGetData(CeedOperator op, void **data) { 7564ce2993fSjeremylt *data = op->data; 7574ce2993fSjeremylt return 0; 7584ce2993fSjeremylt } 7594ce2993fSjeremylt 7604ce2993fSjeremylt /** 7614ce2993fSjeremylt @brief Set the setup flag of a CeedOperator to True 7624ce2993fSjeremylt 7634ce2993fSjeremylt @param op CeedOperator 7644ce2993fSjeremylt 7654ce2993fSjeremylt @return An error code: 0 - success, otherwise - failure 7664ce2993fSjeremylt 76723617272Sjeremylt @ref Advanced 7684ce2993fSjeremylt **/ 7694ce2993fSjeremylt 7704ce2993fSjeremylt int CeedOperatorSetSetupDone(CeedOperator op) { 7714ce2993fSjeremylt op->setupdone = 1; 7724ce2993fSjeremylt return 0; 7734ce2993fSjeremylt } 7744ce2993fSjeremylt 7754ce2993fSjeremylt /** 7762ebaca42Sjeremylt @brief View a field of a CeedOperator 7772ebaca42Sjeremylt 7782ebaca42Sjeremylt @param[in] field Operator field to view 7792ebaca42Sjeremylt @param[in] fieldnumber Number of field being viewed 7802ebaca42Sjeremylt @param[in] stream Stream to view to, e.g., stdout 7812ebaca42Sjeremylt 7822ebaca42Sjeremylt @return An error code: 0 - success, otherwise - failure 7832ebaca42Sjeremylt 7842ebaca42Sjeremylt @ref Utility 7852ebaca42Sjeremylt **/ 7862ebaca42Sjeremylt static int CeedOperatorFieldView(CeedOperatorField field, 7872ebaca42Sjeremylt CeedQFunctionField qffield, 788*2da88da5Sjeremylt CeedInt fieldnumber, bool sub, bool in, 789*2da88da5Sjeremylt FILE *stream) { 7902ebaca42Sjeremylt const char* pre = sub ? " " : ""; 791*2da88da5Sjeremylt const char* inout = in ? "Input" : "Output"; 7922ebaca42Sjeremylt 793*2da88da5Sjeremylt fprintf(stream, "%s %s Field [%d]:\n" 794*2da88da5Sjeremylt "%s Name: \"%s\"\n" 795*2da88da5Sjeremylt "%s Lmode: \"%s\"\n", 796*2da88da5Sjeremylt pre, inout, fieldnumber, pre, qffield->fieldname, 7972ebaca42Sjeremylt pre, CeedTransposeModes[field->lmode]); 7982ebaca42Sjeremylt 7992ebaca42Sjeremylt if (field->basis == CEED_BASIS_COLLOCATED) 8002ebaca42Sjeremylt fprintf(stream, "%s Collocated basis\n", pre); 8012ebaca42Sjeremylt 8022ebaca42Sjeremylt if (field->vec == CEED_VECTOR_ACTIVE) 8032ebaca42Sjeremylt fprintf(stream, "%s Active vector\n", pre); 8042ebaca42Sjeremylt else if (field->vec == CEED_VECTOR_NONE) 8052ebaca42Sjeremylt fprintf(stream, "%s No vector\n", pre); 8062ebaca42Sjeremylt 8072ebaca42Sjeremylt return 0; 8082ebaca42Sjeremylt } 8092ebaca42Sjeremylt 8102ebaca42Sjeremylt /** 8112ebaca42Sjeremylt @brief View a single CeedOperator 8122ebaca42Sjeremylt 8132ebaca42Sjeremylt @param[in] op CeedOperator to view 8142ebaca42Sjeremylt @param[in] stream Stream to write; typically stdout/stderr or a file 8152ebaca42Sjeremylt 8162ebaca42Sjeremylt @return Error code: 0 - success, otherwise - failure 8172ebaca42Sjeremylt 8182ebaca42Sjeremylt @ref Utility 8192ebaca42Sjeremylt **/ 8202ebaca42Sjeremylt int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) { 8212ebaca42Sjeremylt int ierr; 8222ebaca42Sjeremylt const char* pre = sub ? " " : ""; 8232ebaca42Sjeremylt 8242ebaca42Sjeremylt CeedInt totalfields; 8252ebaca42Sjeremylt ierr = CeedOperatorGetNumArgs(op, &totalfields); CeedChk(ierr); 826*2da88da5Sjeremylt 8272ebaca42Sjeremylt fprintf(stream, "%s %d Field%s\n", pre, totalfields, totalfields>1 ? "s" : ""); 8282ebaca42Sjeremylt 829*2da88da5Sjeremylt fprintf(stream, "%s %d Input Field%s:\n", pre, op->qf->numinputfields, 8302ebaca42Sjeremylt op->qf->numinputfields>1 ? "s" : ""); 8312ebaca42Sjeremylt for (CeedInt i=0; i<op->qf->numinputfields; i++) { 8322ebaca42Sjeremylt ierr = CeedOperatorFieldView(op->inputfields[i], op->qf->inputfields[i], 833*2da88da5Sjeremylt i, sub, 1, stream); CeedChk(ierr); 8342ebaca42Sjeremylt } 8352ebaca42Sjeremylt 836*2da88da5Sjeremylt fprintf(stream, "%s %d Output Field%s:\n", pre, op->qf->numoutputfields, 8372ebaca42Sjeremylt op->qf->numoutputfields>1 ? "s" : ""); 8382ebaca42Sjeremylt for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 8392ebaca42Sjeremylt ierr = CeedOperatorFieldView(op->outputfields[i], op->qf->inputfields[i], 840*2da88da5Sjeremylt i, sub, 0, stream); CeedChk(ierr); 8412ebaca42Sjeremylt } 8422ebaca42Sjeremylt 8432ebaca42Sjeremylt return 0; 8442ebaca42Sjeremylt } 8452ebaca42Sjeremylt 8462ebaca42Sjeremylt /** 8472ebaca42Sjeremylt @brief View a CeedOperator 8482ebaca42Sjeremylt 8492ebaca42Sjeremylt @param[in] op CeedOperator to view 8502ebaca42Sjeremylt @param[in] stream Stream to write; typically stdout/stderr or a file 8512ebaca42Sjeremylt 8522ebaca42Sjeremylt @return Error code: 0 - success, otherwise - failure 8532ebaca42Sjeremylt 8542ebaca42Sjeremylt @ref Utility 8552ebaca42Sjeremylt **/ 8562ebaca42Sjeremylt int CeedOperatorView(CeedOperator op, FILE *stream) { 8572ebaca42Sjeremylt int ierr; 8582ebaca42Sjeremylt 8592ebaca42Sjeremylt if (op->composite) { 8602ebaca42Sjeremylt fprintf(stream, "Composite CeedOperator\n"); 8612ebaca42Sjeremylt 8622ebaca42Sjeremylt for (CeedInt i=0; i<op->numsub; i++) { 863*2da88da5Sjeremylt fprintf(stream, " SubOperator [%d]:\n", i); 8642ebaca42Sjeremylt ierr = CeedOperatorSingleView(op->suboperators[i], 1, stream); 8652ebaca42Sjeremylt CeedChk(ierr); 8662ebaca42Sjeremylt } 8672ebaca42Sjeremylt } else { 8682ebaca42Sjeremylt fprintf(stream, "CeedOperator\n"); 8692ebaca42Sjeremylt ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr); 8702ebaca42Sjeremylt } 8712ebaca42Sjeremylt 8722ebaca42Sjeremylt return 0; 8732ebaca42Sjeremylt } 8742ebaca42Sjeremylt 8752ebaca42Sjeremylt /** 876d1bcdac9Sjeremylt @brief Get the CeedOperatorFields of a CeedOperator 877d1bcdac9Sjeremylt 878d1bcdac9Sjeremylt @param op CeedOperator 879d1bcdac9Sjeremylt @param[out] inputfields Variable to store inputfields 880d1bcdac9Sjeremylt @param[out] outputfields Variable to store outputfields 881d1bcdac9Sjeremylt 882d1bcdac9Sjeremylt @return An error code: 0 - success, otherwise - failure 883d1bcdac9Sjeremylt 884d1bcdac9Sjeremylt @ref Advanced 885d1bcdac9Sjeremylt **/ 886d1bcdac9Sjeremylt 887692c2638Sjeremylt int CeedOperatorGetFields(CeedOperator op, CeedOperatorField **inputfields, 888d1bcdac9Sjeremylt CeedOperatorField **outputfields) { 88952d6035fSJeremy L Thompson if (op->composite) 890c042f62fSJeremy L Thompson // LCOV_EXCL_START 89152d6035fSJeremy L Thompson return CeedError(op->ceed, 1, "Not defined for composite operator"); 892c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 89352d6035fSJeremy L Thompson 894d1bcdac9Sjeremylt if (inputfields) *inputfields = op->inputfields; 895d1bcdac9Sjeremylt if (outputfields) *outputfields = op->outputfields; 896d1bcdac9Sjeremylt return 0; 897d1bcdac9Sjeremylt } 898d1bcdac9Sjeremylt 899d1bcdac9Sjeremylt /** 9004dccadb6Sjeremylt @brief Get the L vector CeedTransposeMode of a CeedOperatorField 9014dccadb6Sjeremylt 9024dccadb6Sjeremylt @param opfield CeedOperatorField 9034dccadb6Sjeremylt @param[out] lmode Variable to store CeedTransposeMode 9044dccadb6Sjeremylt 9054dccadb6Sjeremylt @return An error code: 0 - success, otherwise - failure 9064dccadb6Sjeremylt 9074dccadb6Sjeremylt @ref Advanced 9084dccadb6Sjeremylt **/ 9094dccadb6Sjeremylt 9104dccadb6Sjeremylt int CeedOperatorFieldGetLMode(CeedOperatorField opfield, 9114dccadb6Sjeremylt CeedTransposeMode *lmode) { 912fe2413ffSjeremylt *lmode = opfield->lmode; 9134dccadb6Sjeremylt return 0; 9142b8e417aSjeremylt } 9152b8e417aSjeremylt 9162b8e417aSjeremylt /** 917d1bcdac9Sjeremylt @brief Get the CeedElemRestriction of a CeedOperatorField 918d1bcdac9Sjeremylt 919d1bcdac9Sjeremylt @param opfield CeedOperatorField 920d1bcdac9Sjeremylt @param[out] rstr Variable to store CeedElemRestriction 921d1bcdac9Sjeremylt 922d1bcdac9Sjeremylt @return An error code: 0 - success, otherwise - failure 923d1bcdac9Sjeremylt 924d1bcdac9Sjeremylt @ref Advanced 925d1bcdac9Sjeremylt **/ 926d1bcdac9Sjeremylt 927d1bcdac9Sjeremylt int CeedOperatorFieldGetElemRestriction(CeedOperatorField opfield, 928d1bcdac9Sjeremylt CeedElemRestriction *rstr) { 929fe2413ffSjeremylt *rstr = opfield->Erestrict; 930d1bcdac9Sjeremylt return 0; 931d1bcdac9Sjeremylt } 932d1bcdac9Sjeremylt 933d1bcdac9Sjeremylt /** 934d1bcdac9Sjeremylt @brief Get the CeedBasis of a CeedOperatorField 935d1bcdac9Sjeremylt 936d1bcdac9Sjeremylt @param opfield CeedOperatorField 937d1bcdac9Sjeremylt @param[out] basis Variable to store CeedBasis 938d1bcdac9Sjeremylt 939d1bcdac9Sjeremylt @return An error code: 0 - success, otherwise - failure 940d1bcdac9Sjeremylt 941d1bcdac9Sjeremylt @ref Advanced 942d1bcdac9Sjeremylt **/ 943d1bcdac9Sjeremylt 944692c2638Sjeremylt int CeedOperatorFieldGetBasis(CeedOperatorField opfield, CeedBasis *basis) { 945fe2413ffSjeremylt *basis = opfield->basis; 946d1bcdac9Sjeremylt return 0; 947d1bcdac9Sjeremylt } 948d1bcdac9Sjeremylt 949d1bcdac9Sjeremylt /** 950d1bcdac9Sjeremylt @brief Get the CeedVector of a CeedOperatorField 951d1bcdac9Sjeremylt 952d1bcdac9Sjeremylt @param opfield CeedOperatorField 953d1bcdac9Sjeremylt @param[out] vec Variable to store CeedVector 954d1bcdac9Sjeremylt 955d1bcdac9Sjeremylt @return An error code: 0 - success, otherwise - failure 956d1bcdac9Sjeremylt 957d1bcdac9Sjeremylt @ref Advanced 958d1bcdac9Sjeremylt **/ 959d1bcdac9Sjeremylt 960692c2638Sjeremylt int CeedOperatorFieldGetVector(CeedOperatorField opfield, CeedVector *vec) { 961fe2413ffSjeremylt *vec = opfield->vec; 962d1bcdac9Sjeremylt return 0; 963d1bcdac9Sjeremylt } 964d1bcdac9Sjeremylt 965d1bcdac9Sjeremylt /** 966b11c1e72Sjeremylt @brief Destroy a CeedOperator 967d7b241e6Sjeremylt 968d7b241e6Sjeremylt @param op CeedOperator to destroy 969b11c1e72Sjeremylt 970b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 971dfdf5a53Sjeremylt 972dfdf5a53Sjeremylt @ref Basic 973b11c1e72Sjeremylt **/ 974d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) { 975d7b241e6Sjeremylt int ierr; 976d7b241e6Sjeremylt 977d7b241e6Sjeremylt if (!*op || --(*op)->refcount > 0) return 0; 978d7b241e6Sjeremylt if ((*op)->Destroy) { 979d7b241e6Sjeremylt ierr = (*op)->Destroy(*op); CeedChk(ierr); 980d7b241e6Sjeremylt } 981fe2413ffSjeremylt ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 982fe2413ffSjeremylt // Free fields 9831d102b48SJeremy L Thompson for (int i=0; i<(*op)->nfields; i++) 98452d6035fSJeremy L Thompson if ((*op)->inputfields[i]) { 98571352a93Sjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->inputfields[i]->Erestrict); 98671352a93Sjeremylt CeedChk(ierr); 98771352a93Sjeremylt if ((*op)->inputfields[i]->basis != CEED_BASIS_COLLOCATED) { 98871352a93Sjeremylt ierr = CeedBasisDestroy(&(*op)->inputfields[i]->basis); CeedChk(ierr); 98971352a93Sjeremylt } 99071352a93Sjeremylt if ((*op)->inputfields[i]->vec != CEED_VECTOR_ACTIVE && 99171352a93Sjeremylt (*op)->inputfields[i]->vec != CEED_VECTOR_NONE ) { 99271352a93Sjeremylt ierr = CeedVectorDestroy(&(*op)->inputfields[i]->vec); CeedChk(ierr); 99371352a93Sjeremylt } 994fe2413ffSjeremylt ierr = CeedFree(&(*op)->inputfields[i]); CeedChk(ierr); 995fe2413ffSjeremylt } 9961d102b48SJeremy L Thompson for (int i=0; i<(*op)->nfields; i++) 997d0eb30a5Sjeremylt if ((*op)->outputfields[i]) { 99871352a93Sjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->outputfields[i]->Erestrict); 99971352a93Sjeremylt CeedChk(ierr); 100071352a93Sjeremylt if ((*op)->outputfields[i]->basis != CEED_BASIS_COLLOCATED) { 100171352a93Sjeremylt ierr = CeedBasisDestroy(&(*op)->outputfields[i]->basis); CeedChk(ierr); 100271352a93Sjeremylt } 100371352a93Sjeremylt if ((*op)->outputfields[i]->vec != CEED_VECTOR_ACTIVE && 100471352a93Sjeremylt (*op)->outputfields[i]->vec != CEED_VECTOR_NONE ) { 100571352a93Sjeremylt ierr = CeedVectorDestroy(&(*op)->outputfields[i]->vec); CeedChk(ierr); 100671352a93Sjeremylt } 1007fe2413ffSjeremylt ierr = CeedFree(&(*op)->outputfields[i]); CeedChk(ierr); 1008fe2413ffSjeremylt } 100952d6035fSJeremy L Thompson // Destroy suboperators 10101d102b48SJeremy L Thompson for (int i=0; i<(*op)->numsub; i++) 101152d6035fSJeremy L Thompson if ((*op)->suboperators[i]) { 101252d6035fSJeremy L Thompson ierr = CeedOperatorDestroy(&(*op)->suboperators[i]); CeedChk(ierr); 101352d6035fSJeremy L Thompson } 1014d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 1015d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 1016d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 1017fe2413ffSjeremylt 1018fe2413ffSjeremylt ierr = CeedFree(&(*op)->inputfields); CeedChk(ierr); 1019fe2413ffSjeremylt ierr = CeedFree(&(*op)->outputfields); CeedChk(ierr); 102052d6035fSJeremy L Thompson ierr = CeedFree(&(*op)->suboperators); CeedChk(ierr); 1021d7b241e6Sjeremylt ierr = CeedFree(op); CeedChk(ierr); 1022d7b241e6Sjeremylt return 0; 1023d7b241e6Sjeremylt } 1024d7b241e6Sjeremylt 1025d7b241e6Sjeremylt /// @} 1026