1d7b241e6Sjeremylt // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at 2d7b241e6Sjeremylt // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights 3d7b241e6Sjeremylt // reserved. See files LICENSE and NOTICE for details. 4d7b241e6Sjeremylt // 5d7b241e6Sjeremylt // This file is part of CEED, a collection of benchmarks, miniapps, software 6d7b241e6Sjeremylt // libraries and APIs for efficient high-order finite element and spectral 7d7b241e6Sjeremylt // element discretizations for exascale applications. For more information and 8d7b241e6Sjeremylt // source code availability see http://github.com/ceed. 9d7b241e6Sjeremylt // 10d7b241e6Sjeremylt // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 11d7b241e6Sjeremylt // a collaborative effort of two U.S. Department of Energy organizations (Office 12d7b241e6Sjeremylt // of Science and the National Nuclear Security Administration) responsible for 13d7b241e6Sjeremylt // the planning and preparation of a capable exascale ecosystem, including 14d7b241e6Sjeremylt // software, applications, hardware, advanced system engineering and early 15d7b241e6Sjeremylt // testbed platforms, in support of the nation's exascale computing imperative. 16d7b241e6Sjeremylt 173d576824SJeremy L Thompson #include <ceed.h> 18d863ab9bSjeremylt #include <ceed-backend.h> 193d576824SJeremy L Thompson #include <ceed-impl.h> 203bd813ffSjeremylt #include <math.h> 213d576824SJeremy L Thompson #include <stdbool.h> 223d576824SJeremy L Thompson #include <stdio.h> 233d576824SJeremy L Thompson #include <string.h> 24d7b241e6Sjeremylt 25dfdf5a53Sjeremylt /// @file 267a982d89SJeremy L. Thompson /// Implementation of CeedOperator interfaces 277a982d89SJeremy L. Thompson 287a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 297a982d89SJeremy L. Thompson /// CeedOperator Library Internal Functions 307a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 317a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorDeveloper 327a982d89SJeremy L. Thompson /// @{ 337a982d89SJeremy L. Thompson 347a982d89SJeremy L. Thompson /** 357a982d89SJeremy L. Thompson @brief Duplicate a CeedOperator with a reference Ceed to fallback for advanced 367a982d89SJeremy L. Thompson CeedOperator functionality 377a982d89SJeremy L. Thompson 387a982d89SJeremy L. Thompson @param op CeedOperator to create fallback for 397a982d89SJeremy L. Thompson 407a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 417a982d89SJeremy L. Thompson 427a982d89SJeremy L. Thompson @ref Developer 437a982d89SJeremy L. Thompson **/ 447a982d89SJeremy L. Thompson int CeedOperatorCreateFallback(CeedOperator op) { 457a982d89SJeremy L. Thompson int ierr; 467a982d89SJeremy L. Thompson 477a982d89SJeremy L. Thompson // Fallback Ceed 487a982d89SJeremy L. Thompson const char *resource, *fallbackresource; 497a982d89SJeremy L. Thompson ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr); 507a982d89SJeremy L. Thompson ierr = CeedGetOperatorFallbackResource(op->ceed, &fallbackresource); 517a982d89SJeremy L. Thompson CeedChk(ierr); 527a982d89SJeremy L. Thompson if (!strcmp(resource, fallbackresource)) 537a982d89SJeremy L. Thompson // LCOV_EXCL_START 54e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 55e15f9bd0SJeremy L Thompson "Backend %s cannot create an operator" 567a982d89SJeremy L. Thompson "fallback to resource %s", resource, fallbackresource); 577a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 587a982d89SJeremy L. Thompson 597a982d89SJeremy L. Thompson // Fallback Ceed 607a982d89SJeremy L. Thompson Ceed ceedref; 617a982d89SJeremy L. Thompson if (!op->ceed->opfallbackceed) { 627a982d89SJeremy L. Thompson ierr = CeedInit(fallbackresource, &ceedref); CeedChk(ierr); 637a982d89SJeremy L. Thompson ceedref->opfallbackparent = op->ceed; 64fc164cf7SWill Pazner ceedref->Error = op->ceed->Error; 657a982d89SJeremy L. Thompson op->ceed->opfallbackceed = ceedref; 667a982d89SJeremy L. Thompson } 677a982d89SJeremy L. Thompson ceedref = op->ceed->opfallbackceed; 687a982d89SJeremy L. Thompson 697a982d89SJeremy L. Thompson // Clone Op 707a982d89SJeremy L. Thompson CeedOperator opref; 717a982d89SJeremy L. Thompson ierr = CeedCalloc(1, &opref); CeedChk(ierr); 72e15f9bd0SJeremy L Thompson memcpy(opref, op, sizeof(*opref)); 737a982d89SJeremy L. Thompson opref->data = NULL; 74e15f9bd0SJeremy L Thompson opref->interfacesetup = false; 75e15f9bd0SJeremy L Thompson opref->backendsetup = false; 767a982d89SJeremy L. Thompson opref->ceed = ceedref; 777a982d89SJeremy L. Thompson ierr = ceedref->OperatorCreate(opref); CeedChk(ierr); 787a982d89SJeremy L. Thompson op->opfallback = opref; 797a982d89SJeremy L. Thompson 807a982d89SJeremy L. Thompson // Clone QF 817a982d89SJeremy L. Thompson CeedQFunction qfref; 827a982d89SJeremy L. Thompson ierr = CeedCalloc(1, &qfref); CeedChk(ierr); 83e15f9bd0SJeremy L Thompson memcpy(qfref, (op->qf), sizeof(*qfref)); 847a982d89SJeremy L. Thompson qfref->data = NULL; 857a982d89SJeremy L. Thompson qfref->ceed = ceedref; 867a982d89SJeremy L. Thompson ierr = ceedref->QFunctionCreate(qfref); CeedChk(ierr); 877a982d89SJeremy L. Thompson opref->qf = qfref; 887a982d89SJeremy L. Thompson op->qffallback = qfref; 89e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 90e15f9bd0SJeremy L Thompson } 917a982d89SJeremy L. Thompson 92e15f9bd0SJeremy L Thompson /** 93e15f9bd0SJeremy L Thompson @brief Check if a CeedOperator Field matches the QFunction Field 94e15f9bd0SJeremy L Thompson 95e15f9bd0SJeremy L Thompson @param[in] ceed Ceed object for error handling 96e15f9bd0SJeremy L Thompson @param[in] qfield QFunction Field matching Operator Field 97e15f9bd0SJeremy L Thompson @param[in] r Operator Field ElemRestriction 98e15f9bd0SJeremy L Thompson @param[in] b Operator Field Basis 99e15f9bd0SJeremy L Thompson 100e15f9bd0SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 101e15f9bd0SJeremy L Thompson 102e15f9bd0SJeremy L Thompson @ref Developer 103e15f9bd0SJeremy L Thompson **/ 104e15f9bd0SJeremy L Thompson static int CeedOperatorCheckField(Ceed ceed, CeedQFunctionField qfield, 105e15f9bd0SJeremy L Thompson CeedElemRestriction r, CeedBasis b) { 106e15f9bd0SJeremy L Thompson int ierr; 107e15f9bd0SJeremy L Thompson CeedEvalMode emode = qfield->emode; 108e15f9bd0SJeremy L Thompson CeedInt dim = 1, ncomp = 1, restr_ncomp = 1, size = qfield->size; 109e15f9bd0SJeremy L Thompson // Restriction 110e15f9bd0SJeremy L Thompson if (r != CEED_ELEMRESTRICTION_NONE) { 111*e1e9e29dSJed Brown if (emode == CEED_EVAL_WEIGHT) { 112e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 113*e1e9e29dSJed Brown return CeedError(ceed, CEED_ERROR_INCOMPATIBLE, 114*e1e9e29dSJed 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 } 118*e1e9e29dSJed Brown ierr = CeedElemRestrictionGetNumComponents(r, &restr_ncomp); 119*e1e9e29dSJed Brown } 120*e1e9e29dSJed Brown if ((r == CEED_ELEMRESTRICTION_NONE) != (emode == CEED_EVAL_WEIGHT)) { 121*e1e9e29dSJed Brown // LCOV_EXCL_START 122*e1e9e29dSJed Brown return CeedError(ceed, CEED_ERROR_INCOMPATIBLE, 123*e1e9e29dSJed Brown "CEED_ELEMRESTRICTION_NONE and CEED_EVAL_WEIGHT " 124*e1e9e29dSJed Brown "must be used together."); 125*e1e9e29dSJed Brown // LCOV_EXCL_STOP 126*e1e9e29dSJed Brown } 127e15f9bd0SJeremy L Thompson // Basis 128e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 129*e1e9e29dSJed Brown if (emode == CEED_EVAL_NONE) 130*e1e9e29dSJed Brown return CeedError(ceed, CEED_ERROR_INCOMPATIBLE, 131*e1e9e29dSJed Brown "Field '%s' configured with CEED_EVAL_NONE must be used with CEED_BASIS_COLLOCATED", 132*e1e9e29dSJed 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, 138*e1e9e29dSJed Brown "Field '%s' of size %d and EvalMode %s: ElemRestriction has %d components, but Basis has %d components", 139*e1e9e29dSJed Brown qfield->fieldname, qfield->size, CeedEvalModes[qfield->emode], restr_ncomp, 140*e1e9e29dSJed 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, 150*e1e9e29dSJed Brown "Field '%s' of size %d and EvalMode %s: ElemRestriction has %d components", 151*e1e9e29dSJed 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, 158*e1e9e29dSJed Brown "Field '%s' of size %d and EvalMode %s: ElemRestriction/Basis has %d components", 159*e1e9e29dSJed 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, 166*e1e9e29dSJed Brown "Field '%s' of size %d and EvalMode %s in %d dimensions: ElemRestriction/Basis has %d components", 167*e1e9e29dSJed 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 /** 379d99fa3c5SJeremy L Thompson @brief Common code for creating a multigrid coarse operator and level 380d99fa3c5SJeremy L Thompson transfer operators for a CeedOperator 381d99fa3c5SJeremy L Thompson 382d99fa3c5SJeremy L Thompson @param[in] opFine Fine grid operator 383d99fa3c5SJeremy L Thompson @param[in] PMultFine L-vector multiplicity in parallel gather/scatter 384d99fa3c5SJeremy L Thompson @param[in] rstrCoarse Coarse grid restriction 385d99fa3c5SJeremy L Thompson @param[in] basisCoarse Coarse grid active vector basis 386d99fa3c5SJeremy L Thompson @param[in] basisCtoF Basis for coarse to fine interpolation 387d99fa3c5SJeremy L Thompson @param[out] opCoarse Coarse grid operator 388d99fa3c5SJeremy L Thompson @param[out] opProlong Coarse to fine operator 389d99fa3c5SJeremy L Thompson @param[out] opRestrict Fine to coarse operator 390d99fa3c5SJeremy L Thompson 391d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 392d99fa3c5SJeremy L Thompson 393d99fa3c5SJeremy L Thompson @ref Developer 394d99fa3c5SJeremy L Thompson **/ 395d99fa3c5SJeremy L Thompson static int CeedOperatorMultigridLevel_Core(CeedOperator opFine, 396d99fa3c5SJeremy L Thompson CeedVector PMultFine, CeedElemRestriction rstrCoarse, CeedBasis basisCoarse, 397d99fa3c5SJeremy L Thompson CeedBasis basisCtoF, CeedOperator *opCoarse, CeedOperator *opProlong, 398d99fa3c5SJeremy L Thompson CeedOperator *opRestrict) { 399d99fa3c5SJeremy L Thompson int ierr; 400d99fa3c5SJeremy L Thompson Ceed ceed; 401d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(opFine, &ceed); CeedChk(ierr); 402d99fa3c5SJeremy L Thompson 403d99fa3c5SJeremy L Thompson // Check for composite operator 404d99fa3c5SJeremy L Thompson bool isComposite; 405d99fa3c5SJeremy L Thompson ierr = CeedOperatorIsComposite(opFine, &isComposite); CeedChk(ierr); 406d99fa3c5SJeremy L Thompson if (isComposite) 407d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 408e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 409d99fa3c5SJeremy L Thompson "Automatic multigrid setup for composite operators not supported"); 410d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 411d99fa3c5SJeremy L Thompson 412d99fa3c5SJeremy L Thompson // Coarse Grid 413d99fa3c5SJeremy L Thompson ierr = CeedOperatorCreate(ceed, opFine->qf, opFine->dqf, opFine->dqfT, 414d99fa3c5SJeremy L Thompson opCoarse); CeedChk(ierr); 415d99fa3c5SJeremy L Thompson CeedElemRestriction rstrFine = NULL; 416d99fa3c5SJeremy L Thompson // -- Clone input fields 417d99fa3c5SJeremy L Thompson for (int i = 0; i < opFine->qf->numinputfields; i++) { 418d99fa3c5SJeremy L Thompson if (opFine->inputfields[i]->vec == CEED_VECTOR_ACTIVE) { 419d99fa3c5SJeremy L Thompson rstrFine = opFine->inputfields[i]->Erestrict; 420d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opCoarse, opFine->inputfields[i]->fieldname, 421d99fa3c5SJeremy L Thompson rstrCoarse, basisCoarse, CEED_VECTOR_ACTIVE); 422d99fa3c5SJeremy L Thompson CeedChk(ierr); 423d99fa3c5SJeremy L Thompson } else { 424d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opCoarse, opFine->inputfields[i]->fieldname, 425d99fa3c5SJeremy L Thompson opFine->inputfields[i]->Erestrict, 426d99fa3c5SJeremy L Thompson opFine->inputfields[i]->basis, 427d99fa3c5SJeremy L Thompson opFine->inputfields[i]->vec); CeedChk(ierr); 428d99fa3c5SJeremy L Thompson } 429d99fa3c5SJeremy L Thompson } 430d99fa3c5SJeremy L Thompson // -- Clone output fields 431d99fa3c5SJeremy L Thompson for (int i = 0; i < opFine->qf->numoutputfields; i++) { 432d99fa3c5SJeremy L Thompson if (opFine->outputfields[i]->vec == CEED_VECTOR_ACTIVE) { 433d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opCoarse, opFine->outputfields[i]->fieldname, 434d99fa3c5SJeremy L Thompson rstrCoarse, basisCoarse, CEED_VECTOR_ACTIVE); 435d99fa3c5SJeremy L Thompson CeedChk(ierr); 436d99fa3c5SJeremy L Thompson } else { 437d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opCoarse, opFine->outputfields[i]->fieldname, 438d99fa3c5SJeremy L Thompson opFine->outputfields[i]->Erestrict, 439d99fa3c5SJeremy L Thompson opFine->outputfields[i]->basis, 440d99fa3c5SJeremy L Thompson opFine->outputfields[i]->vec); CeedChk(ierr); 441d99fa3c5SJeremy L Thompson } 442d99fa3c5SJeremy L Thompson } 443d99fa3c5SJeremy L Thompson 444d99fa3c5SJeremy L Thompson // Multiplicity vector 445d99fa3c5SJeremy L Thompson CeedVector multVec, multE; 446d99fa3c5SJeremy L Thompson ierr = CeedElemRestrictionCreateVector(rstrFine, &multVec, &multE); 447d99fa3c5SJeremy L Thompson CeedChk(ierr); 448d99fa3c5SJeremy L Thompson ierr = CeedVectorSetValue(multE, 0.0); CeedChk(ierr); 449d99fa3c5SJeremy L Thompson ierr = CeedElemRestrictionApply(rstrFine, CEED_NOTRANSPOSE, PMultFine, multE, 450d99fa3c5SJeremy L Thompson CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 451d99fa3c5SJeremy L Thompson ierr = CeedVectorSetValue(multVec, 0.0); CeedChk(ierr); 452d99fa3c5SJeremy L Thompson ierr = CeedElemRestrictionApply(rstrFine, CEED_TRANSPOSE, multE, multVec, 453d99fa3c5SJeremy L Thompson CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 454d99fa3c5SJeremy L Thompson ierr = CeedVectorDestroy(&multE); CeedChk(ierr); 455d99fa3c5SJeremy L Thompson ierr = CeedVectorReciprocal(multVec); CeedChk(ierr); 456d99fa3c5SJeremy L Thompson 457d99fa3c5SJeremy L Thompson // Restriction 458d99fa3c5SJeremy L Thompson CeedInt ncomp; 459d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumComponents(basisCoarse, &ncomp); CeedChk(ierr); 460d99fa3c5SJeremy L Thompson CeedQFunction qfRestrict; 461d99fa3c5SJeremy L Thompson ierr = CeedQFunctionCreateInteriorByName(ceed, "Scale", &qfRestrict); 462d99fa3c5SJeremy L Thompson CeedChk(ierr); 463777ff853SJeremy L Thompson CeedInt *ncompRData; 464777ff853SJeremy L Thompson ierr = CeedCalloc(1, &ncompRData); CeedChk(ierr); 465777ff853SJeremy L Thompson ncompRData[0] = ncomp; 466777ff853SJeremy L Thompson CeedQFunctionContext ctxR; 467777ff853SJeremy L Thompson ierr = CeedQFunctionContextCreate(ceed, &ctxR); CeedChk(ierr); 468777ff853SJeremy L Thompson ierr = CeedQFunctionContextSetData(ctxR, CEED_MEM_HOST, CEED_OWN_POINTER, 469777ff853SJeremy L Thompson sizeof(*ncompRData), ncompRData); 470777ff853SJeremy L Thompson CeedChk(ierr); 471777ff853SJeremy L Thompson ierr = CeedQFunctionSetContext(qfRestrict, ctxR); CeedChk(ierr); 472777ff853SJeremy L Thompson ierr = CeedQFunctionContextDestroy(&ctxR); CeedChk(ierr); 473d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddInput(qfRestrict, "input", ncomp, CEED_EVAL_NONE); 474d99fa3c5SJeremy L Thompson CeedChk(ierr); 475d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddInput(qfRestrict, "scale", ncomp, CEED_EVAL_NONE); 476d99fa3c5SJeremy L Thompson CeedChk(ierr); 477d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddOutput(qfRestrict, "output", ncomp, CEED_EVAL_INTERP); 478d99fa3c5SJeremy L Thompson CeedChk(ierr); 479d99fa3c5SJeremy L Thompson 480d99fa3c5SJeremy L Thompson ierr = CeedOperatorCreate(ceed, qfRestrict, CEED_QFUNCTION_NONE, 481d99fa3c5SJeremy L Thompson CEED_QFUNCTION_NONE, opRestrict); 482d99fa3c5SJeremy L Thompson CeedChk(ierr); 483d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opRestrict, "input", rstrFine, 484d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE); 485d99fa3c5SJeremy L Thompson CeedChk(ierr); 486d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opRestrict, "scale", rstrFine, 487d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, multVec); 488d99fa3c5SJeremy L Thompson CeedChk(ierr); 489d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opRestrict, "output", rstrCoarse, basisCtoF, 490d99fa3c5SJeremy L Thompson CEED_VECTOR_ACTIVE); CeedChk(ierr); 491d99fa3c5SJeremy L Thompson 492d99fa3c5SJeremy L Thompson // Prolongation 493d99fa3c5SJeremy L Thompson CeedQFunction qfProlong; 494d99fa3c5SJeremy L Thompson ierr = CeedQFunctionCreateInteriorByName(ceed, "Scale", &qfProlong); 495d99fa3c5SJeremy L Thompson CeedChk(ierr); 496777ff853SJeremy L Thompson CeedInt *ncompPData; 497777ff853SJeremy L Thompson ierr = CeedCalloc(1, &ncompPData); CeedChk(ierr); 498777ff853SJeremy L Thompson ncompPData[0] = ncomp; 499777ff853SJeremy L Thompson CeedQFunctionContext ctxP; 500777ff853SJeremy L Thompson ierr = CeedQFunctionContextCreate(ceed, &ctxP); CeedChk(ierr); 501777ff853SJeremy L Thompson ierr = CeedQFunctionContextSetData(ctxP, CEED_MEM_HOST, CEED_OWN_POINTER, 502777ff853SJeremy L Thompson sizeof(*ncompPData), ncompPData); 503777ff853SJeremy L Thompson CeedChk(ierr); 504777ff853SJeremy L Thompson ierr = CeedQFunctionSetContext(qfProlong, ctxP); CeedChk(ierr); 505777ff853SJeremy L Thompson ierr = CeedQFunctionContextDestroy(&ctxP); CeedChk(ierr); 506d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddInput(qfProlong, "input", ncomp, CEED_EVAL_INTERP); 507d99fa3c5SJeremy L Thompson CeedChk(ierr); 508d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddInput(qfProlong, "scale", ncomp, CEED_EVAL_NONE); 509d99fa3c5SJeremy L Thompson CeedChk(ierr); 510d99fa3c5SJeremy L Thompson ierr = CeedQFunctionAddOutput(qfProlong, "output", ncomp, CEED_EVAL_NONE); 511d99fa3c5SJeremy L Thompson CeedChk(ierr); 512d99fa3c5SJeremy L Thompson 513d99fa3c5SJeremy L Thompson ierr = CeedOperatorCreate(ceed, qfProlong, CEED_QFUNCTION_NONE, 514d99fa3c5SJeremy L Thompson CEED_QFUNCTION_NONE, opProlong); 515d99fa3c5SJeremy L Thompson CeedChk(ierr); 516d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opProlong, "input", rstrCoarse, basisCtoF, 517d99fa3c5SJeremy L Thompson CEED_VECTOR_ACTIVE); CeedChk(ierr); 518d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opProlong, "scale", rstrFine, 519d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, multVec); 520d99fa3c5SJeremy L Thompson CeedChk(ierr); 521d99fa3c5SJeremy L Thompson ierr = CeedOperatorSetField(*opProlong, "output", rstrFine, 522d99fa3c5SJeremy L Thompson CEED_BASIS_COLLOCATED, CEED_VECTOR_ACTIVE); 523d99fa3c5SJeremy L Thompson CeedChk(ierr); 524d99fa3c5SJeremy L Thompson 525d99fa3c5SJeremy L Thompson // Cleanup 526d99fa3c5SJeremy L Thompson ierr = CeedVectorDestroy(&multVec); CeedChk(ierr); 527d99fa3c5SJeremy L Thompson ierr = CeedBasisDestroy(&basisCtoF); CeedChk(ierr); 528d99fa3c5SJeremy L Thompson ierr = CeedQFunctionDestroy(&qfRestrict); CeedChk(ierr); 529d99fa3c5SJeremy L Thompson ierr = CeedQFunctionDestroy(&qfProlong); CeedChk(ierr); 530e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 531d99fa3c5SJeremy L Thompson } 532d99fa3c5SJeremy L Thompson 5337a982d89SJeremy L. Thompson /// @} 5347a982d89SJeremy L. Thompson 5357a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 5367a982d89SJeremy L. Thompson /// CeedOperator Backend API 5377a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 5387a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorBackend 5397a982d89SJeremy L. Thompson /// @{ 5407a982d89SJeremy L. Thompson 5417a982d89SJeremy L. Thompson /** 5427a982d89SJeremy L. Thompson @brief Get the Ceed associated with a CeedOperator 5437a982d89SJeremy L. Thompson 5447a982d89SJeremy L. Thompson @param op CeedOperator 5457a982d89SJeremy L. Thompson @param[out] ceed Variable to store Ceed 5467a982d89SJeremy L. Thompson 5477a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5487a982d89SJeremy L. Thompson 5497a982d89SJeremy L. Thompson @ref Backend 5507a982d89SJeremy L. Thompson **/ 5517a982d89SJeremy L. Thompson 5527a982d89SJeremy L. Thompson int CeedOperatorGetCeed(CeedOperator op, Ceed *ceed) { 5537a982d89SJeremy L. Thompson *ceed = op->ceed; 554e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5557a982d89SJeremy L. Thompson } 5567a982d89SJeremy L. Thompson 5577a982d89SJeremy L. Thompson /** 5587a982d89SJeremy L. Thompson @brief Get the number of elements associated with a CeedOperator 5597a982d89SJeremy L. Thompson 5607a982d89SJeremy L. Thompson @param op CeedOperator 5617a982d89SJeremy L. Thompson @param[out] numelem Variable to store number of elements 5627a982d89SJeremy L. Thompson 5637a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5647a982d89SJeremy L. Thompson 5657a982d89SJeremy L. Thompson @ref Backend 5667a982d89SJeremy L. Thompson **/ 5677a982d89SJeremy L. Thompson 5687a982d89SJeremy L. Thompson int CeedOperatorGetNumElements(CeedOperator op, CeedInt *numelem) { 5697a982d89SJeremy L. Thompson if (op->composite) 5707a982d89SJeremy L. Thompson // LCOV_EXCL_START 571e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 572e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 5737a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 5747a982d89SJeremy L. Thompson 5757a982d89SJeremy L. Thompson *numelem = op->numelements; 576e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5777a982d89SJeremy L. Thompson } 5787a982d89SJeremy L. Thompson 5797a982d89SJeremy L. Thompson /** 5807a982d89SJeremy L. Thompson @brief Get the number of quadrature points associated with a CeedOperator 5817a982d89SJeremy L. Thompson 5827a982d89SJeremy L. Thompson @param op CeedOperator 5837a982d89SJeremy L. Thompson @param[out] numqpts Variable to store vector number of quadrature points 5847a982d89SJeremy L. Thompson 5857a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 5867a982d89SJeremy L. Thompson 5877a982d89SJeremy L. Thompson @ref Backend 5887a982d89SJeremy L. Thompson **/ 5897a982d89SJeremy L. Thompson 5907a982d89SJeremy L. Thompson int CeedOperatorGetNumQuadraturePoints(CeedOperator op, CeedInt *numqpts) { 5917a982d89SJeremy L. Thompson if (op->composite) 5927a982d89SJeremy L. Thompson // LCOV_EXCL_START 593e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 594e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 5957a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 5967a982d89SJeremy L. Thompson 5977a982d89SJeremy L. Thompson *numqpts = op->numqpoints; 598e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 5997a982d89SJeremy L. Thompson } 6007a982d89SJeremy L. Thompson 6017a982d89SJeremy L. Thompson /** 6027a982d89SJeremy L. Thompson @brief Get the number of arguments associated with a CeedOperator 6037a982d89SJeremy L. Thompson 6047a982d89SJeremy L. Thompson @param op CeedOperator 6057a982d89SJeremy L. Thompson @param[out] numargs Variable to store vector number of arguments 6067a982d89SJeremy L. Thompson 6077a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6087a982d89SJeremy L. Thompson 6097a982d89SJeremy L. Thompson @ref Backend 6107a982d89SJeremy L. Thompson **/ 6117a982d89SJeremy L. Thompson 6127a982d89SJeremy L. Thompson int CeedOperatorGetNumArgs(CeedOperator op, CeedInt *numargs) { 6137a982d89SJeremy L. Thompson if (op->composite) 6147a982d89SJeremy L. Thompson // LCOV_EXCL_START 615e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 616e15f9bd0SJeremy L Thompson "Not defined for composite operators"); 6177a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 6187a982d89SJeremy L. Thompson 6197a982d89SJeremy L. Thompson *numargs = op->nfields; 620e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6217a982d89SJeremy L. Thompson } 6227a982d89SJeremy L. Thompson 6237a982d89SJeremy L. Thompson /** 6247a982d89SJeremy L. Thompson @brief Get the setup status of a CeedOperator 6257a982d89SJeremy L. Thompson 6267a982d89SJeremy L. Thompson @param op CeedOperator 627fd364f38SJeremy L Thompson @param[out] issetupdone Variable to store setup status 6287a982d89SJeremy L. Thompson 6297a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6307a982d89SJeremy L. Thompson 6317a982d89SJeremy L. Thompson @ref Backend 6327a982d89SJeremy L. Thompson **/ 6337a982d89SJeremy L. Thompson 634fd364f38SJeremy L Thompson int CeedOperatorIsSetupDone(CeedOperator op, bool *issetupdone) { 635e15f9bd0SJeremy L Thompson *issetupdone = op->backendsetup; 636e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6377a982d89SJeremy L. Thompson } 6387a982d89SJeremy L. Thompson 6397a982d89SJeremy L. Thompson /** 6407a982d89SJeremy L. Thompson @brief Get the QFunction associated with a CeedOperator 6417a982d89SJeremy L. Thompson 6427a982d89SJeremy L. Thompson @param op CeedOperator 6437a982d89SJeremy L. Thompson @param[out] qf Variable to store QFunction 6447a982d89SJeremy L. Thompson 6457a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6467a982d89SJeremy L. Thompson 6477a982d89SJeremy L. Thompson @ref Backend 6487a982d89SJeremy L. Thompson **/ 6497a982d89SJeremy L. Thompson 6507a982d89SJeremy L. Thompson int CeedOperatorGetQFunction(CeedOperator op, CeedQFunction *qf) { 6517a982d89SJeremy L. Thompson if (op->composite) 6527a982d89SJeremy L. Thompson // LCOV_EXCL_START 653e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 654e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 6557a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 6567a982d89SJeremy L. Thompson 6577a982d89SJeremy L. Thompson *qf = op->qf; 658e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6597a982d89SJeremy L. Thompson } 6607a982d89SJeremy L. Thompson 6617a982d89SJeremy L. Thompson /** 662c04a41a7SJeremy L Thompson @brief Get a boolean value indicating if the CeedOperator is composite 663c04a41a7SJeremy L Thompson 664c04a41a7SJeremy L Thompson @param op CeedOperator 665fd364f38SJeremy L Thompson @param[out] iscomposite Variable to store composite status 666c04a41a7SJeremy L Thompson 667c04a41a7SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 668c04a41a7SJeremy L Thompson 669c04a41a7SJeremy L Thompson @ref Backend 670c04a41a7SJeremy L Thompson **/ 671c04a41a7SJeremy L Thompson 672fd364f38SJeremy L Thompson int CeedOperatorIsComposite(CeedOperator op, bool *iscomposite) { 673fd364f38SJeremy L Thompson *iscomposite = op->composite; 674e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 675c04a41a7SJeremy L Thompson } 676c04a41a7SJeremy L Thompson 677c04a41a7SJeremy L Thompson /** 6787a982d89SJeremy L. Thompson @brief Get the number of suboperators associated with a CeedOperator 6797a982d89SJeremy L. Thompson 6807a982d89SJeremy L. Thompson @param op CeedOperator 6817a982d89SJeremy L. Thompson @param[out] numsub Variable to store number of suboperators 6827a982d89SJeremy L. Thompson 6837a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 6847a982d89SJeremy L. Thompson 6857a982d89SJeremy L. Thompson @ref Backend 6867a982d89SJeremy L. Thompson **/ 6877a982d89SJeremy L. Thompson 6887a982d89SJeremy L. Thompson int CeedOperatorGetNumSub(CeedOperator op, CeedInt *numsub) { 6897a982d89SJeremy L. Thompson if (!op->composite) 6907a982d89SJeremy L. Thompson // LCOV_EXCL_START 691e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator"); 6927a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 6937a982d89SJeremy L. Thompson 6947a982d89SJeremy L. Thompson *numsub = op->numsub; 695e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6967a982d89SJeremy L. Thompson } 6977a982d89SJeremy L. Thompson 6987a982d89SJeremy L. Thompson /** 6997a982d89SJeremy L. Thompson @brief Get the list of suboperators associated with a CeedOperator 7007a982d89SJeremy L. Thompson 7017a982d89SJeremy L. Thompson @param op CeedOperator 7027a982d89SJeremy L. Thompson @param[out] suboperators Variable to store list of suboperators 7037a982d89SJeremy L. Thompson 7047a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7057a982d89SJeremy L. Thompson 7067a982d89SJeremy L. Thompson @ref Backend 7077a982d89SJeremy L. Thompson **/ 7087a982d89SJeremy L. Thompson 7097a982d89SJeremy L. Thompson int CeedOperatorGetSubList(CeedOperator op, CeedOperator **suboperators) { 7107a982d89SJeremy L. Thompson if (!op->composite) 7117a982d89SJeremy L. Thompson // LCOV_EXCL_START 712e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, "Not a composite operator"); 7137a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 7147a982d89SJeremy L. Thompson 7157a982d89SJeremy L. Thompson *suboperators = op->suboperators; 716e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7177a982d89SJeremy L. Thompson } 7187a982d89SJeremy L. Thompson 7197a982d89SJeremy L. Thompson /** 7207a982d89SJeremy L. Thompson @brief Get the backend data of a CeedOperator 7217a982d89SJeremy L. Thompson 7227a982d89SJeremy L. Thompson @param op CeedOperator 7237a982d89SJeremy L. Thompson @param[out] data Variable to store data 7247a982d89SJeremy L. Thompson 7257a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7267a982d89SJeremy L. Thompson 7277a982d89SJeremy L. Thompson @ref Backend 7287a982d89SJeremy L. Thompson **/ 7297a982d89SJeremy L. Thompson 730777ff853SJeremy L Thompson int CeedOperatorGetData(CeedOperator op, void *data) { 731777ff853SJeremy L Thompson *(void **)data = op->data; 732e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7337a982d89SJeremy L. Thompson } 7347a982d89SJeremy L. Thompson 7357a982d89SJeremy L. Thompson /** 7367a982d89SJeremy L. Thompson @brief Set the backend data of a CeedOperator 7377a982d89SJeremy L. Thompson 7387a982d89SJeremy L. Thompson @param[out] op CeedOperator 7397a982d89SJeremy L. Thompson @param data Data to set 7407a982d89SJeremy L. Thompson 7417a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7427a982d89SJeremy L. Thompson 7437a982d89SJeremy L. Thompson @ref Backend 7447a982d89SJeremy L. Thompson **/ 7457a982d89SJeremy L. Thompson 746777ff853SJeremy L Thompson int CeedOperatorSetData(CeedOperator op, void *data) { 747777ff853SJeremy L Thompson op->data = data; 748e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7497a982d89SJeremy L. Thompson } 7507a982d89SJeremy L. Thompson 7517a982d89SJeremy L. Thompson /** 7527a982d89SJeremy L. Thompson @brief Set the setup flag of a CeedOperator to True 7537a982d89SJeremy L. Thompson 7547a982d89SJeremy L. Thompson @param op CeedOperator 7557a982d89SJeremy L. Thompson 7567a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7577a982d89SJeremy L. Thompson 7587a982d89SJeremy L. Thompson @ref Backend 7597a982d89SJeremy L. Thompson **/ 7607a982d89SJeremy L. Thompson 7617a982d89SJeremy L. Thompson int CeedOperatorSetSetupDone(CeedOperator op) { 762e15f9bd0SJeremy L Thompson op->backendsetup = true; 763e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7647a982d89SJeremy L. Thompson } 7657a982d89SJeremy L. Thompson 7667a982d89SJeremy L. Thompson /** 7677a982d89SJeremy L. Thompson @brief Get the CeedOperatorFields of a CeedOperator 7687a982d89SJeremy L. Thompson 7697a982d89SJeremy L. Thompson @param op CeedOperator 7707a982d89SJeremy L. Thompson @param[out] inputfields Variable to store inputfields 7717a982d89SJeremy L. Thompson @param[out] outputfields Variable to store outputfields 7727a982d89SJeremy L. Thompson 7737a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7747a982d89SJeremy L. Thompson 7757a982d89SJeremy L. Thompson @ref Backend 7767a982d89SJeremy L. Thompson **/ 7777a982d89SJeremy L. Thompson 7787a982d89SJeremy L. Thompson int CeedOperatorGetFields(CeedOperator op, CeedOperatorField **inputfields, 7797a982d89SJeremy L. Thompson CeedOperatorField **outputfields) { 7807a982d89SJeremy L. Thompson if (op->composite) 7817a982d89SJeremy L. Thompson // LCOV_EXCL_START 782e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_MINOR, 783e15f9bd0SJeremy L Thompson "Not defined for composite operator"); 7847a982d89SJeremy L. Thompson // LCOV_EXCL_STOP 7857a982d89SJeremy L. Thompson 7867a982d89SJeremy L. Thompson if (inputfields) *inputfields = op->inputfields; 7877a982d89SJeremy L. Thompson if (outputfields) *outputfields = op->outputfields; 788e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 7897a982d89SJeremy L. Thompson } 7907a982d89SJeremy L. Thompson 7917a982d89SJeremy L. Thompson /** 7927a982d89SJeremy L. Thompson @brief Get the CeedElemRestriction of a CeedOperatorField 7937a982d89SJeremy L. Thompson 7947a982d89SJeremy L. Thompson @param opfield CeedOperatorField 7957a982d89SJeremy L. Thompson @param[out] rstr Variable to store CeedElemRestriction 7967a982d89SJeremy L. Thompson 7977a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 7987a982d89SJeremy L. Thompson 7997a982d89SJeremy L. Thompson @ref Backend 8007a982d89SJeremy L. Thompson **/ 8017a982d89SJeremy L. Thompson 8027a982d89SJeremy L. Thompson int CeedOperatorFieldGetElemRestriction(CeedOperatorField opfield, 8037a982d89SJeremy L. Thompson CeedElemRestriction *rstr) { 8047a982d89SJeremy L. Thompson *rstr = opfield->Erestrict; 805e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8067a982d89SJeremy L. Thompson } 8077a982d89SJeremy L. Thompson 8087a982d89SJeremy L. Thompson /** 8097a982d89SJeremy L. Thompson @brief Get the CeedBasis of a CeedOperatorField 8107a982d89SJeremy L. Thompson 8117a982d89SJeremy L. Thompson @param opfield CeedOperatorField 8127a982d89SJeremy L. Thompson @param[out] basis Variable to store CeedBasis 8137a982d89SJeremy L. Thompson 8147a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 8157a982d89SJeremy L. Thompson 8167a982d89SJeremy L. Thompson @ref Backend 8177a982d89SJeremy L. Thompson **/ 8187a982d89SJeremy L. Thompson 8197a982d89SJeremy L. Thompson int CeedOperatorFieldGetBasis(CeedOperatorField opfield, CeedBasis *basis) { 8207a982d89SJeremy L. Thompson *basis = opfield->basis; 821e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8227a982d89SJeremy L. Thompson } 8237a982d89SJeremy L. Thompson 8247a982d89SJeremy L. Thompson /** 8257a982d89SJeremy L. Thompson @brief Get the CeedVector of a CeedOperatorField 8267a982d89SJeremy L. Thompson 8277a982d89SJeremy L. Thompson @param opfield CeedOperatorField 8287a982d89SJeremy L. Thompson @param[out] vec Variable to store CeedVector 8297a982d89SJeremy L. Thompson 8307a982d89SJeremy L. Thompson @return An error code: 0 - success, otherwise - failure 8317a982d89SJeremy L. Thompson 8327a982d89SJeremy L. Thompson @ref Backend 8337a982d89SJeremy L. Thompson **/ 8347a982d89SJeremy L. Thompson 8357a982d89SJeremy L. Thompson int CeedOperatorFieldGetVector(CeedOperatorField opfield, CeedVector *vec) { 8367a982d89SJeremy L. Thompson *vec = opfield->vec; 837e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8387a982d89SJeremy L. Thompson } 8397a982d89SJeremy L. Thompson 8407a982d89SJeremy L. Thompson /// @} 8417a982d89SJeremy L. Thompson 8427a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 8437a982d89SJeremy L. Thompson /// CeedOperator Public API 8447a982d89SJeremy L. Thompson /// ---------------------------------------------------------------------------- 8457a982d89SJeremy L. Thompson /// @addtogroup CeedOperatorUser 846dfdf5a53Sjeremylt /// @{ 847d7b241e6Sjeremylt 848d7b241e6Sjeremylt /** 8490219ea01SJeremy L Thompson @brief Create a CeedOperator and associate a CeedQFunction. A CeedBasis and 8500219ea01SJeremy L Thompson CeedElemRestriction can be associated with CeedQFunction fields with 8510219ea01SJeremy L Thompson \ref CeedOperatorSetField. 852d7b241e6Sjeremylt 853b11c1e72Sjeremylt @param ceed A Ceed object where the CeedOperator will be created 854d7b241e6Sjeremylt @param qf QFunction defining the action of the operator at quadrature points 85534138859Sjeremylt @param dqf QFunction defining the action of the Jacobian of @a qf (or 8564cc79fe7SJed Brown @ref CEED_QFUNCTION_NONE) 857d7b241e6Sjeremylt @param dqfT QFunction defining the action of the transpose of the Jacobian 8584cc79fe7SJed Brown of @a qf (or @ref CEED_QFUNCTION_NONE) 859b11c1e72Sjeremylt @param[out] op Address of the variable where the newly created 860b11c1e72Sjeremylt CeedOperator will be stored 861b11c1e72Sjeremylt 862b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 863dfdf5a53Sjeremylt 8647a982d89SJeremy L. Thompson @ref User 865d7b241e6Sjeremylt */ 866d7b241e6Sjeremylt int CeedOperatorCreate(Ceed ceed, CeedQFunction qf, CeedQFunction dqf, 867d7b241e6Sjeremylt CeedQFunction dqfT, CeedOperator *op) { 868d7b241e6Sjeremylt int ierr; 869d7b241e6Sjeremylt 8705fe0d4faSjeremylt if (!ceed->OperatorCreate) { 8715fe0d4faSjeremylt Ceed delegate; 872aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 8735fe0d4faSjeremylt 8745fe0d4faSjeremylt if (!delegate) 875c042f62fSJeremy L Thompson // LCOV_EXCL_START 876e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 877e15f9bd0SJeremy L Thompson "Backend does not support OperatorCreate"); 878c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 8795fe0d4faSjeremylt 8805fe0d4faSjeremylt ierr = CeedOperatorCreate(delegate, qf, dqf, dqfT, op); CeedChk(ierr); 881e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8825fe0d4faSjeremylt } 8835fe0d4faSjeremylt 884b3b7035fSJeremy L Thompson if (!qf || qf == CEED_QFUNCTION_NONE) 885b3b7035fSJeremy L Thompson // LCOV_EXCL_START 886e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 887e15f9bd0SJeremy L Thompson "Operator must have a valid QFunction."); 888b3b7035fSJeremy L Thompson // LCOV_EXCL_STOP 889d7b241e6Sjeremylt ierr = CeedCalloc(1, op); CeedChk(ierr); 890d7b241e6Sjeremylt (*op)->ceed = ceed; 891d7b241e6Sjeremylt ceed->refcount++; 892d7b241e6Sjeremylt (*op)->refcount = 1; 893d7b241e6Sjeremylt (*op)->qf = qf; 894d7b241e6Sjeremylt qf->refcount++; 895442e7f0bSjeremylt if (dqf && dqf != CEED_QFUNCTION_NONE) { 896d7b241e6Sjeremylt (*op)->dqf = dqf; 897442e7f0bSjeremylt dqf->refcount++; 898442e7f0bSjeremylt } 899442e7f0bSjeremylt if (dqfT && dqfT != CEED_QFUNCTION_NONE) { 900d7b241e6Sjeremylt (*op)->dqfT = dqfT; 901442e7f0bSjeremylt dqfT->refcount++; 902442e7f0bSjeremylt } 903fe2413ffSjeremylt ierr = CeedCalloc(16, &(*op)->inputfields); CeedChk(ierr); 904fe2413ffSjeremylt ierr = CeedCalloc(16, &(*op)->outputfields); CeedChk(ierr); 905d7b241e6Sjeremylt ierr = ceed->OperatorCreate(*op); CeedChk(ierr); 906e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 907d7b241e6Sjeremylt } 908d7b241e6Sjeremylt 909d7b241e6Sjeremylt /** 91052d6035fSJeremy L Thompson @brief Create an operator that composes the action of several operators 91152d6035fSJeremy L Thompson 91252d6035fSJeremy L Thompson @param ceed A Ceed object where the CeedOperator will be created 91352d6035fSJeremy L Thompson @param[out] op Address of the variable where the newly created 91452d6035fSJeremy L Thompson Composite CeedOperator will be stored 91552d6035fSJeremy L Thompson 91652d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 91752d6035fSJeremy L Thompson 9187a982d89SJeremy L. Thompson @ref User 91952d6035fSJeremy L Thompson */ 92052d6035fSJeremy L Thompson int CeedCompositeOperatorCreate(Ceed ceed, CeedOperator *op) { 92152d6035fSJeremy L Thompson int ierr; 92252d6035fSJeremy L Thompson 92352d6035fSJeremy L Thompson if (!ceed->CompositeOperatorCreate) { 92452d6035fSJeremy L Thompson Ceed delegate; 925aefd8378Sjeremylt ierr = CeedGetObjectDelegate(ceed, &delegate, "Operator"); CeedChk(ierr); 92652d6035fSJeremy L Thompson 927250756a7Sjeremylt if (delegate) { 92852d6035fSJeremy L Thompson ierr = CeedCompositeOperatorCreate(delegate, op); CeedChk(ierr); 929e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 93052d6035fSJeremy L Thompson } 931250756a7Sjeremylt } 93252d6035fSJeremy L Thompson 93352d6035fSJeremy L Thompson ierr = CeedCalloc(1, op); CeedChk(ierr); 93452d6035fSJeremy L Thompson (*op)->ceed = ceed; 93552d6035fSJeremy L Thompson ceed->refcount++; 93652d6035fSJeremy L Thompson (*op)->composite = true; 93752d6035fSJeremy L Thompson ierr = CeedCalloc(16, &(*op)->suboperators); CeedChk(ierr); 938250756a7Sjeremylt 939250756a7Sjeremylt if (ceed->CompositeOperatorCreate) { 94052d6035fSJeremy L Thompson ierr = ceed->CompositeOperatorCreate(*op); CeedChk(ierr); 941250756a7Sjeremylt } 942e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 94352d6035fSJeremy L Thompson } 94452d6035fSJeremy L Thompson 94552d6035fSJeremy L Thompson /** 946b11c1e72Sjeremylt @brief Provide a field to a CeedOperator for use by its CeedQFunction 947d7b241e6Sjeremylt 948d7b241e6Sjeremylt This function is used to specify both active and passive fields to a 949d7b241e6Sjeremylt CeedOperator. For passive fields, a vector @arg v must be provided. Passive 950d7b241e6Sjeremylt fields can inputs or outputs (updated in-place when operator is applied). 951d7b241e6Sjeremylt 952d7b241e6Sjeremylt Active fields must be specified using this function, but their data (in a 953d7b241e6Sjeremylt CeedVector) is passed in CeedOperatorApply(). There can be at most one active 954d7b241e6Sjeremylt input and at most one active output. 955d7b241e6Sjeremylt 9568c91a0c9SJeremy L Thompson @param op CeedOperator on which to provide the field 9578795c945Sjeremylt @param fieldname Name of the field (to be matched with the name used by 9588795c945Sjeremylt CeedQFunction) 959b11c1e72Sjeremylt @param r CeedElemRestriction 9604cc79fe7SJed Brown @param b CeedBasis in which the field resides or @ref CEED_BASIS_COLLOCATED 961b11c1e72Sjeremylt if collocated with quadrature points 9624cc79fe7SJed Brown @param v CeedVector to be used by CeedOperator or @ref CEED_VECTOR_ACTIVE 9634cc79fe7SJed Brown if field is active or @ref CEED_VECTOR_NONE if using 9644cc79fe7SJed Brown @ref CEED_EVAL_WEIGHT in the QFunction 965b11c1e72Sjeremylt 966b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 967dfdf5a53Sjeremylt 9687a982d89SJeremy L. Thompson @ref User 969b11c1e72Sjeremylt **/ 970d7b241e6Sjeremylt int CeedOperatorSetField(CeedOperator op, const char *fieldname, 971a8d32208Sjeremylt CeedElemRestriction r, CeedBasis b, CeedVector v) { 972d7b241e6Sjeremylt int ierr; 97352d6035fSJeremy L Thompson if (op->composite) 974c042f62fSJeremy L Thompson // LCOV_EXCL_START 975*e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 976e15f9bd0SJeremy L Thompson "Cannot add field to composite operator."); 977c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 9788b067b84SJed Brown if (!r) 979c042f62fSJeremy L Thompson // LCOV_EXCL_START 980*e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 981c042f62fSJeremy L Thompson "ElemRestriction r for field \"%s\" must be non-NULL.", 982c042f62fSJeremy L Thompson fieldname); 983c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 9848b067b84SJed Brown if (!b) 985c042f62fSJeremy L Thompson // LCOV_EXCL_START 986*e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 987e15f9bd0SJeremy L Thompson "Basis b for field \"%s\" must be non-NULL.", 988c042f62fSJeremy L Thompson fieldname); 989c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 9908b067b84SJed Brown if (!v) 991c042f62fSJeremy L Thompson // LCOV_EXCL_START 992*e1e9e29dSJed Brown return CeedError(op->ceed, CEED_ERROR_INCOMPATIBLE, 993e15f9bd0SJeremy L Thompson "Vector v for field \"%s\" must be non-NULL.", 994c042f62fSJeremy L Thompson fieldname); 995c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 99652d6035fSJeremy L Thompson 997d7b241e6Sjeremylt CeedInt numelements; 998d7b241e6Sjeremylt ierr = CeedElemRestrictionGetNumElements(r, &numelements); CeedChk(ierr); 99915910d16Sjeremylt if (r != CEED_ELEMRESTRICTION_NONE && op->hasrestriction && 100015910d16Sjeremylt op->numelements != numelements) 1001c042f62fSJeremy L Thompson // LCOV_EXCL_START 1002e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 10031d102b48SJeremy L Thompson "ElemRestriction with %d elements incompatible with prior " 10041d102b48SJeremy L Thompson "%d elements", numelements, op->numelements); 1005c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1006d7b241e6Sjeremylt 1007d7b241e6Sjeremylt CeedInt numqpoints; 1008e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 1009d7b241e6Sjeremylt ierr = CeedBasisGetNumQuadraturePoints(b, &numqpoints); CeedChk(ierr); 1010d7b241e6Sjeremylt if (op->numqpoints && op->numqpoints != numqpoints) 1011c042f62fSJeremy L Thompson // LCOV_EXCL_START 1012e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_DIMENSION, 1013e15f9bd0SJeremy L Thompson "Basis with %d quadrature points " 10141d102b48SJeremy L Thompson "incompatible with prior %d points", numqpoints, 10151d102b48SJeremy L Thompson op->numqpoints); 1016c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1017d7b241e6Sjeremylt } 101815910d16Sjeremylt CeedQFunctionField qfield; 1019d1bcdac9Sjeremylt CeedOperatorField *ofield; 1020d7b241e6Sjeremylt for (CeedInt i=0; i<op->qf->numinputfields; i++) { 1021fe2413ffSjeremylt if (!strcmp(fieldname, (*op->qf->inputfields[i]).fieldname)) { 102215910d16Sjeremylt qfield = op->qf->inputfields[i]; 1023d7b241e6Sjeremylt ofield = &op->inputfields[i]; 1024d7b241e6Sjeremylt goto found; 1025d7b241e6Sjeremylt } 1026d7b241e6Sjeremylt } 1027d7b241e6Sjeremylt for (CeedInt i=0; i<op->qf->numoutputfields; i++) { 1028fe2413ffSjeremylt if (!strcmp(fieldname, (*op->qf->outputfields[i]).fieldname)) { 1029e15f9bd0SJeremy L Thompson qfield = op->qf->outputfields[i]; 1030d7b241e6Sjeremylt ofield = &op->outputfields[i]; 1031d7b241e6Sjeremylt goto found; 1032d7b241e6Sjeremylt } 1033d7b241e6Sjeremylt } 1034c042f62fSJeremy L Thompson // LCOV_EXCL_START 1035e15f9bd0SJeremy L Thompson return CeedError(op->ceed, CEED_ERROR_INCOMPLETE, 1036e15f9bd0SJeremy L Thompson "QFunction has no knowledge of field '%s'", 1037d7b241e6Sjeremylt fieldname); 1038c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 1039d7b241e6Sjeremylt found: 1040e15f9bd0SJeremy L Thompson ierr = CeedOperatorCheckField(op->ceed, qfield, r, b); CeedChk(ierr); 1041fe2413ffSjeremylt ierr = CeedCalloc(1, ofield); CeedChk(ierr); 1042e15f9bd0SJeremy L Thompson 1043e15f9bd0SJeremy L Thompson (*ofield)->vec = v; 1044e15f9bd0SJeremy L Thompson if (v != CEED_VECTOR_ACTIVE && v != CEED_VECTOR_NONE) { 1045e15f9bd0SJeremy L Thompson v->refcount += 1; 1046e15f9bd0SJeremy L Thompson } 1047e15f9bd0SJeremy L Thompson 1048fe2413ffSjeremylt (*ofield)->Erestrict = r; 104971352a93Sjeremylt r->refcount += 1; 1050e15f9bd0SJeremy L Thompson if (r != CEED_ELEMRESTRICTION_NONE) { 1051e15f9bd0SJeremy L Thompson op->numelements = numelements; 1052e15f9bd0SJeremy L Thompson op->hasrestriction = true; // Restriction set, but numelements may be 0 1053e15f9bd0SJeremy L Thompson } 1054d99fa3c5SJeremy L Thompson 1055e15f9bd0SJeremy L Thompson (*ofield)->basis = b; 1056e15f9bd0SJeremy L Thompson if (b != CEED_BASIS_COLLOCATED) { 1057e15f9bd0SJeremy L Thompson op->numqpoints = numqpoints; 1058e15f9bd0SJeremy L Thompson b->refcount += 1; 1059e15f9bd0SJeremy L Thompson } 1060e15f9bd0SJeremy L Thompson 1061e15f9bd0SJeremy L Thompson op->nfields += 1; 1062d99fa3c5SJeremy L Thompson size_t len = strlen(fieldname); 1063d99fa3c5SJeremy L Thompson char *tmp; 1064d99fa3c5SJeremy L Thompson ierr = CeedCalloc(len+1, &tmp); CeedChk(ierr); 1065d99fa3c5SJeremy L Thompson memcpy(tmp, fieldname, len+1); 1066d99fa3c5SJeremy L Thompson (*ofield)->fieldname = tmp; 1067e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1068d7b241e6Sjeremylt } 1069d7b241e6Sjeremylt 1070d7b241e6Sjeremylt /** 107152d6035fSJeremy L Thompson @brief Add a sub-operator to a composite CeedOperator 1072288c0443SJeremy L Thompson 107334138859Sjeremylt @param[out] compositeop Composite CeedOperator 107434138859Sjeremylt @param subop Sub-operator CeedOperator 107552d6035fSJeremy L Thompson 107652d6035fSJeremy L Thompson @return An error code: 0 - success, otherwise - failure 107752d6035fSJeremy L Thompson 10787a982d89SJeremy L. Thompson @ref User 107952d6035fSJeremy L Thompson */ 1080692c2638Sjeremylt int CeedCompositeOperatorAddSub(CeedOperator compositeop, CeedOperator subop) { 108152d6035fSJeremy L Thompson if (!compositeop->composite) 1082c042f62fSJeremy L Thompson // LCOV_EXCL_START 1083e15f9bd0SJeremy L Thompson return CeedError(compositeop->ceed, CEED_ERROR_MINOR, 1084e2f04181SAndrew T. Barker "CeedOperator is not a composite operator"); 1085c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 108652d6035fSJeremy L Thompson 108752d6035fSJeremy L Thompson if (compositeop->numsub == CEED_COMPOSITE_MAX) 1088c042f62fSJeremy L Thompson // LCOV_EXCL_START 1089e15f9bd0SJeremy L Thompson return CeedError(compositeop->ceed, CEED_ERROR_UNSUPPORTED, 1090e15f9bd0SJeremy L Thompson "Cannot add additional suboperators"); 1091c042f62fSJeremy L Thompson // LCOV_EXCL_STOP 109252d6035fSJeremy L Thompson 109352d6035fSJeremy L Thompson compositeop->suboperators[compositeop->numsub] = subop; 109452d6035fSJeremy L Thompson subop->refcount++; 109552d6035fSJeremy L Thompson compositeop->numsub++; 1096e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 109752d6035fSJeremy L Thompson } 109852d6035fSJeremy L Thompson 109952d6035fSJeremy L Thompson /** 11001d102b48SJeremy L Thompson @brief Assemble a linear CeedQFunction associated with a CeedOperator 11011d102b48SJeremy L Thompson 11021d102b48SJeremy L Thompson This returns a CeedVector containing a matrix at each quadrature point 11031d102b48SJeremy L Thompson providing the action of the CeedQFunction associated with the CeedOperator. 11041d102b48SJeremy L Thompson The vector 'assembled' is of shape 11051d102b48SJeremy L Thompson [num_elements, num_input_fields, num_output_fields, num_quad_points] 11061d102b48SJeremy L Thompson and contains column-major matrices representing the action of the 11071d102b48SJeremy L Thompson CeedQFunction for a corresponding quadrature point on an element. Inputs and 11081d102b48SJeremy L Thompson outputs are in the order provided by the user when adding CeedOperator fields. 11094cc79fe7SJed Brown For example, a CeedQFunction with inputs 'u' and 'gradu' and outputs 'gradv' and 11101d102b48SJeremy L Thompson 'v', provided in that order, would result in an assembled QFunction that 11111d102b48SJeremy L Thompson consists of (1 + dim) x (dim + 1) matrices at each quadrature point acting 11121d102b48SJeremy L Thompson on the input [u, du_0, du_1] and producing the output [dv_0, dv_1, v]. 11131d102b48SJeremy L Thompson 11141d102b48SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 11151d102b48SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedQFunction at 11161d102b48SJeremy L Thompson quadrature points 11171d102b48SJeremy L Thompson @param[out] rstr CeedElemRestriction for CeedVector containing assembled 11181d102b48SJeremy L Thompson CeedQFunction 11191d102b48SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 11204cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 11211d102b48SJeremy L Thompson 11221d102b48SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 11231d102b48SJeremy L Thompson 11247a982d89SJeremy L. Thompson @ref User 11251d102b48SJeremy L Thompson **/ 112680ac2e43SJeremy L Thompson int CeedOperatorLinearAssembleQFunction(CeedOperator op, CeedVector *assembled, 11277f823360Sjeremylt CeedElemRestriction *rstr, 11287f823360Sjeremylt CeedRequest *request) { 11291d102b48SJeremy L Thompson int ierr; 1130e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 11311d102b48SJeremy L Thompson 11327172caadSjeremylt // Backend version 113380ac2e43SJeremy L Thompson if (op->LinearAssembleQFunction) { 1134e2f04181SAndrew T. Barker return op->LinearAssembleQFunction(op, assembled, rstr, request); 11355107b09fSJeremy L Thompson } else { 11365107b09fSJeremy L Thompson // Fallback to reference Ceed 11375107b09fSJeremy L Thompson if (!op->opfallback) { 11385107b09fSJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 11395107b09fSJeremy L Thompson } 11405107b09fSJeremy L Thompson // Assemble 1141e2f04181SAndrew T. Barker return CeedOperatorLinearAssembleQFunction(op->opfallback, assembled, 1142e2f04181SAndrew T. Barker rstr, request); 11435107b09fSJeremy L Thompson } 11441d102b48SJeremy L Thompson } 11451d102b48SJeremy L Thompson 11461d102b48SJeremy L Thompson /** 1147d965c7a7SJeremy L Thompson @brief Assemble the diagonal of a square linear CeedOperator 1148b7ec98d8SJeremy L Thompson 11499e9210b8SJeremy L Thompson This overwrites a CeedVector with the diagonal of a linear CeedOperator. 1150b7ec98d8SJeremy L Thompson 1151c04a41a7SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 1152c04a41a7SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 1153d965c7a7SJeremy L Thompson 1154b7ec98d8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 1155b7ec98d8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator diagonal 1156b7ec98d8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 11574cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 1158b7ec98d8SJeremy L Thompson 1159b7ec98d8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1160b7ec98d8SJeremy L Thompson 11617a982d89SJeremy L. Thompson @ref User 1162b7ec98d8SJeremy L Thompson **/ 11632bba3ffaSJeremy L Thompson int CeedOperatorLinearAssembleDiagonal(CeedOperator op, CeedVector assembled, 11647f823360Sjeremylt CeedRequest *request) { 1165b7ec98d8SJeremy L Thompson int ierr; 1166e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1167b7ec98d8SJeremy L Thompson 1168b7ec98d8SJeremy L Thompson // Use backend version, if available 116980ac2e43SJeremy L Thompson if (op->LinearAssembleDiagonal) { 1170e2f04181SAndrew T. Barker return op->LinearAssembleDiagonal(op, assembled, request); 11719e9210b8SJeremy L Thompson } else if (op->LinearAssembleAddDiagonal) { 11729e9210b8SJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 11739e9210b8SJeremy L Thompson return CeedOperatorLinearAssembleAddDiagonal(op, assembled, request); 11749e9210b8SJeremy L Thompson } else { 11759e9210b8SJeremy L Thompson // Fallback to reference Ceed 11769e9210b8SJeremy L Thompson if (!op->opfallback) { 11779e9210b8SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 11789e9210b8SJeremy L Thompson } 11799e9210b8SJeremy L Thompson // Assemble 1180e2f04181SAndrew T. Barker return CeedOperatorLinearAssembleDiagonal(op->opfallback, assembled, 1181e2f04181SAndrew T. Barker request); 11829e9210b8SJeremy L Thompson } 11839e9210b8SJeremy L Thompson } 11849e9210b8SJeremy L Thompson 11859e9210b8SJeremy L Thompson /** 11869e9210b8SJeremy L Thompson @brief Assemble the diagonal of a square linear CeedOperator 11879e9210b8SJeremy L Thompson 11889e9210b8SJeremy L Thompson This sums into a CeedVector the diagonal of a linear CeedOperator. 11899e9210b8SJeremy L Thompson 11909e9210b8SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 11919e9210b8SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 11929e9210b8SJeremy L Thompson 11939e9210b8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 11949e9210b8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator diagonal 11959e9210b8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 11969e9210b8SJeremy L Thompson @ref CEED_REQUEST_IMMEDIATE 11979e9210b8SJeremy L Thompson 11989e9210b8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 11999e9210b8SJeremy L Thompson 12009e9210b8SJeremy L Thompson @ref User 12019e9210b8SJeremy L Thompson **/ 12029e9210b8SJeremy L Thompson int CeedOperatorLinearAssembleAddDiagonal(CeedOperator op, CeedVector assembled, 12039e9210b8SJeremy L Thompson CeedRequest *request) { 12049e9210b8SJeremy L Thompson int ierr; 1205e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 12069e9210b8SJeremy L Thompson 12079e9210b8SJeremy L Thompson // Use backend version, if available 12089e9210b8SJeremy L Thompson if (op->LinearAssembleAddDiagonal) { 1209e2f04181SAndrew T. Barker return op->LinearAssembleAddDiagonal(op, assembled, request); 12107172caadSjeremylt } else { 12117172caadSjeremylt // Fallback to reference Ceed 12127172caadSjeremylt if (!op->opfallback) { 12137172caadSjeremylt ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1214b7ec98d8SJeremy L Thompson } 12157172caadSjeremylt // Assemble 1216e2f04181SAndrew T. Barker return CeedOperatorLinearAssembleAddDiagonal(op->opfallback, assembled, 1217e2f04181SAndrew T. Barker request); 1218b7ec98d8SJeremy L Thompson } 1219b7ec98d8SJeremy L Thompson } 1220b7ec98d8SJeremy L Thompson 1221b7ec98d8SJeremy L Thompson /** 1222d965c7a7SJeremy L Thompson @brief Assemble the point block diagonal of a square linear CeedOperator 1223d965c7a7SJeremy L Thompson 12249e9210b8SJeremy L Thompson This overwrites a CeedVector with the point block diagonal of a linear 1225d965c7a7SJeremy L Thompson CeedOperator. 1226d965c7a7SJeremy L Thompson 1227c04a41a7SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 1228c04a41a7SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 1229d965c7a7SJeremy L Thompson 1230d965c7a7SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 1231d965c7a7SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator point block 1232d965c7a7SJeremy L Thompson diagonal, provided in row-major form with an 1233d965c7a7SJeremy L Thompson @a ncomp * @a ncomp block at each node. The dimensions 1234d965c7a7SJeremy L Thompson of this vector are derived from the active vector 1235d965c7a7SJeremy L Thompson for the CeedOperator. The array has shape 1236d965c7a7SJeremy L Thompson [nodes, component out, component in]. 1237d965c7a7SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 1238d965c7a7SJeremy L Thompson CEED_REQUEST_IMMEDIATE 1239d965c7a7SJeremy L Thompson 1240d965c7a7SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1241d965c7a7SJeremy L Thompson 1242d965c7a7SJeremy L Thompson @ref User 1243d965c7a7SJeremy L Thompson **/ 124480ac2e43SJeremy L Thompson int CeedOperatorLinearAssemblePointBlockDiagonal(CeedOperator op, 12452bba3ffaSJeremy L Thompson CeedVector assembled, CeedRequest *request) { 1246d965c7a7SJeremy L Thompson int ierr; 1247e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1248d965c7a7SJeremy L Thompson 1249d965c7a7SJeremy L Thompson // Use backend version, if available 125080ac2e43SJeremy L Thompson if (op->LinearAssemblePointBlockDiagonal) { 1251e2f04181SAndrew T. Barker return op->LinearAssemblePointBlockDiagonal(op, assembled, request); 12529e9210b8SJeremy L Thompson } else if (op->LinearAssembleAddPointBlockDiagonal) { 12539e9210b8SJeremy L Thompson ierr = CeedVectorSetValue(assembled, 0.0); CeedChk(ierr); 12549e9210b8SJeremy L Thompson return CeedOperatorLinearAssembleAddPointBlockDiagonal(op, assembled, 12559e9210b8SJeremy L Thompson request); 1256d965c7a7SJeremy L Thompson } else { 1257d965c7a7SJeremy L Thompson // Fallback to reference Ceed 1258d965c7a7SJeremy L Thompson if (!op->opfallback) { 1259d965c7a7SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1260d965c7a7SJeremy L Thompson } 1261d965c7a7SJeremy L Thompson // Assemble 1262e2f04181SAndrew T. Barker return CeedOperatorLinearAssemblePointBlockDiagonal(op->opfallback, 1263e2f04181SAndrew T. Barker assembled, request); 12649e9210b8SJeremy L Thompson } 12659e9210b8SJeremy L Thompson } 12669e9210b8SJeremy L Thompson 12679e9210b8SJeremy L Thompson /** 12689e9210b8SJeremy L Thompson @brief Assemble the point block diagonal of a square linear CeedOperator 12699e9210b8SJeremy L Thompson 12709e9210b8SJeremy L Thompson This sums into a CeedVector with the point block diagonal of a linear 12719e9210b8SJeremy L Thompson CeedOperator. 12729e9210b8SJeremy L Thompson 12739e9210b8SJeremy L Thompson Note: Currently only non-composite CeedOperators with a single field and 12749e9210b8SJeremy L Thompson composite CeedOperators with single field sub-operators are supported. 12759e9210b8SJeremy L Thompson 12769e9210b8SJeremy L Thompson @param op CeedOperator to assemble CeedQFunction 12779e9210b8SJeremy L Thompson @param[out] assembled CeedVector to store assembled CeedOperator point block 12789e9210b8SJeremy L Thompson diagonal, provided in row-major form with an 12799e9210b8SJeremy L Thompson @a ncomp * @a ncomp block at each node. The dimensions 12809e9210b8SJeremy L Thompson of this vector are derived from the active vector 12819e9210b8SJeremy L Thompson for the CeedOperator. The array has shape 12829e9210b8SJeremy L Thompson [nodes, component out, component in]. 12839e9210b8SJeremy L Thompson @param request Address of CeedRequest for non-blocking completion, else 12849e9210b8SJeremy L Thompson CEED_REQUEST_IMMEDIATE 12859e9210b8SJeremy L Thompson 12869e9210b8SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 12879e9210b8SJeremy L Thompson 12889e9210b8SJeremy L Thompson @ref User 12899e9210b8SJeremy L Thompson **/ 12909e9210b8SJeremy L Thompson int CeedOperatorLinearAssembleAddPointBlockDiagonal(CeedOperator op, 12919e9210b8SJeremy L Thompson CeedVector assembled, CeedRequest *request) { 12929e9210b8SJeremy L Thompson int ierr; 1293e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 12949e9210b8SJeremy L Thompson 12959e9210b8SJeremy L Thompson // Use backend version, if available 12969e9210b8SJeremy L Thompson if (op->LinearAssembleAddPointBlockDiagonal) { 1297e2f04181SAndrew T. Barker return op->LinearAssembleAddPointBlockDiagonal(op, assembled, request); 12989e9210b8SJeremy L Thompson } else { 12999e9210b8SJeremy L Thompson // Fallback to reference Ceed 13009e9210b8SJeremy L Thompson if (!op->opfallback) { 13019e9210b8SJeremy L Thompson ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 13029e9210b8SJeremy L Thompson } 13039e9210b8SJeremy L Thompson // Assemble 1304e2f04181SAndrew T. Barker return CeedOperatorLinearAssembleAddPointBlockDiagonal(op->opfallback, 1305e2f04181SAndrew T. Barker assembled, request); 1306d965c7a7SJeremy L Thompson } 1307e2f04181SAndrew T. Barker } 1308e2f04181SAndrew T. Barker 1309e2f04181SAndrew T. Barker /** 1310e2f04181SAndrew T. Barker @brief Build nonzero pattern for non-composite operator. 1311e2f04181SAndrew T. Barker 1312e2f04181SAndrew T. Barker Users should generally use CeedOperatorLinearAssembleSymbolic() 1313e2f04181SAndrew T. Barker 1314e2f04181SAndrew T. Barker @ref Developer 1315e2f04181SAndrew T. Barker **/ 1316e2f04181SAndrew T. Barker int CeedSingleOperatorAssembleSymbolic(CeedOperator op, CeedInt offset, 1317e2f04181SAndrew T. Barker CeedInt *rows, CeedInt *cols) { 1318e2f04181SAndrew T. Barker int ierr; 1319e2f04181SAndrew T. Barker Ceed ceed = op->ceed; 1320e2f04181SAndrew T. Barker if (op->composite) 1321e2f04181SAndrew T. Barker // LCOV_EXCL_START 1322e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 1323e2f04181SAndrew T. Barker "Composite operator not supported"); 1324e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1325e2f04181SAndrew T. Barker 1326e2f04181SAndrew T. Barker CeedElemRestriction rstrin; 1327e2f04181SAndrew T. Barker ierr = CeedOperatorGetActiveElemRestriction(op, &rstrin); CeedChk(ierr); 1328e2f04181SAndrew T. Barker CeedInt nelem, elemsize, nnodes, ncomp; 1329e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetNumElements(rstrin, &nelem); CeedChk(ierr); 1330e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetElementSize(rstrin, &elemsize); CeedChk(ierr); 1331e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetLVectorSize(rstrin, &nnodes); CeedChk(ierr); 1332e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetNumComponents(rstrin, &ncomp); CeedChk(ierr); 1333e2f04181SAndrew T. Barker CeedInt layout_er[3]; 1334e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetELayout(rstrin, &layout_er); CeedChk(ierr); 1335e2f04181SAndrew T. Barker 1336e2f04181SAndrew T. Barker CeedInt local_nentries = elemsize*ncomp * elemsize*ncomp * nelem; 1337e2f04181SAndrew T. Barker 1338e2f04181SAndrew T. Barker // Determine elem_dof relation 1339e2f04181SAndrew T. Barker CeedVector index_vec; 1340e2f04181SAndrew T. Barker ierr = CeedVectorCreate(ceed, nnodes, &index_vec); CeedChk(ierr); 1341e2f04181SAndrew T. Barker CeedScalar *array; 1342e2f04181SAndrew T. Barker ierr = CeedVectorGetArray(index_vec, CEED_MEM_HOST, &array); CeedChk(ierr); 1343e2f04181SAndrew T. Barker for (CeedInt i = 0; i < nnodes; ++i) { 1344e2f04181SAndrew T. Barker array[i] = i; 1345e2f04181SAndrew T. Barker } 1346e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArray(index_vec, &array); CeedChk(ierr); 1347e2f04181SAndrew T. Barker CeedVector elem_dof; 1348e2f04181SAndrew T. Barker ierr = CeedVectorCreate(ceed, nelem * elemsize * ncomp, &elem_dof); 1349e2f04181SAndrew T. Barker CeedChk(ierr); 1350e2f04181SAndrew T. Barker ierr = CeedVectorSetValue(elem_dof, 0.0); CeedChk(ierr); 1351e2f04181SAndrew T. Barker CeedElemRestrictionApply(rstrin, CEED_NOTRANSPOSE, index_vec, 1352e2f04181SAndrew T. Barker elem_dof, CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 1353e2f04181SAndrew T. Barker const CeedScalar *elem_dof_a; 1354e2f04181SAndrew T. Barker ierr = CeedVectorGetArrayRead(elem_dof, CEED_MEM_HOST, &elem_dof_a); 1355e2f04181SAndrew T. Barker CeedChk(ierr); 1356e2f04181SAndrew T. Barker ierr = CeedVectorDestroy(&index_vec); CeedChk(ierr); 1357e2f04181SAndrew T. Barker 1358e2f04181SAndrew T. Barker // Determine i, j locations for element matrices 1359e2f04181SAndrew T. Barker CeedInt count = 0; 1360e2f04181SAndrew T. Barker for (int e = 0; e < nelem; ++e) { 1361e2f04181SAndrew T. Barker for (int compin = 0; compin < ncomp; ++compin) { 1362e2f04181SAndrew T. Barker for (int compout = 0; compout < ncomp; ++compout) { 1363e2f04181SAndrew T. Barker for (int i = 0; i < elemsize; ++i) { 1364e2f04181SAndrew T. Barker for (int j = 0; j < elemsize; ++j) { 1365e2f04181SAndrew T. Barker const CeedInt edof_index_row = (i)*layout_er[0] + 1366e2f04181SAndrew T. Barker (compout)*layout_er[1] + e*layout_er[2]; 1367e2f04181SAndrew T. Barker const CeedInt edof_index_col = (j)*layout_er[0] + 1368e2f04181SAndrew T. Barker (compin)*layout_er[1] + e*layout_er[2]; 1369e2f04181SAndrew T. Barker 1370e2f04181SAndrew T. Barker const CeedInt row = elem_dof_a[edof_index_row]; 1371e2f04181SAndrew T. Barker const CeedInt col = elem_dof_a[edof_index_col]; 1372e2f04181SAndrew T. Barker 1373e2f04181SAndrew T. Barker rows[offset + count] = row; 1374e2f04181SAndrew T. Barker cols[offset + count] = col; 1375e2f04181SAndrew T. Barker count++; 1376e2f04181SAndrew T. Barker } 1377e2f04181SAndrew T. Barker } 1378e2f04181SAndrew T. Barker } 1379e2f04181SAndrew T. Barker } 1380e2f04181SAndrew T. Barker } 1381e2f04181SAndrew T. Barker if (count != local_nentries) 1382e2f04181SAndrew T. Barker // LCOV_EXCL_START 1383e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_MAJOR, "Error computing assembled entries"); 1384e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1385e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArrayRead(elem_dof, &elem_dof_a); CeedChk(ierr); 1386e2f04181SAndrew T. Barker ierr = CeedVectorDestroy(&elem_dof); CeedChk(ierr); 1387e2f04181SAndrew T. Barker 1388e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1389e2f04181SAndrew T. Barker } 1390e2f04181SAndrew T. Barker 1391e2f04181SAndrew T. Barker /** 1392e2f04181SAndrew T. Barker @brief Assemble nonzero entries for non-composite operator 1393e2f04181SAndrew T. Barker 1394e2f04181SAndrew T. Barker Users should generally use CeedOperatorLinearAssemble() 1395e2f04181SAndrew T. Barker 1396e2f04181SAndrew T. Barker @ref Developer 1397e2f04181SAndrew T. Barker **/ 1398e2f04181SAndrew T. Barker int CeedSingleOperatorAssemble(CeedOperator op, CeedInt offset, 1399e2f04181SAndrew T. Barker CeedVector values) { 1400e2f04181SAndrew T. Barker int ierr; 1401e2f04181SAndrew T. Barker Ceed ceed = op->ceed;; 1402e2f04181SAndrew T. Barker if (op->composite) 1403e2f04181SAndrew T. Barker // LCOV_EXCL_START 1404e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, 1405e2f04181SAndrew T. Barker "Composite operator not supported"); 1406e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1407e2f04181SAndrew T. Barker 1408e2f04181SAndrew T. Barker // Assemble QFunction 1409e2f04181SAndrew T. Barker CeedQFunction qf; 1410e2f04181SAndrew T. Barker ierr = CeedOperatorGetQFunction(op, &qf); CeedChk(ierr); 1411e2f04181SAndrew T. Barker CeedInt numinputfields, numoutputfields; 1412e2f04181SAndrew T. Barker ierr= CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 1413e2f04181SAndrew T. Barker CeedChk(ierr); 1414e2f04181SAndrew T. Barker CeedVector assembledqf; 1415e2f04181SAndrew T. Barker CeedElemRestriction rstr_q; 1416e2f04181SAndrew T. Barker ierr = CeedOperatorLinearAssembleQFunction( 1417e2f04181SAndrew T. Barker op, &assembledqf, &rstr_q, CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 1418e2f04181SAndrew T. Barker 1419e2f04181SAndrew T. Barker CeedInt qflength; 1420e2f04181SAndrew T. Barker ierr = CeedVectorGetLength(assembledqf, &qflength); CeedChk(ierr); 1421e2f04181SAndrew T. Barker 1422e2f04181SAndrew T. Barker CeedOperatorField *input_fields; 1423e2f04181SAndrew T. Barker CeedOperatorField *output_fields; 1424e2f04181SAndrew T. Barker ierr = CeedOperatorGetFields(op, &input_fields, &output_fields); CeedChk(ierr); 1425e2f04181SAndrew T. Barker 1426e2f04181SAndrew T. Barker // Determine active input basis 1427e2f04181SAndrew T. Barker CeedQFunctionField *qffields; 1428e2f04181SAndrew T. Barker ierr = CeedQFunctionGetFields(qf, &qffields, NULL); CeedChk(ierr); 1429e2f04181SAndrew T. Barker CeedInt numemodein = 0, dim = 1; 1430e2f04181SAndrew T. Barker CeedEvalMode *emodein = NULL; 1431e2f04181SAndrew T. Barker CeedBasis basisin = NULL; 1432e2f04181SAndrew T. Barker CeedElemRestriction rstrin = NULL; 1433e2f04181SAndrew T. Barker for (CeedInt i=0; i<numinputfields; i++) { 1434e2f04181SAndrew T. Barker CeedVector vec; 1435e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetVector(input_fields[i], &vec); CeedChk(ierr); 1436e2f04181SAndrew T. Barker if (vec == CEED_VECTOR_ACTIVE) { 1437e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetBasis(input_fields[i], &basisin); 1438e2f04181SAndrew T. Barker CeedChk(ierr); 1439e2f04181SAndrew T. Barker ierr = CeedBasisGetDimension(basisin, &dim); CeedChk(ierr); 1440e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetElemRestriction(input_fields[i], &rstrin); 1441e2f04181SAndrew T. Barker CeedChk(ierr); 1442e2f04181SAndrew T. Barker CeedEvalMode emode; 1443e2f04181SAndrew T. Barker ierr = CeedQFunctionFieldGetEvalMode(qffields[i], &emode); 1444e2f04181SAndrew T. Barker CeedChk(ierr); 1445e2f04181SAndrew T. Barker switch (emode) { 1446e2f04181SAndrew T. Barker case CEED_EVAL_NONE: 1447e2f04181SAndrew T. Barker case CEED_EVAL_INTERP: 1448e2f04181SAndrew T. Barker ierr = CeedRealloc(numemodein + 1, &emodein); CeedChk(ierr); 1449e2f04181SAndrew T. Barker emodein[numemodein] = emode; 1450e2f04181SAndrew T. Barker numemodein += 1; 1451e2f04181SAndrew T. Barker break; 1452e2f04181SAndrew T. Barker case CEED_EVAL_GRAD: 1453e2f04181SAndrew T. Barker ierr = CeedRealloc(numemodein + dim, &emodein); CeedChk(ierr); 1454e2f04181SAndrew T. Barker for (CeedInt d=0; d<dim; d++) { 1455e2f04181SAndrew T. Barker emodein[numemodein+d] = emode; 1456e2f04181SAndrew T. Barker } 1457e2f04181SAndrew T. Barker numemodein += dim; 1458e2f04181SAndrew T. Barker break; 1459e2f04181SAndrew T. Barker case CEED_EVAL_WEIGHT: 1460e2f04181SAndrew T. Barker case CEED_EVAL_DIV: 1461e2f04181SAndrew T. Barker case CEED_EVAL_CURL: 1462e2f04181SAndrew T. Barker break; // Caught by QF Assembly 1463e2f04181SAndrew T. Barker } 1464e2f04181SAndrew T. Barker } 1465e2f04181SAndrew T. Barker } 1466e2f04181SAndrew T. Barker 1467e2f04181SAndrew T. Barker // Determine active output basis 1468e2f04181SAndrew T. Barker ierr = CeedQFunctionGetFields(qf, NULL, &qffields); CeedChk(ierr); 1469e2f04181SAndrew T. Barker CeedInt numemodeout = 0; 1470e2f04181SAndrew T. Barker CeedEvalMode *emodeout = NULL; 1471e2f04181SAndrew T. Barker CeedBasis basisout = NULL; 1472e2f04181SAndrew T. Barker CeedElemRestriction rstrout = NULL; 1473e2f04181SAndrew T. Barker for (CeedInt i=0; i<numoutputfields; i++) { 1474e2f04181SAndrew T. Barker CeedVector vec; 1475e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetVector(output_fields[i], &vec); CeedChk(ierr); 1476e2f04181SAndrew T. Barker if (vec == CEED_VECTOR_ACTIVE) { 1477e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetBasis(output_fields[i], &basisout); 1478e2f04181SAndrew T. Barker CeedChk(ierr); 1479e2f04181SAndrew T. Barker ierr = CeedOperatorFieldGetElemRestriction(output_fields[i], &rstrout); 1480e2f04181SAndrew T. Barker CeedChk(ierr); 1481e2f04181SAndrew T. Barker CeedEvalMode emode; 1482e2f04181SAndrew T. Barker ierr = CeedQFunctionFieldGetEvalMode(qffields[i], &emode); 1483e2f04181SAndrew T. Barker CeedChk(ierr); 1484e2f04181SAndrew T. Barker switch (emode) { 1485e2f04181SAndrew T. Barker case CEED_EVAL_NONE: 1486e2f04181SAndrew T. Barker case CEED_EVAL_INTERP: 1487e2f04181SAndrew T. Barker ierr = CeedRealloc(numemodeout + 1, &emodeout); CeedChk(ierr); 1488e2f04181SAndrew T. Barker emodeout[numemodeout] = emode; 1489e2f04181SAndrew T. Barker numemodeout += 1; 1490e2f04181SAndrew T. Barker break; 1491e2f04181SAndrew T. Barker case CEED_EVAL_GRAD: 1492e2f04181SAndrew T. Barker ierr = CeedRealloc(numemodeout + dim, &emodeout); CeedChk(ierr); 1493e2f04181SAndrew T. Barker for (CeedInt d=0; d<dim; d++) { 1494e2f04181SAndrew T. Barker emodeout[numemodeout+d] = emode; 1495e2f04181SAndrew T. Barker } 1496e2f04181SAndrew T. Barker numemodeout += dim; 1497e2f04181SAndrew T. Barker break; 1498e2f04181SAndrew T. Barker case CEED_EVAL_WEIGHT: 1499e2f04181SAndrew T. Barker case CEED_EVAL_DIV: 1500e2f04181SAndrew T. Barker case CEED_EVAL_CURL: 1501e2f04181SAndrew T. Barker break; // Caught by QF Assembly 1502e2f04181SAndrew T. Barker } 1503e2f04181SAndrew T. Barker } 1504e2f04181SAndrew T. Barker } 1505e2f04181SAndrew T. Barker 1506e2f04181SAndrew T. Barker CeedInt nelem, elemsize, nqpts, ncomp; 1507e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetNumElements(rstrin, &nelem); CeedChk(ierr); 1508e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetElementSize(rstrin, &elemsize); CeedChk(ierr); 1509e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetNumComponents(rstrin, &ncomp); CeedChk(ierr); 1510e2f04181SAndrew T. Barker ierr = CeedBasisGetNumQuadraturePoints(basisin, &nqpts); CeedChk(ierr); 1511e2f04181SAndrew T. Barker 1512e2f04181SAndrew T. Barker CeedInt local_nentries = elemsize*ncomp * elemsize*ncomp * nelem; 1513e2f04181SAndrew T. Barker 1514e2f04181SAndrew T. Barker // loop over elements and put in data structure 1515e2f04181SAndrew T. Barker const CeedScalar *interpin, *gradin; 1516e2f04181SAndrew T. Barker ierr = CeedBasisGetInterp(basisin, &interpin); CeedChk(ierr); 1517e2f04181SAndrew T. Barker ierr = CeedBasisGetGrad(basisin, &gradin); CeedChk(ierr); 1518e2f04181SAndrew T. Barker 1519e2f04181SAndrew T. Barker const CeedScalar *assembledqfarray; 1520e2f04181SAndrew T. Barker ierr = CeedVectorGetArrayRead(assembledqf, CEED_MEM_HOST, &assembledqfarray); 1521e2f04181SAndrew T. Barker CeedChk(ierr); 1522e2f04181SAndrew T. Barker 1523e2f04181SAndrew T. Barker CeedInt layout_qf[3]; 1524e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetELayout(rstr_q, &layout_qf); CeedChk(ierr); 1525e2f04181SAndrew T. Barker ierr = CeedElemRestrictionDestroy(&rstr_q); CeedChk(ierr); 1526e2f04181SAndrew T. Barker 1527e2f04181SAndrew T. Barker // we store Bmat_in, Bmat_out, BTD, elem_mat in row-major order 1528e2f04181SAndrew T. Barker CeedScalar Bmat_in[(nqpts * numemodein) * elemsize]; 1529e2f04181SAndrew T. Barker CeedScalar Bmat_out[(nqpts * numemodeout) * elemsize]; 1530e2f04181SAndrew T. Barker CeedScalar Dmat[numemodeout * numemodein * nqpts]; // logically 3-tensor 1531e2f04181SAndrew T. Barker CeedScalar BTD[elemsize * nqpts*numemodein]; 1532e2f04181SAndrew T. Barker CeedScalar elem_mat[elemsize * elemsize]; 1533e2f04181SAndrew T. Barker int count = 0; 1534e2f04181SAndrew T. Barker CeedScalar *vals; 1535e2f04181SAndrew T. Barker ierr = CeedVectorGetArray(values, CEED_MEM_HOST, &vals); CeedChk(ierr); 1536e2f04181SAndrew T. Barker for (int e = 0; e < nelem; ++e) { 1537e2f04181SAndrew T. Barker for (int compin = 0; compin < ncomp; ++compin) { 1538e2f04181SAndrew T. Barker for (int compout = 0; compout < ncomp; ++compout) { 1539e2f04181SAndrew T. Barker for (int ell = 0; ell < (nqpts * numemodein) * elemsize; ++ell) { 1540e2f04181SAndrew T. Barker Bmat_in[ell] = 0.0; 1541e2f04181SAndrew T. Barker } 1542e2f04181SAndrew T. Barker for (int ell = 0; ell < (nqpts * numemodeout) * elemsize; ++ell) { 1543e2f04181SAndrew T. Barker Bmat_out[ell] = 0.0; 1544e2f04181SAndrew T. Barker } 1545e2f04181SAndrew T. Barker // Store block-diagonal D matrix as collection of small dense blocks 1546e2f04181SAndrew T. Barker for (int ell = 0; ell < numemodein*numemodeout*nqpts; ++ell) { 1547e2f04181SAndrew T. Barker Dmat[ell] = 0.0; 1548e2f04181SAndrew T. Barker } 1549e2f04181SAndrew T. Barker // form element matrix itself (for each block component) 1550e2f04181SAndrew T. Barker for (int ell = 0; ell < elemsize*elemsize; ++ell) { 1551e2f04181SAndrew T. Barker elem_mat[ell] = 0.0; 1552e2f04181SAndrew T. Barker } 1553e2f04181SAndrew T. Barker for (int q = 0; q < nqpts; ++q) { 1554e2f04181SAndrew T. Barker for (int n = 0; n < elemsize; ++n) { 1555e2f04181SAndrew T. Barker CeedInt din = -1; 1556e2f04181SAndrew T. Barker for (int ein = 0; ein < numemodein; ++ein) { 1557e2f04181SAndrew T. Barker const int qq = numemodein*q; 1558e2f04181SAndrew T. Barker if (emodein[ein] == CEED_EVAL_INTERP) { 1559e2f04181SAndrew T. Barker Bmat_in[(qq+ein)*elemsize + n] += interpin[q * elemsize + n]; 1560e2f04181SAndrew T. Barker } else if (emodein[ein] == CEED_EVAL_GRAD) { 1561e2f04181SAndrew T. Barker din += 1; 1562e2f04181SAndrew T. Barker Bmat_in[(qq+ein)*elemsize + n] += 1563e2f04181SAndrew T. Barker gradin[(din*nqpts+q) * elemsize + n]; 1564e2f04181SAndrew T. Barker } else { 1565e2f04181SAndrew T. Barker // LCOV_EXCL_START 1566e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Not implemented!"); 1567e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1568e2f04181SAndrew T. Barker } 1569e2f04181SAndrew T. Barker } 1570e2f04181SAndrew T. Barker CeedInt dout = -1; 1571e2f04181SAndrew T. Barker for (int eout = 0; eout < numemodeout; ++eout) { 1572e2f04181SAndrew T. Barker const int qq = numemodeout*q; 1573e2f04181SAndrew T. Barker if (emodeout[eout] == CEED_EVAL_INTERP) { 1574e2f04181SAndrew T. Barker Bmat_out[(qq+eout)*elemsize + n] += interpin[q * elemsize + n]; 1575e2f04181SAndrew T. Barker } else if (emodeout[eout] == CEED_EVAL_GRAD) { 1576e2f04181SAndrew T. Barker dout += 1; 1577e2f04181SAndrew T. Barker Bmat_out[(qq+eout)*elemsize + n] += 1578e2f04181SAndrew T. Barker gradin[(dout*nqpts+q) * elemsize + n]; 1579e2f04181SAndrew T. Barker } else { 1580e2f04181SAndrew T. Barker // LCOV_EXCL_START 1581e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Not implemented!"); 1582e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1583e2f04181SAndrew T. Barker } 1584e2f04181SAndrew T. Barker } 1585e2f04181SAndrew T. Barker } 1586e2f04181SAndrew T. Barker for (int ei = 0; ei < numemodeout; ++ei) { 1587e2f04181SAndrew T. Barker for (int ej = 0; ej < numemodein; ++ej) { 1588e2f04181SAndrew T. Barker const int emode_index = ((ei*ncomp+compin)*numemodein+ej)*ncomp+compout; 1589e2f04181SAndrew T. Barker const int index = q*layout_qf[0] + emode_index*layout_qf[1] + e*layout_qf[2]; 1590e2f04181SAndrew T. Barker Dmat[(ei*numemodein+ej)*nqpts + q] += assembledqfarray[index]; 1591e2f04181SAndrew T. Barker } 1592e2f04181SAndrew T. Barker } 1593e2f04181SAndrew T. Barker } 1594e2f04181SAndrew T. Barker // Compute B^T*D 1595e2f04181SAndrew T. Barker for (int ell = 0; ell < elemsize*nqpts*numemodein; ++ell) { 1596e2f04181SAndrew T. Barker BTD[ell] = 0.0; 1597e2f04181SAndrew T. Barker } 1598e2f04181SAndrew T. Barker for (int j = 0; j<elemsize; ++j) { 1599e2f04181SAndrew T. Barker for (int q = 0; q<nqpts; ++q) { 1600e2f04181SAndrew T. Barker int qq = numemodeout*q; 1601e2f04181SAndrew T. Barker for (int ei = 0; ei < numemodein; ++ei) { 1602e2f04181SAndrew T. Barker for (int ej = 0; ej < numemodeout; ++ej) { 1603e2f04181SAndrew T. Barker BTD[j*(nqpts*numemodein) + (qq+ei)] += 1604e2f04181SAndrew T. Barker Bmat_out[(qq+ej)*elemsize + j] * Dmat[(ei*numemodein+ej)*nqpts + q]; 1605e2f04181SAndrew T. Barker } 1606e2f04181SAndrew T. Barker } 1607e2f04181SAndrew T. Barker } 1608e2f04181SAndrew T. Barker } 1609e2f04181SAndrew T. Barker 1610e2f04181SAndrew T. Barker ierr = CeedMatrixMultiply(ceed, BTD, Bmat_in, elem_mat, elemsize, 1611e2f04181SAndrew T. Barker elemsize, nqpts*numemodein); CeedChk(ierr); 1612e2f04181SAndrew T. Barker 1613e2f04181SAndrew T. Barker // put element matrix in coordinate data structure 1614e2f04181SAndrew T. Barker for (int i = 0; i < elemsize; ++i) { 1615e2f04181SAndrew T. Barker for (int j = 0; j < elemsize; ++j) { 1616e2f04181SAndrew T. Barker vals[offset + count] = elem_mat[i*elemsize + j]; 1617e2f04181SAndrew T. Barker count++; 1618e2f04181SAndrew T. Barker } 1619e2f04181SAndrew T. Barker } 1620e2f04181SAndrew T. Barker } 1621e2f04181SAndrew T. Barker } 1622e2f04181SAndrew T. Barker } 1623e2f04181SAndrew T. Barker if (count != local_nentries) 1624e2f04181SAndrew T. Barker // LCOV_EXCL_START 1625e2f04181SAndrew T. Barker return CeedError(ceed, CEED_ERROR_MAJOR, "Error computing entries"); 1626e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1627e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArray(values, &vals); CeedChk(ierr); 1628e2f04181SAndrew T. Barker 1629e2f04181SAndrew T. Barker ierr = CeedVectorRestoreArrayRead(assembledqf, &assembledqfarray); 1630e2f04181SAndrew T. Barker CeedChk(ierr); 1631e2f04181SAndrew T. Barker ierr = CeedVectorDestroy(&assembledqf); CeedChk(ierr); 1632e2f04181SAndrew T. Barker ierr = CeedFree(&emodein); CeedChk(ierr); 1633e2f04181SAndrew T. Barker ierr = CeedFree(&emodeout); CeedChk(ierr); 1634e2f04181SAndrew T. Barker 1635e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1636e2f04181SAndrew T. Barker } 1637e2f04181SAndrew T. Barker 1638e2f04181SAndrew T. Barker /** 1639e2f04181SAndrew T. Barker @ref Utility 1640e2f04181SAndrew T. Barker **/ 1641e2f04181SAndrew T. Barker int CeedSingleOperatorAssemblyCountEntries(CeedOperator op, CeedInt *nentries) { 1642e2f04181SAndrew T. Barker int ierr; 1643e2f04181SAndrew T. Barker CeedElemRestriction rstr; 1644e2f04181SAndrew T. Barker CeedInt nelem, elemsize, ncomp; 1645e2f04181SAndrew T. Barker 1646e2f04181SAndrew T. Barker if (op->composite) 1647e2f04181SAndrew T. Barker // LCOV_EXCL_START 1648e2f04181SAndrew T. Barker return CeedError(op->ceed, CEED_ERROR_UNSUPPORTED, 1649e2f04181SAndrew T. Barker "Composite operator not supported"); 1650e2f04181SAndrew T. Barker // LCOV_EXCL_STOP 1651e2f04181SAndrew T. Barker ierr = CeedOperatorGetActiveElemRestriction(op, &rstr); CeedChk(ierr); 1652e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetNumElements(rstr, &nelem); CeedChk(ierr); 1653e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetElementSize(rstr, &elemsize); CeedChk(ierr); 1654e2f04181SAndrew T. Barker ierr = CeedElemRestrictionGetNumComponents(rstr, &ncomp); CeedChk(ierr); 1655e2f04181SAndrew T. Barker *nentries = elemsize*ncomp * elemsize*ncomp * nelem; 1656e2f04181SAndrew T. Barker 1657e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1658e2f04181SAndrew T. Barker } 1659e2f04181SAndrew T. Barker 1660e2f04181SAndrew T. Barker /** 1661e2f04181SAndrew T. Barker @brief Fully assemble the nonzero pattern of a linear operator. 1662e2f04181SAndrew T. Barker 1663e2f04181SAndrew T. Barker Expected to be used in conjunction with CeedOperatorLinearAssemble() 1664e2f04181SAndrew T. Barker 1665e2f04181SAndrew T. Barker The assembly routines use coordinate format, with nentries tuples of the 1666e2f04181SAndrew T. Barker form (i, j, value) which indicate that value should be added to the matrix 1667e2f04181SAndrew T. Barker in entry (i, j). Note that the (i, j) pairs are not unique and may repeat. 1668e2f04181SAndrew T. Barker This function returns the number of entries and their (i, j) locations, 1669e2f04181SAndrew T. Barker while CeedOperatorLinearAssemble() provides the values in the same 1670e2f04181SAndrew T. Barker ordering. 1671e2f04181SAndrew T. Barker 1672e2f04181SAndrew T. Barker This will generally be slow unless your operator is low-order. 1673e2f04181SAndrew T. Barker 1674e2f04181SAndrew T. Barker @param[in] op CeedOperator to assemble 1675e2f04181SAndrew T. Barker @param[out] nentries Number of entries in coordinate nonzero pattern. 1676e2f04181SAndrew T. Barker @param[out] rows Row number for each entry. 1677e2f04181SAndrew T. Barker @param[out] cols Column number for each entry. 1678e2f04181SAndrew T. Barker 1679e2f04181SAndrew T. Barker @ref User 1680e2f04181SAndrew T. Barker **/ 1681e2f04181SAndrew T. Barker int CeedOperatorLinearAssembleSymbolic(CeedOperator op, 1682e2f04181SAndrew T. Barker CeedInt *nentries, CeedInt **rows, CeedInt **cols) { 1683e2f04181SAndrew T. Barker int ierr; 1684e2f04181SAndrew T. Barker CeedInt numsub, single_entries; 1685e2f04181SAndrew T. Barker CeedOperator *suboperators; 1686e2f04181SAndrew T. Barker bool isComposite; 1687e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1688e2f04181SAndrew T. Barker 1689e2f04181SAndrew T. Barker // Use backend version, if available 1690e2f04181SAndrew T. Barker if (op->LinearAssembleSymbolic) { 1691e2f04181SAndrew T. Barker return op->LinearAssembleSymbolic(op, nentries, rows, cols); 1692e2f04181SAndrew T. Barker } else { 1693e2f04181SAndrew T. Barker // Check for valid fallback resource 1694e2f04181SAndrew T. Barker const char *resource, *fallbackresource; 1695e2f04181SAndrew T. Barker ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr); 1696e2f04181SAndrew T. Barker ierr = CeedGetOperatorFallbackResource(op->ceed, &fallbackresource); 1697e2f04181SAndrew T. Barker if (strcmp(fallbackresource, "") && strcmp(resource, fallbackresource)) { 1698e2f04181SAndrew T. Barker // Fallback to reference Ceed 1699e2f04181SAndrew T. Barker if (!op->opfallback) { 1700e2f04181SAndrew T. Barker ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1701e2f04181SAndrew T. Barker } 1702e2f04181SAndrew T. Barker // Assemble 1703e2f04181SAndrew T. Barker return CeedOperatorLinearAssembleSymbolic(op->opfallback, nentries, rows, cols); 1704e2f04181SAndrew T. Barker } 1705e2f04181SAndrew T. Barker } 1706e2f04181SAndrew T. Barker 1707e2f04181SAndrew T. Barker // if neither backend nor fallback resource provides 1708e2f04181SAndrew T. Barker // LinearAssembleSymbolic, continue with interface-level implementation 1709e2f04181SAndrew T. Barker 1710e2f04181SAndrew T. Barker // count entries and allocate rows, cols arrays 1711e2f04181SAndrew T. Barker ierr = CeedOperatorIsComposite(op, &isComposite); CeedChk(ierr); 1712e2f04181SAndrew T. Barker *nentries = 0; 1713e2f04181SAndrew T. Barker if (isComposite) { 1714e2f04181SAndrew T. Barker ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 1715e2f04181SAndrew T. Barker ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 1716e2f04181SAndrew T. Barker for (int k = 0; k < numsub; ++k) { 1717e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemblyCountEntries(suboperators[k], 1718e2f04181SAndrew T. Barker &single_entries); CeedChk(ierr); 1719e2f04181SAndrew T. Barker *nentries += single_entries; 1720e2f04181SAndrew T. Barker } 1721e2f04181SAndrew T. Barker } else { 1722e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemblyCountEntries(op, 1723e2f04181SAndrew T. Barker &single_entries); CeedChk(ierr); 1724e2f04181SAndrew T. Barker *nentries += single_entries; 1725e2f04181SAndrew T. Barker } 1726e2f04181SAndrew T. Barker ierr = CeedCalloc(*nentries, rows); CeedChk(ierr); 1727e2f04181SAndrew T. Barker ierr = CeedCalloc(*nentries, cols); CeedChk(ierr); 1728e2f04181SAndrew T. Barker 1729e2f04181SAndrew T. Barker // assemble nonzero locations 1730e2f04181SAndrew T. Barker CeedInt offset = 0; 1731e2f04181SAndrew T. Barker if (isComposite) { 1732e2f04181SAndrew T. Barker ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 1733e2f04181SAndrew T. Barker ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 1734e2f04181SAndrew T. Barker for (int k = 0; k < numsub; ++k) { 1735e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssembleSymbolic(suboperators[k], offset, *rows, 1736e2f04181SAndrew T. Barker *cols); CeedChk(ierr); 1737e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemblyCountEntries(suboperators[k], &single_entries); 1738e2f04181SAndrew T. Barker CeedChk(ierr); 1739e2f04181SAndrew T. Barker offset += single_entries; 1740e2f04181SAndrew T. Barker } 1741e2f04181SAndrew T. Barker } else { 1742e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssembleSymbolic(op, offset, *rows, *cols); 1743e2f04181SAndrew T. Barker CeedChk(ierr); 1744e2f04181SAndrew T. Barker } 1745e2f04181SAndrew T. Barker 1746e2f04181SAndrew T. Barker return CEED_ERROR_SUCCESS; 1747e2f04181SAndrew T. Barker } 1748e2f04181SAndrew T. Barker 1749e2f04181SAndrew T. Barker /** 1750e2f04181SAndrew T. Barker @brief Fully assemble the nonzero entries of a linear operator. 1751e2f04181SAndrew T. Barker 1752e2f04181SAndrew T. Barker Expected to be used in conjunction with CeedOperatorLinearAssembleSymbolic() 1753e2f04181SAndrew T. Barker 1754e2f04181SAndrew T. Barker The assembly routines use coordinate format, with nentries tuples of the 1755e2f04181SAndrew T. Barker form (i, j, value) which indicate that value should be added to the matrix 1756e2f04181SAndrew T. Barker in entry (i, j). Note that the (i, j) pairs are not unique and may repeat. 1757e2f04181SAndrew T. Barker This function returns the values of the nonzero entries to be added, their 1758e2f04181SAndrew T. Barker (i, j) locations are provided by CeedOperatorLinearAssembleSymbolic() 1759e2f04181SAndrew T. Barker 1760e2f04181SAndrew T. Barker This will generally be slow unless your operator is low-order. 1761e2f04181SAndrew T. Barker 1762e2f04181SAndrew T. Barker @param[in] op CeedOperator to assemble 1763e2f04181SAndrew T. Barker @param[out] values Values to assemble into matrix 1764e2f04181SAndrew T. Barker 1765e2f04181SAndrew T. Barker @ref User 1766e2f04181SAndrew T. Barker **/ 1767e2f04181SAndrew T. Barker int CeedOperatorLinearAssemble(CeedOperator op, CeedVector values) { 1768e2f04181SAndrew T. Barker int ierr; 1769e2f04181SAndrew T. Barker CeedInt numsub, single_entries; 1770e2f04181SAndrew T. Barker CeedOperator *suboperators; 1771e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 1772e2f04181SAndrew T. Barker 1773e2f04181SAndrew T. Barker // Use backend version, if available 1774e2f04181SAndrew T. Barker if (op->LinearAssemble) { 1775e2f04181SAndrew T. Barker return op->LinearAssemble(op, values); 1776e2f04181SAndrew T. Barker } else { 1777e2f04181SAndrew T. Barker // Check for valid fallback resource 1778e2f04181SAndrew T. Barker const char *resource, *fallbackresource; 1779e2f04181SAndrew T. Barker ierr = CeedGetResource(op->ceed, &resource); CeedChk(ierr); 1780e2f04181SAndrew T. Barker ierr = CeedGetOperatorFallbackResource(op->ceed, &fallbackresource); 1781e2f04181SAndrew T. Barker if (strcmp(fallbackresource, "") && strcmp(resource, fallbackresource)) { 1782e2f04181SAndrew T. Barker // Fallback to reference Ceed 1783e2f04181SAndrew T. Barker if (!op->opfallback) { 1784e2f04181SAndrew T. Barker ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 1785e2f04181SAndrew T. Barker } 1786e2f04181SAndrew T. Barker // Assemble 1787e2f04181SAndrew T. Barker return CeedOperatorLinearAssemble(op->opfallback, values); 1788e2f04181SAndrew T. Barker } 1789e2f04181SAndrew T. Barker } 1790e2f04181SAndrew T. Barker 1791e2f04181SAndrew T. Barker // if neither backend nor fallback resource provides 1792e2f04181SAndrew T. Barker // LinearAssemble, continue with interface-level implementation 1793e2f04181SAndrew T. Barker 1794e2f04181SAndrew T. Barker bool isComposite; 1795e2f04181SAndrew T. Barker ierr = CeedOperatorIsComposite(op, &isComposite); CeedChk(ierr); 1796e2f04181SAndrew T. Barker 1797e2f04181SAndrew T. Barker CeedInt offset = 0; 1798e2f04181SAndrew T. Barker if (isComposite) { 1799e2f04181SAndrew T. Barker ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 1800e2f04181SAndrew T. Barker ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 1801e2f04181SAndrew T. Barker for (int k = 0; k < numsub; ++k) { 1802e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemble(suboperators[k], offset, values); 1803e2f04181SAndrew T. Barker CeedChk(ierr); 1804e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemblyCountEntries(suboperators[k], &single_entries); 1805e2f04181SAndrew T. Barker CeedChk(ierr); 1806e2f04181SAndrew T. Barker offset += single_entries; 1807e2f04181SAndrew T. Barker } 1808e2f04181SAndrew T. Barker } else { 1809e2f04181SAndrew T. Barker ierr = CeedSingleOperatorAssemble(op, offset, values); CeedChk(ierr); 1810e2f04181SAndrew T. Barker } 1811e2f04181SAndrew T. Barker 1812e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1813d965c7a7SJeremy L Thompson } 1814d965c7a7SJeremy L Thompson 1815d965c7a7SJeremy L Thompson /** 1816d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1817d99fa3c5SJeremy L Thompson for a CeedOperator, creating the prolongation basis from the 1818d99fa3c5SJeremy L Thompson fine and coarse grid interpolation 1819d99fa3c5SJeremy L Thompson 1820d99fa3c5SJeremy L Thompson @param[in] opFine Fine grid operator 1821d99fa3c5SJeremy L Thompson @param[in] PMultFine L-vector multiplicity in parallel gather/scatter 1822d99fa3c5SJeremy L Thompson @param[in] rstrCoarse Coarse grid restriction 1823d99fa3c5SJeremy L Thompson @param[in] basisCoarse Coarse grid active vector basis 1824d99fa3c5SJeremy L Thompson @param[out] opCoarse Coarse grid operator 1825d99fa3c5SJeremy L Thompson @param[out] opProlong Coarse to fine operator 1826d99fa3c5SJeremy L Thompson @param[out] opRestrict Fine to coarse operator 1827d99fa3c5SJeremy L Thompson 1828d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1829d99fa3c5SJeremy L Thompson 1830d99fa3c5SJeremy L Thompson @ref User 1831d99fa3c5SJeremy L Thompson **/ 1832d99fa3c5SJeremy L Thompson int CeedOperatorMultigridLevelCreate(CeedOperator opFine, CeedVector PMultFine, 1833d99fa3c5SJeremy L Thompson CeedElemRestriction rstrCoarse, CeedBasis basisCoarse, 1834d99fa3c5SJeremy L Thompson CeedOperator *opCoarse, CeedOperator *opProlong, CeedOperator *opRestrict) { 1835d99fa3c5SJeremy L Thompson int ierr; 1836d99fa3c5SJeremy L Thompson Ceed ceed; 1837d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(opFine, &ceed); CeedChk(ierr); 1838d99fa3c5SJeremy L Thompson 1839d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 1840d99fa3c5SJeremy L Thompson CeedBasis basisFine; 1841d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetActiveBasis(opFine, &basisFine); CeedChk(ierr); 1842d99fa3c5SJeremy L Thompson CeedInt Qf, Qc; 1843d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisFine, &Qf); CeedChk(ierr); 1844d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisCoarse, &Qc); CeedChk(ierr); 1845d99fa3c5SJeremy L Thompson if (Qf != Qc) 1846d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1847e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 1848e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 1849d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1850d99fa3c5SJeremy L Thompson 1851d99fa3c5SJeremy L Thompson // Coarse to fine basis 1852d99fa3c5SJeremy L Thompson CeedInt Pf, Pc, Q = Qf; 1853d99fa3c5SJeremy L Thompson bool isTensorF, isTensorC; 1854d99fa3c5SJeremy L Thompson ierr = CeedBasisIsTensor(basisFine, &isTensorF); CeedChk(ierr); 1855d99fa3c5SJeremy L Thompson ierr = CeedBasisIsTensor(basisCoarse, &isTensorC); CeedChk(ierr); 1856d99fa3c5SJeremy L Thompson CeedScalar *interpC, *interpF, *interpCtoF, *tau; 1857d99fa3c5SJeremy L Thompson if (isTensorF && isTensorC) { 1858d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes1D(basisFine, &Pf); CeedChk(ierr); 1859d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes1D(basisCoarse, &Pc); CeedChk(ierr); 1860d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints1D(basisCoarse, &Q); CeedChk(ierr); 1861d99fa3c5SJeremy L Thompson } else if (!isTensorF && !isTensorC) { 1862d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes(basisFine, &Pf); CeedChk(ierr); 1863d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes(basisCoarse, &Pc); CeedChk(ierr); 1864d99fa3c5SJeremy L Thompson } else { 1865d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1866e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MINOR, 1867e15f9bd0SJeremy L Thompson "Bases must both be tensor or non-tensor"); 1868d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1869d99fa3c5SJeremy L Thompson } 1870d99fa3c5SJeremy L Thompson 1871d99fa3c5SJeremy L Thompson ierr = CeedMalloc(Q*Pf, &interpF); CeedChk(ierr); 1872d99fa3c5SJeremy L Thompson ierr = CeedMalloc(Q*Pc, &interpC); CeedChk(ierr); 1873d99fa3c5SJeremy L Thompson ierr = CeedCalloc(Pc*Pf, &interpCtoF); CeedChk(ierr); 1874d99fa3c5SJeremy L Thompson ierr = CeedMalloc(Q, &tau); CeedChk(ierr); 1875d99fa3c5SJeremy L Thompson if (isTensorF) { 1876d99fa3c5SJeremy L Thompson memcpy(interpF, basisFine->interp1d, Q*Pf*sizeof basisFine->interp1d[0]); 1877d99fa3c5SJeremy L Thompson memcpy(interpC, basisCoarse->interp1d, Q*Pc*sizeof basisCoarse->interp1d[0]); 1878d99fa3c5SJeremy L Thompson } else { 1879d99fa3c5SJeremy L Thompson memcpy(interpF, basisFine->interp, Q*Pf*sizeof basisFine->interp[0]); 1880d99fa3c5SJeremy L Thompson memcpy(interpC, basisCoarse->interp, Q*Pc*sizeof basisCoarse->interp[0]); 1881d99fa3c5SJeremy L Thompson } 1882d99fa3c5SJeremy L Thompson 1883d99fa3c5SJeremy L Thompson // -- QR Factorization, interpF = Q R 1884d99fa3c5SJeremy L Thompson ierr = CeedQRFactorization(ceed, interpF, tau, Q, Pf); CeedChk(ierr); 1885d99fa3c5SJeremy L Thompson 1886d99fa3c5SJeremy L Thompson // -- Apply Qtranspose, interpC = Qtranspose interpC 1887d99fa3c5SJeremy L Thompson CeedHouseholderApplyQ(interpC, interpF, tau, CEED_TRANSPOSE, 1888d99fa3c5SJeremy L Thompson Q, Pc, Pf, Pc, 1); 1889d99fa3c5SJeremy L Thompson 1890d99fa3c5SJeremy L Thompson // -- Apply Rinv, interpCtoF = Rinv interpC 1891d99fa3c5SJeremy L Thompson for (CeedInt j=0; j<Pc; j++) { // Column j 1892d99fa3c5SJeremy L Thompson interpCtoF[j+Pc*(Pf-1)] = interpC[j+Pc*(Pf-1)]/interpF[Pf*Pf-1]; 1893d99fa3c5SJeremy L Thompson for (CeedInt i=Pf-2; i>=0; i--) { // Row i 1894d99fa3c5SJeremy L Thompson interpCtoF[j+Pc*i] = interpC[j+Pc*i]; 1895d99fa3c5SJeremy L Thompson for (CeedInt k=i+1; k<Pf; k++) 1896d99fa3c5SJeremy L Thompson interpCtoF[j+Pc*i] -= interpF[k+Pf*i]*interpCtoF[j+Pc*k]; 1897d99fa3c5SJeremy L Thompson interpCtoF[j+Pc*i] /= interpF[i+Pf*i]; 1898d99fa3c5SJeremy L Thompson } 1899d99fa3c5SJeremy L Thompson } 1900d99fa3c5SJeremy L Thompson ierr = CeedFree(&tau); CeedChk(ierr); 1901d99fa3c5SJeremy L Thompson ierr = CeedFree(&interpC); CeedChk(ierr); 1902d99fa3c5SJeremy L Thompson ierr = CeedFree(&interpF); CeedChk(ierr); 1903d99fa3c5SJeremy L Thompson 1904e15f9bd0SJeremy L Thompson // Complete with interpCtoF versions of code 1905d99fa3c5SJeremy L Thompson if (isTensorF) { 1906d99fa3c5SJeremy L Thompson ierr = CeedOperatorMultigridLevelCreateTensorH1(opFine, PMultFine, 1907d99fa3c5SJeremy L Thompson rstrCoarse, basisCoarse, interpCtoF, opCoarse, opProlong, opRestrict); 1908d99fa3c5SJeremy L Thompson CeedChk(ierr); 1909d99fa3c5SJeremy L Thompson } else { 1910d99fa3c5SJeremy L Thompson ierr = CeedOperatorMultigridLevelCreateH1(opFine, PMultFine, 1911d99fa3c5SJeremy L Thompson rstrCoarse, basisCoarse, interpCtoF, opCoarse, opProlong, opRestrict); 1912d99fa3c5SJeremy L Thompson CeedChk(ierr); 1913d99fa3c5SJeremy L Thompson } 1914d99fa3c5SJeremy L Thompson 1915d99fa3c5SJeremy L Thompson // Cleanup 1916d99fa3c5SJeremy L Thompson ierr = CeedFree(&interpCtoF); CeedChk(ierr); 1917e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1918d99fa3c5SJeremy L Thompson } 1919d99fa3c5SJeremy L Thompson 1920d99fa3c5SJeremy L Thompson /** 1921d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1922d99fa3c5SJeremy L Thompson for a CeedOperator with a tensor basis for the active basis 1923d99fa3c5SJeremy L Thompson 1924d99fa3c5SJeremy L Thompson @param[in] opFine Fine grid operator 1925d99fa3c5SJeremy L Thompson @param[in] PMultFine L-vector multiplicity in parallel gather/scatter 1926d99fa3c5SJeremy L Thompson @param[in] rstrCoarse Coarse grid restriction 1927d99fa3c5SJeremy L Thompson @param[in] basisCoarse Coarse grid active vector basis 1928d99fa3c5SJeremy L Thompson @param[in] interpCtoF Matrix for coarse to fine interpolation 1929d99fa3c5SJeremy L Thompson @param[out] opCoarse Coarse grid operator 1930d99fa3c5SJeremy L Thompson @param[out] opProlong Coarse to fine operator 1931d99fa3c5SJeremy L Thompson @param[out] opRestrict Fine to coarse operator 1932d99fa3c5SJeremy L Thompson 1933d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 1934d99fa3c5SJeremy L Thompson 1935d99fa3c5SJeremy L Thompson @ref User 1936d99fa3c5SJeremy L Thompson **/ 1937d99fa3c5SJeremy L Thompson int CeedOperatorMultigridLevelCreateTensorH1(CeedOperator opFine, 1938d99fa3c5SJeremy L Thompson CeedVector PMultFine, CeedElemRestriction rstrCoarse, CeedBasis basisCoarse, 1939d99fa3c5SJeremy L Thompson const CeedScalar *interpCtoF, CeedOperator *opCoarse, 1940d99fa3c5SJeremy L Thompson CeedOperator *opProlong, CeedOperator *opRestrict) { 1941d99fa3c5SJeremy L Thompson int ierr; 1942d99fa3c5SJeremy L Thompson Ceed ceed; 1943d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(opFine, &ceed); CeedChk(ierr); 1944d99fa3c5SJeremy L Thompson 1945d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 1946d99fa3c5SJeremy L Thompson CeedBasis basisFine; 1947d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetActiveBasis(opFine, &basisFine); CeedChk(ierr); 1948d99fa3c5SJeremy L Thompson CeedInt Qf, Qc; 1949d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisFine, &Qf); CeedChk(ierr); 1950d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisCoarse, &Qc); CeedChk(ierr); 1951d99fa3c5SJeremy L Thompson if (Qf != Qc) 1952d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 1953e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 1954e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 1955d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 1956d99fa3c5SJeremy L Thompson 1957d99fa3c5SJeremy L Thompson // Coarse to fine basis 1958d99fa3c5SJeremy L Thompson CeedInt dim, ncomp, nnodesCoarse, P1dFine, P1dCoarse; 1959d99fa3c5SJeremy L Thompson ierr = CeedBasisGetDimension(basisFine, &dim); CeedChk(ierr); 1960d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumComponents(basisFine, &ncomp); CeedChk(ierr); 1961d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes1D(basisFine, &P1dFine); CeedChk(ierr); 1962d99fa3c5SJeremy L Thompson ierr = CeedElemRestrictionGetElementSize(rstrCoarse, &nnodesCoarse); 1963d99fa3c5SJeremy L Thompson CeedChk(ierr); 1964d99fa3c5SJeremy L Thompson P1dCoarse = dim == 1 ? nnodesCoarse : 1965d99fa3c5SJeremy L Thompson dim == 2 ? sqrt(nnodesCoarse) : 1966d99fa3c5SJeremy L Thompson cbrt(nnodesCoarse); 1967d99fa3c5SJeremy L Thompson CeedScalar *qref, *qweight, *grad; 1968d99fa3c5SJeremy L Thompson ierr = CeedCalloc(P1dFine, &qref); CeedChk(ierr); 1969d99fa3c5SJeremy L Thompson ierr = CeedCalloc(P1dFine, &qweight); CeedChk(ierr); 1970d99fa3c5SJeremy L Thompson ierr = CeedCalloc(P1dFine*P1dCoarse*dim, &grad); CeedChk(ierr); 1971d99fa3c5SJeremy L Thompson CeedBasis basisCtoF; 1972d99fa3c5SJeremy L Thompson ierr = CeedBasisCreateTensorH1(ceed, dim, ncomp, P1dCoarse, P1dFine, 1973d99fa3c5SJeremy L Thompson interpCtoF, grad, qref, qweight, &basisCtoF); 1974d99fa3c5SJeremy L Thompson CeedChk(ierr); 1975d99fa3c5SJeremy L Thompson ierr = CeedFree(&qref); CeedChk(ierr); 1976d99fa3c5SJeremy L Thompson ierr = CeedFree(&qweight); CeedChk(ierr); 1977d99fa3c5SJeremy L Thompson ierr = CeedFree(&grad); CeedChk(ierr); 1978d99fa3c5SJeremy L Thompson 1979d99fa3c5SJeremy L Thompson // Core code 1980d99fa3c5SJeremy L Thompson ierr = CeedOperatorMultigridLevel_Core(opFine, PMultFine, rstrCoarse, 1981d99fa3c5SJeremy L Thompson basisCoarse, basisCtoF, opCoarse, 1982d99fa3c5SJeremy L Thompson opProlong, opRestrict); 1983d99fa3c5SJeremy L Thompson CeedChk(ierr); 1984e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1985d99fa3c5SJeremy L Thompson } 1986d99fa3c5SJeremy L Thompson 1987d99fa3c5SJeremy L Thompson /** 1988d99fa3c5SJeremy L Thompson @brief Create a multigrid coarse operator and level transfer operators 1989d99fa3c5SJeremy L Thompson for a CeedOperator with a non-tensor basis for the active vector 1990d99fa3c5SJeremy L Thompson 1991d99fa3c5SJeremy L Thompson @param[in] opFine Fine grid operator 1992d99fa3c5SJeremy L Thompson @param[in] PMultFine L-vector multiplicity in parallel gather/scatter 1993d99fa3c5SJeremy L Thompson @param[in] rstrCoarse Coarse grid restriction 1994d99fa3c5SJeremy L Thompson @param[in] basisCoarse Coarse grid active vector basis 1995d99fa3c5SJeremy L Thompson @param[in] interpCtoF Matrix for coarse to fine interpolation 1996d99fa3c5SJeremy L Thompson @param[out] opCoarse Coarse grid operator 1997d99fa3c5SJeremy L Thompson @param[out] opProlong Coarse to fine operator 1998d99fa3c5SJeremy L Thompson @param[out] opRestrict Fine to coarse operator 1999d99fa3c5SJeremy L Thompson 2000d99fa3c5SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 2001d99fa3c5SJeremy L Thompson 2002d99fa3c5SJeremy L Thompson @ref User 2003d99fa3c5SJeremy L Thompson **/ 2004d99fa3c5SJeremy L Thompson int CeedOperatorMultigridLevelCreateH1(CeedOperator opFine, 2005d99fa3c5SJeremy L Thompson CeedVector PMultFine, 2006d99fa3c5SJeremy L Thompson CeedElemRestriction rstrCoarse, 2007d99fa3c5SJeremy L Thompson CeedBasis basisCoarse, 2008d99fa3c5SJeremy L Thompson const CeedScalar *interpCtoF, 2009d99fa3c5SJeremy L Thompson CeedOperator *opCoarse, 2010d99fa3c5SJeremy L Thompson CeedOperator *opProlong, 2011d99fa3c5SJeremy L Thompson CeedOperator *opRestrict) { 2012d99fa3c5SJeremy L Thompson int ierr; 2013d99fa3c5SJeremy L Thompson Ceed ceed; 2014d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetCeed(opFine, &ceed); CeedChk(ierr); 2015d99fa3c5SJeremy L Thompson 2016d99fa3c5SJeremy L Thompson // Check for compatible quadrature spaces 2017d99fa3c5SJeremy L Thompson CeedBasis basisFine; 2018d99fa3c5SJeremy L Thompson ierr = CeedOperatorGetActiveBasis(opFine, &basisFine); CeedChk(ierr); 2019d99fa3c5SJeremy L Thompson CeedInt Qf, Qc; 2020d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisFine, &Qf); CeedChk(ierr); 2021d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisCoarse, &Qc); CeedChk(ierr); 2022d99fa3c5SJeremy L Thompson if (Qf != Qc) 2023d99fa3c5SJeremy L Thompson // LCOV_EXCL_START 2024e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_DIMENSION, 2025e15f9bd0SJeremy L Thompson "Bases must have compatible quadrature spaces"); 2026d99fa3c5SJeremy L Thompson // LCOV_EXCL_STOP 2027d99fa3c5SJeremy L Thompson 2028d99fa3c5SJeremy L Thompson // Coarse to fine basis 2029d99fa3c5SJeremy L Thompson CeedElemTopology topo; 2030d99fa3c5SJeremy L Thompson ierr = CeedBasisGetTopology(basisFine, &topo); CeedChk(ierr); 2031d99fa3c5SJeremy L Thompson CeedInt dim, ncomp, nnodesCoarse, nnodesFine; 2032d99fa3c5SJeremy L Thompson ierr = CeedBasisGetDimension(basisFine, &dim); CeedChk(ierr); 2033d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumComponents(basisFine, &ncomp); CeedChk(ierr); 2034d99fa3c5SJeremy L Thompson ierr = CeedBasisGetNumNodes(basisFine, &nnodesFine); CeedChk(ierr); 2035d99fa3c5SJeremy L Thompson ierr = CeedElemRestrictionGetElementSize(rstrCoarse, &nnodesCoarse); 2036d99fa3c5SJeremy L Thompson CeedChk(ierr); 2037d99fa3c5SJeremy L Thompson CeedScalar *qref, *qweight, *grad; 2038d99fa3c5SJeremy L Thompson ierr = CeedCalloc(nnodesFine, &qref); CeedChk(ierr); 2039d99fa3c5SJeremy L Thompson ierr = CeedCalloc(nnodesFine, &qweight); CeedChk(ierr); 2040d99fa3c5SJeremy L Thompson ierr = CeedCalloc(nnodesFine*nnodesCoarse*dim, &grad); CeedChk(ierr); 2041d99fa3c5SJeremy L Thompson CeedBasis basisCtoF; 2042d99fa3c5SJeremy L Thompson ierr = CeedBasisCreateH1(ceed, topo, ncomp, nnodesCoarse, nnodesFine, 2043d99fa3c5SJeremy L Thompson interpCtoF, grad, qref, qweight, &basisCtoF); 2044d99fa3c5SJeremy L Thompson CeedChk(ierr); 2045d99fa3c5SJeremy L Thompson ierr = CeedFree(&qref); CeedChk(ierr); 2046d99fa3c5SJeremy L Thompson ierr = CeedFree(&qweight); CeedChk(ierr); 2047d99fa3c5SJeremy L Thompson ierr = CeedFree(&grad); CeedChk(ierr); 2048d99fa3c5SJeremy L Thompson 2049d99fa3c5SJeremy L Thompson // Core code 2050d99fa3c5SJeremy L Thompson ierr = CeedOperatorMultigridLevel_Core(opFine, PMultFine, rstrCoarse, 2051d99fa3c5SJeremy L Thompson basisCoarse, basisCtoF, opCoarse, 2052d99fa3c5SJeremy L Thompson opProlong, opRestrict); 2053d99fa3c5SJeremy L Thompson CeedChk(ierr); 2054e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2055d99fa3c5SJeremy L Thompson } 2056d99fa3c5SJeremy L Thompson 2057d99fa3c5SJeremy L Thompson /** 20583bd813ffSjeremylt @brief Build a FDM based approximate inverse for each element for a 20593bd813ffSjeremylt CeedOperator 20603bd813ffSjeremylt 20613bd813ffSjeremylt This returns a CeedOperator and CeedVector to apply a Fast Diagonalization 20623bd813ffSjeremylt Method based approximate inverse. This function obtains the simultaneous 20633bd813ffSjeremylt diagonalization for the 1D mass and Laplacian operators, 20643bd813ffSjeremylt M = V^T V, K = V^T S V. 20653bd813ffSjeremylt The assembled QFunction is used to modify the eigenvalues from simultaneous 20663bd813ffSjeremylt diagonalization and obtain an approximate inverse of the form 20673bd813ffSjeremylt V^T S^hat V. The CeedOperator must be linear and non-composite. The 20683bd813ffSjeremylt associated CeedQFunction must therefore also be linear. 20693bd813ffSjeremylt 20703bd813ffSjeremylt @param op CeedOperator to create element inverses 20713bd813ffSjeremylt @param[out] fdminv CeedOperator to apply the action of a FDM based inverse 20723bd813ffSjeremylt for each element 20733bd813ffSjeremylt @param request Address of CeedRequest for non-blocking completion, else 20744cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 20753bd813ffSjeremylt 20763bd813ffSjeremylt @return An error code: 0 - success, otherwise - failure 20773bd813ffSjeremylt 20787a982d89SJeremy L. Thompson @ref Backend 20793bd813ffSjeremylt **/ 20803bd813ffSjeremylt int CeedOperatorCreateFDMElementInverse(CeedOperator op, CeedOperator *fdminv, 20813bd813ffSjeremylt CeedRequest *request) { 20823bd813ffSjeremylt int ierr; 2083e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 20843bd813ffSjeremylt 2085713f43c3Sjeremylt // Use backend version, if available 2086713f43c3Sjeremylt if (op->CreateFDMElementInverse) { 2087713f43c3Sjeremylt ierr = op->CreateFDMElementInverse(op, fdminv, request); CeedChk(ierr); 2088713f43c3Sjeremylt } else { 2089713f43c3Sjeremylt // Fallback to reference Ceed 2090713f43c3Sjeremylt if (!op->opfallback) { 2091713f43c3Sjeremylt ierr = CeedOperatorCreateFallback(op); CeedChk(ierr); 20923bd813ffSjeremylt } 2093713f43c3Sjeremylt // Assemble 2094713f43c3Sjeremylt ierr = op->opfallback->CreateFDMElementInverse(op->opfallback, fdminv, 20953bd813ffSjeremylt request); CeedChk(ierr); 20963bd813ffSjeremylt } 2097e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 20983bd813ffSjeremylt } 20993bd813ffSjeremylt 21007a982d89SJeremy L. Thompson /** 21017a982d89SJeremy L. Thompson @brief View a CeedOperator 21027a982d89SJeremy L. Thompson 21037a982d89SJeremy L. Thompson @param[in] op CeedOperator to view 21047a982d89SJeremy L. Thompson @param[in] stream Stream to write; typically stdout/stderr or a file 21057a982d89SJeremy L. Thompson 21067a982d89SJeremy L. Thompson @return Error code: 0 - success, otherwise - failure 21077a982d89SJeremy L. Thompson 21087a982d89SJeremy L. Thompson @ref User 21097a982d89SJeremy L. Thompson **/ 21107a982d89SJeremy L. Thompson int CeedOperatorView(CeedOperator op, FILE *stream) { 21117a982d89SJeremy L. Thompson int ierr; 21127a982d89SJeremy L. Thompson 21137a982d89SJeremy L. Thompson if (op->composite) { 21147a982d89SJeremy L. Thompson fprintf(stream, "Composite CeedOperator\n"); 21157a982d89SJeremy L. Thompson 21167a982d89SJeremy L. Thompson for (CeedInt i=0; i<op->numsub; i++) { 21177a982d89SJeremy L. Thompson fprintf(stream, " SubOperator [%d]:\n", i); 21187a982d89SJeremy L. Thompson ierr = CeedOperatorSingleView(op->suboperators[i], 1, stream); 21197a982d89SJeremy L. Thompson CeedChk(ierr); 21207a982d89SJeremy L. Thompson } 21217a982d89SJeremy L. Thompson } else { 21227a982d89SJeremy L. Thompson fprintf(stream, "CeedOperator\n"); 21237a982d89SJeremy L. Thompson ierr = CeedOperatorSingleView(op, 0, stream); CeedChk(ierr); 21247a982d89SJeremy L. Thompson } 2125e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 21267a982d89SJeremy L. Thompson } 21273bd813ffSjeremylt 21283bd813ffSjeremylt /** 21293bd813ffSjeremylt @brief Apply CeedOperator to a vector 2130d7b241e6Sjeremylt 2131d7b241e6Sjeremylt This computes the action of the operator on the specified (active) input, 2132d7b241e6Sjeremylt yielding its (active) output. All inputs and outputs must be specified using 2133d7b241e6Sjeremylt CeedOperatorSetField(). 2134d7b241e6Sjeremylt 2135d7b241e6Sjeremylt @param op CeedOperator to apply 21364cc79fe7SJed Brown @param[in] in CeedVector containing input state or @ref CEED_VECTOR_NONE if 213734138859Sjeremylt there are no active inputs 2138b11c1e72Sjeremylt @param[out] out CeedVector to store result of applying operator (must be 21394cc79fe7SJed Brown distinct from @a in) or @ref CEED_VECTOR_NONE if there are no 214034138859Sjeremylt active outputs 2141d7b241e6Sjeremylt @param request Address of CeedRequest for non-blocking completion, else 21424cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 2143b11c1e72Sjeremylt 2144b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 2145dfdf5a53Sjeremylt 21467a982d89SJeremy L. Thompson @ref User 2147b11c1e72Sjeremylt **/ 2148692c2638Sjeremylt int CeedOperatorApply(CeedOperator op, CeedVector in, CeedVector out, 2149692c2638Sjeremylt CeedRequest *request) { 2150d7b241e6Sjeremylt int ierr; 2151e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 2152d7b241e6Sjeremylt 2153250756a7Sjeremylt if (op->numelements) { 2154250756a7Sjeremylt // Standard Operator 2155cae8b89aSjeremylt if (op->Apply) { 2156250756a7Sjeremylt ierr = op->Apply(op, in, out, request); CeedChk(ierr); 2157cae8b89aSjeremylt } else { 2158cae8b89aSjeremylt // Zero all output vectors 2159250756a7Sjeremylt CeedQFunction qf = op->qf; 2160cae8b89aSjeremylt for (CeedInt i=0; i<qf->numoutputfields; i++) { 2161cae8b89aSjeremylt CeedVector vec = op->outputfields[i]->vec; 2162cae8b89aSjeremylt if (vec == CEED_VECTOR_ACTIVE) 2163cae8b89aSjeremylt vec = out; 2164cae8b89aSjeremylt if (vec != CEED_VECTOR_NONE) { 2165cae8b89aSjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 2166cae8b89aSjeremylt } 2167cae8b89aSjeremylt } 2168250756a7Sjeremylt // Apply 2169250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 2170250756a7Sjeremylt } 2171250756a7Sjeremylt } else if (op->composite) { 2172250756a7Sjeremylt // Composite Operator 2173250756a7Sjeremylt if (op->ApplyComposite) { 2174250756a7Sjeremylt ierr = op->ApplyComposite(op, in, out, request); CeedChk(ierr); 2175250756a7Sjeremylt } else { 2176250756a7Sjeremylt CeedInt numsub; 2177250756a7Sjeremylt ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 2178250756a7Sjeremylt CeedOperator *suboperators; 2179250756a7Sjeremylt ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 2180250756a7Sjeremylt 2181250756a7Sjeremylt // Zero all output vectors 2182250756a7Sjeremylt if (out != CEED_VECTOR_NONE) { 2183cae8b89aSjeremylt ierr = CeedVectorSetValue(out, 0.0); CeedChk(ierr); 2184cae8b89aSjeremylt } 2185250756a7Sjeremylt for (CeedInt i=0; i<numsub; i++) { 2186250756a7Sjeremylt for (CeedInt j=0; j<suboperators[i]->qf->numoutputfields; j++) { 2187250756a7Sjeremylt CeedVector vec = suboperators[i]->outputfields[j]->vec; 2188250756a7Sjeremylt if (vec != CEED_VECTOR_ACTIVE && vec != CEED_VECTOR_NONE) { 2189250756a7Sjeremylt ierr = CeedVectorSetValue(vec, 0.0); CeedChk(ierr); 2190250756a7Sjeremylt } 2191250756a7Sjeremylt } 2192250756a7Sjeremylt } 2193250756a7Sjeremylt // Apply 2194250756a7Sjeremylt for (CeedInt i=0; i<op->numsub; i++) { 2195250756a7Sjeremylt ierr = CeedOperatorApplyAdd(op->suboperators[i], in, out, request); 2196cae8b89aSjeremylt CeedChk(ierr); 2197cae8b89aSjeremylt } 2198cae8b89aSjeremylt } 2199250756a7Sjeremylt } 2200e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2201cae8b89aSjeremylt } 2202cae8b89aSjeremylt 2203cae8b89aSjeremylt /** 2204cae8b89aSjeremylt @brief Apply CeedOperator to a vector and add result to output vector 2205cae8b89aSjeremylt 2206cae8b89aSjeremylt This computes the action of the operator on the specified (active) input, 2207cae8b89aSjeremylt yielding its (active) output. All inputs and outputs must be specified using 2208cae8b89aSjeremylt CeedOperatorSetField(). 2209cae8b89aSjeremylt 2210cae8b89aSjeremylt @param op CeedOperator to apply 2211cae8b89aSjeremylt @param[in] in CeedVector containing input state or NULL if there are no 2212cae8b89aSjeremylt active inputs 2213cae8b89aSjeremylt @param[out] out CeedVector to sum in result of applying operator (must be 2214cae8b89aSjeremylt distinct from @a in) or NULL if there are no active outputs 2215cae8b89aSjeremylt @param request Address of CeedRequest for non-blocking completion, else 22164cc79fe7SJed Brown @ref CEED_REQUEST_IMMEDIATE 2217cae8b89aSjeremylt 2218cae8b89aSjeremylt @return An error code: 0 - success, otherwise - failure 2219cae8b89aSjeremylt 22207a982d89SJeremy L. Thompson @ref User 2221cae8b89aSjeremylt **/ 2222cae8b89aSjeremylt int CeedOperatorApplyAdd(CeedOperator op, CeedVector in, CeedVector out, 2223cae8b89aSjeremylt CeedRequest *request) { 2224cae8b89aSjeremylt int ierr; 2225e2f04181SAndrew T. Barker ierr = CeedOperatorCheckReady(op); CeedChk(ierr); 2226cae8b89aSjeremylt 2227250756a7Sjeremylt if (op->numelements) { 2228250756a7Sjeremylt // Standard Operator 2229250756a7Sjeremylt ierr = op->ApplyAdd(op, in, out, request); CeedChk(ierr); 2230250756a7Sjeremylt } else if (op->composite) { 2231250756a7Sjeremylt // Composite Operator 2232250756a7Sjeremylt if (op->ApplyAddComposite) { 2233250756a7Sjeremylt ierr = op->ApplyAddComposite(op, in, out, request); CeedChk(ierr); 2234cae8b89aSjeremylt } else { 2235250756a7Sjeremylt CeedInt numsub; 2236250756a7Sjeremylt ierr = CeedOperatorGetNumSub(op, &numsub); CeedChk(ierr); 2237250756a7Sjeremylt CeedOperator *suboperators; 2238250756a7Sjeremylt ierr = CeedOperatorGetSubList(op, &suboperators); CeedChk(ierr); 2239250756a7Sjeremylt 2240250756a7Sjeremylt for (CeedInt i=0; i<numsub; i++) { 2241250756a7Sjeremylt ierr = CeedOperatorApplyAdd(suboperators[i], in, out, request); 2242cae8b89aSjeremylt CeedChk(ierr); 22431d7d2407SJeremy L Thompson } 2244250756a7Sjeremylt } 2245250756a7Sjeremylt } 2246e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2247d7b241e6Sjeremylt } 2248d7b241e6Sjeremylt 2249d7b241e6Sjeremylt /** 2250b11c1e72Sjeremylt @brief Destroy a CeedOperator 2251d7b241e6Sjeremylt 2252d7b241e6Sjeremylt @param op CeedOperator to destroy 2253b11c1e72Sjeremylt 2254b11c1e72Sjeremylt @return An error code: 0 - success, otherwise - failure 2255dfdf5a53Sjeremylt 22567a982d89SJeremy L. Thompson @ref User 2257b11c1e72Sjeremylt **/ 2258d7b241e6Sjeremylt int CeedOperatorDestroy(CeedOperator *op) { 2259d7b241e6Sjeremylt int ierr; 2260d7b241e6Sjeremylt 2261e15f9bd0SJeremy L Thompson if (!*op || --(*op)->refcount > 0) return CEED_ERROR_SUCCESS; 2262d7b241e6Sjeremylt if ((*op)->Destroy) { 2263d7b241e6Sjeremylt ierr = (*op)->Destroy(*op); CeedChk(ierr); 2264d7b241e6Sjeremylt } 2265fe2413ffSjeremylt ierr = CeedDestroy(&(*op)->ceed); CeedChk(ierr); 2266fe2413ffSjeremylt // Free fields 22671d102b48SJeremy L Thompson for (int i=0; i<(*op)->nfields; i++) 226852d6035fSJeremy L Thompson if ((*op)->inputfields[i]) { 226915910d16Sjeremylt if ((*op)->inputfields[i]->Erestrict != CEED_ELEMRESTRICTION_NONE) { 227071352a93Sjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->inputfields[i]->Erestrict); 227171352a93Sjeremylt CeedChk(ierr); 227215910d16Sjeremylt } 227371352a93Sjeremylt if ((*op)->inputfields[i]->basis != CEED_BASIS_COLLOCATED) { 227471352a93Sjeremylt ierr = CeedBasisDestroy(&(*op)->inputfields[i]->basis); CeedChk(ierr); 227571352a93Sjeremylt } 227671352a93Sjeremylt if ((*op)->inputfields[i]->vec != CEED_VECTOR_ACTIVE && 227771352a93Sjeremylt (*op)->inputfields[i]->vec != CEED_VECTOR_NONE ) { 227871352a93Sjeremylt ierr = CeedVectorDestroy(&(*op)->inputfields[i]->vec); CeedChk(ierr); 227971352a93Sjeremylt } 2280d99fa3c5SJeremy L Thompson ierr = CeedFree(&(*op)->inputfields[i]->fieldname); CeedChk(ierr); 2281fe2413ffSjeremylt ierr = CeedFree(&(*op)->inputfields[i]); CeedChk(ierr); 2282fe2413ffSjeremylt } 22831d102b48SJeremy L Thompson for (int i=0; i<(*op)->nfields; i++) 2284d0eb30a5Sjeremylt if ((*op)->outputfields[i]) { 228571352a93Sjeremylt ierr = CeedElemRestrictionDestroy(&(*op)->outputfields[i]->Erestrict); 228671352a93Sjeremylt CeedChk(ierr); 228771352a93Sjeremylt if ((*op)->outputfields[i]->basis != CEED_BASIS_COLLOCATED) { 228871352a93Sjeremylt ierr = CeedBasisDestroy(&(*op)->outputfields[i]->basis); CeedChk(ierr); 228971352a93Sjeremylt } 229071352a93Sjeremylt if ((*op)->outputfields[i]->vec != CEED_VECTOR_ACTIVE && 229171352a93Sjeremylt (*op)->outputfields[i]->vec != CEED_VECTOR_NONE ) { 229271352a93Sjeremylt ierr = CeedVectorDestroy(&(*op)->outputfields[i]->vec); CeedChk(ierr); 229371352a93Sjeremylt } 2294d99fa3c5SJeremy L Thompson ierr = CeedFree(&(*op)->outputfields[i]->fieldname); CeedChk(ierr); 2295fe2413ffSjeremylt ierr = CeedFree(&(*op)->outputfields[i]); CeedChk(ierr); 2296fe2413ffSjeremylt } 229752d6035fSJeremy L Thompson // Destroy suboperators 22981d102b48SJeremy L Thompson for (int i=0; i<(*op)->numsub; i++) 229952d6035fSJeremy L Thompson if ((*op)->suboperators[i]) { 230052d6035fSJeremy L Thompson ierr = CeedOperatorDestroy(&(*op)->suboperators[i]); CeedChk(ierr); 230152d6035fSJeremy L Thompson } 2302e15f9bd0SJeremy L Thompson if ((*op)->qf) 2303e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2304e15f9bd0SJeremy L Thompson (*op)->qf->operatorsset--; 2305e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2306d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->qf); CeedChk(ierr); 2307e15f9bd0SJeremy L Thompson if ((*op)->dqf && (*op)->dqf != CEED_QFUNCTION_NONE) 2308e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2309e15f9bd0SJeremy L Thompson (*op)->dqf->operatorsset--; 2310e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2311d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqf); CeedChk(ierr); 2312e15f9bd0SJeremy L Thompson if ((*op)->dqfT && (*op)->dqfT != CEED_QFUNCTION_NONE) 2313e15f9bd0SJeremy L Thompson // LCOV_EXCL_START 2314e15f9bd0SJeremy L Thompson (*op)->dqfT->operatorsset--; 2315e15f9bd0SJeremy L Thompson // LCOV_EXCL_STOP 2316d7b241e6Sjeremylt ierr = CeedQFunctionDestroy(&(*op)->dqfT); CeedChk(ierr); 2317fe2413ffSjeremylt 23185107b09fSJeremy L Thompson // Destroy fallback 23195107b09fSJeremy L Thompson if ((*op)->opfallback) { 23205107b09fSJeremy L Thompson ierr = (*op)->qffallback->Destroy((*op)->qffallback); CeedChk(ierr); 23215107b09fSJeremy L Thompson ierr = CeedFree(&(*op)->qffallback); CeedChk(ierr); 23225107b09fSJeremy L Thompson ierr = (*op)->opfallback->Destroy((*op)->opfallback); CeedChk(ierr); 23235107b09fSJeremy L Thompson ierr = CeedFree(&(*op)->opfallback); CeedChk(ierr); 23245107b09fSJeremy L Thompson } 23255107b09fSJeremy L Thompson 2326fe2413ffSjeremylt ierr = CeedFree(&(*op)->inputfields); CeedChk(ierr); 2327fe2413ffSjeremylt ierr = CeedFree(&(*op)->outputfields); CeedChk(ierr); 232852d6035fSJeremy L Thompson ierr = CeedFree(&(*op)->suboperators); CeedChk(ierr); 2329d7b241e6Sjeremylt ierr = CeedFree(op); CeedChk(ierr); 2330e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 2331d7b241e6Sjeremylt } 2332d7b241e6Sjeremylt 2333d7b241e6Sjeremylt /// @} 2334