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 17*ec3da8bcSJed Brown #include <ceed/ceed.h> 18*ec3da8bcSJed Brown #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) { 111e1e9e29dSJed Brown if (emode == CEED_EVAL_WEIGHT) { 112e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 113e1e9e29dSJed Brown return CeedError(ceed, CEED_ERROR_INCOMPATIBLE, 114e1e9e29dSJed Brown "CEED_ELEMRESTRICTION_NONE should be used " 115e15f9bd0SJeremy L Thompson "for a field with eval mode CEED_EVAL_WEIGHT"); 116e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 117e15f9bd0SJeremy L Thompson } 118e1e9e29dSJed Brown ierr = CeedElemRestrictionGetNumComponents(r, &restr_ncomp); 119e1e9e29dSJed Brown } 120e1e9e29dSJed Brown if ((r == CEED_ELEMRESTRICTION_NONE) != (emode == CEED_EVAL_WEIGHT)) { 121e1e9e29dSJed Brown // LCOV_EXCL_START 122e1e9e29dSJed Brown return CeedError(ceed, CEED_ERROR_INCOMPATIBLE, 123e1e9e29dSJed Brown "CEED_ELEMRESTRICTION_NONE and CEED_EVAL_WEIGHT " 124e1e9e29dSJed Brown "must be used together."); 125e1e9e29dSJed Brown // LCOV_EXCL_STOP 126e1e9e29dSJed Brown } 127e15f9bd0SJeremy L Thompson // Basis 128e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 129e1e9e29dSJed Brown if (emode == CEED_EVAL_NONE) 130e1e9e29dSJed Brown return CeedError(ceed, CEED_ERROR_INCOMPATIBLE, 131e1e9e29dSJed Brown "Field '%s' configured with CEED_EVAL_NONE must be used with CEED_BASIS_COLLOCATED", 132e1e9e29dSJed Brown qfield->fieldname); 133e15f9bd0SJeremy L Thompson ierr = CeedBasisGetDimension(b, &dim); CeedChk(ierr); 134e15f9bd0SJeremy L Thompson ierr = CeedBasisGetNumComponents(b, &ncomp); CeedChk(ierr); 135e15f9bd0SJeremy L Thompson if (r != CEED_ELEMRESTRICTION_NONE && restr_ncomp != ncomp) { 136e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 137e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 138e1e9e29dSJed Brown "Field '%s' of size %d and EvalMode %s: ElemRestriction has %d components, but Basis has %d components", 139e1e9e29dSJed Brown qfield->fieldname, qfield->size, CeedEvalModes[qfield->emode], restr_ncomp, 140e1e9e29dSJed Brown ncomp); 141e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 142e15f9bd0SJeremy L Thompson } 143e15f9bd0SJeremy L Thompson } 144e15f9bd0SJeremy L Thompson // Field size 145e15f9bd0SJeremy L Thompson switch(emode) { 146e15f9bd0SJeremy L Thompson case CEED_EVAL_NONE: 147e15f9bd0SJeremy L Thompson if (size != restr_ncomp) 148e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 149e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 150e1e9e29dSJed Brown "Field '%s' of size %d and EvalMode %s: ElemRestriction has %d components", 151e1e9e29dSJed Brown qfield->fieldname, qfield->size, CeedEvalModes[qfield->emode], restr_ncomp); 152e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 153e15f9bd0SJeremy L Thompson break; 154e15f9bd0SJeremy L Thompson case CEED_EVAL_INTERP: 155e15f9bd0SJeremy L Thompson if (size != ncomp) 156e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 157e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 158e1e9e29dSJed Brown "Field '%s' of size %d and EvalMode %s: ElemRestriction/Basis has %d components", 159e1e9e29dSJed Brown qfield->fieldname, qfield->size, CeedEvalModes[qfield->emode], ncomp); 160e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 161e15f9bd0SJeremy L Thompson break; 162e15f9bd0SJeremy L Thompson case CEED_EVAL_GRAD: 163e15f9bd0SJeremy L Thompson if (size != ncomp * dim) 164e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 165e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 166e1e9e29dSJed Brown "Field '%s' of size %d and EvalMode %s in %d dimensions: ElemRestriction/Basis has %d components", 167e1e9e29dSJed Brown qfield->fieldname, qfield->size, CeedEvalModes[qfield->emode], dim, ncomp); 168e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 169e15f9bd0SJeremy L Thompson break; 170e15f9bd0SJeremy L Thompson case CEED_EVAL_WEIGHT: 171e15f9bd0SJeremy L Thompson // No addional checks required 172e15f9bd0SJeremy L Thompson break; 173e15f9bd0SJeremy L Thompson case CEED_EVAL_DIV: 174e15f9bd0SJeremy L Thompson // Not implemented 175e15f9bd0SJeremy L Thompson break; 176e15f9bd0SJeremy L Thompson case CEED_EVAL_CURL: 177e15f9bd0SJeremy L Thompson // Not implemented 178e15f9bd0SJeremy L Thompson break; 179e15f9bd0SJeremy L Thompson } 180e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1817a982d89SJeremy L. Thompson } 1827a982d89SJeremy L. Thompson 1837a982d89SJeremy L. Thompson /** 1847a982d89SJeremy L. Thompson @brief Check if a CeedOperator is ready to be used. 1857a982d89SJeremy L. Thompson 1867a982d89SJeremy L. Thompson @param[in] op CeedOperator to check 1877a982d89SJeremy L. Thompson 1887a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 1897a982d89SJeremy L. Thompson 1907a982d89SJeremy L. Thompson @ref Developer 1917a982d89SJeremy L. Thompson **/ 192e2f04181SAndrew T. Barker static int CeedOperatorCheckReady(CeedOperator op) { 193e2f04181SAndrew T. Barker int ierr; 194e2f04181SAndrew T. Barker Ceed ceed; 195e2f04181SAndrew T. Barker ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 196e2f04181SAndrew T. Barker 197e15f9bd0SJeremy L Thompson if (op->interfacesetup) 198e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1997a982d89SJeremy L. Thompson 200e15f9bd0SJeremy L Thompson CeedQFunction qf = op->qf; 2017a982d89SJeremy L. Thompson if (op->composite) { 2027a982d89SJeremy L. Thompson if (!op->numsub) 2037a982d89SJeremy L. Thompson // LCOV_EXCL_START 204e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No suboperators set"); 2057a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 2067a982d89SJeremy L. Thompson } else { 2077a982d89SJeremy L. Thompson if (op->nfields == 0) 2087a982d89SJeremy L. Thompson // LCOV_EXCL_START 209e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "No operator fields set"); 2107a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 2117a982d89SJeremy L. Thompson if (op->nfields < qf->numinputfields + qf->numoutputfields) 2127a982d89SJeremy L. Thompson // LCOV_EXCL_START 213e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, "Not all operator fields set"); 2147a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 2157a982d89SJeremy L. Thompson if (!op->hasrestriction) 2167a982d89SJeremy L. Thompson // LCOV_EXCL_START 217e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, 218e15f9bd0SJeremy L Thompson "At least one restriction required"); 2197a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 2207a982d89SJeremy L. Thompson if (op->numqpoints == 0) 2217a982d89SJeremy L. Thompson // LCOV_EXCL_START 222e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_INCOMPLETE, 223e15f9bd0SJeremy L Thompson "At least one non-collocated basis required"); 2247a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 2257a982d89SJeremy L. Thompson } 2267a982d89SJeremy L. Thompson 227e15f9bd0SJeremy L Thompson // Flag as immutable and ready 228e15f9bd0SJeremy L Thompson op->interfacesetup = true; 229e15f9bd0SJeremy L Thompson if (op->qf && op->qf != CEED_QFUNCTION_NONE) 230e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 231e15f9bd0SJeremy L Thompson op->qf->operatorsset++; 232e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 233e15f9bd0SJeremy L Thompson if (op->dqf && op->dqf != CEED_QFUNCTION_NONE) 234e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 235e15f9bd0SJeremy L Thompson op->dqf->operatorsset++; 236e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 237e15f9bd0SJeremy L Thompson if (op->dqfT && op->dqfT != CEED_QFUNCTION_NONE) 238e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 239e15f9bd0SJeremy L Thompson op->dqfT->operatorsset++; 240e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 241e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2427a982d89SJeremy L. Thompson } 2437a982d89SJeremy L. Thompson 2447a982d89SJeremy L. Thompson /** 2457a982d89SJeremy L. Thompson @brief View a field of a CeedOperator 2467a982d89SJeremy L. Thompson 2477a982d89SJeremy L. Thompson @param[in] field Operator field to view 2484c4400c7SValeria Barra @param[in] qffield QFunction field (carries field name) 2497a982d89SJeremy L. Thompson @param[in] fieldnumber Number of field being viewed 2504c4400c7SValeria Barra @param[in] sub true indicates sub-operator, which increases indentation; false for top-level operator 2514c4400c7SValeria Barra @param[in] in true for an input field; false for output field 2527a982d89SJeremy L. Thompson @param[in] stream Stream to view to, e.g., stdout 2537a982d89SJeremy L. Thompson 2547a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 2557a982d89SJeremy L. Thompson 2567a982d89SJeremy L. Thompson @ref Utility 2577a982d89SJeremy L. Thompson **/ 2587a982d89SJeremy L. Thompson static int CeedOperatorFieldView(CeedOperatorField field, 2597a982d89SJeremy L. Thompson CeedQFunctionField qffield, 2607a982d89SJeremy L. Thompson CeedInt fieldnumber, bool sub, bool in, 2617a982d89SJeremy L. Thompson FILE *stream) { 2627a982d89SJeremy L. Thompson const char *pre = sub ? " " : ""; 2637a982d89SJeremy L. Thompson const char *inout = in ? "Input" : "Output"; 2647a982d89SJeremy L. Thompson 2657a982d89SJeremy L. Thompson fprintf(stream, "%s %s Field [%d]:\n" 2667a982d89SJeremy L. Thompson "%s Name: \"%s\"\n", 2677a982d89SJeremy L. Thompson pre, inout, fieldnumber, pre, qffield->fieldname); 2687a982d89SJeremy L. Thompson 2697a982d89SJeremy L. Thompson if (field->basis == CEED_BASIS_COLLOCATED) 2707a982d89SJeremy L. Thompson fprintf(stream, "%s Collocated basis\n", pre); 2717a982d89SJeremy L. Thompson 2727a982d89SJeremy L. Thompson if (field->vec == CEED_VECTOR_ACTIVE) 2737a982d89SJeremy L. Thompson fprintf(stream, "%s Active vector\n", pre); 2747a982d89SJeremy L. Thompson else if (field->vec == CEED_VECTOR_NONE) 2757a982d89SJeremy L. Thompson fprintf(stream, "%s No vector\n", pre); 276e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2777a982d89SJeremy L. Thompson } 2787a982d89SJeremy L. Thompson 2797a982d89SJeremy L. Thompson /** 2807a982d89SJeremy L. Thompson @brief View a single CeedOperator 2817a982d89SJeremy L. Thompson 2827a982d89SJeremy L. Thompson @param[in] op CeedOperator to view 2837a982d89SJeremy L. Thompson @param[in] sub Boolean flag for sub-operator 2847a982d89SJeremy L. Thompson @param[in] stream Stream to write; typically stdout/stderr or a file 2857a982d89SJeremy L. Thompson 2867a982d89SJeremy L. Thompson @return Error code: 0 - success, otherwise - failure 2877a982d89SJeremy L. Thompson 2887a982d89SJeremy L. Thompson @ref Utility 2897a982d89SJeremy L. Thompson **/ 2907a982d89SJeremy L. Thompson int CeedOperatorSingleView(CeedOperator op, bool sub, FILE *stream) { 2917a982d89SJeremy L. Thompson int ierr; 2927a982d89SJeremy L. Thompson const char *pre = sub ? " " : ""; 2937a982d89SJeremy L. Thompson 2947a982d89SJeremy L. Thompson CeedInt totalfields; 2957a982d89SJeremy L. Thompson ierr = CeedOperatorGetNumArgs(op, &totalfields); CeedChk(ierr); 2967a982d89SJeremy L. Thompson 2977a982d89SJeremy L. Thompson fprintf(stream, "%s %d Field%s\n", pre, totalfields, totalfields>1 ? "s" : ""); 2987a982d89SJeremy L. Thompson 2997a982d89SJeremy L. Thompson fprintf(stream, "%s %d Input Field%s:\n", pre, op->qf->numinputfields, 3007a982d89SJeremy L. Thompson op->qf->numinputfields>1 ? "s" : ""); 3017a982d89SJeremy L. Thompson for (CeedInt i=0; i<op->qf->numinputfields; i++) { 3027a982d89SJeremy L. Thompson ierr = CeedOperatorFieldView(op->inputfields[i], op->qf->inputfields[i], 3037a982d89SJeremy L. Thompson i, sub, 1, stream); CeedChk(ierr); 3047a982d89SJeremy L. Thompson } 3057a982d89SJeremy L. Thompson 3067a982d89SJeremy L. Thompson fprintf(stream, "%s %d Output Field%s:\n", pre, op->qf->numoutputfields, 3077a982d89SJeremy L. Thompson op->qf->numoutputfields>1 ? "s" : ""); 3087a982d89SJeremy L. Thompson for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 309829936eeSWill Pazner ierr = CeedOperatorFieldView(op->outputfields[i], op->qf->outputfields[i], 3107a982d89SJeremy L. Thompson i, sub, 0, stream); CeedChk(ierr); 3117a982d89SJeremy L. Thompson } 312e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3137a982d89SJeremy L. Thompson } 3147a982d89SJeremy L. Thompson 315d99fa3c5SJeremy L Thompson /** 316e2f04181SAndrew T. Barker @brief Find the active vector ElemRestriction for a CeedOperator 317e2f04181SAndrew T. Barker 318e2f04181SAndrew T. Barker @param[in] op CeedOperator to find active basis for 319e2f04181SAndrew T. Barker @param[out] activerstr ElemRestriction for active input vector 320e2f04181SAndrew T. Barker 321e2f04181SAndrew T. Barker @return An error code: 0 - success, otherwise - failure 322e2f04181SAndrew T. Barker 323e2f04181SAndrew T. Barker @ref Utility 324e2f04181SAndrew T. Barker **/ 325e2f04181SAndrew T. Barker static int CeedOperatorGetActiveElemRestriction(CeedOperator op, 326e2f04181SAndrew T. Barker CeedElemRestriction *activerstr) { 327e2f04181SAndrew T. Barker *activerstr = NULL; 328e2f04181SAndrew T. Barker for (int i = 0; i < op->qf->numinputfields; i++) 329e2f04181SAndrew T. Barker if (op->inputfields[i]->vec == CEED_VECTOR_ACTIVE) { 330e2f04181SAndrew T. Barker *activerstr = op->inputfields[i]->Erestrict; 331e2f04181SAndrew T. Barker break; 332e2f04181SAndrew T. Barker } 333e2f04181SAndrew T. Barker 334e2f04181SAndrew T. Barker if (!*activerstr) { 335e2f04181SAndrew T. Barker // LCOV_EXCL_START 336e2f04181SAndrew T. Barker int ierr; 337e2f04181SAndrew T. Barker Ceed ceed; 338e2f04181SAndrew T. Barker ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 339e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_INCOMPLETE, 340e2f04181SAndrew T. Barker "No active ElemRestriction found!"); 341e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 342e2f04181SAndrew T. Barker } 343e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 344e2f04181SAndrew T. Barker } 345e2f04181SAndrew T. Barker 346e2f04181SAndrew T. Barker /** 347d99fa3c5SJeremy L Thompson @brief Find the active vector basis for a CeedOperator 348d99fa3c5SJeremy L Thompson 349d99fa3c5SJeremy L Thompson @param[in] op CeedOperator to find active basis for 350d99fa3c5SJeremy L Thompson @param[out] activeBasis Basis for active input vector 351d99fa3c5SJeremy L Thompson 352d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 353d99fa3c5SJeremy L Thompson 354d99fa3c5SJeremy L Thompson @ ref Developer 355d99fa3c5SJeremy L Thompson **/ 356d99fa3c5SJeremy L Thompson static int CeedOperatorGetActiveBasis(CeedOperator op, 357d99fa3c5SJeremy L Thompson CeedBasis *activeBasis) { 358d99fa3c5SJeremy L Thompson *activeBasis = NULL; 359d99fa3c5SJeremy L Thompson for (int i = 0; i < op->qf->numinputfields; i++) 360d99fa3c5SJeremy L Thompson if (op->inputfields[i]->vec == CEED_VECTOR_ACTIVE) { 361d99fa3c5SJeremy L Thompson *activeBasis = op->inputfields[i]->basis; 362d99fa3c5SJeremy L Thompson break; 363d99fa3c5SJeremy L Thompson } 364d99fa3c5SJeremy L Thompson 365d99fa3c5SJeremy L Thompson if (!*activeBasis) { 366d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 367d99fa3c5SJeremy L Thompson int ierr; 368d99fa3c5SJeremy L Thompson Ceed ceed; 369d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChk(ierr); 370e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 371d99fa3c5SJeremy L Thompson "No active basis found for automatic multigrid setup"); 372d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 373d99fa3c5SJeremy L Thompson } 374e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 375d99fa3c5SJeremy L Thompson } 376d99fa3c5SJeremy L Thompson 377d99fa3c5SJeremy L Thompson /** 378d99fa3c5SJeremy L Thompson @brief Common code for creating a multigrid coarse operator and level 379d99fa3c5SJeremy L Thompson transfer operators for a CeedOperator 380d99fa3c5SJeremy L Thompson 381d99fa3c5SJeremy L Thompson @param[in] opFine Fine grid operator 382d99fa3c5SJeremy L Thompson @param[in] PMultFine L-vector multiplicity in parallel gather/scatter 383d99fa3c5SJeremy L Thompson @param[in] rstrCoarse Coarse grid restriction 384d99fa3c5SJeremy L Thompson @param[in] basisCoarse Coarse grid active vector basis 385d99fa3c5SJeremy L Thompson @param[in] basisCtoF Basis for coarse to fine interpolation 386d99fa3c5SJeremy L Thompson @param[out] opCoarse Coarse grid operator 387d99fa3c5SJeremy L Thompson @param[out] opProlong Coarse to fine operator 388d99fa3c5SJeremy L Thompson @param[out] opRestrict Fine to coarse operator 389d99fa3c5SJeremy L Thompson 390d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 391d99fa3c5SJeremy L Thompson 392d99fa3c5SJeremy L Thompson @ref Developer 393d99fa3c5SJeremy L Thompson **/ 394d99fa3c5SJeremy L Thompson static int CeedOperatorMultigridLevel_Core(CeedOperator opFine, 395d99fa3c5SJeremy L Thompson CeedVector PMultFine, CeedElemRestriction rstrCoarse, CeedBasis basisCoarse, 396d99fa3c5SJeremy L Thompson CeedBasis basisCtoF, CeedOperator *opCoarse, CeedOperator *opProlong, 397d99fa3c5SJeremy L Thompson CeedOperator *opRestrict) { 398d99fa3c5SJeremy L Thompson int ierr; 399d99fa3c5SJeremy L Thompson Ceed ceed; 400d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(opFine, &ceed); CeedChk(ierr); 401d99fa3c5SJeremy L Thompson 402d99fa3c5SJeremy L Thompson // Check for composite operator 403d99fa3c5SJeremy L Thompson bool isComposite; 404d99fa3c5SJeremy L Thompson ierr = CeedOperatorIsComposite(opFine, &isComposite); CeedChk(ierr); 405d99fa3c5SJeremy L Thompson if (isComposite) 406d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 407e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 408d99fa3c5SJeremy L Thompson "Automatic multigrid setup for composite operators not supported"); 409d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 410d99fa3c5SJeremy L Thompson 411d99fa3c5SJeremy L Thompson // Coarse Grid 412d99fa3c5SJeremy L Thompson ierr = CeedOperatorCreate(ceed, opFine->qf, opFine->dqf, opFine->dqfT, 413d99fa3c5SJeremy L Thompson opCoarse); CeedChk(ierr); 414d99fa3c5SJeremy L Thompson CeedElemRestriction rstrFine = NULL; 415d99fa3c5SJeremy L Thompson // -- Clone input fields 416d99fa3c5SJeremy L Thompson for (int i = 0; i < opFine->qf->numinputfields; i++) { 417d99fa3c5SJeremy L Thompson if (opFine->inputfields[i]->vec == CEED_VECTOR_ACTIVE) { 418d99fa3c5SJeremy L Thompson rstrFine = opFine->inputfields[i]->Erestrict; 419d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opCoarse, opFine->inputfields[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->inputfields[i]->fieldname, 424d99fa3c5SJeremy L Thompson opFine->inputfields[i]->Erestrict, 425d99fa3c5SJeremy L Thompson opFine->inputfields[i]->basis, 426d99fa3c5SJeremy L Thompson opFine->inputfields[i]->vec); CeedChk(ierr); 427d99fa3c5SJeremy L Thompson } 428d99fa3c5SJeremy L Thompson } 429d99fa3c5SJeremy L Thompson // -- Clone output fields 430d99fa3c5SJeremy L Thompson for (int i = 0; i < opFine->qf->numoutputfields; i++) { 431d99fa3c5SJeremy L Thompson if (opFine->outputfields[i]->vec == CEED_VECTOR_ACTIVE) { 432d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opCoarse, opFine->outputfields[i]->fieldname, 433d99fa3c5SJeremy L Thompson rstrCoarse, basisCoarse, CEED_VECTOR_ACTIVE); 434d99fa3c5SJeremy L Thompson CeedChk(ierr); 435d99fa3c5SJeremy L Thompson } else { 436d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opCoarse, opFine->outputfields[i]->fieldname, 437d99fa3c5SJeremy L Thompson opFine->outputfields[i]->Erestrict, 438d99fa3c5SJeremy L Thompson opFine->outputfields[i]->basis, 439d99fa3c5SJeremy L Thompson opFine->outputfields[i]->vec); CeedChk(ierr); 440d99fa3c5SJeremy L Thompson } 441d99fa3c5SJeremy L Thompson } 442d99fa3c5SJeremy L Thompson 443d99fa3c5SJeremy L Thompson // Multiplicity vector 444d99fa3c5SJeremy L Thompson CeedVector multVec, multE; 445d99fa3c5SJeremy L Thompson ierr = CeedElemRestrictionCreateVector(rstrFine, &multVec, &multE); 446d99fa3c5SJeremy L Thompson CeedChk(ierr); 447d99fa3c5SJeremy L Thompson ierr = CeedVectorSetValue(multE, 0.0); CeedChk(ierr); 448d99fa3c5SJeremy L Thompson ierr = CeedElemRestrictionApply(rstrFine, CEED_NOTRANSPOSE, PMultFine, multE, 449d99fa3c5SJeremy L Thompson CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 450d99fa3c5SJeremy L Thompson ierr = CeedVectorSetValue(multVec, 0.0); CeedChk(ierr); 451d99fa3c5SJeremy L Thompson ierr = CeedElemRestrictionApply(rstrFine, CEED_TRANSPOSE, multE, multVec, 452d99fa3c5SJeremy L Thompson CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 453d99fa3c5SJeremy L Thompson ierr = CeedVectorDestroy(&multE); CeedChk(ierr); 454d99fa3c5SJeremy L Thompson ierr = CeedVectorReciprocal(multVec); CeedChk(ierr); 455d99fa3c5SJeremy L Thompson 456d99fa3c5SJeremy L Thompson // Restriction 457d99fa3c5SJeremy L Thompson CeedInt ncomp; 458d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumComponents(basisCoarse, &ncomp); CeedChk(ierr); 459d99fa3c5SJeremy L Thompson CeedQFunction qfRestrict; 460d99fa3c5SJeremy L Thompson ierr = CeedQFunctionCreateInteriorByName(ceed, "Scale", &qfRestrict); 461d99fa3c5SJeremy L Thompson CeedChk(ierr); 462777ff853SJeremy L Thompson CeedInt *ncompRData; 463777ff853SJeremy L Thompson ierr = CeedCalloc(1, &ncompRData); CeedChk(ierr); 464777ff853SJeremy L Thompson ncompRData[0] = ncomp; 465777ff853SJeremy L Thompson CeedQFunctionContext ctxR; 466777ff853SJeremy L Thompson ierr = CeedQFunctionContextCreate(ceed, &ctxR); CeedChk(ierr); 467777ff853SJeremy L Thompson ierr = CeedQFunctionContextSetData(ctxR, CEED_MEM_HOST, CEED_OWN_POINTER, 468777ff853SJeremy L Thompson sizeof(*ncompRData), ncompRData); 469777ff853SJeremy L Thompson CeedChk(ierr); 470777ff853SJeremy L Thompson ierr = CeedQFunctionSetContext(qfRestrict, ctxR); CeedChk(ierr); 471777ff853SJeremy L Thompson ierr = CeedQFunctionContextDestroy(&ctxR); CeedChk(ierr); 472d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddInput(qfRestrict, "input", ncomp, CEED_EVAL_NONE); 473d99fa3c5SJeremy L Thompson CeedChk(ierr); 474d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddInput(qfRestrict, "scale", ncomp, CEED_EVAL_NONE); 475d99fa3c5SJeremy L Thompson CeedChk(ierr); 476d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddOutput(qfRestrict, "output", ncomp, CEED_EVAL_INTERP); 477d99fa3c5SJeremy L Thompson CeedChk(ierr); 478d99fa3c5SJeremy L Thompson 479d99fa3c5SJeremy L Thompson ierr = CeedOperatorCreate(ceed, qfRestrict, CEED_QFUNCTION_NONE, 480d99fa3c5SJeremy L Thompson CEED_QFUNCTION_NONE, opRestrict); 481d99fa3c5SJeremy L Thompson CeedChk(ierr); 482d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opRestrict, "input", rstrFine, 483d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE); 484d99fa3c5SJeremy L Thompson CeedChk(ierr); 485d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opRestrict, "scale", rstrFine, 486d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, multVec); 487d99fa3c5SJeremy L Thompson CeedChk(ierr); 488d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opRestrict, "output", rstrCoarse, basisCtoF, 489d99fa3c5SJeremy L Thompson CEED_VECTOR_ACTIVE); CeedChk(ierr); 490d99fa3c5SJeremy L Thompson 491d99fa3c5SJeremy L Thompson // Prolongation 492d99fa3c5SJeremy L Thompson CeedQFunction qfProlong; 493d99fa3c5SJeremy L Thompson ierr = CeedQFunctionCreateInteriorByName(ceed, "Scale", &qfProlong); 494d99fa3c5SJeremy L Thompson CeedChk(ierr); 495777ff853SJeremy L Thompson CeedInt *ncompPData; 496777ff853SJeremy L Thompson ierr = CeedCalloc(1, &ncompPData); CeedChk(ierr); 497777ff853SJeremy L Thompson ncompPData[0] = ncomp; 498777ff853SJeremy L Thompson CeedQFunctionContext ctxP; 499777ff853SJeremy L Thompson ierr = CeedQFunctionContextCreate(ceed, &ctxP); CeedChk(ierr); 500777ff853SJeremy L Thompson ierr = CeedQFunctionContextSetData(ctxP, CEED_MEM_HOST, CEED_OWN_POINTER, 501777ff853SJeremy L Thompson sizeof(*ncompPData), ncompPData); 502777ff853SJeremy L Thompson CeedChk(ierr); 503777ff853SJeremy L Thompson ierr = CeedQFunctionSetContext(qfProlong, ctxP); CeedChk(ierr); 504777ff853SJeremy L Thompson ierr = CeedQFunctionContextDestroy(&ctxP); CeedChk(ierr); 505d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddInput(qfProlong, "input", ncomp, CEED_EVAL_INTERP); 506d99fa3c5SJeremy L Thompson CeedChk(ierr); 507d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddInput(qfProlong, "scale", ncomp, CEED_EVAL_NONE); 508d99fa3c5SJeremy L Thompson CeedChk(ierr); 509d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddOutput(qfProlong, "output", ncomp, CEED_EVAL_NONE); 510d99fa3c5SJeremy L Thompson CeedChk(ierr); 511d99fa3c5SJeremy L Thompson 512d99fa3c5SJeremy L Thompson ierr = CeedOperatorCreate(ceed, qfProlong, CEED_QFUNCTION_NONE, 513d99fa3c5SJeremy L Thompson CEED_QFUNCTION_NONE, opProlong); 514d99fa3c5SJeremy L Thompson CeedChk(ierr); 515d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opProlong, "input", rstrCoarse, basisCtoF, 516d99fa3c5SJeremy L Thompson CEED_VECTOR_ACTIVE); CeedChk(ierr); 517d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opProlong, "scale", rstrFine, 518d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, multVec); 519d99fa3c5SJeremy L Thompson CeedChk(ierr); 520d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opProlong, "output", rstrFine, 521d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE); 522d99fa3c5SJeremy L Thompson CeedChk(ierr); 523d99fa3c5SJeremy L Thompson 524d99fa3c5SJeremy L Thompson // Cleanup 525d99fa3c5SJeremy L Thompson ierr = CeedVectorDestroy(&multVec); CeedChk(ierr); 526d99fa3c5SJeremy L Thompson ierr = CeedBasisDestroy(&basisCtoF); CeedChk(ierr); 527d99fa3c5SJeremy L Thompson ierr = CeedQFunctionDestroy(&qfRestrict); CeedChk(ierr); 528d99fa3c5SJeremy L Thompson ierr = CeedQFunctionDestroy(&qfProlong); CeedChk(ierr); 529e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 530d99fa3c5SJeremy L Thompson } 531d99fa3c5SJeremy L Thompson 5327a982d89SJeremy L. Thompson /// @} 5337a982d89SJeremy L. Thompson 5347a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 5357a982d89SJeremy L. Thompson /// CeedOperator Backend API 5367a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 5377a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorBackend 5387a982d89SJeremy L. Thompson /// @{ 5397a982d89SJeremy L. Thompson 5407a982d89SJeremy L. Thompson /** 5417a982d89SJeremy L. Thompson @brief Get the Ceed associated with a CeedOperator 5427a982d89SJeremy L. Thompson 5437a982d89SJeremy L. Thompson @param op CeedOperator 5447a982d89SJeremy L. Thompson @param[out] ceed Variable to store Ceed 5457a982d89SJeremy L. Thompson 5467a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5477a982d89SJeremy L. Thompson 5487a982d89SJeremy L. Thompson @ref Backend 5497a982d89SJeremy L. Thompson **/ 5507a982d89SJeremy L. Thompson 5517a982d89SJeremy L. Thompson int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 5527a982d89SJeremy L. Thompson *ceed = op->ceed; 553e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5547a982d89SJeremy L. Thompson } 5557a982d89SJeremy L. Thompson 5567a982d89SJeremy L. Thompson /** 5577a982d89SJeremy L. Thompson @brief Get the number of elements associated with a CeedOperator 5587a982d89SJeremy L. Thompson 5597a982d89SJeremy L. Thompson @param op CeedOperator 5607a982d89SJeremy L. Thompson @param[out] numelem Variable to store number of elements 5617a982d89SJeremy L. Thompson 5627a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5637a982d89SJeremy L. Thompson 5647a982d89SJeremy L. Thompson @ref Backend 5657a982d89SJeremy L. Thompson **/ 5667a982d89SJeremy L. Thompson 5677a982d89SJeremy L. Thompson int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) { 5687a982d89SJeremy L. Thompson if (op->composite) 5697a982d89SJeremy L. Thompson // LCOV_EXCL_START 570e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 571e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 5727a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 5737a982d89SJeremy L. Thompson 5747a982d89SJeremy L. Thompson *numelem = op->numelements; 575e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5767a982d89SJeremy L. Thompson } 5777a982d89SJeremy L. Thompson 5787a982d89SJeremy L. Thompson /** 5797a982d89SJeremy L. Thompson @brief Get the number of quadrature points associated with a CeedOperator 5807a982d89SJeremy L. Thompson 5817a982d89SJeremy L. Thompson @param op CeedOperator 5827a982d89SJeremy L. Thompson @param[out] numqpts Variable to store vector number of quadrature points 5837a982d89SJeremy L. Thompson 5847a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5857a982d89SJeremy L. Thompson 5867a982d89SJeremy L. Thompson @ref Backend 5877a982d89SJeremy L. Thompson **/ 5887a982d89SJeremy L. Thompson 5897a982d89SJeremy L. Thompson int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) { 5907a982d89SJeremy L. Thompson if (op->composite) 5917a982d89SJeremy L. Thompson // LCOV_EXCL_START 592e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 593e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 5947a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 5957a982d89SJeremy L. Thompson 5967a982d89SJeremy L. Thompson *numqpts = op->numqpoints; 597e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5987a982d89SJeremy L. Thompson } 5997a982d89SJeremy L. Thompson 6007a982d89SJeremy L. Thompson /** 6017a982d89SJeremy L. Thompson @brief Get the number of arguments associated with a CeedOperator 6027a982d89SJeremy L. Thompson 6037a982d89SJeremy L. Thompson @param op CeedOperator 6047a982d89SJeremy L. Thompson @param[out] numargs Variable to store vector number of arguments 6057a982d89SJeremy L. Thompson 6067a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6077a982d89SJeremy L. Thompson 6087a982d89SJeremy L. Thompson @ref Backend 6097a982d89SJeremy L. Thompson **/ 6107a982d89SJeremy L. Thompson 6117a982d89SJeremy L. Thompson int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) { 6127a982d89SJeremy L. Thompson if (op->composite) 6137a982d89SJeremy L. Thompson // LCOV_EXCL_START 614e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 615e15f9bd0SJeremy L Thompson "Not defined for composite operators"); 6167a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 6177a982d89SJeremy L. Thompson 6187a982d89SJeremy L. Thompson *numargs = op->nfields; 619e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6207a982d89SJeremy L. Thompson } 6217a982d89SJeremy L. Thompson 6227a982d89SJeremy L. Thompson /** 6237a982d89SJeremy L. Thompson @brief Get the setup status of a CeedOperator 6247a982d89SJeremy L. Thompson 6257a982d89SJeremy L. Thompson @param op CeedOperator 626fd364f38SJeremy L Thompson @param[out] issetupdone Variable to store setup status 6277a982d89SJeremy L. Thompson 6287a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6297a982d89SJeremy L. Thompson 6307a982d89SJeremy L. Thompson @ref Backend 6317a982d89SJeremy L. Thompson **/ 6327a982d89SJeremy L. Thompson 633fd364f38SJeremy L Thompson int CeedOperatorIsSetupDone(CeedOperator op, bool *issetupdone) { 634e15f9bd0SJeremy L Thompson *issetupdone = op->backendsetup; 635e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6367a982d89SJeremy L. Thompson } 6377a982d89SJeremy L. Thompson 6387a982d89SJeremy L. Thompson /** 6397a982d89SJeremy L. Thompson @brief Get the QFunction associated with a CeedOperator 6407a982d89SJeremy L. Thompson 6417a982d89SJeremy L. Thompson @param op CeedOperator 6427a982d89SJeremy L. Thompson @param[out] qf Variable to store QFunction 6437a982d89SJeremy L. Thompson 6447a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6457a982d89SJeremy L. Thompson 6467a982d89SJeremy L. Thompson @ref Backend 6477a982d89SJeremy L. Thompson **/ 6487a982d89SJeremy L. Thompson 6497a982d89SJeremy L. Thompson int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 6507a982d89SJeremy L. Thompson if (op->composite) 6517a982d89SJeremy L. Thompson // LCOV_EXCL_START 652e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 653e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 6547a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 6557a982d89SJeremy L. Thompson 6567a982d89SJeremy L. Thompson *qf = op->qf; 657e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6587a982d89SJeremy L. Thompson } 6597a982d89SJeremy L. Thompson 6607a982d89SJeremy L. Thompson /** 661c04a41a7SJeremy L Thompson @brief Get a boolean value indicating if the CeedOperator is composite 662c04a41a7SJeremy L Thompson 663c04a41a7SJeremy L Thompson @param op CeedOperator 664fd364f38SJeremy L Thompson @param[out] iscomposite Variable to store composite status 665c04a41a7SJeremy L Thompson 666c04a41a7SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 667c04a41a7SJeremy L Thompson 668c04a41a7SJeremy L Thompson @ref Backend 669c04a41a7SJeremy L Thompson **/ 670c04a41a7SJeremy L Thompson 671fd364f38SJeremy L Thompson int CeedOperatorIsComposite(CeedOperator op, bool *iscomposite) { 672fd364f38SJeremy L Thompson *iscomposite = op->composite; 673e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 674c04a41a7SJeremy L Thompson } 675c04a41a7SJeremy L Thompson 676c04a41a7SJeremy L Thompson /** 6777a982d89SJeremy L. Thompson @brief Get the number of suboperators associated with a CeedOperator 6787a982d89SJeremy L. Thompson 6797a982d89SJeremy L. Thompson @param op CeedOperator 6807a982d89SJeremy L. Thompson @param[out] numsub Variable to store number of suboperators 6817a982d89SJeremy L. Thompson 6827a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6837a982d89SJeremy L. Thompson 6847a982d89SJeremy L. Thompson @ref Backend 6857a982d89SJeremy L. Thompson **/ 6867a982d89SJeremy L. Thompson 6877a982d89SJeremy L. Thompson int CeedOperatorGetNumSub(CeedOperator op, CeedInt *numsub) { 6887a982d89SJeremy L. Thompson if (!op->composite) 6897a982d89SJeremy L. Thompson // LCOV_EXCL_START 690e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator"); 6917a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 6927a982d89SJeremy L. Thompson 6937a982d89SJeremy L. Thompson *numsub = op->numsub; 694e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6957a982d89SJeremy L. Thompson } 6967a982d89SJeremy L. Thompson 6977a982d89SJeremy L. Thompson /** 6987a982d89SJeremy L. Thompson @brief Get the list of suboperators associated with a CeedOperator 6997a982d89SJeremy L. Thompson 7007a982d89SJeremy L. Thompson @param op CeedOperator 7017a982d89SJeremy L. Thompson @param[out] suboperators Variable to store list of suboperators 7027a982d89SJeremy L. Thompson 7037a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7047a982d89SJeremy L. Thompson 7057a982d89SJeremy L. Thompson @ref Backend 7067a982d89SJeremy L. Thompson **/ 7077a982d89SJeremy L. Thompson 7087a982d89SJeremy L. Thompson int CeedOperatorGetSubList(CeedOperator op, CeedOperator **suboperators) { 7097a982d89SJeremy L. Thompson if (!op->composite) 7107a982d89SJeremy L. Thompson // LCOV_EXCL_START 711e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator"); 7127a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 7137a982d89SJeremy L. Thompson 7147a982d89SJeremy L. Thompson *suboperators = op->suboperators; 715e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7167a982d89SJeremy L. Thompson } 7177a982d89SJeremy L. Thompson 7187a982d89SJeremy L. Thompson /** 7197a982d89SJeremy L. Thompson @brief Get the backend data of a CeedOperator 7207a982d89SJeremy L. Thompson 7217a982d89SJeremy L. Thompson @param op CeedOperator 7227a982d89SJeremy L. Thompson @param[out] data Variable to store data 7237a982d89SJeremy L. Thompson 7247a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7257a982d89SJeremy L. Thompson 7267a982d89SJeremy L. Thompson @ref Backend 7277a982d89SJeremy L. Thompson **/ 7287a982d89SJeremy L. Thompson 729777ff853SJeremy L Thompson int CeedOperatorGetData(CeedOperator op, void *data) { 730777ff853SJeremy L Thompson *(void **)data = op->data; 731e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7327a982d89SJeremy L. Thompson } 7337a982d89SJeremy L. Thompson 7347a982d89SJeremy L. Thompson /** 7357a982d89SJeremy L. Thompson @brief Set the backend data of a CeedOperator 7367a982d89SJeremy L. Thompson 7377a982d89SJeremy L. Thompson @param[out] op CeedOperator 7387a982d89SJeremy L. Thompson @param data Data to set 7397a982d89SJeremy L. Thompson 7407a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7417a982d89SJeremy L. Thompson 7427a982d89SJeremy L. Thompson @ref Backend 7437a982d89SJeremy L. Thompson **/ 7447a982d89SJeremy L. Thompson 745777ff853SJeremy L Thompson int CeedOperatorSetData(CeedOperator op, void *data) { 746777ff853SJeremy L Thompson op->data = data; 747e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7487a982d89SJeremy L. Thompson } 7497a982d89SJeremy L. Thompson 7507a982d89SJeremy L. Thompson /** 7517a982d89SJeremy L. Thompson @brief Set the setup flag of a CeedOperator to True 7527a982d89SJeremy L. Thompson 7537a982d89SJeremy L. Thompson @param op CeedOperator 7547a982d89SJeremy L. Thompson 7557a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7567a982d89SJeremy L. Thompson 7577a982d89SJeremy L. Thompson @ref Backend 7587a982d89SJeremy L. Thompson **/ 7597a982d89SJeremy L. Thompson 7607a982d89SJeremy L. Thompson int CeedOperatorSetSetupDone(CeedOperator op) { 761e15f9bd0SJeremy L Thompson op->backendsetup = true; 762e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7637a982d89SJeremy L. Thompson } 7647a982d89SJeremy L. Thompson 7657a982d89SJeremy L. Thompson /** 7667a982d89SJeremy L. Thompson @brief Get the CeedOperatorFields of a CeedOperator 7677a982d89SJeremy L. Thompson 7687a982d89SJeremy L. Thompson @param op CeedOperator 7697a982d89SJeremy L. Thompson @param[out] inputfields Variable to store inputfields 7707a982d89SJeremy L. Thompson @param[out] outputfields Variable to store outputfields 7717a982d89SJeremy L. Thompson 7727a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7737a982d89SJeremy L. Thompson 7747a982d89SJeremy L. Thompson @ref Backend 7757a982d89SJeremy L. Thompson **/ 7767a982d89SJeremy L. Thompson 7777a982d89SJeremy L. Thompson int CeedOperatorGetFields(CeedOperator op, CeedOperatorField **inputfields, 7787a982d89SJeremy L. Thompson CeedOperatorField **outputfields) { 7797a982d89SJeremy L. Thompson if (op->composite) 7807a982d89SJeremy L. Thompson // LCOV_EXCL_START 781e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 782e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 7837a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 7847a982d89SJeremy L. Thompson 7857a982d89SJeremy L. Thompson if (inputfields) *inputfields = op->inputfields; 7867a982d89SJeremy L. Thompson if (outputfields) *outputfields = op->outputfields; 787e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7887a982d89SJeremy L. Thompson } 7897a982d89SJeremy L. Thompson 7907a982d89SJeremy L. Thompson /** 7917a982d89SJeremy L. Thompson @brief Get the CeedElemRestriction of a CeedOperatorField 7927a982d89SJeremy L. Thompson 7937a982d89SJeremy L. Thompson @param opfield CeedOperatorField 7947a982d89SJeremy L. Thompson @param[out] rstr Variable to store CeedElemRestriction 7957a982d89SJeremy L. Thompson 7967a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7977a982d89SJeremy L. Thompson 7987a982d89SJeremy L. Thompson @ref Backend 7997a982d89SJeremy L. Thompson **/ 8007a982d89SJeremy L. Thompson 8017a982d89SJeremy L. Thompson int CeedOperatorFieldGetElemRestriction(CeedOperatorField opfield, 8027a982d89SJeremy L. Thompson CeedElemRestriction *rstr) { 8037a982d89SJeremy L. Thompson *rstr = opfield->Erestrict; 804e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8057a982d89SJeremy L. Thompson } 8067a982d89SJeremy L. Thompson 8077a982d89SJeremy L. Thompson /** 8087a982d89SJeremy L. Thompson @brief Get the CeedBasis of a CeedOperatorField 8097a982d89SJeremy L. Thompson 8107a982d89SJeremy L. Thompson @param opfield CeedOperatorField 8117a982d89SJeremy L. Thompson @param[out] basis Variable to store CeedBasis 8127a982d89SJeremy L. Thompson 8137a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 8147a982d89SJeremy L. Thompson 8157a982d89SJeremy L. Thompson @ref Backend 8167a982d89SJeremy L. Thompson **/ 8177a982d89SJeremy L. Thompson 8187a982d89SJeremy L. Thompson int CeedOperatorFieldGetBasis(CeedOperatorField opfield, CeedBasis *basis) { 8197a982d89SJeremy L. Thompson *basis = opfield->basis; 820e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8217a982d89SJeremy L. Thompson } 8227a982d89SJeremy L. Thompson 8237a982d89SJeremy L. Thompson /** 8247a982d89SJeremy L. Thompson @brief Get the CeedVector of a CeedOperatorField 8257a982d89SJeremy L. Thompson 8267a982d89SJeremy L. Thompson @param opfield CeedOperatorField 8277a982d89SJeremy L. Thompson @param[out] vec Variable to store CeedVector 8287a982d89SJeremy L. Thompson 8297a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 8307a982d89SJeremy L. Thompson 8317a982d89SJeremy L. Thompson @ref Backend 8327a982d89SJeremy L. Thompson **/ 8337a982d89SJeremy L. Thompson 8347a982d89SJeremy L. Thompson int CeedOperatorFieldGetVector(CeedOperatorField opfield, CeedVector *vec) { 8357a982d89SJeremy L. Thompson *vec = opfield->vec; 836e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8377a982d89SJeremy L. Thompson } 8387a982d89SJeremy L. Thompson 8397a982d89SJeremy L. Thompson /// @} 8407a982d89SJeremy L. Thompson 8417a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 8427a982d89SJeremy L. Thompson /// CeedOperator Public API 8437a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 8447a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorUser 845dfdf5a53Sjeremylt /// @{ 846d7b241e6Sjeremylt 847d7b241e6Sjeremylt /** 8480219ea01SJeremy L Thompson @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and 8490219ea01SJeremy L Thompson CeedElemRestriction can be associated with CeedQFunction fields with 8500219ea01SJeremy L Thompson \ref CeedOperatorSetField. 851d7b241e6Sjeremylt 852b11c1e72Sjeremylt @param ceed A Ceed object where the CeedOperator will be created 853d7b241e6Sjeremylt @param qf QFunction defining the action of the operator at quadrature points 85434138859Sjeremylt @param dqf QFunction defining the action of the Jacobian of @a qf (or 8554cc79fe7SJed Brown @ref CEED_QFUNCTION_NONE) 856d7b241e6Sjeremylt @param dqfT QFunction defining the action of the transpose of the Jacobian 8574cc79fe7SJed Brown of @a qf (or @ref CEED_QFUNCTION_NONE) 858b11c1e72Sjeremylt @param[out] op Address of the variable where the newly created 859b11c1e72Sjeremylt CeedOperator will be stored 860b11c1e72Sjeremylt 861b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 862dfdf5a53Sjeremylt 8637a982d89SJeremy L. Thompson @ref User 864d7b241e6Sjeremylt */ 865d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf, 866d7b241e6Sjeremylt CeedQFunction dqfT, CeedOperator *op) { 867d7b241e6Sjeremylt int ierr; 868d7b241e6Sjeremylt 8695fe0d4faSjeremylt if (!ceed->OperatorCreate) { 8705fe0d4faSjeremylt Ceed delegate; 871aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 8725fe0d4faSjeremylt 8735fe0d4faSjeremylt if (!delegate) 874c042f62fSJeremy L Thompson // LCOV_EXCL_START 875e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 876e15f9bd0SJeremy L Thompson "Backend does not support OperatorCreate"); 877c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 8785fe0d4faSjeremylt 8795fe0d4faSjeremylt ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr); 880e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8815fe0d4faSjeremylt } 8825fe0d4faSjeremylt 883b3b7035fSJeremy L Thompson if (!qf || qf == CEED_QFUNCTION_NONE) 884b3b7035fSJeremy L Thompson // LCOV_EXCL_START 885e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 886e15f9bd0SJeremy L Thompson "Operator must have a valid QFunction."); 887b3b7035fSJeremy L Thompson // LCOV_EXCL_STOP 888d7b241e6Sjeremylt ierr = CeedCalloc(1, op); CeedChk(ierr); 889d7b241e6Sjeremylt (*op)->ceed = ceed; 890d7b241e6Sjeremylt ceed->refcount++; 891d7b241e6Sjeremylt (*op)->refcount = 1; 892d7b241e6Sjeremylt (*op)->qf = qf; 893d7b241e6Sjeremylt qf->refcount++; 894442e7f0bSjeremylt if (dqf && dqf != CEED_QFUNCTION_NONE) { 895d7b241e6Sjeremylt (*op)->dqf = dqf; 896442e7f0bSjeremylt dqf->refcount++; 897442e7f0bSjeremylt } 898442e7f0bSjeremylt if (dqfT && dqfT != CEED_QFUNCTION_NONE) { 899d7b241e6Sjeremylt (*op)->dqfT = dqfT; 900442e7f0bSjeremylt dqfT->refcount++; 901442e7f0bSjeremylt } 902fe2413ffSjeremylt ierr = CeedCalloc(16, &(*op)->inputfields); CeedChk(ierr); 903fe2413ffSjeremylt ierr = CeedCalloc(16, &(*op)->outputfields); CeedChk(ierr); 904d7b241e6Sjeremylt ierr = ceed->OperatorCreate(*op); CeedChk(ierr); 905e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 906d7b241e6Sjeremylt } 907d7b241e6Sjeremylt 908d7b241e6Sjeremylt /** 90952d6035fSJeremy L Thompson @brief Create an operator that composes the action of several operators 91052d6035fSJeremy L Thompson 91152d6035fSJeremy L Thompson @param ceed A Ceed object where the CeedOperator will be created 91252d6035fSJeremy L Thompson @param[out] op Address of the variable where the newly created 91352d6035fSJeremy L Thompson Composite CeedOperator will be stored 91452d6035fSJeremy L Thompson 91552d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 91652d6035fSJeremy L Thompson 9177a982d89SJeremy L. Thompson @ref User 91852d6035fSJeremy L Thompson */ 91952d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) { 92052d6035fSJeremy L Thompson int ierr; 92152d6035fSJeremy L Thompson 92252d6035fSJeremy L Thompson if (!ceed->CompositeOperatorCreate) { 92352d6035fSJeremy L Thompson Ceed delegate; 924aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 92552d6035fSJeremy L Thompson 926250756a7Sjeremylt if (delegate) { 92752d6035fSJeremy L Thompson ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr); 928e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 92952d6035fSJeremy L Thompson } 930250756a7Sjeremylt } 93152d6035fSJeremy L Thompson 93252d6035fSJeremy L Thompson ierr = CeedCalloc(1, op); CeedChk(ierr); 93352d6035fSJeremy L Thompson (*op)->ceed = ceed; 93452d6035fSJeremy L Thompson ceed->refcount++; 93552d6035fSJeremy L Thompson (*op)->composite = true; 93652d6035fSJeremy L Thompson ierr = CeedCalloc(16, &(*op)->suboperators); CeedChk(ierr); 937250756a7Sjeremylt 938250756a7Sjeremylt if (ceed->CompositeOperatorCreate) { 93952d6035fSJeremy L Thompson ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr); 940250756a7Sjeremylt } 941e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 94252d6035fSJeremy L Thompson } 94352d6035fSJeremy L Thompson 94452d6035fSJeremy L Thompson /** 945b11c1e72Sjeremylt @brief Provide a field to a CeedOperator for use by its CeedQFunction 946d7b241e6Sjeremylt 947d7b241e6Sjeremylt This function is used to specify both active and passive fields to a 948d7b241e6Sjeremylt CeedOperator. For passive fields, a vector @arg v must be provided. Passive 949d7b241e6Sjeremylt fields can inputs or outputs (updated in-place when operator is applied). 950d7b241e6Sjeremylt 951d7b241e6Sjeremylt Active fields must be specified using this function, but their data (in a 952d7b241e6Sjeremylt CeedVector) is passed in CeedOperatorApply(). There can be at most one active 953d7b241e6Sjeremylt input and at most one active output. 954d7b241e6Sjeremylt 9558c91a0c9SJeremy L Thompson @param op CeedOperator on which to provide the field 9568795c945Sjeremylt @param fieldname Name of the field (to be matched with the name used by 9578795c945Sjeremylt CeedQFunction) 958b11c1e72Sjeremylt @param r CeedElemRestriction 9594cc79fe7SJed Brown @param b CeedBasis in which the field resides or @ref CEED_BASIS_COLLOCATED 960b11c1e72Sjeremylt if collocated with quadrature points 9614cc79fe7SJed Brown @param v CeedVector to be used by CeedOperator or @ref CEED_VECTOR_ACTIVE 9624cc79fe7SJed Brown if field is active or @ref CEED_VECTOR_NONE if using 9634cc79fe7SJed Brown @ref CEED_EVAL_WEIGHT in the QFunction 964b11c1e72Sjeremylt 965b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 966dfdf5a53Sjeremylt 9677a982d89SJeremy L. Thompson @ref User 968b11c1e72Sjeremylt **/ 969d7b241e6Sjeremylt int CeedOperatorSetField(CeedOperator op, const char *fieldname, 970a8d32208Sjeremylt CeedElemRestriction r, CeedBasis b, CeedVector v) { 971d7b241e6Sjeremylt int ierr; 97252d6035fSJeremy L Thompson if (op->composite) 973c042f62fSJeremy L Thompson // LCOV_EXCL_START 974e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 975e15f9bd0SJeremy L Thompson "Cannot add field to composite operator."); 976c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 9778b067b84SJed Brown if (!r) 978c042f62fSJeremy L Thompson // LCOV_EXCL_START 979e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 980c042f62fSJeremy L Thompson "ElemRestriction r for field \"%s\" must be non-NULL.", 981c042f62fSJeremy L Thompson fieldname); 982c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 9838b067b84SJed Brown if (!b) 984c042f62fSJeremy L Thompson // LCOV_EXCL_START 985e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 986e15f9bd0SJeremy L Thompson "Basis b for field \"%s\" must be non-NULL.", 987c042f62fSJeremy L Thompson fieldname); 988c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 9898b067b84SJed Brown if (!v) 990c042f62fSJeremy L Thompson // LCOV_EXCL_START 991e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 992e15f9bd0SJeremy L Thompson "Vector v for field \"%s\" must be non-NULL.", 993c042f62fSJeremy L Thompson fieldname); 994c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 99552d6035fSJeremy L Thompson 996d7b241e6Sjeremylt CeedInt numelements; 997d7b241e6Sjeremylt ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr); 99815910d16Sjeremylt if (r != CEED_ELEMRESTRICTION_NONE && op->hasrestriction && 99915910d16Sjeremylt op->numelements != numelements) 1000c042f62fSJeremy L Thompson // LCOV_EXCL_START 1001e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 10021d102b48SJeremy L Thompson "ElemRestriction with %d elements incompatible with prior " 10031d102b48SJeremy L Thompson "%d elements", numelements, op->numelements); 1004c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1005d7b241e6Sjeremylt 1006d7b241e6Sjeremylt CeedInt numqpoints; 1007e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 1008d7b241e6Sjeremylt ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr); 1009d7b241e6Sjeremylt if (op->numqpoints && op->numqpoints != numqpoints) 1010c042f62fSJeremy L Thompson // LCOV_EXCL_START 1011e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 1012e15f9bd0SJeremy L Thompson "Basis with %d quadrature points " 10131d102b48SJeremy L Thompson "incompatible with prior %d points", numqpoints, 10141d102b48SJeremy L Thompson op->numqpoints); 1015c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1016d7b241e6Sjeremylt } 101715910d16Sjeremylt CeedQFunctionField qfield; 1018d1bcdac9Sjeremylt CeedOperatorField *ofield; 1019d7b241e6Sjeremylt for (CeedInt i=0; i<op->qf->numinputfields; i++) { 1020fe2413ffSjeremylt if (!strcmp(fieldname, (*op->qf->inputfields[i]).fieldname)) { 102115910d16Sjeremylt qfield = op->qf->inputfields[i]; 1022d7b241e6Sjeremylt ofield = &op->inputfields[i]; 1023d7b241e6Sjeremylt goto found; 1024d7b241e6Sjeremylt } 1025d7b241e6Sjeremylt } 1026d7b241e6Sjeremylt for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 1027fe2413ffSjeremylt if (!strcmp(fieldname, (*op->qf->outputfields[i]).fieldname)) { 1028e15f9bd0SJeremy L Thompson qfield = op->qf->outputfields[i]; 1029d7b241e6Sjeremylt ofield = &op->outputfields[i]; 1030d7b241e6Sjeremylt goto found; 1031d7b241e6Sjeremylt } 1032d7b241e6Sjeremylt } 1033c042f62fSJeremy L Thompson // LCOV_EXCL_START 1034e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_INCOMPLETE, 1035e15f9bd0SJeremy L Thompson "QFunction has no knowledge of field '%s'", 1036d7b241e6Sjeremylt fieldname); 1037c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1038d7b241e6Sjeremylt found: 1039e15f9bd0SJeremy L Thompson ierr = CeedOperatorCheckField(op->ceed, qfield, r, b); CeedChk(ierr); 1040fe2413ffSjeremylt ierr = CeedCalloc(1, ofield); CeedChk(ierr); 1041e15f9bd0SJeremy L Thompson 1042e15f9bd0SJeremy L Thompson (*ofield)->vec = v; 1043e15f9bd0SJeremy L Thompson if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) { 1044e15f9bd0SJeremy L Thompson v->refcount += 1; 1045e15f9bd0SJeremy L Thompson } 1046e15f9bd0SJeremy L Thompson 1047fe2413ffSjeremylt (*ofield)->Erestrict = r; 104871352a93Sjeremylt r->refcount += 1; 1049e15f9bd0SJeremy L Thompson if (r != CEED_ELEMRESTRICTION_NONE) { 1050e15f9bd0SJeremy L Thompson op->numelements = numelements; 1051e15f9bd0SJeremy L Thompson op->hasrestriction = true; // Restriction set, but numelements may be 0 1052e15f9bd0SJeremy L Thompson } 1053d99fa3c5SJeremy L Thompson 1054e15f9bd0SJeremy L Thompson (*ofield)->basis = b; 1055e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 1056e15f9bd0SJeremy L Thompson op->numqpoints = numqpoints; 1057e15f9bd0SJeremy L Thompson b->refcount += 1; 1058e15f9bd0SJeremy L Thompson } 1059e15f9bd0SJeremy L Thompson 1060e15f9bd0SJeremy L Thompson op->nfields += 1; 1061d99fa3c5SJeremy L Thompson size_t len = strlen(fieldname); 1062d99fa3c5SJeremy L Thompson char *tmp; 1063d99fa3c5SJeremy L Thompson ierr = CeedCalloc(len+1, &tmp); CeedChk(ierr); 1064d99fa3c5SJeremy L Thompson memcpy(tmp, fieldname, len+1); 1065d99fa3c5SJeremy L Thompson (*ofield)->fieldname = tmp; 1066e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1067d7b241e6Sjeremylt } 1068d7b241e6Sjeremylt 1069d7b241e6Sjeremylt /** 107052d6035fSJeremy L Thompson @brief Add a sub-operator to a composite CeedOperator 1071288c0443SJeremy L Thompson 107234138859Sjeremylt @param[out] compositeop Composite CeedOperator 107334138859Sjeremylt @param subop Sub-operator CeedOperator 107452d6035fSJeremy L Thompson 107552d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 107652d6035fSJeremy L Thompson 10777a982d89SJeremy L. Thompson @ref User 107852d6035fSJeremy L Thompson */ 1079692c2638Sjeremylt int CeedCompositeOperatorAddSub(CeedOperator compositeop, CeedOperator subop) { 108052d6035fSJeremy L Thompson if (!compositeop->composite) 1081c042f62fSJeremy L Thompson // LCOV_EXCL_START 1082e15f9bd0SJeremy L Thompson return CeedError(compositeop->ceed, CEED_ERROR_MINOR, 1083e2f04181SAndrew T. Barker "CeedOperator is not a composite operator"); 1084c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 108552d6035fSJeremy L Thompson 108652d6035fSJeremy L Thompson if (compositeop->numsub == CEED_COMPOSITE_MAX) 1087c042f62fSJeremy L Thompson // LCOV_EXCL_START 1088e15f9bd0SJeremy L Thompson return CeedError(compositeop->ceed, CEED_ERROR_UNSUPPORTED, 1089e15f9bd0SJeremy L Thompson "Cannot add additional suboperators"); 1090c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 109152d6035fSJeremy L Thompson 109252d6035fSJeremy L Thompson compositeop->suboperators[compositeop->numsub] = subop; 109352d6035fSJeremy L Thompson subop->refcount++; 109452d6035fSJeremy L Thompson compositeop->numsub++; 1095e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 109652d6035fSJeremy L Thompson } 109752d6035fSJeremy L Thompson 109852d6035fSJeremy L Thompson /** 10991d102b48SJeremy L Thompson @brief Assemble a linear CeedQFunction associated with a CeedOperator 11001d102b48SJeremy L Thompson 11011d102b48SJeremy L Thompson This returns a CeedVector containing a matrix at each quadrature point 11021d102b48SJeremy L Thompson providing the action of the CeedQFunction associated with the CeedOperator. 11031d102b48SJeremy L Thompson The vector 'assembled' is of shape 11041d102b48SJeremy L Thompson [num_elements, num_input_fields, num_output_fields, num_quad_points] 11051d102b48SJeremy L Thompson and contains column-major matrices representing the action of the 11061d102b48SJeremy L Thompson CeedQFunction for a corresponding quadrature point on an element. Inputs and 11071d102b48SJeremy L Thompson outputs are in the order provided by the user when adding CeedOperator fields. 11084cc79fe7SJed Brown For example, a CeedQFunction with inputs 'u' and 'gradu' and outputs 'gradv' and 11091d102b48SJeremy L Thompson 'v', provided in that order, would result in an assembled QFunction that 11101d102b48SJeremy L Thompson consists of (1 + dim) x (dim + 1) matrices at each quadrature point acting 11111d102b48SJeremy L Thompson on the input [u, du_0, du_1] and producing the output [dv_0, dv_1, v]. 11121d102b48SJeremy L Thompson 11131d102b48SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 11141d102b48SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedQFunction at 11151d102b48SJeremy L Thompson quadrature points 11161d102b48SJeremy L Thompson @param[out] rstr CeedElemRestriction for CeedVector containing assembled 11171d102b48SJeremy L Thompson CeedQFunction 11181d102b48SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 11194cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 11201d102b48SJeremy L Thompson 11211d102b48SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 11221d102b48SJeremy L Thompson 11237a982d89SJeremy L. Thompson @ref User 11241d102b48SJeremy L Thompson **/ 112580ac2e43SJeremy L Thompson int CeedOperatorLinearAssembleQFunction(CeedOperator op, CeedVector *assembled, 11267f823360Sjeremylt CeedElemRestriction *rstr, 11277f823360Sjeremylt CeedRequest *request) { 11281d102b48SJeremy L Thompson int ierr; 1129e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 11301d102b48SJeremy L Thompson 11317172caadSjeremylt // Backend version 113280ac2e43SJeremy L Thompson if (op->LinearAssembleQFunction) { 1133e2f04181SAndrew T. Barker return op->LinearAssembleQFunction(op, assembled, rstr, request); 11345107b09fSJeremy L Thompson } else { 11355107b09fSJeremy L Thompson // Fallback to reference Ceed 11365107b09fSJeremy L Thompson if (!op->opfallback) { 11375107b09fSJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 11385107b09fSJeremy L Thompson } 11395107b09fSJeremy L Thompson // Assemble 1140e2f04181SAndrew T. Barker return CeedOperatorLinearAssembleQFunction(op->opfallback, assembled, 1141e2f04181SAndrew T. Barker rstr, request); 11425107b09fSJeremy L Thompson } 11431d102b48SJeremy L Thompson } 11441d102b48SJeremy L Thompson 11451d102b48SJeremy L Thompson /** 1146d965c7a7SJeremy L Thompson @brief Assemble the diagonal of a square linear CeedOperator 1147b7ec98d8SJeremy L Thompson 11489e9210b8SJeremy L Thompson This overwrites a CeedVector with the diagonal of a linear CeedOperator. 1149b7ec98d8SJeremy L Thompson 1150c04a41a7SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 1151c04a41a7SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 1152d965c7a7SJeremy L Thompson 1153b7ec98d8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 1154b7ec98d8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator diagonal 1155b7ec98d8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 11564cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 1157b7ec98d8SJeremy L Thompson 1158b7ec98d8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1159b7ec98d8SJeremy L Thompson 11607a982d89SJeremy L. Thompson @ref User 1161b7ec98d8SJeremy L Thompson **/ 11622bba3ffaSJeremy L Thompson int CeedOperatorLinearAssembleDiagonal(CeedOperator op, CeedVector assembled, 11637f823360Sjeremylt CeedRequest *request) { 1164b7ec98d8SJeremy L Thompson int ierr; 1165e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1166b7ec98d8SJeremy L Thompson 1167b7ec98d8SJeremy L Thompson // Use backend version, if available 116880ac2e43SJeremy L Thompson if (op->LinearAssembleDiagonal) { 1169e2f04181SAndrew T. Barker return op->LinearAssembleDiagonal(op, assembled, request); 11709e9210b8SJeremy L Thompson } else if (op->LinearAssembleAddDiagonal) { 11719e9210b8SJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 11729e9210b8SJeremy L Thompson return CeedOperatorLinearAssembleAddDiagonal(op, assembled, request); 11739e9210b8SJeremy L Thompson } else { 11749e9210b8SJeremy L Thompson // Fallback to reference Ceed 11759e9210b8SJeremy L Thompson if (!op->opfallback) { 11769e9210b8SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 11779e9210b8SJeremy L Thompson } 11789e9210b8SJeremy L Thompson // Assemble 1179e2f04181SAndrew T. Barker return CeedOperatorLinearAssembleDiagonal(op->opfallback, assembled, 1180e2f04181SAndrew T. Barker request); 11819e9210b8SJeremy L Thompson } 11829e9210b8SJeremy L Thompson } 11839e9210b8SJeremy L Thompson 11849e9210b8SJeremy L Thompson /** 11859e9210b8SJeremy L Thompson @brief Assemble the diagonal of a square linear CeedOperator 11869e9210b8SJeremy L Thompson 11879e9210b8SJeremy L Thompson This sums into a CeedVector the diagonal of a linear CeedOperator. 11889e9210b8SJeremy L Thompson 11899e9210b8SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 11909e9210b8SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 11919e9210b8SJeremy L Thompson 11929e9210b8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 11939e9210b8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator diagonal 11949e9210b8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 11959e9210b8SJeremy L Thompson @ref CEED_REQUEST_IMMEDIATE 11969e9210b8SJeremy L Thompson 11979e9210b8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 11989e9210b8SJeremy L Thompson 11999e9210b8SJeremy L Thompson @ref User 12009e9210b8SJeremy L Thompson **/ 12019e9210b8SJeremy L Thompson int CeedOperatorLinearAssembleAddDiagonal(CeedOperator op, CeedVector assembled, 12029e9210b8SJeremy L Thompson CeedRequest *request) { 12039e9210b8SJeremy L Thompson int ierr; 1204e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 12059e9210b8SJeremy L Thompson 12069e9210b8SJeremy L Thompson // Use backend version, if available 12079e9210b8SJeremy L Thompson if (op->LinearAssembleAddDiagonal) { 1208e2f04181SAndrew T. Barker return op->LinearAssembleAddDiagonal(op, assembled, request); 12097172caadSjeremylt } else { 12107172caadSjeremylt // Fallback to reference Ceed 12117172caadSjeremylt if (!op->opfallback) { 12127172caadSjeremylt ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1213b7ec98d8SJeremy L Thompson } 12147172caadSjeremylt // Assemble 1215e2f04181SAndrew T. Barker return CeedOperatorLinearAssembleAddDiagonal(op->opfallback, assembled, 1216e2f04181SAndrew T. Barker request); 1217b7ec98d8SJeremy L Thompson } 1218b7ec98d8SJeremy L Thompson } 1219b7ec98d8SJeremy L Thompson 1220b7ec98d8SJeremy L Thompson /** 1221d965c7a7SJeremy L Thompson @brief Assemble the point block diagonal of a square linear CeedOperator 1222d965c7a7SJeremy L Thompson 12239e9210b8SJeremy L Thompson This overwrites a CeedVector with the point block diagonal of a linear 1224d965c7a7SJeremy L Thompson CeedOperator. 1225d965c7a7SJeremy L Thompson 1226c04a41a7SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 1227c04a41a7SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 1228d965c7a7SJeremy L Thompson 1229d965c7a7SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 1230d965c7a7SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator point block 1231d965c7a7SJeremy L Thompson diagonal, provided in row-major form with an 1232d965c7a7SJeremy L Thompson @a ncomp * @a ncomp block at each node. The dimensions 1233d965c7a7SJeremy L Thompson of this vector are derived from the active vector 1234d965c7a7SJeremy L Thompson for the CeedOperator. The array has shape 1235d965c7a7SJeremy L Thompson [nodes, component out, component in]. 1236d965c7a7SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 1237d965c7a7SJeremy L Thompson CEED_REQUEST_IMMEDIATE 1238d965c7a7SJeremy L Thompson 1239d965c7a7SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1240d965c7a7SJeremy L Thompson 1241d965c7a7SJeremy L Thompson @ref User 1242d965c7a7SJeremy L Thompson **/ 124380ac2e43SJeremy L Thompson int CeedOperatorLinearAssemblePointBlockDiagonal(CeedOperator op, 12442bba3ffaSJeremy L Thompson CeedVector assembled, CeedRequest *request) { 1245d965c7a7SJeremy L Thompson int ierr; 1246e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1247d965c7a7SJeremy L Thompson 1248d965c7a7SJeremy L Thompson // Use backend version, if available 124980ac2e43SJeremy L Thompson if (op->LinearAssemblePointBlockDiagonal) { 1250e2f04181SAndrew T. Barker return op->LinearAssemblePointBlockDiagonal(op, assembled, request); 12519e9210b8SJeremy L Thompson } else if (op->LinearAssembleAddPointBlockDiagonal) { 12529e9210b8SJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 12539e9210b8SJeremy L Thompson return CeedOperatorLinearAssembleAddPointBlockDiagonal(op, assembled, 12549e9210b8SJeremy L Thompson request); 1255d965c7a7SJeremy L Thompson } else { 1256d965c7a7SJeremy L Thompson // Fallback to reference Ceed 1257d965c7a7SJeremy L Thompson if (!op->opfallback) { 1258d965c7a7SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1259d965c7a7SJeremy L Thompson } 1260d965c7a7SJeremy L Thompson // Assemble 1261e2f04181SAndrew T. Barker return CeedOperatorLinearAssemblePointBlockDiagonal(op->opfallback, 1262e2f04181SAndrew T. Barker assembled, request); 12639e9210b8SJeremy L Thompson } 12649e9210b8SJeremy L Thompson } 12659e9210b8SJeremy L Thompson 12669e9210b8SJeremy L Thompson /** 12679e9210b8SJeremy L Thompson @brief Assemble the point block diagonal of a square linear CeedOperator 12689e9210b8SJeremy L Thompson 12699e9210b8SJeremy L Thompson This sums into a CeedVector with the point block diagonal of a linear 12709e9210b8SJeremy L Thompson CeedOperator. 12719e9210b8SJeremy L Thompson 12729e9210b8SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 12739e9210b8SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 12749e9210b8SJeremy L Thompson 12759e9210b8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 12769e9210b8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator point block 12779e9210b8SJeremy L Thompson diagonal, provided in row-major form with an 12789e9210b8SJeremy L Thompson @a ncomp * @a ncomp block at each node. The dimensions 12799e9210b8SJeremy L Thompson of this vector are derived from the active vector 12809e9210b8SJeremy L Thompson for the CeedOperator. The array has shape 12819e9210b8SJeremy L Thompson [nodes, component out, component in]. 12829e9210b8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 12839e9210b8SJeremy L Thompson CEED_REQUEST_IMMEDIATE 12849e9210b8SJeremy L Thompson 12859e9210b8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 12869e9210b8SJeremy L Thompson 12879e9210b8SJeremy L Thompson @ref User 12889e9210b8SJeremy L Thompson **/ 12899e9210b8SJeremy L Thompson int CeedOperatorLinearAssembleAddPointBlockDiagonal(CeedOperator op, 12909e9210b8SJeremy L Thompson CeedVector assembled, CeedRequest *request) { 12919e9210b8SJeremy L Thompson int ierr; 1292e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 12939e9210b8SJeremy L Thompson 12949e9210b8SJeremy L Thompson // Use backend version, if available 12959e9210b8SJeremy L Thompson if (op->LinearAssembleAddPointBlockDiagonal) { 1296e2f04181SAndrew T. Barker return op->LinearAssembleAddPointBlockDiagonal(op, assembled, request); 12979e9210b8SJeremy L Thompson } else { 12989e9210b8SJeremy L Thompson // Fallback to reference Ceed 12999e9210b8SJeremy L Thompson if (!op->opfallback) { 13009e9210b8SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 13019e9210b8SJeremy L Thompson } 13029e9210b8SJeremy L Thompson // Assemble 1303e2f04181SAndrew T. Barker return CeedOperatorLinearAssembleAddPointBlockDiagonal(op->opfallback, 1304e2f04181SAndrew T. Barker assembled, request); 1305d965c7a7SJeremy L Thompson } 1306e2f04181SAndrew T. Barker } 1307e2f04181SAndrew T. Barker 1308e2f04181SAndrew T. Barker /** 1309e2f04181SAndrew T. Barker @brief Build nonzero pattern for non-composite operator. 1310e2f04181SAndrew T. Barker 1311e2f04181SAndrew T. Barker Users should generally use CeedOperatorLinearAssembleSymbolic() 1312e2f04181SAndrew T. Barker 1313e2f04181SAndrew T. Barker @ref Developer 1314e2f04181SAndrew T. Barker **/ 1315e2f04181SAndrew T. Barker int CeedSingleOperatorAssembleSymbolic(CeedOperator op, CeedInt offset, 1316e2f04181SAndrew T. Barker CeedInt *rows, CeedInt *cols) { 1317e2f04181SAndrew T. Barker int ierr; 1318e2f04181SAndrew T. Barker Ceed ceed = op->ceed; 1319e2f04181SAndrew T. Barker if (op->composite) 1320e2f04181SAndrew T. Barker // LCOV_EXCL_START 1321e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 1322e2f04181SAndrew T. Barker "Composite operator not supported"); 1323e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1324e2f04181SAndrew T. Barker 1325e2f04181SAndrew T. Barker CeedElemRestriction rstrin; 1326e2f04181SAndrew T. Barker ierr = CeedOperatorGetActiveElemRestriction(op, &rstrin); CeedChk(ierr); 1327e2f04181SAndrew T. Barker CeedInt nelem, elemsize, nnodes, ncomp; 1328e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetNumElements(rstrin, &nelem); CeedChk(ierr); 1329e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetElementSize(rstrin, &elemsize); CeedChk(ierr); 1330e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetLVectorSize(rstrin, &nnodes); CeedChk(ierr); 1331e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetNumComponents(rstrin, &ncomp); CeedChk(ierr); 1332e2f04181SAndrew T. Barker CeedInt layout_er[3]; 1333e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetELayout(rstrin, &layout_er); CeedChk(ierr); 1334e2f04181SAndrew T. Barker 1335e2f04181SAndrew T. Barker CeedInt local_nentries = elemsize*ncomp * elemsize*ncomp * nelem; 1336e2f04181SAndrew T. Barker 1337e2f04181SAndrew T. Barker // Determine elem_dof relation 1338e2f04181SAndrew T. Barker CeedVector index_vec; 1339e2f04181SAndrew T. Barker ierr = CeedVectorCreate(ceed, nnodes, &index_vec); CeedChk(ierr); 1340e2f04181SAndrew T. Barker CeedScalar *array; 1341e2f04181SAndrew T. Barker ierr = CeedVectorGetArray(index_vec, CEED_MEM_HOST, &array); CeedChk(ierr); 1342e2f04181SAndrew T. Barker for (CeedInt i = 0; i < nnodes; ++i) { 1343e2f04181SAndrew T. Barker array[i] = i; 1344e2f04181SAndrew T. Barker } 1345e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArray(index_vec, &array); CeedChk(ierr); 1346e2f04181SAndrew T. Barker CeedVector elem_dof; 1347e2f04181SAndrew T. Barker ierr = CeedVectorCreate(ceed, nelem * elemsize * ncomp, &elem_dof); 1348e2f04181SAndrew T. Barker CeedChk(ierr); 1349e2f04181SAndrew T. Barker ierr = CeedVectorSetValue(elem_dof, 0.0); CeedChk(ierr); 1350e2f04181SAndrew T. Barker CeedElemRestrictionApply(rstrin, CEED_NOTRANSPOSE, index_vec, 1351e2f04181SAndrew T. Barker elem_dof, CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 1352e2f04181SAndrew T. Barker const CeedScalar *elem_dof_a; 1353e2f04181SAndrew T. Barker ierr = CeedVectorGetArrayRead(elem_dof, CEED_MEM_HOST, &elem_dof_a); 1354e2f04181SAndrew T. Barker CeedChk(ierr); 1355e2f04181SAndrew T. Barker ierr = CeedVectorDestroy(&index_vec); CeedChk(ierr); 1356e2f04181SAndrew T. Barker 1357e2f04181SAndrew T. Barker // Determine i, j locations for element matrices 1358e2f04181SAndrew T. Barker CeedInt count = 0; 1359e2f04181SAndrew T. Barker for (int e = 0; e < nelem; ++e) { 1360e2f04181SAndrew T. Barker for (int compin = 0; compin < ncomp; ++compin) { 1361e2f04181SAndrew T. Barker for (int compout = 0; compout < ncomp; ++compout) { 1362e2f04181SAndrew T. Barker for (int i = 0; i < elemsize; ++i) { 1363e2f04181SAndrew T. Barker for (int j = 0; j < elemsize; ++j) { 1364e2f04181SAndrew T. Barker const CeedInt edof_index_row = (i)*layout_er[0] + 1365e2f04181SAndrew T. Barker (compout)*layout_er[1] + e*layout_er[2]; 1366e2f04181SAndrew T. Barker const CeedInt edof_index_col = (j)*layout_er[0] + 1367e2f04181SAndrew T. Barker (compin)*layout_er[1] + e*layout_er[2]; 1368e2f04181SAndrew T. Barker 1369e2f04181SAndrew T. Barker const CeedInt row = elem_dof_a[edof_index_row]; 1370e2f04181SAndrew T. Barker const CeedInt col = elem_dof_a[edof_index_col]; 1371e2f04181SAndrew T. Barker 1372e2f04181SAndrew T. Barker rows[offset + count] = row; 1373e2f04181SAndrew T. Barker cols[offset + count] = col; 1374e2f04181SAndrew T. Barker count++; 1375e2f04181SAndrew T. Barker } 1376e2f04181SAndrew T. Barker } 1377e2f04181SAndrew T. Barker } 1378e2f04181SAndrew T. Barker } 1379e2f04181SAndrew T. Barker } 1380e2f04181SAndrew T. Barker if (count != local_nentries) 1381e2f04181SAndrew T. Barker // LCOV_EXCL_START 1382e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_MAJOR, "Error computing assembled entries"); 1383e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1384e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArrayRead(elem_dof, &elem_dof_a); CeedChk(ierr); 1385e2f04181SAndrew T. Barker ierr = CeedVectorDestroy(&elem_dof); CeedChk(ierr); 1386e2f04181SAndrew T. Barker 1387e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1388e2f04181SAndrew T. Barker } 1389e2f04181SAndrew T. Barker 1390e2f04181SAndrew T. Barker /** 1391e2f04181SAndrew T. Barker @brief Assemble nonzero entries for non-composite operator 1392e2f04181SAndrew T. Barker 1393e2f04181SAndrew T. Barker Users should generally use CeedOperatorLinearAssemble() 1394e2f04181SAndrew T. Barker 1395e2f04181SAndrew T. Barker @ref Developer 1396e2f04181SAndrew T. Barker **/ 1397e2f04181SAndrew T. Barker int CeedSingleOperatorAssemble(CeedOperator op, CeedInt offset, 1398e2f04181SAndrew T. Barker CeedVector values) { 1399e2f04181SAndrew T. Barker int ierr; 1400e2f04181SAndrew T. Barker Ceed ceed = op->ceed;; 1401e2f04181SAndrew T. Barker if (op->composite) 1402e2f04181SAndrew T. Barker // LCOV_EXCL_START 1403e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 1404e2f04181SAndrew T. Barker "Composite operator not supported"); 1405e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1406e2f04181SAndrew T. Barker 1407e2f04181SAndrew T. Barker // Assemble QFunction 1408e2f04181SAndrew T. Barker CeedQFunction qf; 1409e2f04181SAndrew T. Barker ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 1410e2f04181SAndrew T. Barker CeedInt numinputfields, numoutputfields; 1411e2f04181SAndrew T. Barker ierr= CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 1412e2f04181SAndrew T. Barker CeedChk(ierr); 1413e2f04181SAndrew T. Barker CeedVector assembledqf; 1414e2f04181SAndrew T. Barker CeedElemRestriction rstr_q; 1415e2f04181SAndrew T. Barker ierr = CeedOperatorLinearAssembleQFunction( 1416e2f04181SAndrew T. Barker op, &assembledqf, &rstr_q, CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 1417e2f04181SAndrew T. Barker 1418e2f04181SAndrew T. Barker CeedInt qflength; 1419e2f04181SAndrew T. Barker ierr = CeedVectorGetLength(assembledqf, &qflength); CeedChk(ierr); 1420e2f04181SAndrew T. Barker 1421e2f04181SAndrew T. Barker CeedOperatorField *input_fields; 1422e2f04181SAndrew T. Barker CeedOperatorField *output_fields; 1423e2f04181SAndrew T. Barker ierr = CeedOperatorGetFields(op, &input_fields, &output_fields); CeedChk(ierr); 1424e2f04181SAndrew T. Barker 1425e2f04181SAndrew T. Barker // Determine active input basis 1426e2f04181SAndrew T. Barker CeedQFunctionField *qffields; 1427e2f04181SAndrew T. Barker ierr = CeedQFunctionGetFields(qf, &qffields, NULL); CeedChk(ierr); 1428e2f04181SAndrew T. Barker CeedInt numemodein = 0, dim = 1; 1429e2f04181SAndrew T. Barker CeedEvalMode *emodein = NULL; 1430e2f04181SAndrew T. Barker CeedBasis basisin = NULL; 1431e2f04181SAndrew T. Barker CeedElemRestriction rstrin = NULL; 1432e2f04181SAndrew T. Barker for (CeedInt i=0; i<numinputfields; i++) { 1433e2f04181SAndrew T. Barker CeedVector vec; 1434e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetVector(input_fields[i], &vec); CeedChk(ierr); 1435e2f04181SAndrew T. Barker if (vec == CEED_VECTOR_ACTIVE) { 1436e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetBasis(input_fields[i], &basisin); 1437e2f04181SAndrew T. Barker CeedChk(ierr); 1438e2f04181SAndrew T. Barker ierr = CeedBasisGetDimension(basisin, &dim); CeedChk(ierr); 1439e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetElemRestriction(input_fields[i], &rstrin); 1440e2f04181SAndrew T. Barker CeedChk(ierr); 1441e2f04181SAndrew T. Barker CeedEvalMode emode; 1442e2f04181SAndrew T. Barker ierr = CeedQFunctionFieldGetEvalMode(qffields[i], &emode); 1443e2f04181SAndrew T. Barker CeedChk(ierr); 1444e2f04181SAndrew T. Barker switch (emode) { 1445e2f04181SAndrew T. Barker case CEED_EVAL_NONE: 1446e2f04181SAndrew T. Barker case CEED_EVAL_INTERP: 1447e2f04181SAndrew T. Barker ierr = CeedRealloc(numemodein + 1, &emodein); CeedChk(ierr); 1448e2f04181SAndrew T. Barker emodein[numemodein] = emode; 1449e2f04181SAndrew T. Barker numemodein += 1; 1450e2f04181SAndrew T. Barker break; 1451e2f04181SAndrew T. Barker case CEED_EVAL_GRAD: 1452e2f04181SAndrew T. Barker ierr = CeedRealloc(numemodein + dim, &emodein); CeedChk(ierr); 1453e2f04181SAndrew T. Barker for (CeedInt d=0; d<dim; d++) { 1454e2f04181SAndrew T. Barker emodein[numemodein+d] = emode; 1455e2f04181SAndrew T. Barker } 1456e2f04181SAndrew T. Barker numemodein += dim; 1457e2f04181SAndrew T. Barker break; 1458e2f04181SAndrew T. Barker case CEED_EVAL_WEIGHT: 1459e2f04181SAndrew T. Barker case CEED_EVAL_DIV: 1460e2f04181SAndrew T. Barker case CEED_EVAL_CURL: 1461e2f04181SAndrew T. Barker break; // Caught by QF Assembly 1462e2f04181SAndrew T. Barker } 1463e2f04181SAndrew T. Barker } 1464e2f04181SAndrew T. Barker } 1465e2f04181SAndrew T. Barker 1466e2f04181SAndrew T. Barker // Determine active output basis 1467e2f04181SAndrew T. Barker ierr = CeedQFunctionGetFields(qf, NULL, &qffields); CeedChk(ierr); 1468e2f04181SAndrew T. Barker CeedInt numemodeout = 0; 1469e2f04181SAndrew T. Barker CeedEvalMode *emodeout = NULL; 1470e2f04181SAndrew T. Barker CeedBasis basisout = NULL; 1471e2f04181SAndrew T. Barker CeedElemRestriction rstrout = NULL; 1472e2f04181SAndrew T. Barker for (CeedInt i=0; i<numoutputfields; i++) { 1473e2f04181SAndrew T. Barker CeedVector vec; 1474e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetVector(output_fields[i], &vec); CeedChk(ierr); 1475e2f04181SAndrew T. Barker if (vec == CEED_VECTOR_ACTIVE) { 1476e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetBasis(output_fields[i], &basisout); 1477e2f04181SAndrew T. Barker CeedChk(ierr); 1478e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetElemRestriction(output_fields[i], &rstrout); 1479e2f04181SAndrew T. Barker CeedChk(ierr); 1480e2f04181SAndrew T. Barker CeedEvalMode emode; 1481e2f04181SAndrew T. Barker ierr = CeedQFunctionFieldGetEvalMode(qffields[i], &emode); 1482e2f04181SAndrew T. Barker CeedChk(ierr); 1483e2f04181SAndrew T. Barker switch (emode) { 1484e2f04181SAndrew T. Barker case CEED_EVAL_NONE: 1485e2f04181SAndrew T. Barker case CEED_EVAL_INTERP: 1486e2f04181SAndrew T. Barker ierr = CeedRealloc(numemodeout + 1, &emodeout); CeedChk(ierr); 1487e2f04181SAndrew T. Barker emodeout[numemodeout] = emode; 1488e2f04181SAndrew T. Barker numemodeout += 1; 1489e2f04181SAndrew T. Barker break; 1490e2f04181SAndrew T. Barker case CEED_EVAL_GRAD: 1491e2f04181SAndrew T. Barker ierr = CeedRealloc(numemodeout + dim, &emodeout); CeedChk(ierr); 1492e2f04181SAndrew T. Barker for (CeedInt d=0; d<dim; d++) { 1493e2f04181SAndrew T. Barker emodeout[numemodeout+d] = emode; 1494e2f04181SAndrew T. Barker } 1495e2f04181SAndrew T. Barker numemodeout += dim; 1496e2f04181SAndrew T. Barker break; 1497e2f04181SAndrew T. Barker case CEED_EVAL_WEIGHT: 1498e2f04181SAndrew T. Barker case CEED_EVAL_DIV: 1499e2f04181SAndrew T. Barker case CEED_EVAL_CURL: 1500e2f04181SAndrew T. Barker break; // Caught by QF Assembly 1501e2f04181SAndrew T. Barker } 1502e2f04181SAndrew T. Barker } 1503e2f04181SAndrew T. Barker } 1504e2f04181SAndrew T. Barker 1505e2f04181SAndrew T. Barker CeedInt nelem, elemsize, nqpts, ncomp; 1506e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetNumElements(rstrin, &nelem); CeedChk(ierr); 1507e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetElementSize(rstrin, &elemsize); CeedChk(ierr); 1508e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetNumComponents(rstrin, &ncomp); CeedChk(ierr); 1509e2f04181SAndrew T. Barker ierr = CeedBasisGetNumQuadraturePoints(basisin, &nqpts); CeedChk(ierr); 1510e2f04181SAndrew T. Barker 1511e2f04181SAndrew T. Barker CeedInt local_nentries = elemsize*ncomp * elemsize*ncomp * nelem; 1512e2f04181SAndrew T. Barker 1513e2f04181SAndrew T. Barker // loop over elements and put in data structure 1514e2f04181SAndrew T. Barker const CeedScalar *interpin, *gradin; 1515e2f04181SAndrew T. Barker ierr = CeedBasisGetInterp(basisin, &interpin); CeedChk(ierr); 1516e2f04181SAndrew T. Barker ierr = CeedBasisGetGrad(basisin, &gradin); CeedChk(ierr); 1517e2f04181SAndrew T. Barker 1518e2f04181SAndrew T. Barker const CeedScalar *assembledqfarray; 1519e2f04181SAndrew T. Barker ierr = CeedVectorGetArrayRead(assembledqf, CEED_MEM_HOST, &assembledqfarray); 1520e2f04181SAndrew T. Barker CeedChk(ierr); 1521e2f04181SAndrew T. Barker 1522e2f04181SAndrew T. Barker CeedInt layout_qf[3]; 1523e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetELayout(rstr_q, &layout_qf); CeedChk(ierr); 1524e2f04181SAndrew T. Barker ierr = CeedElemRestrictionDestroy(&rstr_q); CeedChk(ierr); 1525e2f04181SAndrew T. Barker 1526e2f04181SAndrew T. Barker // we store Bmat_in, Bmat_out, BTD, elem_mat in row-major order 1527e2f04181SAndrew T. Barker CeedScalar Bmat_in[(nqpts * numemodein) * elemsize]; 1528e2f04181SAndrew T. Barker CeedScalar Bmat_out[(nqpts * numemodeout) * elemsize]; 1529e2f04181SAndrew T. Barker CeedScalar Dmat[numemodeout * numemodein * nqpts]; // logically 3-tensor 1530e2f04181SAndrew T. Barker CeedScalar BTD[elemsize * nqpts*numemodein]; 1531e2f04181SAndrew T. Barker CeedScalar elem_mat[elemsize * elemsize]; 1532e2f04181SAndrew T. Barker int count = 0; 1533e2f04181SAndrew T. Barker CeedScalar *vals; 1534e2f04181SAndrew T. Barker ierr = CeedVectorGetArray(values, CEED_MEM_HOST, &vals); CeedChk(ierr); 1535e2f04181SAndrew T. Barker for (int e = 0; e < nelem; ++e) { 1536e2f04181SAndrew T. Barker for (int compin = 0; compin < ncomp; ++compin) { 1537e2f04181SAndrew T. Barker for (int compout = 0; compout < ncomp; ++compout) { 1538e2f04181SAndrew T. Barker for (int ell = 0; ell < (nqpts * numemodein) * elemsize; ++ell) { 1539e2f04181SAndrew T. Barker Bmat_in[ell] = 0.0; 1540e2f04181SAndrew T. Barker } 1541e2f04181SAndrew T. Barker for (int ell = 0; ell < (nqpts * numemodeout) * elemsize; ++ell) { 1542e2f04181SAndrew T. Barker Bmat_out[ell] = 0.0; 1543e2f04181SAndrew T. Barker } 1544e2f04181SAndrew T. Barker // Store block-diagonal D matrix as collection of small dense blocks 1545e2f04181SAndrew T. Barker for (int ell = 0; ell < numemodein*numemodeout*nqpts; ++ell) { 1546e2f04181SAndrew T. Barker Dmat[ell] = 0.0; 1547e2f04181SAndrew T. Barker } 1548e2f04181SAndrew T. Barker // form element matrix itself (for each block component) 1549e2f04181SAndrew T. Barker for (int ell = 0; ell < elemsize*elemsize; ++ell) { 1550e2f04181SAndrew T. Barker elem_mat[ell] = 0.0; 1551e2f04181SAndrew T. Barker } 1552e2f04181SAndrew T. Barker for (int q = 0; q < nqpts; ++q) { 1553e2f04181SAndrew T. Barker for (int n = 0; n < elemsize; ++n) { 1554e2f04181SAndrew T. Barker CeedInt din = -1; 1555e2f04181SAndrew T. Barker for (int ein = 0; ein < numemodein; ++ein) { 1556e2f04181SAndrew T. Barker const int qq = numemodein*q; 1557e2f04181SAndrew T. Barker if (emodein[ein] == CEED_EVAL_INTERP) { 1558e2f04181SAndrew T. Barker Bmat_in[(qq+ein)*elemsize + n] += interpin[q * elemsize + n]; 1559e2f04181SAndrew T. Barker } else if (emodein[ein] == CEED_EVAL_GRAD) { 1560e2f04181SAndrew T. Barker din += 1; 1561e2f04181SAndrew T. Barker Bmat_in[(qq+ein)*elemsize + n] += 1562e2f04181SAndrew T. Barker gradin[(din*nqpts+q) * elemsize + n]; 1563e2f04181SAndrew T. Barker } else { 1564e2f04181SAndrew T. Barker // LCOV_EXCL_START 1565e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Not implemented!"); 1566e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1567e2f04181SAndrew T. Barker } 1568e2f04181SAndrew T. Barker } 1569e2f04181SAndrew T. Barker CeedInt dout = -1; 1570e2f04181SAndrew T. Barker for (int eout = 0; eout < numemodeout; ++eout) { 1571e2f04181SAndrew T. Barker const int qq = numemodeout*q; 1572e2f04181SAndrew T. Barker if (emodeout[eout] == CEED_EVAL_INTERP) { 1573e2f04181SAndrew T. Barker Bmat_out[(qq+eout)*elemsize + n] += interpin[q * elemsize + n]; 1574e2f04181SAndrew T. Barker } else if (emodeout[eout] == CEED_EVAL_GRAD) { 1575e2f04181SAndrew T. Barker dout += 1; 1576e2f04181SAndrew T. Barker Bmat_out[(qq+eout)*elemsize + n] += 1577e2f04181SAndrew T. Barker gradin[(dout*nqpts+q) * elemsize + n]; 1578e2f04181SAndrew T. Barker } else { 1579e2f04181SAndrew T. Barker // LCOV_EXCL_START 1580e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Not implemented!"); 1581e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1582e2f04181SAndrew T. Barker } 1583e2f04181SAndrew T. Barker } 1584e2f04181SAndrew T. Barker } 1585e2f04181SAndrew T. Barker for (int ei = 0; ei < numemodeout; ++ei) { 1586e2f04181SAndrew T. Barker for (int ej = 0; ej < numemodein; ++ej) { 1587e2f04181SAndrew T. Barker const int emode_index = ((ei*ncomp+compin)*numemodein+ej)*ncomp+compout; 1588e2f04181SAndrew T. Barker const int index = q*layout_qf[0] + emode_index*layout_qf[1] + e*layout_qf[2]; 1589e2f04181SAndrew T. Barker Dmat[(ei*numemodein+ej)*nqpts + q] += assembledqfarray[index]; 1590e2f04181SAndrew T. Barker } 1591e2f04181SAndrew T. Barker } 1592e2f04181SAndrew T. Barker } 1593e2f04181SAndrew T. Barker // Compute B^T*D 1594e2f04181SAndrew T. Barker for (int ell = 0; ell < elemsize*nqpts*numemodein; ++ell) { 1595e2f04181SAndrew T. Barker BTD[ell] = 0.0; 1596e2f04181SAndrew T. Barker } 1597e2f04181SAndrew T. Barker for (int j = 0; j<elemsize; ++j) { 1598e2f04181SAndrew T. Barker for (int q = 0; q<nqpts; ++q) { 1599e2f04181SAndrew T. Barker int qq = numemodeout*q; 1600e2f04181SAndrew T. Barker for (int ei = 0; ei < numemodein; ++ei) { 1601e2f04181SAndrew T. Barker for (int ej = 0; ej < numemodeout; ++ej) { 1602e2f04181SAndrew T. Barker BTD[j*(nqpts*numemodein) + (qq+ei)] += 1603e2f04181SAndrew T. Barker Bmat_out[(qq+ej)*elemsize + j] * Dmat[(ei*numemodein+ej)*nqpts + q]; 1604e2f04181SAndrew T. Barker } 1605e2f04181SAndrew T. Barker } 1606e2f04181SAndrew T. Barker } 1607e2f04181SAndrew T. Barker } 1608e2f04181SAndrew T. Barker 1609e2f04181SAndrew T. Barker ierr = CeedMatrixMultiply(ceed, BTD, Bmat_in, elem_mat, elemsize, 1610e2f04181SAndrew T. Barker elemsize, nqpts*numemodein); CeedChk(ierr); 1611e2f04181SAndrew T. Barker 1612e2f04181SAndrew T. Barker // put element matrix in coordinate data structure 1613e2f04181SAndrew T. Barker for (int i = 0; i < elemsize; ++i) { 1614e2f04181SAndrew T. Barker for (int j = 0; j < elemsize; ++j) { 1615e2f04181SAndrew T. Barker vals[offset + count] = elem_mat[i*elemsize + j]; 1616e2f04181SAndrew T. Barker count++; 1617e2f04181SAndrew T. Barker } 1618e2f04181SAndrew T. Barker } 1619e2f04181SAndrew T. Barker } 1620e2f04181SAndrew T. Barker } 1621e2f04181SAndrew T. Barker } 1622e2f04181SAndrew T. Barker if (count != local_nentries) 1623e2f04181SAndrew T. Barker // LCOV_EXCL_START 1624e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_MAJOR, "Error computing entries"); 1625e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1626e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArray(values, &vals); CeedChk(ierr); 1627e2f04181SAndrew T. Barker 1628e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArrayRead(assembledqf, &assembledqfarray); 1629e2f04181SAndrew T. Barker CeedChk(ierr); 1630e2f04181SAndrew T. Barker ierr = CeedVectorDestroy(&assembledqf); CeedChk(ierr); 1631e2f04181SAndrew T. Barker ierr = CeedFree(&emodein); CeedChk(ierr); 1632e2f04181SAndrew T. Barker ierr = CeedFree(&emodeout); CeedChk(ierr); 1633e2f04181SAndrew T. Barker 1634e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1635e2f04181SAndrew T. Barker } 1636e2f04181SAndrew T. Barker 1637e2f04181SAndrew T. Barker /** 1638e2f04181SAndrew T. Barker @ref Utility 1639e2f04181SAndrew T. Barker **/ 1640e2f04181SAndrew T. Barker int CeedSingleOperatorAssemblyCountEntries(CeedOperator op, CeedInt *nentries) { 1641e2f04181SAndrew T. Barker int ierr; 1642e2f04181SAndrew T. Barker CeedElemRestriction rstr; 1643e2f04181SAndrew T. Barker CeedInt nelem, elemsize, ncomp; 1644e2f04181SAndrew T. Barker 1645e2f04181SAndrew T. Barker if (op->composite) 1646e2f04181SAndrew T. Barker // LCOV_EXCL_START 1647e2f04181SAndrew T. Barker return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 1648e2f04181SAndrew T. Barker "Composite operator not supported"); 1649e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1650e2f04181SAndrew T. Barker ierr = CeedOperatorGetActiveElemRestriction(op, &rstr); CeedChk(ierr); 1651e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetNumElements(rstr, &nelem); CeedChk(ierr); 1652e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetElementSize(rstr, &elemsize); CeedChk(ierr); 1653e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetNumComponents(rstr, &ncomp); CeedChk(ierr); 1654e2f04181SAndrew T. Barker *nentries = elemsize*ncomp * elemsize*ncomp * nelem; 1655e2f04181SAndrew T. Barker 1656e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1657e2f04181SAndrew T. Barker } 1658e2f04181SAndrew T. Barker 1659e2f04181SAndrew T. Barker /** 1660e2f04181SAndrew T. Barker @brief Fully assemble the nonzero pattern of a linear operator. 1661e2f04181SAndrew T. Barker 1662e2f04181SAndrew T. Barker Expected to be used in conjunction with CeedOperatorLinearAssemble() 1663e2f04181SAndrew T. Barker 1664e2f04181SAndrew T. Barker The assembly routines use coordinate format, with nentries tuples of the 1665e2f04181SAndrew T. Barker form (i, j, value) which indicate that value should be added to the matrix 1666e2f04181SAndrew T. Barker in entry (i, j). Note that the (i, j) pairs are not unique and may repeat. 1667e2f04181SAndrew T. Barker This function returns the number of entries and their (i, j) locations, 1668e2f04181SAndrew T. Barker while CeedOperatorLinearAssemble() provides the values in the same 1669e2f04181SAndrew T. Barker ordering. 1670e2f04181SAndrew T. Barker 1671e2f04181SAndrew T. Barker This will generally be slow unless your operator is low-order. 1672e2f04181SAndrew T. Barker 1673e2f04181SAndrew T. Barker @param[in] op CeedOperator to assemble 1674e2f04181SAndrew T. Barker @param[out] nentries Number of entries in coordinate nonzero pattern. 1675e2f04181SAndrew T. Barker @param[out] rows Row number for each entry. 1676e2f04181SAndrew T. Barker @param[out] cols Column number for each entry. 1677e2f04181SAndrew T. Barker 1678e2f04181SAndrew T. Barker @ref User 1679e2f04181SAndrew T. Barker **/ 1680e2f04181SAndrew T. Barker int CeedOperatorLinearAssembleSymbolic(CeedOperator op, 1681e2f04181SAndrew T. Barker CeedInt *nentries, CeedInt **rows, CeedInt **cols) { 1682e2f04181SAndrew T. Barker int ierr; 1683e2f04181SAndrew T. Barker CeedInt numsub, single_entries; 1684e2f04181SAndrew T. Barker CeedOperator *suboperators; 1685e2f04181SAndrew T. Barker bool isComposite; 1686e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1687e2f04181SAndrew T. Barker 1688e2f04181SAndrew T. Barker // Use backend version, if available 1689e2f04181SAndrew T. Barker if (op->LinearAssembleSymbolic) { 1690e2f04181SAndrew T. Barker return op->LinearAssembleSymbolic(op, nentries, rows, cols); 1691e2f04181SAndrew T. Barker } else { 1692e2f04181SAndrew T. Barker // Check for valid fallback resource 1693e2f04181SAndrew T. Barker const char *resource, *fallbackresource; 1694e2f04181SAndrew T. Barker ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr); 1695e2f04181SAndrew T. Barker ierr = CeedGetOperatorFallbackResource(op->ceed, &fallbackresource); 1696e2f04181SAndrew T. Barker if (strcmp(fallbackresource, "") && strcmp(resource, fallbackresource)) { 1697e2f04181SAndrew T. Barker // Fallback to reference Ceed 1698e2f04181SAndrew T. Barker if (!op->opfallback) { 1699e2f04181SAndrew T. Barker ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1700e2f04181SAndrew T. Barker } 1701e2f04181SAndrew T. Barker // Assemble 1702e2f04181SAndrew T. Barker return CeedOperatorLinearAssembleSymbolic(op->opfallback, nentries, rows, cols); 1703e2f04181SAndrew T. Barker } 1704e2f04181SAndrew T. Barker } 1705e2f04181SAndrew T. Barker 1706e2f04181SAndrew T. Barker // if neither backend nor fallback resource provides 1707e2f04181SAndrew T. Barker // LinearAssembleSymbolic, continue with interface-level implementation 1708e2f04181SAndrew T. Barker 1709e2f04181SAndrew T. Barker // count entries and allocate rows, cols arrays 1710e2f04181SAndrew T. Barker ierr = CeedOperatorIsComposite(op, &isComposite); CeedChk(ierr); 1711e2f04181SAndrew T. Barker *nentries = 0; 1712e2f04181SAndrew T. Barker if (isComposite) { 1713e2f04181SAndrew T. Barker ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 1714e2f04181SAndrew T. Barker ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 1715e2f04181SAndrew T. Barker for (int k = 0; k < numsub; ++k) { 1716e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemblyCountEntries(suboperators[k], 1717e2f04181SAndrew T. Barker &single_entries); CeedChk(ierr); 1718e2f04181SAndrew T. Barker *nentries += single_entries; 1719e2f04181SAndrew T. Barker } 1720e2f04181SAndrew T. Barker } else { 1721e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemblyCountEntries(op, 1722e2f04181SAndrew T. Barker &single_entries); CeedChk(ierr); 1723e2f04181SAndrew T. Barker *nentries += single_entries; 1724e2f04181SAndrew T. Barker } 1725e2f04181SAndrew T. Barker ierr = CeedCalloc(*nentries, rows); CeedChk(ierr); 1726e2f04181SAndrew T. Barker ierr = CeedCalloc(*nentries, cols); CeedChk(ierr); 1727e2f04181SAndrew T. Barker 1728e2f04181SAndrew T. Barker // assemble nonzero locations 1729e2f04181SAndrew T. Barker CeedInt offset = 0; 1730e2f04181SAndrew T. Barker if (isComposite) { 1731e2f04181SAndrew T. Barker ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 1732e2f04181SAndrew T. Barker ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 1733e2f04181SAndrew T. Barker for (int k = 0; k < numsub; ++k) { 1734e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssembleSymbolic(suboperators[k], offset, *rows, 1735e2f04181SAndrew T. Barker *cols); CeedChk(ierr); 1736e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemblyCountEntries(suboperators[k], &single_entries); 1737e2f04181SAndrew T. Barker CeedChk(ierr); 1738e2f04181SAndrew T. Barker offset += single_entries; 1739e2f04181SAndrew T. Barker } 1740e2f04181SAndrew T. Barker } else { 1741e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssembleSymbolic(op, offset, *rows, *cols); 1742e2f04181SAndrew T. Barker CeedChk(ierr); 1743e2f04181SAndrew T. Barker } 1744e2f04181SAndrew T. Barker 1745e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1746e2f04181SAndrew T. Barker } 1747e2f04181SAndrew T. Barker 1748e2f04181SAndrew T. Barker /** 1749e2f04181SAndrew T. Barker @brief Fully assemble the nonzero entries of a linear operator. 1750e2f04181SAndrew T. Barker 1751e2f04181SAndrew T. Barker Expected to be used in conjunction with CeedOperatorLinearAssembleSymbolic() 1752e2f04181SAndrew T. Barker 1753e2f04181SAndrew T. Barker The assembly routines use coordinate format, with nentries tuples of the 1754e2f04181SAndrew T. Barker form (i, j, value) which indicate that value should be added to the matrix 1755e2f04181SAndrew T. Barker in entry (i, j). Note that the (i, j) pairs are not unique and may repeat. 1756e2f04181SAndrew T. Barker This function returns the values of the nonzero entries to be added, their 1757e2f04181SAndrew T. Barker (i, j) locations are provided by CeedOperatorLinearAssembleSymbolic() 1758e2f04181SAndrew T. Barker 1759e2f04181SAndrew T. Barker This will generally be slow unless your operator is low-order. 1760e2f04181SAndrew T. Barker 1761e2f04181SAndrew T. Barker @param[in] op CeedOperator to assemble 1762e2f04181SAndrew T. Barker @param[out] values Values to assemble into matrix 1763e2f04181SAndrew T. Barker 1764e2f04181SAndrew T. Barker @ref User 1765e2f04181SAndrew T. Barker **/ 1766e2f04181SAndrew T. Barker int CeedOperatorLinearAssemble(CeedOperator op, CeedVector values) { 1767e2f04181SAndrew T. Barker int ierr; 1768e2f04181SAndrew T. Barker CeedInt numsub, single_entries; 1769e2f04181SAndrew T. Barker CeedOperator *suboperators; 1770e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1771e2f04181SAndrew T. Barker 1772e2f04181SAndrew T. Barker // Use backend version, if available 1773e2f04181SAndrew T. Barker if (op->LinearAssemble) { 1774e2f04181SAndrew T. Barker return op->LinearAssemble(op, values); 1775e2f04181SAndrew T. Barker } else { 1776e2f04181SAndrew T. Barker // Check for valid fallback resource 1777e2f04181SAndrew T. Barker const char *resource, *fallbackresource; 1778e2f04181SAndrew T. Barker ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr); 1779e2f04181SAndrew T. Barker ierr = CeedGetOperatorFallbackResource(op->ceed, &fallbackresource); 1780e2f04181SAndrew T. Barker if (strcmp(fallbackresource, "") && strcmp(resource, fallbackresource)) { 1781e2f04181SAndrew T. Barker // Fallback to reference Ceed 1782e2f04181SAndrew T. Barker if (!op->opfallback) { 1783e2f04181SAndrew T. Barker ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1784e2f04181SAndrew T. Barker } 1785e2f04181SAndrew T. Barker // Assemble 1786e2f04181SAndrew T. Barker return CeedOperatorLinearAssemble(op->opfallback, values); 1787e2f04181SAndrew T. Barker } 1788e2f04181SAndrew T. Barker } 1789e2f04181SAndrew T. Barker 1790e2f04181SAndrew T. Barker // if neither backend nor fallback resource provides 1791e2f04181SAndrew T. Barker // LinearAssemble, continue with interface-level implementation 1792e2f04181SAndrew T. Barker 1793e2f04181SAndrew T. Barker bool isComposite; 1794e2f04181SAndrew T. Barker ierr = CeedOperatorIsComposite(op, &isComposite); CeedChk(ierr); 1795e2f04181SAndrew T. Barker 1796e2f04181SAndrew T. Barker CeedInt offset = 0; 1797e2f04181SAndrew T. Barker if (isComposite) { 1798e2f04181SAndrew T. Barker ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 1799e2f04181SAndrew T. Barker ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 1800e2f04181SAndrew T. Barker for (int k = 0; k < numsub; ++k) { 1801e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemble(suboperators[k], offset, values); 1802e2f04181SAndrew T. Barker CeedChk(ierr); 1803e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemblyCountEntries(suboperators[k], &single_entries); 1804e2f04181SAndrew T. Barker CeedChk(ierr); 1805e2f04181SAndrew T. Barker offset += single_entries; 1806e2f04181SAndrew T. Barker } 1807e2f04181SAndrew T. Barker } else { 1808e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemble(op, offset, values); CeedChk(ierr); 1809e2f04181SAndrew T. Barker } 1810e2f04181SAndrew T. Barker 1811e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1812d965c7a7SJeremy L Thompson } 1813d965c7a7SJeremy L Thompson 1814d965c7a7SJeremy L Thompson /** 1815d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1816d99fa3c5SJeremy L Thompson for a CeedOperator, creating the prolongation basis from the 1817d99fa3c5SJeremy L Thompson fine and coarse grid interpolation 1818d99fa3c5SJeremy L Thompson 1819d99fa3c5SJeremy L Thompson @param[in] opFine Fine grid operator 1820d99fa3c5SJeremy L Thompson @param[in] PMultFine L-vector multiplicity in parallel gather/scatter 1821d99fa3c5SJeremy L Thompson @param[in] rstrCoarse Coarse grid restriction 1822d99fa3c5SJeremy L Thompson @param[in] basisCoarse Coarse grid active vector basis 1823d99fa3c5SJeremy L Thompson @param[out] opCoarse Coarse grid operator 1824d99fa3c5SJeremy L Thompson @param[out] opProlong Coarse to fine operator 1825d99fa3c5SJeremy L Thompson @param[out] opRestrict Fine to coarse operator 1826d99fa3c5SJeremy L Thompson 1827d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1828d99fa3c5SJeremy L Thompson 1829d99fa3c5SJeremy L Thompson @ref User 1830d99fa3c5SJeremy L Thompson **/ 1831d99fa3c5SJeremy L Thompson int CeedOperatorMultigridLevelCreate(CeedOperator opFine, CeedVector PMultFine, 1832d99fa3c5SJeremy L Thompson CeedElemRestriction rstrCoarse, CeedBasis basisCoarse, 1833d99fa3c5SJeremy L Thompson CeedOperator *opCoarse, CeedOperator *opProlong, CeedOperator *opRestrict) { 1834d99fa3c5SJeremy L Thompson int ierr; 1835d99fa3c5SJeremy L Thompson Ceed ceed; 1836d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(opFine, &ceed); CeedChk(ierr); 1837d99fa3c5SJeremy L Thompson 1838d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 1839d99fa3c5SJeremy L Thompson CeedBasis basisFine; 1840d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetActiveBasis(opFine, &basisFine); CeedChk(ierr); 1841d99fa3c5SJeremy L Thompson CeedInt Qf, Qc; 1842d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisFine, &Qf); CeedChk(ierr); 1843d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisCoarse, &Qc); CeedChk(ierr); 1844d99fa3c5SJeremy L Thompson if (Qf != Qc) 1845d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1846e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 1847e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 1848d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1849d99fa3c5SJeremy L Thompson 1850d99fa3c5SJeremy L Thompson // Coarse to fine basis 1851d99fa3c5SJeremy L Thompson CeedInt Pf, Pc, Q = Qf; 1852d99fa3c5SJeremy L Thompson bool isTensorF, isTensorC; 1853d99fa3c5SJeremy L Thompson ierr = CeedBasisIsTensor(basisFine, &isTensorF); CeedChk(ierr); 1854d99fa3c5SJeremy L Thompson ierr = CeedBasisIsTensor(basisCoarse, &isTensorC); CeedChk(ierr); 1855d99fa3c5SJeremy L Thompson CeedScalar *interpC, *interpF, *interpCtoF, *tau; 1856d99fa3c5SJeremy L Thompson if (isTensorF && isTensorC) { 1857d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes1D(basisFine, &Pf); CeedChk(ierr); 1858d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes1D(basisCoarse, &Pc); CeedChk(ierr); 1859d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints1D(basisCoarse, &Q); CeedChk(ierr); 1860d99fa3c5SJeremy L Thompson } else if (!isTensorF && !isTensorC) { 1861d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes(basisFine, &Pf); CeedChk(ierr); 1862d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes(basisCoarse, &Pc); CeedChk(ierr); 1863d99fa3c5SJeremy L Thompson } else { 1864d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1865e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 1866e15f9bd0SJeremy L Thompson "Bases must both be tensor or non-tensor"); 1867d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1868d99fa3c5SJeremy L Thompson } 1869d99fa3c5SJeremy L Thompson 1870d99fa3c5SJeremy L Thompson ierr = CeedMalloc(Q*Pf, &interpF); CeedChk(ierr); 1871d99fa3c5SJeremy L Thompson ierr = CeedMalloc(Q*Pc, &interpC); CeedChk(ierr); 1872d99fa3c5SJeremy L Thompson ierr = CeedCalloc(Pc*Pf, &interpCtoF); CeedChk(ierr); 1873d99fa3c5SJeremy L Thompson ierr = CeedMalloc(Q, &tau); CeedChk(ierr); 1874d99fa3c5SJeremy L Thompson if (isTensorF) { 1875d99fa3c5SJeremy L Thompson memcpy(interpF, basisFine->interp1d, Q*Pf*sizeof basisFine->interp1d[0]); 1876d99fa3c5SJeremy L Thompson memcpy(interpC, basisCoarse->interp1d, Q*Pc*sizeof basisCoarse->interp1d[0]); 1877d99fa3c5SJeremy L Thompson } else { 1878d99fa3c5SJeremy L Thompson memcpy(interpF, basisFine->interp, Q*Pf*sizeof basisFine->interp[0]); 1879d99fa3c5SJeremy L Thompson memcpy(interpC, basisCoarse->interp, Q*Pc*sizeof basisCoarse->interp[0]); 1880d99fa3c5SJeremy L Thompson } 1881d99fa3c5SJeremy L Thompson 1882d99fa3c5SJeremy L Thompson // -- QR Factorization, interpF = Q R 1883d99fa3c5SJeremy L Thompson ierr = CeedQRFactorization(ceed, interpF, tau, Q, Pf); CeedChk(ierr); 1884d99fa3c5SJeremy L Thompson 1885d99fa3c5SJeremy L Thompson // -- Apply Qtranspose, interpC = Qtranspose interpC 1886d99fa3c5SJeremy L Thompson CeedHouseholderApplyQ(interpC, interpF, tau, CEED_TRANSPOSE, 1887d99fa3c5SJeremy L Thompson Q, Pc, Pf, Pc, 1); 1888d99fa3c5SJeremy L Thompson 1889d99fa3c5SJeremy L Thompson // -- Apply Rinv, interpCtoF = Rinv interpC 1890d99fa3c5SJeremy L Thompson for (CeedInt j=0; j<Pc; j++) { // Column j 1891d99fa3c5SJeremy L Thompson interpCtoF[j+Pc*(Pf-1)] = interpC[j+Pc*(Pf-1)]/interpF[Pf*Pf-1]; 1892d99fa3c5SJeremy L Thompson for (CeedInt i=Pf-2; i>=0; i--) { // Row i 1893d99fa3c5SJeremy L Thompson interpCtoF[j+Pc*i] = interpC[j+Pc*i]; 1894d99fa3c5SJeremy L Thompson for (CeedInt k=i+1; k<Pf; k++) 1895d99fa3c5SJeremy L Thompson interpCtoF[j+Pc*i] -= interpF[k+Pf*i]*interpCtoF[j+Pc*k]; 1896d99fa3c5SJeremy L Thompson interpCtoF[j+Pc*i] /= interpF[i+Pf*i]; 1897d99fa3c5SJeremy L Thompson } 1898d99fa3c5SJeremy L Thompson } 1899d99fa3c5SJeremy L Thompson ierr = CeedFree(&tau); CeedChk(ierr); 1900d99fa3c5SJeremy L Thompson ierr = CeedFree(&interpC); CeedChk(ierr); 1901d99fa3c5SJeremy L Thompson ierr = CeedFree(&interpF); CeedChk(ierr); 1902d99fa3c5SJeremy L Thompson 1903e15f9bd0SJeremy L Thompson // Complete with interpCtoF versions of code 1904d99fa3c5SJeremy L Thompson if (isTensorF) { 1905d99fa3c5SJeremy L Thompson ierr = CeedOperatorMultigridLevelCreateTensorH1(opFine, PMultFine, 1906d99fa3c5SJeremy L Thompson rstrCoarse, basisCoarse, interpCtoF, opCoarse, opProlong, opRestrict); 1907d99fa3c5SJeremy L Thompson CeedChk(ierr); 1908d99fa3c5SJeremy L Thompson } else { 1909d99fa3c5SJeremy L Thompson ierr = CeedOperatorMultigridLevelCreateH1(opFine, PMultFine, 1910d99fa3c5SJeremy L Thompson rstrCoarse, basisCoarse, interpCtoF, opCoarse, opProlong, opRestrict); 1911d99fa3c5SJeremy L Thompson CeedChk(ierr); 1912d99fa3c5SJeremy L Thompson } 1913d99fa3c5SJeremy L Thompson 1914d99fa3c5SJeremy L Thompson // Cleanup 1915d99fa3c5SJeremy L Thompson ierr = CeedFree(&interpCtoF); CeedChk(ierr); 1916e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1917d99fa3c5SJeremy L Thompson } 1918d99fa3c5SJeremy L Thompson 1919d99fa3c5SJeremy L Thompson /** 1920d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1921d99fa3c5SJeremy L Thompson for a CeedOperator with a tensor basis for the active basis 1922d99fa3c5SJeremy L Thompson 1923d99fa3c5SJeremy L Thompson @param[in] opFine Fine grid operator 1924d99fa3c5SJeremy L Thompson @param[in] PMultFine L-vector multiplicity in parallel gather/scatter 1925d99fa3c5SJeremy L Thompson @param[in] rstrCoarse Coarse grid restriction 1926d99fa3c5SJeremy L Thompson @param[in] basisCoarse Coarse grid active vector basis 1927d99fa3c5SJeremy L Thompson @param[in] interpCtoF Matrix for coarse to fine interpolation 1928d99fa3c5SJeremy L Thompson @param[out] opCoarse Coarse grid operator 1929d99fa3c5SJeremy L Thompson @param[out] opProlong Coarse to fine operator 1930d99fa3c5SJeremy L Thompson @param[out] opRestrict Fine to coarse operator 1931d99fa3c5SJeremy L Thompson 1932d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1933d99fa3c5SJeremy L Thompson 1934d99fa3c5SJeremy L Thompson @ref User 1935d99fa3c5SJeremy L Thompson **/ 1936d99fa3c5SJeremy L Thompson int CeedOperatorMultigridLevelCreateTensorH1(CeedOperator opFine, 1937d99fa3c5SJeremy L Thompson CeedVector PMultFine, CeedElemRestriction rstrCoarse, CeedBasis basisCoarse, 1938d99fa3c5SJeremy L Thompson const CeedScalar *interpCtoF, CeedOperator *opCoarse, 1939d99fa3c5SJeremy L Thompson CeedOperator *opProlong, CeedOperator *opRestrict) { 1940d99fa3c5SJeremy L Thompson int ierr; 1941d99fa3c5SJeremy L Thompson Ceed ceed; 1942d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(opFine, &ceed); CeedChk(ierr); 1943d99fa3c5SJeremy L Thompson 1944d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 1945d99fa3c5SJeremy L Thompson CeedBasis basisFine; 1946d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetActiveBasis(opFine, &basisFine); CeedChk(ierr); 1947d99fa3c5SJeremy L Thompson CeedInt Qf, Qc; 1948d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisFine, &Qf); CeedChk(ierr); 1949d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisCoarse, &Qc); CeedChk(ierr); 1950d99fa3c5SJeremy L Thompson if (Qf != Qc) 1951d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1952e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 1953e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 1954d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1955d99fa3c5SJeremy L Thompson 1956d99fa3c5SJeremy L Thompson // Coarse to fine basis 1957d99fa3c5SJeremy L Thompson CeedInt dim, ncomp, nnodesCoarse, P1dFine, P1dCoarse; 1958d99fa3c5SJeremy L Thompson ierr = CeedBasisGetDimension(basisFine, &dim); CeedChk(ierr); 1959d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumComponents(basisFine, &ncomp); CeedChk(ierr); 1960d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes1D(basisFine, &P1dFine); CeedChk(ierr); 1961d99fa3c5SJeremy L Thompson ierr = CeedElemRestrictionGetElementSize(rstrCoarse, &nnodesCoarse); 1962d99fa3c5SJeremy L Thompson CeedChk(ierr); 1963d99fa3c5SJeremy L Thompson P1dCoarse = dim == 1 ? nnodesCoarse : 1964d99fa3c5SJeremy L Thompson dim == 2 ? sqrt(nnodesCoarse) : 1965d99fa3c5SJeremy L Thompson cbrt(nnodesCoarse); 1966d99fa3c5SJeremy L Thompson CeedScalar *qref, *qweight, *grad; 1967d99fa3c5SJeremy L Thompson ierr = CeedCalloc(P1dFine, &qref); CeedChk(ierr); 1968d99fa3c5SJeremy L Thompson ierr = CeedCalloc(P1dFine, &qweight); CeedChk(ierr); 1969d99fa3c5SJeremy L Thompson ierr = CeedCalloc(P1dFine*P1dCoarse*dim, &grad); CeedChk(ierr); 1970d99fa3c5SJeremy L Thompson CeedBasis basisCtoF; 1971d99fa3c5SJeremy L Thompson ierr = CeedBasisCreateTensorH1(ceed, dim, ncomp, P1dCoarse, P1dFine, 1972d99fa3c5SJeremy L Thompson interpCtoF, grad, qref, qweight, &basisCtoF); 1973d99fa3c5SJeremy L Thompson CeedChk(ierr); 1974d99fa3c5SJeremy L Thompson ierr = CeedFree(&qref); CeedChk(ierr); 1975d99fa3c5SJeremy L Thompson ierr = CeedFree(&qweight); CeedChk(ierr); 1976d99fa3c5SJeremy L Thompson ierr = CeedFree(&grad); CeedChk(ierr); 1977d99fa3c5SJeremy L Thompson 1978d99fa3c5SJeremy L Thompson // Core code 1979d99fa3c5SJeremy L Thompson ierr = CeedOperatorMultigridLevel_Core(opFine, PMultFine, rstrCoarse, 1980d99fa3c5SJeremy L Thompson basisCoarse, basisCtoF, opCoarse, 1981d99fa3c5SJeremy L Thompson opProlong, opRestrict); 1982d99fa3c5SJeremy L Thompson CeedChk(ierr); 1983e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1984d99fa3c5SJeremy L Thompson } 1985d99fa3c5SJeremy L Thompson 1986d99fa3c5SJeremy L Thompson /** 1987d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1988d99fa3c5SJeremy L Thompson for a CeedOperator with a non-tensor basis for the active vector 1989d99fa3c5SJeremy L Thompson 1990d99fa3c5SJeremy L Thompson @param[in] opFine Fine grid operator 1991d99fa3c5SJeremy L Thompson @param[in] PMultFine L-vector multiplicity in parallel gather/scatter 1992d99fa3c5SJeremy L Thompson @param[in] rstrCoarse Coarse grid restriction 1993d99fa3c5SJeremy L Thompson @param[in] basisCoarse Coarse grid active vector basis 1994d99fa3c5SJeremy L Thompson @param[in] interpCtoF Matrix for coarse to fine interpolation 1995d99fa3c5SJeremy L Thompson @param[out] opCoarse Coarse grid operator 1996d99fa3c5SJeremy L Thompson @param[out] opProlong Coarse to fine operator 1997d99fa3c5SJeremy L Thompson @param[out] opRestrict Fine to coarse operator 1998d99fa3c5SJeremy L Thompson 1999d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 2000d99fa3c5SJeremy L Thompson 2001d99fa3c5SJeremy L Thompson @ref User 2002d99fa3c5SJeremy L Thompson **/ 2003d99fa3c5SJeremy L Thompson int CeedOperatorMultigridLevelCreateH1(CeedOperator opFine, 2004d99fa3c5SJeremy L Thompson CeedVector PMultFine, 2005d99fa3c5SJeremy L Thompson CeedElemRestriction rstrCoarse, 2006d99fa3c5SJeremy L Thompson CeedBasis basisCoarse, 2007d99fa3c5SJeremy L Thompson const CeedScalar *interpCtoF, 2008d99fa3c5SJeremy L Thompson CeedOperator *opCoarse, 2009d99fa3c5SJeremy L Thompson CeedOperator *opProlong, 2010d99fa3c5SJeremy L Thompson CeedOperator *opRestrict) { 2011d99fa3c5SJeremy L Thompson int ierr; 2012d99fa3c5SJeremy L Thompson Ceed ceed; 2013d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(opFine, &ceed); CeedChk(ierr); 2014d99fa3c5SJeremy L Thompson 2015d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 2016d99fa3c5SJeremy L Thompson CeedBasis basisFine; 2017d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetActiveBasis(opFine, &basisFine); CeedChk(ierr); 2018d99fa3c5SJeremy L Thompson CeedInt Qf, Qc; 2019d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisFine, &Qf); CeedChk(ierr); 2020d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisCoarse, &Qc); CeedChk(ierr); 2021d99fa3c5SJeremy L Thompson if (Qf != Qc) 2022d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 2023e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 2024e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 2025d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 2026d99fa3c5SJeremy L Thompson 2027d99fa3c5SJeremy L Thompson // Coarse to fine basis 2028d99fa3c5SJeremy L Thompson CeedElemTopology topo; 2029d99fa3c5SJeremy L Thompson ierr = CeedBasisGetTopology(basisFine, &topo); CeedChk(ierr); 2030d99fa3c5SJeremy L Thompson CeedInt dim, ncomp, nnodesCoarse, nnodesFine; 2031d99fa3c5SJeremy L Thompson ierr = CeedBasisGetDimension(basisFine, &dim); CeedChk(ierr); 2032d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumComponents(basisFine, &ncomp); CeedChk(ierr); 2033d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes(basisFine, &nnodesFine); CeedChk(ierr); 2034d99fa3c5SJeremy L Thompson ierr = CeedElemRestrictionGetElementSize(rstrCoarse, &nnodesCoarse); 2035d99fa3c5SJeremy L Thompson CeedChk(ierr); 2036d99fa3c5SJeremy L Thompson CeedScalar *qref, *qweight, *grad; 2037d99fa3c5SJeremy L Thompson ierr = CeedCalloc(nnodesFine, &qref); CeedChk(ierr); 2038d99fa3c5SJeremy L Thompson ierr = CeedCalloc(nnodesFine, &qweight); CeedChk(ierr); 2039d99fa3c5SJeremy L Thompson ierr = CeedCalloc(nnodesFine*nnodesCoarse*dim, &grad); CeedChk(ierr); 2040d99fa3c5SJeremy L Thompson CeedBasis basisCtoF; 2041d99fa3c5SJeremy L Thompson ierr = CeedBasisCreateH1(ceed, topo, ncomp, nnodesCoarse, nnodesFine, 2042d99fa3c5SJeremy L Thompson interpCtoF, grad, qref, qweight, &basisCtoF); 2043d99fa3c5SJeremy L Thompson CeedChk(ierr); 2044d99fa3c5SJeremy L Thompson ierr = CeedFree(&qref); CeedChk(ierr); 2045d99fa3c5SJeremy L Thompson ierr = CeedFree(&qweight); CeedChk(ierr); 2046d99fa3c5SJeremy L Thompson ierr = CeedFree(&grad); CeedChk(ierr); 2047d99fa3c5SJeremy L Thompson 2048d99fa3c5SJeremy L Thompson // Core code 2049d99fa3c5SJeremy L Thompson ierr = CeedOperatorMultigridLevel_Core(opFine, PMultFine, rstrCoarse, 2050d99fa3c5SJeremy L Thompson basisCoarse, basisCtoF, opCoarse, 2051d99fa3c5SJeremy L Thompson opProlong, opRestrict); 2052d99fa3c5SJeremy L Thompson CeedChk(ierr); 2053e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2054d99fa3c5SJeremy L Thompson } 2055d99fa3c5SJeremy L Thompson 2056d99fa3c5SJeremy L Thompson /** 20573bd813ffSjeremylt @brief Build a FDM based approximate inverse for each element for a 20583bd813ffSjeremylt CeedOperator 20593bd813ffSjeremylt 20603bd813ffSjeremylt This returns a CeedOperator and CeedVector to apply a Fast Diagonalization 20613bd813ffSjeremylt Method based approximate inverse. This function obtains the simultaneous 20623bd813ffSjeremylt diagonalization for the 1D mass and Laplacian operators, 20633bd813ffSjeremylt M = V^T V, K = V^T S V. 20643bd813ffSjeremylt The assembled QFunction is used to modify the eigenvalues from simultaneous 20653bd813ffSjeremylt diagonalization and obtain an approximate inverse of the form 20663bd813ffSjeremylt V^T S^hat V. The CeedOperator must be linear and non-composite. The 20673bd813ffSjeremylt associated CeedQFunction must therefore also be linear. 20683bd813ffSjeremylt 20693bd813ffSjeremylt @param op CeedOperator to create element inverses 20703bd813ffSjeremylt @param[out] fdminv CeedOperator to apply the action of a FDM based inverse 20713bd813ffSjeremylt for each element 20723bd813ffSjeremylt @param request Address of CeedRequest for non-blocking completion, else 20734cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 20743bd813ffSjeremylt 20753bd813ffSjeremylt @return An error code: 0 - success, otherwise - failure 20763bd813ffSjeremylt 20777a982d89SJeremy L. Thompson @ref Backend 20783bd813ffSjeremylt **/ 20793bd813ffSjeremylt int CeedOperatorCreateFDMElementInverse(CeedOperator op, CeedOperator *fdminv, 20803bd813ffSjeremylt CeedRequest *request) { 20813bd813ffSjeremylt int ierr; 2082e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 20833bd813ffSjeremylt 2084713f43c3Sjeremylt // Use backend version, if available 2085713f43c3Sjeremylt if (op->CreateFDMElementInverse) { 2086713f43c3Sjeremylt ierr = op->CreateFDMElementInverse(op, fdminv, request); CeedChk(ierr); 2087713f43c3Sjeremylt } else { 2088713f43c3Sjeremylt // Fallback to reference Ceed 2089713f43c3Sjeremylt if (!op->opfallback) { 2090713f43c3Sjeremylt ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 20913bd813ffSjeremylt } 2092713f43c3Sjeremylt // Assemble 2093713f43c3Sjeremylt ierr = op->opfallback->CreateFDMElementInverse(op->opfallback, fdminv, 20943bd813ffSjeremylt request); CeedChk(ierr); 20953bd813ffSjeremylt } 2096e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 20973bd813ffSjeremylt } 20983bd813ffSjeremylt 20997a982d89SJeremy L. Thompson /** 21007a982d89SJeremy L. Thompson @brief View a CeedOperator 21017a982d89SJeremy L. Thompson 21027a982d89SJeremy L. Thompson @param[in] op CeedOperator to view 21037a982d89SJeremy L. Thompson @param[in] stream Stream to write; typically stdout/stderr or a file 21047a982d89SJeremy L. Thompson 21057a982d89SJeremy L. Thompson @return Error code: 0 - success, otherwise - failure 21067a982d89SJeremy L. Thompson 21077a982d89SJeremy L. Thompson @ref User 21087a982d89SJeremy L. Thompson **/ 21097a982d89SJeremy L. Thompson int CeedOperatorView(CeedOperator op, FILE *stream) { 21107a982d89SJeremy L. Thompson int ierr; 21117a982d89SJeremy L. Thompson 21127a982d89SJeremy L. Thompson if (op->composite) { 21137a982d89SJeremy L. Thompson fprintf(stream, "Composite CeedOperator\n"); 21147a982d89SJeremy L. Thompson 21157a982d89SJeremy L. Thompson for (CeedInt i=0; i<op->numsub; i++) { 21167a982d89SJeremy L. Thompson fprintf(stream, " SubOperator [%d]:\n", i); 21177a982d89SJeremy L. Thompson ierr = CeedOperatorSingleView(op->suboperators[i], 1, stream); 21187a982d89SJeremy L. Thompson CeedChk(ierr); 21197a982d89SJeremy L. Thompson } 21207a982d89SJeremy L. Thompson } else { 21217a982d89SJeremy L. Thompson fprintf(stream, "CeedOperator\n"); 21227a982d89SJeremy L. Thompson ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr); 21237a982d89SJeremy L. Thompson } 2124e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 21257a982d89SJeremy L. Thompson } 21263bd813ffSjeremylt 21273bd813ffSjeremylt /** 21283bd813ffSjeremylt @brief Apply CeedOperator to a vector 2129d7b241e6Sjeremylt 2130d7b241e6Sjeremylt This computes the action of the operator on the specified (active) input, 2131d7b241e6Sjeremylt yielding its (active) output. All inputs and outputs must be specified using 2132d7b241e6Sjeremylt CeedOperatorSetField(). 2133d7b241e6Sjeremylt 2134d7b241e6Sjeremylt @param op CeedOperator to apply 21354cc79fe7SJed Brown @param[in] in CeedVector containing input state or @ref CEED_VECTOR_NONE if 213634138859Sjeremylt there are no active inputs 2137b11c1e72Sjeremylt @param[out] out CeedVector to store result of applying operator (must be 21384cc79fe7SJed Brown distinct from @a in) or @ref CEED_VECTOR_NONE if there are no 213934138859Sjeremylt active outputs 2140d7b241e6Sjeremylt @param request Address of CeedRequest for non-blocking completion, else 21414cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 2142b11c1e72Sjeremylt 2143b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 2144dfdf5a53Sjeremylt 21457a982d89SJeremy L. Thompson @ref User 2146b11c1e72Sjeremylt **/ 2147692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out, 2148692c2638Sjeremylt CeedRequest *request) { 2149d7b241e6Sjeremylt int ierr; 2150e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 2151d7b241e6Sjeremylt 2152250756a7Sjeremylt if (op->numelements) { 2153250756a7Sjeremylt // Standard Operator 2154cae8b89aSjeremylt if (op->Apply) { 2155250756a7Sjeremylt ierr = op->Apply(op, in, out, request); CeedChk(ierr); 2156cae8b89aSjeremylt } else { 2157cae8b89aSjeremylt // Zero all output vectors 2158250756a7Sjeremylt CeedQFunction qf = op->qf; 2159cae8b89aSjeremylt for (CeedInt i=0; i<qf->numoutputfields; i++) { 2160cae8b89aSjeremylt CeedVector vec = op->outputfields[i]->vec; 2161cae8b89aSjeremylt if (vec == CEED_VECTOR_ACTIVE) 2162cae8b89aSjeremylt vec = out; 2163cae8b89aSjeremylt if (vec != CEED_VECTOR_NONE) { 2164cae8b89aSjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 2165cae8b89aSjeremylt } 2166cae8b89aSjeremylt } 2167250756a7Sjeremylt // Apply 2168250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 2169250756a7Sjeremylt } 2170250756a7Sjeremylt } else if (op->composite) { 2171250756a7Sjeremylt // Composite Operator 2172250756a7Sjeremylt if (op->ApplyComposite) { 2173250756a7Sjeremylt ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr); 2174250756a7Sjeremylt } else { 2175250756a7Sjeremylt CeedInt numsub; 2176250756a7Sjeremylt ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 2177250756a7Sjeremylt CeedOperator *suboperators; 2178250756a7Sjeremylt ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 2179250756a7Sjeremylt 2180250756a7Sjeremylt // Zero all output vectors 2181250756a7Sjeremylt if (out != CEED_VECTOR_NONE) { 2182cae8b89aSjeremylt ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr); 2183cae8b89aSjeremylt } 2184250756a7Sjeremylt for (CeedInt i=0; i<numsub; i++) { 2185250756a7Sjeremylt for (CeedInt j=0; j<suboperators[i]->qf->numoutputfields; j++) { 2186250756a7Sjeremylt CeedVector vec = suboperators[i]->outputfields[j]->vec; 2187250756a7Sjeremylt if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) { 2188250756a7Sjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 2189250756a7Sjeremylt } 2190250756a7Sjeremylt } 2191250756a7Sjeremylt } 2192250756a7Sjeremylt // Apply 2193250756a7Sjeremylt for (CeedInt i=0; i<op->numsub; i++) { 2194250756a7Sjeremylt ierr = CeedOperatorApplyAdd(op->suboperators[i], in, out, request); 2195cae8b89aSjeremylt CeedChk(ierr); 2196cae8b89aSjeremylt } 2197cae8b89aSjeremylt } 2198250756a7Sjeremylt } 2199e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2200cae8b89aSjeremylt } 2201cae8b89aSjeremylt 2202cae8b89aSjeremylt /** 2203cae8b89aSjeremylt @brief Apply CeedOperator to a vector and add result to output vector 2204cae8b89aSjeremylt 2205cae8b89aSjeremylt This computes the action of the operator on the specified (active) input, 2206cae8b89aSjeremylt yielding its (active) output. All inputs and outputs must be specified using 2207cae8b89aSjeremylt CeedOperatorSetField(). 2208cae8b89aSjeremylt 2209cae8b89aSjeremylt @param op CeedOperator to apply 2210cae8b89aSjeremylt @param[in] in CeedVector containing input state or NULL if there are no 2211cae8b89aSjeremylt active inputs 2212cae8b89aSjeremylt @param[out] out CeedVector to sum in result of applying operator (must be 2213cae8b89aSjeremylt distinct from @a in) or NULL if there are no active outputs 2214cae8b89aSjeremylt @param request Address of CeedRequest for non-blocking completion, else 22154cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 2216cae8b89aSjeremylt 2217cae8b89aSjeremylt @return An error code: 0 - success, otherwise - failure 2218cae8b89aSjeremylt 22197a982d89SJeremy L. Thompson @ref User 2220cae8b89aSjeremylt **/ 2221cae8b89aSjeremylt int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out, 2222cae8b89aSjeremylt CeedRequest *request) { 2223cae8b89aSjeremylt int ierr; 2224e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 2225cae8b89aSjeremylt 2226250756a7Sjeremylt if (op->numelements) { 2227250756a7Sjeremylt // Standard Operator 2228250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 2229250756a7Sjeremylt } else if (op->composite) { 2230250756a7Sjeremylt // Composite Operator 2231250756a7Sjeremylt if (op->ApplyAddComposite) { 2232250756a7Sjeremylt ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr); 2233cae8b89aSjeremylt } else { 2234250756a7Sjeremylt CeedInt numsub; 2235250756a7Sjeremylt ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 2236250756a7Sjeremylt CeedOperator *suboperators; 2237250756a7Sjeremylt ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 2238250756a7Sjeremylt 2239250756a7Sjeremylt for (CeedInt i=0; i<numsub; i++) { 2240250756a7Sjeremylt ierr = CeedOperatorApplyAdd(suboperators[i], in, out, request); 2241cae8b89aSjeremylt CeedChk(ierr); 22421d7d2407SJeremy L Thompson } 2243250756a7Sjeremylt } 2244250756a7Sjeremylt } 2245e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2246d7b241e6Sjeremylt } 2247d7b241e6Sjeremylt 2248d7b241e6Sjeremylt /** 2249b11c1e72Sjeremylt @brief Destroy a CeedOperator 2250d7b241e6Sjeremylt 2251d7b241e6Sjeremylt @param op CeedOperator to destroy 2252b11c1e72Sjeremylt 2253b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 2254dfdf5a53Sjeremylt 22557a982d89SJeremy L. Thompson @ref User 2256b11c1e72Sjeremylt **/ 2257d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) { 2258d7b241e6Sjeremylt int ierr; 2259d7b241e6Sjeremylt 2260e15f9bd0SJeremy L Thompson if (!*op || --(*op)->refcount > 0) return CEED_ERROR_SUCCESS; 2261d7b241e6Sjeremylt if ((*op)->Destroy) { 2262d7b241e6Sjeremylt ierr = (*op)->Destroy(*op); CeedChk(ierr); 2263d7b241e6Sjeremylt } 2264fe2413ffSjeremylt ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 2265fe2413ffSjeremylt // Free fields 22661d102b48SJeremy L Thompson for (int i=0; i<(*op)->nfields; i++) 226752d6035fSJeremy L Thompson if ((*op)->inputfields[i]) { 226815910d16Sjeremylt if ((*op)->inputfields[i]->Erestrict != CEED_ELEMRESTRICTION_NONE) { 226971352a93Sjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->inputfields[i]->Erestrict); 227071352a93Sjeremylt CeedChk(ierr); 227115910d16Sjeremylt } 227271352a93Sjeremylt if ((*op)->inputfields[i]->basis != CEED_BASIS_COLLOCATED) { 227371352a93Sjeremylt ierr = CeedBasisDestroy(&(*op)->inputfields[i]->basis); CeedChk(ierr); 227471352a93Sjeremylt } 227571352a93Sjeremylt if ((*op)->inputfields[i]->vec != CEED_VECTOR_ACTIVE && 227671352a93Sjeremylt (*op)->inputfields[i]->vec != CEED_VECTOR_NONE ) { 227771352a93Sjeremylt ierr = CeedVectorDestroy(&(*op)->inputfields[i]->vec); CeedChk(ierr); 227871352a93Sjeremylt } 2279d99fa3c5SJeremy L Thompson ierr = CeedFree(&(*op)->inputfields[i]->fieldname); CeedChk(ierr); 2280fe2413ffSjeremylt ierr = CeedFree(&(*op)->inputfields[i]); CeedChk(ierr); 2281fe2413ffSjeremylt } 22821d102b48SJeremy L Thompson for (int i=0; i<(*op)->nfields; i++) 2283d0eb30a5Sjeremylt if ((*op)->outputfields[i]) { 228471352a93Sjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->outputfields[i]->Erestrict); 228571352a93Sjeremylt CeedChk(ierr); 228671352a93Sjeremylt if ((*op)->outputfields[i]->basis != CEED_BASIS_COLLOCATED) { 228771352a93Sjeremylt ierr = CeedBasisDestroy(&(*op)->outputfields[i]->basis); CeedChk(ierr); 228871352a93Sjeremylt } 228971352a93Sjeremylt if ((*op)->outputfields[i]->vec != CEED_VECTOR_ACTIVE && 229071352a93Sjeremylt (*op)->outputfields[i]->vec != CEED_VECTOR_NONE ) { 229171352a93Sjeremylt ierr = CeedVectorDestroy(&(*op)->outputfields[i]->vec); CeedChk(ierr); 229271352a93Sjeremylt } 2293d99fa3c5SJeremy L Thompson ierr = CeedFree(&(*op)->outputfields[i]->fieldname); CeedChk(ierr); 2294fe2413ffSjeremylt ierr = CeedFree(&(*op)->outputfields[i]); CeedChk(ierr); 2295fe2413ffSjeremylt } 229652d6035fSJeremy L Thompson // Destroy suboperators 22971d102b48SJeremy L Thompson for (int i=0; i<(*op)->numsub; i++) 229852d6035fSJeremy L Thompson if ((*op)->suboperators[i]) { 229952d6035fSJeremy L Thompson ierr = CeedOperatorDestroy(&(*op)->suboperators[i]); CeedChk(ierr); 230052d6035fSJeremy L Thompson } 2301e15f9bd0SJeremy L Thompson if ((*op)->qf) 2302e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2303e15f9bd0SJeremy L Thompson (*op)->qf->operatorsset--; 2304e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2305d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 2306e15f9bd0SJeremy L Thompson if ((*op)->dqf && (*op)->dqf != CEED_QFUNCTION_NONE) 2307e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2308e15f9bd0SJeremy L Thompson (*op)->dqf->operatorsset--; 2309e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2310d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 2311e15f9bd0SJeremy L Thompson if ((*op)->dqfT && (*op)->dqfT != CEED_QFUNCTION_NONE) 2312e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2313e15f9bd0SJeremy L Thompson (*op)->dqfT->operatorsset--; 2314e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2315d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 2316fe2413ffSjeremylt 23175107b09fSJeremy L Thompson // Destroy fallback 23185107b09fSJeremy L Thompson if ((*op)->opfallback) { 23195107b09fSJeremy L Thompson ierr = (*op)->qffallback->Destroy((*op)->qffallback); CeedChk(ierr); 23205107b09fSJeremy L Thompson ierr = CeedFree(&(*op)->qffallback); CeedChk(ierr); 23215107b09fSJeremy L Thompson ierr = (*op)->opfallback->Destroy((*op)->opfallback); CeedChk(ierr); 23225107b09fSJeremy L Thompson ierr = CeedFree(&(*op)->opfallback); CeedChk(ierr); 23235107b09fSJeremy L Thompson } 23245107b09fSJeremy L Thompson 2325fe2413ffSjeremylt ierr = CeedFree(&(*op)->inputfields); CeedChk(ierr); 2326fe2413ffSjeremylt ierr = CeedFree(&(*op)->outputfields); CeedChk(ierr); 232752d6035fSJeremy L Thompson ierr = CeedFree(&(*op)->suboperators); CeedChk(ierr); 2328d7b241e6Sjeremylt ierr = CeedFree(op); CeedChk(ierr); 2329e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2330d7b241e6Sjeremylt } 2331d7b241e6Sjeremylt 2332d7b241e6Sjeremylt /// @} 2333