1bd882c8aSJames Wright // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other 2bd882c8aSJames Wright // CEED contributors. All Rights Reserved. See the top-level LICENSE and NOTICE 3bd882c8aSJames Wright // files for details. 4bd882c8aSJames Wright // 5bd882c8aSJames Wright // SPDX-License-Identifier: BSD-2-Clause 6bd882c8aSJames Wright // 7bd882c8aSJames Wright // This file is part of CEED: http://github.com/ceed 8bd882c8aSJames Wright 9bd882c8aSJames Wright #include <ceed/backend.h> 10bd882c8aSJames Wright #include <ceed/ceed.h> 11bd882c8aSJames Wright 12bd882c8aSJames Wright #include <cassert> 13bd882c8aSJames Wright #include <string> 14bd882c8aSJames Wright #include <sycl/sycl.hpp> 15bd882c8aSJames Wright 16bd882c8aSJames Wright #include "../sycl/ceed-sycl-compile.hpp" 17bd882c8aSJames Wright #include "ceed-sycl-ref.hpp" 18bd882c8aSJames Wright 19bd882c8aSJames Wright class CeedOperatorSyclLinearDiagonal; 20bd882c8aSJames Wright class CeedOperatorSyclLinearAssemble; 21bd882c8aSJames Wright class CeedOperatorSyclLinearAssembleFallback; 22bd882c8aSJames Wright 23bd882c8aSJames Wright //------------------------------------------------------------------------------ 24bd882c8aSJames Wright // Get Basis Emode Pointer 25bd882c8aSJames Wright //------------------------------------------------------------------------------ 26bd882c8aSJames Wright void CeedOperatorGetBasisPointer_Sycl(const CeedScalar **basisptr, CeedEvalMode emode, const CeedScalar *identity, const CeedScalar *interp, 27bd882c8aSJames Wright const CeedScalar *grad) { 28bd882c8aSJames Wright switch (emode) { 29bd882c8aSJames Wright case CEED_EVAL_NONE: 30bd882c8aSJames Wright *basisptr = identity; 31bd882c8aSJames Wright break; 32bd882c8aSJames Wright case CEED_EVAL_INTERP: 33bd882c8aSJames Wright *basisptr = interp; 34bd882c8aSJames Wright break; 35bd882c8aSJames Wright case CEED_EVAL_GRAD: 36bd882c8aSJames Wright *basisptr = grad; 37bd882c8aSJames Wright break; 38bd882c8aSJames Wright case CEED_EVAL_WEIGHT: 39bd882c8aSJames Wright case CEED_EVAL_DIV: 40bd882c8aSJames Wright case CEED_EVAL_CURL: 41bd882c8aSJames Wright break; // Caught by QF Assembly 42bd882c8aSJames Wright } 43bd882c8aSJames Wright } 44bd882c8aSJames Wright 45bd882c8aSJames Wright //------------------------------------------------------------------------------ 46bd882c8aSJames Wright // Destroy operator 47bd882c8aSJames Wright //------------------------------------------------------------------------------ 48bd882c8aSJames Wright static int CeedOperatorDestroy_Sycl(CeedOperator op) { 49bd882c8aSJames Wright CeedOperator_Sycl *impl; 50bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetData(op, &impl)); 51bd882c8aSJames Wright Ceed ceed; 52bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetCeed(op, &ceed)); 53bd882c8aSJames Wright Ceed_Sycl *sycl_data; 54bd882c8aSJames Wright CeedCallBackend(CeedGetData(ceed, &sycl_data)); 55bd882c8aSJames Wright 56bd882c8aSJames Wright // Apply data 57bd882c8aSJames Wright for (CeedInt i = 0; i < impl->numein + impl->numeout; i++) { 58bd882c8aSJames Wright CeedCallBackend(CeedVectorDestroy(&impl->evecs[i])); 59bd882c8aSJames Wright } 60bd882c8aSJames Wright CeedCallBackend(CeedFree(&impl->evecs)); 61bd882c8aSJames Wright 62bd882c8aSJames Wright for (CeedInt i = 0; i < impl->numein; i++) { 63bd882c8aSJames Wright CeedCallBackend(CeedVectorDestroy(&impl->qvecsin[i])); 64bd882c8aSJames Wright } 65bd882c8aSJames Wright CeedCallBackend(CeedFree(&impl->qvecsin)); 66bd882c8aSJames Wright 67bd882c8aSJames Wright for (CeedInt i = 0; i < impl->numeout; i++) { 68bd882c8aSJames Wright CeedCallBackend(CeedVectorDestroy(&impl->qvecsout[i])); 69bd882c8aSJames Wright } 70bd882c8aSJames Wright CeedCallBackend(CeedFree(&impl->qvecsout)); 71bd882c8aSJames Wright 72bd882c8aSJames Wright // QFunction assembly data 73bd882c8aSJames Wright for (CeedInt i = 0; i < impl->qfnumactivein; i++) { 74bd882c8aSJames Wright CeedCallBackend(CeedVectorDestroy(&impl->qfactivein[i])); 75bd882c8aSJames Wright } 76bd882c8aSJames Wright CeedCallBackend(CeedFree(&impl->qfactivein)); 77bd882c8aSJames Wright 78bd882c8aSJames Wright // Diag data 79bd882c8aSJames Wright if (impl->diag) { 80bd882c8aSJames Wright CeedCallBackend(CeedFree(&impl->diag->h_emodein)); 81bd882c8aSJames Wright CeedCallBackend(CeedFree(&impl->diag->h_emodeout)); 82bd882c8aSJames Wright 83bd882c8aSJames Wright CeedCallSycl(ceed, sycl_data->sycl_queue.wait_and_throw()); 84bd882c8aSJames Wright CeedCallSycl(ceed, sycl::free(impl->diag->d_emodein, sycl_data->sycl_context)); 85bd882c8aSJames Wright CeedCallSycl(ceed, sycl::free(impl->diag->d_emodeout, sycl_data->sycl_context)); 86bd882c8aSJames Wright CeedCallSycl(ceed, sycl::free(impl->diag->d_identity, sycl_data->sycl_context)); 87bd882c8aSJames Wright CeedCallSycl(ceed, sycl::free(impl->diag->d_interpin, sycl_data->sycl_context)); 88bd882c8aSJames Wright CeedCallSycl(ceed, sycl::free(impl->diag->d_interpout, sycl_data->sycl_context)); 89bd882c8aSJames Wright CeedCallSycl(ceed, sycl::free(impl->diag->d_gradin, sycl_data->sycl_context)); 90bd882c8aSJames Wright CeedCallSycl(ceed, sycl::free(impl->diag->d_gradout, sycl_data->sycl_context)); 91bd882c8aSJames Wright CeedCallBackend(CeedElemRestrictionDestroy(&impl->diag->pbdiagrstr)); 92bd882c8aSJames Wright 93bd882c8aSJames Wright CeedCallBackend(CeedVectorDestroy(&impl->diag->elemdiag)); 94bd882c8aSJames Wright CeedCallBackend(CeedVectorDestroy(&impl->diag->pbelemdiag)); 95bd882c8aSJames Wright } 96bd882c8aSJames Wright CeedCallBackend(CeedFree(&impl->diag)); 97bd882c8aSJames Wright 98bd882c8aSJames Wright if (impl->asmb) { 99bd882c8aSJames Wright CeedCallSycl(ceed, sycl_data->sycl_queue.wait_and_throw()); 100bd882c8aSJames Wright CeedCallSycl(ceed, sycl::free(impl->asmb->d_B_in, sycl_data->sycl_context)); 101bd882c8aSJames Wright CeedCallSycl(ceed, sycl::free(impl->asmb->d_B_out, sycl_data->sycl_context)); 102bd882c8aSJames Wright } 103bd882c8aSJames Wright CeedCallBackend(CeedFree(&impl->asmb)); 104bd882c8aSJames Wright 105bd882c8aSJames Wright CeedCallBackend(CeedFree(&impl)); 106bd882c8aSJames Wright return CEED_ERROR_SUCCESS; 107bd882c8aSJames Wright } 108bd882c8aSJames Wright 109bd882c8aSJames Wright //------------------------------------------------------------------------------ 110bd882c8aSJames Wright // Setup infields or outfields 111bd882c8aSJames Wright //------------------------------------------------------------------------------ 112bd882c8aSJames Wright static int CeedOperatorSetupFields_Sycl(CeedQFunction qf, CeedOperator op, bool isinput, CeedVector *evecs, CeedVector *qvecs, CeedInt starte, 113bd882c8aSJames Wright CeedInt numfields, CeedInt Q, CeedInt numelements) { 114bd882c8aSJames Wright CeedInt dim, size; 115bd882c8aSJames Wright CeedSize q_size; 116bd882c8aSJames Wright Ceed ceed; 117bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetCeed(op, &ceed)); 118bd882c8aSJames Wright CeedBasis basis; 119bd882c8aSJames Wright CeedElemRestriction Erestrict; 120bd882c8aSJames Wright CeedOperatorField *opfields; 121bd882c8aSJames Wright CeedQFunctionField *qffields; 122bd882c8aSJames Wright CeedVector fieldvec; 123bd882c8aSJames Wright bool strided; 124bd882c8aSJames Wright bool skiprestrict; 125bd882c8aSJames Wright 126bd882c8aSJames Wright if (isinput) { 127bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetFields(op, NULL, &opfields, NULL, NULL)); 128bd882c8aSJames Wright CeedCallBackend(CeedQFunctionGetFields(qf, NULL, &qffields, NULL, NULL)); 129bd882c8aSJames Wright } else { 130bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetFields(op, NULL, NULL, NULL, &opfields)); 131bd882c8aSJames Wright CeedCallBackend(CeedQFunctionGetFields(qf, NULL, NULL, NULL, &qffields)); 132bd882c8aSJames Wright } 133bd882c8aSJames Wright 134bd882c8aSJames Wright // Loop over fields 135bd882c8aSJames Wright for (CeedInt i = 0; i < numfields; i++) { 136bd882c8aSJames Wright CeedEvalMode emode; 137bd882c8aSJames Wright CeedCallBackend(CeedQFunctionFieldGetEvalMode(qffields[i], &emode)); 138bd882c8aSJames Wright 139bd882c8aSJames Wright strided = false; 140bd882c8aSJames Wright skiprestrict = false; 141bd882c8aSJames Wright if (emode != CEED_EVAL_WEIGHT) { 142bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetElemRestriction(opfields[i], &Erestrict)); 143bd882c8aSJames Wright 144bd882c8aSJames Wright // Check whether this field can skip the element restriction: 145bd882c8aSJames Wright // must be passive input, with emode NONE, and have a strided restriction with CEED_STRIDES_BACKEND. 146bd882c8aSJames Wright 147bd882c8aSJames Wright // First, check whether the field is input or output: 148bd882c8aSJames Wright if (isinput) { 149bd882c8aSJames Wright // Check for passive input: 150bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetVector(opfields[i], &fieldvec)); 151bd882c8aSJames Wright if (fieldvec != CEED_VECTOR_ACTIVE) { 152bd882c8aSJames Wright // Check emode 153bd882c8aSJames Wright if (emode == CEED_EVAL_NONE) { 154bd882c8aSJames Wright // Check for strided restriction 155bd882c8aSJames Wright CeedCallBackend(CeedElemRestrictionIsStrided(Erestrict, &strided)); 156bd882c8aSJames Wright if (strided) { 157bd882c8aSJames Wright // Check if vector is already in preferred backend ordering 158bd882c8aSJames Wright CeedCallBackend(CeedElemRestrictionHasBackendStrides(Erestrict, &skiprestrict)); 159bd882c8aSJames Wright } 160bd882c8aSJames Wright } 161bd882c8aSJames Wright } 162bd882c8aSJames Wright } 163bd882c8aSJames Wright if (skiprestrict) { 164bd882c8aSJames Wright // We do not need an E-Vector, but will use the input field vector's data directly in the operator application 165bd882c8aSJames Wright evecs[i + starte] = NULL; 166bd882c8aSJames Wright } else { 167bd882c8aSJames Wright CeedCallBackend(CeedElemRestrictionCreateVector(Erestrict, NULL, &evecs[i + starte])); 168bd882c8aSJames Wright } 169bd882c8aSJames Wright } 170bd882c8aSJames Wright 171bd882c8aSJames Wright switch (emode) { 172bd882c8aSJames Wright case CEED_EVAL_NONE: 173bd882c8aSJames Wright CeedCallBackend(CeedQFunctionFieldGetSize(qffields[i], &size)); 174bd882c8aSJames Wright q_size = (CeedSize)numelements * Q * size; 175bd882c8aSJames Wright CeedCallBackend(CeedVectorCreate(ceed, q_size, &qvecs[i])); 176bd882c8aSJames Wright break; 177bd882c8aSJames Wright case CEED_EVAL_INTERP: 178bd882c8aSJames Wright CeedCallBackend(CeedQFunctionFieldGetSize(qffields[i], &size)); 179bd882c8aSJames Wright q_size = (CeedSize)numelements * Q * size; 180bd882c8aSJames Wright CeedCallBackend(CeedVectorCreate(ceed, q_size, &qvecs[i])); 181bd882c8aSJames Wright break; 182bd882c8aSJames Wright case CEED_EVAL_GRAD: 183bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetBasis(opfields[i], &basis)); 184bd882c8aSJames Wright CeedCallBackend(CeedQFunctionFieldGetSize(qffields[i], &size)); 185bd882c8aSJames Wright CeedCallBackend(CeedBasisGetDimension(basis, &dim)); 186bd882c8aSJames Wright q_size = (CeedSize)numelements * Q * size; 187bd882c8aSJames Wright CeedCallBackend(CeedVectorCreate(ceed, q_size, &qvecs[i])); 188bd882c8aSJames Wright break; 189bd882c8aSJames Wright case CEED_EVAL_WEIGHT: // Only on input fields 190bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetBasis(opfields[i], &basis)); 191bd882c8aSJames Wright q_size = (CeedSize)numelements * Q; 192bd882c8aSJames Wright CeedCallBackend(CeedVectorCreate(ceed, q_size, &qvecs[i])); 193bd882c8aSJames Wright CeedCallBackend(CeedBasisApply(basis, numelements, CEED_NOTRANSPOSE, CEED_EVAL_WEIGHT, NULL, qvecs[i])); 194bd882c8aSJames Wright break; 195bd882c8aSJames Wright case CEED_EVAL_DIV: 196bd882c8aSJames Wright break; // TODO: Not implemented 197bd882c8aSJames Wright case CEED_EVAL_CURL: 198bd882c8aSJames Wright break; // TODO: Not implemented 199bd882c8aSJames Wright } 200bd882c8aSJames Wright } 201bd882c8aSJames Wright return CEED_ERROR_SUCCESS; 202bd882c8aSJames Wright } 203bd882c8aSJames Wright 204bd882c8aSJames Wright //------------------------------------------------------------------------------ 205bd882c8aSJames Wright // CeedOperator needs to connect all the named fields (be they active or 206bd882c8aSJames Wright // passive) to the named inputs and outputs of its CeedQFunction. 207bd882c8aSJames Wright //------------------------------------------------------------------------------ 208bd882c8aSJames Wright static int CeedOperatorSetup_Sycl(CeedOperator op) { 209bd882c8aSJames Wright bool setupdone; 210bd882c8aSJames Wright CeedCallBackend(CeedOperatorIsSetupDone(op, &setupdone)); 211bd882c8aSJames Wright if (setupdone) return CEED_ERROR_SUCCESS; 212bd882c8aSJames Wright 213bd882c8aSJames Wright Ceed ceed; 214bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetCeed(op, &ceed)); 215bd882c8aSJames Wright CeedOperator_Sycl *impl; 216bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetData(op, &impl)); 217bd882c8aSJames Wright CeedQFunction qf; 218bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetQFunction(op, &qf)); 219bd882c8aSJames Wright CeedInt Q, numelements, numinputfields, numoutputfields; 220bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetNumQuadraturePoints(op, &Q)); 221bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetNumElements(op, &numelements)); 222bd882c8aSJames Wright CeedOperatorField *opinputfields, *opoutputfields; 223bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetFields(op, &numinputfields, &opinputfields, &numoutputfields, &opoutputfields)); 224bd882c8aSJames Wright CeedQFunctionField *qfinputfields, *qfoutputfields; 225bd882c8aSJames Wright CeedCallBackend(CeedQFunctionGetFields(qf, NULL, &qfinputfields, NULL, &qfoutputfields)); 226bd882c8aSJames Wright 227bd882c8aSJames Wright // Allocate 228bd882c8aSJames Wright CeedCallBackend(CeedCalloc(numinputfields + numoutputfields, &impl->evecs)); 229bd882c8aSJames Wright 230bd882c8aSJames Wright CeedCallBackend(CeedCalloc(CEED_FIELD_MAX, &impl->qvecsin)); 231bd882c8aSJames Wright CeedCallBackend(CeedCalloc(CEED_FIELD_MAX, &impl->qvecsout)); 232bd882c8aSJames Wright 233bd882c8aSJames Wright impl->numein = numinputfields; 234bd882c8aSJames Wright impl->numeout = numoutputfields; 235bd882c8aSJames Wright 236bd882c8aSJames Wright // Set up infield and outfield evecs and qvecs 237bd882c8aSJames Wright // Infields 238bd882c8aSJames Wright CeedCallBackend(CeedOperatorSetupFields_Sycl(qf, op, true, impl->evecs, impl->qvecsin, 0, numinputfields, Q, numelements)); 239bd882c8aSJames Wright 240bd882c8aSJames Wright // Outfields 241bd882c8aSJames Wright CeedCallBackend(CeedOperatorSetupFields_Sycl(qf, op, false, impl->evecs, impl->qvecsout, numinputfields, numoutputfields, Q, numelements)); 242bd882c8aSJames Wright 243bd882c8aSJames Wright CeedCallBackend(CeedOperatorSetSetupDone(op)); 244bd882c8aSJames Wright return CEED_ERROR_SUCCESS; 245bd882c8aSJames Wright } 246bd882c8aSJames Wright 247bd882c8aSJames Wright //------------------------------------------------------------------------------ 248bd882c8aSJames Wright // Setup Operator Inputs 249bd882c8aSJames Wright //------------------------------------------------------------------------------ 250bd882c8aSJames Wright static inline int CeedOperatorSetupInputs_Sycl(CeedInt numinputfields, CeedQFunctionField *qfinputfields, CeedOperatorField *opinputfields, 251bd882c8aSJames Wright CeedVector invec, const bool skipactive, CeedScalar *edata[2 * CEED_FIELD_MAX], 252bd882c8aSJames Wright CeedOperator_Sycl *impl, CeedRequest *request) { 253bd882c8aSJames Wright CeedEvalMode emode; 254bd882c8aSJames Wright CeedVector vec; 255bd882c8aSJames Wright CeedElemRestriction Erestrict; 256bd882c8aSJames Wright 257bd882c8aSJames Wright for (CeedInt i = 0; i < numinputfields; i++) { 258bd882c8aSJames Wright // Get input vector 259bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetVector(opinputfields[i], &vec)); 260bd882c8aSJames Wright if (vec == CEED_VECTOR_ACTIVE) { 261bd882c8aSJames Wright if (skipactive) continue; 262bd882c8aSJames Wright else vec = invec; 263bd882c8aSJames Wright } 264bd882c8aSJames Wright 265bd882c8aSJames Wright CeedCallBackend(CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode)); 266bd882c8aSJames Wright if (emode == CEED_EVAL_WEIGHT) { // Skip 267bd882c8aSJames Wright } else { 268bd882c8aSJames Wright // Get input vector 269bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetVector(opinputfields[i], &vec)); 270bd882c8aSJames Wright // Get input element restriction 271bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetElemRestriction(opinputfields[i], &Erestrict)); 272bd882c8aSJames Wright if (vec == CEED_VECTOR_ACTIVE) vec = invec; 273bd882c8aSJames Wright // Restrict, if necessary 274bd882c8aSJames Wright if (!impl->evecs[i]) { 275bd882c8aSJames Wright // No restriction for this field; read data directly from vec. 276bd882c8aSJames Wright CeedCallBackend(CeedVectorGetArrayRead(vec, CEED_MEM_DEVICE, (const CeedScalar **)&edata[i])); 277bd882c8aSJames Wright } else { 278bd882c8aSJames Wright CeedCallBackend(CeedElemRestrictionApply(Erestrict, CEED_NOTRANSPOSE, vec, impl->evecs[i], request)); 279bd882c8aSJames Wright // Get evec 280bd882c8aSJames Wright CeedCallBackend(CeedVectorGetArrayRead(impl->evecs[i], CEED_MEM_DEVICE, (const CeedScalar **)&edata[i])); 281bd882c8aSJames Wright } 282bd882c8aSJames Wright } 283bd882c8aSJames Wright } 284bd882c8aSJames Wright return CEED_ERROR_SUCCESS; 285bd882c8aSJames Wright } 286bd882c8aSJames Wright 287bd882c8aSJames Wright //------------------------------------------------------------------------------ 288bd882c8aSJames Wright // Input Basis Action 289bd882c8aSJames Wright //------------------------------------------------------------------------------ 290bd882c8aSJames Wright static inline int CeedOperatorInputBasis_Sycl(CeedInt numelements, CeedQFunctionField *qfinputfields, CeedOperatorField *opinputfields, 291bd882c8aSJames Wright CeedInt numinputfields, const bool skipactive, CeedScalar *edata[2 * CEED_FIELD_MAX], 292bd882c8aSJames Wright CeedOperator_Sycl *impl) { 293bd882c8aSJames Wright CeedInt elemsize, size; 294bd882c8aSJames Wright CeedElemRestriction Erestrict; 295bd882c8aSJames Wright CeedEvalMode emode; 296bd882c8aSJames Wright CeedBasis basis; 297bd882c8aSJames Wright 298bd882c8aSJames Wright for (CeedInt i = 0; i < numinputfields; i++) { 299bd882c8aSJames Wright // Skip active input 300bd882c8aSJames Wright if (skipactive) { 301bd882c8aSJames Wright CeedVector vec; 302bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetVector(opinputfields[i], &vec)); 303bd882c8aSJames Wright if (vec == CEED_VECTOR_ACTIVE) continue; 304bd882c8aSJames Wright } 305bd882c8aSJames Wright // Get elemsize, emode, size 306bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetElemRestriction(opinputfields[i], &Erestrict)); 307bd882c8aSJames Wright CeedCallBackend(CeedElemRestrictionGetElementSize(Erestrict, &elemsize)); 308bd882c8aSJames Wright CeedCallBackend(CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode)); 309bd882c8aSJames Wright CeedCallBackend(CeedQFunctionFieldGetSize(qfinputfields[i], &size)); 310bd882c8aSJames Wright // Basis action 311bd882c8aSJames Wright switch (emode) { 312bd882c8aSJames Wright case CEED_EVAL_NONE: 313bd882c8aSJames Wright CeedCallBackend(CeedVectorSetArray(impl->qvecsin[i], CEED_MEM_DEVICE, CEED_USE_POINTER, edata[i])); 314bd882c8aSJames Wright break; 315bd882c8aSJames Wright case CEED_EVAL_INTERP: 316bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetBasis(opinputfields[i], &basis)); 317bd882c8aSJames Wright CeedCallBackend(CeedBasisApply(basis, numelements, CEED_NOTRANSPOSE, CEED_EVAL_INTERP, impl->evecs[i], impl->qvecsin[i])); 318bd882c8aSJames Wright break; 319bd882c8aSJames Wright case CEED_EVAL_GRAD: 320bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetBasis(opinputfields[i], &basis)); 321bd882c8aSJames Wright CeedCallBackend(CeedBasisApply(basis, numelements, CEED_NOTRANSPOSE, CEED_EVAL_GRAD, impl->evecs[i], impl->qvecsin[i])); 322bd882c8aSJames Wright break; 323bd882c8aSJames Wright case CEED_EVAL_WEIGHT: 324bd882c8aSJames Wright break; // No action 325bd882c8aSJames Wright case CEED_EVAL_DIV: 326bd882c8aSJames Wright break; // TODO: Not implemented 327bd882c8aSJames Wright case CEED_EVAL_CURL: 328bd882c8aSJames Wright break; // TODO: Not implemented 329bd882c8aSJames Wright } 330bd882c8aSJames Wright } 331bd882c8aSJames Wright return CEED_ERROR_SUCCESS; 332bd882c8aSJames Wright } 333bd882c8aSJames Wright 334bd882c8aSJames Wright //------------------------------------------------------------------------------ 335bd882c8aSJames Wright // Restore Input Vectors 336bd882c8aSJames Wright //------------------------------------------------------------------------------ 337bd882c8aSJames Wright static inline int CeedOperatorRestoreInputs_Sycl(CeedInt numinputfields, CeedQFunctionField *qfinputfields, CeedOperatorField *opinputfields, 338bd882c8aSJames Wright const bool skipactive, CeedScalar *edata[2 * CEED_FIELD_MAX], CeedOperator_Sycl *impl) { 339bd882c8aSJames Wright CeedEvalMode emode; 340bd882c8aSJames Wright CeedVector vec; 341bd882c8aSJames Wright 342bd882c8aSJames Wright for (CeedInt i = 0; i < numinputfields; i++) { 343bd882c8aSJames Wright // Skip active input 344bd882c8aSJames Wright if (skipactive) { 345bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetVector(opinputfields[i], &vec)); 346bd882c8aSJames Wright if (vec == CEED_VECTOR_ACTIVE) continue; 347bd882c8aSJames Wright } 348bd882c8aSJames Wright CeedCallBackend(CeedQFunctionFieldGetEvalMode(qfinputfields[i], &emode)); 349bd882c8aSJames Wright if (emode == CEED_EVAL_WEIGHT) { // Skip 350bd882c8aSJames Wright } else { 351bd882c8aSJames Wright if (!impl->evecs[i]) { // This was a skiprestrict case 352bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetVector(opinputfields[i], &vec)); 353bd882c8aSJames Wright CeedCallBackend(CeedVectorRestoreArrayRead(vec, (const CeedScalar **)&edata[i])); 354bd882c8aSJames Wright } else { 355bd882c8aSJames Wright CeedCallBackend(CeedVectorRestoreArrayRead(impl->evecs[i], (const CeedScalar **)&edata[i])); 356bd882c8aSJames Wright } 357bd882c8aSJames Wright } 358bd882c8aSJames Wright } 359bd882c8aSJames Wright return CEED_ERROR_SUCCESS; 360bd882c8aSJames Wright } 361bd882c8aSJames Wright 362bd882c8aSJames Wright //------------------------------------------------------------------------------ 363bd882c8aSJames Wright // Apply and add to output 364bd882c8aSJames Wright //------------------------------------------------------------------------------ 365bd882c8aSJames Wright static int CeedOperatorApplyAdd_Sycl(CeedOperator op, CeedVector invec, CeedVector outvec, CeedRequest *request) { 366bd882c8aSJames Wright CeedOperator_Sycl *impl; 367bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetData(op, &impl)); 368bd882c8aSJames Wright CeedQFunction qf; 369bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetQFunction(op, &qf)); 370bd882c8aSJames Wright CeedInt Q, numelements, elemsize, numinputfields, numoutputfields, size; 371bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetNumQuadraturePoints(op, &Q)); 372bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetNumElements(op, &numelements)); 373bd882c8aSJames Wright CeedOperatorField *opinputfields, *opoutputfields; 374bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetFields(op, &numinputfields, &opinputfields, &numoutputfields, &opoutputfields)); 375bd882c8aSJames Wright CeedQFunctionField *qfinputfields, *qfoutputfields; 376bd882c8aSJames Wright CeedCallBackend(CeedQFunctionGetFields(qf, NULL, &qfinputfields, NULL, &qfoutputfields)); 377bd882c8aSJames Wright CeedEvalMode emode; 378bd882c8aSJames Wright CeedVector vec; 379bd882c8aSJames Wright CeedBasis basis; 380bd882c8aSJames Wright CeedElemRestriction Erestrict; 381bd882c8aSJames Wright CeedScalar *edata[2 * CEED_FIELD_MAX] = {0}; 382bd882c8aSJames Wright 383bd882c8aSJames Wright // Setup 384bd882c8aSJames Wright CeedCallBackend(CeedOperatorSetup_Sycl(op)); 385bd882c8aSJames Wright 386bd882c8aSJames Wright // Input Evecs and Restriction 387bd882c8aSJames Wright CeedCallBackend(CeedOperatorSetupInputs_Sycl(numinputfields, qfinputfields, opinputfields, invec, false, edata, impl, request)); 388bd882c8aSJames Wright 389bd882c8aSJames Wright // Input basis apply if needed 390bd882c8aSJames Wright CeedCallBackend(CeedOperatorInputBasis_Sycl(numelements, qfinputfields, opinputfields, numinputfields, false, edata, impl)); 391bd882c8aSJames Wright 392bd882c8aSJames Wright // Output pointers, as necessary 393bd882c8aSJames Wright for (CeedInt i = 0; i < numoutputfields; i++) { 394bd882c8aSJames Wright CeedCallBackend(CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode)); 395bd882c8aSJames Wright if (emode == CEED_EVAL_NONE) { 396bd882c8aSJames Wright // Set the output Q-Vector to use the E-Vector data directly 397bd882c8aSJames Wright CeedCallBackend(CeedVectorGetArrayWrite(impl->evecs[i + impl->numein], CEED_MEM_DEVICE, &edata[i + numinputfields])); 398bd882c8aSJames Wright CeedCallBackend(CeedVectorSetArray(impl->qvecsout[i], CEED_MEM_DEVICE, CEED_USE_POINTER, edata[i + numinputfields])); 399bd882c8aSJames Wright } 400bd882c8aSJames Wright } 401bd882c8aSJames Wright 402bd882c8aSJames Wright // Q function 403bd882c8aSJames Wright CeedCallBackend(CeedQFunctionApply(qf, numelements * Q, impl->qvecsin, impl->qvecsout)); 404bd882c8aSJames Wright 405bd882c8aSJames Wright // Output basis apply if needed 406bd882c8aSJames Wright for (CeedInt i = 0; i < numoutputfields; i++) { 407bd882c8aSJames Wright // Get elemsize, emode, size 408bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetElemRestriction(opoutputfields[i], &Erestrict)); 409bd882c8aSJames Wright CeedCallBackend(CeedElemRestrictionGetElementSize(Erestrict, &elemsize)); 410bd882c8aSJames Wright CeedCallBackend(CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode)); 411bd882c8aSJames Wright CeedCallBackend(CeedQFunctionFieldGetSize(qfoutputfields[i], &size)); 412bd882c8aSJames Wright // Basis action 413bd882c8aSJames Wright switch (emode) { 414bd882c8aSJames Wright case CEED_EVAL_NONE: 415bd882c8aSJames Wright break; 416bd882c8aSJames Wright case CEED_EVAL_INTERP: 417bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetBasis(opoutputfields[i], &basis)); 418bd882c8aSJames Wright CeedCallBackend(CeedBasisApply(basis, numelements, CEED_TRANSPOSE, CEED_EVAL_INTERP, impl->qvecsout[i], impl->evecs[i + impl->numein])); 419bd882c8aSJames Wright break; 420bd882c8aSJames Wright case CEED_EVAL_GRAD: 421bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetBasis(opoutputfields[i], &basis)); 422bd882c8aSJames Wright CeedCallBackend(CeedBasisApply(basis, numelements, CEED_TRANSPOSE, CEED_EVAL_GRAD, impl->qvecsout[i], impl->evecs[i + impl->numein])); 423bd882c8aSJames Wright break; 424bd882c8aSJames Wright // LCOV_EXCL_START 425bd882c8aSJames Wright case CEED_EVAL_WEIGHT: 426bd882c8aSJames Wright Ceed ceed; 427bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetCeed(op, &ceed)); 428bd882c8aSJames Wright return CeedError(ceed, CEED_ERROR_BACKEND, "CEED_EVAL_WEIGHT cannot be an output evaluation mode"); 429bd882c8aSJames Wright break; // Should not occur 430bd882c8aSJames Wright case CEED_EVAL_DIV: 431bd882c8aSJames Wright break; // TODO: Not implemented 432bd882c8aSJames Wright case CEED_EVAL_CURL: 433bd882c8aSJames Wright break; // TODO: Not implemented 434bd882c8aSJames Wright // LCOV_EXCL_STOP 435bd882c8aSJames Wright } 436bd882c8aSJames Wright } 437bd882c8aSJames Wright 438bd882c8aSJames Wright // Output restriction 439bd882c8aSJames Wright for (CeedInt i = 0; i < numoutputfields; i++) { 440bd882c8aSJames Wright // Restore evec 441bd882c8aSJames Wright CeedCallBackend(CeedQFunctionFieldGetEvalMode(qfoutputfields[i], &emode)); 442bd882c8aSJames Wright if (emode == CEED_EVAL_NONE) { 443bd882c8aSJames Wright CeedCallBackend(CeedVectorRestoreArray(impl->evecs[i + impl->numein], &edata[i + numinputfields])); 444bd882c8aSJames Wright } 445bd882c8aSJames Wright // Get output vector 446bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetVector(opoutputfields[i], &vec)); 447bd882c8aSJames Wright // Restrict 448bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetElemRestriction(opoutputfields[i], &Erestrict)); 449bd882c8aSJames Wright // Active 450bd882c8aSJames Wright if (vec == CEED_VECTOR_ACTIVE) vec = outvec; 451bd882c8aSJames Wright 452bd882c8aSJames Wright CeedCallBackend(CeedElemRestrictionApply(Erestrict, CEED_TRANSPOSE, impl->evecs[i + impl->numein], vec, request)); 453bd882c8aSJames Wright } 454bd882c8aSJames Wright 455bd882c8aSJames Wright // Restore input arrays 456bd882c8aSJames Wright CeedCallBackend(CeedOperatorRestoreInputs_Sycl(numinputfields, qfinputfields, opinputfields, false, edata, impl)); 457bd882c8aSJames Wright return CEED_ERROR_SUCCESS; 458bd882c8aSJames Wright } 459bd882c8aSJames Wright 460bd882c8aSJames Wright //------------------------------------------------------------------------------ 461bd882c8aSJames Wright // Core code for assembling linear QFunction 462bd882c8aSJames Wright //------------------------------------------------------------------------------ 463bd882c8aSJames Wright static inline int CeedOperatorLinearAssembleQFunctionCore_Sycl(CeedOperator op, bool build_objects, CeedVector *assembled, CeedElemRestriction *rstr, 464bd882c8aSJames Wright CeedRequest *request) { 465bd882c8aSJames Wright Ceed ceed, ceedparent; 466*e984cf9aSJeremy L Thompson CeedOperator_Sycl *impl; 467*e984cf9aSJeremy L Thompson CeedQFunction qf; 468*e984cf9aSJeremy L Thompson CeedQFunctionField *qfinputfields, *qfoutputfields; 469*e984cf9aSJeremy L Thompson CeedOperatorField *opinputfields, *opoutputfields; 470*e984cf9aSJeremy L Thompson CeedVector vec, *activein; 471*e984cf9aSJeremy L Thompson CeedInt numactivein, numactiveout, Q, numelements, numinputfields, numoutputfields, size; 472*e984cf9aSJeremy L Thompson CeedSize q_size; 473*e984cf9aSJeremy L Thompson CeedScalar *a, *tmp, *edata[2 * CEED_FIELD_MAX] = {NULL}; 474bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetCeed(op, &ceed)); 475bb229da9SJeremy L Thompson CeedCallBackend(CeedOperatorGetFallbackParentCeed(op, &ceedparent)); 476*e984cf9aSJeremy L Thompson CeedCallBackend(CeedOperatorGetData(op, &impl)); 477*e984cf9aSJeremy L Thompson activein = impl->qfactivein; 478*e984cf9aSJeremy L Thompson numactivein = impl->qfnumactivein, numactiveout = impl->qfnumactiveout; 479*e984cf9aSJeremy L Thompson CeedCallBackend(CeedOperatorGetQFunction(op, &qf)); 480*e984cf9aSJeremy L Thompson CeedCallBackend(CeedOperatorGetNumQuadraturePoints(op, &Q)); 481*e984cf9aSJeremy L Thompson CeedCallBackend(CeedOperatorGetNumElements(op, &numelements)); 482*e984cf9aSJeremy L Thompson CeedCallBackend(CeedQFunctionGetFields(qf, NULL, &qfinputfields, NULL, &qfoutputfields)); 483*e984cf9aSJeremy L Thompson CeedCallBackend(CeedOperatorGetFields(op, &numinputfields, &opinputfields, &numoutputfields, &opoutputfields)); 484bd882c8aSJames Wright 485bd882c8aSJames Wright // Setup 486bd882c8aSJames Wright CeedCallBackend(CeedOperatorSetup_Sycl(op)); 487bd882c8aSJames Wright 488bd882c8aSJames Wright // Check for identity 489bd882c8aSJames Wright bool identityqf; 490bd882c8aSJames Wright CeedCallBackend(CeedQFunctionIsIdentity(qf, &identityqf)); 491bd882c8aSJames Wright if (identityqf) { 492bd882c8aSJames Wright // LCOV_EXCL_START 493bd882c8aSJames Wright return CeedError(ceed, CEED_ERROR_BACKEND, "Assembling identity QFunctions not supported"); 494bd882c8aSJames Wright // LCOV_EXCL_STOP 495bd882c8aSJames Wright } 496bd882c8aSJames Wright 497bd882c8aSJames Wright // Input Evecs and Restriction 498bd882c8aSJames Wright CeedCallBackend(CeedOperatorSetupInputs_Sycl(numinputfields, qfinputfields, opinputfields, NULL, true, edata, impl, request)); 499bd882c8aSJames Wright 500bd882c8aSJames Wright // Count number of active input fields 501bd882c8aSJames Wright if (!numactivein) { 502bd882c8aSJames Wright for (CeedInt i = 0; i < numinputfields; i++) { 503bd882c8aSJames Wright // Get input vector 504bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetVector(opinputfields[i], &vec)); 505bd882c8aSJames Wright // Check if active input 506bd882c8aSJames Wright if (vec == CEED_VECTOR_ACTIVE) { 507bd882c8aSJames Wright CeedCallBackend(CeedQFunctionFieldGetSize(qfinputfields[i], &size)); 508bd882c8aSJames Wright CeedCallBackend(CeedVectorSetValue(impl->qvecsin[i], 0.0)); 509bd882c8aSJames Wright CeedCallBackend(CeedVectorGetArray(impl->qvecsin[i], CEED_MEM_DEVICE, &tmp)); 510bd882c8aSJames Wright CeedCallBackend(CeedRealloc(numactivein + size, &activein)); 511bd882c8aSJames Wright for (CeedInt field = 0; field < size; field++) { 512bd882c8aSJames Wright q_size = (CeedSize)Q * numelements; 513bd882c8aSJames Wright CeedCallBackend(CeedVectorCreate(ceed, q_size, &activein[numactivein + field])); 514bd882c8aSJames Wright CeedCallBackend(CeedVectorSetArray(activein[numactivein + field], CEED_MEM_DEVICE, CEED_USE_POINTER, &tmp[field * Q * numelements])); 515bd882c8aSJames Wright } 516bd882c8aSJames Wright numactivein += size; 517bd882c8aSJames Wright CeedCallBackend(CeedVectorRestoreArray(impl->qvecsin[i], &tmp)); 518bd882c8aSJames Wright } 519bd882c8aSJames Wright } 520bd882c8aSJames Wright impl->qfnumactivein = numactivein; 521bd882c8aSJames Wright impl->qfactivein = activein; 522bd882c8aSJames Wright } 523bd882c8aSJames Wright 524bd882c8aSJames Wright // Count number of active output fields 525bd882c8aSJames Wright if (!numactiveout) { 526bd882c8aSJames Wright for (CeedInt i = 0; i < numoutputfields; i++) { 527bd882c8aSJames Wright // Get output vector 528bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetVector(opoutputfields[i], &vec)); 529bd882c8aSJames Wright // Check if active output 530bd882c8aSJames Wright if (vec == CEED_VECTOR_ACTIVE) { 531bd882c8aSJames Wright CeedCallBackend(CeedQFunctionFieldGetSize(qfoutputfields[i], &size)); 532bd882c8aSJames Wright numactiveout += size; 533bd882c8aSJames Wright } 534bd882c8aSJames Wright } 535bd882c8aSJames Wright impl->qfnumactiveout = numactiveout; 536bd882c8aSJames Wright } 537bd882c8aSJames Wright 538bd882c8aSJames Wright // Check sizes 539bd882c8aSJames Wright if (!numactivein || !numactiveout) { 540bd882c8aSJames Wright // LCOV_EXCL_START 541bd882c8aSJames Wright return CeedError(ceed, CEED_ERROR_BACKEND, "Cannot assemble QFunction without active inputs and outputs"); 542bd882c8aSJames Wright // LCOV_EXCL_STOP 543bd882c8aSJames Wright } 544bd882c8aSJames Wright 545bd882c8aSJames Wright // Build objects if needed 546bd882c8aSJames Wright if (build_objects) { 547bd882c8aSJames Wright // Create output restriction 548bd882c8aSJames Wright CeedInt strides[3] = {1, numelements * Q, Q}; /* *NOPAD* */ 549bd882c8aSJames Wright CeedCallBackend(CeedElemRestrictionCreateStrided(ceedparent, numelements, Q, numactivein * numactiveout, 550bd882c8aSJames Wright numactivein * numactiveout * numelements * Q, strides, rstr)); 551bd882c8aSJames Wright // Create assembled vector 552bd882c8aSJames Wright CeedSize l_size = (CeedSize)numelements * Q * numactivein * numactiveout; 553bd882c8aSJames Wright CeedCallBackend(CeedVectorCreate(ceedparent, l_size, assembled)); 554bd882c8aSJames Wright } 555bd882c8aSJames Wright CeedCallBackend(CeedVectorSetValue(*assembled, 0.0)); 556bd882c8aSJames Wright CeedCallBackend(CeedVectorGetArray(*assembled, CEED_MEM_DEVICE, &a)); 557bd882c8aSJames Wright 558bd882c8aSJames Wright // Input basis apply 559bd882c8aSJames Wright CeedCallBackend(CeedOperatorInputBasis_Sycl(numelements, qfinputfields, opinputfields, numinputfields, true, edata, impl)); 560bd882c8aSJames Wright 561bd882c8aSJames Wright // Assemble QFunction 562bd882c8aSJames Wright for (CeedInt in = 0; in < numactivein; in++) { 563bd882c8aSJames Wright // Set Inputs 564bd882c8aSJames Wright CeedCallBackend(CeedVectorSetValue(activein[in], 1.0)); 565bd882c8aSJames Wright if (numactivein > 1) { 566bd882c8aSJames Wright CeedCallBackend(CeedVectorSetValue(activein[(in + numactivein - 1) % numactivein], 0.0)); 567bd882c8aSJames Wright } 568bd882c8aSJames Wright // Set Outputs 569bd882c8aSJames Wright for (CeedInt out = 0; out < numoutputfields; out++) { 570bd882c8aSJames Wright // Get output vector 571bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetVector(opoutputfields[out], &vec)); 572bd882c8aSJames Wright // Check if active output 573bd882c8aSJames Wright if (vec == CEED_VECTOR_ACTIVE) { 574bd882c8aSJames Wright CeedCallBackend(CeedVectorSetArray(impl->qvecsout[out], CEED_MEM_DEVICE, CEED_USE_POINTER, a)); 575bd882c8aSJames Wright CeedCallBackend(CeedQFunctionFieldGetSize(qfoutputfields[out], &size)); 576bd882c8aSJames Wright a += size * Q * numelements; // Advance the pointer by the size of the output 577bd882c8aSJames Wright } 578bd882c8aSJames Wright } 579bd882c8aSJames Wright // Apply QFunction 580bd882c8aSJames Wright CeedCallBackend(CeedQFunctionApply(qf, Q * numelements, impl->qvecsin, impl->qvecsout)); 581bd882c8aSJames Wright } 582bd882c8aSJames Wright 583bd882c8aSJames Wright // Un-set output Qvecs to prevent accidental overwrite of Assembled 584bd882c8aSJames Wright for (CeedInt out = 0; out < numoutputfields; out++) { 585bd882c8aSJames Wright // Get output vector 586bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetVector(opoutputfields[out], &vec)); 587bd882c8aSJames Wright // Check if active output 588bd882c8aSJames Wright if (vec == CEED_VECTOR_ACTIVE) { 589bd882c8aSJames Wright CeedCallBackend(CeedVectorTakeArray(impl->qvecsout[out], CEED_MEM_DEVICE, NULL)); 590bd882c8aSJames Wright } 591bd882c8aSJames Wright } 592bd882c8aSJames Wright 593bd882c8aSJames Wright // Restore input arrays 594bd882c8aSJames Wright CeedCallBackend(CeedOperatorRestoreInputs_Sycl(numinputfields, qfinputfields, opinputfields, true, edata, impl)); 595bd882c8aSJames Wright 596bd882c8aSJames Wright // Restore output 597bd882c8aSJames Wright CeedCallBackend(CeedVectorRestoreArray(*assembled, &a)); 598bd882c8aSJames Wright 599bd882c8aSJames Wright return CEED_ERROR_SUCCESS; 600bd882c8aSJames Wright } 601bd882c8aSJames Wright 602bd882c8aSJames Wright //------------------------------------------------------------------------------ 603bd882c8aSJames Wright // Assemble Linear QFunction 604bd882c8aSJames Wright //------------------------------------------------------------------------------ 605bd882c8aSJames Wright static int CeedOperatorLinearAssembleQFunction_Sycl(CeedOperator op, CeedVector *assembled, CeedElemRestriction *rstr, CeedRequest *request) { 606bd882c8aSJames Wright return CeedOperatorLinearAssembleQFunctionCore_Sycl(op, true, assembled, rstr, request); 607bd882c8aSJames Wright } 608bd882c8aSJames Wright 609bd882c8aSJames Wright //------------------------------------------------------------------------------ 610bd882c8aSJames Wright // Update Assembled Linear QFunction 611bd882c8aSJames Wright //------------------------------------------------------------------------------ 612bd882c8aSJames Wright static int CeedOperatorLinearAssembleQFunctionUpdate_Sycl(CeedOperator op, CeedVector assembled, CeedElemRestriction rstr, CeedRequest *request) { 613bd882c8aSJames Wright return CeedOperatorLinearAssembleQFunctionCore_Sycl(op, false, &assembled, &rstr, request); 614bd882c8aSJames Wright } 615bd882c8aSJames Wright 616bd882c8aSJames Wright //------------------------------------------------------------------------------ 617bd882c8aSJames Wright // Create point block restriction 618bd882c8aSJames Wright //------------------------------------------------------------------------------ 619bd882c8aSJames Wright static int CreatePBRestriction(CeedElemRestriction rstr, CeedElemRestriction *pbRstr) { 620bd882c8aSJames Wright Ceed ceed; 621bd882c8aSJames Wright CeedCallBackend(CeedElemRestrictionGetCeed(rstr, &ceed)); 622bd882c8aSJames Wright const CeedInt *offsets; 623bd882c8aSJames Wright CeedCallBackend(CeedElemRestrictionGetOffsets(rstr, CEED_MEM_HOST, &offsets)); 624bd882c8aSJames Wright 625bd882c8aSJames Wright // Expand offsets 626bd882c8aSJames Wright CeedInt nelem, ncomp, elemsize, compstride, *pbOffsets; 627bd882c8aSJames Wright CeedSize l_size; 628bd882c8aSJames Wright CeedCallBackend(CeedElemRestrictionGetNumElements(rstr, &nelem)); 629bd882c8aSJames Wright CeedCallBackend(CeedElemRestrictionGetNumComponents(rstr, &ncomp)); 630bd882c8aSJames Wright CeedCallBackend(CeedElemRestrictionGetElementSize(rstr, &elemsize)); 631bd882c8aSJames Wright CeedCallBackend(CeedElemRestrictionGetCompStride(rstr, &compstride)); 632bd882c8aSJames Wright CeedCallBackend(CeedElemRestrictionGetLVectorSize(rstr, &l_size)); 633bd882c8aSJames Wright CeedInt shift = ncomp; 634bd882c8aSJames Wright if (compstride != 1) shift *= ncomp; 635bd882c8aSJames Wright CeedCallBackend(CeedCalloc(nelem * elemsize, &pbOffsets)); 636bd882c8aSJames Wright for (CeedInt i = 0; i < nelem * elemsize; i++) { 637bd882c8aSJames Wright pbOffsets[i] = offsets[i] * shift; 638bd882c8aSJames Wright } 639bd882c8aSJames Wright 640bd882c8aSJames Wright // Create new restriction 641bd882c8aSJames Wright CeedCallBackend( 642bd882c8aSJames Wright CeedElemRestrictionCreate(ceed, nelem, elemsize, ncomp * ncomp, 1, l_size * ncomp, CEED_MEM_HOST, CEED_OWN_POINTER, pbOffsets, pbRstr)); 643bd882c8aSJames Wright 644bd882c8aSJames Wright // Cleanup 645bd882c8aSJames Wright CeedCallBackend(CeedElemRestrictionRestoreOffsets(rstr, &offsets)); 646bd882c8aSJames Wright 647bd882c8aSJames Wright return CEED_ERROR_SUCCESS; 648bd882c8aSJames Wright } 649bd882c8aSJames Wright 650bd882c8aSJames Wright //------------------------------------------------------------------------------ 651bd882c8aSJames Wright // Assemble diagonal setup 652bd882c8aSJames Wright //------------------------------------------------------------------------------ 653bd882c8aSJames Wright static inline int CeedOperatorAssembleDiagonalSetup_Sycl(CeedOperator op, const bool pointBlock) { 654bd882c8aSJames Wright Ceed ceed; 655bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetCeed(op, &ceed)); 656bd882c8aSJames Wright CeedQFunction qf; 657bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetQFunction(op, &qf)); 658bd882c8aSJames Wright CeedInt numinputfields, numoutputfields; 659bd882c8aSJames Wright CeedCallBackend(CeedQFunctionGetNumArgs(qf, &numinputfields, &numoutputfields)); 660bd882c8aSJames Wright 661bd882c8aSJames Wright // Determine active input basis 662bd882c8aSJames Wright CeedOperatorField *opfields; 663bd882c8aSJames Wright CeedQFunctionField *qffields; 664bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetFields(op, NULL, &opfields, NULL, NULL)); 665bd882c8aSJames Wright CeedCallBackend(CeedQFunctionGetFields(qf, NULL, &qffields, NULL, NULL)); 666bd882c8aSJames Wright CeedInt numemodein = 0, ncomp = 0, dim = 1; 667bd882c8aSJames Wright CeedEvalMode *emodein = NULL; 668bd882c8aSJames Wright CeedBasis basisin = NULL; 669bd882c8aSJames Wright CeedElemRestriction rstrin = NULL; 670bd882c8aSJames Wright for (CeedInt i = 0; i < numinputfields; i++) { 671bd882c8aSJames Wright CeedVector vec; 672bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetVector(opfields[i], &vec)); 673bd882c8aSJames Wright if (vec == CEED_VECTOR_ACTIVE) { 674bd882c8aSJames Wright CeedElemRestriction rstr; 675bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetBasis(opfields[i], &basisin)); 676bd882c8aSJames Wright CeedCallBackend(CeedBasisGetNumComponents(basisin, &ncomp)); 677bd882c8aSJames Wright CeedCallBackend(CeedBasisGetDimension(basisin, &dim)); 678bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetElemRestriction(opfields[i], &rstr)); 679bd882c8aSJames Wright if (rstrin && rstrin != rstr) { 680bd882c8aSJames Wright // LCOV_EXCL_START 681bd882c8aSJames Wright return CeedError(ceed, CEED_ERROR_BACKEND, "Backend does not implement multi-field non-composite operator diagonal assembly"); 682bd882c8aSJames Wright // LCOV_EXCL_STOP 683bd882c8aSJames Wright } 684bd882c8aSJames Wright rstrin = rstr; 685bd882c8aSJames Wright CeedEvalMode emode; 686bd882c8aSJames Wright CeedCallBackend(CeedQFunctionFieldGetEvalMode(qffields[i], &emode)); 687bd882c8aSJames Wright switch (emode) { 688bd882c8aSJames Wright case CEED_EVAL_NONE: 689bd882c8aSJames Wright case CEED_EVAL_INTERP: 690bd882c8aSJames Wright CeedCallBackend(CeedRealloc(numemodein + 1, &emodein)); 691bd882c8aSJames Wright emodein[numemodein] = emode; 692bd882c8aSJames Wright numemodein += 1; 693bd882c8aSJames Wright break; 694bd882c8aSJames Wright case CEED_EVAL_GRAD: 695bd882c8aSJames Wright CeedCallBackend(CeedRealloc(numemodein + dim, &emodein)); 696bd882c8aSJames Wright for (CeedInt d = 0; d < dim; d++) emodein[numemodein + d] = emode; 697bd882c8aSJames Wright numemodein += dim; 698bd882c8aSJames Wright break; 699bd882c8aSJames Wright case CEED_EVAL_WEIGHT: 700bd882c8aSJames Wright case CEED_EVAL_DIV: 701bd882c8aSJames Wright case CEED_EVAL_CURL: 702bd882c8aSJames Wright break; // Caught by QF Assembly 703bd882c8aSJames Wright } 704bd882c8aSJames Wright } 705bd882c8aSJames Wright } 706bd882c8aSJames Wright 707bd882c8aSJames Wright // Determine active output basis 708bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetFields(op, NULL, NULL, NULL, &opfields)); 709bd882c8aSJames Wright CeedCallBackend(CeedQFunctionGetFields(qf, NULL, NULL, NULL, &qffields)); 710bd882c8aSJames Wright CeedInt numemodeout = 0; 711bd882c8aSJames Wright CeedEvalMode *emodeout = NULL; 712bd882c8aSJames Wright CeedBasis basisout = NULL; 713bd882c8aSJames Wright CeedElemRestriction rstrout = NULL; 714bd882c8aSJames Wright for (CeedInt i = 0; i < numoutputfields; i++) { 715bd882c8aSJames Wright CeedVector vec; 716bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetVector(opfields[i], &vec)); 717bd882c8aSJames Wright if (vec == CEED_VECTOR_ACTIVE) { 718bd882c8aSJames Wright CeedElemRestriction rstr; 719bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetBasis(opfields[i], &basisout)); 720bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetElemRestriction(opfields[i], &rstr)); 721bd882c8aSJames Wright if (rstrout && rstrout != rstr) { 722bd882c8aSJames Wright // LCOV_EXCL_START 723bd882c8aSJames Wright return CeedError(ceed, CEED_ERROR_BACKEND, "Backend does not implement multi-field non-composite operator diagonal assembly"); 724bd882c8aSJames Wright // LCOV_EXCL_STOP 725bd882c8aSJames Wright } 726bd882c8aSJames Wright rstrout = rstr; 727bd882c8aSJames Wright CeedEvalMode emode; 728bd882c8aSJames Wright CeedCallBackend(CeedQFunctionFieldGetEvalMode(qffields[i], &emode)); 729bd882c8aSJames Wright switch (emode) { 730bd882c8aSJames Wright case CEED_EVAL_NONE: 731bd882c8aSJames Wright case CEED_EVAL_INTERP: 732bd882c8aSJames Wright CeedCallBackend(CeedRealloc(numemodeout + 1, &emodeout)); 733bd882c8aSJames Wright emodeout[numemodeout] = emode; 734bd882c8aSJames Wright numemodeout += 1; 735bd882c8aSJames Wright break; 736bd882c8aSJames Wright case CEED_EVAL_GRAD: 737bd882c8aSJames Wright CeedCallBackend(CeedRealloc(numemodeout + dim, &emodeout)); 738bd882c8aSJames Wright for (CeedInt d = 0; d < dim; d++) emodeout[numemodeout + d] = emode; 739bd882c8aSJames Wright numemodeout += dim; 740bd882c8aSJames Wright break; 741bd882c8aSJames Wright case CEED_EVAL_WEIGHT: 742bd882c8aSJames Wright case CEED_EVAL_DIV: 743bd882c8aSJames Wright case CEED_EVAL_CURL: 744bd882c8aSJames Wright break; // Caught by QF Assembly 745bd882c8aSJames Wright } 746bd882c8aSJames Wright } 747bd882c8aSJames Wright } 748bd882c8aSJames Wright 749bd882c8aSJames Wright // Operator data struct 750bd882c8aSJames Wright CeedOperator_Sycl *impl; 751bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetData(op, &impl)); 752bd882c8aSJames Wright Ceed_Sycl *sycl_data; 753bd882c8aSJames Wright CeedCallBackend(CeedGetData(ceed, &sycl_data)); 754bd882c8aSJames Wright CeedCallBackend(CeedCalloc(1, &impl->diag)); 755bd882c8aSJames Wright CeedOperatorDiag_Sycl *diag = impl->diag; 756bd882c8aSJames Wright diag->basisin = basisin; 757bd882c8aSJames Wright diag->basisout = basisout; 758bd882c8aSJames Wright diag->h_emodein = emodein; 759bd882c8aSJames Wright diag->h_emodeout = emodeout; 760bd882c8aSJames Wright diag->numemodein = numemodein; 761bd882c8aSJames Wright diag->numemodeout = numemodeout; 762bd882c8aSJames Wright 763bd882c8aSJames Wright // Kernel parameters 764bd882c8aSJames Wright CeedInt nnodes, nqpts; 765bd882c8aSJames Wright CeedCallBackend(CeedBasisGetNumNodes(basisin, &nnodes)); 766bd882c8aSJames Wright CeedCallBackend(CeedBasisGetNumQuadraturePoints(basisin, &nqpts)); 767bd882c8aSJames Wright diag->nnodes = nnodes; 768bd882c8aSJames Wright diag->nqpts = nqpts; 769bd882c8aSJames Wright diag->ncomp = ncomp; 770bd882c8aSJames Wright 771bd882c8aSJames Wright // Basis matrices 772bd882c8aSJames Wright const CeedInt iLen = nqpts * nnodes; 773bd882c8aSJames Wright const CeedInt gLen = nqpts * nnodes * dim; 774bd882c8aSJames Wright const CeedScalar *interpin, *interpout, *gradin, *gradout; 775bd882c8aSJames Wright 776bd882c8aSJames Wright // CEED_EVAL_NONE 777bd882c8aSJames Wright CeedScalar *identity = NULL; 778bd882c8aSJames Wright bool evalNone = false; 779bd882c8aSJames Wright for (CeedInt i = 0; i < numemodein; i++) evalNone = evalNone || (emodein[i] == CEED_EVAL_NONE); 780bd882c8aSJames Wright for (CeedInt i = 0; i < numemodeout; i++) evalNone = evalNone || (emodeout[i] == CEED_EVAL_NONE); 781bd882c8aSJames Wright 782bd882c8aSJames Wright // Order queue 783bd882c8aSJames Wright sycl::event e = sycl_data->sycl_queue.ext_oneapi_submit_barrier(); 784bd882c8aSJames Wright 785bd882c8aSJames Wright std::vector<sycl::event> copy_events; 786bd882c8aSJames Wright if (evalNone) { 787bd882c8aSJames Wright CeedCallBackend(CeedCalloc(nqpts * nnodes, &identity)); 7886ca0f394SUmesh Unnikrishnan for (CeedSize i = 0; i < (nnodes < nqpts ? nnodes : nqpts); i++) identity[i * nnodes + i] = 1.0; 789bd882c8aSJames Wright CeedCallSycl(ceed, diag->d_identity = sycl::malloc_device<CeedScalar>(iLen, sycl_data->sycl_device, sycl_data->sycl_context)); 790bd882c8aSJames Wright sycl::event identity_copy = sycl_data->sycl_queue.copy<CeedScalar>(identity, diag->d_identity, iLen, {e}); 791bd882c8aSJames Wright copy_events.push_back(identity_copy); 792bd882c8aSJames Wright } 793bd882c8aSJames Wright 794bd882c8aSJames Wright // CEED_EVAL_INTERP 795bd882c8aSJames Wright CeedCallBackend(CeedBasisGetInterp(basisin, &interpin)); 796bd882c8aSJames Wright CeedCallSycl(ceed, diag->d_interpin = sycl::malloc_device<CeedScalar>(iLen, sycl_data->sycl_device, sycl_data->sycl_context)); 797bd882c8aSJames Wright sycl::event interpin_copy = sycl_data->sycl_queue.copy<CeedScalar>(interpin, diag->d_interpin, iLen, {e}); 798bd882c8aSJames Wright copy_events.push_back(interpin_copy); 799bd882c8aSJames Wright 800bd882c8aSJames Wright CeedCallBackend(CeedBasisGetInterp(basisout, &interpout)); 801bd882c8aSJames Wright CeedCallSycl(ceed, diag->d_interpout = sycl::malloc_device<CeedScalar>(iLen, sycl_data->sycl_device, sycl_data->sycl_context)); 802bd882c8aSJames Wright sycl::event interpout_copy = sycl_data->sycl_queue.copy<CeedScalar>(interpout, diag->d_interpout, iLen, {e}); 803bd882c8aSJames Wright copy_events.push_back(interpout_copy); 804bd882c8aSJames Wright 805bd882c8aSJames Wright // CEED_EVAL_GRAD 806bd882c8aSJames Wright CeedCallBackend(CeedBasisGetGrad(basisin, &gradin)); 807bd882c8aSJames Wright CeedCallSycl(ceed, diag->d_gradin = sycl::malloc_device<CeedScalar>(gLen, sycl_data->sycl_device, sycl_data->sycl_context)); 808bd882c8aSJames Wright sycl::event gradin_copy = sycl_data->sycl_queue.copy<CeedScalar>(gradin, diag->d_gradin, gLen, {e}); 809bd882c8aSJames Wright copy_events.push_back(gradin_copy); 810bd882c8aSJames Wright 811bd882c8aSJames Wright CeedCallBackend(CeedBasisGetGrad(basisout, &gradout)); 812bd882c8aSJames Wright CeedCallSycl(ceed, diag->d_gradout = sycl::malloc_device<CeedScalar>(gLen, sycl_data->sycl_device, sycl_data->sycl_context)); 813bd882c8aSJames Wright sycl::event gradout_copy = sycl_data->sycl_queue.copy<CeedScalar>(gradout, diag->d_gradout, gLen, {e}); 814bd882c8aSJames Wright copy_events.push_back(gradout_copy); 815bd882c8aSJames Wright 816bd882c8aSJames Wright // Arrays of emodes 817bd882c8aSJames Wright CeedCallSycl(ceed, diag->d_emodein = sycl::malloc_device<CeedEvalMode>(numemodein, sycl_data->sycl_device, sycl_data->sycl_context)); 818bd882c8aSJames Wright sycl::event emodein_copy = sycl_data->sycl_queue.copy<CeedEvalMode>(emodein, diag->d_emodein, numemodein, {e}); 819bd882c8aSJames Wright copy_events.push_back(emodein_copy); 820bd882c8aSJames Wright 821bd882c8aSJames Wright CeedCallSycl(ceed, diag->d_emodeout = sycl::malloc_device<CeedEvalMode>(numemodeout, sycl_data->sycl_device, sycl_data->sycl_context)); 822bd882c8aSJames Wright sycl::event emodeout_copy = sycl_data->sycl_queue.copy<CeedEvalMode>(emodeout, diag->d_emodeout, numemodeout, {e}); 823bd882c8aSJames Wright copy_events.push_back(emodeout_copy); 824bd882c8aSJames Wright 825bd882c8aSJames Wright // Restriction 826bd882c8aSJames Wright diag->diagrstr = rstrout; 827bd882c8aSJames Wright 828bd882c8aSJames Wright // Wait for all copies to complete and handle exceptions 829bd882c8aSJames Wright CeedCallSycl(ceed, sycl::event::wait_and_throw(copy_events)); 830bd882c8aSJames Wright 831bd882c8aSJames Wright return CEED_ERROR_SUCCESS; 832bd882c8aSJames Wright } 833bd882c8aSJames Wright 834bd882c8aSJames Wright //------------------------------------------------------------------------------ 835bd882c8aSJames Wright // Kernel for diagonal assembly 836bd882c8aSJames Wright //------------------------------------------------------------------------------ 837bd882c8aSJames Wright static int CeedOperatorLinearDiagonal_Sycl(sycl::queue &sycl_queue, const bool pointBlock, const CeedInt nelem, const CeedOperatorDiag_Sycl *diag, 838bd882c8aSJames Wright const CeedScalar *assembledqfarray, CeedScalar *elemdiagarray) { 8396ca0f394SUmesh Unnikrishnan const CeedSize nnodes = diag->nnodes; 8406ca0f394SUmesh Unnikrishnan const CeedSize nqpts = diag->nqpts; 8416ca0f394SUmesh Unnikrishnan const CeedSize ncomp = diag->ncomp; 8426ca0f394SUmesh Unnikrishnan const CeedSize numemodein = diag->numemodein; 8436ca0f394SUmesh Unnikrishnan const CeedSize numemodeout = diag->numemodeout; 844bd882c8aSJames Wright 845bd882c8aSJames Wright const CeedScalar *identity = diag->d_identity; 846bd882c8aSJames Wright const CeedScalar *interpin = diag->d_interpin; 847bd882c8aSJames Wright const CeedScalar *gradin = diag->d_gradin; 848bd882c8aSJames Wright const CeedScalar *interpout = diag->d_interpout; 849bd882c8aSJames Wright const CeedScalar *gradout = diag->d_gradout; 850bd882c8aSJames Wright const CeedEvalMode *emodein = diag->d_emodein; 851bd882c8aSJames Wright const CeedEvalMode *emodeout = diag->d_emodeout; 852bd882c8aSJames Wright 853bd882c8aSJames Wright sycl::range<1> kernel_range(nelem * nnodes); 854bd882c8aSJames Wright 855bd882c8aSJames Wright // Order queue 856bd882c8aSJames Wright sycl::event e = sycl_queue.ext_oneapi_submit_barrier(); 857bd882c8aSJames Wright sycl_queue.parallel_for<CeedOperatorSyclLinearDiagonal>(kernel_range, {e}, [=](sycl::id<1> idx) { 858bd882c8aSJames Wright const CeedInt tid = idx % nnodes; 859bd882c8aSJames Wright const CeedInt e = idx / nnodes; 860bd882c8aSJames Wright 861bd882c8aSJames Wright // Compute the diagonal of B^T D B 862bd882c8aSJames Wright // Each element 863bd882c8aSJames Wright CeedInt dout = -1; 864bd882c8aSJames Wright // Each basis eval mode pair 8656ca0f394SUmesh Unnikrishnan for (CeedSize eout = 0; eout < numemodeout; eout++) { 866bd882c8aSJames Wright const CeedScalar *bt = NULL; 867bd882c8aSJames Wright if (emodeout[eout] == CEED_EVAL_GRAD) ++dout; 868bd882c8aSJames Wright CeedOperatorGetBasisPointer_Sycl(&bt, emodeout[eout], identity, interpout, &gradout[dout * nqpts * nnodes]); 869bd882c8aSJames Wright CeedInt din = -1; 8706ca0f394SUmesh Unnikrishnan for (CeedSize ein = 0; ein < numemodein; ein++) { 871bd882c8aSJames Wright const CeedScalar *b = NULL; 872bd882c8aSJames Wright if (emodein[ein] == CEED_EVAL_GRAD) ++din; 873bd882c8aSJames Wright CeedOperatorGetBasisPointer_Sycl(&b, emodein[ein], identity, interpin, &gradin[din * nqpts * nnodes]); 874bd882c8aSJames Wright // Each component 8756ca0f394SUmesh Unnikrishnan for (CeedSize compOut = 0; compOut < ncomp; compOut++) { 876bd882c8aSJames Wright // Each qpoint/node pair 877bd882c8aSJames Wright if (pointBlock) { 878bd882c8aSJames Wright // Point Block Diagonal 879bd882c8aSJames Wright for (CeedInt compIn = 0; compIn < ncomp; compIn++) { 880bd882c8aSJames Wright CeedScalar evalue = 0.0; 8816ca0f394SUmesh Unnikrishnan for (CeedSize q = 0; q < nqpts; q++) { 882bd882c8aSJames Wright const CeedScalar qfvalue = 883bd882c8aSJames Wright assembledqfarray[((((ein * ncomp + compIn) * numemodeout + eout) * ncomp + compOut) * nelem + e) * nqpts + q]; 884bd882c8aSJames Wright evalue += bt[q * nnodes + tid] * qfvalue * b[q * nnodes + tid]; 885bd882c8aSJames Wright } 886bd882c8aSJames Wright elemdiagarray[((compOut * ncomp + compIn) * nelem + e) * nnodes + tid] += evalue; 887bd882c8aSJames Wright } 888bd882c8aSJames Wright } else { 889bd882c8aSJames Wright // Diagonal Only 890bd882c8aSJames Wright CeedScalar evalue = 0.0; 8916ca0f394SUmesh Unnikrishnan for (CeedSize q = 0; q < nqpts; q++) { 892bd882c8aSJames Wright const CeedScalar qfvalue = 893bd882c8aSJames Wright assembledqfarray[((((ein * ncomp + compOut) * numemodeout + eout) * ncomp + compOut) * nelem + e) * nqpts + q]; 894bd882c8aSJames Wright evalue += bt[q * nnodes + tid] * qfvalue * b[q * nnodes + tid]; 895bd882c8aSJames Wright } 896bd882c8aSJames Wright elemdiagarray[(compOut * nelem + e) * nnodes + tid] += evalue; 897bd882c8aSJames Wright } 898bd882c8aSJames Wright } 899bd882c8aSJames Wright } 900bd882c8aSJames Wright } 901bd882c8aSJames Wright }); 902bd882c8aSJames Wright return CEED_ERROR_SUCCESS; 903bd882c8aSJames Wright } 904bd882c8aSJames Wright 905bd882c8aSJames Wright //------------------------------------------------------------------------------ 906bd882c8aSJames Wright // Assemble diagonal common code 907bd882c8aSJames Wright //------------------------------------------------------------------------------ 908bd882c8aSJames Wright static inline int CeedOperatorAssembleDiagonalCore_Sycl(CeedOperator op, CeedVector assembled, CeedRequest *request, const bool pointBlock) { 909bd882c8aSJames Wright Ceed ceed; 910bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetCeed(op, &ceed)); 911bd882c8aSJames Wright CeedOperator_Sycl *impl; 912bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetData(op, &impl)); 913bd882c8aSJames Wright Ceed_Sycl *sycl_data; 914bd882c8aSJames Wright CeedCallBackend(CeedGetData(ceed, &sycl_data)); 915bd882c8aSJames Wright 916bd882c8aSJames Wright // Assemble QFunction 917bd882c8aSJames Wright CeedVector assembledqf = NULL; 918bd882c8aSJames Wright CeedElemRestriction rstr = NULL; 919bd882c8aSJames Wright CeedCallBackend(CeedOperatorLinearAssembleQFunctionBuildOrUpdate(op, &assembledqf, &rstr, request)); 920bd882c8aSJames Wright CeedCallBackend(CeedElemRestrictionDestroy(&rstr)); 921bd882c8aSJames Wright 922bd882c8aSJames Wright // Setup 923bd882c8aSJames Wright if (!impl->diag) { 924bd882c8aSJames Wright CeedCallBackend(CeedOperatorAssembleDiagonalSetup_Sycl(op, pointBlock)); 925bd882c8aSJames Wright } 926bd882c8aSJames Wright CeedOperatorDiag_Sycl *diag = impl->diag; 927bd882c8aSJames Wright assert(diag != NULL); 928bd882c8aSJames Wright 929bd882c8aSJames Wright // Restriction 930bd882c8aSJames Wright if (pointBlock && !diag->pbdiagrstr) { 931bd882c8aSJames Wright CeedElemRestriction pbdiagrstr; 932bd882c8aSJames Wright CeedCallBackend(CreatePBRestriction(diag->diagrstr, &pbdiagrstr)); 933bd882c8aSJames Wright diag->pbdiagrstr = pbdiagrstr; 934bd882c8aSJames Wright } 935bd882c8aSJames Wright CeedElemRestriction diagrstr = pointBlock ? diag->pbdiagrstr : diag->diagrstr; 936bd882c8aSJames Wright 937bd882c8aSJames Wright // Create diagonal vector 938bd882c8aSJames Wright CeedVector elemdiag = pointBlock ? diag->pbelemdiag : diag->elemdiag; 939bd882c8aSJames Wright if (!elemdiag) { 940bd882c8aSJames Wright CeedCallBackend(CeedElemRestrictionCreateVector(diagrstr, NULL, &elemdiag)); 941bd882c8aSJames Wright if (pointBlock) diag->pbelemdiag = elemdiag; 942bd882c8aSJames Wright else diag->elemdiag = elemdiag; 943bd882c8aSJames Wright } 944bd882c8aSJames Wright CeedCallBackend(CeedVectorSetValue(elemdiag, 0.0)); 945bd882c8aSJames Wright 946bd882c8aSJames Wright // Assemble element operator diagonals 947bd882c8aSJames Wright CeedScalar *elemdiagarray; 948bd882c8aSJames Wright const CeedScalar *assembledqfarray; 949bd882c8aSJames Wright CeedCallBackend(CeedVectorGetArray(elemdiag, CEED_MEM_DEVICE, &elemdiagarray)); 950bd882c8aSJames Wright CeedCallBackend(CeedVectorGetArrayRead(assembledqf, CEED_MEM_DEVICE, &assembledqfarray)); 951bd882c8aSJames Wright CeedInt nelem; 952bd882c8aSJames Wright CeedCallBackend(CeedElemRestrictionGetNumElements(diagrstr, &nelem)); 953bd882c8aSJames Wright 954bd882c8aSJames Wright // Compute the diagonal of B^T D B 955bd882c8aSJames Wright // Umesh: This needs to be reviewed later 956bd882c8aSJames Wright // if (pointBlock) { 957bd882c8aSJames Wright // CeedCallBackend(CeedOperatorLinearPointBlockDiagonal_Sycl(sycl_data->sycl_queue, nelem, diag, assembledqfarray, elemdiagarray)); 958bd882c8aSJames Wright //} else { 959bd882c8aSJames Wright CeedCallBackend(CeedOperatorLinearDiagonal_Sycl(sycl_data->sycl_queue, pointBlock, nelem, diag, assembledqfarray, elemdiagarray)); 960bd882c8aSJames Wright // } 961bd882c8aSJames Wright 962bd882c8aSJames Wright // Wait for queue to complete and handle exceptions 963bd882c8aSJames Wright sycl_data->sycl_queue.wait_and_throw(); 964bd882c8aSJames Wright 965bd882c8aSJames Wright // Restore arrays 966bd882c8aSJames Wright CeedCallBackend(CeedVectorRestoreArray(elemdiag, &elemdiagarray)); 967bd882c8aSJames Wright CeedCallBackend(CeedVectorRestoreArrayRead(assembledqf, &assembledqfarray)); 968bd882c8aSJames Wright 969bd882c8aSJames Wright // Assemble local operator diagonal 970bd882c8aSJames Wright CeedCallBackend(CeedElemRestrictionApply(diagrstr, CEED_TRANSPOSE, elemdiag, assembled, request)); 971bd882c8aSJames Wright 972bd882c8aSJames Wright // Cleanup 973bd882c8aSJames Wright CeedCallBackend(CeedVectorDestroy(&assembledqf)); 974bd882c8aSJames Wright 975bd882c8aSJames Wright return CEED_ERROR_SUCCESS; 976bd882c8aSJames Wright } 977bd882c8aSJames Wright 978bd882c8aSJames Wright //------------------------------------------------------------------------------ 979bd882c8aSJames Wright // Assemble Linear Diagonal 980bd882c8aSJames Wright //------------------------------------------------------------------------------ 981bd882c8aSJames Wright static int CeedOperatorLinearAssembleAddDiagonal_Sycl(CeedOperator op, CeedVector assembled, CeedRequest *request) { 982bd882c8aSJames Wright CeedCallBackend(CeedOperatorAssembleDiagonalCore_Sycl(op, assembled, request, false)); 983bd882c8aSJames Wright return CEED_ERROR_SUCCESS; 984bd882c8aSJames Wright } 985bd882c8aSJames Wright 986bd882c8aSJames Wright //------------------------------------------------------------------------------ 987bd882c8aSJames Wright // Assemble Linear Point Block Diagonal 988bd882c8aSJames Wright //------------------------------------------------------------------------------ 989bd882c8aSJames Wright static int CeedOperatorLinearAssembleAddPointBlockDiagonal_Sycl(CeedOperator op, CeedVector assembled, CeedRequest *request) { 990bd882c8aSJames Wright CeedCallBackend(CeedOperatorAssembleDiagonalCore_Sycl(op, assembled, request, true)); 991bd882c8aSJames Wright return CEED_ERROR_SUCCESS; 992bd882c8aSJames Wright } 993bd882c8aSJames Wright 994bd882c8aSJames Wright //------------------------------------------------------------------------------ 995bd882c8aSJames Wright // Single operator assembly setup 996bd882c8aSJames Wright //------------------------------------------------------------------------------ 997bd882c8aSJames Wright static int CeedSingleOperatorAssembleSetup_Sycl(CeedOperator op) { 998bd882c8aSJames Wright Ceed ceed; 999bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetCeed(op, &ceed)); 1000bd882c8aSJames Wright CeedOperator_Sycl *impl; 1001bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetData(op, &impl)); 1002bd882c8aSJames Wright 1003bd882c8aSJames Wright // Get input and output fields 1004bd882c8aSJames Wright CeedInt num_input_fields, num_output_fields; 1005bd882c8aSJames Wright CeedOperatorField *input_fields; 1006bd882c8aSJames Wright CeedOperatorField *output_fields; 1007bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetFields(op, &num_input_fields, &input_fields, &num_output_fields, &output_fields)); 1008bd882c8aSJames Wright 1009bd882c8aSJames Wright // Determine active input basis eval mode 1010bd882c8aSJames Wright CeedQFunction qf; 1011bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetQFunction(op, &qf)); 1012bd882c8aSJames Wright CeedQFunctionField *qf_fields; 1013bd882c8aSJames Wright CeedCallBackend(CeedQFunctionGetFields(qf, NULL, &qf_fields, NULL, NULL)); 1014bd882c8aSJames Wright // Note that the kernel will treat each dimension of a gradient action separately; 1015bd882c8aSJames Wright // i.e., when an active input has a CEED_EVAL_GRAD mode, num_emode_in will increment by dim. 1016bd882c8aSJames Wright // However, for the purposes of loading the B matrices, it will be treated as one mode, and we will load/copy the entire gradient matrix at once, so 1017bd882c8aSJames Wright // num_B_in_mats_to_load will be incremented by 1. 1018bd882c8aSJames Wright CeedInt num_emode_in = 0, dim = 1, num_B_in_mats_to_load = 0, size_B_in = 0; 1019bd882c8aSJames Wright CeedEvalMode *eval_mode_in = NULL; // will be of size num_B_in_mats_load 1020bd882c8aSJames Wright CeedBasis basis_in = NULL; 1021bd882c8aSJames Wright CeedInt nqpts = 0, esize = 0; 1022bd882c8aSJames Wright CeedElemRestriction rstr_in = NULL; 1023bd882c8aSJames Wright for (CeedInt i = 0; i < num_input_fields; i++) { 1024bd882c8aSJames Wright CeedVector vec; 1025bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetVector(input_fields[i], &vec)); 1026bd882c8aSJames Wright if (vec == CEED_VECTOR_ACTIVE) { 1027bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetBasis(input_fields[i], &basis_in)); 1028bd882c8aSJames Wright CeedCallBackend(CeedBasisGetDimension(basis_in, &dim)); 1029bd882c8aSJames Wright CeedCallBackend(CeedBasisGetNumQuadraturePoints(basis_in, &nqpts)); 1030bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetElemRestriction(input_fields[i], &rstr_in)); 1031bd882c8aSJames Wright CeedCallBackend(CeedElemRestrictionGetElementSize(rstr_in, &esize)); 1032bd882c8aSJames Wright CeedEvalMode eval_mode; 1033bd882c8aSJames Wright CeedCallBackend(CeedQFunctionFieldGetEvalMode(qf_fields[i], &eval_mode)); 1034bd882c8aSJames Wright if (eval_mode != CEED_EVAL_NONE) { 1035bd882c8aSJames Wright CeedCallBackend(CeedRealloc(num_B_in_mats_to_load + 1, &eval_mode_in)); 1036bd882c8aSJames Wright eval_mode_in[num_B_in_mats_to_load] = eval_mode; 1037bd882c8aSJames Wright num_B_in_mats_to_load += 1; 1038bd882c8aSJames Wright if (eval_mode == CEED_EVAL_GRAD) { 1039bd882c8aSJames Wright num_emode_in += dim; 1040bd882c8aSJames Wright size_B_in += dim * esize * nqpts; 1041bd882c8aSJames Wright } else { 1042bd882c8aSJames Wright num_emode_in += 1; 1043bd882c8aSJames Wright size_B_in += esize * nqpts; 1044bd882c8aSJames Wright } 1045bd882c8aSJames Wright } 1046bd882c8aSJames Wright } 1047bd882c8aSJames Wright } 1048bd882c8aSJames Wright 1049bd882c8aSJames Wright // Determine active output basis; basis_out and rstr_out only used if same as input, TODO 1050bd882c8aSJames Wright CeedCallBackend(CeedQFunctionGetFields(qf, NULL, NULL, NULL, &qf_fields)); 1051bd882c8aSJames Wright CeedInt num_emode_out = 0, num_B_out_mats_to_load = 0, size_B_out = 0; 1052bd882c8aSJames Wright CeedEvalMode *eval_mode_out = NULL; 1053bd882c8aSJames Wright CeedBasis basis_out = NULL; 1054bd882c8aSJames Wright CeedElemRestriction rstr_out = NULL; 1055bd882c8aSJames Wright for (CeedInt i = 0; i < num_output_fields; i++) { 1056bd882c8aSJames Wright CeedVector vec; 1057bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetVector(output_fields[i], &vec)); 1058bd882c8aSJames Wright if (vec == CEED_VECTOR_ACTIVE) { 1059bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetBasis(output_fields[i], &basis_out)); 1060bd882c8aSJames Wright CeedCallBackend(CeedOperatorFieldGetElemRestriction(output_fields[i], &rstr_out)); 1061bd882c8aSJames Wright if (rstr_out && rstr_out != rstr_in) { 1062bd882c8aSJames Wright // LCOV_EXCL_START 1063bd882c8aSJames Wright return CeedError(ceed, CEED_ERROR_BACKEND, "Backend does not implement multi-field non-composite operator assembly"); 1064bd882c8aSJames Wright // LCOV_EXCL_STOP 1065bd882c8aSJames Wright } 1066bd882c8aSJames Wright CeedEvalMode eval_mode; 1067bd882c8aSJames Wright CeedCallBackend(CeedQFunctionFieldGetEvalMode(qf_fields[i], &eval_mode)); 1068bd882c8aSJames Wright if (eval_mode != CEED_EVAL_NONE) { 1069bd882c8aSJames Wright CeedCallBackend(CeedRealloc(num_B_out_mats_to_load + 1, &eval_mode_out)); 1070bd882c8aSJames Wright eval_mode_out[num_B_out_mats_to_load] = eval_mode; 1071bd882c8aSJames Wright num_B_out_mats_to_load += 1; 1072bd882c8aSJames Wright if (eval_mode == CEED_EVAL_GRAD) { 1073bd882c8aSJames Wright num_emode_out += dim; 1074bd882c8aSJames Wright size_B_out += dim * esize * nqpts; 1075bd882c8aSJames Wright } else { 1076bd882c8aSJames Wright num_emode_out += 1; 1077bd882c8aSJames Wright size_B_out += esize * nqpts; 1078bd882c8aSJames Wright } 1079bd882c8aSJames Wright } 1080bd882c8aSJames Wright } 1081bd882c8aSJames Wright } 1082bd882c8aSJames Wright 1083bd882c8aSJames Wright if (num_emode_in == 0 || num_emode_out == 0) { 1084bd882c8aSJames Wright // LCOV_EXCL_START 1085bd882c8aSJames Wright return CeedError(ceed, CEED_ERROR_UNSUPPORTED, "Cannot assemble operator without inputs/outputs"); 1086bd882c8aSJames Wright // LCOV_EXCL_STOP 1087bd882c8aSJames Wright } 1088bd882c8aSJames Wright 1089bd882c8aSJames Wright CeedInt nelem, ncomp; 1090bd882c8aSJames Wright CeedCallBackend(CeedElemRestrictionGetNumElements(rstr_in, &nelem)); 1091bd882c8aSJames Wright CeedCallBackend(CeedElemRestrictionGetNumComponents(rstr_in, &ncomp)); 1092bd882c8aSJames Wright 1093bd882c8aSJames Wright CeedCallBackend(CeedCalloc(1, &impl->asmb)); 1094bd882c8aSJames Wright CeedOperatorAssemble_Sycl *asmb = impl->asmb; 1095bd882c8aSJames Wright asmb->nelem = nelem; 1096bd882c8aSJames Wright 1097bd882c8aSJames Wright Ceed_Sycl *sycl_data; 1098bd882c8aSJames Wright CeedCallBackend(CeedGetData(ceed, &sycl_data)); 1099bd882c8aSJames Wright 1100bd882c8aSJames Wright // Kernel setup 1101bd882c8aSJames Wright int elemsPerBlock = 1; 1102bd882c8aSJames Wright asmb->elemsPerBlock = elemsPerBlock; 1103bd882c8aSJames Wright CeedInt block_size = esize * esize * elemsPerBlock; 1104bd882c8aSJames Wright /* CeedInt maxThreadsPerBlock = sycl_data->sycl_device.get_info<sycl::info::device::max_work_group_size>(); 1105bd882c8aSJames Wright bool fallback = block_size > maxThreadsPerBlock; 1106bd882c8aSJames Wright asmb->fallback = fallback; 1107bd882c8aSJames Wright if (fallback) { 1108bd882c8aSJames Wright // Use fallback kernel with 1D threadblock 1109bd882c8aSJames Wright block_size = esize * elemsPerBlock; 1110bd882c8aSJames Wright asmb->block_size_x = esize; 1111bd882c8aSJames Wright asmb->block_size_y = 1; 1112bd882c8aSJames Wright } else { // Use kernel with 2D threadblock 1113bd882c8aSJames Wright asmb->block_size_x = esize; 1114bd882c8aSJames Wright asmb->block_size_y = esize; 1115bd882c8aSJames Wright }*/ 1116bd882c8aSJames Wright asmb->block_size_x = esize; 1117bd882c8aSJames Wright asmb->block_size_y = esize; 1118bd882c8aSJames Wright asmb->numemodein = num_emode_in; 1119bd882c8aSJames Wright asmb->numemodeout = num_emode_out; 1120bd882c8aSJames Wright asmb->nqpts = nqpts; 1121bd882c8aSJames Wright asmb->nnodes = esize; 1122bd882c8aSJames Wright asmb->block_size = block_size; 1123bd882c8aSJames Wright asmb->ncomp = ncomp; 1124bd882c8aSJames Wright 1125bd882c8aSJames Wright // Build 'full' B matrices (not 1D arrays used for tensor-product matrices 1126bd882c8aSJames Wright const CeedScalar *interp_in, *grad_in; 1127bd882c8aSJames Wright CeedCallBackend(CeedBasisGetInterp(basis_in, &interp_in)); 1128bd882c8aSJames Wright CeedCallBackend(CeedBasisGetGrad(basis_in, &grad_in)); 1129bd882c8aSJames Wright 1130bd882c8aSJames Wright // Load into B_in, in order that they will be used in eval_mode 1131bd882c8aSJames Wright CeedInt mat_start = 0; 1132bd882c8aSJames Wright CeedCallSycl(ceed, asmb->d_B_in = sycl::malloc_device<CeedScalar>(size_B_in, sycl_data->sycl_device, sycl_data->sycl_context)); 1133bd882c8aSJames Wright for (int i = 0; i < num_B_in_mats_to_load; i++) { 1134bd882c8aSJames Wright CeedEvalMode eval_mode = eval_mode_in[i]; 1135bd882c8aSJames Wright if (eval_mode == CEED_EVAL_INTERP) { 1136bd882c8aSJames Wright // Order queue 1137bd882c8aSJames Wright sycl::event e = sycl_data->sycl_queue.ext_oneapi_submit_barrier(); 1138bd882c8aSJames Wright sycl_data->sycl_queue.copy<CeedScalar>(interp_in, &asmb->d_B_in[mat_start], esize * nqpts, {e}); 1139bd882c8aSJames Wright mat_start += esize * nqpts; 1140bd882c8aSJames Wright } else if (eval_mode == CEED_EVAL_GRAD) { 1141bd882c8aSJames Wright // Order queue 1142bd882c8aSJames Wright sycl::event e = sycl_data->sycl_queue.ext_oneapi_submit_barrier(); 1143bd882c8aSJames Wright sycl_data->sycl_queue.copy<CeedScalar>(grad_in, &asmb->d_B_in[mat_start], dim * esize * nqpts, {e}); 1144bd882c8aSJames Wright mat_start += dim * esize * nqpts; 1145bd882c8aSJames Wright } 1146bd882c8aSJames Wright } 1147bd882c8aSJames Wright 1148bd882c8aSJames Wright const CeedScalar *interp_out, *grad_out; 1149bd882c8aSJames Wright // Note that this function currently assumes 1 basis, so this should always be true 1150bd882c8aSJames Wright // for now 1151bd882c8aSJames Wright if (basis_out == basis_in) { 1152bd882c8aSJames Wright interp_out = interp_in; 1153bd882c8aSJames Wright grad_out = grad_in; 1154bd882c8aSJames Wright } else { 1155bd882c8aSJames Wright CeedCallBackend(CeedBasisGetInterp(basis_out, &interp_out)); 1156bd882c8aSJames Wright CeedCallBackend(CeedBasisGetGrad(basis_out, &grad_out)); 1157bd882c8aSJames Wright } 1158bd882c8aSJames Wright 1159bd882c8aSJames Wright // Load into B_out, in order that they will be used in eval_mode 1160bd882c8aSJames Wright mat_start = 0; 1161bd882c8aSJames Wright CeedCallSycl(ceed, asmb->d_B_out = sycl::malloc_device<CeedScalar>(size_B_out, sycl_data->sycl_device, sycl_data->sycl_context)); 1162bd882c8aSJames Wright for (int i = 0; i < num_B_out_mats_to_load; i++) { 1163bd882c8aSJames Wright CeedEvalMode eval_mode = eval_mode_out[i]; 1164bd882c8aSJames Wright if (eval_mode == CEED_EVAL_INTERP) { 1165bd882c8aSJames Wright // Order queue 1166bd882c8aSJames Wright sycl::event e = sycl_data->sycl_queue.ext_oneapi_submit_barrier(); 1167bd882c8aSJames Wright sycl_data->sycl_queue.copy<CeedScalar>(interp_out, &asmb->d_B_out[mat_start], esize * nqpts, {e}); 1168bd882c8aSJames Wright mat_start += esize * nqpts; 1169bd882c8aSJames Wright } else if (eval_mode == CEED_EVAL_GRAD) { 1170bd882c8aSJames Wright // Order queue 1171bd882c8aSJames Wright sycl::event e = sycl_data->sycl_queue.ext_oneapi_submit_barrier(); 1172bd882c8aSJames Wright sycl_data->sycl_queue.copy<CeedScalar>(grad_out, &asmb->d_B_out[mat_start], dim * esize * nqpts, {e}); 1173bd882c8aSJames Wright mat_start += dim * esize * nqpts; 1174bd882c8aSJames Wright } 1175bd882c8aSJames Wright } 1176bd882c8aSJames Wright return CEED_ERROR_SUCCESS; 1177bd882c8aSJames Wright } 1178bd882c8aSJames Wright 1179bd882c8aSJames Wright //------------------------------------------------------------------------------ 1180bd882c8aSJames Wright // Matrix assembly kernel for low-order elements (3D thread block) 1181bd882c8aSJames Wright //------------------------------------------------------------------------------ 1182bd882c8aSJames Wright static int CeedOperatorLinearAssemble_Sycl(sycl::queue &sycl_queue, const CeedOperator_Sycl *impl, const CeedScalar *qf_array, 1183bd882c8aSJames Wright CeedScalar *values_array) { 1184bd882c8aSJames Wright // This kernels assumes B_in and B_out have the same number of quadrature points and basis points. 1185bd882c8aSJames Wright // TODO: expand to more general cases 1186bd882c8aSJames Wright CeedOperatorAssemble_Sycl *asmb = impl->asmb; 1187bd882c8aSJames Wright const CeedInt nelem = asmb->nelem; 11886ca0f394SUmesh Unnikrishnan const CeedSize nnodes = asmb->nnodes; 11896ca0f394SUmesh Unnikrishnan const CeedSize ncomp = asmb->ncomp; 11906ca0f394SUmesh Unnikrishnan const CeedSize nqpts = asmb->nqpts; 11916ca0f394SUmesh Unnikrishnan const CeedSize numemodein = asmb->numemodein; 11926ca0f394SUmesh Unnikrishnan const CeedSize numemodeout = asmb->numemodeout; 1193bd882c8aSJames Wright 1194bd882c8aSJames Wright // Strides for final output ordering, determined by the reference (inference) implementation of the symbolic assembly, slowest --> fastest: element, 1195bd882c8aSJames Wright // comp_in, comp_out, node_row, node_col 11966ca0f394SUmesh Unnikrishnan const CeedSize comp_out_stride = nnodes * nnodes; 11976ca0f394SUmesh Unnikrishnan const CeedSize comp_in_stride = comp_out_stride * ncomp; 11986ca0f394SUmesh Unnikrishnan const CeedSize e_stride = comp_in_stride * ncomp; 1199bd882c8aSJames Wright // Strides for QF array, slowest --> fastest: emode_in, comp_in, emode_out, comp_out, elem, qpt 12006ca0f394SUmesh Unnikrishnan const CeedSize qe_stride = nqpts; 12016ca0f394SUmesh Unnikrishnan const CeedSize qcomp_out_stride = nelem * qe_stride; 12026ca0f394SUmesh Unnikrishnan const CeedSize qemode_out_stride = qcomp_out_stride * ncomp; 12036ca0f394SUmesh Unnikrishnan const CeedSize qcomp_in_stride = qemode_out_stride * numemodeout; 12046ca0f394SUmesh Unnikrishnan const CeedSize qemode_in_stride = qcomp_in_stride * ncomp; 1205bd882c8aSJames Wright 1206bd882c8aSJames Wright CeedScalar *B_in, *B_out; 1207bd882c8aSJames Wright B_in = asmb->d_B_in; 1208bd882c8aSJames Wright B_out = asmb->d_B_out; 1209bd882c8aSJames Wright const CeedInt block_size_x = asmb->block_size_x; 1210bd882c8aSJames Wright const CeedInt block_size_y = asmb->block_size_y; 1211bd882c8aSJames Wright 1212bd882c8aSJames Wright sycl::range<3> kernel_range(nelem, block_size_y, block_size_x); 1213bd882c8aSJames Wright 1214bd882c8aSJames Wright // Order queue 1215bd882c8aSJames Wright sycl::event e = sycl_queue.ext_oneapi_submit_barrier(); 1216bd882c8aSJames Wright sycl_queue.parallel_for<CeedOperatorSyclLinearAssemble>(kernel_range, {e}, [=](sycl::id<3> idx) { 1217bd882c8aSJames Wright const int e = idx.get(0); // Element index 1218bd882c8aSJames Wright const int l = idx.get(1); // The output column index of each B^TDB operation 1219bd882c8aSJames Wright const int i = idx.get(2); // The output row index of each B^TDB operation 1220bd882c8aSJames Wright // such that we have (Bout^T)_ij D_jk Bin_kl = C_il 12216ca0f394SUmesh Unnikrishnan for (CeedSize comp_in = 0; comp_in < ncomp; comp_in++) { 12226ca0f394SUmesh Unnikrishnan for (CeedSize comp_out = 0; comp_out < ncomp; comp_out++) { 1223bd882c8aSJames Wright CeedScalar result = 0.0; 12246ca0f394SUmesh Unnikrishnan CeedSize qf_index_comp = qcomp_in_stride * comp_in + qcomp_out_stride * comp_out + qe_stride * e; 12256ca0f394SUmesh Unnikrishnan for (CeedSize emode_in = 0; emode_in < numemodein; emode_in++) { 12266ca0f394SUmesh Unnikrishnan CeedSize b_in_index = emode_in * nqpts * nnodes; 12276ca0f394SUmesh Unnikrishnan for (CeedSize emode_out = 0; emode_out < numemodeout; emode_out++) { 12286ca0f394SUmesh Unnikrishnan CeedSize b_out_index = emode_out * nqpts * nnodes; 12296ca0f394SUmesh Unnikrishnan CeedSize qf_index = qf_index_comp + qemode_out_stride * emode_out + qemode_in_stride * emode_in; 1230bd882c8aSJames Wright // Perform the B^T D B operation for this 'chunk' of D (the qf_array) 12316ca0f394SUmesh Unnikrishnan for (CeedSize j = 0; j < nqpts; j++) { 1232bd882c8aSJames Wright result += B_out[b_out_index + j * nnodes + i] * qf_array[qf_index + j] * B_in[b_in_index + j * nnodes + l]; 1233bd882c8aSJames Wright } 1234bd882c8aSJames Wright } // end of emode_out 1235bd882c8aSJames Wright } // end of emode_in 12366ca0f394SUmesh Unnikrishnan CeedSize val_index = comp_in_stride * comp_in + comp_out_stride * comp_out + e_stride * e + nnodes * i + l; 1237bd882c8aSJames Wright values_array[val_index] = result; 1238bd882c8aSJames Wright } // end of out component 1239bd882c8aSJames Wright } // end of in component 1240bd882c8aSJames Wright }); 1241bd882c8aSJames Wright 1242bd882c8aSJames Wright return CEED_ERROR_SUCCESS; 1243bd882c8aSJames Wright } 1244bd882c8aSJames Wright 1245bd882c8aSJames Wright //------------------------------------------------------------------------------ 1246bd882c8aSJames Wright // Fallback kernel for larger orders (1D thread block) 1247bd882c8aSJames Wright //------------------------------------------------------------------------------ 1248bd882c8aSJames Wright /* 1249bd882c8aSJames Wright static int CeedOperatorLinearAssembleFallback_Sycl(sycl::queue &sycl_queue, const CeedOperator_Sycl *impl, const CeedScalar *qf_array, 1250bd882c8aSJames Wright CeedScalar *values_array) { 1251bd882c8aSJames Wright // This kernel assumes B_in and B_out have the same number of quadrature points and basis points. 1252bd882c8aSJames Wright // TODO: expand to more general cases 1253bd882c8aSJames Wright CeedOperatorAssemble_Sycl *asmb = impl->asmb; 1254bd882c8aSJames Wright const CeedInt nelem = asmb->nelem; 1255bd882c8aSJames Wright const CeedInt nnodes = asmb->nnodes; 1256bd882c8aSJames Wright const CeedInt ncomp = asmb->ncomp; 1257bd882c8aSJames Wright const CeedInt nqpts = asmb->nqpts; 1258bd882c8aSJames Wright const CeedInt numemodein = asmb->numemodein; 1259bd882c8aSJames Wright const CeedInt numemodeout = asmb->numemodeout; 1260bd882c8aSJames Wright 1261bd882c8aSJames Wright // Strides for final output ordering, determined by the reference (interface) implementation of the symbolic assembly, slowest --> fastest: elememt, 1262bd882c8aSJames Wright // comp_in, comp_out, node_row, node_col 1263bd882c8aSJames Wright const CeedInt comp_out_stride = nnodes * nnodes; 1264bd882c8aSJames Wright const CeedInt comp_in_stride = comp_out_stride * ncomp; 1265bd882c8aSJames Wright const CeedInt e_stride = comp_in_stride * ncomp; 1266bd882c8aSJames Wright // Strides for QF array, slowest --> fastest: emode_in, comp_in, emode_out, comp_out, elem, qpt 1267bd882c8aSJames Wright const CeedInt qe_stride = nqpts; 1268bd882c8aSJames Wright const CeedInt qcomp_out_stride = nelem * qe_stride; 1269bd882c8aSJames Wright const CeedInt qemode_out_stride = qcomp_out_stride * ncomp; 1270bd882c8aSJames Wright const CeedInt qcomp_in_stride = qemode_out_stride * numemodeout; 1271bd882c8aSJames Wright const CeedInt qemode_in_stride = qcomp_in_stride * ncomp; 1272bd882c8aSJames Wright 1273bd882c8aSJames Wright CeedScalar *B_in, *B_out; 1274bd882c8aSJames Wright B_in = asmb->d_B_in; 1275bd882c8aSJames Wright B_out = asmb->d_B_out; 1276bd882c8aSJames Wright const CeedInt elemsPerBlock = asmb->elemsPerBlock; 1277bd882c8aSJames Wright const CeedInt block_size_x = asmb->block_size_x; 1278bd882c8aSJames Wright const CeedInt block_size_y = asmb->block_size_y; // This will be 1 for the fallback kernel 1279bd882c8aSJames Wright 1280bd882c8aSJames Wright const CeedInt grid = nelem / elemsPerBlock + ((nelem / elemsPerBlock * elemsPerBlock < nelem) ? 1 : 0); 1281bd882c8aSJames Wright sycl::range<3> local_range(block_size_x, block_size_y, elemsPerBlock); 1282bd882c8aSJames Wright sycl::range<3> global_range(grid * block_size_x, block_size_y, elemsPerBlock); 1283bd882c8aSJames Wright sycl::nd_range<3> kernel_range(global_range, local_range); 1284bd882c8aSJames Wright 1285bd882c8aSJames Wright sycl_queue.parallel_for<CeedOperatorSyclLinearAssembleFallback>(kernel_range, [=](sycl::nd_item<3> work_item) { 1286bd882c8aSJames Wright const CeedInt blockIdx = work_item.get_group(0); 1287bd882c8aSJames Wright const CeedInt gridDimx = work_item.get_group_range(0); 1288bd882c8aSJames Wright const CeedInt threadIdx = work_item.get_local_id(0); 1289bd882c8aSJames Wright const CeedInt threadIdz = work_item.get_local_id(2); 1290bd882c8aSJames Wright const CeedInt blockDimz = work_item.get_local_range(2); 1291bd882c8aSJames Wright 1292bd882c8aSJames Wright const int l = threadIdx; // The output column index of each B^TDB operation 1293bd882c8aSJames Wright // such that we have (Bout^T)_ij D_jk Bin_kl = C_il 1294bd882c8aSJames Wright for (CeedInt e = blockIdx * blockDimz + threadIdz; e < nelem; e += gridDimx * blockDimz) { 1295bd882c8aSJames Wright for (CeedInt comp_in = 0; comp_in < ncomp; comp_in++) { 1296bd882c8aSJames Wright for (CeedInt comp_out = 0; comp_out < ncomp; comp_out++) { 1297bd882c8aSJames Wright for (CeedInt i = 0; i < nnodes; i++) { 1298bd882c8aSJames Wright CeedScalar result = 0.0; 1299bd882c8aSJames Wright CeedInt qf_index_comp = qcomp_in_stride * comp_in + qcomp_out_stride * comp_out + qe_stride * e; 1300bd882c8aSJames Wright for (CeedInt emode_in = 0; emode_in < numemodein; emode_in++) { 1301bd882c8aSJames Wright CeedInt b_in_index = emode_in * nqpts * nnodes; 1302bd882c8aSJames Wright for (CeedInt emode_out = 0; emode_out < numemodeout; emode_out++) { 1303bd882c8aSJames Wright CeedInt b_out_index = emode_out * nqpts * nnodes; 1304bd882c8aSJames Wright CeedInt qf_index = qf_index_comp + qemode_out_stride * emode_out + qemode_in_stride * emode_in; 1305bd882c8aSJames Wright // Perform the B^T D B operation for this 'chunk' of D (the qf_array) 1306bd882c8aSJames Wright for (CeedInt j = 0; j < nqpts; j++) { 1307bd882c8aSJames Wright result += B_out[b_out_index + j * nnodes + i] * qf_array[qf_index + j] * B_in[b_in_index + j * nnodes + l]; 1308bd882c8aSJames Wright } 1309bd882c8aSJames Wright } // end of emode_out 1310bd882c8aSJames Wright } // end of emode_in 1311bd882c8aSJames Wright CeedInt val_index = comp_in_stride * comp_in + comp_out_stride * comp_out + e_stride * e + nnodes * i + l; 1312bd882c8aSJames Wright values_array[val_index] = result; 1313bd882c8aSJames Wright } // end of loop over element node index, i 1314bd882c8aSJames Wright } // end of out component 1315bd882c8aSJames Wright } // end of in component 1316bd882c8aSJames Wright } // end of element loop 1317bd882c8aSJames Wright }); 1318bd882c8aSJames Wright return CEED_ERROR_SUCCESS; 1319bd882c8aSJames Wright }*/ 1320bd882c8aSJames Wright 1321bd882c8aSJames Wright //------------------------------------------------------------------------------ 1322bd882c8aSJames Wright // Assemble matrix data for COO matrix of assembled operator. 1323bd882c8aSJames Wright // The sparsity pattern is set by CeedOperatorLinearAssembleSymbolic. 1324bd882c8aSJames Wright // 1325bd882c8aSJames Wright // Note that this (and other assembly routines) currently assume only one active 1326bd882c8aSJames Wright // input restriction/basis per operator (could have multiple basis eval modes). 1327bd882c8aSJames Wright // TODO: allow multiple active input restrictions/basis objects 1328bd882c8aSJames Wright //------------------------------------------------------------------------------ 1329bd882c8aSJames Wright static int CeedSingleOperatorAssemble_Sycl(CeedOperator op, CeedInt offset, CeedVector values) { 1330bd882c8aSJames Wright Ceed ceed; 1331bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetCeed(op, &ceed)); 1332bd882c8aSJames Wright CeedOperator_Sycl *impl; 1333bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetData(op, &impl)); 1334bd882c8aSJames Wright Ceed_Sycl *sycl_data; 1335bd882c8aSJames Wright CeedCallBackend(CeedGetData(ceed, &sycl_data)); 1336bd882c8aSJames Wright 1337bd882c8aSJames Wright // Setup 1338bd882c8aSJames Wright if (!impl->asmb) { 1339bd882c8aSJames Wright CeedCallBackend(CeedSingleOperatorAssembleSetup_Sycl(op)); 1340bd882c8aSJames Wright assert(impl->asmb != NULL); 1341bd882c8aSJames Wright } 1342bd882c8aSJames Wright 1343bd882c8aSJames Wright // Assemble QFunction 1344bd882c8aSJames Wright CeedVector assembled_qf = NULL; 1345bd882c8aSJames Wright CeedElemRestriction rstr_q = NULL; 1346bd882c8aSJames Wright CeedCallBackend(CeedOperatorLinearAssembleQFunctionBuildOrUpdate(op, &assembled_qf, &rstr_q, CEED_REQUEST_IMMEDIATE)); 1347bd882c8aSJames Wright CeedCallBackend(CeedElemRestrictionDestroy(&rstr_q)); 1348bd882c8aSJames Wright CeedScalar *values_array; 1349bd882c8aSJames Wright CeedCallBackend(CeedVectorGetArrayWrite(values, CEED_MEM_DEVICE, &values_array)); 1350bd882c8aSJames Wright values_array += offset; 1351bd882c8aSJames Wright const CeedScalar *qf_array; 1352bd882c8aSJames Wright CeedCallBackend(CeedVectorGetArrayRead(assembled_qf, CEED_MEM_DEVICE, &qf_array)); 1353bd882c8aSJames Wright 1354bd882c8aSJames Wright // Compute B^T D B 1355bd882c8aSJames Wright CeedCallBackend(CeedOperatorLinearAssemble_Sycl(sycl_data->sycl_queue, impl, qf_array, values_array)); 1356bd882c8aSJames Wright 1357bd882c8aSJames Wright // Wait for kernels to be completed 1358bd882c8aSJames Wright // Kris: Review if this is necessary -- enqueing an async barrier may be sufficient 1359bd882c8aSJames Wright sycl_data->sycl_queue.wait_and_throw(); 1360bd882c8aSJames Wright 1361bd882c8aSJames Wright // Restore arrays 1362bd882c8aSJames Wright CeedCallBackend(CeedVectorRestoreArray(values, &values_array)); 1363bd882c8aSJames Wright CeedCallBackend(CeedVectorRestoreArrayRead(assembled_qf, &qf_array)); 1364bd882c8aSJames Wright 1365bd882c8aSJames Wright // Cleanup 1366bd882c8aSJames Wright CeedCallBackend(CeedVectorDestroy(&assembled_qf)); 1367bd882c8aSJames Wright 1368bd882c8aSJames Wright return CEED_ERROR_SUCCESS; 1369bd882c8aSJames Wright } 1370bd882c8aSJames Wright 1371bd882c8aSJames Wright //------------------------------------------------------------------------------ 1372bd882c8aSJames Wright // Create operator 1373bd882c8aSJames Wright //------------------------------------------------------------------------------ 1374bd882c8aSJames Wright int CeedOperatorCreate_Sycl(CeedOperator op) { 1375bd882c8aSJames Wright Ceed ceed; 1376bd882c8aSJames Wright CeedCallBackend(CeedOperatorGetCeed(op, &ceed)); 1377bd882c8aSJames Wright CeedOperator_Sycl *impl; 1378bd882c8aSJames Wright 1379bd882c8aSJames Wright CeedCallBackend(CeedCalloc(1, &impl)); 1380bd882c8aSJames Wright CeedCallBackend(CeedOperatorSetData(op, impl)); 1381bd882c8aSJames Wright 1382bd882c8aSJames Wright CeedCallBackend(CeedSetBackendFunctionCpp(ceed, "Operator", op, "LinearAssembleQFunction", CeedOperatorLinearAssembleQFunction_Sycl)); 1383bd882c8aSJames Wright CeedCallBackend(CeedSetBackendFunctionCpp(ceed, "Operator", op, "LinearAssembleQFunctionUpdate", CeedOperatorLinearAssembleQFunctionUpdate_Sycl)); 1384bd882c8aSJames Wright CeedCallBackend(CeedSetBackendFunctionCpp(ceed, "Operator", op, "LinearAssembleAddDiagonal", CeedOperatorLinearAssembleAddDiagonal_Sycl)); 1385bd882c8aSJames Wright CeedCallBackend( 1386bd882c8aSJames Wright CeedSetBackendFunctionCpp(ceed, "Operator", op, "LinearAssembleAddPointBlockDiagonal", CeedOperatorLinearAssembleAddPointBlockDiagonal_Sycl)); 1387bd882c8aSJames Wright CeedCallBackend(CeedSetBackendFunctionCpp(ceed, "Operator", op, "LinearAssembleSingle", CeedSingleOperatorAssemble_Sycl)); 1388bd882c8aSJames Wright CeedCallBackend(CeedSetBackendFunctionCpp(ceed, "Operator", op, "ApplyAdd", CeedOperatorApplyAdd_Sycl)); 1389bd882c8aSJames Wright CeedCallBackend(CeedSetBackendFunctionCpp(ceed, "Operator", op, "Destroy", CeedOperatorDestroy_Sycl)); 1390bd882c8aSJames Wright return CEED_ERROR_SUCCESS; 1391bd882c8aSJames Wright } 1392bd882c8aSJames Wright 1393bd882c8aSJames Wright //------------------------------------------------------------------------------ 1394