121617c04Sjeremylt // Copyright (c) 2017-2018, Lawrence Livermore National Security, LLC. 221617c04Sjeremylt // Produced at the Lawrence Livermore National Laboratory. LLNL-CODE-734707. 321617c04Sjeremylt // All Rights reserved. See files LICENSE and NOTICE for details. 421617c04Sjeremylt // 521617c04Sjeremylt // This file is part of CEED, a collection of benchmarks, miniapps, software 621617c04Sjeremylt // libraries and APIs for efficient high-order finite element and spectral 721617c04Sjeremylt // element discretizations for exascale applications. For more information and 821617c04Sjeremylt // source code availability see http://github.com/ceed. 921617c04Sjeremylt // 1021617c04Sjeremylt // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 1121617c04Sjeremylt // a collaborative effort of two U.S. Department of Energy organizations (Office 1221617c04Sjeremylt // of Science and the National Nuclear Security Administration) responsible for 1321617c04Sjeremylt // the planning and preparation of a capable exascale ecosystem, including 1421617c04Sjeremylt // software, applications, hardware, advanced system engineering and early 1521617c04Sjeremylt // testbed platforms, in support of the nation's exascale computing imperative. 1621617c04Sjeremylt 17*ec3da8bcSJed Brown #include <ceed/ceed.h> 18*ec3da8bcSJed Brown #include <ceed/backend.h> 193d576824SJeremy L Thompson #include <math.h> 203d576824SJeremy L Thompson #include <stdbool.h> 213d576824SJeremy L Thompson #include <stddef.h> 223d576824SJeremy L Thompson #include <stdint.h> 2321617c04Sjeremylt #include "ceed-ref.h" 2421617c04Sjeremylt 25f10650afSjeremylt //------------------------------------------------------------------------------ 26f10650afSjeremylt // Setup Input/Output Fields 27f10650afSjeremylt //------------------------------------------------------------------------------ 28fe2413ffSjeremylt static int CeedOperatorSetupFields_Ref(CeedQFunction qf, CeedOperator op, 2991703d3fSjeremylt bool inOrOut, 3091703d3fSjeremylt CeedVector *fullevecs, CeedVector *evecs, 31aedaa0e5Sjeremylt CeedVector *qvecs, CeedInt starte, 32135a076eSjeremylt CeedInt numfields, CeedInt Q) { 334d537eeaSYohann CeedInt dim, ierr, size, P; 34aedaa0e5Sjeremylt Ceed ceed; 35e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChkBackend(ierr); 36d1bcdac9Sjeremylt CeedBasis basis; 37d1bcdac9Sjeremylt CeedElemRestriction Erestrict; 38aedaa0e5Sjeremylt CeedOperatorField *opfields; 39aedaa0e5Sjeremylt CeedQFunctionField *qffields; 40fe2413ffSjeremylt if (inOrOut) { 41e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetFields(op, NULL, &opfields); CeedChkBackend(ierr); 42e15f9bd0SJeremy L Thompson ierr = CeedQFunctionGetFields(qf, NULL, &qffields); CeedChkBackend(ierr); 43fe2413ffSjeremylt } else { 44e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetFields(op, &opfields, NULL); CeedChkBackend(ierr); 45e15f9bd0SJeremy L Thompson ierr = CeedQFunctionGetFields(qf, &qffields, NULL); CeedChkBackend(ierr); 46fe2413ffSjeremylt } 4721617c04Sjeremylt 48885ac19cSjeremylt // Loop over fields 49885ac19cSjeremylt for (CeedInt i=0; i<numfields; i++) { 50d1bcdac9Sjeremylt CeedEvalMode emode; 51e15f9bd0SJeremy L Thompson ierr = CeedQFunctionFieldGetEvalMode(qffields[i], &emode); CeedChkBackend(ierr); 52135a076eSjeremylt 53135a076eSjeremylt if (emode != CEED_EVAL_WEIGHT) { 54aedaa0e5Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opfields[i], &Erestrict); 55e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 56d1bcdac9Sjeremylt ierr = CeedElemRestrictionCreateVector(Erestrict, NULL, 5791703d3fSjeremylt &fullevecs[i+starte]); 58e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 59135a076eSjeremylt } 60135a076eSjeremylt 61885ac19cSjeremylt switch(emode) { 62885ac19cSjeremylt case CEED_EVAL_NONE: 63e15f9bd0SJeremy L Thompson ierr = CeedQFunctionFieldGetSize(qffields[i], &size); CeedChkBackend(ierr); 64e15f9bd0SJeremy L Thompson ierr = CeedVectorCreate(ceed, Q*size, &qvecs[i]); CeedChkBackend(ierr); 65aedaa0e5Sjeremylt break; 66aedaa0e5Sjeremylt case CEED_EVAL_INTERP: 67e15f9bd0SJeremy L Thompson ierr = CeedQFunctionFieldGetSize(qffields[i], &size); CeedChkBackend(ierr); 684d1cd9fcSJeremy L Thompson ierr = CeedElemRestrictionGetElementSize(Erestrict, &P); 69e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 70e15f9bd0SJeremy L Thompson ierr = CeedVectorCreate(ceed, P*size, &evecs[i]); CeedChkBackend(ierr); 71e15f9bd0SJeremy L Thompson ierr = CeedVectorCreate(ceed, Q*size, &qvecs[i]); CeedChkBackend(ierr); 72885ac19cSjeremylt break; 73885ac19cSjeremylt case CEED_EVAL_GRAD: 74e15f9bd0SJeremy L Thompson ierr = CeedOperatorFieldGetBasis(opfields[i], &basis); CeedChkBackend(ierr); 75e15f9bd0SJeremy L Thompson ierr = CeedQFunctionFieldGetSize(qffields[i], &size); CeedChkBackend(ierr); 76e15f9bd0SJeremy L Thompson ierr = CeedBasisGetDimension(basis, &dim); CeedChkBackend(ierr); 774d1cd9fcSJeremy L Thompson ierr = CeedElemRestrictionGetElementSize(Erestrict, &P); 78e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 79e15f9bd0SJeremy L Thompson ierr = CeedVectorCreate(ceed, P*size/dim, &evecs[i]); CeedChkBackend(ierr); 80e15f9bd0SJeremy L Thompson ierr = CeedVectorCreate(ceed, Q*size, &qvecs[i]); CeedChkBackend(ierr); 81885ac19cSjeremylt break; 82885ac19cSjeremylt case CEED_EVAL_WEIGHT: // Only on input fields 83e15f9bd0SJeremy L Thompson ierr = CeedOperatorFieldGetBasis(opfields[i], &basis); CeedChkBackend(ierr); 84e15f9bd0SJeremy L Thompson ierr = CeedVectorCreate(ceed, Q, &qvecs[i]); CeedChkBackend(ierr); 85d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, CEED_EVAL_WEIGHT, 86e15f9bd0SJeremy L Thompson CEED_VECTOR_NONE, qvecs[i]); CeedChkBackend(ierr); 87885ac19cSjeremylt break; 88885ac19cSjeremylt case CEED_EVAL_DIV: 894d537eeaSYohann break; // Not implemented 90885ac19cSjeremylt case CEED_EVAL_CURL: 914d537eeaSYohann break; // Not implemented 9221617c04Sjeremylt } 93885ac19cSjeremylt } 94e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 9521617c04Sjeremylt } 9621617c04Sjeremylt 97f10650afSjeremylt //------------------------------------------------------------------------------ 98f10650afSjeremylt // Setup Operator 99f10650afSjeremylt //------------------------------------------------------------------------------/* 100885ac19cSjeremylt static int CeedOperatorSetup_Ref(CeedOperator op) { 10121617c04Sjeremylt int ierr; 1024ce2993fSjeremylt bool setupdone; 103e15f9bd0SJeremy L Thompson ierr = CeedOperatorIsSetupDone(op, &setupdone); CeedChkBackend(ierr); 104e15f9bd0SJeremy L Thompson if (setupdone) return CEED_ERROR_SUCCESS; 105aedaa0e5Sjeremylt Ceed ceed; 106e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChkBackend(ierr); 1074ce2993fSjeremylt CeedOperator_Ref *impl; 108e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetData(op, &impl); CeedChkBackend(ierr); 1094ce2993fSjeremylt CeedQFunction qf; 110e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetQFunction(op, &qf); CeedChkBackend(ierr); 1114ce2993fSjeremylt CeedInt Q, numinputfields, numoutputfields; 112e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChkBackend(ierr); 113e15f9bd0SJeremy L Thompson ierr = CeedQFunctionIsIdentity(qf, &impl->identityqf); CeedChkBackend(ierr); 114a8de75f0Sjeremylt ierr = CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 115e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 116d1bcdac9Sjeremylt CeedOperatorField *opinputfields, *opoutputfields; 117d1bcdac9Sjeremylt ierr = CeedOperatorGetFields(op, &opinputfields, &opoutputfields); 118e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 119d1bcdac9Sjeremylt CeedQFunctionField *qfinputfields, *qfoutputfields; 120d1bcdac9Sjeremylt ierr = CeedQFunctionGetFields(qf, &qfinputfields, &qfoutputfields); 121e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 122885ac19cSjeremylt 123885ac19cSjeremylt // Allocate 124aedaa0e5Sjeremylt ierr = CeedCalloc(numinputfields + numoutputfields, &impl->evecs); 125e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 126aedaa0e5Sjeremylt ierr = CeedCalloc(numinputfields + numoutputfields, &impl->edata); 127e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 128885ac19cSjeremylt 129e15f9bd0SJeremy L Thompson ierr = CeedCalloc(16, &impl->inputstate); CeedChkBackend(ierr); 130e15f9bd0SJeremy L Thompson ierr = CeedCalloc(16, &impl->evecsin); CeedChkBackend(ierr); 131e15f9bd0SJeremy L Thompson ierr = CeedCalloc(16, &impl->evecsout); CeedChkBackend(ierr); 132e15f9bd0SJeremy L Thompson ierr = CeedCalloc(16, &impl->qvecsin); CeedChkBackend(ierr); 133e15f9bd0SJeremy L Thompson ierr = CeedCalloc(16, &impl->qvecsout); CeedChkBackend(ierr); 134885ac19cSjeremylt 135aedaa0e5Sjeremylt impl->numein = numinputfields; impl->numeout = numoutputfields; 136885ac19cSjeremylt 137aedaa0e5Sjeremylt // Set up infield and outfield evecs and qvecs 138885ac19cSjeremylt // Infields 13991703d3fSjeremylt ierr = CeedOperatorSetupFields_Ref(qf, op, 0, impl->evecs, 14091703d3fSjeremylt impl->evecsin, impl->qvecsin, 0, 141aedaa0e5Sjeremylt numinputfields, Q); 142e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 143885ac19cSjeremylt // Outfields 14491703d3fSjeremylt ierr = CeedOperatorSetupFields_Ref(qf, op, 1, impl->evecs, 14591703d3fSjeremylt impl->evecsout, impl->qvecsout, 146aedaa0e5Sjeremylt numinputfields, numoutputfields, Q); 147e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 148885ac19cSjeremylt 14916911fdaSjeremylt // Identity QFunctions 15016911fdaSjeremylt if (impl->identityqf) { 15116911fdaSjeremylt CeedEvalMode inmode, outmode; 15216911fdaSjeremylt CeedQFunctionField *infields, *outfields; 153e15f9bd0SJeremy L Thompson ierr = CeedQFunctionGetFields(qf, &infields, &outfields); CeedChkBackend(ierr); 15416911fdaSjeremylt 15516911fdaSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 15616911fdaSjeremylt ierr = CeedQFunctionFieldGetEvalMode(infields[i], &inmode); 157e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 15816911fdaSjeremylt ierr = CeedQFunctionFieldGetEvalMode(outfields[i], &outmode); 159e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 16016911fdaSjeremylt 161e15f9bd0SJeremy L Thompson ierr = CeedVectorDestroy(&impl->qvecsout[i]); CeedChkBackend(ierr); 16216911fdaSjeremylt impl->qvecsout[i] = impl->qvecsin[i]; 163e15f9bd0SJeremy L Thompson ierr = CeedVectorAddReference(impl->qvecsin[i]); CeedChkBackend(ierr); 16416911fdaSjeremylt } 16516911fdaSjeremylt } 16616911fdaSjeremylt 167e15f9bd0SJeremy L Thompson ierr = CeedOperatorSetSetupDone(op); CeedChkBackend(ierr); 168885ac19cSjeremylt 169e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 170885ac19cSjeremylt } 171885ac19cSjeremylt 172f10650afSjeremylt //------------------------------------------------------------------------------ 173f10650afSjeremylt // Setup Operator Inputs 174f10650afSjeremylt //------------------------------------------------------------------------------ 1751d102b48SJeremy L Thompson static inline int CeedOperatorSetupInputs_Ref(CeedInt numinputfields, 1761d102b48SJeremy L Thompson CeedQFunctionField *qfinputfields, CeedOperatorField *opinputfields, 1771d102b48SJeremy L Thompson CeedVector invec, const bool skipactive, CeedOperator_Ref *impl, 1781d102b48SJeremy L Thompson CeedRequest *request) { 1791d102b48SJeremy L Thompson CeedInt ierr; 180d1bcdac9Sjeremylt CeedEvalMode emode; 181d1bcdac9Sjeremylt CeedVector vec; 182d1bcdac9Sjeremylt CeedElemRestriction Erestrict; 1838d713cf6Sjeremylt uint64_t state; 184885ac19cSjeremylt 1851a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 186d1bcdac9Sjeremylt // Get input vector 187e15f9bd0SJeremy L Thompson ierr = CeedOperatorFieldGetVector(opinputfields[i], &vec); CeedChkBackend(ierr); 1881d102b48SJeremy L Thompson if (vec == CEED_VECTOR_ACTIVE) { 1891d102b48SJeremy L Thompson if (skipactive) 1901d102b48SJeremy L Thompson continue; 1911d102b48SJeremy L Thompson else 192d1bcdac9Sjeremylt vec = invec; 1931d102b48SJeremy L Thompson } 1941d102b48SJeremy L Thompson 1951d102b48SJeremy L Thompson ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 196e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1971d102b48SJeremy L Thompson // Restrict and Evec 1981d102b48SJeremy L Thompson if (emode == CEED_EVAL_WEIGHT) { // Skip 1991d102b48SJeremy L Thompson } else { 200668048e2SJed Brown // Restrict 201e15f9bd0SJeremy L Thompson ierr = CeedVectorGetState(vec, &state); CeedChkBackend(ierr); 2028d713cf6Sjeremylt // Skip restriction if input is unchanged 2038d713cf6Sjeremylt if (state != impl->inputstate[i] || vec == invec) { 204d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opinputfields[i], &Erestrict); 205e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 206a8d32208Sjeremylt ierr = CeedElemRestrictionApply(Erestrict, CEED_NOTRANSPOSE, vec, 207e15f9bd0SJeremy L Thompson impl->evecs[i], request); CeedChkBackend(ierr); 2088d713cf6Sjeremylt impl->inputstate[i] = state; 2098d713cf6Sjeremylt } 210668048e2SJed Brown // Get evec 211a2b73c81Sjeremylt ierr = CeedVectorGetArrayRead(impl->evecs[i], CEED_MEM_HOST, 212d1bcdac9Sjeremylt (const CeedScalar **) &impl->edata[i]); 213e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 214885ac19cSjeremylt } 215885ac19cSjeremylt } 216e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 217885ac19cSjeremylt } 218885ac19cSjeremylt 219f10650afSjeremylt //------------------------------------------------------------------------------ 220f10650afSjeremylt // Input Basis Action 221f10650afSjeremylt //------------------------------------------------------------------------------ 2221d102b48SJeremy L Thompson static inline int CeedOperatorInputBasis_Ref(CeedInt e, CeedInt Q, 2231d102b48SJeremy L Thompson CeedQFunctionField *qfinputfields, CeedOperatorField *opinputfields, 2241d102b48SJeremy L Thompson CeedInt numinputfields, const bool skipactive, CeedOperator_Ref *impl) { 2251d102b48SJeremy L Thompson CeedInt ierr; 2261d102b48SJeremy L Thompson CeedInt dim, elemsize, size; 2271d102b48SJeremy L Thompson CeedElemRestriction Erestrict; 2281d102b48SJeremy L Thompson CeedEvalMode emode; 2291d102b48SJeremy L Thompson CeedBasis basis; 2301d102b48SJeremy L Thompson 2311a4ead9bSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 2321d102b48SJeremy L Thompson // Skip active input 2331d102b48SJeremy L Thompson if (skipactive) { 2341d102b48SJeremy L Thompson CeedVector vec; 235e15f9bd0SJeremy L Thompson ierr = CeedOperatorFieldGetVector(opinputfields[i], &vec); CeedChkBackend(ierr); 2361d102b48SJeremy L Thompson if (vec == CEED_VECTOR_ACTIVE) 2371d102b48SJeremy L Thompson continue; 2381d102b48SJeremy L Thompson } 2394d537eeaSYohann // Get elemsize, emode, size 240d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opinputfields[i], &Erestrict); 241e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 242d1bcdac9Sjeremylt ierr = CeedElemRestrictionGetElementSize(Erestrict, &elemsize); 243e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 244d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 245e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 246e15f9bd0SJeremy L Thompson ierr = CeedQFunctionFieldGetSize(qfinputfields[i], &size); CeedChkBackend(ierr); 247885ac19cSjeremylt // Basis action 248885ac19cSjeremylt switch(emode) { 249885ac19cSjeremylt case CEED_EVAL_NONE: 250aedaa0e5Sjeremylt ierr = CeedVectorSetArray(impl->qvecsin[i], CEED_MEM_HOST, 251aedaa0e5Sjeremylt CEED_USE_POINTER, 252e15f9bd0SJeremy L Thompson &impl->edata[i][e*Q*size]); CeedChkBackend(ierr); 253885ac19cSjeremylt break; 254885ac19cSjeremylt case CEED_EVAL_INTERP: 255e15f9bd0SJeremy L Thompson ierr = CeedOperatorFieldGetBasis(opinputfields[i], &basis); 256e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 25791703d3fSjeremylt ierr = CeedVectorSetArray(impl->evecsin[i], CEED_MEM_HOST, 258aedaa0e5Sjeremylt CEED_USE_POINTER, 2594d537eeaSYohann &impl->edata[i][e*elemsize*size]); 260e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 261d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, 26291703d3fSjeremylt CEED_EVAL_INTERP, impl->evecsin[i], 263e15f9bd0SJeremy L Thompson impl->qvecsin[i]); CeedChkBackend(ierr); 264885ac19cSjeremylt break; 265885ac19cSjeremylt case CEED_EVAL_GRAD: 266e15f9bd0SJeremy L Thompson ierr = CeedOperatorFieldGetBasis(opinputfields[i], &basis); 267e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 268e15f9bd0SJeremy L Thompson ierr = CeedBasisGetDimension(basis, &dim); CeedChkBackend(ierr); 26991703d3fSjeremylt ierr = CeedVectorSetArray(impl->evecsin[i], CEED_MEM_HOST, 270aedaa0e5Sjeremylt CEED_USE_POINTER, 2714d537eeaSYohann &impl->edata[i][e*elemsize*size/dim]); 272e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 273d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, 27491703d3fSjeremylt CEED_EVAL_GRAD, impl->evecsin[i], 275e15f9bd0SJeremy L Thompson impl->qvecsin[i]); CeedChkBackend(ierr); 276885ac19cSjeremylt break; 277885ac19cSjeremylt case CEED_EVAL_WEIGHT: 278885ac19cSjeremylt break; // No action 279bbfacfcdSjeremylt // LCOV_EXCL_START 280885ac19cSjeremylt case CEED_EVAL_DIV: 2811d102b48SJeremy L Thompson case CEED_EVAL_CURL: { 2821d102b48SJeremy L Thompson ierr = CeedOperatorFieldGetBasis(opinputfields[i], &basis); 283e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 2841d102b48SJeremy L Thompson Ceed ceed; 285e15f9bd0SJeremy L Thompson ierr = CeedBasisGetCeed(basis, &ceed); CeedChkBackend(ierr); 286e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 287e15f9bd0SJeremy L Thompson "Ceed evaluation mode not implemented"); 288bbfacfcdSjeremylt // LCOV_EXCL_STOP 289885ac19cSjeremylt } 290885ac19cSjeremylt } 291885ac19cSjeremylt } 292e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 293885ac19cSjeremylt } 294885ac19cSjeremylt 295f10650afSjeremylt //------------------------------------------------------------------------------ 296f10650afSjeremylt // Output Basis Action 297f10650afSjeremylt //------------------------------------------------------------------------------ 2981d102b48SJeremy L Thompson static inline int CeedOperatorOutputBasis_Ref(CeedInt e, CeedInt Q, 2991d102b48SJeremy L Thompson CeedQFunctionField *qfoutputfields, CeedOperatorField *opoutputfields, 3001d102b48SJeremy L Thompson CeedInt numinputfields, CeedInt numoutputfields, CeedOperator op, 3011d102b48SJeremy L Thompson CeedOperator_Ref *impl) { 3021d102b48SJeremy L Thompson CeedInt ierr; 3031d102b48SJeremy L Thompson CeedInt dim, elemsize, size; 3041d102b48SJeremy L Thompson CeedElemRestriction Erestrict; 3051d102b48SJeremy L Thompson CeedEvalMode emode; 3061d102b48SJeremy L Thompson CeedBasis basis; 3071d102b48SJeremy L Thompson 3081a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 3094d537eeaSYohann // Get elemsize, emode, size 310d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opoutputfields[i], &Erestrict); 311e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 312d1bcdac9Sjeremylt ierr = CeedElemRestrictionGetElementSize(Erestrict, &elemsize); 313e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 314d1bcdac9Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode); 315e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 316e15f9bd0SJeremy L Thompson ierr = CeedQFunctionFieldGetSize(qfoutputfields[i], &size); 317e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 318885ac19cSjeremylt // Basis action 319885ac19cSjeremylt switch(emode) { 320885ac19cSjeremylt case CEED_EVAL_NONE: 321885ac19cSjeremylt break; // No action 322885ac19cSjeremylt case CEED_EVAL_INTERP: 323d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opoutputfields[i], &basis); 324e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 32591703d3fSjeremylt ierr = CeedVectorSetArray(impl->evecsout[i], CEED_MEM_HOST, 326aedaa0e5Sjeremylt CEED_USE_POINTER, 3274d537eeaSYohann &impl->edata[i + numinputfields][e*elemsize*size]); 328e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 329aedaa0e5Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, 330aedaa0e5Sjeremylt CEED_EVAL_INTERP, impl->qvecsout[i], 331e15f9bd0SJeremy L Thompson impl->evecsout[i]); CeedChkBackend(ierr); 332885ac19cSjeremylt break; 333885ac19cSjeremylt case CEED_EVAL_GRAD: 334d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetBasis(opoutputfields[i], &basis); 335e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 336e15f9bd0SJeremy L Thompson ierr = CeedBasisGetDimension(basis, &dim); CeedChkBackend(ierr); 33791703d3fSjeremylt ierr = CeedVectorSetArray(impl->evecsout[i], CEED_MEM_HOST, 338aedaa0e5Sjeremylt CEED_USE_POINTER, 3394d537eeaSYohann &impl->edata[i + numinputfields][e*elemsize*size/dim]); 340e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 341aedaa0e5Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, 342aedaa0e5Sjeremylt CEED_EVAL_GRAD, impl->qvecsout[i], 343e15f9bd0SJeremy L Thompson impl->evecsout[i]); CeedChkBackend(ierr); 344885ac19cSjeremylt break; 345c042f62fSJeremy L Thompson // LCOV_EXCL_START 346bbfacfcdSjeremylt case CEED_EVAL_WEIGHT: { 3474ce2993fSjeremylt Ceed ceed; 348e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChkBackend(ierr); 349e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 350e15f9bd0SJeremy L Thompson "CEED_EVAL_WEIGHT cannot be an output " 3511d102b48SJeremy L Thompson "evaluation mode"); 3524ce2993fSjeremylt } 353885ac19cSjeremylt case CEED_EVAL_DIV: 3541d102b48SJeremy L Thompson case CEED_EVAL_CURL: { 3551d102b48SJeremy L Thompson Ceed ceed; 356e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChkBackend(ierr); 357e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 358e15f9bd0SJeremy L Thompson "Ceed evaluation mode not implemented"); 3591d102b48SJeremy L Thompson // LCOV_EXCL_STOP 360885ac19cSjeremylt } 361885ac19cSjeremylt } 362885ac19cSjeremylt } 363e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3641d102b48SJeremy L Thompson } 3651d102b48SJeremy L Thompson 366f10650afSjeremylt //------------------------------------------------------------------------------ 367f10650afSjeremylt // Restore Input Vectors 368f10650afSjeremylt //------------------------------------------------------------------------------ 3691d102b48SJeremy L Thompson static inline int CeedOperatorRestoreInputs_Ref(CeedInt numinputfields, 3701d102b48SJeremy L Thompson CeedQFunctionField *qfinputfields, CeedOperatorField *opinputfields, 3711d102b48SJeremy L Thompson const bool skipactive, CeedOperator_Ref *impl) { 3721d102b48SJeremy L Thompson CeedInt ierr; 3731d102b48SJeremy L Thompson CeedEvalMode emode; 3741d102b48SJeremy L Thompson 3751d102b48SJeremy L Thompson for (CeedInt i=0; i<numinputfields; i++) { 3761d102b48SJeremy L Thompson // Skip active inputs 3771d102b48SJeremy L Thompson if (skipactive) { 3781d102b48SJeremy L Thompson CeedVector vec; 379e15f9bd0SJeremy L Thompson ierr = CeedOperatorFieldGetVector(opinputfields[i], &vec); CeedChkBackend(ierr); 3801d102b48SJeremy L Thompson if (vec == CEED_VECTOR_ACTIVE) 3811d102b48SJeremy L Thompson continue; 3821d102b48SJeremy L Thompson } 3831d102b48SJeremy L Thompson // Restore input 3841d102b48SJeremy L Thompson ierr = CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode); 385e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 3861d102b48SJeremy L Thompson if (emode == CEED_EVAL_WEIGHT) { // Skip 3871d102b48SJeremy L Thompson } else { 3881d102b48SJeremy L Thompson ierr = CeedVectorRestoreArrayRead(impl->evecs[i], 3891d102b48SJeremy L Thompson (const CeedScalar **) &impl->edata[i]); 390e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 3911d102b48SJeremy L Thompson } 3921d102b48SJeremy L Thompson } 393e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3941d102b48SJeremy L Thompson } 3951d102b48SJeremy L Thompson 396f10650afSjeremylt //------------------------------------------------------------------------------ 397f10650afSjeremylt // Operator Apply 398f10650afSjeremylt //------------------------------------------------------------------------------ 39969af5e5fSJeremy L Thompson static int CeedOperatorApplyAdd_Ref(CeedOperator op, CeedVector invec, 4001d102b48SJeremy L Thompson CeedVector outvec, CeedRequest *request) { 4011d102b48SJeremy L Thompson int ierr; 4021d102b48SJeremy L Thompson CeedOperator_Ref *impl; 403e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetData(op, &impl); CeedChkBackend(ierr); 4041d102b48SJeremy L Thompson CeedQFunction qf; 405e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetQFunction(op, &qf); CeedChkBackend(ierr); 4061d102b48SJeremy L Thompson CeedInt Q, numelements, numinputfields, numoutputfields, size; 407e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChkBackend(ierr); 408e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetNumElements(op, &numelements); CeedChkBackend(ierr); 4091d102b48SJeremy L Thompson ierr= CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 410e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 4111d102b48SJeremy L Thompson CeedOperatorField *opinputfields, *opoutputfields; 4121d102b48SJeremy L Thompson ierr = CeedOperatorGetFields(op, &opinputfields, &opoutputfields); 413e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 4141d102b48SJeremy L Thompson CeedQFunctionField *qfinputfields, *qfoutputfields; 4151d102b48SJeremy L Thompson ierr = CeedQFunctionGetFields(qf, &qfinputfields, &qfoutputfields); 416e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 4171d102b48SJeremy L Thompson CeedEvalMode emode; 4181d102b48SJeremy L Thompson CeedVector vec; 4191d102b48SJeremy L Thompson CeedElemRestriction Erestrict; 4201d102b48SJeremy L Thompson 4211d102b48SJeremy L Thompson // Setup 422e15f9bd0SJeremy L Thompson ierr = CeedOperatorSetup_Ref(op); CeedChkBackend(ierr); 4231d102b48SJeremy L Thompson 4241d102b48SJeremy L Thompson // Input Evecs and Restriction 4251d102b48SJeremy L Thompson ierr = CeedOperatorSetupInputs_Ref(numinputfields, qfinputfields, 4261d102b48SJeremy L Thompson opinputfields, invec, false, impl, 427e15f9bd0SJeremy L Thompson request); CeedChkBackend(ierr); 4281d102b48SJeremy L Thompson 4291d102b48SJeremy L Thompson // Output Evecs 4301d102b48SJeremy L Thompson for (CeedInt i=0; i<numoutputfields; i++) { 4311d102b48SJeremy L Thompson ierr = CeedVectorGetArray(impl->evecs[i+impl->numein], CEED_MEM_HOST, 432e15f9bd0SJeremy L Thompson &impl->edata[i + numinputfields]); CeedChkBackend(ierr); 4331d102b48SJeremy L Thompson } 4341d102b48SJeremy L Thompson 4351d102b48SJeremy L Thompson // Loop through elements 4361d102b48SJeremy L Thompson for (CeedInt e=0; e<numelements; e++) { 4371d102b48SJeremy L Thompson // Output pointers 4381d102b48SJeremy L Thompson for (CeedInt i=0; i<numoutputfields; i++) { 4391d102b48SJeremy L Thompson ierr = CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode); 440e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 4411d102b48SJeremy L Thompson if (emode == CEED_EVAL_NONE) { 4421d102b48SJeremy L Thompson ierr = CeedQFunctionFieldGetSize(qfoutputfields[i], &size); 443e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 4441d102b48SJeremy L Thompson ierr = CeedVectorSetArray(impl->qvecsout[i], CEED_MEM_HOST, 4451d102b48SJeremy L Thompson CEED_USE_POINTER, 4461d102b48SJeremy L Thompson &impl->edata[i + numinputfields][e*Q*size]); 447e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 4481d102b48SJeremy L Thompson } 4491d102b48SJeremy L Thompson } 4501d102b48SJeremy L Thompson 45116911fdaSjeremylt // Input basis apply 45216911fdaSjeremylt ierr = CeedOperatorInputBasis_Ref(e, Q, qfinputfields, opinputfields, 45316911fdaSjeremylt numinputfields, false, impl); 454e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 45516911fdaSjeremylt 4561d102b48SJeremy L Thompson // Q function 45716911fdaSjeremylt if (!impl->identityqf) { 45816911fdaSjeremylt ierr = CeedQFunctionApply(qf, Q, impl->qvecsin, impl->qvecsout); 459e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 46016911fdaSjeremylt } 4611d102b48SJeremy L Thompson 4621d102b48SJeremy L Thompson // Output basis apply 4631d102b48SJeremy L Thompson ierr = CeedOperatorOutputBasis_Ref(e, Q, qfoutputfields, opoutputfields, 4641d102b48SJeremy L Thompson numinputfields, numoutputfields, op, impl); 465e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 4661d102b48SJeremy L Thompson } 467885ac19cSjeremylt 468885ac19cSjeremylt // Output restriction 4691a4ead9bSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 470a2b73c81Sjeremylt // Restore evec 471a2b73c81Sjeremylt ierr = CeedVectorRestoreArray(impl->evecs[i+impl->numein], 472d1bcdac9Sjeremylt &impl->edata[i + numinputfields]); 473e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 474d1bcdac9Sjeremylt // Get output vector 475e15f9bd0SJeremy L Thompson ierr = CeedOperatorFieldGetVector(opoutputfields[i], &vec); 476e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 477668048e2SJed Brown // Active 478d1bcdac9Sjeremylt if (vec == CEED_VECTOR_ACTIVE) 479d1bcdac9Sjeremylt vec = outvec; 4807ca8db16Sjeremylt // Restrict 481d1bcdac9Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opoutputfields[i], &Erestrict); 482e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 483d1bcdac9Sjeremylt ierr = CeedElemRestrictionApply(Erestrict, CEED_TRANSPOSE, 484a8d32208Sjeremylt impl->evecs[i+impl->numein], vec, request); 485e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 486885ac19cSjeremylt } 487885ac19cSjeremylt 4887ca8db16Sjeremylt // Restore input arrays 4891d102b48SJeremy L Thompson ierr = CeedOperatorRestoreInputs_Ref(numinputfields, qfinputfields, 4901d102b48SJeremy L Thompson opinputfields, false, impl); 491e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 4927ca8db16Sjeremylt 493e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 49421617c04Sjeremylt } 49521617c04Sjeremylt 496f10650afSjeremylt //------------------------------------------------------------------------------ 4971d102b48SJeremy L Thompson // Assemble Linear QFunction 498f10650afSjeremylt //------------------------------------------------------------------------------ 49980ac2e43SJeremy L Thompson static int CeedOperatorLinearAssembleQFunction_Ref(CeedOperator op, 5001d102b48SJeremy L Thompson CeedVector *assembled, CeedElemRestriction *rstr, CeedRequest *request) { 5011d102b48SJeremy L Thompson int ierr; 5021d102b48SJeremy L Thompson CeedOperator_Ref *impl; 503e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetData(op, &impl); CeedChkBackend(ierr); 5041d102b48SJeremy L Thompson CeedQFunction qf; 505e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetQFunction(op, &qf); CeedChkBackend(ierr); 5061d102b48SJeremy L Thompson CeedInt Q, numelements, numinputfields, numoutputfields, size; 507e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChkBackend(ierr); 508e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetNumElements(op, &numelements); CeedChkBackend(ierr); 5091d102b48SJeremy L Thompson ierr= CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 510e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 5111d102b48SJeremy L Thompson CeedOperatorField *opinputfields, *opoutputfields; 5121d102b48SJeremy L Thompson ierr = CeedOperatorGetFields(op, &opinputfields, &opoutputfields); 513e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 5141d102b48SJeremy L Thompson CeedQFunctionField *qfinputfields, *qfoutputfields; 5151d102b48SJeremy L Thompson ierr = CeedQFunctionGetFields(qf, &qfinputfields, &qfoutputfields); 516e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 5171d102b48SJeremy L Thompson CeedVector vec; 5181d102b48SJeremy L Thompson CeedInt numactivein = 0, numactiveout = 0; 51942ea3801Sjeremylt CeedVector *activein = NULL; 5201d102b48SJeremy L Thompson CeedScalar *a, *tmp; 5215107b09fSJeremy L Thompson Ceed ceed, ceedparent; 522e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChkBackend(ierr); 523e15f9bd0SJeremy L Thompson ierr = CeedGetOperatorFallbackParentCeed(ceed, &ceedparent); 524e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 5255107b09fSJeremy L Thompson ceedparent = ceedparent ? ceedparent : ceed; 5261d102b48SJeremy L Thompson 5271d102b48SJeremy L Thompson // Setup 528e15f9bd0SJeremy L Thompson ierr = CeedOperatorSetup_Ref(op); CeedChkBackend(ierr); 5291d102b48SJeremy L Thompson 53016911fdaSjeremylt // Check for identity 53116911fdaSjeremylt if (impl->identityqf) 53216911fdaSjeremylt // LCOV_EXCL_START 533e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 534e15f9bd0SJeremy L Thompson "Assembling identity QFunctions not supported"); 53516911fdaSjeremylt // LCOV_EXCL_STOP 53616911fdaSjeremylt 5371d102b48SJeremy L Thompson // Input Evecs and Restriction 5381d102b48SJeremy L Thompson ierr = CeedOperatorSetupInputs_Ref(numinputfields, qfinputfields, 53916911fdaSjeremylt opinputfields, NULL, true, impl, request); 540e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 5411d102b48SJeremy L Thompson 5421d102b48SJeremy L Thompson // Count number of active input fields 5431d102b48SJeremy L Thompson for (CeedInt i=0; i<numinputfields; i++) { 5441d102b48SJeremy L Thompson // Get input vector 545e15f9bd0SJeremy L Thompson ierr = CeedOperatorFieldGetVector(opinputfields[i], &vec); CeedChkBackend(ierr); 5461d102b48SJeremy L Thompson // Check if active input 5471d102b48SJeremy L Thompson if (vec == CEED_VECTOR_ACTIVE) { 548e15f9bd0SJeremy L Thompson ierr = CeedQFunctionFieldGetSize(qfinputfields[i], &size); CeedChkBackend(ierr); 549e15f9bd0SJeremy L Thompson ierr = CeedVectorSetValue(impl->qvecsin[i], 0.0); CeedChkBackend(ierr); 5501d102b48SJeremy L Thompson ierr = CeedVectorGetArray(impl->qvecsin[i], CEED_MEM_HOST, &tmp); 551e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 552e15f9bd0SJeremy L Thompson ierr = CeedRealloc(numactivein + size, &activein); CeedChkBackend(ierr); 5531d102b48SJeremy L Thompson for (CeedInt field=0; field<size; field++) { 55442ea3801Sjeremylt ierr = CeedVectorCreate(ceed, Q, &activein[numactivein+field]); 555e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 55642ea3801Sjeremylt ierr = CeedVectorSetArray(activein[numactivein+field], CEED_MEM_HOST, 55742ea3801Sjeremylt CEED_USE_POINTER, &tmp[field*Q]); 558e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 5591d102b48SJeremy L Thompson } 5601d102b48SJeremy L Thompson numactivein += size; 561e15f9bd0SJeremy L Thompson ierr = CeedVectorRestoreArray(impl->qvecsin[i], &tmp); CeedChkBackend(ierr); 5621d102b48SJeremy L Thompson } 5631d102b48SJeremy L Thompson } 5641d102b48SJeremy L Thompson 5651d102b48SJeremy L Thompson // Count number of active output fields 5661d102b48SJeremy L Thompson for (CeedInt i=0; i<numoutputfields; i++) { 5671d102b48SJeremy L Thompson // Get output vector 568e15f9bd0SJeremy L Thompson ierr = CeedOperatorFieldGetVector(opoutputfields[i], &vec); 569e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 5701d102b48SJeremy L Thompson // Check if active output 5711d102b48SJeremy L Thompson if (vec == CEED_VECTOR_ACTIVE) { 572e15f9bd0SJeremy L Thompson ierr = CeedQFunctionFieldGetSize(qfoutputfields[i], &size); 573e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 5741d102b48SJeremy L Thompson numactiveout += size; 5751d102b48SJeremy L Thompson } 5761d102b48SJeremy L Thompson } 5771d102b48SJeremy L Thompson 5781d102b48SJeremy L Thompson // Check sizes 5791d102b48SJeremy L Thompson if (!numactivein || !numactiveout) 580138d4072Sjeremylt // LCOV_EXCL_START 581e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 582e15f9bd0SJeremy L Thompson "Cannot assemble QFunction without active inputs " 583138d4072Sjeremylt "and outputs"); 584138d4072Sjeremylt // LCOV_EXCL_STOP 5851d102b48SJeremy L Thompson 5861d102b48SJeremy L Thompson // Create output restriction 587d965c7a7SJeremy L Thompson CeedInt strides[3] = {1, Q, numactivein*numactiveout*Q}; /* *NOPAD* */ 5887509a596Sjeremylt ierr = CeedElemRestrictionCreateStrided(ceedparent, numelements, Q, 589d979a051Sjeremylt numactivein*numactiveout, 590d979a051Sjeremylt numactivein*numactiveout*numelements*Q, 591e15f9bd0SJeremy L Thompson strides, rstr); CeedChkBackend(ierr); 5921d102b48SJeremy L Thompson // Create assembled vector 5935107b09fSJeremy L Thompson ierr = CeedVectorCreate(ceedparent, numelements*Q*numactivein*numactiveout, 594e15f9bd0SJeremy L Thompson assembled); CeedChkBackend(ierr); 595e15f9bd0SJeremy L Thompson ierr = CeedVectorSetValue(*assembled, 0.0); CeedChkBackend(ierr); 596e15f9bd0SJeremy L Thompson ierr = CeedVectorGetArray(*assembled, CEED_MEM_HOST, &a); CeedChkBackend(ierr); 5971d102b48SJeremy L Thompson 5981d102b48SJeremy L Thompson // Loop through elements 5991d102b48SJeremy L Thompson for (CeedInt e=0; e<numelements; e++) { 6001d102b48SJeremy L Thompson // Input basis apply 6011d102b48SJeremy L Thompson ierr = CeedOperatorInputBasis_Ref(e, Q, qfinputfields, opinputfields, 6021d102b48SJeremy L Thompson numinputfields, true, impl); 603e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 6041d102b48SJeremy L Thompson 6051d102b48SJeremy L Thompson // Assemble QFunction 6061d102b48SJeremy L Thompson for (CeedInt in=0; in<numactivein; in++) { 6071d102b48SJeremy L Thompson // Set Inputs 608e15f9bd0SJeremy L Thompson ierr = CeedVectorSetValue(activein[in], 1.0); CeedChkBackend(ierr); 60942ea3801Sjeremylt if (numactivein > 1) { 61042ea3801Sjeremylt ierr = CeedVectorSetValue(activein[(in+numactivein-1)%numactivein], 611e15f9bd0SJeremy L Thompson 0.0); CeedChkBackend(ierr); 61242ea3801Sjeremylt } 6131d102b48SJeremy L Thompson // Set Outputs 6141d102b48SJeremy L Thompson for (CeedInt out=0; out<numoutputfields; out++) { 6151d102b48SJeremy L Thompson // Get output vector 6161d102b48SJeremy L Thompson ierr = CeedOperatorFieldGetVector(opoutputfields[out], &vec); 617e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 6181d102b48SJeremy L Thompson // Check if active output 6191d102b48SJeremy L Thompson if (vec == CEED_VECTOR_ACTIVE) { 6201d102b48SJeremy L Thompson CeedVectorSetArray(impl->qvecsout[out], CEED_MEM_HOST, 621e15f9bd0SJeremy L Thompson CEED_USE_POINTER, a); CeedChkBackend(ierr); 6221d102b48SJeremy L Thompson ierr = CeedQFunctionFieldGetSize(qfoutputfields[out], &size); 623e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 6241d102b48SJeremy L Thompson a += size*Q; // Advance the pointer by the size of the output 6251d102b48SJeremy L Thompson } 6261d102b48SJeremy L Thompson } 6271d102b48SJeremy L Thompson // Apply QFunction 6281d102b48SJeremy L Thompson ierr = CeedQFunctionApply(qf, Q, impl->qvecsin, impl->qvecsout); 629e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 6301d102b48SJeremy L Thompson } 6311d102b48SJeremy L Thompson } 6321d102b48SJeremy L Thompson 6331d102b48SJeremy L Thompson // Un-set output Qvecs to prevent accidental overwrite of Assembled 6341d102b48SJeremy L Thompson for (CeedInt out=0; out<numoutputfields; out++) { 6351d102b48SJeremy L Thompson // Get output vector 6361d102b48SJeremy L Thompson ierr = CeedOperatorFieldGetVector(opoutputfields[out], &vec); 637e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 6381d102b48SJeremy L Thompson // Check if active output 6391d102b48SJeremy L Thompson if (vec == CEED_VECTOR_ACTIVE) { 640f4289877SJeremy L Thompson CeedVectorTakeArray(impl->qvecsout[out], CEED_MEM_HOST, NULL); 641e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 6421d102b48SJeremy L Thompson } 6431d102b48SJeremy L Thompson } 6441d102b48SJeremy L Thompson 6451d102b48SJeremy L Thompson // Restore input arrays 6461d102b48SJeremy L Thompson ierr = CeedOperatorRestoreInputs_Ref(numinputfields, qfinputfields, 6471d102b48SJeremy L Thompson opinputfields, true, impl); 648e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 6491d102b48SJeremy L Thompson 6501d102b48SJeremy L Thompson // Restore output 651e15f9bd0SJeremy L Thompson ierr = CeedVectorRestoreArray(*assembled, &a); CeedChkBackend(ierr); 6521d102b48SJeremy L Thompson 6531d102b48SJeremy L Thompson // Cleanup 65442ea3801Sjeremylt for (CeedInt i=0; i<numactivein; i++) { 655e15f9bd0SJeremy L Thompson ierr = CeedVectorDestroy(&activein[i]); CeedChkBackend(ierr); 65642ea3801Sjeremylt } 657e15f9bd0SJeremy L Thompson ierr = CeedFree(&activein); CeedChkBackend(ierr); 6581d102b48SJeremy L Thompson 659e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6601d102b48SJeremy L Thompson } 6611d102b48SJeremy L Thompson 662f10650afSjeremylt //------------------------------------------------------------------------------ 663dfffd467Sjeremylt // Get Basis Emode Pointer 664dfffd467Sjeremylt //------------------------------------------------------------------------------ 6656c58de82SJeremy L Thompson static inline void CeedOperatorGetBasisPointer_Ref(const CeedScalar **basisptr, 6666c58de82SJeremy L Thompson CeedEvalMode emode, const CeedScalar *identity, const CeedScalar *interp, 6676c58de82SJeremy L Thompson const CeedScalar *grad) { 668dfffd467Sjeremylt switch (emode) { 669dfffd467Sjeremylt case CEED_EVAL_NONE: 670dfffd467Sjeremylt *basisptr = identity; 671dfffd467Sjeremylt break; 672dfffd467Sjeremylt case CEED_EVAL_INTERP: 673dfffd467Sjeremylt *basisptr = interp; 674dfffd467Sjeremylt break; 675dfffd467Sjeremylt case CEED_EVAL_GRAD: 676dfffd467Sjeremylt *basisptr = grad; 677dfffd467Sjeremylt break; 678dfffd467Sjeremylt case CEED_EVAL_WEIGHT: 679dfffd467Sjeremylt case CEED_EVAL_DIV: 680dfffd467Sjeremylt case CEED_EVAL_CURL: 681dfffd467Sjeremylt break; // Caught by QF Assembly 682dfffd467Sjeremylt } 683dfffd467Sjeremylt } 684dfffd467Sjeremylt 685dfffd467Sjeremylt //------------------------------------------------------------------------------ 686d965c7a7SJeremy L Thompson // Create point block restriction 687d965c7a7SJeremy L Thompson //------------------------------------------------------------------------------ 688868092e3SJeremy L Thompson static int CreatePBRestriction_Ref(CeedElemRestriction rstr, 689d965c7a7SJeremy L Thompson CeedElemRestriction *pbRstr) { 690d965c7a7SJeremy L Thompson int ierr; 691d965c7a7SJeremy L Thompson Ceed ceed; 692e15f9bd0SJeremy L Thompson ierr = CeedElemRestrictionGetCeed(rstr, &ceed); CeedChkBackend(ierr); 693d965c7a7SJeremy L Thompson const CeedInt *offsets; 694d965c7a7SJeremy L Thompson ierr = CeedElemRestrictionGetOffsets(rstr, CEED_MEM_HOST, &offsets); 695e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 696d965c7a7SJeremy L Thompson 697d965c7a7SJeremy L Thompson // Expand offsets 698d965c7a7SJeremy L Thompson CeedInt nelem, ncomp, elemsize, compstride, max = 1, *pbOffsets; 699e15f9bd0SJeremy L Thompson ierr = CeedElemRestrictionGetNumElements(rstr, &nelem); CeedChkBackend(ierr); 700e15f9bd0SJeremy L Thompson ierr = CeedElemRestrictionGetNumComponents(rstr, &ncomp); CeedChkBackend(ierr); 701e15f9bd0SJeremy L Thompson ierr = CeedElemRestrictionGetElementSize(rstr, &elemsize); CeedChkBackend(ierr); 702e15f9bd0SJeremy L Thompson ierr = CeedElemRestrictionGetCompStride(rstr, &compstride); 703e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 704d965c7a7SJeremy L Thompson CeedInt shift = ncomp; 705d965c7a7SJeremy L Thompson if (compstride != 1) 706d965c7a7SJeremy L Thompson shift *= ncomp; 707e15f9bd0SJeremy L Thompson ierr = CeedCalloc(nelem*elemsize, &pbOffsets); CeedChkBackend(ierr); 708d965c7a7SJeremy L Thompson for (CeedInt i = 0; i < nelem*elemsize; i++) { 709d965c7a7SJeremy L Thompson pbOffsets[i] = offsets[i]*shift; 710d965c7a7SJeremy L Thompson if (pbOffsets[i] > max) 711d965c7a7SJeremy L Thompson max = pbOffsets[i]; 712d965c7a7SJeremy L Thompson } 713d965c7a7SJeremy L Thompson 714d965c7a7SJeremy L Thompson // Create new restriction 715d965c7a7SJeremy L Thompson ierr = CeedElemRestrictionCreate(ceed, nelem, elemsize, ncomp*ncomp, 1, 716d965c7a7SJeremy L Thompson max + ncomp*ncomp, CEED_MEM_HOST, 717d965c7a7SJeremy L Thompson CEED_OWN_POINTER, pbOffsets, pbRstr); 718e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 719d965c7a7SJeremy L Thompson 720d965c7a7SJeremy L Thompson // Cleanup 721e15f9bd0SJeremy L Thompson ierr = CeedElemRestrictionRestoreOffsets(rstr, &offsets); CeedChkBackend(ierr); 722d965c7a7SJeremy L Thompson 723e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 724d965c7a7SJeremy L Thompson } 725d965c7a7SJeremy L Thompson 726d965c7a7SJeremy L Thompson //------------------------------------------------------------------------------ 727c04a41a7SJeremy L Thompson // Assemble diagonal common code 728f10650afSjeremylt //------------------------------------------------------------------------------ 72969af5e5fSJeremy L Thompson static inline int CeedOperatorAssembleAddDiagonalCore_Ref(CeedOperator op, 7302bba3ffaSJeremy L Thompson CeedVector assembled, CeedRequest *request, const bool pointBlock) { 7317172caadSjeremylt int ierr; 732c04a41a7SJeremy L Thompson Ceed ceed; 733e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChkBackend(ierr); 7347172caadSjeremylt 7357172caadSjeremylt // Assemble QFunction 7367172caadSjeremylt CeedQFunction qf; 737e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetQFunction(op, &qf); CeedChkBackend(ierr); 7387172caadSjeremylt CeedInt numinputfields, numoutputfields; 7397172caadSjeremylt ierr= CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields); 740e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 7417172caadSjeremylt CeedVector assembledqf; 7427172caadSjeremylt CeedElemRestriction rstr; 74380ac2e43SJeremy L Thompson ierr = CeedOperatorLinearAssembleQFunction(op, &assembledqf, &rstr, request); 744e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 745e15f9bd0SJeremy L Thompson ierr = CeedElemRestrictionDestroy(&rstr); CeedChkBackend(ierr); 7464f694d2fSjeremylt CeedScalar maxnorm = 0; 747e15f9bd0SJeremy L Thompson ierr = CeedVectorNorm(assembledqf, CEED_NORM_MAX, &maxnorm); 748e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 7497172caadSjeremylt 7507172caadSjeremylt // Determine active input basis 7517172caadSjeremylt CeedOperatorField *opfields; 7527172caadSjeremylt CeedQFunctionField *qffields; 753e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetFields(op, &opfields, NULL); CeedChkBackend(ierr); 754e15f9bd0SJeremy L Thompson ierr = CeedQFunctionGetFields(qf, &qffields, NULL); CeedChkBackend(ierr); 7557172caadSjeremylt CeedInt numemodein = 0, ncomp, dim = 1; 7567172caadSjeremylt CeedEvalMode *emodein = NULL; 7577172caadSjeremylt CeedBasis basisin = NULL; 7587172caadSjeremylt CeedElemRestriction rstrin = NULL; 7597172caadSjeremylt for (CeedInt i=0; i<numinputfields; i++) { 7607172caadSjeremylt CeedVector vec; 761e15f9bd0SJeremy L Thompson ierr = CeedOperatorFieldGetVector(opfields[i], &vec); CeedChkBackend(ierr); 7627172caadSjeremylt if (vec == CEED_VECTOR_ACTIVE) { 763c04a41a7SJeremy L Thompson CeedElemRestriction rstr; 764e15f9bd0SJeremy L Thompson ierr = CeedOperatorFieldGetBasis(opfields[i], &basisin); CeedChkBackend(ierr); 765e15f9bd0SJeremy L Thompson ierr = CeedBasisGetNumComponents(basisin, &ncomp); CeedChkBackend(ierr); 766e15f9bd0SJeremy L Thompson ierr = CeedBasisGetDimension(basisin, &dim); CeedChkBackend(ierr); 767c04a41a7SJeremy L Thompson ierr = CeedOperatorFieldGetElemRestriction(opfields[i], &rstr); 768e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 769c04a41a7SJeremy L Thompson if (rstrin && rstrin != rstr) 770c04a41a7SJeremy L Thompson // LCOV_EXCL_START 771e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 772c04a41a7SJeremy L Thompson "Multi-field non-composite operator diagonal assembly not supported"); 773c04a41a7SJeremy L Thompson // LCOV_EXCL_STOP 774c04a41a7SJeremy L Thompson rstrin = rstr; 7757172caadSjeremylt CeedEvalMode emode; 7767172caadSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qffields[i], &emode); 777e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 7787172caadSjeremylt switch (emode) { 7797172caadSjeremylt case CEED_EVAL_NONE: 7807172caadSjeremylt case CEED_EVAL_INTERP: 781e15f9bd0SJeremy L Thompson ierr = CeedRealloc(numemodein + 1, &emodein); CeedChkBackend(ierr); 7827172caadSjeremylt emodein[numemodein] = emode; 7837172caadSjeremylt numemodein += 1; 7847172caadSjeremylt break; 7857172caadSjeremylt case CEED_EVAL_GRAD: 786e15f9bd0SJeremy L Thompson ierr = CeedRealloc(numemodein + dim, &emodein); CeedChkBackend(ierr); 7877172caadSjeremylt for (CeedInt d=0; d<dim; d++) 7887172caadSjeremylt emodein[numemodein+d] = emode; 7897172caadSjeremylt numemodein += dim; 7907172caadSjeremylt break; 7917172caadSjeremylt case CEED_EVAL_WEIGHT: 7927172caadSjeremylt case CEED_EVAL_DIV: 7937172caadSjeremylt case CEED_EVAL_CURL: 7947172caadSjeremylt break; // Caught by QF Assembly 7957172caadSjeremylt } 7967172caadSjeremylt } 7977172caadSjeremylt } 7987172caadSjeremylt 7997172caadSjeremylt // Determine active output basis 800e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetFields(op, NULL, &opfields); CeedChkBackend(ierr); 801e15f9bd0SJeremy L Thompson ierr = CeedQFunctionGetFields(qf, NULL, &qffields); CeedChkBackend(ierr); 8027172caadSjeremylt CeedInt numemodeout = 0; 8037172caadSjeremylt CeedEvalMode *emodeout = NULL; 8047172caadSjeremylt CeedBasis basisout = NULL; 8057172caadSjeremylt CeedElemRestriction rstrout = NULL; 8067172caadSjeremylt for (CeedInt i=0; i<numoutputfields; i++) { 8077172caadSjeremylt CeedVector vec; 808e15f9bd0SJeremy L Thompson ierr = CeedOperatorFieldGetVector(opfields[i], &vec); CeedChkBackend(ierr); 8097172caadSjeremylt if (vec == CEED_VECTOR_ACTIVE) { 810c04a41a7SJeremy L Thompson CeedElemRestriction rstr; 811e15f9bd0SJeremy L Thompson ierr = CeedOperatorFieldGetBasis(opfields[i], &basisout); CeedChkBackend(ierr); 812c04a41a7SJeremy L Thompson ierr = CeedOperatorFieldGetElemRestriction(opfields[i], &rstr); 813e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 814c04a41a7SJeremy L Thompson if (rstrout && rstrout != rstr) 815c04a41a7SJeremy L Thompson // LCOV_EXCL_START 816e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 817c04a41a7SJeremy L Thompson "Multi-field non-composite operator diagonal assembly not supported"); 818c04a41a7SJeremy L Thompson // LCOV_EXCL_STOP 819c04a41a7SJeremy L Thompson rstrout = rstr; 8207172caadSjeremylt CeedEvalMode emode; 821e15f9bd0SJeremy L Thompson ierr = CeedQFunctionFieldGetEvalMode(qffields[i], &emode); CeedChkBackend(ierr); 8227172caadSjeremylt switch (emode) { 8237172caadSjeremylt case CEED_EVAL_NONE: 8247172caadSjeremylt case CEED_EVAL_INTERP: 825e15f9bd0SJeremy L Thompson ierr = CeedRealloc(numemodeout + 1, &emodeout); CeedChkBackend(ierr); 8267172caadSjeremylt emodeout[numemodeout] = emode; 8277172caadSjeremylt numemodeout += 1; 8287172caadSjeremylt break; 8297172caadSjeremylt case CEED_EVAL_GRAD: 830e15f9bd0SJeremy L Thompson ierr = CeedRealloc(numemodeout + dim, &emodeout); CeedChkBackend(ierr); 8317172caadSjeremylt for (CeedInt d=0; d<dim; d++) 8327172caadSjeremylt emodeout[numemodeout+d] = emode; 8337172caadSjeremylt numemodeout += dim; 8347172caadSjeremylt break; 8357172caadSjeremylt case CEED_EVAL_WEIGHT: 8367172caadSjeremylt case CEED_EVAL_DIV: 8377172caadSjeremylt case CEED_EVAL_CURL: 8387172caadSjeremylt break; // Caught by QF Assembly 8397172caadSjeremylt } 8407172caadSjeremylt } 8417172caadSjeremylt } 8427172caadSjeremylt 843d965c7a7SJeremy L Thompson // Assemble point-block diagonal restriction, if needed 844d965c7a7SJeremy L Thompson CeedElemRestriction diagrstr = rstrout; 845d965c7a7SJeremy L Thompson if (pointBlock) { 846e15f9bd0SJeremy L Thompson ierr = CreatePBRestriction_Ref(rstrout, &diagrstr); CeedChkBackend(ierr); 847d965c7a7SJeremy L Thompson } 848d965c7a7SJeremy L Thompson 8497172caadSjeremylt // Create diagonal vector 8507172caadSjeremylt CeedVector elemdiag; 851c04a41a7SJeremy L Thompson ierr = CeedElemRestrictionCreateVector(diagrstr, NULL, &elemdiag); 852e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 8537172caadSjeremylt 8547172caadSjeremylt // Assemble element operator diagonals 8557172caadSjeremylt CeedScalar *elemdiagarray, *assembledqfarray; 856e15f9bd0SJeremy L Thompson ierr = CeedVectorSetValue(elemdiag, 0.0); CeedChkBackend(ierr); 8577172caadSjeremylt ierr = CeedVectorGetArray(elemdiag, CEED_MEM_HOST, &elemdiagarray); 858e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 8597172caadSjeremylt ierr = CeedVectorGetArray(assembledqf, CEED_MEM_HOST, &assembledqfarray); 860e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 8617172caadSjeremylt CeedInt nelem, nnodes, nqpts; 862e15f9bd0SJeremy L Thompson ierr = CeedElemRestrictionGetNumElements(diagrstr, &nelem); 863e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 864e15f9bd0SJeremy L Thompson ierr = CeedBasisGetNumNodes(basisin, &nnodes); CeedChkBackend(ierr); 865e15f9bd0SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basisin, &nqpts); CeedChkBackend(ierr); 866dfffd467Sjeremylt // Basis matrices 8676c58de82SJeremy L Thompson const CeedScalar *interpin, *interpout, *gradin, *gradout; 8686c58de82SJeremy L Thompson CeedScalar *identity = NULL; 869dfffd467Sjeremylt bool evalNone = false; 870dfffd467Sjeremylt for (CeedInt i=0; i<numemodein; i++) 871dfffd467Sjeremylt evalNone = evalNone || (emodein[i] == CEED_EVAL_NONE); 872dfffd467Sjeremylt for (CeedInt i=0; i<numemodeout; i++) 873dfffd467Sjeremylt evalNone = evalNone || (emodeout[i] == CEED_EVAL_NONE); 874dfffd467Sjeremylt if (evalNone) { 875e15f9bd0SJeremy L Thompson ierr = CeedCalloc(nqpts*nnodes, &identity); CeedChkBackend(ierr); 876dfffd467Sjeremylt for (CeedInt i=0; i<(nnodes<nqpts?nnodes:nqpts); i++) 877dfffd467Sjeremylt identity[i*nnodes+i] = 1.0; 878dfffd467Sjeremylt } 879e15f9bd0SJeremy L Thompson ierr = CeedBasisGetInterp(basisin, &interpin); CeedChkBackend(ierr); 880e15f9bd0SJeremy L Thompson ierr = CeedBasisGetInterp(basisout, &interpout); CeedChkBackend(ierr); 881e15f9bd0SJeremy L Thompson ierr = CeedBasisGetGrad(basisin, &gradin); CeedChkBackend(ierr); 882e15f9bd0SJeremy L Thompson ierr = CeedBasisGetGrad(basisout, &gradout); CeedChkBackend(ierr); 883dfffd467Sjeremylt // Compute the diagonal of B^T D B 884dfffd467Sjeremylt // Each element 885c43c9481SJeremy L Thompson const CeedScalar qfvaluebound = maxnorm*1e-12; 88600f91b2bSjeremylt for (CeedInt e=0; e<nelem; e++) { 8877172caadSjeremylt CeedInt dout = -1; 8887172caadSjeremylt // Each basis eval mode pair 8897172caadSjeremylt for (CeedInt eout=0; eout<numemodeout; eout++) { 8906c58de82SJeremy L Thompson const CeedScalar *bt = NULL; 8917172caadSjeremylt if (emodeout[eout] == CEED_EVAL_GRAD) 8927172caadSjeremylt dout += 1; 893dfffd467Sjeremylt CeedOperatorGetBasisPointer_Ref(&bt, emodeout[eout], identity, interpout, 894dfffd467Sjeremylt &gradout[dout*nqpts*nnodes]); 8957172caadSjeremylt CeedInt din = -1; 8967172caadSjeremylt for (CeedInt ein=0; ein<numemodein; ein++) { 8976c58de82SJeremy L Thompson const CeedScalar *b = NULL; 8987172caadSjeremylt if (emodein[ein] == CEED_EVAL_GRAD) 8997172caadSjeremylt din += 1; 900dfffd467Sjeremylt CeedOperatorGetBasisPointer_Ref(&b, emodein[ein], identity, interpin, 901dfffd467Sjeremylt &gradin[din*nqpts*nnodes]); 902efcf4563Sjeremylt // Each component 903d965c7a7SJeremy L Thompson for (CeedInt compOut=0; compOut<ncomp; compOut++) 904dfffd467Sjeremylt // Each qpoint/node pair 905d965c7a7SJeremy L Thompson for (CeedInt q=0; q<nqpts; q++) 906d965c7a7SJeremy L Thompson if (pointBlock) { 907d965c7a7SJeremy L Thompson // Point Block Diagonal 908d965c7a7SJeremy L Thompson for (CeedInt compIn=0; compIn<ncomp; compIn++) { 9094ff7492eSjeremylt const CeedScalar qfvalue = 910d965c7a7SJeremy L Thompson assembledqfarray[((((e*numemodein+ein)*ncomp+compIn)* 911d965c7a7SJeremy L Thompson numemodeout+eout)*ncomp+compOut)*nqpts+q]; 912c43c9481SJeremy L Thompson if (fabs(qfvalue) > qfvaluebound) 913dfffd467Sjeremylt for (CeedInt n=0; n<nnodes; n++) 914d965c7a7SJeremy L Thompson elemdiagarray[((e*ncomp+compOut)*ncomp+compIn)*nnodes+n] += 915d965c7a7SJeremy L Thompson bt[q*nnodes+n] * qfvalue * b[q*nnodes+n]; 916d965c7a7SJeremy L Thompson } 917d965c7a7SJeremy L Thompson } else { 918d965c7a7SJeremy L Thompson // Diagonal Only 919d965c7a7SJeremy L Thompson const CeedScalar qfvalue = 920d965c7a7SJeremy L Thompson assembledqfarray[((((e*numemodein+ein)*ncomp+compOut)* 921d965c7a7SJeremy L Thompson numemodeout+eout)*ncomp+compOut)*nqpts+q]; 922c43c9481SJeremy L Thompson if (fabs(qfvalue) > qfvaluebound) 923d965c7a7SJeremy L Thompson for (CeedInt n=0; n<nnodes; n++) 924d965c7a7SJeremy L Thompson elemdiagarray[(e*ncomp+compOut)*nnodes+n] += 925d965c7a7SJeremy L Thompson bt[q*nnodes+n] * qfvalue * b[q*nnodes+n]; 9264ff7492eSjeremylt } 9277172caadSjeremylt } 9287172caadSjeremylt } 9297172caadSjeremylt } 930e15f9bd0SJeremy L Thompson ierr = CeedVectorRestoreArray(elemdiag, &elemdiagarray); CeedChkBackend(ierr); 931e15f9bd0SJeremy L Thompson ierr = CeedVectorRestoreArray(assembledqf, &assembledqfarray); 932e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 9337172caadSjeremylt 9347172caadSjeremylt // Assemble local operator diagonal 935d965c7a7SJeremy L Thompson ierr = CeedElemRestrictionApply(diagrstr, CEED_TRANSPOSE, elemdiag, 936e15f9bd0SJeremy L Thompson assembled, request); CeedChkBackend(ierr); 9377172caadSjeremylt 9387172caadSjeremylt // Cleanup 939d965c7a7SJeremy L Thompson if (pointBlock) { 940e15f9bd0SJeremy L Thompson ierr = CeedElemRestrictionDestroy(&diagrstr); CeedChkBackend(ierr); 941d965c7a7SJeremy L Thompson } 942e15f9bd0SJeremy L Thompson ierr = CeedVectorDestroy(&assembledqf); CeedChkBackend(ierr); 943e15f9bd0SJeremy L Thompson ierr = CeedVectorDestroy(&elemdiag); CeedChkBackend(ierr); 944e15f9bd0SJeremy L Thompson ierr = CeedFree(&emodein); CeedChkBackend(ierr); 945e15f9bd0SJeremy L Thompson ierr = CeedFree(&emodeout); CeedChkBackend(ierr); 946e15f9bd0SJeremy L Thompson ierr = CeedFree(&identity); CeedChkBackend(ierr); 9477172caadSjeremylt 948e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 9497172caadSjeremylt } 9507172caadSjeremylt 951f10650afSjeremylt //------------------------------------------------------------------------------ 952c04a41a7SJeremy L Thompson // Assemble composite diagonal common code 953c04a41a7SJeremy L Thompson //------------------------------------------------------------------------------ 95469af5e5fSJeremy L Thompson static inline int CeedOperatorLinearAssembleAddDiagonalCompositeCore_Ref( 9552bba3ffaSJeremy L Thompson CeedOperator op, CeedVector assembled, CeedRequest *request, 956c04a41a7SJeremy L Thompson const bool pointBlock) { 957c04a41a7SJeremy L Thompson int ierr; 958c04a41a7SJeremy L Thompson CeedInt numSub; 959c04a41a7SJeremy L Thompson CeedOperator *subOperators; 960e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetNumSub(op, &numSub); CeedChkBackend(ierr); 961e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetSubList(op, &subOperators); CeedChkBackend(ierr); 962c04a41a7SJeremy L Thompson for (CeedInt i = 0; i < numSub; i++) { 96369af5e5fSJeremy L Thompson ierr = CeedOperatorAssembleAddDiagonalCore_Ref(subOperators[i], assembled, 964e15f9bd0SJeremy L Thompson request, pointBlock); CeedChkBackend(ierr); 965c04a41a7SJeremy L Thompson } 966e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 967c04a41a7SJeremy L Thompson } 968c04a41a7SJeremy L Thompson 969c04a41a7SJeremy L Thompson //------------------------------------------------------------------------------ 970d965c7a7SJeremy L Thompson // Assemble Linear Diagonal 971d965c7a7SJeremy L Thompson //------------------------------------------------------------------------------ 97269af5e5fSJeremy L Thompson static int CeedOperatorLinearAssembleAddDiagonal_Ref(CeedOperator op, 9732bba3ffaSJeremy L Thompson CeedVector assembled, CeedRequest *request) { 974c04a41a7SJeremy L Thompson int ierr; 975c04a41a7SJeremy L Thompson bool isComposite; 976e15f9bd0SJeremy L Thompson ierr = CeedOperatorIsComposite(op, &isComposite); CeedChkBackend(ierr); 977c04a41a7SJeremy L Thompson if (isComposite) { 97869af5e5fSJeremy L Thompson return CeedOperatorLinearAssembleAddDiagonalCompositeCore_Ref(op, assembled, 979c04a41a7SJeremy L Thompson request, false); 980c04a41a7SJeremy L Thompson } else { 98169af5e5fSJeremy L Thompson return CeedOperatorAssembleAddDiagonalCore_Ref(op, assembled, request, false); 982c04a41a7SJeremy L Thompson } 983d965c7a7SJeremy L Thompson } 984d965c7a7SJeremy L Thompson 985d965c7a7SJeremy L Thompson //------------------------------------------------------------------------------ 986d965c7a7SJeremy L Thompson // Assemble Linear Point Block Diagonal 987d965c7a7SJeremy L Thompson //------------------------------------------------------------------------------ 98869af5e5fSJeremy L Thompson static int CeedOperatorLinearAssembleAddPointBlockDiagonal_Ref(CeedOperator op, 9892bba3ffaSJeremy L Thompson CeedVector assembled, CeedRequest *request) { 990c04a41a7SJeremy L Thompson int ierr; 991c04a41a7SJeremy L Thompson bool isComposite; 992e15f9bd0SJeremy L Thompson ierr = CeedOperatorIsComposite(op, &isComposite); CeedChkBackend(ierr); 993c04a41a7SJeremy L Thompson if (isComposite) { 99469af5e5fSJeremy L Thompson return CeedOperatorLinearAssembleAddDiagonalCompositeCore_Ref(op, assembled, 995c04a41a7SJeremy L Thompson request, true); 996c04a41a7SJeremy L Thompson } else { 99769af5e5fSJeremy L Thompson return CeedOperatorAssembleAddDiagonalCore_Ref(op, assembled, request, true); 998c04a41a7SJeremy L Thompson } 999d965c7a7SJeremy L Thompson } 1000d965c7a7SJeremy L Thompson 1001d965c7a7SJeremy L Thompson //------------------------------------------------------------------------------ 1002713f43c3Sjeremylt // Create FDM Element Inverse 1003f10650afSjeremylt //------------------------------------------------------------------------------ 1004713f43c3Sjeremylt int CeedOperatorCreateFDMElementInverse_Ref(CeedOperator op, 1005ccaff030SJeremy L Thompson CeedOperator *fdminv, CeedRequest *request) { 1006713f43c3Sjeremylt int ierr; 1007713f43c3Sjeremylt Ceed ceed, ceedparent; 1008e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChkBackend(ierr); 1009e15f9bd0SJeremy L Thompson ierr = CeedGetOperatorFallbackParentCeed(ceed, &ceedparent); 1010e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1011713f43c3Sjeremylt ceedparent = ceedparent ? ceedparent : ceed; 1012713f43c3Sjeremylt CeedQFunction qf; 1013e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetQFunction(op, &qf); CeedChkBackend(ierr); 1014713f43c3Sjeremylt 1015713f43c3Sjeremylt // Determine active input basis 1016713f43c3Sjeremylt bool interp = false, grad = false; 1017713f43c3Sjeremylt CeedBasis basis = NULL; 1018713f43c3Sjeremylt CeedElemRestriction rstr = NULL; 1019713f43c3Sjeremylt CeedOperatorField *opfields; 1020713f43c3Sjeremylt CeedQFunctionField *qffields; 1021e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetFields(op, &opfields, NULL); CeedChkBackend(ierr); 1022e15f9bd0SJeremy L Thompson ierr = CeedQFunctionGetFields(qf, &qffields, NULL); CeedChkBackend(ierr); 1023713f43c3Sjeremylt CeedInt numinputfields; 1024e15f9bd0SJeremy L Thompson ierr = CeedQFunctionGetNumArgs(qf, &numinputfields, NULL); CeedChkBackend(ierr); 1025713f43c3Sjeremylt for (CeedInt i=0; i<numinputfields; i++) { 1026713f43c3Sjeremylt CeedVector vec; 1027e15f9bd0SJeremy L Thompson ierr = CeedOperatorFieldGetVector(opfields[i], &vec); CeedChkBackend(ierr); 1028713f43c3Sjeremylt if (vec == CEED_VECTOR_ACTIVE) { 1029713f43c3Sjeremylt CeedEvalMode emode; 1030e15f9bd0SJeremy L Thompson ierr = CeedQFunctionFieldGetEvalMode(qffields[i], &emode); CeedChkBackend(ierr); 1031713f43c3Sjeremylt interp = interp || emode == CEED_EVAL_INTERP; 1032713f43c3Sjeremylt grad = grad || emode == CEED_EVAL_GRAD; 1033e15f9bd0SJeremy L Thompson ierr = CeedOperatorFieldGetBasis(opfields[i], &basis); CeedChkBackend(ierr); 1034713f43c3Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(opfields[i], &rstr); 1035e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1036713f43c3Sjeremylt } 1037713f43c3Sjeremylt } 1038713f43c3Sjeremylt if (!basis) 1039d9995aecSjeremylt // LCOV_EXCL_START 1040e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "No active field set"); 1041d9995aecSjeremylt // LCOV_EXCL_STOP 1042d979a051Sjeremylt CeedInt P1d, Q1d, elemsize, nqpts, dim, ncomp = 1, nelem = 1, lsize = 1; 1043e15f9bd0SJeremy L Thompson ierr = CeedBasisGetNumNodes1D(basis, &P1d); CeedChkBackend(ierr); 1044e15f9bd0SJeremy L Thompson ierr = CeedBasisGetNumNodes(basis, &elemsize); CeedChkBackend(ierr); 1045e15f9bd0SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints1D(basis, &Q1d); CeedChkBackend(ierr); 1046e15f9bd0SJeremy L Thompson ierr = CeedBasisGetNumQuadraturePoints(basis, &nqpts); CeedChkBackend(ierr); 1047e15f9bd0SJeremy L Thompson ierr = CeedBasisGetDimension(basis, &dim); CeedChkBackend(ierr); 1048e15f9bd0SJeremy L Thompson ierr = CeedBasisGetNumComponents(basis, &ncomp); CeedChkBackend(ierr); 1049e15f9bd0SJeremy L Thompson ierr = CeedElemRestrictionGetNumElements(rstr, &nelem); CeedChkBackend(ierr); 1050e15f9bd0SJeremy L Thompson ierr = CeedElemRestrictionGetLVectorSize(rstr, &lsize); CeedChkBackend(ierr); 1051713f43c3Sjeremylt 1052713f43c3Sjeremylt // Build and diagonalize 1D Mass and Laplacian 1053713f43c3Sjeremylt bool tensorbasis; 1054e15f9bd0SJeremy L Thompson ierr = CeedBasisIsTensor(basis, &tensorbasis); CeedChkBackend(ierr); 1055713f43c3Sjeremylt if (!tensorbasis) 1056d9995aecSjeremylt // LCOV_EXCL_START 1057e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 1058e15f9bd0SJeremy L Thompson "FDMElementInverse only supported for tensor " 1059713f43c3Sjeremylt "bases"); 1060d9995aecSjeremylt // LCOV_EXCL_STOP 1061713f43c3Sjeremylt CeedScalar *work, *mass, *laplace, *x, *x2, *lambda; 1062e15f9bd0SJeremy L Thompson ierr = CeedMalloc(Q1d*P1d, &work); CeedChkBackend(ierr); 1063e15f9bd0SJeremy L Thompson ierr = CeedMalloc(P1d*P1d, &mass); CeedChkBackend(ierr); 1064e15f9bd0SJeremy L Thompson ierr = CeedMalloc(P1d*P1d, &laplace); CeedChkBackend(ierr); 1065e15f9bd0SJeremy L Thompson ierr = CeedMalloc(P1d*P1d, &x); CeedChkBackend(ierr); 1066e15f9bd0SJeremy L Thompson ierr = CeedMalloc(P1d*P1d, &x2); CeedChkBackend(ierr); 1067e15f9bd0SJeremy L Thompson ierr = CeedMalloc(P1d, &lambda); CeedChkBackend(ierr); 1068713f43c3Sjeremylt // -- Mass 10696c58de82SJeremy L Thompson const CeedScalar *interp1d, *grad1d, *qweight1d; 1070e15f9bd0SJeremy L Thompson ierr = CeedBasisGetInterp1D(basis, &interp1d); CeedChkBackend(ierr); 1071e15f9bd0SJeremy L Thompson ierr = CeedBasisGetGrad1D(basis, &grad1d); CeedChkBackend(ierr); 1072e15f9bd0SJeremy L Thompson ierr = CeedBasisGetQWeights(basis, &qweight1d); CeedChkBackend(ierr); 1073713f43c3Sjeremylt for (CeedInt i=0; i<Q1d; i++) 1074713f43c3Sjeremylt for (CeedInt j=0; j<P1d; j++) 1075713f43c3Sjeremylt work[i+j*Q1d] = interp1d[i*P1d+j]*qweight1d[i]; 10769289e5bfSjeremylt ierr = CeedMatrixMultiply(ceed, (const CeedScalar *)work, 10779289e5bfSjeremylt (const CeedScalar *)interp1d, mass, P1d, P1d, Q1d); 1078e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1079713f43c3Sjeremylt // -- Laplacian 1080713f43c3Sjeremylt for (CeedInt i=0; i<Q1d; i++) 1081713f43c3Sjeremylt for (CeedInt j=0; j<P1d; j++) 1082713f43c3Sjeremylt work[i+j*Q1d] = grad1d[i*P1d+j]*qweight1d[i]; 10839289e5bfSjeremylt ierr = CeedMatrixMultiply(ceed, (const CeedScalar *)work, 10849289e5bfSjeremylt (const CeedScalar *)grad1d, laplace, P1d, P1d, Q1d); 1085e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1086713f43c3Sjeremylt // -- Diagonalize 1087713f43c3Sjeremylt ierr = CeedSimultaneousDiagonalization(ceed, laplace, mass, x, lambda, P1d); 1088e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1089e15f9bd0SJeremy L Thompson ierr = CeedFree(&work); CeedChkBackend(ierr); 1090e15f9bd0SJeremy L Thompson ierr = CeedFree(&mass); CeedChkBackend(ierr); 1091e15f9bd0SJeremy L Thompson ierr = CeedFree(&laplace); CeedChkBackend(ierr); 1092713f43c3Sjeremylt for (CeedInt i=0; i<P1d; i++) 1093713f43c3Sjeremylt for (CeedInt j=0; j<P1d; j++) 1094713f43c3Sjeremylt x2[i+j*P1d] = x[j+i*P1d]; 1095e15f9bd0SJeremy L Thompson ierr = CeedFree(&x); CeedChkBackend(ierr); 1096713f43c3Sjeremylt 1097713f43c3Sjeremylt // Assemble QFunction 1098713f43c3Sjeremylt CeedVector assembled; 1099713f43c3Sjeremylt CeedElemRestriction rstr_qf; 110080ac2e43SJeremy L Thompson ierr = CeedOperatorLinearAssembleQFunction(op, &assembled, &rstr_qf, 1101e15f9bd0SJeremy L Thompson request); CeedChkBackend(ierr); 1102e15f9bd0SJeremy L Thompson ierr = CeedElemRestrictionDestroy(&rstr_qf); CeedChkBackend(ierr); 11034f694d2fSjeremylt CeedScalar maxnorm = 0; 1104e15f9bd0SJeremy L Thompson ierr = CeedVectorNorm(assembled, CEED_NORM_MAX, &maxnorm); CeedChkBackend(ierr); 1105713f43c3Sjeremylt 1106713f43c3Sjeremylt // Calculate element averages 1107713f43c3Sjeremylt CeedInt nfields = ((interp?1:0) + (grad?dim:0))*((interp?1:0) + (grad?dim:0)); 1108713f43c3Sjeremylt CeedScalar *elemavg; 1109713f43c3Sjeremylt const CeedScalar *assembledarray, *qweightsarray; 1110713f43c3Sjeremylt CeedVector qweights; 1111e15f9bd0SJeremy L Thompson ierr = CeedVectorCreate(ceedparent, nqpts, &qweights); CeedChkBackend(ierr); 1112713f43c3Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, CEED_EVAL_WEIGHT, 1113e15f9bd0SJeremy L Thompson CEED_VECTOR_NONE, qweights); CeedChkBackend(ierr); 1114713f43c3Sjeremylt ierr = CeedVectorGetArrayRead(assembled, CEED_MEM_HOST, &assembledarray); 1115e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1116713f43c3Sjeremylt ierr = CeedVectorGetArrayRead(qweights, CEED_MEM_HOST, &qweightsarray); 1117e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1118e15f9bd0SJeremy L Thompson ierr = CeedCalloc(nelem, &elemavg); CeedChkBackend(ierr); 1119713f43c3Sjeremylt for (CeedInt e=0; e<nelem; e++) { 1120713f43c3Sjeremylt CeedInt count = 0; 1121713f43c3Sjeremylt for (CeedInt q=0; q<nqpts; q++) 1122713f43c3Sjeremylt for (CeedInt i=0; i<ncomp*ncomp*nfields; i++) 1123713f43c3Sjeremylt if (fabs(assembledarray[e*nelem*nqpts*ncomp*ncomp*nfields + 11244f694d2fSjeremylt i*nqpts + q]) > maxnorm*1e-12) { 1125713f43c3Sjeremylt elemavg[e] += assembledarray[e*nelem*nqpts*ncomp*ncomp*nfields + 1126713f43c3Sjeremylt i*nqpts + q] / qweightsarray[q]; 1127713f43c3Sjeremylt count++; 1128713f43c3Sjeremylt } 1129713f43c3Sjeremylt if (count) 1130713f43c3Sjeremylt elemavg[e] /= count; 1131713f43c3Sjeremylt } 1132e15f9bd0SJeremy L Thompson ierr = CeedVectorRestoreArrayRead(assembled, &assembledarray); 1133e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1134e15f9bd0SJeremy L Thompson ierr = CeedVectorDestroy(&assembled); CeedChkBackend(ierr); 1135e15f9bd0SJeremy L Thompson ierr = CeedVectorRestoreArrayRead(qweights, &qweightsarray); 1136e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1137e15f9bd0SJeremy L Thompson ierr = CeedVectorDestroy(&qweights); CeedChkBackend(ierr); 1138713f43c3Sjeremylt 1139713f43c3Sjeremylt // Build FDM diagonal 1140713f43c3Sjeremylt CeedVector qdata; 1141713f43c3Sjeremylt CeedScalar *qdataarray; 1142e15f9bd0SJeremy L Thompson ierr = CeedVectorCreate(ceedparent, nelem*ncomp*lsize, &qdata); 1143e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1144713f43c3Sjeremylt ierr = CeedVectorSetArray(qdata, CEED_MEM_HOST, CEED_COPY_VALUES, NULL); 1145e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1146e15f9bd0SJeremy L Thompson ierr = CeedVectorGetArray(qdata, CEED_MEM_HOST, &qdataarray); 1147e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1148713f43c3Sjeremylt for (CeedInt e=0; e<nelem; e++) 1149713f43c3Sjeremylt for (CeedInt c=0; c<ncomp; c++) 1150d979a051Sjeremylt for (CeedInt n=0; n<lsize; n++) { 1151713f43c3Sjeremylt if (interp) 1152d979a051Sjeremylt qdataarray[(e*ncomp+c)*lsize+n] = 1; 1153713f43c3Sjeremylt if (grad) 1154713f43c3Sjeremylt for (CeedInt d=0; d<dim; d++) { 1155713f43c3Sjeremylt CeedInt i = (n / CeedIntPow(P1d, d)) % P1d; 1156d979a051Sjeremylt qdataarray[(e*ncomp+c)*lsize+n] += lambda[i]; 1157713f43c3Sjeremylt } 1158d979a051Sjeremylt qdataarray[(e*ncomp+c)*lsize+n] = 1 / (elemavg[e] * 1159d979a051Sjeremylt qdataarray[(e*ncomp+c)*lsize+n]); 1160713f43c3Sjeremylt } 1161e15f9bd0SJeremy L Thompson ierr = CeedFree(&elemavg); CeedChkBackend(ierr); 1162e15f9bd0SJeremy L Thompson ierr = CeedVectorRestoreArray(qdata, &qdataarray); CeedChkBackend(ierr); 1163713f43c3Sjeremylt 1164713f43c3Sjeremylt // Setup FDM operator 1165713f43c3Sjeremylt // -- Basis 1166713f43c3Sjeremylt CeedBasis fdm_basis; 1167713f43c3Sjeremylt CeedScalar *graddummy, *qrefdummy, *qweightdummy; 1168e15f9bd0SJeremy L Thompson ierr = CeedCalloc(P1d*P1d, &graddummy); CeedChkBackend(ierr); 1169e15f9bd0SJeremy L Thompson ierr = CeedCalloc(P1d, &qrefdummy); CeedChkBackend(ierr); 1170e15f9bd0SJeremy L Thompson ierr = CeedCalloc(P1d, &qweightdummy); CeedChkBackend(ierr); 1171713f43c3Sjeremylt ierr = CeedBasisCreateTensorH1(ceedparent, dim, ncomp, P1d, P1d, x2, 1172713f43c3Sjeremylt graddummy, qrefdummy, qweightdummy, 1173e15f9bd0SJeremy L Thompson &fdm_basis); CeedChkBackend(ierr); 1174e15f9bd0SJeremy L Thompson ierr = CeedFree(&graddummy); CeedChkBackend(ierr); 1175e15f9bd0SJeremy L Thompson ierr = CeedFree(&qrefdummy); CeedChkBackend(ierr); 1176e15f9bd0SJeremy L Thompson ierr = CeedFree(&qweightdummy); CeedChkBackend(ierr); 1177e15f9bd0SJeremy L Thompson ierr = CeedFree(&x2); CeedChkBackend(ierr); 1178e15f9bd0SJeremy L Thompson ierr = CeedFree(&lambda); CeedChkBackend(ierr); 1179713f43c3Sjeremylt 1180713f43c3Sjeremylt // -- Restriction 1181713f43c3Sjeremylt CeedElemRestriction rstr_i; 1182d979a051Sjeremylt CeedInt strides[3] = {1, lsize, lsize*ncomp}; 1183d979a051Sjeremylt ierr = CeedElemRestrictionCreateStrided(ceedparent, nelem, lsize, ncomp, 1184d979a051Sjeremylt lsize*nelem*ncomp, strides, &rstr_i); 1185e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1186713f43c3Sjeremylt // -- QFunction 1187713f43c3Sjeremylt CeedQFunction mass_qf; 1188713f43c3Sjeremylt ierr = CeedQFunctionCreateInteriorByName(ceedparent, "MassApply", &mass_qf); 1189e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1190713f43c3Sjeremylt // -- Operator 1191713f43c3Sjeremylt ierr = CeedOperatorCreate(ceedparent, mass_qf, NULL, NULL, fdminv); 1192e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1193a8d32208Sjeremylt CeedOperatorSetField(*fdminv, "u", rstr_i, fdm_basis, CEED_VECTOR_ACTIVE); 1194e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1195a8d32208Sjeremylt CeedOperatorSetField(*fdminv, "qdata", rstr_i, CEED_BASIS_COLLOCATED, qdata); 1196e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1197a8d32208Sjeremylt CeedOperatorSetField(*fdminv, "v", rstr_i, fdm_basis, CEED_VECTOR_ACTIVE); 1198e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1199713f43c3Sjeremylt 1200713f43c3Sjeremylt // Cleanup 1201e15f9bd0SJeremy L Thompson ierr = CeedVectorDestroy(&qdata); CeedChkBackend(ierr); 1202e15f9bd0SJeremy L Thompson ierr = CeedBasisDestroy(&fdm_basis); CeedChkBackend(ierr); 1203e15f9bd0SJeremy L Thompson ierr = CeedElemRestrictionDestroy(&rstr_i); CeedChkBackend(ierr); 1204e15f9bd0SJeremy L Thompson ierr = CeedQFunctionDestroy(&mass_qf); CeedChkBackend(ierr); 1205713f43c3Sjeremylt 1206e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1207713f43c3Sjeremylt } 1208713f43c3Sjeremylt 1209f10650afSjeremylt //------------------------------------------------------------------------------ 1210f10650afSjeremylt // Operator Destroy 1211f10650afSjeremylt //------------------------------------------------------------------------------ 1212f10650afSjeremylt static int CeedOperatorDestroy_Ref(CeedOperator op) { 1213f10650afSjeremylt int ierr; 1214f10650afSjeremylt CeedOperator_Ref *impl; 1215e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetData(op, &impl); CeedChkBackend(ierr); 1216f10650afSjeremylt 1217f10650afSjeremylt for (CeedInt i=0; i<impl->numein+impl->numeout; i++) { 1218e15f9bd0SJeremy L Thompson ierr = CeedVectorDestroy(&impl->evecs[i]); CeedChkBackend(ierr); 1219f10650afSjeremylt } 1220e15f9bd0SJeremy L Thompson ierr = CeedFree(&impl->evecs); CeedChkBackend(ierr); 1221e15f9bd0SJeremy L Thompson ierr = CeedFree(&impl->edata); CeedChkBackend(ierr); 1222e15f9bd0SJeremy L Thompson ierr = CeedFree(&impl->inputstate); CeedChkBackend(ierr); 1223f10650afSjeremylt 1224f10650afSjeremylt for (CeedInt i=0; i<impl->numein; i++) { 1225e15f9bd0SJeremy L Thompson ierr = CeedVectorDestroy(&impl->evecsin[i]); CeedChkBackend(ierr); 1226e15f9bd0SJeremy L Thompson ierr = CeedVectorDestroy(&impl->qvecsin[i]); CeedChkBackend(ierr); 1227f10650afSjeremylt } 1228e15f9bd0SJeremy L Thompson ierr = CeedFree(&impl->evecsin); CeedChkBackend(ierr); 1229e15f9bd0SJeremy L Thompson ierr = CeedFree(&impl->qvecsin); CeedChkBackend(ierr); 1230f10650afSjeremylt 1231f10650afSjeremylt for (CeedInt i=0; i<impl->numeout; i++) { 1232e15f9bd0SJeremy L Thompson ierr = CeedVectorDestroy(&impl->evecsout[i]); CeedChkBackend(ierr); 1233e15f9bd0SJeremy L Thompson ierr = CeedVectorDestroy(&impl->qvecsout[i]); CeedChkBackend(ierr); 1234f10650afSjeremylt } 1235e15f9bd0SJeremy L Thompson ierr = CeedFree(&impl->evecsout); CeedChkBackend(ierr); 1236e15f9bd0SJeremy L Thompson ierr = CeedFree(&impl->qvecsout); CeedChkBackend(ierr); 1237f10650afSjeremylt 1238e15f9bd0SJeremy L Thompson ierr = CeedFree(&impl); CeedChkBackend(ierr); 1239e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1240f10650afSjeremylt } 1241f10650afSjeremylt 1242f10650afSjeremylt //------------------------------------------------------------------------------ 1243713f43c3Sjeremylt // Operator Create 1244f10650afSjeremylt //------------------------------------------------------------------------------ 124521617c04Sjeremylt int CeedOperatorCreate_Ref(CeedOperator op) { 124621617c04Sjeremylt int ierr; 1247fe2413ffSjeremylt Ceed ceed; 1248e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChkBackend(ierr); 12494ce2993fSjeremylt CeedOperator_Ref *impl; 125021617c04Sjeremylt 1251e15f9bd0SJeremy L Thompson ierr = CeedCalloc(1, &impl); CeedChkBackend(ierr); 1252e15f9bd0SJeremy L Thompson ierr = CeedOperatorSetData(op, impl); CeedChkBackend(ierr); 1253fe2413ffSjeremylt 125480ac2e43SJeremy L Thompson ierr = CeedSetBackendFunction(ceed, "Operator", op, "LinearAssembleQFunction", 125580ac2e43SJeremy L Thompson CeedOperatorLinearAssembleQFunction_Ref); 1256e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 12579e9210b8SJeremy L Thompson ierr = CeedSetBackendFunction(ceed, "Operator", op, "LinearAssembleAddDiagonal", 125869af5e5fSJeremy L Thompson CeedOperatorLinearAssembleAddDiagonal_Ref); 1259e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1260d965c7a7SJeremy L Thompson ierr = CeedSetBackendFunction(ceed, "Operator", op, 12619e9210b8SJeremy L Thompson "LinearAssembleAddPointBlockDiagonal", 126269af5e5fSJeremy L Thompson CeedOperatorLinearAssembleAddPointBlockDiagonal_Ref); 1263e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1264713f43c3Sjeremylt ierr = CeedSetBackendFunction(ceed, "Operator", op, "CreateFDMElementInverse", 1265713f43c3Sjeremylt CeedOperatorCreateFDMElementInverse_Ref); 1266e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1267cae8b89aSjeremylt ierr = CeedSetBackendFunction(ceed, "Operator", op, "ApplyAdd", 1268e15f9bd0SJeremy L Thompson CeedOperatorApplyAdd_Ref); CeedChkBackend(ierr); 1269fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Operator", op, "Destroy", 1270e15f9bd0SJeremy L Thompson CeedOperatorDestroy_Ref); CeedChkBackend(ierr); 1271e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 127221617c04Sjeremylt } 1273c04a41a7SJeremy L Thompson 1274c04a41a7SJeremy L Thompson //------------------------------------------------------------------------------ 1275c04a41a7SJeremy L Thompson // Composite Operator Create 1276c04a41a7SJeremy L Thompson //------------------------------------------------------------------------------ 1277c04a41a7SJeremy L Thompson int CeedCompositeOperatorCreate_Ref(CeedOperator op) { 1278c04a41a7SJeremy L Thompson int ierr; 1279c04a41a7SJeremy L Thompson Ceed ceed; 1280e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChkBackend(ierr); 12819e9210b8SJeremy L Thompson ierr = CeedSetBackendFunction(ceed, "Operator", op, "LinearAssembleAddDiagonal", 128269af5e5fSJeremy L Thompson CeedOperatorLinearAssembleAddDiagonal_Ref); 1283e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1284c04a41a7SJeremy L Thompson ierr = CeedSetBackendFunction(ceed, "Operator", op, 12859e9210b8SJeremy L Thompson "LinearAssembleAddPointBlockDiagonal", 128669af5e5fSJeremy L Thompson CeedOperatorLinearAssembleAddPointBlockDiagonal_Ref); 1287e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1288e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1289c04a41a7SJeremy L Thompson } 1290f10650afSjeremylt //------------------------------------------------------------------------------ 1291