1ae3cba82Scamierjs // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at 2ae3cba82Scamierjs // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights 3ae3cba82Scamierjs // reserved. See files LICENSE and NOTICE for details. 4ae3cba82Scamierjs // 5ae3cba82Scamierjs // This file is part of CEED, a collection of benchmarks, miniapps, software 6ae3cba82Scamierjs // libraries and APIs for efficient high-order finite element and spectral 7ae3cba82Scamierjs // element discretizations for exascale applications. For more information and 8ae3cba82Scamierjs // source code availability see http://github.com/ceed. 9ae3cba82Scamierjs // 10ae3cba82Scamierjs // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 11ae3cba82Scamierjs // a collaborative effort of two U.S. Department of Energy organizations (Office 12ae3cba82Scamierjs // of Science and the National Nuclear Security Administration) responsible for 13ae3cba82Scamierjs // the planning and preparation of a capable exascale ecosystem, including 14ae3cba82Scamierjs // software, applications, hardware, advanced system engineering and early 15ae3cba82Scamierjs // testbed platforms, in support of the nation's exascale computing imperative. 16ae3cba82Scamierjs 17ae3cba82Scamierjs #include <ceed-impl.h> 18ae3cba82Scamierjs #include <string.h> 19ae3cba82Scamierjs 20ae3cba82Scamierjs typedef struct { 21ae3cba82Scamierjs CeedScalar *array; 22ae3cba82Scamierjs CeedScalar *array_allocated; 23ae3cba82Scamierjs } CeedVector_Ref; 24ae3cba82Scamierjs 25ae3cba82Scamierjs typedef struct { 26ae3cba82Scamierjs const CeedInt *indices; 27ae3cba82Scamierjs CeedInt *indices_allocated; 28ae3cba82Scamierjs } CeedElemRestriction_Ref; 29ae3cba82Scamierjs 30ae3cba82Scamierjs typedef struct { 31ae3cba82Scamierjs CeedVector etmp; 32ae3cba82Scamierjs CeedVector qdata; 33ae3cba82Scamierjs } CeedOperator_Ref; 34ae3cba82Scamierjs 35ae3cba82Scamierjs static int CeedVectorSetArray_Ref(CeedVector vec, CeedMemType mtype, 36ae3cba82Scamierjs CeedCopyMode cmode, CeedScalar *array) { 37ae3cba82Scamierjs CeedVector_Ref *impl = vec->data; 38ae3cba82Scamierjs int ierr; 39ae3cba82Scamierjs 40ae3cba82Scamierjs if (mtype != CEED_MEM_HOST) 41ae3cba82Scamierjs return CeedError(vec->ceed, 1, "Only MemType = HOST supported"); 42ae3cba82Scamierjs ierr = CeedFree(&impl->array_allocated); CeedChk(ierr); 43ae3cba82Scamierjs switch (cmode) { 44ae3cba82Scamierjs case CEED_COPY_VALUES: 45ae3cba82Scamierjs ierr = CeedMalloc(vec->length, &impl->array_allocated); CeedChk(ierr); 46ae3cba82Scamierjs impl->array = impl->array_allocated; 47ae3cba82Scamierjs if (array) memcpy(impl->array, array, vec->length * sizeof(array[0])); 48ae3cba82Scamierjs break; 49ae3cba82Scamierjs case CEED_OWN_POINTER: 50ae3cba82Scamierjs impl->array_allocated = array; 51ae3cba82Scamierjs impl->array = array; 52ae3cba82Scamierjs break; 53ae3cba82Scamierjs case CEED_USE_POINTER: 54ae3cba82Scamierjs impl->array = array; 55ae3cba82Scamierjs } 56ae3cba82Scamierjs return 0; 57ae3cba82Scamierjs } 58ae3cba82Scamierjs 59ae3cba82Scamierjs static int CeedVectorGetArray_Ref(CeedVector vec, CeedMemType mtype, 60ae3cba82Scamierjs CeedScalar **array) { 61ae3cba82Scamierjs CeedVector_Ref *impl = vec->data; 62ae3cba82Scamierjs int ierr; 63ae3cba82Scamierjs 64ae3cba82Scamierjs if (mtype != CEED_MEM_HOST) 65ae3cba82Scamierjs return CeedError(vec->ceed, 1, "Can only provide to HOST memory"); 66ae3cba82Scamierjs if (!impl->array) { // Allocate if array is not yet allocated 67ae3cba82Scamierjs ierr = CeedVectorSetArray(vec, CEED_MEM_HOST, CEED_COPY_VALUES, NULL); 68ae3cba82Scamierjs CeedChk(ierr); 69ae3cba82Scamierjs } 70ae3cba82Scamierjs *array = impl->array; 71ae3cba82Scamierjs return 0; 72ae3cba82Scamierjs } 73ae3cba82Scamierjs 74ae3cba82Scamierjs static int CeedVectorGetArrayRead_Ref(CeedVector vec, CeedMemType mtype, 75ae3cba82Scamierjs const CeedScalar **array) { 76ae3cba82Scamierjs CeedVector_Ref *impl = vec->data; 77ae3cba82Scamierjs int ierr; 78ae3cba82Scamierjs 79ae3cba82Scamierjs if (mtype != CEED_MEM_HOST) 80ae3cba82Scamierjs return CeedError(vec->ceed, 1, "Can only provide to HOST memory"); 81ae3cba82Scamierjs if (!impl->array) { // Allocate if array is not yet allocated 82ae3cba82Scamierjs ierr = CeedVectorSetArray(vec, CEED_MEM_HOST, CEED_COPY_VALUES, NULL); 83ae3cba82Scamierjs CeedChk(ierr); 84ae3cba82Scamierjs } 85ae3cba82Scamierjs *array = impl->array; 86ae3cba82Scamierjs return 0; 87ae3cba82Scamierjs } 88ae3cba82Scamierjs 89ae3cba82Scamierjs static int CeedVectorRestoreArray_Ref(CeedVector vec, CeedScalar **array) { 90ae3cba82Scamierjs *array = NULL; 91ae3cba82Scamierjs return 0; 92ae3cba82Scamierjs } 93ae3cba82Scamierjs 94ae3cba82Scamierjs static int CeedVectorRestoreArrayRead_Ref(CeedVector vec, 95ae3cba82Scamierjs const CeedScalar **array) { 96ae3cba82Scamierjs *array = NULL; 97ae3cba82Scamierjs return 0; 98ae3cba82Scamierjs } 99ae3cba82Scamierjs 100ae3cba82Scamierjs static int CeedVectorDestroy_Ref(CeedVector vec) { 101ae3cba82Scamierjs CeedVector_Ref *impl = vec->data; 102ae3cba82Scamierjs int ierr; 103ae3cba82Scamierjs 104ae3cba82Scamierjs ierr = CeedFree(&impl->array_allocated); CeedChk(ierr); 105ae3cba82Scamierjs ierr = CeedFree(&vec->data); CeedChk(ierr); 106ae3cba82Scamierjs return 0; 107ae3cba82Scamierjs } 108ae3cba82Scamierjs 109ae3cba82Scamierjs static int CeedVectorCreate_Ref(Ceed ceed, CeedInt n, CeedVector vec) { 110ae3cba82Scamierjs CeedVector_Ref *impl; 111ae3cba82Scamierjs int ierr; 112ae3cba82Scamierjs 113ae3cba82Scamierjs vec->SetArray = CeedVectorSetArray_Ref; 114ae3cba82Scamierjs vec->GetArray = CeedVectorGetArray_Ref; 115ae3cba82Scamierjs vec->GetArrayRead = CeedVectorGetArrayRead_Ref; 116ae3cba82Scamierjs vec->RestoreArray = CeedVectorRestoreArray_Ref; 117ae3cba82Scamierjs vec->RestoreArrayRead = CeedVectorRestoreArrayRead_Ref; 118ae3cba82Scamierjs vec->Destroy = CeedVectorDestroy_Ref; 119ae3cba82Scamierjs ierr = CeedCalloc(1,&impl); CeedChk(ierr); 120ae3cba82Scamierjs vec->data = impl; 121ae3cba82Scamierjs return 0; 122ae3cba82Scamierjs } 123ae3cba82Scamierjs 124ae3cba82Scamierjs static int CeedElemRestrictionApply_Ref(CeedElemRestriction r, 125ae3cba82Scamierjs CeedTransposeMode tmode, CeedVector u, 126ae3cba82Scamierjs CeedVector v, CeedRequest *request) { 127ae3cba82Scamierjs CeedElemRestriction_Ref *impl = r->data; 128ae3cba82Scamierjs int ierr; 129ae3cba82Scamierjs const CeedScalar *uu; 130ae3cba82Scamierjs CeedScalar *vv; 131ae3cba82Scamierjs 132ae3cba82Scamierjs ierr = CeedVectorGetArrayRead(u, CEED_MEM_HOST, &uu); CeedChk(ierr); 133ae3cba82Scamierjs ierr = CeedVectorGetArray(v, CEED_MEM_HOST, &vv); CeedChk(ierr); 134ae3cba82Scamierjs if (tmode == CEED_NOTRANSPOSE) { 135ae3cba82Scamierjs for (CeedInt i=0; i<r->nelem*r->elemsize; i++) vv[i] = uu[impl->indices[i]]; 136ae3cba82Scamierjs } else { 137ae3cba82Scamierjs for (CeedInt i=0; i<r->nelem*r->elemsize; i++) vv[impl->indices[i]] += uu[i]; 138ae3cba82Scamierjs } 139ae3cba82Scamierjs ierr = CeedVectorRestoreArrayRead(u, &uu); CeedChk(ierr); 140ae3cba82Scamierjs ierr = CeedVectorRestoreArray(v, &vv); CeedChk(ierr); 141ae3cba82Scamierjs if (request != CEED_REQUEST_IMMEDIATE) *request = NULL; 142ae3cba82Scamierjs return 0; 143ae3cba82Scamierjs } 144ae3cba82Scamierjs 145ae3cba82Scamierjs static int CeedElemRestrictionDestroy_Ref(CeedElemRestriction r) { 146ae3cba82Scamierjs CeedElemRestriction_Ref *impl = r->data; 147ae3cba82Scamierjs int ierr; 148ae3cba82Scamierjs 149ae3cba82Scamierjs ierr = CeedFree(&impl->indices_allocated); CeedChk(ierr); 150ae3cba82Scamierjs ierr = CeedFree(&r->data); CeedChk(ierr); 151ae3cba82Scamierjs return 0; 152ae3cba82Scamierjs } 153ae3cba82Scamierjs 154ae3cba82Scamierjs static int CeedElemRestrictionCreate_Ref(CeedElemRestriction r, 155ae3cba82Scamierjs CeedMemType mtype, 156ae3cba82Scamierjs CeedCopyMode cmode, const CeedInt *indices) { 157ae3cba82Scamierjs int ierr; 158ae3cba82Scamierjs CeedElemRestriction_Ref *impl; 159ae3cba82Scamierjs 160ae3cba82Scamierjs if (mtype != CEED_MEM_HOST) 161ae3cba82Scamierjs return CeedError(r->ceed, 1, "Only MemType = HOST supported"); 162ae3cba82Scamierjs ierr = CeedCalloc(1,&impl); CeedChk(ierr); 163ae3cba82Scamierjs switch (cmode) { 164ae3cba82Scamierjs case CEED_COPY_VALUES: 165ae3cba82Scamierjs ierr = CeedMalloc(r->nelem*r->elemsize, &impl->indices_allocated); 166ae3cba82Scamierjs CeedChk(ierr); 167ae3cba82Scamierjs memcpy(impl->indices_allocated, indices, 168ae3cba82Scamierjs r->nelem * r->elemsize * sizeof(indices[0])); 169ae3cba82Scamierjs impl->indices = impl->indices_allocated; 170ae3cba82Scamierjs break; 171ae3cba82Scamierjs case CEED_OWN_POINTER: 172ae3cba82Scamierjs impl->indices_allocated = (CeedInt*)indices; 173ae3cba82Scamierjs impl->indices = impl->indices_allocated; 174ae3cba82Scamierjs break; 175ae3cba82Scamierjs case CEED_USE_POINTER: 176ae3cba82Scamierjs impl->indices = indices; 177ae3cba82Scamierjs } 178ae3cba82Scamierjs r->data = impl; 179ae3cba82Scamierjs r->Apply = CeedElemRestrictionApply_Ref; 180ae3cba82Scamierjs r->Destroy = CeedElemRestrictionDestroy_Ref; 181ae3cba82Scamierjs return 0; 182ae3cba82Scamierjs } 183ae3cba82Scamierjs 184ae3cba82Scamierjs // Contracts on the middle index 185ae3cba82Scamierjs // NOTRANSPOSE: V_ajc = T_jb U_abc 186ae3cba82Scamierjs // TRANSPOSE: V_ajc = T_bj U_abc 187ae3cba82Scamierjs static int CeedTensorContract_Ref(Ceed ceed, 188ae3cba82Scamierjs CeedInt A, CeedInt B, CeedInt C, CeedInt J, 189ae3cba82Scamierjs const CeedScalar *t, CeedTransposeMode tmode, 190ae3cba82Scamierjs const CeedScalar *u, CeedScalar *v) { 191ae3cba82Scamierjs CeedInt tstride0 = B, tstride1 = 1; 192ae3cba82Scamierjs if (tmode == CEED_TRANSPOSE) { 193ae3cba82Scamierjs tstride0 = 1; tstride1 = J; 194ae3cba82Scamierjs } 195ae3cba82Scamierjs 196ae3cba82Scamierjs for (CeedInt a=0; a<A; a++) { 197ae3cba82Scamierjs for (CeedInt j=0; j<J; j++) { 198ae3cba82Scamierjs for (CeedInt c=0; c<C; c++) 199ae3cba82Scamierjs v[(a*J+j)*C+c] = 0; 200ae3cba82Scamierjs for (CeedInt b=0; b<B; b++) { 201ae3cba82Scamierjs for (CeedInt c=0; c<C; c++) { 202ae3cba82Scamierjs v[(a*J+j)*C+c] += t[j*tstride0 + b*tstride1] * u[(a*B+b)*C+c]; 203ae3cba82Scamierjs } 204ae3cba82Scamierjs } 205ae3cba82Scamierjs } 206ae3cba82Scamierjs } 207ae3cba82Scamierjs return 0; 208ae3cba82Scamierjs } 209ae3cba82Scamierjs 210ae3cba82Scamierjs static int CeedBasisApply_Ref(CeedBasis basis, CeedTransposeMode tmode, 211ae3cba82Scamierjs CeedEvalMode emode, 212ae3cba82Scamierjs const CeedScalar *u, CeedScalar *v) { 213ae3cba82Scamierjs int ierr; 214ae3cba82Scamierjs const CeedInt dim = basis->dim; 215ae3cba82Scamierjs const CeedInt ndof = basis->ndof; 216ae3cba82Scamierjs 217ae3cba82Scamierjs switch (emode) { 218ae3cba82Scamierjs case CEED_EVAL_NONE: break; 219ae3cba82Scamierjs case CEED_EVAL_INTERP: { 220ae3cba82Scamierjs CeedInt P = basis->P1d, Q = basis->Q1d; 221ae3cba82Scamierjs if (tmode == CEED_TRANSPOSE) { 222ae3cba82Scamierjs P = basis->Q1d; Q = basis->P1d; 223ae3cba82Scamierjs } 224ae3cba82Scamierjs CeedInt pre = ndof*CeedPowInt(P, dim-1), post = 1; 225ae3cba82Scamierjs CeedScalar tmp[2][Q*CeedPowInt(P>Q?P:Q, dim-1)]; 226ae3cba82Scamierjs for (CeedInt d=0; d<dim; d++) { 227ae3cba82Scamierjs ierr = CeedTensorContract_Ref(basis->ceed, pre, P, post, Q, basis->interp1d, 228ae3cba82Scamierjs tmode, 229ae3cba82Scamierjs d==0?u:tmp[d%2], d==dim-1?v:tmp[(d+1)%2]); CeedChk(ierr); 230ae3cba82Scamierjs pre /= P; 231ae3cba82Scamierjs post *= Q; 232ae3cba82Scamierjs } 233ae3cba82Scamierjs } break; 234ae3cba82Scamierjs case CEED_EVAL_WEIGHT: { 235ae3cba82Scamierjs if (tmode == CEED_TRANSPOSE) 236ae3cba82Scamierjs return CeedError(basis->ceed, 1, "CEED_EVAL_WEIGHT incompatible with CEED_TRANSPOSE"); 237ae3cba82Scamierjs CeedInt Q = basis->Q1d; 238ae3cba82Scamierjs for (CeedInt d=0; d<dim; d++) { 239ae3cba82Scamierjs CeedInt pre = CeedPowInt(Q, dim-d-1), post = CeedPowInt(Q, d); 240ae3cba82Scamierjs for (CeedInt i=0; i<pre; i++) { 241ae3cba82Scamierjs for (CeedInt j=0; j<Q; j++) { 242ae3cba82Scamierjs for (CeedInt k=0; k<post; k++) { 243ae3cba82Scamierjs v[(i*Q + j)*post + k] = basis->qweight1d[j] 244ae3cba82Scamierjs * (d == 0 ? 1 : v[(i*Q + j)*post + k]); 245ae3cba82Scamierjs } 246ae3cba82Scamierjs } 247ae3cba82Scamierjs } 248ae3cba82Scamierjs } 249ae3cba82Scamierjs } break; 250ae3cba82Scamierjs default: 251ae3cba82Scamierjs return CeedError(basis->ceed, 1, "EvalMode %d not supported", emode); 252ae3cba82Scamierjs } 253ae3cba82Scamierjs return 0; 254ae3cba82Scamierjs } 255ae3cba82Scamierjs 256ae3cba82Scamierjs static int CeedBasisDestroy_Ref(CeedBasis basis) { 257ae3cba82Scamierjs return 0; 258ae3cba82Scamierjs } 259ae3cba82Scamierjs 260ae3cba82Scamierjs static int CeedBasisCreateTensorH1_Ref(Ceed ceed, CeedInt dim, CeedInt P1d, 261ae3cba82Scamierjs CeedInt Q1d, const CeedScalar *interp1d, 262ae3cba82Scamierjs const CeedScalar *grad1d, 263ae3cba82Scamierjs const CeedScalar *qref1d, 264ae3cba82Scamierjs const CeedScalar *qweight1d, 265ae3cba82Scamierjs CeedBasis basis) { 266ae3cba82Scamierjs basis->Apply = CeedBasisApply_Ref; 267ae3cba82Scamierjs basis->Destroy = CeedBasisDestroy_Ref; 268ae3cba82Scamierjs return 0; 269ae3cba82Scamierjs } 270ae3cba82Scamierjs 271ae3cba82Scamierjs static int CeedQFunctionApply_Ref(CeedQFunction qf, void *qdata, CeedInt Q, 272ae3cba82Scamierjs const CeedScalar *const *u, 273ae3cba82Scamierjs CeedScalar *const *v) { 274ae3cba82Scamierjs int ierr; 275ae3cba82Scamierjs ierr = qf->function(qf->ctx, qdata, Q, u, v); CeedChk(ierr); 276ae3cba82Scamierjs return 0; 277ae3cba82Scamierjs } 278ae3cba82Scamierjs 279ae3cba82Scamierjs static int CeedQFunctionDestroy_Ref(CeedQFunction qf) { 280ae3cba82Scamierjs return 0; 281ae3cba82Scamierjs } 282ae3cba82Scamierjs 283ae3cba82Scamierjs static int CeedQFunctionCreate_Ref(CeedQFunction qf) { 284ae3cba82Scamierjs qf->Apply = CeedQFunctionApply_Ref; 285ae3cba82Scamierjs qf->Destroy = CeedQFunctionDestroy_Ref; 286ae3cba82Scamierjs return 0; 287ae3cba82Scamierjs } 288ae3cba82Scamierjs 289ae3cba82Scamierjs static int CeedOperatorDestroy_Ref(CeedOperator op) { 290ae3cba82Scamierjs CeedOperator_Ref *impl = op->data; 291ae3cba82Scamierjs int ierr; 292ae3cba82Scamierjs 293ae3cba82Scamierjs ierr = CeedVectorDestroy(&impl->etmp); CeedChk(ierr); 294ae3cba82Scamierjs ierr = CeedVectorDestroy(&impl->qdata); CeedChk(ierr); 295ae3cba82Scamierjs ierr = CeedFree(&op->data); CeedChk(ierr); 296ae3cba82Scamierjs return 0; 297ae3cba82Scamierjs } 298ae3cba82Scamierjs 299ae3cba82Scamierjs static int CeedOperatorApply_Ref(CeedOperator op, CeedVector qdata, 300ae3cba82Scamierjs CeedVector ustate, 301ae3cba82Scamierjs CeedVector residual, CeedRequest *request) { 302ae3cba82Scamierjs CeedOperator_Ref *impl = op->data; 303ae3cba82Scamierjs CeedVector etmp; 304ae3cba82Scamierjs CeedInt Q; 305ae3cba82Scamierjs CeedScalar *Eu; 306ae3cba82Scamierjs char *qd; 307ae3cba82Scamierjs int ierr; 308ae3cba82Scamierjs 309ae3cba82Scamierjs if (!impl->etmp) { 310ae3cba82Scamierjs ierr = CeedVectorCreate(op->ceed, 311ae3cba82Scamierjs op->Erestrict->nelem * op->Erestrict->elemsize, 312ae3cba82Scamierjs &impl->etmp); CeedChk(ierr); 313ae3cba82Scamierjs } 314ae3cba82Scamierjs etmp = impl->etmp; 315ae3cba82Scamierjs if (op->qf->inmode != CEED_EVAL_NONE || op->qf->inmode != CEED_EVAL_WEIGHT) { 316ae3cba82Scamierjs ierr = CeedElemRestrictionApply(op->Erestrict, CEED_NOTRANSPOSE, ustate, etmp, 317ae3cba82Scamierjs CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 318ae3cba82Scamierjs } 319ae3cba82Scamierjs ierr = CeedBasisGetNumQuadraturePoints(op->basis, &Q); CeedChk(ierr); 320ae3cba82Scamierjs ierr = CeedVectorGetArray(etmp, CEED_MEM_HOST, &Eu); CeedChk(ierr); 321ae3cba82Scamierjs ierr = CeedVectorGetArray(qdata, CEED_MEM_HOST, (CeedScalar**)&qd); CeedChk(ierr); 322ae3cba82Scamierjs for (CeedInt e=0; e<op->Erestrict->nelem; e++) { 323ae3cba82Scamierjs CeedScalar BEu[Q], BEv[Q], *out[1]; 324ae3cba82Scamierjs const CeedScalar *in[1]; 325ae3cba82Scamierjs ierr = CeedBasisApply(op->basis, CEED_NOTRANSPOSE, op->qf->inmode, 326ae3cba82Scamierjs &Eu[e*op->Erestrict->elemsize], BEu); CeedChk(ierr); 327ae3cba82Scamierjs in[0] = BEu; 328ae3cba82Scamierjs out[0] = BEv; 329ae3cba82Scamierjs ierr = CeedQFunctionApply(op->qf, &qd[e*Q*op->qf->qdatasize], Q, in, out); 330ae3cba82Scamierjs CeedChk(ierr); 331ae3cba82Scamierjs ierr = CeedBasisApply(op->basis, CEED_TRANSPOSE, op->qf->outmode, BEv, 332ae3cba82Scamierjs &Eu[e*op->Erestrict->elemsize]); CeedChk(ierr); 333ae3cba82Scamierjs } 334ae3cba82Scamierjs ierr = CeedVectorRestoreArray(etmp, &Eu); CeedChk(ierr); 335ae3cba82Scamierjs if (residual) { 336ae3cba82Scamierjs ierr = CeedElemRestrictionApply(op->Erestrict, CEED_TRANSPOSE, etmp, residual, 337ae3cba82Scamierjs CEED_REQUEST_IMMEDIATE); CeedChk(ierr); 338ae3cba82Scamierjs } 339ae3cba82Scamierjs if (request != CEED_REQUEST_IMMEDIATE) *request = NULL; 340ae3cba82Scamierjs return 0; 341ae3cba82Scamierjs } 342ae3cba82Scamierjs 343ae3cba82Scamierjs static int CeedOperatorGetQData_Ref(CeedOperator op, CeedVector *qdata) { 344ae3cba82Scamierjs CeedOperator_Ref *impl = op->data; 345ae3cba82Scamierjs int ierr; 346ae3cba82Scamierjs 347ae3cba82Scamierjs if (!impl->qdata) { 348ae3cba82Scamierjs CeedInt Q; 349ae3cba82Scamierjs ierr = CeedBasisGetNumQuadraturePoints(op->basis, &Q); CeedChk(ierr); 350ae3cba82Scamierjs ierr = CeedVectorCreate(op->ceed, 351*0f253a1aSTzanio op->Erestrict->nelem * Q 352*0f253a1aSTzanio * op->qf->qdatasize / sizeof(CeedScalar), 353ae3cba82Scamierjs &impl->qdata); CeedChk(ierr); 354ae3cba82Scamierjs } 355ae3cba82Scamierjs *qdata = impl->qdata; 356ae3cba82Scamierjs return 0; 357ae3cba82Scamierjs } 358ae3cba82Scamierjs 359ae3cba82Scamierjs static int CeedOperatorCreate_Ref(CeedOperator op) { 360ae3cba82Scamierjs CeedOperator_Ref *impl; 361ae3cba82Scamierjs int ierr; 362ae3cba82Scamierjs 363ae3cba82Scamierjs ierr = CeedCalloc(1, &impl); CeedChk(ierr); 364ae3cba82Scamierjs op->data = impl; 365ae3cba82Scamierjs op->Destroy = CeedOperatorDestroy_Ref; 366ae3cba82Scamierjs op->Apply = CeedOperatorApply_Ref; 367ae3cba82Scamierjs op->GetQData = CeedOperatorGetQData_Ref; 368ae3cba82Scamierjs return 0; 369ae3cba82Scamierjs } 370ae3cba82Scamierjs 371ae3cba82Scamierjs static int CeedInit_Ref(const char *resource, Ceed ceed) { 372ae3cba82Scamierjs if (strcmp(resource, "/cpu/self") 373ae3cba82Scamierjs && strcmp(resource, "/cpu/self/ref")) 374ae3cba82Scamierjs return CeedError(ceed, 1, "Ref backend cannot use resource: %s", resource); 375ae3cba82Scamierjs ceed->VecCreate = CeedVectorCreate_Ref; 376ae3cba82Scamierjs ceed->BasisCreateTensorH1 = CeedBasisCreateTensorH1_Ref; 377ae3cba82Scamierjs ceed->ElemRestrictionCreate = CeedElemRestrictionCreate_Ref; 378ae3cba82Scamierjs ceed->QFunctionCreate = CeedQFunctionCreate_Ref; 379ae3cba82Scamierjs ceed->OperatorCreate = CeedOperatorCreate_Ref; 380ae3cba82Scamierjs return 0; 381ae3cba82Scamierjs } 382ae3cba82Scamierjs 383ae3cba82Scamierjs __attribute__((constructor)) 384ae3cba82Scamierjs static void Register(void) { 385ae3cba82Scamierjs CeedRegister("/cpu/self/ref", CeedInit_Ref); 386ae3cba82Scamierjs } 387