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 173d576824SJeremy L Thompson #include <ceed.h> 18d863ab9bSjeremylt #include <ceed-backend.h> 193d576824SJeremy L Thompson #include <ceed-impl.h> 203bd813ffSjeremylt #include <math.h> 213d576824SJeremy L Thompson #include <stdbool.h> 223d576824SJeremy L Thompson #include <stdio.h> 233d576824SJeremy L Thompson #include <string.h> 24d7b241e6Sjeremylt 25dfdf5a53Sjeremylt /// @file 267a982d89SJeremy L. Thompson /// Implementation of CeedOperator interfaces 277a982d89SJeremy L. Thompson 287a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 297a982d89SJeremy L. Thompson /// CeedOperator Library Internal Functions 307a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 317a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorDeveloper 327a982d89SJeremy L. Thompson /// @{ 337a982d89SJeremy L. Thompson 347a982d89SJeremy L. Thompson /** 357a982d89SJeremy L. Thompson @brief Duplicate a CeedOperator with a reference Ceed to fallback for advanced 367a982d89SJeremy L. Thompson CeedOperator functionality 377a982d89SJeremy L. Thompson 387a982d89SJeremy L. Thompson @param op CeedOperator to create fallback for 397a982d89SJeremy L. Thompson 407a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 417a982d89SJeremy L. Thompson 427a982d89SJeremy L. Thompson @ref Developer 437a982d89SJeremy L. Thompson **/ 447a982d89SJeremy L. Thompson int CeedOperatorCreateFallback(CeedOperator op) { 457a982d89SJeremy L. Thompson int ierr; 467a982d89SJeremy L. Thompson 477a982d89SJeremy L. Thompson // Fallback Ceed 487a982d89SJeremy L. Thompson const char *resource, *fallbackresource; 497a982d89SJeremy L. Thompson ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr); 507a982d89SJeremy L. Thompson ierr = CeedGetOperatorFallbackResource(op->ceed, &fallbackresource); 517a982d89SJeremy L. Thompson CeedChk(ierr); 527a982d89SJeremy L. Thompson if (!strcmp(resource, fallbackresource)) 537a982d89SJeremy L. Thompson // LCOV_EXCL_START 54e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 55e15f9bd0SJeremy L Thompson "Backend %s cannot create an operator" 567a982d89SJeremy L. Thompson "fallback to resource %s", resource, fallbackresource); 577a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 587a982d89SJeremy L. Thompson 597a982d89SJeremy L. Thompson // Fallback Ceed 607a982d89SJeremy L. Thompson Ceed ceedref; 617a982d89SJeremy L. Thompson if (!op->ceed->opfallbackceed) { 627a982d89SJeremy L. Thompson ierr = CeedInit(fallbackresource, &ceedref); CeedChk(ierr); 637a982d89SJeremy L. Thompson ceedref->opfallbackparent = op->ceed; 64fc164cf7SWill Pazner ceedref->Error = op->ceed->Error; 657a982d89SJeremy L. Thompson op->ceed->opfallbackceed = ceedref; 667a982d89SJeremy L. Thompson } 677a982d89SJeremy L. Thompson ceedref = op->ceed->opfallbackceed; 687a982d89SJeremy L. Thompson 697a982d89SJeremy L. Thompson // Clone Op 707a982d89SJeremy L. Thompson CeedOperator opref; 717a982d89SJeremy L. Thompson ierr = CeedCalloc(1, &opref); CeedChk(ierr); 72e15f9bd0SJeremy L Thompson memcpy(opref, op, sizeof(*opref)); 737a982d89SJeremy L. Thompson opref->data = NULL; 74e15f9bd0SJeremy L Thompson opref->interfacesetup = false; 75e15f9bd0SJeremy L Thompson opref->backendsetup = false; 767a982d89SJeremy L. Thompson opref->ceed = ceedref; 777a982d89SJeremy L. Thompson ierr = ceedref->OperatorCreate(opref); CeedChk(ierr); 787a982d89SJeremy L. Thompson op->opfallback = opref; 797a982d89SJeremy L. Thompson 807a982d89SJeremy L. Thompson // Clone QF 817a982d89SJeremy L. Thompson CeedQFunction qfref; 827a982d89SJeremy L. Thompson ierr = CeedCalloc(1, &qfref); CeedChk(ierr); 83e15f9bd0SJeremy L Thompson memcpy(qfref, (op->qf), sizeof(*qfref)); 847a982d89SJeremy L. Thompson qfref->data = NULL; 857a982d89SJeremy L. Thompson qfref->ceed = ceedref; 867a982d89SJeremy L. Thompson ierr = ceedref->QFunctionCreate(qfref); CeedChk(ierr); 877a982d89SJeremy L. Thompson opref->qf = qfref; 887a982d89SJeremy L. Thompson op->qffallback = qfref; 89e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 90e15f9bd0SJeremy L Thompson } 917a982d89SJeremy L. Thompson 92e15f9bd0SJeremy L Thompson /** 93e15f9bd0SJeremy L Thompson @brief Check if a CeedOperator Field matches the QFunction Field 94e15f9bd0SJeremy L Thompson 95e15f9bd0SJeremy L Thompson @param[in] ceed Ceed object for error handling 96e15f9bd0SJeremy L Thompson @param[in] qfield QFunction Field matching Operator Field 97e15f9bd0SJeremy L Thompson @param[in] r Operator Field ElemRestriction 98e15f9bd0SJeremy L Thompson @param[in] b Operator Field Basis 99e15f9bd0SJeremy L Thompson 100e15f9bd0SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 101e15f9bd0SJeremy L Thompson 102e15f9bd0SJeremy L Thompson @ref Developer 103e15f9bd0SJeremy L Thompson **/ 104e15f9bd0SJeremy L Thompson static int CeedOperatorCheckField(Ceed ceed, CeedQFunctionField qfield, 105e15f9bd0SJeremy L Thompson CeedElemRestriction r, CeedBasis b) { 106e15f9bd0SJeremy L Thompson int ierr; 107e15f9bd0SJeremy L Thompson CeedEvalMode emode = qfield->emode; 108e15f9bd0SJeremy L Thompson CeedInt dim = 1, ncomp = 1, restr_ncomp = 1, size = qfield->size; 109e15f9bd0SJeremy L Thompson // Restriction 110e15f9bd0SJeremy L Thompson if (r != CEED_ELEMRESTRICTION_NONE) { 111e15f9bd0SJeremy L Thompson ierr = CeedElemRestrictionGetNumComponents(r, &restr_ncomp); 112e15f9bd0SJeremy L Thompson } else if (emode != CEED_EVAL_WEIGHT) { 113e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 114e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 115e15f9bd0SJeremy L Thompson "CEED_ELEMRESTRICTION_NONE can only be used " 116e15f9bd0SJeremy L Thompson "for a field with eval mode CEED_EVAL_WEIGHT"); 117e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 118e15f9bd0SJeremy L Thompson } 119e15f9bd0SJeremy L Thompson // Basis 120e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 121e15f9bd0SJeremy L Thompson ierr = CeedBasisGetDimension(b, &dim); CeedChk(ierr); 122e15f9bd0SJeremy L Thompson ierr = CeedBasisGetNumComponents(b, &ncomp); CeedChk(ierr); 123e15f9bd0SJeremy L Thompson if (r != CEED_ELEMRESTRICTION_NONE && restr_ncomp != ncomp) { 124e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 125e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 126e15f9bd0SJeremy L Thompson "ElemRestriction and Basis have incompatible numbers of components"); 127e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 128e15f9bd0SJeremy L Thompson } 129e15f9bd0SJeremy L Thompson } 130e15f9bd0SJeremy L Thompson // Field size 131e15f9bd0SJeremy L Thompson switch(emode) { 132e15f9bd0SJeremy L Thompson case CEED_EVAL_NONE: 133e15f9bd0SJeremy L Thompson if (size != restr_ncomp) 134e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 135e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 136e15f9bd0SJeremy L Thompson "Incompatible QFunction field size and Operator field " 137e15f9bd0SJeremy L Thompson "ElemRestriction number of components"); 138e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 139e15f9bd0SJeremy L Thompson break; 140e15f9bd0SJeremy L Thompson case CEED_EVAL_INTERP: 141e15f9bd0SJeremy L Thompson if (size != ncomp) 142e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 143e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 144e15f9bd0SJeremy L Thompson "Incompatible QFunction field size and Operator field " 145e15f9bd0SJeremy L Thompson "Basis number of components"); 146e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 147e15f9bd0SJeremy L Thompson break; 148e15f9bd0SJeremy L Thompson case CEED_EVAL_GRAD: 149e15f9bd0SJeremy L Thompson if (size != ncomp * dim) 150e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 151e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 152e15f9bd0SJeremy L Thompson "Incompatible QFunction field size and Operator field " 153e15f9bd0SJeremy L Thompson "Basis dimension and number of components"); 154e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 155e15f9bd0SJeremy L Thompson break; 156e15f9bd0SJeremy L Thompson case CEED_EVAL_WEIGHT: 157e15f9bd0SJeremy L Thompson // No addional checks required 158e15f9bd0SJeremy L Thompson break; 159e15f9bd0SJeremy L Thompson case CEED_EVAL_DIV: 160e15f9bd0SJeremy L Thompson // Not implemented 161e15f9bd0SJeremy L Thompson break; 162e15f9bd0SJeremy L Thompson case CEED_EVAL_CURL: 163e15f9bd0SJeremy L Thompson // Not implemented 164e15f9bd0SJeremy L Thompson break; 165e15f9bd0SJeremy L Thompson } 166e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1677a982d89SJeremy L. Thompson } 1687a982d89SJeremy L. Thompson 1697a982d89SJeremy L. Thompson /** 1707a982d89SJeremy L. Thompson @brief Check if a CeedOperator is ready to be used. 1717a982d89SJeremy L. Thompson 1727a982d89SJeremy L. Thompson @param[in] op CeedOperator to check 1737a982d89SJeremy L. Thompson 1747a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 1757a982d89SJeremy L. Thompson 1767a982d89SJeremy L. Thompson @ref Developer 1777a982d89SJeremy L. Thompson **/ 178*e2f04181SAndrew T. Barker static int CeedOperatorCheckReady(CeedOperator op) { 179*e2f04181SAndrew T. Barker int ierr; 180*e2f04181SAndrew T. Barker Ceed ceed; 181*e2f04181SAndrew T. Barker ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 182*e2f04181SAndrew T. Barker 183e15f9bd0SJeremy L Thompson if (op->interfacesetup) 184e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1857a982d89SJeremy L. Thompson 186e15f9bd0SJeremy L Thompson CeedQFunction qf = op->qf; 1877a982d89SJeremy L. Thompson if (op->composite) { 1887a982d89SJeremy L. Thompson if (!op->numsub) 1897a982d89SJeremy L. Thompson // LCOV_EXCL_START 190e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No suboperators set"); 1917a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 1927a982d89SJeremy L. Thompson } else { 1937a982d89SJeremy L. Thompson if (op->nfields == 0) 1947a982d89SJeremy L. Thompson // LCOV_EXCL_START 195e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No operator fields set"); 1967a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 1977a982d89SJeremy L. Thompson if (op->nfields < qf->numinputfields + qf->numoutputfields) 1987a982d89SJeremy L. Thompson // LCOV_EXCL_START 199e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "Not all operator fields set"); 2007a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 2017a982d89SJeremy L. Thompson if (!op->hasrestriction) 2027a982d89SJeremy L. Thompson // LCOV_EXCL_START 203e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, 204e15f9bd0SJeremy L Thompson "At least one restriction required"); 2057a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 2067a982d89SJeremy L. Thompson if (op->numqpoints == 0) 2077a982d89SJeremy L. Thompson // LCOV_EXCL_START 208e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, 209e15f9bd0SJeremy L Thompson "At least one non-collocated basis required"); 2107a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 2117a982d89SJeremy L. Thompson } 2127a982d89SJeremy L. Thompson 213e15f9bd0SJeremy L Thompson // Flag as immutable and ready 214e15f9bd0SJeremy L Thompson op->interfacesetup = true; 215e15f9bd0SJeremy L Thompson if (op->qf && op->qf != CEED_QFUNCTION_NONE) 216e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 217e15f9bd0SJeremy L Thompson op->qf->operatorsset++; 218e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 219e15f9bd0SJeremy L Thompson if (op->dqf && op->dqf != CEED_QFUNCTION_NONE) 220e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 221e15f9bd0SJeremy L Thompson op->dqf->operatorsset++; 222e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 223e15f9bd0SJeremy L Thompson if (op->dqfT && op->dqfT != CEED_QFUNCTION_NONE) 224e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 225e15f9bd0SJeremy L Thompson op->dqfT->operatorsset++; 226e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 227e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2287a982d89SJeremy L. Thompson } 2297a982d89SJeremy L. Thompson 2307a982d89SJeremy L. Thompson /** 2317a982d89SJeremy L. Thompson @brief View a field of a CeedOperator 2327a982d89SJeremy L. Thompson 2337a982d89SJeremy L. Thompson @param[in] field Operator field to view 2344c4400c7SValeria Barra @param[in] qffield QFunction field (carries field name) 2357a982d89SJeremy L. Thompson @param[in] fieldnumber Number of field being viewed 2364c4400c7SValeria Barra @param[in] sub true indicates sub-operator, which increases indentation; false for top-level operator 2374c4400c7SValeria Barra @param[in] in true for an input field; false for output field 2387a982d89SJeremy L. Thompson @param[in] stream Stream to view to, e.g., stdout 2397a982d89SJeremy L. Thompson 2407a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 2417a982d89SJeremy L. Thompson 2427a982d89SJeremy L. Thompson @ref Utility 2437a982d89SJeremy L. Thompson **/ 2447a982d89SJeremy L. Thompson static int CeedOperatorFieldView(CeedOperatorField field, 2457a982d89SJeremy L. Thompson CeedQFunctionField qffield, 2467a982d89SJeremy L. Thompson CeedInt fieldnumber, bool sub, bool in, 2477a982d89SJeremy L. Thompson FILE *stream) { 2487a982d89SJeremy L. Thompson const char *pre = sub ? " " : ""; 2497a982d89SJeremy L. Thompson const char *inout = in ? "Input" : "Output"; 2507a982d89SJeremy L. Thompson 2517a982d89SJeremy L. Thompson fprintf(stream, "%s %s Field [%d]:\n" 2527a982d89SJeremy L. Thompson "%s Name: \"%s\"\n", 2537a982d89SJeremy L. Thompson pre, inout, fieldnumber, pre, qffield->fieldname); 2547a982d89SJeremy L. Thompson 2557a982d89SJeremy L. Thompson if (field->basis == CEED_BASIS_COLLOCATED) 2567a982d89SJeremy L. Thompson fprintf(stream, "%s Collocated basis\n", pre); 2577a982d89SJeremy L. Thompson 2587a982d89SJeremy L. Thompson if (field->vec == CEED_VECTOR_ACTIVE) 2597a982d89SJeremy L. Thompson fprintf(stream, "%s Active vector\n", pre); 2607a982d89SJeremy L. Thompson else if (field->vec == CEED_VECTOR_NONE) 2617a982d89SJeremy L. Thompson fprintf(stream, "%s No vector\n", pre); 262e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2637a982d89SJeremy L. Thompson } 2647a982d89SJeremy L. Thompson 2657a982d89SJeremy L. Thompson /** 2667a982d89SJeremy L. Thompson @brief View a single CeedOperator 2677a982d89SJeremy L. Thompson 2687a982d89SJeremy L. Thompson @param[in] op CeedOperator to view 2697a982d89SJeremy L. Thompson @param[in] sub Boolean flag for sub-operator 2707a982d89SJeremy L. Thompson @param[in] stream Stream to write; typically stdout/stderr or a file 2717a982d89SJeremy L. Thompson 2727a982d89SJeremy L. Thompson @return Error code: 0 - success, otherwise - failure 2737a982d89SJeremy L. Thompson 2747a982d89SJeremy L. Thompson @ref Utility 2757a982d89SJeremy L. Thompson **/ 2767a982d89SJeremy L. Thompson int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) { 2777a982d89SJeremy L. Thompson int ierr; 2787a982d89SJeremy L. Thompson const char *pre = sub ? " " : ""; 2797a982d89SJeremy L. Thompson 2807a982d89SJeremy L. Thompson CeedInt totalfields; 2817a982d89SJeremy L. Thompson ierr = CeedOperatorGetNumArgs(op, &totalfields); CeedChk(ierr); 2827a982d89SJeremy L. Thompson 2837a982d89SJeremy L. Thompson fprintf(stream, "%s %d Field%s\n", pre, totalfields, totalfields>1 ? "s" : ""); 2847a982d89SJeremy L. Thompson 2857a982d89SJeremy L. Thompson fprintf(stream, "%s %d Input Field%s:\n", pre, op->qf->numinputfields, 2867a982d89SJeremy L. Thompson op->qf->numinputfields>1 ? "s" : ""); 2877a982d89SJeremy L. Thompson for (CeedInt i=0; i<op->qf->numinputfields; i++) { 2887a982d89SJeremy L. Thompson ierr = CeedOperatorFieldView(op->inputfields[i], op->qf->inputfields[i], 2897a982d89SJeremy L. Thompson i, sub, 1, stream); CeedChk(ierr); 2907a982d89SJeremy L. Thompson } 2917a982d89SJeremy L. Thompson 2927a982d89SJeremy L. Thompson fprintf(stream, "%s %d Output Field%s:\n", pre, op->qf->numoutputfields, 2937a982d89SJeremy L. Thompson op->qf->numoutputfields>1 ? "s" : ""); 2947a982d89SJeremy L. Thompson for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 295829936eeSWill Pazner ierr = CeedOperatorFieldView(op->outputfields[i], op->qf->outputfields[i], 2967a982d89SJeremy L. Thompson i, sub, 0, stream); CeedChk(ierr); 2977a982d89SJeremy L. Thompson } 298e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2997a982d89SJeremy L. Thompson } 3007a982d89SJeremy L. Thompson 301d99fa3c5SJeremy L Thompson /** 302*e2f04181SAndrew T. Barker @brief Find the active vector ElemRestriction for a CeedOperator 303*e2f04181SAndrew T. Barker 304*e2f04181SAndrew T. Barker @param[in] op CeedOperator to find active basis for 305*e2f04181SAndrew T. Barker @param[out] activerstr ElemRestriction for active input vector 306*e2f04181SAndrew T. Barker 307*e2f04181SAndrew T. Barker @return An error code: 0 - success, otherwise - failure 308*e2f04181SAndrew T. Barker 309*e2f04181SAndrew T. Barker @ref Utility 310*e2f04181SAndrew T. Barker **/ 311*e2f04181SAndrew T. Barker static int CeedOperatorGetActiveElemRestriction(CeedOperator op, 312*e2f04181SAndrew T. Barker CeedElemRestriction *activerstr) { 313*e2f04181SAndrew T. Barker *activerstr = NULL; 314*e2f04181SAndrew T. Barker for (int i = 0; i < op->qf->numinputfields; i++) 315*e2f04181SAndrew T. Barker if (op->inputfields[i]->vec == CEED_VECTOR_ACTIVE) { 316*e2f04181SAndrew T. Barker *activerstr = op->inputfields[i]->Erestrict; 317*e2f04181SAndrew T. Barker break; 318*e2f04181SAndrew T. Barker } 319*e2f04181SAndrew T. Barker 320*e2f04181SAndrew T. Barker if (!*activerstr) { 321*e2f04181SAndrew T. Barker // LCOV_EXCL_START 322*e2f04181SAndrew T. Barker int ierr; 323*e2f04181SAndrew T. Barker Ceed ceed; 324*e2f04181SAndrew T. Barker ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 325*e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_INCOMPLETE, 326*e2f04181SAndrew T. Barker "No active ElemRestriction found!"); 327*e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 328*e2f04181SAndrew T. Barker } 329*e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 330*e2f04181SAndrew T. Barker } 331*e2f04181SAndrew T. Barker 332*e2f04181SAndrew T. Barker /** 333d99fa3c5SJeremy L Thompson @brief Find the active vector basis for a CeedOperator 334d99fa3c5SJeremy L Thompson 335d99fa3c5SJeremy L Thompson @param[in] op CeedOperator to find active basis for 336d99fa3c5SJeremy L Thompson @param[out] activeBasis Basis for active input vector 337d99fa3c5SJeremy L Thompson 338d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 339d99fa3c5SJeremy L Thompson 340d99fa3c5SJeremy L Thompson @ ref Developer 341d99fa3c5SJeremy L Thompson **/ 342d99fa3c5SJeremy L Thompson static int CeedOperatorGetActiveBasis(CeedOperator op, 343d99fa3c5SJeremy L Thompson CeedBasis *activeBasis) { 344d99fa3c5SJeremy L Thompson *activeBasis = NULL; 345d99fa3c5SJeremy L Thompson for (int i = 0; i < op->qf->numinputfields; i++) 346d99fa3c5SJeremy L Thompson if (op->inputfields[i]->vec == CEED_VECTOR_ACTIVE) { 347d99fa3c5SJeremy L Thompson *activeBasis = op->inputfields[i]->basis; 348d99fa3c5SJeremy L Thompson break; 349d99fa3c5SJeremy L Thompson } 350d99fa3c5SJeremy L Thompson 351d99fa3c5SJeremy L Thompson if (!*activeBasis) { 352d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 353d99fa3c5SJeremy L Thompson int ierr; 354d99fa3c5SJeremy L Thompson Ceed ceed; 355d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 356e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 357d99fa3c5SJeremy L Thompson "No active basis found for automatic multigrid setup"); 358d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 359d99fa3c5SJeremy L Thompson } 360e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 361d99fa3c5SJeremy L Thompson } 362d99fa3c5SJeremy L Thompson 363d99fa3c5SJeremy L Thompson 364d99fa3c5SJeremy L Thompson /** 365d99fa3c5SJeremy L Thompson @brief Common code for creating a multigrid coarse operator and level 366d99fa3c5SJeremy L Thompson transfer operators for a CeedOperator 367d99fa3c5SJeremy L Thompson 368d99fa3c5SJeremy L Thompson @param[in] opFine Fine grid operator 369d99fa3c5SJeremy L Thompson @param[in] PMultFine L-vector multiplicity in parallel gather/scatter 370d99fa3c5SJeremy L Thompson @param[in] rstrCoarse Coarse grid restriction 371d99fa3c5SJeremy L Thompson @param[in] basisCoarse Coarse grid active vector basis 372d99fa3c5SJeremy L Thompson @param[in] basisCtoF Basis for coarse to fine interpolation 373d99fa3c5SJeremy L Thompson @param[out] opCoarse Coarse grid operator 374d99fa3c5SJeremy L Thompson @param[out] opProlong Coarse to fine operator 375d99fa3c5SJeremy L Thompson @param[out] opRestrict Fine to coarse operator 376d99fa3c5SJeremy L Thompson 377d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 378d99fa3c5SJeremy L Thompson 379d99fa3c5SJeremy L Thompson @ref Developer 380d99fa3c5SJeremy L Thompson **/ 381d99fa3c5SJeremy L Thompson static int CeedOperatorMultigridLevel_Core(CeedOperator opFine, 382d99fa3c5SJeremy L Thompson CeedVector PMultFine, CeedElemRestriction rstrCoarse, CeedBasis basisCoarse, 383d99fa3c5SJeremy L Thompson CeedBasis basisCtoF, CeedOperator *opCoarse, CeedOperator *opProlong, 384d99fa3c5SJeremy L Thompson CeedOperator *opRestrict) { 385d99fa3c5SJeremy L Thompson int ierr; 386d99fa3c5SJeremy L Thompson Ceed ceed; 387d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(opFine, &ceed); CeedChk(ierr); 388d99fa3c5SJeremy L Thompson 389d99fa3c5SJeremy L Thompson // Check for composite operator 390d99fa3c5SJeremy L Thompson bool isComposite; 391d99fa3c5SJeremy L Thompson ierr = CeedOperatorIsComposite(opFine, &isComposite); CeedChk(ierr); 392d99fa3c5SJeremy L Thompson if (isComposite) 393d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 394e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 395d99fa3c5SJeremy L Thompson "Automatic multigrid setup for composite operators not supported"); 396d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 397d99fa3c5SJeremy L Thompson 398d99fa3c5SJeremy L Thompson // Coarse Grid 399d99fa3c5SJeremy L Thompson ierr = CeedOperatorCreate(ceed, opFine->qf, opFine->dqf, opFine->dqfT, 400d99fa3c5SJeremy L Thompson opCoarse); CeedChk(ierr); 401d99fa3c5SJeremy L Thompson CeedElemRestriction rstrFine = NULL; 402d99fa3c5SJeremy L Thompson // -- Clone input fields 403d99fa3c5SJeremy L Thompson for (int i = 0; i < opFine->qf->numinputfields; i++) { 404d99fa3c5SJeremy L Thompson if (opFine->inputfields[i]->vec == CEED_VECTOR_ACTIVE) { 405d99fa3c5SJeremy L Thompson rstrFine = opFine->inputfields[i]->Erestrict; 406d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opCoarse, opFine->inputfields[i]->fieldname, 407d99fa3c5SJeremy L Thompson rstrCoarse, basisCoarse, CEED_VECTOR_ACTIVE); 408d99fa3c5SJeremy L Thompson CeedChk(ierr); 409d99fa3c5SJeremy L Thompson } else { 410d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opCoarse, opFine->inputfields[i]->fieldname, 411d99fa3c5SJeremy L Thompson opFine->inputfields[i]->Erestrict, 412d99fa3c5SJeremy L Thompson opFine->inputfields[i]->basis, 413d99fa3c5SJeremy L Thompson opFine->inputfields[i]->vec); CeedChk(ierr); 414d99fa3c5SJeremy L Thompson } 415d99fa3c5SJeremy L Thompson } 416d99fa3c5SJeremy L Thompson // -- Clone output fields 417d99fa3c5SJeremy L Thompson for (int i = 0; i < opFine->qf->numoutputfields; i++) { 418d99fa3c5SJeremy L Thompson if (opFine->outputfields[i]->vec == CEED_VECTOR_ACTIVE) { 419d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opCoarse, opFine->outputfields[i]->fieldname, 420d99fa3c5SJeremy L Thompson rstrCoarse, basisCoarse, CEED_VECTOR_ACTIVE); 421d99fa3c5SJeremy L Thompson CeedChk(ierr); 422d99fa3c5SJeremy L Thompson } else { 423d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opCoarse, opFine->outputfields[i]->fieldname, 424d99fa3c5SJeremy L Thompson opFine->outputfields[i]->Erestrict, 425d99fa3c5SJeremy L Thompson opFine->outputfields[i]->basis, 426d99fa3c5SJeremy L Thompson opFine->outputfields[i]->vec); CeedChk(ierr); 427d99fa3c5SJeremy L Thompson } 428d99fa3c5SJeremy L Thompson } 429d99fa3c5SJeremy L Thompson 430d99fa3c5SJeremy L Thompson // Multiplicity vector 431d99fa3c5SJeremy L Thompson CeedVector multVec, multE; 432d99fa3c5SJeremy L Thompson ierr = CeedElemRestrictionCreateVector(rstrFine, &multVec, &multE); 433d99fa3c5SJeremy L Thompson CeedChk(ierr); 434d99fa3c5SJeremy L Thompson ierr = CeedVectorSetValue(multE, 0.0); CeedChk(ierr); 435d99fa3c5SJeremy L Thompson ierr = CeedElemRestrictionApply(rstrFine, CEED_NOTRANSPOSE, PMultFine, multE, 436d99fa3c5SJeremy L Thompson CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 437d99fa3c5SJeremy L Thompson ierr = CeedVectorSetValue(multVec, 0.0); CeedChk(ierr); 438d99fa3c5SJeremy L Thompson ierr = CeedElemRestrictionApply(rstrFine, CEED_TRANSPOSE, multE, multVec, 439d99fa3c5SJeremy L Thompson CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 440d99fa3c5SJeremy L Thompson ierr = CeedVectorDestroy(&multE); CeedChk(ierr); 441d99fa3c5SJeremy L Thompson ierr = CeedVectorReciprocal(multVec); CeedChk(ierr); 442d99fa3c5SJeremy L Thompson 443d99fa3c5SJeremy L Thompson // Restriction 444d99fa3c5SJeremy L Thompson CeedInt ncomp; 445d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumComponents(basisCoarse, &ncomp); CeedChk(ierr); 446d99fa3c5SJeremy L Thompson CeedQFunction qfRestrict; 447d99fa3c5SJeremy L Thompson ierr = CeedQFunctionCreateInteriorByName(ceed, "Scale", &qfRestrict); 448d99fa3c5SJeremy L Thompson CeedChk(ierr); 449777ff853SJeremy L Thompson CeedInt *ncompRData; 450777ff853SJeremy L Thompson ierr = CeedCalloc(1, &ncompRData); CeedChk(ierr); 451777ff853SJeremy L Thompson ncompRData[0] = ncomp; 452777ff853SJeremy L Thompson CeedQFunctionContext ctxR; 453777ff853SJeremy L Thompson ierr = CeedQFunctionContextCreate(ceed, &ctxR); CeedChk(ierr); 454777ff853SJeremy L Thompson ierr = CeedQFunctionContextSetData(ctxR, CEED_MEM_HOST, CEED_OWN_POINTER, 455777ff853SJeremy L Thompson sizeof(*ncompRData), ncompRData); 456777ff853SJeremy L Thompson CeedChk(ierr); 457777ff853SJeremy L Thompson ierr = CeedQFunctionSetContext(qfRestrict, ctxR); CeedChk(ierr); 458777ff853SJeremy L Thompson ierr = CeedQFunctionContextDestroy(&ctxR); CeedChk(ierr); 459d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddInput(qfRestrict, "input", ncomp, CEED_EVAL_NONE); 460d99fa3c5SJeremy L Thompson CeedChk(ierr); 461d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddInput(qfRestrict, "scale", ncomp, CEED_EVAL_NONE); 462d99fa3c5SJeremy L Thompson CeedChk(ierr); 463d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddOutput(qfRestrict, "output", ncomp, CEED_EVAL_INTERP); 464d99fa3c5SJeremy L Thompson CeedChk(ierr); 465d99fa3c5SJeremy L Thompson 466d99fa3c5SJeremy L Thompson ierr = CeedOperatorCreate(ceed, qfRestrict, CEED_QFUNCTION_NONE, 467d99fa3c5SJeremy L Thompson CEED_QFUNCTION_NONE, opRestrict); 468d99fa3c5SJeremy L Thompson CeedChk(ierr); 469d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opRestrict, "input", rstrFine, 470d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE); 471d99fa3c5SJeremy L Thompson CeedChk(ierr); 472d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opRestrict, "scale", rstrFine, 473d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, multVec); 474d99fa3c5SJeremy L Thompson CeedChk(ierr); 475d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opRestrict, "output", rstrCoarse, basisCtoF, 476d99fa3c5SJeremy L Thompson CEED_VECTOR_ACTIVE); CeedChk(ierr); 477d99fa3c5SJeremy L Thompson 478d99fa3c5SJeremy L Thompson // Prolongation 479d99fa3c5SJeremy L Thompson CeedQFunction qfProlong; 480d99fa3c5SJeremy L Thompson ierr = CeedQFunctionCreateInteriorByName(ceed, "Scale", &qfProlong); 481d99fa3c5SJeremy L Thompson CeedChk(ierr); 482777ff853SJeremy L Thompson CeedInt *ncompPData; 483777ff853SJeremy L Thompson ierr = CeedCalloc(1, &ncompPData); CeedChk(ierr); 484777ff853SJeremy L Thompson ncompPData[0] = ncomp; 485777ff853SJeremy L Thompson CeedQFunctionContext ctxP; 486777ff853SJeremy L Thompson ierr = CeedQFunctionContextCreate(ceed, &ctxP); CeedChk(ierr); 487777ff853SJeremy L Thompson ierr = CeedQFunctionContextSetData(ctxP, CEED_MEM_HOST, CEED_OWN_POINTER, 488777ff853SJeremy L Thompson sizeof(*ncompPData), ncompPData); 489777ff853SJeremy L Thompson CeedChk(ierr); 490777ff853SJeremy L Thompson ierr = CeedQFunctionSetContext(qfProlong, ctxP); CeedChk(ierr); 491777ff853SJeremy L Thompson ierr = CeedQFunctionContextDestroy(&ctxP); CeedChk(ierr); 492d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddInput(qfProlong, "input", ncomp, CEED_EVAL_INTERP); 493d99fa3c5SJeremy L Thompson CeedChk(ierr); 494d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddInput(qfProlong, "scale", ncomp, CEED_EVAL_NONE); 495d99fa3c5SJeremy L Thompson CeedChk(ierr); 496d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddOutput(qfProlong, "output", ncomp, CEED_EVAL_NONE); 497d99fa3c5SJeremy L Thompson CeedChk(ierr); 498d99fa3c5SJeremy L Thompson 499d99fa3c5SJeremy L Thompson ierr = CeedOperatorCreate(ceed, qfProlong, CEED_QFUNCTION_NONE, 500d99fa3c5SJeremy L Thompson CEED_QFUNCTION_NONE, opProlong); 501d99fa3c5SJeremy L Thompson CeedChk(ierr); 502d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opProlong, "input", rstrCoarse, basisCtoF, 503d99fa3c5SJeremy L Thompson CEED_VECTOR_ACTIVE); CeedChk(ierr); 504d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opProlong, "scale", rstrFine, 505d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, multVec); 506d99fa3c5SJeremy L Thompson CeedChk(ierr); 507d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opProlong, "output", rstrFine, 508d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE); 509d99fa3c5SJeremy L Thompson CeedChk(ierr); 510d99fa3c5SJeremy L Thompson 511d99fa3c5SJeremy L Thompson // Cleanup 512d99fa3c5SJeremy L Thompson ierr = CeedVectorDestroy(&multVec); CeedChk(ierr); 513d99fa3c5SJeremy L Thompson ierr = CeedBasisDestroy(&basisCtoF); CeedChk(ierr); 514d99fa3c5SJeremy L Thompson ierr = CeedQFunctionDestroy(&qfRestrict); CeedChk(ierr); 515d99fa3c5SJeremy L Thompson ierr = CeedQFunctionDestroy(&qfProlong); CeedChk(ierr); 516e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 517d99fa3c5SJeremy L Thompson } 518d99fa3c5SJeremy L Thompson 5197a982d89SJeremy L. Thompson /// @} 5207a982d89SJeremy L. Thompson 5217a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 5227a982d89SJeremy L. Thompson /// CeedOperator Backend API 5237a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 5247a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorBackend 5257a982d89SJeremy L. Thompson /// @{ 5267a982d89SJeremy L. Thompson 5277a982d89SJeremy L. Thompson /** 5287a982d89SJeremy L. Thompson @brief Get the Ceed associated with a CeedOperator 5297a982d89SJeremy L. Thompson 5307a982d89SJeremy L. Thompson @param op CeedOperator 5317a982d89SJeremy L. Thompson @param[out] ceed Variable to store Ceed 5327a982d89SJeremy L. Thompson 5337a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5347a982d89SJeremy L. Thompson 5357a982d89SJeremy L. Thompson @ref Backend 5367a982d89SJeremy L. Thompson **/ 5377a982d89SJeremy L. Thompson 5387a982d89SJeremy L. Thompson int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 5397a982d89SJeremy L. Thompson *ceed = op->ceed; 540e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5417a982d89SJeremy L. Thompson } 5427a982d89SJeremy L. Thompson 5437a982d89SJeremy L. Thompson /** 5447a982d89SJeremy L. Thompson @brief Get the number of elements associated with a CeedOperator 5457a982d89SJeremy L. Thompson 5467a982d89SJeremy L. Thompson @param op CeedOperator 5477a982d89SJeremy L. Thompson @param[out] numelem Variable to store number of elements 5487a982d89SJeremy L. Thompson 5497a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5507a982d89SJeremy L. Thompson 5517a982d89SJeremy L. Thompson @ref Backend 5527a982d89SJeremy L. Thompson **/ 5537a982d89SJeremy L. Thompson 5547a982d89SJeremy L. Thompson int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) { 5557a982d89SJeremy L. Thompson if (op->composite) 5567a982d89SJeremy L. Thompson // LCOV_EXCL_START 557e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 558e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 5597a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 5607a982d89SJeremy L. Thompson 5617a982d89SJeremy L. Thompson *numelem = op->numelements; 562e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5637a982d89SJeremy L. Thompson } 5647a982d89SJeremy L. Thompson 5657a982d89SJeremy L. Thompson /** 5667a982d89SJeremy L. Thompson @brief Get the number of quadrature points associated with a CeedOperator 5677a982d89SJeremy L. Thompson 5687a982d89SJeremy L. Thompson @param op CeedOperator 5697a982d89SJeremy L. Thompson @param[out] numqpts Variable to store vector number of quadrature points 5707a982d89SJeremy L. Thompson 5717a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5727a982d89SJeremy L. Thompson 5737a982d89SJeremy L. Thompson @ref Backend 5747a982d89SJeremy L. Thompson **/ 5757a982d89SJeremy L. Thompson 5767a982d89SJeremy L. Thompson int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) { 5777a982d89SJeremy L. Thompson if (op->composite) 5787a982d89SJeremy L. Thompson // LCOV_EXCL_START 579e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 580e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 5817a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 5827a982d89SJeremy L. Thompson 5837a982d89SJeremy L. Thompson *numqpts = op->numqpoints; 584e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5857a982d89SJeremy L. Thompson } 5867a982d89SJeremy L. Thompson 5877a982d89SJeremy L. Thompson /** 5887a982d89SJeremy L. Thompson @brief Get the number of arguments associated with a CeedOperator 5897a982d89SJeremy L. Thompson 5907a982d89SJeremy L. Thompson @param op CeedOperator 5917a982d89SJeremy L. Thompson @param[out] numargs Variable to store vector number of arguments 5927a982d89SJeremy L. Thompson 5937a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5947a982d89SJeremy L. Thompson 5957a982d89SJeremy L. Thompson @ref Backend 5967a982d89SJeremy L. Thompson **/ 5977a982d89SJeremy L. Thompson 5987a982d89SJeremy L. Thompson int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) { 5997a982d89SJeremy L. Thompson if (op->composite) 6007a982d89SJeremy L. Thompson // LCOV_EXCL_START 601e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 602e15f9bd0SJeremy L Thompson "Not defined for composite operators"); 6037a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 6047a982d89SJeremy L. Thompson 6057a982d89SJeremy L. Thompson *numargs = op->nfields; 606e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6077a982d89SJeremy L. Thompson } 6087a982d89SJeremy L. Thompson 6097a982d89SJeremy L. Thompson /** 6107a982d89SJeremy L. Thompson @brief Get the setup status of a CeedOperator 6117a982d89SJeremy L. Thompson 6127a982d89SJeremy L. Thompson @param op CeedOperator 613fd364f38SJeremy L Thompson @param[out] issetupdone Variable to store setup status 6147a982d89SJeremy L. Thompson 6157a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6167a982d89SJeremy L. Thompson 6177a982d89SJeremy L. Thompson @ref Backend 6187a982d89SJeremy L. Thompson **/ 6197a982d89SJeremy L. Thompson 620fd364f38SJeremy L Thompson int CeedOperatorIsSetupDone(CeedOperator op, bool *issetupdone) { 621e15f9bd0SJeremy L Thompson *issetupdone = op->backendsetup; 622e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6237a982d89SJeremy L. Thompson } 6247a982d89SJeremy L. Thompson 6257a982d89SJeremy L. Thompson /** 6267a982d89SJeremy L. Thompson @brief Get the QFunction associated with a CeedOperator 6277a982d89SJeremy L. Thompson 6287a982d89SJeremy L. Thompson @param op CeedOperator 6297a982d89SJeremy L. Thompson @param[out] qf Variable to store QFunction 6307a982d89SJeremy L. Thompson 6317a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6327a982d89SJeremy L. Thompson 6337a982d89SJeremy L. Thompson @ref Backend 6347a982d89SJeremy L. Thompson **/ 6357a982d89SJeremy L. Thompson 6367a982d89SJeremy L. Thompson int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 6377a982d89SJeremy L. Thompson if (op->composite) 6387a982d89SJeremy L. Thompson // LCOV_EXCL_START 639e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 640e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 6417a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 6427a982d89SJeremy L. Thompson 6437a982d89SJeremy L. Thompson *qf = op->qf; 644e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6457a982d89SJeremy L. Thompson } 6467a982d89SJeremy L. Thompson 6477a982d89SJeremy L. Thompson /** 648c04a41a7SJeremy L Thompson @brief Get a boolean value indicating if the CeedOperator is composite 649c04a41a7SJeremy L Thompson 650c04a41a7SJeremy L Thompson @param op CeedOperator 651fd364f38SJeremy L Thompson @param[out] iscomposite Variable to store composite status 652c04a41a7SJeremy L Thompson 653c04a41a7SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 654c04a41a7SJeremy L Thompson 655c04a41a7SJeremy L Thompson @ref Backend 656c04a41a7SJeremy L Thompson **/ 657c04a41a7SJeremy L Thompson 658fd364f38SJeremy L Thompson int CeedOperatorIsComposite(CeedOperator op, bool *iscomposite) { 659fd364f38SJeremy L Thompson *iscomposite = op->composite; 660e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 661c04a41a7SJeremy L Thompson } 662c04a41a7SJeremy L Thompson 663c04a41a7SJeremy L Thompson /** 6647a982d89SJeremy L. Thompson @brief Get the number of suboperators associated with a CeedOperator 6657a982d89SJeremy L. Thompson 6667a982d89SJeremy L. Thompson @param op CeedOperator 6677a982d89SJeremy L. Thompson @param[out] numsub Variable to store number of suboperators 6687a982d89SJeremy L. Thompson 6697a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6707a982d89SJeremy L. Thompson 6717a982d89SJeremy L. Thompson @ref Backend 6727a982d89SJeremy L. Thompson **/ 6737a982d89SJeremy L. Thompson 6747a982d89SJeremy L. Thompson int CeedOperatorGetNumSub(CeedOperator op, CeedInt *numsub) { 6757a982d89SJeremy L. Thompson if (!op->composite) 6767a982d89SJeremy L. Thompson // LCOV_EXCL_START 677e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator"); 6787a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 6797a982d89SJeremy L. Thompson 6807a982d89SJeremy L. Thompson *numsub = op->numsub; 681e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6827a982d89SJeremy L. Thompson } 6837a982d89SJeremy L. Thompson 6847a982d89SJeremy L. Thompson /** 6857a982d89SJeremy L. Thompson @brief Get the list of suboperators associated with a CeedOperator 6867a982d89SJeremy L. Thompson 6877a982d89SJeremy L. Thompson @param op CeedOperator 6887a982d89SJeremy L. Thompson @param[out] suboperators Variable to store list of suboperators 6897a982d89SJeremy L. Thompson 6907a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6917a982d89SJeremy L. Thompson 6927a982d89SJeremy L. Thompson @ref Backend 6937a982d89SJeremy L. Thompson **/ 6947a982d89SJeremy L. Thompson 6957a982d89SJeremy L. Thompson int CeedOperatorGetSubList(CeedOperator op, CeedOperator **suboperators) { 6967a982d89SJeremy L. Thompson if (!op->composite) 6977a982d89SJeremy L. Thompson // LCOV_EXCL_START 698e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator"); 6997a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 7007a982d89SJeremy L. Thompson 7017a982d89SJeremy L. Thompson *suboperators = op->suboperators; 702e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7037a982d89SJeremy L. Thompson } 7047a982d89SJeremy L. Thompson 7057a982d89SJeremy L. Thompson /** 7067a982d89SJeremy L. Thompson @brief Get the backend data of a CeedOperator 7077a982d89SJeremy L. Thompson 7087a982d89SJeremy L. Thompson @param op CeedOperator 7097a982d89SJeremy L. Thompson @param[out] data Variable to store data 7107a982d89SJeremy L. Thompson 7117a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7127a982d89SJeremy L. Thompson 7137a982d89SJeremy L. Thompson @ref Backend 7147a982d89SJeremy L. Thompson **/ 7157a982d89SJeremy L. Thompson 716777ff853SJeremy L Thompson int CeedOperatorGetData(CeedOperator op, void *data) { 717777ff853SJeremy L Thompson *(void **)data = op->data; 718e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7197a982d89SJeremy L. Thompson } 7207a982d89SJeremy L. Thompson 7217a982d89SJeremy L. Thompson /** 7227a982d89SJeremy L. Thompson @brief Set the backend data of a CeedOperator 7237a982d89SJeremy L. Thompson 7247a982d89SJeremy L. Thompson @param[out] op CeedOperator 7257a982d89SJeremy L. Thompson @param data Data to set 7267a982d89SJeremy L. Thompson 7277a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7287a982d89SJeremy L. Thompson 7297a982d89SJeremy L. Thompson @ref Backend 7307a982d89SJeremy L. Thompson **/ 7317a982d89SJeremy L. Thompson 732777ff853SJeremy L Thompson int CeedOperatorSetData(CeedOperator op, void *data) { 733777ff853SJeremy L Thompson op->data = data; 734e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7357a982d89SJeremy L. Thompson } 7367a982d89SJeremy L. Thompson 7377a982d89SJeremy L. Thompson /** 7387a982d89SJeremy L. Thompson @brief Set the setup flag of a CeedOperator to True 7397a982d89SJeremy L. Thompson 7407a982d89SJeremy L. Thompson @param op CeedOperator 7417a982d89SJeremy L. Thompson 7427a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7437a982d89SJeremy L. Thompson 7447a982d89SJeremy L. Thompson @ref Backend 7457a982d89SJeremy L. Thompson **/ 7467a982d89SJeremy L. Thompson 7477a982d89SJeremy L. Thompson int CeedOperatorSetSetupDone(CeedOperator op) { 748e15f9bd0SJeremy L Thompson op->backendsetup = true; 749e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7507a982d89SJeremy L. Thompson } 7517a982d89SJeremy L. Thompson 7527a982d89SJeremy L. Thompson /** 7537a982d89SJeremy L. Thompson @brief Get the CeedOperatorFields of a CeedOperator 7547a982d89SJeremy L. Thompson 7557a982d89SJeremy L. Thompson @param op CeedOperator 7567a982d89SJeremy L. Thompson @param[out] inputfields Variable to store inputfields 7577a982d89SJeremy L. Thompson @param[out] outputfields Variable to store outputfields 7587a982d89SJeremy L. Thompson 7597a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7607a982d89SJeremy L. Thompson 7617a982d89SJeremy L. Thompson @ref Backend 7627a982d89SJeremy L. Thompson **/ 7637a982d89SJeremy L. Thompson 7647a982d89SJeremy L. Thompson int CeedOperatorGetFields(CeedOperator op, CeedOperatorField **inputfields, 7657a982d89SJeremy L. Thompson CeedOperatorField **outputfields) { 7667a982d89SJeremy L. Thompson if (op->composite) 7677a982d89SJeremy L. Thompson // LCOV_EXCL_START 768e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 769e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 7707a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 7717a982d89SJeremy L. Thompson 7727a982d89SJeremy L. Thompson if (inputfields) *inputfields = op->inputfields; 7737a982d89SJeremy L. Thompson if (outputfields) *outputfields = op->outputfields; 774e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7757a982d89SJeremy L. Thompson } 7767a982d89SJeremy L. Thompson 7777a982d89SJeremy L. Thompson /** 7787a982d89SJeremy L. Thompson @brief Get the CeedElemRestriction of a CeedOperatorField 7797a982d89SJeremy L. Thompson 7807a982d89SJeremy L. Thompson @param opfield CeedOperatorField 7817a982d89SJeremy L. Thompson @param[out] rstr Variable to store CeedElemRestriction 7827a982d89SJeremy L. Thompson 7837a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7847a982d89SJeremy L. Thompson 7857a982d89SJeremy L. Thompson @ref Backend 7867a982d89SJeremy L. Thompson **/ 7877a982d89SJeremy L. Thompson 7887a982d89SJeremy L. Thompson int CeedOperatorFieldGetElemRestriction(CeedOperatorField opfield, 7897a982d89SJeremy L. Thompson CeedElemRestriction *rstr) { 7907a982d89SJeremy L. Thompson *rstr = opfield->Erestrict; 791e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7927a982d89SJeremy L. Thompson } 7937a982d89SJeremy L. Thompson 7947a982d89SJeremy L. Thompson /** 7957a982d89SJeremy L. Thompson @brief Get the CeedBasis of a CeedOperatorField 7967a982d89SJeremy L. Thompson 7977a982d89SJeremy L. Thompson @param opfield CeedOperatorField 7987a982d89SJeremy L. Thompson @param[out] basis Variable to store CeedBasis 7997a982d89SJeremy L. Thompson 8007a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 8017a982d89SJeremy L. Thompson 8027a982d89SJeremy L. Thompson @ref Backend 8037a982d89SJeremy L. Thompson **/ 8047a982d89SJeremy L. Thompson 8057a982d89SJeremy L. Thompson int CeedOperatorFieldGetBasis(CeedOperatorField opfield, CeedBasis *basis) { 8067a982d89SJeremy L. Thompson *basis = opfield->basis; 807e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8087a982d89SJeremy L. Thompson } 8097a982d89SJeremy L. Thompson 8107a982d89SJeremy L. Thompson /** 8117a982d89SJeremy L. Thompson @brief Get the CeedVector of a CeedOperatorField 8127a982d89SJeremy L. Thompson 8137a982d89SJeremy L. Thompson @param opfield CeedOperatorField 8147a982d89SJeremy L. Thompson @param[out] vec Variable to store CeedVector 8157a982d89SJeremy L. Thompson 8167a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 8177a982d89SJeremy L. Thompson 8187a982d89SJeremy L. Thompson @ref Backend 8197a982d89SJeremy L. Thompson **/ 8207a982d89SJeremy L. Thompson 8217a982d89SJeremy L. Thompson int CeedOperatorFieldGetVector(CeedOperatorField opfield, CeedVector *vec) { 8227a982d89SJeremy L. Thompson *vec = opfield->vec; 823e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8247a982d89SJeremy L. Thompson } 8257a982d89SJeremy L. Thompson 8267a982d89SJeremy L. Thompson /// @} 8277a982d89SJeremy L. Thompson 8287a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 8297a982d89SJeremy L. Thompson /// CeedOperator Public API 8307a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 8317a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorUser 832dfdf5a53Sjeremylt /// @{ 833d7b241e6Sjeremylt 834d7b241e6Sjeremylt /** 8350219ea01SJeremy L Thompson @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and 8360219ea01SJeremy L Thompson CeedElemRestriction can be associated with CeedQFunction fields with 8370219ea01SJeremy L Thompson \ref CeedOperatorSetField. 838d7b241e6Sjeremylt 839b11c1e72Sjeremylt @param ceed A Ceed object where the CeedOperator will be created 840d7b241e6Sjeremylt @param qf QFunction defining the action of the operator at quadrature points 84134138859Sjeremylt @param dqf QFunction defining the action of the Jacobian of @a qf (or 8424cc79fe7SJed Brown @ref CEED_QFUNCTION_NONE) 843d7b241e6Sjeremylt @param dqfT QFunction defining the action of the transpose of the Jacobian 8444cc79fe7SJed Brown of @a qf (or @ref CEED_QFUNCTION_NONE) 845b11c1e72Sjeremylt @param[out] op Address of the variable where the newly created 846b11c1e72Sjeremylt CeedOperator will be stored 847b11c1e72Sjeremylt 848b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 849dfdf5a53Sjeremylt 8507a982d89SJeremy L. Thompson @ref User 851d7b241e6Sjeremylt */ 852d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf, 853d7b241e6Sjeremylt CeedQFunction dqfT, CeedOperator *op) { 854d7b241e6Sjeremylt int ierr; 855d7b241e6Sjeremylt 8565fe0d4faSjeremylt if (!ceed->OperatorCreate) { 8575fe0d4faSjeremylt Ceed delegate; 858aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 8595fe0d4faSjeremylt 8605fe0d4faSjeremylt if (!delegate) 861c042f62fSJeremy L Thompson // LCOV_EXCL_START 862e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 863e15f9bd0SJeremy L Thompson "Backend does not support OperatorCreate"); 864c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 8655fe0d4faSjeremylt 8665fe0d4faSjeremylt ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr); 867e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8685fe0d4faSjeremylt } 8695fe0d4faSjeremylt 870b3b7035fSJeremy L Thompson if (!qf || qf == CEED_QFUNCTION_NONE) 871b3b7035fSJeremy L Thompson // LCOV_EXCL_START 872e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 873e15f9bd0SJeremy L Thompson "Operator must have a valid QFunction."); 874b3b7035fSJeremy L Thompson // LCOV_EXCL_STOP 875d7b241e6Sjeremylt ierr = CeedCalloc(1, op); CeedChk(ierr); 876d7b241e6Sjeremylt (*op)->ceed = ceed; 877d7b241e6Sjeremylt ceed->refcount++; 878d7b241e6Sjeremylt (*op)->refcount = 1; 879d7b241e6Sjeremylt (*op)->qf = qf; 880d7b241e6Sjeremylt qf->refcount++; 881442e7f0bSjeremylt if (dqf && dqf != CEED_QFUNCTION_NONE) { 882d7b241e6Sjeremylt (*op)->dqf = dqf; 883442e7f0bSjeremylt dqf->refcount++; 884442e7f0bSjeremylt } 885442e7f0bSjeremylt if (dqfT && dqfT != CEED_QFUNCTION_NONE) { 886d7b241e6Sjeremylt (*op)->dqfT = dqfT; 887442e7f0bSjeremylt dqfT->refcount++; 888442e7f0bSjeremylt } 889fe2413ffSjeremylt ierr = CeedCalloc(16, &(*op)->inputfields); CeedChk(ierr); 890fe2413ffSjeremylt ierr = CeedCalloc(16, &(*op)->outputfields); CeedChk(ierr); 891d7b241e6Sjeremylt ierr = ceed->OperatorCreate(*op); CeedChk(ierr); 892e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 893d7b241e6Sjeremylt } 894d7b241e6Sjeremylt 895d7b241e6Sjeremylt /** 89652d6035fSJeremy L Thompson @brief Create an operator that composes the action of several operators 89752d6035fSJeremy L Thompson 89852d6035fSJeremy L Thompson @param ceed A Ceed object where the CeedOperator will be created 89952d6035fSJeremy L Thompson @param[out] op Address of the variable where the newly created 90052d6035fSJeremy L Thompson Composite CeedOperator will be stored 90152d6035fSJeremy L Thompson 90252d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 90352d6035fSJeremy L Thompson 9047a982d89SJeremy L. Thompson @ref User 90552d6035fSJeremy L Thompson */ 90652d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) { 90752d6035fSJeremy L Thompson int ierr; 90852d6035fSJeremy L Thompson 90952d6035fSJeremy L Thompson if (!ceed->CompositeOperatorCreate) { 91052d6035fSJeremy L Thompson Ceed delegate; 911aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 91252d6035fSJeremy L Thompson 913250756a7Sjeremylt if (delegate) { 91452d6035fSJeremy L Thompson ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr); 915e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 91652d6035fSJeremy L Thompson } 917250756a7Sjeremylt } 91852d6035fSJeremy L Thompson 91952d6035fSJeremy L Thompson ierr = CeedCalloc(1, op); CeedChk(ierr); 92052d6035fSJeremy L Thompson (*op)->ceed = ceed; 92152d6035fSJeremy L Thompson ceed->refcount++; 92252d6035fSJeremy L Thompson (*op)->composite = true; 92352d6035fSJeremy L Thompson ierr = CeedCalloc(16, &(*op)->suboperators); CeedChk(ierr); 924250756a7Sjeremylt 925250756a7Sjeremylt if (ceed->CompositeOperatorCreate) { 92652d6035fSJeremy L Thompson ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr); 927250756a7Sjeremylt } 928e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 92952d6035fSJeremy L Thompson } 93052d6035fSJeremy L Thompson 93152d6035fSJeremy L Thompson /** 932b11c1e72Sjeremylt @brief Provide a field to a CeedOperator for use by its CeedQFunction 933d7b241e6Sjeremylt 934d7b241e6Sjeremylt This function is used to specify both active and passive fields to a 935d7b241e6Sjeremylt CeedOperator. For passive fields, a vector @arg v must be provided. Passive 936d7b241e6Sjeremylt fields can inputs or outputs (updated in-place when operator is applied). 937d7b241e6Sjeremylt 938d7b241e6Sjeremylt Active fields must be specified using this function, but their data (in a 939d7b241e6Sjeremylt CeedVector) is passed in CeedOperatorApply(). There can be at most one active 940d7b241e6Sjeremylt input and at most one active output. 941d7b241e6Sjeremylt 9428c91a0c9SJeremy L Thompson @param op CeedOperator on which to provide the field 9438795c945Sjeremylt @param fieldname Name of the field (to be matched with the name used by 9448795c945Sjeremylt CeedQFunction) 945b11c1e72Sjeremylt @param r CeedElemRestriction 9464cc79fe7SJed Brown @param b CeedBasis in which the field resides or @ref CEED_BASIS_COLLOCATED 947b11c1e72Sjeremylt if collocated with quadrature points 9484cc79fe7SJed Brown @param v CeedVector to be used by CeedOperator or @ref CEED_VECTOR_ACTIVE 9494cc79fe7SJed Brown if field is active or @ref CEED_VECTOR_NONE if using 9504cc79fe7SJed Brown @ref CEED_EVAL_WEIGHT in the QFunction 951b11c1e72Sjeremylt 952b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 953dfdf5a53Sjeremylt 9547a982d89SJeremy L. Thompson @ref User 955b11c1e72Sjeremylt **/ 956d7b241e6Sjeremylt int CeedOperatorSetField(CeedOperator op, const char *fieldname, 957a8d32208Sjeremylt CeedElemRestriction r, CeedBasis b, CeedVector v) { 958d7b241e6Sjeremylt int ierr; 95952d6035fSJeremy L Thompson if (op->composite) 960c042f62fSJeremy L Thompson // LCOV_EXCL_START 961e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 962e15f9bd0SJeremy L Thompson "Cannot add field to composite operator."); 963c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 9648b067b84SJed Brown if (!r) 965c042f62fSJeremy L Thompson // LCOV_EXCL_START 966e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 967c042f62fSJeremy L Thompson "ElemRestriction r for field \"%s\" must be non-NULL.", 968c042f62fSJeremy L Thompson fieldname); 969c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 9708b067b84SJed Brown if (!b) 971c042f62fSJeremy L Thompson // LCOV_EXCL_START 972e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 973e15f9bd0SJeremy L Thompson "Basis b for field \"%s\" must be non-NULL.", 974c042f62fSJeremy L Thompson fieldname); 975c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 9768b067b84SJed Brown if (!v) 977c042f62fSJeremy L Thompson // LCOV_EXCL_START 978e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 979e15f9bd0SJeremy L Thompson "Vector v for field \"%s\" must be non-NULL.", 980c042f62fSJeremy L Thompson fieldname); 981c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 98252d6035fSJeremy L Thompson 983d7b241e6Sjeremylt CeedInt numelements; 984d7b241e6Sjeremylt ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr); 98515910d16Sjeremylt if (r != CEED_ELEMRESTRICTION_NONE && op->hasrestriction && 98615910d16Sjeremylt op->numelements != numelements) 987c042f62fSJeremy L Thompson // LCOV_EXCL_START 988e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 9891d102b48SJeremy L Thompson "ElemRestriction with %d elements incompatible with prior " 9901d102b48SJeremy L Thompson "%d elements", numelements, op->numelements); 991c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 992d7b241e6Sjeremylt 993d7b241e6Sjeremylt CeedInt numqpoints; 994e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 995d7b241e6Sjeremylt ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr); 996d7b241e6Sjeremylt if (op->numqpoints && op->numqpoints != numqpoints) 997c042f62fSJeremy L Thompson // LCOV_EXCL_START 998e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 999e15f9bd0SJeremy L Thompson "Basis with %d quadrature points " 10001d102b48SJeremy L Thompson "incompatible with prior %d points", numqpoints, 10011d102b48SJeremy L Thompson op->numqpoints); 1002c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1003d7b241e6Sjeremylt } 100415910d16Sjeremylt CeedQFunctionField qfield; 1005d1bcdac9Sjeremylt CeedOperatorField *ofield; 1006d7b241e6Sjeremylt for (CeedInt i=0; i<op->qf->numinputfields; i++) { 1007fe2413ffSjeremylt if (!strcmp(fieldname, (*op->qf->inputfields[i]).fieldname)) { 100815910d16Sjeremylt qfield = op->qf->inputfields[i]; 1009d7b241e6Sjeremylt ofield = &op->inputfields[i]; 1010d7b241e6Sjeremylt goto found; 1011d7b241e6Sjeremylt } 1012d7b241e6Sjeremylt } 1013d7b241e6Sjeremylt for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 1014fe2413ffSjeremylt if (!strcmp(fieldname, (*op->qf->outputfields[i]).fieldname)) { 1015e15f9bd0SJeremy L Thompson qfield = op->qf->outputfields[i]; 1016d7b241e6Sjeremylt ofield = &op->outputfields[i]; 1017d7b241e6Sjeremylt goto found; 1018d7b241e6Sjeremylt } 1019d7b241e6Sjeremylt } 1020c042f62fSJeremy L Thompson // LCOV_EXCL_START 1021e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_INCOMPLETE, 1022e15f9bd0SJeremy L Thompson "QFunction has no knowledge of field '%s'", 1023d7b241e6Sjeremylt fieldname); 1024c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1025d7b241e6Sjeremylt found: 1026e15f9bd0SJeremy L Thompson ierr = CeedOperatorCheckField(op->ceed, qfield, r, b); CeedChk(ierr); 1027fe2413ffSjeremylt ierr = CeedCalloc(1, ofield); CeedChk(ierr); 1028e15f9bd0SJeremy L Thompson 1029e15f9bd0SJeremy L Thompson (*ofield)->vec = v; 1030e15f9bd0SJeremy L Thompson if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) { 1031e15f9bd0SJeremy L Thompson v->refcount += 1; 1032e15f9bd0SJeremy L Thompson } 1033e15f9bd0SJeremy L Thompson 1034fe2413ffSjeremylt (*ofield)->Erestrict = r; 103571352a93Sjeremylt r->refcount += 1; 1036e15f9bd0SJeremy L Thompson if (r != CEED_ELEMRESTRICTION_NONE) { 1037e15f9bd0SJeremy L Thompson op->numelements = numelements; 1038e15f9bd0SJeremy L Thompson op->hasrestriction = true; // Restriction set, but numelements may be 0 1039e15f9bd0SJeremy L Thompson } 1040d99fa3c5SJeremy L Thompson 1041e15f9bd0SJeremy L Thompson (*ofield)->basis = b; 1042e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 1043e15f9bd0SJeremy L Thompson op->numqpoints = numqpoints; 1044e15f9bd0SJeremy L Thompson b->refcount += 1; 1045e15f9bd0SJeremy L Thompson } 1046e15f9bd0SJeremy L Thompson 1047e15f9bd0SJeremy L Thompson op->nfields += 1; 1048d99fa3c5SJeremy L Thompson size_t len = strlen(fieldname); 1049d99fa3c5SJeremy L Thompson char *tmp; 1050d99fa3c5SJeremy L Thompson ierr = CeedCalloc(len+1, &tmp); CeedChk(ierr); 1051d99fa3c5SJeremy L Thompson memcpy(tmp, fieldname, len+1); 1052d99fa3c5SJeremy L Thompson (*ofield)->fieldname = tmp; 1053e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1054d7b241e6Sjeremylt } 1055d7b241e6Sjeremylt 1056d7b241e6Sjeremylt /** 105752d6035fSJeremy L Thompson @brief Add a sub-operator to a composite CeedOperator 1058288c0443SJeremy L Thompson 105934138859Sjeremylt @param[out] compositeop Composite CeedOperator 106034138859Sjeremylt @param subop Sub-operator CeedOperator 106152d6035fSJeremy L Thompson 106252d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 106352d6035fSJeremy L Thompson 10647a982d89SJeremy L. Thompson @ref User 106552d6035fSJeremy L Thompson */ 1066692c2638Sjeremylt int CeedCompositeOperatorAddSub(CeedOperator compositeop, CeedOperator subop) { 106752d6035fSJeremy L Thompson if (!compositeop->composite) 1068c042f62fSJeremy L Thompson // LCOV_EXCL_START 1069e15f9bd0SJeremy L Thompson return CeedError(compositeop->ceed, CEED_ERROR_MINOR, 1070*e2f04181SAndrew T. Barker "CeedOperator is not a composite operator"); 1071c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 107252d6035fSJeremy L Thompson 107352d6035fSJeremy L Thompson if (compositeop->numsub == CEED_COMPOSITE_MAX) 1074c042f62fSJeremy L Thompson // LCOV_EXCL_START 1075e15f9bd0SJeremy L Thompson return CeedError(compositeop->ceed, CEED_ERROR_UNSUPPORTED, 1076e15f9bd0SJeremy L Thompson "Cannot add additional suboperators"); 1077c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 107852d6035fSJeremy L Thompson 107952d6035fSJeremy L Thompson compositeop->suboperators[compositeop->numsub] = subop; 108052d6035fSJeremy L Thompson subop->refcount++; 108152d6035fSJeremy L Thompson compositeop->numsub++; 1082e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 108352d6035fSJeremy L Thompson } 108452d6035fSJeremy L Thompson 108552d6035fSJeremy L Thompson /** 10861d102b48SJeremy L Thompson @brief Assemble a linear CeedQFunction associated with a CeedOperator 10871d102b48SJeremy L Thompson 10881d102b48SJeremy L Thompson This returns a CeedVector containing a matrix at each quadrature point 10891d102b48SJeremy L Thompson providing the action of the CeedQFunction associated with the CeedOperator. 10901d102b48SJeremy L Thompson The vector 'assembled' is of shape 10911d102b48SJeremy L Thompson [num_elements, num_input_fields, num_output_fields, num_quad_points] 10921d102b48SJeremy L Thompson and contains column-major matrices representing the action of the 10931d102b48SJeremy L Thompson CeedQFunction for a corresponding quadrature point on an element. Inputs and 10941d102b48SJeremy L Thompson outputs are in the order provided by the user when adding CeedOperator fields. 10954cc79fe7SJed Brown For example, a CeedQFunction with inputs 'u' and 'gradu' and outputs 'gradv' and 10961d102b48SJeremy L Thompson 'v', provided in that order, would result in an assembled QFunction that 10971d102b48SJeremy L Thompson consists of (1 + dim) x (dim + 1) matrices at each quadrature point acting 10981d102b48SJeremy L Thompson on the input [u, du_0, du_1] and producing the output [dv_0, dv_1, v]. 10991d102b48SJeremy L Thompson 11001d102b48SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 11011d102b48SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedQFunction at 11021d102b48SJeremy L Thompson quadrature points 11031d102b48SJeremy L Thompson @param[out] rstr CeedElemRestriction for CeedVector containing assembled 11041d102b48SJeremy L Thompson CeedQFunction 11051d102b48SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 11064cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 11071d102b48SJeremy L Thompson 11081d102b48SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 11091d102b48SJeremy L Thompson 11107a982d89SJeremy L. Thompson @ref User 11111d102b48SJeremy L Thompson **/ 111280ac2e43SJeremy L Thompson int CeedOperatorLinearAssembleQFunction(CeedOperator op, CeedVector *assembled, 11137f823360Sjeremylt CeedElemRestriction *rstr, 11147f823360Sjeremylt CeedRequest *request) { 11151d102b48SJeremy L Thompson int ierr; 1116*e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 11171d102b48SJeremy L Thompson 11187172caadSjeremylt // Backend version 111980ac2e43SJeremy L Thompson if (op->LinearAssembleQFunction) { 1120*e2f04181SAndrew T. Barker return op->LinearAssembleQFunction(op, assembled, rstr, request); 11215107b09fSJeremy L Thompson } else { 11225107b09fSJeremy L Thompson // Fallback to reference Ceed 11235107b09fSJeremy L Thompson if (!op->opfallback) { 11245107b09fSJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 11255107b09fSJeremy L Thompson } 11265107b09fSJeremy L Thompson // Assemble 1127*e2f04181SAndrew T. Barker return CeedOperatorLinearAssembleQFunction(op->opfallback, assembled, 1128*e2f04181SAndrew T. Barker rstr, request); 11295107b09fSJeremy L Thompson } 11301d102b48SJeremy L Thompson } 11311d102b48SJeremy L Thompson 11321d102b48SJeremy L Thompson /** 1133d965c7a7SJeremy L Thompson @brief Assemble the diagonal of a square linear CeedOperator 1134b7ec98d8SJeremy L Thompson 11359e9210b8SJeremy L Thompson This overwrites a CeedVector with the diagonal of a linear CeedOperator. 1136b7ec98d8SJeremy L Thompson 1137c04a41a7SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 1138c04a41a7SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 1139d965c7a7SJeremy L Thompson 1140b7ec98d8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 1141b7ec98d8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator diagonal 1142b7ec98d8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 11434cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 1144b7ec98d8SJeremy L Thompson 1145b7ec98d8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1146b7ec98d8SJeremy L Thompson 11477a982d89SJeremy L. Thompson @ref User 1148b7ec98d8SJeremy L Thompson **/ 11492bba3ffaSJeremy L Thompson int CeedOperatorLinearAssembleDiagonal(CeedOperator op, CeedVector assembled, 11507f823360Sjeremylt CeedRequest *request) { 1151b7ec98d8SJeremy L Thompson int ierr; 1152*e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1153b7ec98d8SJeremy L Thompson 1154b7ec98d8SJeremy L Thompson // Use backend version, if available 115580ac2e43SJeremy L Thompson if (op->LinearAssembleDiagonal) { 1156*e2f04181SAndrew T. Barker return op->LinearAssembleDiagonal(op, assembled, request); 11579e9210b8SJeremy L Thompson } else if (op->LinearAssembleAddDiagonal) { 11589e9210b8SJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 11599e9210b8SJeremy L Thompson return CeedOperatorLinearAssembleAddDiagonal(op, assembled, request); 11609e9210b8SJeremy L Thompson } else { 11619e9210b8SJeremy L Thompson // Fallback to reference Ceed 11629e9210b8SJeremy L Thompson if (!op->opfallback) { 11639e9210b8SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 11649e9210b8SJeremy L Thompson } 11659e9210b8SJeremy L Thompson // Assemble 1166*e2f04181SAndrew T. Barker return CeedOperatorLinearAssembleDiagonal(op->opfallback, assembled, 1167*e2f04181SAndrew T. Barker request); 11689e9210b8SJeremy L Thompson } 11699e9210b8SJeremy L Thompson } 11709e9210b8SJeremy L Thompson 11719e9210b8SJeremy L Thompson /** 11729e9210b8SJeremy L Thompson @brief Assemble the diagonal of a square linear CeedOperator 11739e9210b8SJeremy L Thompson 11749e9210b8SJeremy L Thompson This sums into a CeedVector the diagonal of a linear CeedOperator. 11759e9210b8SJeremy L Thompson 11769e9210b8SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 11779e9210b8SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 11789e9210b8SJeremy L Thompson 11799e9210b8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 11809e9210b8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator diagonal 11819e9210b8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 11829e9210b8SJeremy L Thompson @ref CEED_REQUEST_IMMEDIATE 11839e9210b8SJeremy L Thompson 11849e9210b8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 11859e9210b8SJeremy L Thompson 11869e9210b8SJeremy L Thompson @ref User 11879e9210b8SJeremy L Thompson **/ 11889e9210b8SJeremy L Thompson int CeedOperatorLinearAssembleAddDiagonal(CeedOperator op, CeedVector assembled, 11899e9210b8SJeremy L Thompson CeedRequest *request) { 11909e9210b8SJeremy L Thompson int ierr; 1191*e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 11929e9210b8SJeremy L Thompson 11939e9210b8SJeremy L Thompson // Use backend version, if available 11949e9210b8SJeremy L Thompson if (op->LinearAssembleAddDiagonal) { 1195*e2f04181SAndrew T. Barker return op->LinearAssembleAddDiagonal(op, assembled, request); 11967172caadSjeremylt } else { 11977172caadSjeremylt // Fallback to reference Ceed 11987172caadSjeremylt if (!op->opfallback) { 11997172caadSjeremylt ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1200b7ec98d8SJeremy L Thompson } 12017172caadSjeremylt // Assemble 1202*e2f04181SAndrew T. Barker return CeedOperatorLinearAssembleAddDiagonal(op->opfallback, assembled, 1203*e2f04181SAndrew T. Barker request); 1204b7ec98d8SJeremy L Thompson } 1205b7ec98d8SJeremy L Thompson } 1206b7ec98d8SJeremy L Thompson 1207b7ec98d8SJeremy L Thompson /** 1208d965c7a7SJeremy L Thompson @brief Assemble the point block diagonal of a square linear CeedOperator 1209d965c7a7SJeremy L Thompson 12109e9210b8SJeremy L Thompson This overwrites a CeedVector with the point block diagonal of a linear 1211d965c7a7SJeremy L Thompson CeedOperator. 1212d965c7a7SJeremy L Thompson 1213c04a41a7SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 1214c04a41a7SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 1215d965c7a7SJeremy L Thompson 1216d965c7a7SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 1217d965c7a7SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator point block 1218d965c7a7SJeremy L Thompson diagonal, provided in row-major form with an 1219d965c7a7SJeremy L Thompson @a ncomp * @a ncomp block at each node. The dimensions 1220d965c7a7SJeremy L Thompson of this vector are derived from the active vector 1221d965c7a7SJeremy L Thompson for the CeedOperator. The array has shape 1222d965c7a7SJeremy L Thompson [nodes, component out, component in]. 1223d965c7a7SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 1224d965c7a7SJeremy L Thompson CEED_REQUEST_IMMEDIATE 1225d965c7a7SJeremy L Thompson 1226d965c7a7SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1227d965c7a7SJeremy L Thompson 1228d965c7a7SJeremy L Thompson @ref User 1229d965c7a7SJeremy L Thompson **/ 123080ac2e43SJeremy L Thompson int CeedOperatorLinearAssemblePointBlockDiagonal(CeedOperator op, 12312bba3ffaSJeremy L Thompson CeedVector assembled, CeedRequest *request) { 1232d965c7a7SJeremy L Thompson int ierr; 1233*e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1234d965c7a7SJeremy L Thompson 1235d965c7a7SJeremy L Thompson // Use backend version, if available 123680ac2e43SJeremy L Thompson if (op->LinearAssemblePointBlockDiagonal) { 1237*e2f04181SAndrew T. Barker return op->LinearAssemblePointBlockDiagonal(op, assembled, request); 12389e9210b8SJeremy L Thompson } else if (op->LinearAssembleAddPointBlockDiagonal) { 12399e9210b8SJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 12409e9210b8SJeremy L Thompson return CeedOperatorLinearAssembleAddPointBlockDiagonal(op, assembled, 12419e9210b8SJeremy L Thompson request); 1242d965c7a7SJeremy L Thompson } else { 1243d965c7a7SJeremy L Thompson // Fallback to reference Ceed 1244d965c7a7SJeremy L Thompson if (!op->opfallback) { 1245d965c7a7SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1246d965c7a7SJeremy L Thompson } 1247d965c7a7SJeremy L Thompson // Assemble 1248*e2f04181SAndrew T. Barker return CeedOperatorLinearAssemblePointBlockDiagonal(op->opfallback, 1249*e2f04181SAndrew T. Barker assembled, request); 12509e9210b8SJeremy L Thompson } 12519e9210b8SJeremy L Thompson } 12529e9210b8SJeremy L Thompson 12539e9210b8SJeremy L Thompson /** 12549e9210b8SJeremy L Thompson @brief Assemble the point block diagonal of a square linear CeedOperator 12559e9210b8SJeremy L Thompson 12569e9210b8SJeremy L Thompson This sums into a CeedVector with the point block diagonal of a linear 12579e9210b8SJeremy L Thompson CeedOperator. 12589e9210b8SJeremy L Thompson 12599e9210b8SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 12609e9210b8SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 12619e9210b8SJeremy L Thompson 12629e9210b8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 12639e9210b8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator point block 12649e9210b8SJeremy L Thompson diagonal, provided in row-major form with an 12659e9210b8SJeremy L Thompson @a ncomp * @a ncomp block at each node. The dimensions 12669e9210b8SJeremy L Thompson of this vector are derived from the active vector 12679e9210b8SJeremy L Thompson for the CeedOperator. The array has shape 12689e9210b8SJeremy L Thompson [nodes, component out, component in]. 12699e9210b8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 12709e9210b8SJeremy L Thompson CEED_REQUEST_IMMEDIATE 12719e9210b8SJeremy L Thompson 12729e9210b8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 12739e9210b8SJeremy L Thompson 12749e9210b8SJeremy L Thompson @ref User 12759e9210b8SJeremy L Thompson **/ 12769e9210b8SJeremy L Thompson int CeedOperatorLinearAssembleAddPointBlockDiagonal(CeedOperator op, 12779e9210b8SJeremy L Thompson CeedVector assembled, CeedRequest *request) { 12789e9210b8SJeremy L Thompson int ierr; 1279*e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 12809e9210b8SJeremy L Thompson 12819e9210b8SJeremy L Thompson // Use backend version, if available 12829e9210b8SJeremy L Thompson if (op->LinearAssembleAddPointBlockDiagonal) { 1283*e2f04181SAndrew T. Barker return op->LinearAssembleAddPointBlockDiagonal(op, assembled, request); 12849e9210b8SJeremy L Thompson } else { 12859e9210b8SJeremy L Thompson // Fallback to reference Ceed 12869e9210b8SJeremy L Thompson if (!op->opfallback) { 12879e9210b8SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 12889e9210b8SJeremy L Thompson } 12899e9210b8SJeremy L Thompson // Assemble 1290*e2f04181SAndrew T. Barker return CeedOperatorLinearAssembleAddPointBlockDiagonal(op->opfallback, 1291*e2f04181SAndrew T. Barker assembled, request); 1292d965c7a7SJeremy L Thompson } 1293*e2f04181SAndrew T. Barker } 1294*e2f04181SAndrew T. Barker 1295*e2f04181SAndrew T. Barker /** 1296*e2f04181SAndrew T. Barker @brief Build nonzero pattern for non-composite operator. 1297*e2f04181SAndrew T. Barker 1298*e2f04181SAndrew T. Barker Users should generally use CeedOperatorLinearAssembleSymbolic() 1299*e2f04181SAndrew T. Barker 1300*e2f04181SAndrew T. Barker @ref Developer 1301*e2f04181SAndrew T. Barker **/ 1302*e2f04181SAndrew T. Barker int CeedSingleOperatorAssembleSymbolic(CeedOperator op, CeedInt offset, 1303*e2f04181SAndrew T. Barker CeedInt *rows, CeedInt *cols) { 1304*e2f04181SAndrew T. Barker int ierr; 1305*e2f04181SAndrew T. Barker Ceed ceed = op->ceed; 1306*e2f04181SAndrew T. Barker if (op->composite) 1307*e2f04181SAndrew T. Barker // LCOV_EXCL_START 1308*e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 1309*e2f04181SAndrew T. Barker "Composite operator not supported"); 1310*e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1311*e2f04181SAndrew T. Barker 1312*e2f04181SAndrew T. Barker CeedElemRestriction rstrin; 1313*e2f04181SAndrew T. Barker ierr = CeedOperatorGetActiveElemRestriction(op, &rstrin); CeedChk(ierr); 1314*e2f04181SAndrew T. Barker CeedInt nelem, elemsize, nnodes, ncomp; 1315*e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetNumElements(rstrin, &nelem); CeedChk(ierr); 1316*e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetElementSize(rstrin, &elemsize); CeedChk(ierr); 1317*e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetLVectorSize(rstrin, &nnodes); CeedChk(ierr); 1318*e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetNumComponents(rstrin, &ncomp); CeedChk(ierr); 1319*e2f04181SAndrew T. Barker CeedInt layout_er[3]; 1320*e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetELayout(rstrin, &layout_er); CeedChk(ierr); 1321*e2f04181SAndrew T. Barker 1322*e2f04181SAndrew T. Barker CeedInt local_nentries = elemsize*ncomp * elemsize*ncomp * nelem; 1323*e2f04181SAndrew T. Barker 1324*e2f04181SAndrew T. Barker // Determine elem_dof relation 1325*e2f04181SAndrew T. Barker CeedVector index_vec; 1326*e2f04181SAndrew T. Barker ierr = CeedVectorCreate(ceed, nnodes, &index_vec); CeedChk(ierr); 1327*e2f04181SAndrew T. Barker CeedScalar *array; 1328*e2f04181SAndrew T. Barker ierr = CeedVectorGetArray(index_vec, CEED_MEM_HOST, &array); CeedChk(ierr); 1329*e2f04181SAndrew T. Barker for (CeedInt i = 0; i < nnodes; ++i) { 1330*e2f04181SAndrew T. Barker array[i] = i; 1331*e2f04181SAndrew T. Barker } 1332*e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArray(index_vec, &array); CeedChk(ierr); 1333*e2f04181SAndrew T. Barker CeedVector elem_dof; 1334*e2f04181SAndrew T. Barker ierr = CeedVectorCreate(ceed, nelem * elemsize * ncomp, &elem_dof); 1335*e2f04181SAndrew T. Barker CeedChk(ierr); 1336*e2f04181SAndrew T. Barker ierr = CeedVectorSetValue(elem_dof, 0.0); CeedChk(ierr); 1337*e2f04181SAndrew T. Barker CeedElemRestrictionApply(rstrin, CEED_NOTRANSPOSE, index_vec, 1338*e2f04181SAndrew T. Barker elem_dof, CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 1339*e2f04181SAndrew T. Barker const CeedScalar *elem_dof_a; 1340*e2f04181SAndrew T. Barker ierr = CeedVectorGetArrayRead(elem_dof, CEED_MEM_HOST, &elem_dof_a); 1341*e2f04181SAndrew T. Barker CeedChk(ierr); 1342*e2f04181SAndrew T. Barker ierr = CeedVectorDestroy(&index_vec); CeedChk(ierr); 1343*e2f04181SAndrew T. Barker 1344*e2f04181SAndrew T. Barker // Determine i, j locations for element matrices 1345*e2f04181SAndrew T. Barker CeedInt count = 0; 1346*e2f04181SAndrew T. Barker for (int e = 0; e < nelem; ++e) { 1347*e2f04181SAndrew T. Barker for (int compin = 0; compin < ncomp; ++compin) { 1348*e2f04181SAndrew T. Barker for (int compout = 0; compout < ncomp; ++compout) { 1349*e2f04181SAndrew T. Barker for (int i = 0; i < elemsize; ++i) { 1350*e2f04181SAndrew T. Barker for (int j = 0; j < elemsize; ++j) { 1351*e2f04181SAndrew T. Barker const CeedInt edof_index_row = (i)*layout_er[0] + 1352*e2f04181SAndrew T. Barker (compout)*layout_er[1] + e*layout_er[2]; 1353*e2f04181SAndrew T. Barker const CeedInt edof_index_col = (j)*layout_er[0] + 1354*e2f04181SAndrew T. Barker (compin)*layout_er[1] + e*layout_er[2]; 1355*e2f04181SAndrew T. Barker 1356*e2f04181SAndrew T. Barker const CeedInt row = elem_dof_a[edof_index_row]; 1357*e2f04181SAndrew T. Barker const CeedInt col = elem_dof_a[edof_index_col]; 1358*e2f04181SAndrew T. Barker 1359*e2f04181SAndrew T. Barker rows[offset + count] = row; 1360*e2f04181SAndrew T. Barker cols[offset + count] = col; 1361*e2f04181SAndrew T. Barker count++; 1362*e2f04181SAndrew T. Barker } 1363*e2f04181SAndrew T. Barker } 1364*e2f04181SAndrew T. Barker } 1365*e2f04181SAndrew T. Barker } 1366*e2f04181SAndrew T. Barker } 1367*e2f04181SAndrew T. Barker if (count != local_nentries) 1368*e2f04181SAndrew T. Barker // LCOV_EXCL_START 1369*e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_MAJOR, "Error computing assembled entries"); 1370*e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1371*e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArrayRead(elem_dof, &elem_dof_a); CeedChk(ierr); 1372*e2f04181SAndrew T. Barker ierr = CeedVectorDestroy(&elem_dof); CeedChk(ierr); 1373*e2f04181SAndrew T. Barker 1374*e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1375*e2f04181SAndrew T. Barker } 1376*e2f04181SAndrew T. Barker 1377*e2f04181SAndrew T. Barker /** 1378*e2f04181SAndrew T. Barker @brief Assemble nonzero entries for non-composite operator 1379*e2f04181SAndrew T. Barker 1380*e2f04181SAndrew T. Barker Users should generally use CeedOperatorLinearAssemble() 1381*e2f04181SAndrew T. Barker 1382*e2f04181SAndrew T. Barker @ref Developer 1383*e2f04181SAndrew T. Barker **/ 1384*e2f04181SAndrew T. Barker int CeedSingleOperatorAssemble(CeedOperator op, CeedInt offset, 1385*e2f04181SAndrew T. Barker CeedVector values) { 1386*e2f04181SAndrew T. Barker int ierr; 1387*e2f04181SAndrew T. Barker Ceed ceed = op->ceed;; 1388*e2f04181SAndrew T. Barker if (op->composite) 1389*e2f04181SAndrew T. Barker // LCOV_EXCL_START 1390*e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 1391*e2f04181SAndrew T. Barker "Composite operator not supported"); 1392*e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1393*e2f04181SAndrew T. Barker 1394*e2f04181SAndrew T. Barker // Assemble QFunction 1395*e2f04181SAndrew T. Barker CeedQFunction qf; 1396*e2f04181SAndrew T. Barker ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 1397*e2f04181SAndrew T. Barker CeedInt numinputfields, numoutputfields; 1398*e2f04181SAndrew T. Barker ierr= CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 1399*e2f04181SAndrew T. Barker CeedChk(ierr); 1400*e2f04181SAndrew T. Barker CeedVector assembledqf; 1401*e2f04181SAndrew T. Barker CeedElemRestriction rstr_q; 1402*e2f04181SAndrew T. Barker ierr = CeedOperatorLinearAssembleQFunction( 1403*e2f04181SAndrew T. Barker op, &assembledqf, &rstr_q, CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 1404*e2f04181SAndrew T. Barker 1405*e2f04181SAndrew T. Barker CeedInt qflength; 1406*e2f04181SAndrew T. Barker ierr = CeedVectorGetLength(assembledqf, &qflength); CeedChk(ierr); 1407*e2f04181SAndrew T. Barker 1408*e2f04181SAndrew T. Barker CeedOperatorField *input_fields; 1409*e2f04181SAndrew T. Barker CeedOperatorField *output_fields; 1410*e2f04181SAndrew T. Barker ierr = CeedOperatorGetFields(op, &input_fields, &output_fields); CeedChk(ierr); 1411*e2f04181SAndrew T. Barker 1412*e2f04181SAndrew T. Barker // Determine active input basis 1413*e2f04181SAndrew T. Barker CeedQFunctionField *qffields; 1414*e2f04181SAndrew T. Barker ierr = CeedQFunctionGetFields(qf, &qffields, NULL); CeedChk(ierr); 1415*e2f04181SAndrew T. Barker CeedInt numemodein = 0, dim = 1; 1416*e2f04181SAndrew T. Barker CeedEvalMode *emodein = NULL; 1417*e2f04181SAndrew T. Barker CeedBasis basisin = NULL; 1418*e2f04181SAndrew T. Barker CeedElemRestriction rstrin = NULL; 1419*e2f04181SAndrew T. Barker for (CeedInt i=0; i<numinputfields; i++) { 1420*e2f04181SAndrew T. Barker CeedVector vec; 1421*e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetVector(input_fields[i], &vec); CeedChk(ierr); 1422*e2f04181SAndrew T. Barker if (vec == CEED_VECTOR_ACTIVE) { 1423*e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetBasis(input_fields[i], &basisin); 1424*e2f04181SAndrew T. Barker CeedChk(ierr); 1425*e2f04181SAndrew T. Barker ierr = CeedBasisGetDimension(basisin, &dim); CeedChk(ierr); 1426*e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetElemRestriction(input_fields[i], &rstrin); 1427*e2f04181SAndrew T. Barker CeedChk(ierr); 1428*e2f04181SAndrew T. Barker CeedEvalMode emode; 1429*e2f04181SAndrew T. Barker ierr = CeedQFunctionFieldGetEvalMode(qffields[i], &emode); 1430*e2f04181SAndrew T. Barker CeedChk(ierr); 1431*e2f04181SAndrew T. Barker switch (emode) { 1432*e2f04181SAndrew T. Barker case CEED_EVAL_NONE: 1433*e2f04181SAndrew T. Barker case CEED_EVAL_INTERP: 1434*e2f04181SAndrew T. Barker ierr = CeedRealloc(numemodein + 1, &emodein); CeedChk(ierr); 1435*e2f04181SAndrew T. Barker emodein[numemodein] = emode; 1436*e2f04181SAndrew T. Barker numemodein += 1; 1437*e2f04181SAndrew T. Barker break; 1438*e2f04181SAndrew T. Barker case CEED_EVAL_GRAD: 1439*e2f04181SAndrew T. Barker ierr = CeedRealloc(numemodein + dim, &emodein); CeedChk(ierr); 1440*e2f04181SAndrew T. Barker for (CeedInt d=0; d<dim; d++) { 1441*e2f04181SAndrew T. Barker emodein[numemodein+d] = emode; 1442*e2f04181SAndrew T. Barker } 1443*e2f04181SAndrew T. Barker numemodein += dim; 1444*e2f04181SAndrew T. Barker break; 1445*e2f04181SAndrew T. Barker case CEED_EVAL_WEIGHT: 1446*e2f04181SAndrew T. Barker case CEED_EVAL_DIV: 1447*e2f04181SAndrew T. Barker case CEED_EVAL_CURL: 1448*e2f04181SAndrew T. Barker break; // Caught by QF Assembly 1449*e2f04181SAndrew T. Barker } 1450*e2f04181SAndrew T. Barker } 1451*e2f04181SAndrew T. Barker } 1452*e2f04181SAndrew T. Barker 1453*e2f04181SAndrew T. Barker // Determine active output basis 1454*e2f04181SAndrew T. Barker ierr = CeedQFunctionGetFields(qf, NULL, &qffields); CeedChk(ierr); 1455*e2f04181SAndrew T. Barker CeedInt numemodeout = 0; 1456*e2f04181SAndrew T. Barker CeedEvalMode *emodeout = NULL; 1457*e2f04181SAndrew T. Barker CeedBasis basisout = NULL; 1458*e2f04181SAndrew T. Barker CeedElemRestriction rstrout = NULL; 1459*e2f04181SAndrew T. Barker for (CeedInt i=0; i<numoutputfields; i++) { 1460*e2f04181SAndrew T. Barker CeedVector vec; 1461*e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetVector(output_fields[i], &vec); CeedChk(ierr); 1462*e2f04181SAndrew T. Barker if (vec == CEED_VECTOR_ACTIVE) { 1463*e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetBasis(output_fields[i], &basisout); 1464*e2f04181SAndrew T. Barker CeedChk(ierr); 1465*e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetElemRestriction(output_fields[i], &rstrout); 1466*e2f04181SAndrew T. Barker CeedChk(ierr); 1467*e2f04181SAndrew T. Barker CeedEvalMode emode; 1468*e2f04181SAndrew T. Barker ierr = CeedQFunctionFieldGetEvalMode(qffields[i], &emode); 1469*e2f04181SAndrew T. Barker CeedChk(ierr); 1470*e2f04181SAndrew T. Barker switch (emode) { 1471*e2f04181SAndrew T. Barker case CEED_EVAL_NONE: 1472*e2f04181SAndrew T. Barker case CEED_EVAL_INTERP: 1473*e2f04181SAndrew T. Barker ierr = CeedRealloc(numemodeout + 1, &emodeout); CeedChk(ierr); 1474*e2f04181SAndrew T. Barker emodeout[numemodeout] = emode; 1475*e2f04181SAndrew T. Barker numemodeout += 1; 1476*e2f04181SAndrew T. Barker break; 1477*e2f04181SAndrew T. Barker case CEED_EVAL_GRAD: 1478*e2f04181SAndrew T. Barker ierr = CeedRealloc(numemodeout + dim, &emodeout); CeedChk(ierr); 1479*e2f04181SAndrew T. Barker for (CeedInt d=0; d<dim; d++) { 1480*e2f04181SAndrew T. Barker emodeout[numemodeout+d] = emode; 1481*e2f04181SAndrew T. Barker } 1482*e2f04181SAndrew T. Barker numemodeout += dim; 1483*e2f04181SAndrew T. Barker break; 1484*e2f04181SAndrew T. Barker case CEED_EVAL_WEIGHT: 1485*e2f04181SAndrew T. Barker case CEED_EVAL_DIV: 1486*e2f04181SAndrew T. Barker case CEED_EVAL_CURL: 1487*e2f04181SAndrew T. Barker break; // Caught by QF Assembly 1488*e2f04181SAndrew T. Barker } 1489*e2f04181SAndrew T. Barker } 1490*e2f04181SAndrew T. Barker } 1491*e2f04181SAndrew T. Barker 1492*e2f04181SAndrew T. Barker CeedInt nelem, elemsize, nqpts, ncomp; 1493*e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetNumElements(rstrin, &nelem); CeedChk(ierr); 1494*e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetElementSize(rstrin, &elemsize); CeedChk(ierr); 1495*e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetNumComponents(rstrin, &ncomp); CeedChk(ierr); 1496*e2f04181SAndrew T. Barker ierr = CeedBasisGetNumQuadraturePoints(basisin, &nqpts); CeedChk(ierr); 1497*e2f04181SAndrew T. Barker 1498*e2f04181SAndrew T. Barker CeedInt local_nentries = elemsize*ncomp * elemsize*ncomp * nelem; 1499*e2f04181SAndrew T. Barker 1500*e2f04181SAndrew T. Barker // loop over elements and put in data structure 1501*e2f04181SAndrew T. Barker const CeedScalar *interpin, *gradin; 1502*e2f04181SAndrew T. Barker ierr = CeedBasisGetInterp(basisin, &interpin); CeedChk(ierr); 1503*e2f04181SAndrew T. Barker ierr = CeedBasisGetGrad(basisin, &gradin); CeedChk(ierr); 1504*e2f04181SAndrew T. Barker 1505*e2f04181SAndrew T. Barker const CeedScalar *assembledqfarray; 1506*e2f04181SAndrew T. Barker ierr = CeedVectorGetArrayRead(assembledqf, CEED_MEM_HOST, &assembledqfarray); 1507*e2f04181SAndrew T. Barker CeedChk(ierr); 1508*e2f04181SAndrew T. Barker 1509*e2f04181SAndrew T. Barker CeedInt layout_qf[3]; 1510*e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetELayout(rstr_q, &layout_qf); CeedChk(ierr); 1511*e2f04181SAndrew T. Barker ierr = CeedElemRestrictionDestroy(&rstr_q); CeedChk(ierr); 1512*e2f04181SAndrew T. Barker 1513*e2f04181SAndrew T. Barker // we store Bmat_in, Bmat_out, BTD, elem_mat in row-major order 1514*e2f04181SAndrew T. Barker CeedScalar Bmat_in[(nqpts * numemodein) * elemsize]; 1515*e2f04181SAndrew T. Barker CeedScalar Bmat_out[(nqpts * numemodeout) * elemsize]; 1516*e2f04181SAndrew T. Barker CeedScalar Dmat[numemodeout * numemodein * nqpts]; // logically 3-tensor 1517*e2f04181SAndrew T. Barker CeedScalar BTD[elemsize * nqpts*numemodein]; 1518*e2f04181SAndrew T. Barker CeedScalar elem_mat[elemsize * elemsize]; 1519*e2f04181SAndrew T. Barker int count = 0; 1520*e2f04181SAndrew T. Barker CeedScalar *vals; 1521*e2f04181SAndrew T. Barker ierr = CeedVectorGetArray(values, CEED_MEM_HOST, &vals); CeedChk(ierr); 1522*e2f04181SAndrew T. Barker for (int e = 0; e < nelem; ++e) { 1523*e2f04181SAndrew T. Barker for (int compin = 0; compin < ncomp; ++compin) { 1524*e2f04181SAndrew T. Barker for (int compout = 0; compout < ncomp; ++compout) { 1525*e2f04181SAndrew T. Barker for (int ell = 0; ell < (nqpts * numemodein) * elemsize; ++ell) { 1526*e2f04181SAndrew T. Barker Bmat_in[ell] = 0.0; 1527*e2f04181SAndrew T. Barker } 1528*e2f04181SAndrew T. Barker for (int ell = 0; ell < (nqpts * numemodeout) * elemsize; ++ell) { 1529*e2f04181SAndrew T. Barker Bmat_out[ell] = 0.0; 1530*e2f04181SAndrew T. Barker } 1531*e2f04181SAndrew T. Barker // Store block-diagonal D matrix as collection of small dense blocks 1532*e2f04181SAndrew T. Barker for (int ell = 0; ell < numemodein*numemodeout*nqpts; ++ell) { 1533*e2f04181SAndrew T. Barker Dmat[ell] = 0.0; 1534*e2f04181SAndrew T. Barker } 1535*e2f04181SAndrew T. Barker // form element matrix itself (for each block component) 1536*e2f04181SAndrew T. Barker for (int ell = 0; ell < elemsize*elemsize; ++ell) { 1537*e2f04181SAndrew T. Barker elem_mat[ell] = 0.0; 1538*e2f04181SAndrew T. Barker } 1539*e2f04181SAndrew T. Barker for (int q = 0; q < nqpts; ++q) { 1540*e2f04181SAndrew T. Barker for (int n = 0; n < elemsize; ++n) { 1541*e2f04181SAndrew T. Barker CeedInt din = -1; 1542*e2f04181SAndrew T. Barker for (int ein = 0; ein < numemodein; ++ein) { 1543*e2f04181SAndrew T. Barker const int qq = numemodein*q; 1544*e2f04181SAndrew T. Barker if (emodein[ein] == CEED_EVAL_INTERP) { 1545*e2f04181SAndrew T. Barker Bmat_in[(qq+ein)*elemsize + n] += interpin[q * elemsize + n]; 1546*e2f04181SAndrew T. Barker } else if (emodein[ein] == CEED_EVAL_GRAD) { 1547*e2f04181SAndrew T. Barker din += 1; 1548*e2f04181SAndrew T. Barker Bmat_in[(qq+ein)*elemsize + n] += 1549*e2f04181SAndrew T. Barker gradin[(din*nqpts+q) * elemsize + n]; 1550*e2f04181SAndrew T. Barker } else { 1551*e2f04181SAndrew T. Barker // LCOV_EXCL_START 1552*e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Not implemented!"); 1553*e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1554*e2f04181SAndrew T. Barker } 1555*e2f04181SAndrew T. Barker } 1556*e2f04181SAndrew T. Barker CeedInt dout = -1; 1557*e2f04181SAndrew T. Barker for (int eout = 0; eout < numemodeout; ++eout) { 1558*e2f04181SAndrew T. Barker const int qq = numemodeout*q; 1559*e2f04181SAndrew T. Barker if (emodeout[eout] == CEED_EVAL_INTERP) { 1560*e2f04181SAndrew T. Barker Bmat_out[(qq+eout)*elemsize + n] += interpin[q * elemsize + n]; 1561*e2f04181SAndrew T. Barker } else if (emodeout[eout] == CEED_EVAL_GRAD) { 1562*e2f04181SAndrew T. Barker dout += 1; 1563*e2f04181SAndrew T. Barker Bmat_out[(qq+eout)*elemsize + n] += 1564*e2f04181SAndrew T. Barker gradin[(dout*nqpts+q) * elemsize + n]; 1565*e2f04181SAndrew T. Barker } else { 1566*e2f04181SAndrew T. Barker // LCOV_EXCL_START 1567*e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Not implemented!"); 1568*e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1569*e2f04181SAndrew T. Barker } 1570*e2f04181SAndrew T. Barker } 1571*e2f04181SAndrew T. Barker } 1572*e2f04181SAndrew T. Barker for (int ei = 0; ei < numemodeout; ++ei) { 1573*e2f04181SAndrew T. Barker for (int ej = 0; ej < numemodein; ++ej) { 1574*e2f04181SAndrew T. Barker const int emode_index = ((ei*ncomp+compin)*numemodein+ej)*ncomp+compout; 1575*e2f04181SAndrew T. Barker const int index = q*layout_qf[0] + emode_index*layout_qf[1] + e*layout_qf[2]; 1576*e2f04181SAndrew T. Barker Dmat[(ei*numemodein+ej)*nqpts + q] += assembledqfarray[index]; 1577*e2f04181SAndrew T. Barker } 1578*e2f04181SAndrew T. Barker } 1579*e2f04181SAndrew T. Barker } 1580*e2f04181SAndrew T. Barker // Compute B^T*D 1581*e2f04181SAndrew T. Barker for (int ell = 0; ell < elemsize*nqpts*numemodein; ++ell) { 1582*e2f04181SAndrew T. Barker BTD[ell] = 0.0; 1583*e2f04181SAndrew T. Barker } 1584*e2f04181SAndrew T. Barker for (int j = 0; j<elemsize; ++j) { 1585*e2f04181SAndrew T. Barker for (int q = 0; q<nqpts; ++q) { 1586*e2f04181SAndrew T. Barker int qq = numemodeout*q; 1587*e2f04181SAndrew T. Barker for (int ei = 0; ei < numemodein; ++ei) { 1588*e2f04181SAndrew T. Barker for (int ej = 0; ej < numemodeout; ++ej) { 1589*e2f04181SAndrew T. Barker BTD[j*(nqpts*numemodein) + (qq+ei)] += 1590*e2f04181SAndrew T. Barker Bmat_out[(qq+ej)*elemsize + j] * Dmat[(ei*numemodein+ej)*nqpts + q]; 1591*e2f04181SAndrew T. Barker } 1592*e2f04181SAndrew T. Barker } 1593*e2f04181SAndrew T. Barker } 1594*e2f04181SAndrew T. Barker } 1595*e2f04181SAndrew T. Barker 1596*e2f04181SAndrew T. Barker ierr = CeedMatrixMultiply(ceed, BTD, Bmat_in, elem_mat, elemsize, 1597*e2f04181SAndrew T. Barker elemsize, nqpts*numemodein); CeedChk(ierr); 1598*e2f04181SAndrew T. Barker 1599*e2f04181SAndrew T. Barker // put element matrix in coordinate data structure 1600*e2f04181SAndrew T. Barker for (int i = 0; i < elemsize; ++i) { 1601*e2f04181SAndrew T. Barker for (int j = 0; j < elemsize; ++j) { 1602*e2f04181SAndrew T. Barker vals[offset + count] = elem_mat[i*elemsize + j]; 1603*e2f04181SAndrew T. Barker count++; 1604*e2f04181SAndrew T. Barker } 1605*e2f04181SAndrew T. Barker } 1606*e2f04181SAndrew T. Barker } 1607*e2f04181SAndrew T. Barker } 1608*e2f04181SAndrew T. Barker } 1609*e2f04181SAndrew T. Barker if (count != local_nentries) 1610*e2f04181SAndrew T. Barker // LCOV_EXCL_START 1611*e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_MAJOR, "Error computing entries"); 1612*e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1613*e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArray(values, &vals); CeedChk(ierr); 1614*e2f04181SAndrew T. Barker 1615*e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArrayRead(assembledqf, &assembledqfarray); 1616*e2f04181SAndrew T. Barker CeedChk(ierr); 1617*e2f04181SAndrew T. Barker ierr = CeedVectorDestroy(&assembledqf); CeedChk(ierr); 1618*e2f04181SAndrew T. Barker ierr = CeedFree(&emodein); CeedChk(ierr); 1619*e2f04181SAndrew T. Barker ierr = CeedFree(&emodeout); CeedChk(ierr); 1620*e2f04181SAndrew T. Barker 1621*e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1622*e2f04181SAndrew T. Barker } 1623*e2f04181SAndrew T. Barker 1624*e2f04181SAndrew T. Barker /** 1625*e2f04181SAndrew T. Barker @ref Utility 1626*e2f04181SAndrew T. Barker **/ 1627*e2f04181SAndrew T. Barker int CeedSingleOperatorAssemblyCountEntries(CeedOperator op, CeedInt *nentries) { 1628*e2f04181SAndrew T. Barker int ierr; 1629*e2f04181SAndrew T. Barker CeedElemRestriction rstr; 1630*e2f04181SAndrew T. Barker CeedInt nelem, elemsize, ncomp; 1631*e2f04181SAndrew T. Barker 1632*e2f04181SAndrew T. Barker if (op->composite) 1633*e2f04181SAndrew T. Barker // LCOV_EXCL_START 1634*e2f04181SAndrew T. Barker return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 1635*e2f04181SAndrew T. Barker "Composite operator not supported"); 1636*e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1637*e2f04181SAndrew T. Barker ierr = CeedOperatorGetActiveElemRestriction(op, &rstr); CeedChk(ierr); 1638*e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetNumElements(rstr, &nelem); CeedChk(ierr); 1639*e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetElementSize(rstr, &elemsize); CeedChk(ierr); 1640*e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetNumComponents(rstr, &ncomp); CeedChk(ierr); 1641*e2f04181SAndrew T. Barker *nentries = elemsize*ncomp * elemsize*ncomp * nelem; 1642*e2f04181SAndrew T. Barker 1643*e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1644*e2f04181SAndrew T. Barker } 1645*e2f04181SAndrew T. Barker 1646*e2f04181SAndrew T. Barker /** 1647*e2f04181SAndrew T. Barker @brief Fully assemble the nonzero pattern of a linear operator. 1648*e2f04181SAndrew T. Barker 1649*e2f04181SAndrew T. Barker Expected to be used in conjunction with CeedOperatorLinearAssemble() 1650*e2f04181SAndrew T. Barker 1651*e2f04181SAndrew T. Barker The assembly routines use coordinate format, with nentries tuples of the 1652*e2f04181SAndrew T. Barker form (i, j, value) which indicate that value should be added to the matrix 1653*e2f04181SAndrew T. Barker in entry (i, j). Note that the (i, j) pairs are not unique and may repeat. 1654*e2f04181SAndrew T. Barker This function returns the number of entries and their (i, j) locations, 1655*e2f04181SAndrew T. Barker while CeedOperatorLinearAssemble() provides the values in the same 1656*e2f04181SAndrew T. Barker ordering. 1657*e2f04181SAndrew T. Barker 1658*e2f04181SAndrew T. Barker This will generally be slow unless your operator is low-order. 1659*e2f04181SAndrew T. Barker 1660*e2f04181SAndrew T. Barker @param[in] op CeedOperator to assemble 1661*e2f04181SAndrew T. Barker @param[out] nentries Number of entries in coordinate nonzero pattern. 1662*e2f04181SAndrew T. Barker @param[out] rows Row number for each entry. 1663*e2f04181SAndrew T. Barker @param[out] cols Column number for each entry. 1664*e2f04181SAndrew T. Barker 1665*e2f04181SAndrew T. Barker @ref User 1666*e2f04181SAndrew T. Barker **/ 1667*e2f04181SAndrew T. Barker int CeedOperatorLinearAssembleSymbolic(CeedOperator op, 1668*e2f04181SAndrew T. Barker CeedInt *nentries, CeedInt **rows, CeedInt **cols) { 1669*e2f04181SAndrew T. Barker int ierr; 1670*e2f04181SAndrew T. Barker CeedInt numsub, single_entries; 1671*e2f04181SAndrew T. Barker CeedOperator *suboperators; 1672*e2f04181SAndrew T. Barker bool isComposite; 1673*e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1674*e2f04181SAndrew T. Barker 1675*e2f04181SAndrew T. Barker // Use backend version, if available 1676*e2f04181SAndrew T. Barker if (op->LinearAssembleSymbolic) { 1677*e2f04181SAndrew T. Barker return op->LinearAssembleSymbolic(op, nentries, rows, cols); 1678*e2f04181SAndrew T. Barker } else { 1679*e2f04181SAndrew T. Barker // Check for valid fallback resource 1680*e2f04181SAndrew T. Barker const char *resource, *fallbackresource; 1681*e2f04181SAndrew T. Barker ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr); 1682*e2f04181SAndrew T. Barker ierr = CeedGetOperatorFallbackResource(op->ceed, &fallbackresource); 1683*e2f04181SAndrew T. Barker if (strcmp(fallbackresource, "") && strcmp(resource, fallbackresource)) { 1684*e2f04181SAndrew T. Barker // Fallback to reference Ceed 1685*e2f04181SAndrew T. Barker if (!op->opfallback) { 1686*e2f04181SAndrew T. Barker ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1687*e2f04181SAndrew T. Barker } 1688*e2f04181SAndrew T. Barker // Assemble 1689*e2f04181SAndrew T. Barker return CeedOperatorLinearAssembleSymbolic(op->opfallback, nentries, rows, cols); 1690*e2f04181SAndrew T. Barker } 1691*e2f04181SAndrew T. Barker } 1692*e2f04181SAndrew T. Barker 1693*e2f04181SAndrew T. Barker // if neither backend nor fallback resource provides 1694*e2f04181SAndrew T. Barker // LinearAssembleSymbolic, continue with interface-level implementation 1695*e2f04181SAndrew T. Barker 1696*e2f04181SAndrew T. Barker // count entries and allocate rows, cols arrays 1697*e2f04181SAndrew T. Barker ierr = CeedOperatorIsComposite(op, &isComposite); CeedChk(ierr); 1698*e2f04181SAndrew T. Barker *nentries = 0; 1699*e2f04181SAndrew T. Barker if (isComposite) { 1700*e2f04181SAndrew T. Barker ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 1701*e2f04181SAndrew T. Barker ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 1702*e2f04181SAndrew T. Barker for (int k = 0; k < numsub; ++k) { 1703*e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemblyCountEntries(suboperators[k], 1704*e2f04181SAndrew T. Barker &single_entries); CeedChk(ierr); 1705*e2f04181SAndrew T. Barker *nentries += single_entries; 1706*e2f04181SAndrew T. Barker } 1707*e2f04181SAndrew T. Barker } else { 1708*e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemblyCountEntries(op, 1709*e2f04181SAndrew T. Barker &single_entries); CeedChk(ierr); 1710*e2f04181SAndrew T. Barker *nentries += single_entries; 1711*e2f04181SAndrew T. Barker } 1712*e2f04181SAndrew T. Barker ierr = CeedCalloc(*nentries, rows); CeedChk(ierr); 1713*e2f04181SAndrew T. Barker ierr = CeedCalloc(*nentries, cols); CeedChk(ierr); 1714*e2f04181SAndrew T. Barker 1715*e2f04181SAndrew T. Barker // assemble nonzero locations 1716*e2f04181SAndrew T. Barker CeedInt offset = 0; 1717*e2f04181SAndrew T. Barker if (isComposite) { 1718*e2f04181SAndrew T. Barker ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 1719*e2f04181SAndrew T. Barker ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 1720*e2f04181SAndrew T. Barker for (int k = 0; k < numsub; ++k) { 1721*e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssembleSymbolic(suboperators[k], offset, *rows, 1722*e2f04181SAndrew T. Barker *cols); CeedChk(ierr); 1723*e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemblyCountEntries(suboperators[k], &single_entries); 1724*e2f04181SAndrew T. Barker CeedChk(ierr); 1725*e2f04181SAndrew T. Barker offset += single_entries; 1726*e2f04181SAndrew T. Barker } 1727*e2f04181SAndrew T. Barker } else { 1728*e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssembleSymbolic(op, offset, *rows, *cols); 1729*e2f04181SAndrew T. Barker CeedChk(ierr); 1730*e2f04181SAndrew T. Barker } 1731*e2f04181SAndrew T. Barker 1732*e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1733*e2f04181SAndrew T. Barker } 1734*e2f04181SAndrew T. Barker 1735*e2f04181SAndrew T. Barker /** 1736*e2f04181SAndrew T. Barker @brief Fully assemble the nonzero entries of a linear operator. 1737*e2f04181SAndrew T. Barker 1738*e2f04181SAndrew T. Barker Expected to be used in conjunction with CeedOperatorLinearAssembleSymbolic() 1739*e2f04181SAndrew T. Barker 1740*e2f04181SAndrew T. Barker The assembly routines use coordinate format, with nentries tuples of the 1741*e2f04181SAndrew T. Barker form (i, j, value) which indicate that value should be added to the matrix 1742*e2f04181SAndrew T. Barker in entry (i, j). Note that the (i, j) pairs are not unique and may repeat. 1743*e2f04181SAndrew T. Barker This function returns the values of the nonzero entries to be added, their 1744*e2f04181SAndrew T. Barker (i, j) locations are provided by CeedOperatorLinearAssembleSymbolic() 1745*e2f04181SAndrew T. Barker 1746*e2f04181SAndrew T. Barker This will generally be slow unless your operator is low-order. 1747*e2f04181SAndrew T. Barker 1748*e2f04181SAndrew T. Barker @param[in] op CeedOperator to assemble 1749*e2f04181SAndrew T. Barker @param[out] values Values to assemble into matrix 1750*e2f04181SAndrew T. Barker 1751*e2f04181SAndrew T. Barker @ref User 1752*e2f04181SAndrew T. Barker **/ 1753*e2f04181SAndrew T. Barker int CeedOperatorLinearAssemble(CeedOperator op, CeedVector values) { 1754*e2f04181SAndrew T. Barker int ierr; 1755*e2f04181SAndrew T. Barker CeedInt numsub, single_entries; 1756*e2f04181SAndrew T. Barker CeedOperator *suboperators; 1757*e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1758*e2f04181SAndrew T. Barker 1759*e2f04181SAndrew T. Barker // Use backend version, if available 1760*e2f04181SAndrew T. Barker if (op->LinearAssemble) { 1761*e2f04181SAndrew T. Barker return op->LinearAssemble(op, values); 1762*e2f04181SAndrew T. Barker } else { 1763*e2f04181SAndrew T. Barker // Check for valid fallback resource 1764*e2f04181SAndrew T. Barker const char *resource, *fallbackresource; 1765*e2f04181SAndrew T. Barker ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr); 1766*e2f04181SAndrew T. Barker ierr = CeedGetOperatorFallbackResource(op->ceed, &fallbackresource); 1767*e2f04181SAndrew T. Barker if (strcmp(fallbackresource, "") && strcmp(resource, fallbackresource)) { 1768*e2f04181SAndrew T. Barker // Fallback to reference Ceed 1769*e2f04181SAndrew T. Barker if (!op->opfallback) { 1770*e2f04181SAndrew T. Barker ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1771*e2f04181SAndrew T. Barker } 1772*e2f04181SAndrew T. Barker // Assemble 1773*e2f04181SAndrew T. Barker return CeedOperatorLinearAssemble(op->opfallback, values); 1774*e2f04181SAndrew T. Barker } 1775*e2f04181SAndrew T. Barker } 1776*e2f04181SAndrew T. Barker 1777*e2f04181SAndrew T. Barker // if neither backend nor fallback resource provides 1778*e2f04181SAndrew T. Barker // LinearAssemble, continue with interface-level implementation 1779*e2f04181SAndrew T. Barker 1780*e2f04181SAndrew T. Barker bool isComposite; 1781*e2f04181SAndrew T. Barker ierr = CeedOperatorIsComposite(op, &isComposite); CeedChk(ierr); 1782*e2f04181SAndrew T. Barker 1783*e2f04181SAndrew T. Barker CeedInt offset = 0; 1784*e2f04181SAndrew T. Barker if (isComposite) { 1785*e2f04181SAndrew T. Barker ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 1786*e2f04181SAndrew T. Barker ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 1787*e2f04181SAndrew T. Barker for (int k = 0; k < numsub; ++k) { 1788*e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemble(suboperators[k], offset, values); 1789*e2f04181SAndrew T. Barker CeedChk(ierr); 1790*e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemblyCountEntries(suboperators[k], &single_entries); 1791*e2f04181SAndrew T. Barker CeedChk(ierr); 1792*e2f04181SAndrew T. Barker offset += single_entries; 1793*e2f04181SAndrew T. Barker } 1794*e2f04181SAndrew T. Barker } else { 1795*e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemble(op, offset, values); CeedChk(ierr); 1796*e2f04181SAndrew T. Barker } 1797*e2f04181SAndrew T. Barker 1798e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1799d965c7a7SJeremy L Thompson } 1800d965c7a7SJeremy L Thompson 1801d965c7a7SJeremy L Thompson /** 1802d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1803d99fa3c5SJeremy L Thompson for a CeedOperator, creating the prolongation basis from the 1804d99fa3c5SJeremy L Thompson fine and coarse grid interpolation 1805d99fa3c5SJeremy L Thompson 1806d99fa3c5SJeremy L Thompson @param[in] opFine Fine grid operator 1807d99fa3c5SJeremy L Thompson @param[in] PMultFine L-vector multiplicity in parallel gather/scatter 1808d99fa3c5SJeremy L Thompson @param[in] rstrCoarse Coarse grid restriction 1809d99fa3c5SJeremy L Thompson @param[in] basisCoarse Coarse grid active vector basis 1810d99fa3c5SJeremy L Thompson @param[out] opCoarse Coarse grid operator 1811d99fa3c5SJeremy L Thompson @param[out] opProlong Coarse to fine operator 1812d99fa3c5SJeremy L Thompson @param[out] opRestrict Fine to coarse operator 1813d99fa3c5SJeremy L Thompson 1814d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1815d99fa3c5SJeremy L Thompson 1816d99fa3c5SJeremy L Thompson @ref User 1817d99fa3c5SJeremy L Thompson **/ 1818d99fa3c5SJeremy L Thompson int CeedOperatorMultigridLevelCreate(CeedOperator opFine, CeedVector PMultFine, 1819d99fa3c5SJeremy L Thompson CeedElemRestriction rstrCoarse, CeedBasis basisCoarse, 1820d99fa3c5SJeremy L Thompson CeedOperator *opCoarse, CeedOperator *opProlong, CeedOperator *opRestrict) { 1821d99fa3c5SJeremy L Thompson int ierr; 1822d99fa3c5SJeremy L Thompson Ceed ceed; 1823d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(opFine, &ceed); CeedChk(ierr); 1824d99fa3c5SJeremy L Thompson 1825d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 1826d99fa3c5SJeremy L Thompson CeedBasis basisFine; 1827d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetActiveBasis(opFine, &basisFine); CeedChk(ierr); 1828d99fa3c5SJeremy L Thompson CeedInt Qf, Qc; 1829d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisFine, &Qf); CeedChk(ierr); 1830d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisCoarse, &Qc); CeedChk(ierr); 1831d99fa3c5SJeremy L Thompson if (Qf != Qc) 1832d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1833e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 1834e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 1835d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1836d99fa3c5SJeremy L Thompson 1837d99fa3c5SJeremy L Thompson // Coarse to fine basis 1838d99fa3c5SJeremy L Thompson CeedInt Pf, Pc, Q = Qf; 1839d99fa3c5SJeremy L Thompson bool isTensorF, isTensorC; 1840d99fa3c5SJeremy L Thompson ierr = CeedBasisIsTensor(basisFine, &isTensorF); CeedChk(ierr); 1841d99fa3c5SJeremy L Thompson ierr = CeedBasisIsTensor(basisCoarse, &isTensorC); CeedChk(ierr); 1842d99fa3c5SJeremy L Thompson CeedScalar *interpC, *interpF, *interpCtoF, *tau; 1843d99fa3c5SJeremy L Thompson if (isTensorF && isTensorC) { 1844d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes1D(basisFine, &Pf); CeedChk(ierr); 1845d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes1D(basisCoarse, &Pc); CeedChk(ierr); 1846d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints1D(basisCoarse, &Q); CeedChk(ierr); 1847d99fa3c5SJeremy L Thompson } else if (!isTensorF && !isTensorC) { 1848d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes(basisFine, &Pf); CeedChk(ierr); 1849d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes(basisCoarse, &Pc); CeedChk(ierr); 1850d99fa3c5SJeremy L Thompson } else { 1851d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1852e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 1853e15f9bd0SJeremy L Thompson "Bases must both be tensor or non-tensor"); 1854d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1855d99fa3c5SJeremy L Thompson } 1856d99fa3c5SJeremy L Thompson 1857d99fa3c5SJeremy L Thompson ierr = CeedMalloc(Q*Pf, &interpF); CeedChk(ierr); 1858d99fa3c5SJeremy L Thompson ierr = CeedMalloc(Q*Pc, &interpC); CeedChk(ierr); 1859d99fa3c5SJeremy L Thompson ierr = CeedCalloc(Pc*Pf, &interpCtoF); CeedChk(ierr); 1860d99fa3c5SJeremy L Thompson ierr = CeedMalloc(Q, &tau); CeedChk(ierr); 1861d99fa3c5SJeremy L Thompson if (isTensorF) { 1862d99fa3c5SJeremy L Thompson memcpy(interpF, basisFine->interp1d, Q*Pf*sizeof basisFine->interp1d[0]); 1863d99fa3c5SJeremy L Thompson memcpy(interpC, basisCoarse->interp1d, Q*Pc*sizeof basisCoarse->interp1d[0]); 1864d99fa3c5SJeremy L Thompson } else { 1865d99fa3c5SJeremy L Thompson memcpy(interpF, basisFine->interp, Q*Pf*sizeof basisFine->interp[0]); 1866d99fa3c5SJeremy L Thompson memcpy(interpC, basisCoarse->interp, Q*Pc*sizeof basisCoarse->interp[0]); 1867d99fa3c5SJeremy L Thompson } 1868d99fa3c5SJeremy L Thompson 1869d99fa3c5SJeremy L Thompson // -- QR Factorization, interpF = Q R 1870d99fa3c5SJeremy L Thompson ierr = CeedQRFactorization(ceed, interpF, tau, Q, Pf); CeedChk(ierr); 1871d99fa3c5SJeremy L Thompson 1872d99fa3c5SJeremy L Thompson // -- Apply Qtranspose, interpC = Qtranspose interpC 1873d99fa3c5SJeremy L Thompson CeedHouseholderApplyQ(interpC, interpF, tau, CEED_TRANSPOSE, 1874d99fa3c5SJeremy L Thompson Q, Pc, Pf, Pc, 1); 1875d99fa3c5SJeremy L Thompson 1876d99fa3c5SJeremy L Thompson // -- Apply Rinv, interpCtoF = Rinv interpC 1877d99fa3c5SJeremy L Thompson for (CeedInt j=0; j<Pc; j++) { // Column j 1878d99fa3c5SJeremy L Thompson interpCtoF[j+Pc*(Pf-1)] = interpC[j+Pc*(Pf-1)]/interpF[Pf*Pf-1]; 1879d99fa3c5SJeremy L Thompson for (CeedInt i=Pf-2; i>=0; i--) { // Row i 1880d99fa3c5SJeremy L Thompson interpCtoF[j+Pc*i] = interpC[j+Pc*i]; 1881d99fa3c5SJeremy L Thompson for (CeedInt k=i+1; k<Pf; k++) 1882d99fa3c5SJeremy L Thompson interpCtoF[j+Pc*i] -= interpF[k+Pf*i]*interpCtoF[j+Pc*k]; 1883d99fa3c5SJeremy L Thompson interpCtoF[j+Pc*i] /= interpF[i+Pf*i]; 1884d99fa3c5SJeremy L Thompson } 1885d99fa3c5SJeremy L Thompson } 1886d99fa3c5SJeremy L Thompson ierr = CeedFree(&tau); CeedChk(ierr); 1887d99fa3c5SJeremy L Thompson ierr = CeedFree(&interpC); CeedChk(ierr); 1888d99fa3c5SJeremy L Thompson ierr = CeedFree(&interpF); CeedChk(ierr); 1889d99fa3c5SJeremy L Thompson 1890e15f9bd0SJeremy L Thompson // Complete with interpCtoF versions of code 1891d99fa3c5SJeremy L Thompson if (isTensorF) { 1892d99fa3c5SJeremy L Thompson ierr = CeedOperatorMultigridLevelCreateTensorH1(opFine, PMultFine, 1893d99fa3c5SJeremy L Thompson rstrCoarse, basisCoarse, interpCtoF, opCoarse, opProlong, opRestrict); 1894d99fa3c5SJeremy L Thompson CeedChk(ierr); 1895d99fa3c5SJeremy L Thompson } else { 1896d99fa3c5SJeremy L Thompson ierr = CeedOperatorMultigridLevelCreateH1(opFine, PMultFine, 1897d99fa3c5SJeremy L Thompson rstrCoarse, basisCoarse, interpCtoF, opCoarse, opProlong, opRestrict); 1898d99fa3c5SJeremy L Thompson CeedChk(ierr); 1899d99fa3c5SJeremy L Thompson } 1900d99fa3c5SJeremy L Thompson 1901d99fa3c5SJeremy L Thompson // Cleanup 1902d99fa3c5SJeremy L Thompson ierr = CeedFree(&interpCtoF); CeedChk(ierr); 1903e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1904d99fa3c5SJeremy L Thompson } 1905d99fa3c5SJeremy L Thompson 1906d99fa3c5SJeremy L Thompson /** 1907d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1908d99fa3c5SJeremy L Thompson for a CeedOperator with a tensor basis for the active basis 1909d99fa3c5SJeremy L Thompson 1910d99fa3c5SJeremy L Thompson @param[in] opFine Fine grid operator 1911d99fa3c5SJeremy L Thompson @param[in] PMultFine L-vector multiplicity in parallel gather/scatter 1912d99fa3c5SJeremy L Thompson @param[in] rstrCoarse Coarse grid restriction 1913d99fa3c5SJeremy L Thompson @param[in] basisCoarse Coarse grid active vector basis 1914d99fa3c5SJeremy L Thompson @param[in] interpCtoF Matrix for coarse to fine interpolation 1915d99fa3c5SJeremy L Thompson @param[out] opCoarse Coarse grid operator 1916d99fa3c5SJeremy L Thompson @param[out] opProlong Coarse to fine operator 1917d99fa3c5SJeremy L Thompson @param[out] opRestrict Fine to coarse operator 1918d99fa3c5SJeremy L Thompson 1919d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1920d99fa3c5SJeremy L Thompson 1921d99fa3c5SJeremy L Thompson @ref User 1922d99fa3c5SJeremy L Thompson **/ 1923d99fa3c5SJeremy L Thompson int CeedOperatorMultigridLevelCreateTensorH1(CeedOperator opFine, 1924d99fa3c5SJeremy L Thompson CeedVector PMultFine, CeedElemRestriction rstrCoarse, CeedBasis basisCoarse, 1925d99fa3c5SJeremy L Thompson const CeedScalar *interpCtoF, CeedOperator *opCoarse, 1926d99fa3c5SJeremy L Thompson CeedOperator *opProlong, CeedOperator *opRestrict) { 1927d99fa3c5SJeremy L Thompson int ierr; 1928d99fa3c5SJeremy L Thompson Ceed ceed; 1929d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(opFine, &ceed); CeedChk(ierr); 1930d99fa3c5SJeremy L Thompson 1931d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 1932d99fa3c5SJeremy L Thompson CeedBasis basisFine; 1933d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetActiveBasis(opFine, &basisFine); CeedChk(ierr); 1934d99fa3c5SJeremy L Thompson CeedInt Qf, Qc; 1935d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisFine, &Qf); CeedChk(ierr); 1936d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisCoarse, &Qc); CeedChk(ierr); 1937d99fa3c5SJeremy L Thompson if (Qf != Qc) 1938d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1939e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 1940e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 1941d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1942d99fa3c5SJeremy L Thompson 1943d99fa3c5SJeremy L Thompson // Coarse to fine basis 1944d99fa3c5SJeremy L Thompson CeedInt dim, ncomp, nnodesCoarse, P1dFine, P1dCoarse; 1945d99fa3c5SJeremy L Thompson ierr = CeedBasisGetDimension(basisFine, &dim); CeedChk(ierr); 1946d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumComponents(basisFine, &ncomp); CeedChk(ierr); 1947d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes1D(basisFine, &P1dFine); CeedChk(ierr); 1948d99fa3c5SJeremy L Thompson ierr = CeedElemRestrictionGetElementSize(rstrCoarse, &nnodesCoarse); 1949d99fa3c5SJeremy L Thompson CeedChk(ierr); 1950d99fa3c5SJeremy L Thompson P1dCoarse = dim == 1 ? nnodesCoarse : 1951d99fa3c5SJeremy L Thompson dim == 2 ? sqrt(nnodesCoarse) : 1952d99fa3c5SJeremy L Thompson cbrt(nnodesCoarse); 1953d99fa3c5SJeremy L Thompson CeedScalar *qref, *qweight, *grad; 1954d99fa3c5SJeremy L Thompson ierr = CeedCalloc(P1dFine, &qref); CeedChk(ierr); 1955d99fa3c5SJeremy L Thompson ierr = CeedCalloc(P1dFine, &qweight); CeedChk(ierr); 1956d99fa3c5SJeremy L Thompson ierr = CeedCalloc(P1dFine*P1dCoarse*dim, &grad); CeedChk(ierr); 1957d99fa3c5SJeremy L Thompson CeedBasis basisCtoF; 1958d99fa3c5SJeremy L Thompson ierr = CeedBasisCreateTensorH1(ceed, dim, ncomp, P1dCoarse, P1dFine, 1959d99fa3c5SJeremy L Thompson interpCtoF, grad, qref, qweight, &basisCtoF); 1960d99fa3c5SJeremy L Thompson CeedChk(ierr); 1961d99fa3c5SJeremy L Thompson ierr = CeedFree(&qref); CeedChk(ierr); 1962d99fa3c5SJeremy L Thompson ierr = CeedFree(&qweight); CeedChk(ierr); 1963d99fa3c5SJeremy L Thompson ierr = CeedFree(&grad); CeedChk(ierr); 1964d99fa3c5SJeremy L Thompson 1965d99fa3c5SJeremy L Thompson // Core code 1966d99fa3c5SJeremy L Thompson ierr = CeedOperatorMultigridLevel_Core(opFine, PMultFine, rstrCoarse, 1967d99fa3c5SJeremy L Thompson basisCoarse, basisCtoF, opCoarse, 1968d99fa3c5SJeremy L Thompson opProlong, opRestrict); 1969d99fa3c5SJeremy L Thompson CeedChk(ierr); 1970e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1971d99fa3c5SJeremy L Thompson } 1972d99fa3c5SJeremy L Thompson 1973d99fa3c5SJeremy L Thompson /** 1974d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1975d99fa3c5SJeremy L Thompson for a CeedOperator with a non-tensor basis for the active vector 1976d99fa3c5SJeremy L Thompson 1977d99fa3c5SJeremy L Thompson @param[in] opFine Fine grid operator 1978d99fa3c5SJeremy L Thompson @param[in] PMultFine L-vector multiplicity in parallel gather/scatter 1979d99fa3c5SJeremy L Thompson @param[in] rstrCoarse Coarse grid restriction 1980d99fa3c5SJeremy L Thompson @param[in] basisCoarse Coarse grid active vector basis 1981d99fa3c5SJeremy L Thompson @param[in] interpCtoF Matrix for coarse to fine interpolation 1982d99fa3c5SJeremy L Thompson @param[out] opCoarse Coarse grid operator 1983d99fa3c5SJeremy L Thompson @param[out] opProlong Coarse to fine operator 1984d99fa3c5SJeremy L Thompson @param[out] opRestrict Fine to coarse operator 1985d99fa3c5SJeremy L Thompson 1986d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1987d99fa3c5SJeremy L Thompson 1988d99fa3c5SJeremy L Thompson @ref User 1989d99fa3c5SJeremy L Thompson **/ 1990d99fa3c5SJeremy L Thompson int CeedOperatorMultigridLevelCreateH1(CeedOperator opFine, 1991d99fa3c5SJeremy L Thompson CeedVector PMultFine, 1992d99fa3c5SJeremy L Thompson CeedElemRestriction rstrCoarse, 1993d99fa3c5SJeremy L Thompson CeedBasis basisCoarse, 1994d99fa3c5SJeremy L Thompson const CeedScalar *interpCtoF, 1995d99fa3c5SJeremy L Thompson CeedOperator *opCoarse, 1996d99fa3c5SJeremy L Thompson CeedOperator *opProlong, 1997d99fa3c5SJeremy L Thompson CeedOperator *opRestrict) { 1998d99fa3c5SJeremy L Thompson int ierr; 1999d99fa3c5SJeremy L Thompson Ceed ceed; 2000d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(opFine, &ceed); CeedChk(ierr); 2001d99fa3c5SJeremy L Thompson 2002d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 2003d99fa3c5SJeremy L Thompson CeedBasis basisFine; 2004d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetActiveBasis(opFine, &basisFine); CeedChk(ierr); 2005d99fa3c5SJeremy L Thompson CeedInt Qf, Qc; 2006d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisFine, &Qf); CeedChk(ierr); 2007d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisCoarse, &Qc); CeedChk(ierr); 2008d99fa3c5SJeremy L Thompson if (Qf != Qc) 2009d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 2010e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 2011e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 2012d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 2013d99fa3c5SJeremy L Thompson 2014d99fa3c5SJeremy L Thompson // Coarse to fine basis 2015d99fa3c5SJeremy L Thompson CeedElemTopology topo; 2016d99fa3c5SJeremy L Thompson ierr = CeedBasisGetTopology(basisFine, &topo); CeedChk(ierr); 2017d99fa3c5SJeremy L Thompson CeedInt dim, ncomp, nnodesCoarse, nnodesFine; 2018d99fa3c5SJeremy L Thompson ierr = CeedBasisGetDimension(basisFine, &dim); CeedChk(ierr); 2019d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumComponents(basisFine, &ncomp); CeedChk(ierr); 2020d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes(basisFine, &nnodesFine); CeedChk(ierr); 2021d99fa3c5SJeremy L Thompson ierr = CeedElemRestrictionGetElementSize(rstrCoarse, &nnodesCoarse); 2022d99fa3c5SJeremy L Thompson CeedChk(ierr); 2023d99fa3c5SJeremy L Thompson CeedScalar *qref, *qweight, *grad; 2024d99fa3c5SJeremy L Thompson ierr = CeedCalloc(nnodesFine, &qref); CeedChk(ierr); 2025d99fa3c5SJeremy L Thompson ierr = CeedCalloc(nnodesFine, &qweight); CeedChk(ierr); 2026d99fa3c5SJeremy L Thompson ierr = CeedCalloc(nnodesFine*nnodesCoarse*dim, &grad); CeedChk(ierr); 2027d99fa3c5SJeremy L Thompson CeedBasis basisCtoF; 2028d99fa3c5SJeremy L Thompson ierr = CeedBasisCreateH1(ceed, topo, ncomp, nnodesCoarse, nnodesFine, 2029d99fa3c5SJeremy L Thompson interpCtoF, grad, qref, qweight, &basisCtoF); 2030d99fa3c5SJeremy L Thompson CeedChk(ierr); 2031d99fa3c5SJeremy L Thompson ierr = CeedFree(&qref); CeedChk(ierr); 2032d99fa3c5SJeremy L Thompson ierr = CeedFree(&qweight); CeedChk(ierr); 2033d99fa3c5SJeremy L Thompson ierr = CeedFree(&grad); CeedChk(ierr); 2034d99fa3c5SJeremy L Thompson 2035d99fa3c5SJeremy L Thompson // Core code 2036d99fa3c5SJeremy L Thompson ierr = CeedOperatorMultigridLevel_Core(opFine, PMultFine, rstrCoarse, 2037d99fa3c5SJeremy L Thompson basisCoarse, basisCtoF, opCoarse, 2038d99fa3c5SJeremy L Thompson opProlong, opRestrict); 2039d99fa3c5SJeremy L Thompson CeedChk(ierr); 2040e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2041d99fa3c5SJeremy L Thompson } 2042d99fa3c5SJeremy L Thompson 2043d99fa3c5SJeremy L Thompson /** 20443bd813ffSjeremylt @brief Build a FDM based approximate inverse for each element for a 20453bd813ffSjeremylt CeedOperator 20463bd813ffSjeremylt 20473bd813ffSjeremylt This returns a CeedOperator and CeedVector to apply a Fast Diagonalization 20483bd813ffSjeremylt Method based approximate inverse. This function obtains the simultaneous 20493bd813ffSjeremylt diagonalization for the 1D mass and Laplacian operators, 20503bd813ffSjeremylt M = V^T V, K = V^T S V. 20513bd813ffSjeremylt The assembled QFunction is used to modify the eigenvalues from simultaneous 20523bd813ffSjeremylt diagonalization and obtain an approximate inverse of the form 20533bd813ffSjeremylt V^T S^hat V. The CeedOperator must be linear and non-composite. The 20543bd813ffSjeremylt associated CeedQFunction must therefore also be linear. 20553bd813ffSjeremylt 20563bd813ffSjeremylt @param op CeedOperator to create element inverses 20573bd813ffSjeremylt @param[out] fdminv CeedOperator to apply the action of a FDM based inverse 20583bd813ffSjeremylt for each element 20593bd813ffSjeremylt @param request Address of CeedRequest for non-blocking completion, else 20604cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 20613bd813ffSjeremylt 20623bd813ffSjeremylt @return An error code: 0 - success, otherwise - failure 20633bd813ffSjeremylt 20647a982d89SJeremy L. Thompson @ref Backend 20653bd813ffSjeremylt **/ 20663bd813ffSjeremylt int CeedOperatorCreateFDMElementInverse(CeedOperator op, CeedOperator *fdminv, 20673bd813ffSjeremylt CeedRequest *request) { 20683bd813ffSjeremylt int ierr; 2069*e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 20703bd813ffSjeremylt 2071713f43c3Sjeremylt // Use backend version, if available 2072713f43c3Sjeremylt if (op->CreateFDMElementInverse) { 2073713f43c3Sjeremylt ierr = op->CreateFDMElementInverse(op, fdminv, request); CeedChk(ierr); 2074713f43c3Sjeremylt } else { 2075713f43c3Sjeremylt // Fallback to reference Ceed 2076713f43c3Sjeremylt if (!op->opfallback) { 2077713f43c3Sjeremylt ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 20783bd813ffSjeremylt } 2079713f43c3Sjeremylt // Assemble 2080713f43c3Sjeremylt ierr = op->opfallback->CreateFDMElementInverse(op->opfallback, fdminv, 20813bd813ffSjeremylt request); CeedChk(ierr); 20823bd813ffSjeremylt } 2083e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 20843bd813ffSjeremylt } 20853bd813ffSjeremylt 20867a982d89SJeremy L. Thompson /** 20877a982d89SJeremy L. Thompson @brief View a CeedOperator 20887a982d89SJeremy L. Thompson 20897a982d89SJeremy L. Thompson @param[in] op CeedOperator to view 20907a982d89SJeremy L. Thompson @param[in] stream Stream to write; typically stdout/stderr or a file 20917a982d89SJeremy L. Thompson 20927a982d89SJeremy L. Thompson @return Error code: 0 - success, otherwise - failure 20937a982d89SJeremy L. Thompson 20947a982d89SJeremy L. Thompson @ref User 20957a982d89SJeremy L. Thompson **/ 20967a982d89SJeremy L. Thompson int CeedOperatorView(CeedOperator op, FILE *stream) { 20977a982d89SJeremy L. Thompson int ierr; 20987a982d89SJeremy L. Thompson 20997a982d89SJeremy L. Thompson if (op->composite) { 21007a982d89SJeremy L. Thompson fprintf(stream, "Composite CeedOperator\n"); 21017a982d89SJeremy L. Thompson 21027a982d89SJeremy L. Thompson for (CeedInt i=0; i<op->numsub; i++) { 21037a982d89SJeremy L. Thompson fprintf(stream, " SubOperator [%d]:\n", i); 21047a982d89SJeremy L. Thompson ierr = CeedOperatorSingleView(op->suboperators[i], 1, stream); 21057a982d89SJeremy L. Thompson CeedChk(ierr); 21067a982d89SJeremy L. Thompson } 21077a982d89SJeremy L. Thompson } else { 21087a982d89SJeremy L. Thompson fprintf(stream, "CeedOperator\n"); 21097a982d89SJeremy L. Thompson ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr); 21107a982d89SJeremy L. Thompson } 2111e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 21127a982d89SJeremy L. Thompson } 21133bd813ffSjeremylt 21143bd813ffSjeremylt /** 21153bd813ffSjeremylt @brief Apply CeedOperator to a vector 2116d7b241e6Sjeremylt 2117d7b241e6Sjeremylt This computes the action of the operator on the specified (active) input, 2118d7b241e6Sjeremylt yielding its (active) output. All inputs and outputs must be specified using 2119d7b241e6Sjeremylt CeedOperatorSetField(). 2120d7b241e6Sjeremylt 2121d7b241e6Sjeremylt @param op CeedOperator to apply 21224cc79fe7SJed Brown @param[in] in CeedVector containing input state or @ref CEED_VECTOR_NONE if 212334138859Sjeremylt there are no active inputs 2124b11c1e72Sjeremylt @param[out] out CeedVector to store result of applying operator (must be 21254cc79fe7SJed Brown distinct from @a in) or @ref CEED_VECTOR_NONE if there are no 212634138859Sjeremylt active outputs 2127d7b241e6Sjeremylt @param request Address of CeedRequest for non-blocking completion, else 21284cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 2129b11c1e72Sjeremylt 2130b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 2131dfdf5a53Sjeremylt 21327a982d89SJeremy L. Thompson @ref User 2133b11c1e72Sjeremylt **/ 2134692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out, 2135692c2638Sjeremylt CeedRequest *request) { 2136d7b241e6Sjeremylt int ierr; 2137*e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 2138d7b241e6Sjeremylt 2139250756a7Sjeremylt if (op->numelements) { 2140250756a7Sjeremylt // Standard Operator 2141cae8b89aSjeremylt if (op->Apply) { 2142250756a7Sjeremylt ierr = op->Apply(op, in, out, request); CeedChk(ierr); 2143cae8b89aSjeremylt } else { 2144cae8b89aSjeremylt // Zero all output vectors 2145250756a7Sjeremylt CeedQFunction qf = op->qf; 2146cae8b89aSjeremylt for (CeedInt i=0; i<qf->numoutputfields; i++) { 2147cae8b89aSjeremylt CeedVector vec = op->outputfields[i]->vec; 2148cae8b89aSjeremylt if (vec == CEED_VECTOR_ACTIVE) 2149cae8b89aSjeremylt vec = out; 2150cae8b89aSjeremylt if (vec != CEED_VECTOR_NONE) { 2151cae8b89aSjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 2152cae8b89aSjeremylt } 2153cae8b89aSjeremylt } 2154250756a7Sjeremylt // Apply 2155250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 2156250756a7Sjeremylt } 2157250756a7Sjeremylt } else if (op->composite) { 2158250756a7Sjeremylt // Composite Operator 2159250756a7Sjeremylt if (op->ApplyComposite) { 2160250756a7Sjeremylt ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr); 2161250756a7Sjeremylt } else { 2162250756a7Sjeremylt CeedInt numsub; 2163250756a7Sjeremylt ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 2164250756a7Sjeremylt CeedOperator *suboperators; 2165250756a7Sjeremylt ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 2166250756a7Sjeremylt 2167250756a7Sjeremylt // Zero all output vectors 2168250756a7Sjeremylt if (out != CEED_VECTOR_NONE) { 2169cae8b89aSjeremylt ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr); 2170cae8b89aSjeremylt } 2171250756a7Sjeremylt for (CeedInt i=0; i<numsub; i++) { 2172250756a7Sjeremylt for (CeedInt j=0; j<suboperators[i]->qf->numoutputfields; j++) { 2173250756a7Sjeremylt CeedVector vec = suboperators[i]->outputfields[j]->vec; 2174250756a7Sjeremylt if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) { 2175250756a7Sjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 2176250756a7Sjeremylt } 2177250756a7Sjeremylt } 2178250756a7Sjeremylt } 2179250756a7Sjeremylt // Apply 2180250756a7Sjeremylt for (CeedInt i=0; i<op->numsub; i++) { 2181250756a7Sjeremylt ierr = CeedOperatorApplyAdd(op->suboperators[i], in, out, request); 2182cae8b89aSjeremylt CeedChk(ierr); 2183cae8b89aSjeremylt } 2184cae8b89aSjeremylt } 2185250756a7Sjeremylt } 2186e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2187cae8b89aSjeremylt } 2188cae8b89aSjeremylt 2189cae8b89aSjeremylt /** 2190cae8b89aSjeremylt @brief Apply CeedOperator to a vector and add result to output vector 2191cae8b89aSjeremylt 2192cae8b89aSjeremylt This computes the action of the operator on the specified (active) input, 2193cae8b89aSjeremylt yielding its (active) output. All inputs and outputs must be specified using 2194cae8b89aSjeremylt CeedOperatorSetField(). 2195cae8b89aSjeremylt 2196cae8b89aSjeremylt @param op CeedOperator to apply 2197cae8b89aSjeremylt @param[in] in CeedVector containing input state or NULL if there are no 2198cae8b89aSjeremylt active inputs 2199cae8b89aSjeremylt @param[out] out CeedVector to sum in result of applying operator (must be 2200cae8b89aSjeremylt distinct from @a in) or NULL if there are no active outputs 2201cae8b89aSjeremylt @param request Address of CeedRequest for non-blocking completion, else 22024cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 2203cae8b89aSjeremylt 2204cae8b89aSjeremylt @return An error code: 0 - success, otherwise - failure 2205cae8b89aSjeremylt 22067a982d89SJeremy L. Thompson @ref User 2207cae8b89aSjeremylt **/ 2208cae8b89aSjeremylt int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out, 2209cae8b89aSjeremylt CeedRequest *request) { 2210cae8b89aSjeremylt int ierr; 2211*e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 2212cae8b89aSjeremylt 2213250756a7Sjeremylt if (op->numelements) { 2214250756a7Sjeremylt // Standard Operator 2215250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 2216250756a7Sjeremylt } else if (op->composite) { 2217250756a7Sjeremylt // Composite Operator 2218250756a7Sjeremylt if (op->ApplyAddComposite) { 2219250756a7Sjeremylt ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr); 2220cae8b89aSjeremylt } else { 2221250756a7Sjeremylt CeedInt numsub; 2222250756a7Sjeremylt ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 2223250756a7Sjeremylt CeedOperator *suboperators; 2224250756a7Sjeremylt ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 2225250756a7Sjeremylt 2226250756a7Sjeremylt for (CeedInt i=0; i<numsub; i++) { 2227250756a7Sjeremylt ierr = CeedOperatorApplyAdd(suboperators[i], in, out, request); 2228cae8b89aSjeremylt CeedChk(ierr); 22291d7d2407SJeremy L Thompson } 2230250756a7Sjeremylt } 2231250756a7Sjeremylt } 2232e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2233d7b241e6Sjeremylt } 2234d7b241e6Sjeremylt 2235d7b241e6Sjeremylt /** 2236b11c1e72Sjeremylt @brief Destroy a CeedOperator 2237d7b241e6Sjeremylt 2238d7b241e6Sjeremylt @param op CeedOperator to destroy 2239b11c1e72Sjeremylt 2240b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 2241dfdf5a53Sjeremylt 22427a982d89SJeremy L. Thompson @ref User 2243b11c1e72Sjeremylt **/ 2244d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) { 2245d7b241e6Sjeremylt int ierr; 2246d7b241e6Sjeremylt 2247e15f9bd0SJeremy L Thompson if (!*op || --(*op)->refcount > 0) return CEED_ERROR_SUCCESS; 2248d7b241e6Sjeremylt if ((*op)->Destroy) { 2249d7b241e6Sjeremylt ierr = (*op)->Destroy(*op); CeedChk(ierr); 2250d7b241e6Sjeremylt } 2251fe2413ffSjeremylt ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 2252fe2413ffSjeremylt // Free fields 22531d102b48SJeremy L Thompson for (int i=0; i<(*op)->nfields; i++) 225452d6035fSJeremy L Thompson if ((*op)->inputfields[i]) { 225515910d16Sjeremylt if ((*op)->inputfields[i]->Erestrict != CEED_ELEMRESTRICTION_NONE) { 225671352a93Sjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->inputfields[i]->Erestrict); 225771352a93Sjeremylt CeedChk(ierr); 225815910d16Sjeremylt } 225971352a93Sjeremylt if ((*op)->inputfields[i]->basis != CEED_BASIS_COLLOCATED) { 226071352a93Sjeremylt ierr = CeedBasisDestroy(&(*op)->inputfields[i]->basis); CeedChk(ierr); 226171352a93Sjeremylt } 226271352a93Sjeremylt if ((*op)->inputfields[i]->vec != CEED_VECTOR_ACTIVE && 226371352a93Sjeremylt (*op)->inputfields[i]->vec != CEED_VECTOR_NONE ) { 226471352a93Sjeremylt ierr = CeedVectorDestroy(&(*op)->inputfields[i]->vec); CeedChk(ierr); 226571352a93Sjeremylt } 2266d99fa3c5SJeremy L Thompson ierr = CeedFree(&(*op)->inputfields[i]->fieldname); CeedChk(ierr); 2267fe2413ffSjeremylt ierr = CeedFree(&(*op)->inputfields[i]); CeedChk(ierr); 2268fe2413ffSjeremylt } 22691d102b48SJeremy L Thompson for (int i=0; i<(*op)->nfields; i++) 2270d0eb30a5Sjeremylt if ((*op)->outputfields[i]) { 227171352a93Sjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->outputfields[i]->Erestrict); 227271352a93Sjeremylt CeedChk(ierr); 227371352a93Sjeremylt if ((*op)->outputfields[i]->basis != CEED_BASIS_COLLOCATED) { 227471352a93Sjeremylt ierr = CeedBasisDestroy(&(*op)->outputfields[i]->basis); CeedChk(ierr); 227571352a93Sjeremylt } 227671352a93Sjeremylt if ((*op)->outputfields[i]->vec != CEED_VECTOR_ACTIVE && 227771352a93Sjeremylt (*op)->outputfields[i]->vec != CEED_VECTOR_NONE ) { 227871352a93Sjeremylt ierr = CeedVectorDestroy(&(*op)->outputfields[i]->vec); CeedChk(ierr); 227971352a93Sjeremylt } 2280d99fa3c5SJeremy L Thompson ierr = CeedFree(&(*op)->outputfields[i]->fieldname); CeedChk(ierr); 2281fe2413ffSjeremylt ierr = CeedFree(&(*op)->outputfields[i]); CeedChk(ierr); 2282fe2413ffSjeremylt } 228352d6035fSJeremy L Thompson // Destroy suboperators 22841d102b48SJeremy L Thompson for (int i=0; i<(*op)->numsub; i++) 228552d6035fSJeremy L Thompson if ((*op)->suboperators[i]) { 228652d6035fSJeremy L Thompson ierr = CeedOperatorDestroy(&(*op)->suboperators[i]); CeedChk(ierr); 228752d6035fSJeremy L Thompson } 2288e15f9bd0SJeremy L Thompson if ((*op)->qf) 2289e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2290e15f9bd0SJeremy L Thompson (*op)->qf->operatorsset--; 2291e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2292d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 2293e15f9bd0SJeremy L Thompson if ((*op)->dqf && (*op)->dqf != CEED_QFUNCTION_NONE) 2294e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2295e15f9bd0SJeremy L Thompson (*op)->dqf->operatorsset--; 2296e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2297d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 2298e15f9bd0SJeremy L Thompson if ((*op)->dqfT && (*op)->dqfT != CEED_QFUNCTION_NONE) 2299e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2300e15f9bd0SJeremy L Thompson (*op)->dqfT->operatorsset--; 2301e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2302d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 2303fe2413ffSjeremylt 23045107b09fSJeremy L Thompson // Destroy fallback 23055107b09fSJeremy L Thompson if ((*op)->opfallback) { 23065107b09fSJeremy L Thompson ierr = (*op)->qffallback->Destroy((*op)->qffallback); CeedChk(ierr); 23075107b09fSJeremy L Thompson ierr = CeedFree(&(*op)->qffallback); CeedChk(ierr); 23085107b09fSJeremy L Thompson ierr = (*op)->opfallback->Destroy((*op)->opfallback); CeedChk(ierr); 23095107b09fSJeremy L Thompson ierr = CeedFree(&(*op)->opfallback); CeedChk(ierr); 23105107b09fSJeremy L Thompson } 23115107b09fSJeremy L Thompson 2312fe2413ffSjeremylt ierr = CeedFree(&(*op)->inputfields); CeedChk(ierr); 2313fe2413ffSjeremylt ierr = CeedFree(&(*op)->outputfields); CeedChk(ierr); 231452d6035fSJeremy L Thompson ierr = CeedFree(&(*op)->suboperators); CeedChk(ierr); 2315d7b241e6Sjeremylt ierr = CeedFree(op); CeedChk(ierr); 2316e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2317d7b241e6Sjeremylt } 2318d7b241e6Sjeremylt 2319d7b241e6Sjeremylt /// @} 2320