121617c04Sjeremylt // Copyright (c) 2017-2018, Lawrence Livermore National Security, LLC. 221617c04Sjeremylt // Produced at the Lawrence Livermore National Laboratory. LLNL-CODE-734707. 321617c04Sjeremylt // All Rights reserved. See files LICENSE and NOTICE for details. 421617c04Sjeremylt // 521617c04Sjeremylt // This file is part of CEED, a collection of benchmarks, miniapps, software 621617c04Sjeremylt // libraries and APIs for efficient high-order finite element and spectral 721617c04Sjeremylt // element discretizations for exascale applications. For more information and 821617c04Sjeremylt // source code availability see http://github.com/ceed. 921617c04Sjeremylt // 1021617c04Sjeremylt // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 1121617c04Sjeremylt // a collaborative effort of two U.S. Department of Energy organizations (Office 1221617c04Sjeremylt // of Science and the National Nuclear Security Administration) responsible for 1321617c04Sjeremylt // the planning and preparation of a capable exascale ecosystem, including 1421617c04Sjeremylt // software, applications, hardware, advanced system engineering and early 1521617c04Sjeremylt // testbed platforms, in support of the nation's exascale computing imperative. 1621617c04Sjeremylt 17ec3da8bcSJed Brown #include <ceed/ceed.h> 18ec3da8bcSJed Brown #include <ceed/backend.h> 193d576824SJeremy L Thompson #include <math.h> 203d576824SJeremy L Thompson #include <stdbool.h> 213d576824SJeremy L Thompson #include <stddef.h> 223d576824SJeremy L Thompson #include <stdint.h> 2321617c04Sjeremylt #include "ceed-ref.h" 2421617c04Sjeremylt 25f10650afSjeremylt //------------------------------------------------------------------------------ 26f10650afSjeremylt // Setup Input/Output Fields 27f10650afSjeremylt //------------------------------------------------------------------------------ 28fe2413ffSjeremylt static int CeedOperatorSetupFields_Ref(CeedQFunction qf, CeedOperator op, 2991703d3fSjeremylt bool inOrOut, 30*d1d35e2fSjeremylt CeedVector *full_evecs, CeedVector *e_vecs, 31*d1d35e2fSjeremylt CeedVector *q_vecs, CeedInt starte, 32*d1d35e2fSjeremylt CeedInt num_fields, CeedInt Q) { 334d537eeaSYohann CeedInt dim, ierr, size, P; 34aedaa0e5Sjeremylt Ceed ceed; 35e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChkBackend(ierr); 36d1bcdac9Sjeremylt CeedBasis basis; 37*d1d35e2fSjeremylt CeedElemRestriction elem_restr; 38*d1d35e2fSjeremylt CeedOperatorField *op_fields; 39*d1d35e2fSjeremylt CeedQFunctionField *qf_fields; 40fe2413ffSjeremylt if (inOrOut) { 41*d1d35e2fSjeremylt ierr = CeedOperatorGetFields(op, NULL, &op_fields); CeedChkBackend(ierr); 42*d1d35e2fSjeremylt ierr = CeedQFunctionGetFields(qf, NULL, &qf_fields); CeedChkBackend(ierr); 43fe2413ffSjeremylt } else { 44*d1d35e2fSjeremylt ierr = CeedOperatorGetFields(op, &op_fields, NULL); CeedChkBackend(ierr); 45*d1d35e2fSjeremylt ierr = CeedQFunctionGetFields(qf, &qf_fields, NULL); CeedChkBackend(ierr); 46fe2413ffSjeremylt } 4721617c04Sjeremylt 48885ac19cSjeremylt // Loop over fields 49*d1d35e2fSjeremylt for (CeedInt i=0; i<num_fields; i++) { 50*d1d35e2fSjeremylt CeedEvalMode eval_mode; 51*d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_fields[i], &eval_mode); 52e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 53*d1d35e2fSjeremylt 54*d1d35e2fSjeremylt if (eval_mode != CEED_EVAL_WEIGHT) { 55*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetElemRestriction(op_fields[i], &elem_restr); 56*d1d35e2fSjeremylt CeedChkBackend(ierr); 57*d1d35e2fSjeremylt ierr = CeedElemRestrictionCreateVector(elem_restr, NULL, 58*d1d35e2fSjeremylt &full_evecs[i+starte]); 59e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 60135a076eSjeremylt } 61135a076eSjeremylt 62*d1d35e2fSjeremylt switch(eval_mode) { 63885ac19cSjeremylt case CEED_EVAL_NONE: 64*d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetSize(qf_fields[i], &size); CeedChkBackend(ierr); 65*d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed, Q*size, &q_vecs[i]); CeedChkBackend(ierr); 66aedaa0e5Sjeremylt break; 67aedaa0e5Sjeremylt case CEED_EVAL_INTERP: 68*d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetSize(qf_fields[i], &size); CeedChkBackend(ierr); 69*d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(elem_restr, &P); 70e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 71*d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed, P*size, &e_vecs[i]); CeedChkBackend(ierr); 72*d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed, Q*size, &q_vecs[i]); CeedChkBackend(ierr); 73885ac19cSjeremylt break; 74885ac19cSjeremylt case CEED_EVAL_GRAD: 75*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(op_fields[i], &basis); CeedChkBackend(ierr); 76*d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetSize(qf_fields[i], &size); CeedChkBackend(ierr); 77e15f9bd0SJeremy L Thompson ierr = CeedBasisGetDimension(basis, &dim); CeedChkBackend(ierr); 78*d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(elem_restr, &P); 79e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 80*d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed, P*size/dim, &e_vecs[i]); CeedChkBackend(ierr); 81*d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed, Q*size, &q_vecs[i]); CeedChkBackend(ierr); 82885ac19cSjeremylt break; 83885ac19cSjeremylt case CEED_EVAL_WEIGHT: // Only on input fields 84*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(op_fields[i], &basis); CeedChkBackend(ierr); 85*d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed, Q, &q_vecs[i]); CeedChkBackend(ierr); 86d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, CEED_EVAL_WEIGHT, 87*d1d35e2fSjeremylt CEED_VECTOR_NONE, q_vecs[i]); CeedChkBackend(ierr); 88885ac19cSjeremylt break; 89885ac19cSjeremylt case CEED_EVAL_DIV: 904d537eeaSYohann break; // Not implemented 91885ac19cSjeremylt case CEED_EVAL_CURL: 924d537eeaSYohann break; // Not implemented 9321617c04Sjeremylt } 94885ac19cSjeremylt } 95e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 9621617c04Sjeremylt } 9721617c04Sjeremylt 98f10650afSjeremylt //------------------------------------------------------------------------------ 99f10650afSjeremylt // Setup Operator 100f10650afSjeremylt //------------------------------------------------------------------------------/* 101885ac19cSjeremylt static int CeedOperatorSetup_Ref(CeedOperator op) { 10221617c04Sjeremylt int ierr; 103*d1d35e2fSjeremylt bool setup_done; 104*d1d35e2fSjeremylt ierr = CeedOperatorIsSetupDone(op, &setup_done); CeedChkBackend(ierr); 105*d1d35e2fSjeremylt if (setup_done) return CEED_ERROR_SUCCESS; 106aedaa0e5Sjeremylt Ceed ceed; 107e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChkBackend(ierr); 1084ce2993fSjeremylt CeedOperator_Ref *impl; 109e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetData(op, &impl); CeedChkBackend(ierr); 1104ce2993fSjeremylt CeedQFunction qf; 111e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetQFunction(op, &qf); CeedChkBackend(ierr); 112*d1d35e2fSjeremylt CeedInt Q, num_input_fields, num_output_fields; 113e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChkBackend(ierr); 114*d1d35e2fSjeremylt ierr = CeedQFunctionIsIdentity(qf, &impl->identity_qf); CeedChkBackend(ierr); 115*d1d35e2fSjeremylt ierr = CeedQFunctionGetNumArgs(qf, &num_input_fields, &num_output_fields); 116e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 117*d1d35e2fSjeremylt CeedOperatorField *op_input_fields, *op_output_fields; 118*d1d35e2fSjeremylt ierr = CeedOperatorGetFields(op, &op_input_fields, &op_output_fields); 119e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 120*d1d35e2fSjeremylt CeedQFunctionField *qf_input_fields, *qf_output_fields; 121*d1d35e2fSjeremylt ierr = CeedQFunctionGetFields(qf, &qf_input_fields, &qf_output_fields); 122e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 123885ac19cSjeremylt 124885ac19cSjeremylt // Allocate 125*d1d35e2fSjeremylt ierr = CeedCalloc(num_input_fields + num_output_fields, &impl->e_vecs); 126e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 127*d1d35e2fSjeremylt ierr = CeedCalloc(num_input_fields + num_output_fields, &impl->e_data); 128e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 129885ac19cSjeremylt 130*d1d35e2fSjeremylt ierr = CeedCalloc(16, &impl->input_state); CeedChkBackend(ierr); 131*d1d35e2fSjeremylt ierr = CeedCalloc(16, &impl->e_vecs_in); CeedChkBackend(ierr); 132*d1d35e2fSjeremylt ierr = CeedCalloc(16, &impl->e_vecs_out); CeedChkBackend(ierr); 133*d1d35e2fSjeremylt ierr = CeedCalloc(16, &impl->q_vecs_in); CeedChkBackend(ierr); 134*d1d35e2fSjeremylt ierr = CeedCalloc(16, &impl->q_vecs_out); CeedChkBackend(ierr); 135885ac19cSjeremylt 136*d1d35e2fSjeremylt impl->num_e_vecs_in = num_input_fields; 137*d1d35e2fSjeremylt impl->num_e_vecs_out = num_output_fields; 138885ac19cSjeremylt 139*d1d35e2fSjeremylt // Set up infield and outfield e_vecs and q_vecs 140885ac19cSjeremylt // Infields 141*d1d35e2fSjeremylt ierr = CeedOperatorSetupFields_Ref(qf, op, 0, impl->e_vecs, 142*d1d35e2fSjeremylt impl->e_vecs_in, impl->q_vecs_in, 0, 143*d1d35e2fSjeremylt num_input_fields, Q); 144e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 145885ac19cSjeremylt // Outfields 146*d1d35e2fSjeremylt ierr = CeedOperatorSetupFields_Ref(qf, op, 1, impl->e_vecs, 147*d1d35e2fSjeremylt impl->e_vecs_out, impl->q_vecs_out, 148*d1d35e2fSjeremylt num_input_fields, num_output_fields, Q); 149e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 150885ac19cSjeremylt 15116911fdaSjeremylt // Identity QFunctions 152*d1d35e2fSjeremylt if (impl->identity_qf) { 153*d1d35e2fSjeremylt CeedEvalMode in_mode, out_mode; 154*d1d35e2fSjeremylt CeedQFunctionField *in_fields, *out_fields; 155*d1d35e2fSjeremylt ierr = CeedQFunctionGetFields(qf, &in_fields, &out_fields); 156e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 15716911fdaSjeremylt 158*d1d35e2fSjeremylt for (CeedInt i=0; i<num_input_fields; i++) { 159*d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(in_fields[i], &in_mode); 160*d1d35e2fSjeremylt CeedChkBackend(ierr); 161*d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(out_fields[i], &out_mode); 162*d1d35e2fSjeremylt CeedChkBackend(ierr); 163*d1d35e2fSjeremylt 164*d1d35e2fSjeremylt ierr = CeedVectorDestroy(&impl->q_vecs_out[i]); CeedChkBackend(ierr); 165*d1d35e2fSjeremylt impl->q_vecs_out[i] = impl->q_vecs_in[i]; 166*d1d35e2fSjeremylt ierr = CeedVectorAddReference(impl->q_vecs_in[i]); CeedChkBackend(ierr); 16716911fdaSjeremylt } 16816911fdaSjeremylt } 16916911fdaSjeremylt 170e15f9bd0SJeremy L Thompson ierr = CeedOperatorSetSetupDone(op); CeedChkBackend(ierr); 171885ac19cSjeremylt 172e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 173885ac19cSjeremylt } 174885ac19cSjeremylt 175f10650afSjeremylt //------------------------------------------------------------------------------ 176f10650afSjeremylt // Setup Operator Inputs 177f10650afSjeremylt //------------------------------------------------------------------------------ 178*d1d35e2fSjeremylt static inline int CeedOperatorSetupInputs_Ref(CeedInt num_input_fields, 179*d1d35e2fSjeremylt CeedQFunctionField *qf_input_fields, CeedOperatorField *op_input_fields, 180*d1d35e2fSjeremylt CeedVector in_vec, const bool skip_active, CeedOperator_Ref *impl, 1811d102b48SJeremy L Thompson CeedRequest *request) { 1821d102b48SJeremy L Thompson CeedInt ierr; 183*d1d35e2fSjeremylt CeedEvalMode eval_mode; 184d1bcdac9Sjeremylt CeedVector vec; 185*d1d35e2fSjeremylt CeedElemRestriction elem_restr; 1868d713cf6Sjeremylt uint64_t state; 187885ac19cSjeremylt 188*d1d35e2fSjeremylt for (CeedInt i=0; i<num_input_fields; i++) { 189d1bcdac9Sjeremylt // Get input vector 190*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetVector(op_input_fields[i], &vec); 191*d1d35e2fSjeremylt CeedChkBackend(ierr); 1921d102b48SJeremy L Thompson if (vec == CEED_VECTOR_ACTIVE) { 193*d1d35e2fSjeremylt if (skip_active) 1941d102b48SJeremy L Thompson continue; 1951d102b48SJeremy L Thompson else 196*d1d35e2fSjeremylt vec = in_vec; 1971d102b48SJeremy L Thompson } 1981d102b48SJeremy L Thompson 199*d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_input_fields[i], &eval_mode); 200e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 2011d102b48SJeremy L Thompson // Restrict and Evec 202*d1d35e2fSjeremylt if (eval_mode == CEED_EVAL_WEIGHT) { // Skip 2031d102b48SJeremy L Thompson } else { 204668048e2SJed Brown // Restrict 205e15f9bd0SJeremy L Thompson ierr = CeedVectorGetState(vec, &state); CeedChkBackend(ierr); 2068d713cf6Sjeremylt // Skip restriction if input is unchanged 207*d1d35e2fSjeremylt if (state != impl->input_state[i] || vec == in_vec) { 208*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetElemRestriction(op_input_fields[i], &elem_restr); 209e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 210*d1d35e2fSjeremylt ierr = CeedElemRestrictionApply(elem_restr, CEED_NOTRANSPOSE, vec, 211*d1d35e2fSjeremylt impl->e_vecs[i], request); CeedChkBackend(ierr); 212*d1d35e2fSjeremylt impl->input_state[i] = state; 2138d713cf6Sjeremylt } 214668048e2SJed Brown // Get evec 215*d1d35e2fSjeremylt ierr = CeedVectorGetArrayRead(impl->e_vecs[i], CEED_MEM_HOST, 216*d1d35e2fSjeremylt (const CeedScalar **) &impl->e_data[i]); 217e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 218885ac19cSjeremylt } 219885ac19cSjeremylt } 220e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 221885ac19cSjeremylt } 222885ac19cSjeremylt 223f10650afSjeremylt //------------------------------------------------------------------------------ 224f10650afSjeremylt // Input Basis Action 225f10650afSjeremylt //------------------------------------------------------------------------------ 2261d102b48SJeremy L Thompson static inline int CeedOperatorInputBasis_Ref(CeedInt e, CeedInt Q, 227*d1d35e2fSjeremylt CeedQFunctionField *qf_input_fields, CeedOperatorField *op_input_fields, 228*d1d35e2fSjeremylt CeedInt num_input_fields, const bool skip_active, CeedOperator_Ref *impl) { 2291d102b48SJeremy L Thompson CeedInt ierr; 230*d1d35e2fSjeremylt CeedInt dim, elem_size, size; 231*d1d35e2fSjeremylt CeedElemRestriction elem_restr; 232*d1d35e2fSjeremylt CeedEvalMode eval_mode; 2331d102b48SJeremy L Thompson CeedBasis basis; 2341d102b48SJeremy L Thompson 235*d1d35e2fSjeremylt for (CeedInt i=0; i<num_input_fields; i++) { 2361d102b48SJeremy L Thompson // Skip active input 237*d1d35e2fSjeremylt if (skip_active) { 2381d102b48SJeremy L Thompson CeedVector vec; 239*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetVector(op_input_fields[i], &vec); 240*d1d35e2fSjeremylt CeedChkBackend(ierr); 2411d102b48SJeremy L Thompson if (vec == CEED_VECTOR_ACTIVE) 2421d102b48SJeremy L Thompson continue; 2431d102b48SJeremy L Thompson } 244*d1d35e2fSjeremylt // Get elem_size, eval_mode, size 245*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetElemRestriction(op_input_fields[i], &elem_restr); 246e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 247*d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(elem_restr, &elem_size); 248e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 249*d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_input_fields[i], &eval_mode); 250e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 251*d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetSize(qf_input_fields[i], &size); 252*d1d35e2fSjeremylt CeedChkBackend(ierr); 253885ac19cSjeremylt // Basis action 254*d1d35e2fSjeremylt switch(eval_mode) { 255885ac19cSjeremylt case CEED_EVAL_NONE: 256*d1d35e2fSjeremylt ierr = CeedVectorSetArray(impl->q_vecs_in[i], CEED_MEM_HOST, 257*d1d35e2fSjeremylt CEED_USE_POINTER, &impl->e_data[i][e*Q*size]); 258*d1d35e2fSjeremylt CeedChkBackend(ierr); 259885ac19cSjeremylt break; 260885ac19cSjeremylt case CEED_EVAL_INTERP: 261*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(op_input_fields[i], &basis); 262e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 263*d1d35e2fSjeremylt ierr = CeedVectorSetArray(impl->e_vecs_in[i], CEED_MEM_HOST, 264*d1d35e2fSjeremylt CEED_USE_POINTER, &impl->e_data[i][e*elem_size*size]); 265e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 266*d1d35e2fSjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, CEED_EVAL_INTERP, 267*d1d35e2fSjeremylt impl->e_vecs_in[i], impl->q_vecs_in[i]); CeedChkBackend(ierr); 268885ac19cSjeremylt break; 269885ac19cSjeremylt case CEED_EVAL_GRAD: 270*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(op_input_fields[i], &basis); 271e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 272e15f9bd0SJeremy L Thompson ierr = CeedBasisGetDimension(basis, &dim); CeedChkBackend(ierr); 273*d1d35e2fSjeremylt ierr = CeedVectorSetArray(impl->e_vecs_in[i], CEED_MEM_HOST, 274*d1d35e2fSjeremylt CEED_USE_POINTER, &impl->e_data[i][e*elem_size*size/dim]); 275e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 276d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, 277*d1d35e2fSjeremylt CEED_EVAL_GRAD, impl->e_vecs_in[i], 278*d1d35e2fSjeremylt impl->q_vecs_in[i]); CeedChkBackend(ierr); 279885ac19cSjeremylt break; 280885ac19cSjeremylt case CEED_EVAL_WEIGHT: 281885ac19cSjeremylt break; // No action 282bbfacfcdSjeremylt // LCOV_EXCL_START 283885ac19cSjeremylt case CEED_EVAL_DIV: 2841d102b48SJeremy L Thompson case CEED_EVAL_CURL: { 285*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(op_input_fields[i], &basis); 286e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 2871d102b48SJeremy L Thompson Ceed ceed; 288e15f9bd0SJeremy L Thompson ierr = CeedBasisGetCeed(basis, &ceed); CeedChkBackend(ierr); 289e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 290e15f9bd0SJeremy L Thompson "Ceed evaluation mode not implemented"); 291bbfacfcdSjeremylt // LCOV_EXCL_STOP 292885ac19cSjeremylt } 293885ac19cSjeremylt } 294885ac19cSjeremylt } 295e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 296885ac19cSjeremylt } 297885ac19cSjeremylt 298f10650afSjeremylt //------------------------------------------------------------------------------ 299f10650afSjeremylt // Output Basis Action 300f10650afSjeremylt //------------------------------------------------------------------------------ 3011d102b48SJeremy L Thompson static inline int CeedOperatorOutputBasis_Ref(CeedInt e, CeedInt Q, 302*d1d35e2fSjeremylt CeedQFunctionField *qf_output_fields, CeedOperatorField *op_output_fields, 303*d1d35e2fSjeremylt CeedInt num_input_fields, CeedInt num_output_fields, CeedOperator op, 3041d102b48SJeremy L Thompson CeedOperator_Ref *impl) { 3051d102b48SJeremy L Thompson CeedInt ierr; 306*d1d35e2fSjeremylt CeedInt dim, elem_size, size; 307*d1d35e2fSjeremylt CeedElemRestriction elem_restr; 308*d1d35e2fSjeremylt CeedEvalMode eval_mode; 3091d102b48SJeremy L Thompson CeedBasis basis; 3101d102b48SJeremy L Thompson 311*d1d35e2fSjeremylt for (CeedInt i=0; i<num_output_fields; i++) { 312*d1d35e2fSjeremylt // Get elem_size, eval_mode, size 313*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetElemRestriction(op_output_fields[i], &elem_restr); 314e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 315*d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(elem_restr, &elem_size); 316e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 317*d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_output_fields[i], &eval_mode); 318e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 319*d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetSize(qf_output_fields[i], &size); 320e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 321885ac19cSjeremylt // Basis action 322*d1d35e2fSjeremylt switch(eval_mode) { 323885ac19cSjeremylt case CEED_EVAL_NONE: 324885ac19cSjeremylt break; // No action 325885ac19cSjeremylt case CEED_EVAL_INTERP: 326*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(op_output_fields[i], &basis); 327e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 328*d1d35e2fSjeremylt ierr = CeedVectorSetArray(impl->e_vecs_out[i], CEED_MEM_HOST, 329aedaa0e5Sjeremylt CEED_USE_POINTER, 330*d1d35e2fSjeremylt &impl->e_data[i + num_input_fields][e*elem_size*size]); 331e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 332aedaa0e5Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, 333*d1d35e2fSjeremylt CEED_EVAL_INTERP, impl->q_vecs_out[i], 334*d1d35e2fSjeremylt impl->e_vecs_out[i]); CeedChkBackend(ierr); 335885ac19cSjeremylt break; 336885ac19cSjeremylt case CEED_EVAL_GRAD: 337*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(op_output_fields[i], &basis); 338e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 339e15f9bd0SJeremy L Thompson ierr = CeedBasisGetDimension(basis, &dim); CeedChkBackend(ierr); 340*d1d35e2fSjeremylt ierr = CeedVectorSetArray(impl->e_vecs_out[i], CEED_MEM_HOST, 341aedaa0e5Sjeremylt CEED_USE_POINTER, 342*d1d35e2fSjeremylt &impl->e_data[i + num_input_fields][e*elem_size*size/dim]); 343e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 344aedaa0e5Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, 345*d1d35e2fSjeremylt CEED_EVAL_GRAD, impl->q_vecs_out[i], 346*d1d35e2fSjeremylt impl->e_vecs_out[i]); CeedChkBackend(ierr); 347885ac19cSjeremylt break; 348c042f62fSJeremy L Thompson // LCOV_EXCL_START 349bbfacfcdSjeremylt case CEED_EVAL_WEIGHT: { 3504ce2993fSjeremylt Ceed ceed; 351e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChkBackend(ierr); 352e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 353e15f9bd0SJeremy L Thompson "CEED_EVAL_WEIGHT cannot be an output " 3541d102b48SJeremy L Thompson "evaluation mode"); 3554ce2993fSjeremylt } 356885ac19cSjeremylt case CEED_EVAL_DIV: 3571d102b48SJeremy L Thompson case CEED_EVAL_CURL: { 3581d102b48SJeremy L Thompson Ceed ceed; 359e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChkBackend(ierr); 360e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 361e15f9bd0SJeremy L Thompson "Ceed evaluation mode not implemented"); 3621d102b48SJeremy L Thompson // LCOV_EXCL_STOP 363885ac19cSjeremylt } 364885ac19cSjeremylt } 365885ac19cSjeremylt } 366e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3671d102b48SJeremy L Thompson } 3681d102b48SJeremy L Thompson 369f10650afSjeremylt //------------------------------------------------------------------------------ 370f10650afSjeremylt // Restore Input Vectors 371f10650afSjeremylt //------------------------------------------------------------------------------ 372*d1d35e2fSjeremylt static inline int CeedOperatorRestoreInputs_Ref(CeedInt num_input_fields, 373*d1d35e2fSjeremylt CeedQFunctionField *qf_input_fields, CeedOperatorField *op_input_fields, 374*d1d35e2fSjeremylt const bool skip_active, CeedOperator_Ref *impl) { 3751d102b48SJeremy L Thompson CeedInt ierr; 376*d1d35e2fSjeremylt CeedEvalMode eval_mode; 3771d102b48SJeremy L Thompson 378*d1d35e2fSjeremylt for (CeedInt i=0; i<num_input_fields; i++) { 3791d102b48SJeremy L Thompson // Skip active inputs 380*d1d35e2fSjeremylt if (skip_active) { 3811d102b48SJeremy L Thompson CeedVector vec; 382*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetVector(op_input_fields[i], &vec); 383*d1d35e2fSjeremylt CeedChkBackend(ierr); 3841d102b48SJeremy L Thompson if (vec == CEED_VECTOR_ACTIVE) 3851d102b48SJeremy L Thompson continue; 3861d102b48SJeremy L Thompson } 3871d102b48SJeremy L Thompson // Restore input 388*d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_input_fields[i], &eval_mode); 389e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 390*d1d35e2fSjeremylt if (eval_mode == CEED_EVAL_WEIGHT) { // Skip 3911d102b48SJeremy L Thompson } else { 392*d1d35e2fSjeremylt ierr = CeedVectorRestoreArrayRead(impl->e_vecs[i], 393*d1d35e2fSjeremylt (const CeedScalar **) &impl->e_data[i]); 394e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 3951d102b48SJeremy L Thompson } 3961d102b48SJeremy L Thompson } 397e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3981d102b48SJeremy L Thompson } 3991d102b48SJeremy L Thompson 400f10650afSjeremylt //------------------------------------------------------------------------------ 401f10650afSjeremylt // Operator Apply 402f10650afSjeremylt //------------------------------------------------------------------------------ 403*d1d35e2fSjeremylt static int CeedOperatorApplyAdd_Ref(CeedOperator op, CeedVector in_vec, 404*d1d35e2fSjeremylt CeedVector out_vec, CeedRequest *request) { 4051d102b48SJeremy L Thompson int ierr; 4061d102b48SJeremy L Thompson CeedOperator_Ref *impl; 407e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetData(op, &impl); CeedChkBackend(ierr); 4081d102b48SJeremy L Thompson CeedQFunction qf; 409e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetQFunction(op, &qf); CeedChkBackend(ierr); 410*d1d35e2fSjeremylt CeedInt Q, num_elem, num_input_fields, num_output_fields, size; 411e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChkBackend(ierr); 412*d1d35e2fSjeremylt ierr = CeedOperatorGetNumElements(op, &num_elem); CeedChkBackend(ierr); 413*d1d35e2fSjeremylt ierr= CeedQFunctionGetNumArgs(qf, &num_input_fields, &num_output_fields); 414e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 415*d1d35e2fSjeremylt CeedOperatorField *op_input_fields, *op_output_fields; 416*d1d35e2fSjeremylt ierr = CeedOperatorGetFields(op, &op_input_fields, &op_output_fields); 417e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 418*d1d35e2fSjeremylt CeedQFunctionField *qf_input_fields, *qf_output_fields; 419*d1d35e2fSjeremylt ierr = CeedQFunctionGetFields(qf, &qf_input_fields, &qf_output_fields); 420e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 421*d1d35e2fSjeremylt CeedEvalMode eval_mode; 4221d102b48SJeremy L Thompson CeedVector vec; 423*d1d35e2fSjeremylt CeedElemRestriction elem_restr; 4241d102b48SJeremy L Thompson 4251d102b48SJeremy L Thompson // Setup 426e15f9bd0SJeremy L Thompson ierr = CeedOperatorSetup_Ref(op); CeedChkBackend(ierr); 4271d102b48SJeremy L Thompson 4281d102b48SJeremy L Thompson // Input Evecs and Restriction 429*d1d35e2fSjeremylt ierr = CeedOperatorSetupInputs_Ref(num_input_fields, qf_input_fields, 430*d1d35e2fSjeremylt op_input_fields, in_vec, false, impl, 431e15f9bd0SJeremy L Thompson request); CeedChkBackend(ierr); 4321d102b48SJeremy L Thompson 4331d102b48SJeremy L Thompson // Output Evecs 434*d1d35e2fSjeremylt for (CeedInt i=0; i<num_output_fields; i++) { 435*d1d35e2fSjeremylt ierr = CeedVectorGetArray(impl->e_vecs[i+impl->num_e_vecs_in], CEED_MEM_HOST, 436*d1d35e2fSjeremylt &impl->e_data[i + num_input_fields]); CeedChkBackend(ierr); 4371d102b48SJeremy L Thompson } 4381d102b48SJeremy L Thompson 4391d102b48SJeremy L Thompson // Loop through elements 440*d1d35e2fSjeremylt for (CeedInt e=0; e<num_elem; e++) { 4411d102b48SJeremy L Thompson // Output pointers 442*d1d35e2fSjeremylt for (CeedInt i=0; i<num_output_fields; i++) { 443*d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_output_fields[i], &eval_mode); 444e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 445*d1d35e2fSjeremylt if (eval_mode == CEED_EVAL_NONE) { 446*d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetSize(qf_output_fields[i], &size); 447e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 448*d1d35e2fSjeremylt ierr = CeedVectorSetArray(impl->q_vecs_out[i], CEED_MEM_HOST, 4491d102b48SJeremy L Thompson CEED_USE_POINTER, 450*d1d35e2fSjeremylt &impl->e_data[i + num_input_fields][e*Q*size]); 451e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 4521d102b48SJeremy L Thompson } 4531d102b48SJeremy L Thompson } 4541d102b48SJeremy L Thompson 45516911fdaSjeremylt // Input basis apply 456*d1d35e2fSjeremylt ierr = CeedOperatorInputBasis_Ref(e, Q, qf_input_fields, op_input_fields, 457*d1d35e2fSjeremylt num_input_fields, false, impl); 458e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 45916911fdaSjeremylt 4601d102b48SJeremy L Thompson // Q function 461*d1d35e2fSjeremylt if (!impl->identity_qf) { 462*d1d35e2fSjeremylt ierr = CeedQFunctionApply(qf, Q, impl->q_vecs_in, impl->q_vecs_out); 463e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 46416911fdaSjeremylt } 4651d102b48SJeremy L Thompson 4661d102b48SJeremy L Thompson // Output basis apply 467*d1d35e2fSjeremylt ierr = CeedOperatorOutputBasis_Ref(e, Q, qf_output_fields, op_output_fields, 468*d1d35e2fSjeremylt num_input_fields, num_output_fields, op, impl); 469e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 4701d102b48SJeremy L Thompson } 471885ac19cSjeremylt 472885ac19cSjeremylt // Output restriction 473*d1d35e2fSjeremylt for (CeedInt i=0; i<num_output_fields; i++) { 474*d1d35e2fSjeremylt // Restore Evec 475*d1d35e2fSjeremylt ierr = CeedVectorRestoreArray(impl->e_vecs[i+impl->num_e_vecs_in], 476*d1d35e2fSjeremylt &impl->e_data[i + num_input_fields]); 477e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 478d1bcdac9Sjeremylt // Get output vector 479*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetVector(op_output_fields[i], &vec); 480e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 481668048e2SJed Brown // Active 482d1bcdac9Sjeremylt if (vec == CEED_VECTOR_ACTIVE) 483*d1d35e2fSjeremylt vec = out_vec; 4847ca8db16Sjeremylt // Restrict 485*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetElemRestriction(op_output_fields[i], &elem_restr); 486e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 487*d1d35e2fSjeremylt ierr = CeedElemRestrictionApply(elem_restr, CEED_TRANSPOSE, 488*d1d35e2fSjeremylt impl->e_vecs[i+impl->num_e_vecs_in], vec, request); 489e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 490885ac19cSjeremylt } 491885ac19cSjeremylt 4927ca8db16Sjeremylt // Restore input arrays 493*d1d35e2fSjeremylt ierr = CeedOperatorRestoreInputs_Ref(num_input_fields, qf_input_fields, 494*d1d35e2fSjeremylt op_input_fields, false, impl); 495e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 4967ca8db16Sjeremylt 497e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 49821617c04Sjeremylt } 49921617c04Sjeremylt 500f10650afSjeremylt //------------------------------------------------------------------------------ 5011d102b48SJeremy L Thompson // Assemble Linear QFunction 502f10650afSjeremylt //------------------------------------------------------------------------------ 50380ac2e43SJeremy L Thompson static int CeedOperatorLinearAssembleQFunction_Ref(CeedOperator op, 5041d102b48SJeremy L Thompson CeedVector *assembled, CeedElemRestriction *rstr, CeedRequest *request) { 5051d102b48SJeremy L Thompson int ierr; 5061d102b48SJeremy L Thompson CeedOperator_Ref *impl; 507e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetData(op, &impl); CeedChkBackend(ierr); 5081d102b48SJeremy L Thompson CeedQFunction qf; 509e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetQFunction(op, &qf); CeedChkBackend(ierr); 510*d1d35e2fSjeremylt CeedInt Q, num_elem, num_input_fields, num_output_fields, size; 511e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChkBackend(ierr); 512*d1d35e2fSjeremylt ierr = CeedOperatorGetNumElements(op, &num_elem); CeedChkBackend(ierr); 513*d1d35e2fSjeremylt ierr= CeedQFunctionGetNumArgs(qf, &num_input_fields, &num_output_fields); 514e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 515*d1d35e2fSjeremylt CeedOperatorField *op_input_fields, *op_output_fields; 516*d1d35e2fSjeremylt ierr = CeedOperatorGetFields(op, &op_input_fields, &op_output_fields); 517e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 518*d1d35e2fSjeremylt CeedQFunctionField *qf_input_fields, *qf_output_fields; 519*d1d35e2fSjeremylt ierr = CeedQFunctionGetFields(qf, &qf_input_fields, &qf_output_fields); 520e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 5211d102b48SJeremy L Thompson CeedVector vec; 522*d1d35e2fSjeremylt CeedInt num_active_in = 0, num_active_out = 0; 523*d1d35e2fSjeremylt CeedVector *active_in = NULL; 5241d102b48SJeremy L Thompson CeedScalar *a, *tmp; 525*d1d35e2fSjeremylt Ceed ceed, ceed_parent; 526e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChkBackend(ierr); 527*d1d35e2fSjeremylt ierr = CeedGetOperatorFallbackParentCeed(ceed, &ceed_parent); 528e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 529*d1d35e2fSjeremylt ceed_parent = ceed_parent ? ceed_parent : ceed; 5301d102b48SJeremy L Thompson 5311d102b48SJeremy L Thompson // Setup 532e15f9bd0SJeremy L Thompson ierr = CeedOperatorSetup_Ref(op); CeedChkBackend(ierr); 5331d102b48SJeremy L Thompson 53416911fdaSjeremylt // Check for identity 535*d1d35e2fSjeremylt if (impl->identity_qf) 53616911fdaSjeremylt // LCOV_EXCL_START 537e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 538e15f9bd0SJeremy L Thompson "Assembling identity QFunctions not supported"); 53916911fdaSjeremylt // LCOV_EXCL_STOP 54016911fdaSjeremylt 5411d102b48SJeremy L Thompson // Input Evecs and Restriction 542*d1d35e2fSjeremylt ierr = CeedOperatorSetupInputs_Ref(num_input_fields, qf_input_fields, 543*d1d35e2fSjeremylt op_input_fields, NULL, true, impl, request); 544e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 5451d102b48SJeremy L Thompson 5461d102b48SJeremy L Thompson // Count number of active input fields 547*d1d35e2fSjeremylt for (CeedInt i=0; i<num_input_fields; i++) { 5481d102b48SJeremy L Thompson // Get input vector 549*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetVector(op_input_fields[i], &vec); 550*d1d35e2fSjeremylt CeedChkBackend(ierr); 5511d102b48SJeremy L Thompson // Check if active input 5521d102b48SJeremy L Thompson if (vec == CEED_VECTOR_ACTIVE) { 553*d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetSize(qf_input_fields[i], &size); 554e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 555*d1d35e2fSjeremylt ierr = CeedVectorSetValue(impl->q_vecs_in[i], 0.0); CeedChkBackend(ierr); 556*d1d35e2fSjeremylt ierr = CeedVectorGetArray(impl->q_vecs_in[i], CEED_MEM_HOST, &tmp); 557*d1d35e2fSjeremylt CeedChkBackend(ierr); 558*d1d35e2fSjeremylt ierr = CeedRealloc(num_active_in + size, &active_in); CeedChkBackend(ierr); 5591d102b48SJeremy L Thompson for (CeedInt field=0; field<size; field++) { 560*d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed, Q, &active_in[num_active_in+field]); 561e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 562*d1d35e2fSjeremylt ierr = CeedVectorSetArray(active_in[num_active_in+field], CEED_MEM_HOST, 56342ea3801Sjeremylt CEED_USE_POINTER, &tmp[field*Q]); 564e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 5651d102b48SJeremy L Thompson } 566*d1d35e2fSjeremylt num_active_in += size; 567*d1d35e2fSjeremylt ierr = CeedVectorRestoreArray(impl->q_vecs_in[i], &tmp); CeedChkBackend(ierr); 5681d102b48SJeremy L Thompson } 5691d102b48SJeremy L Thompson } 5701d102b48SJeremy L Thompson 5711d102b48SJeremy L Thompson // Count number of active output fields 572*d1d35e2fSjeremylt for (CeedInt i=0; i<num_output_fields; i++) { 5731d102b48SJeremy L Thompson // Get output vector 574*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetVector(op_output_fields[i], &vec); 575e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 5761d102b48SJeremy L Thompson // Check if active output 5771d102b48SJeremy L Thompson if (vec == CEED_VECTOR_ACTIVE) { 578*d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetSize(qf_output_fields[i], &size); 579e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 580*d1d35e2fSjeremylt num_active_out += size; 5811d102b48SJeremy L Thompson } 5821d102b48SJeremy L Thompson } 5831d102b48SJeremy L Thompson 5841d102b48SJeremy L Thompson // Check sizes 585*d1d35e2fSjeremylt if (!num_active_in || !num_active_out) 586138d4072Sjeremylt // LCOV_EXCL_START 587e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 588e15f9bd0SJeremy L Thompson "Cannot assemble QFunction without active inputs " 589138d4072Sjeremylt "and outputs"); 590138d4072Sjeremylt // LCOV_EXCL_STOP 5911d102b48SJeremy L Thompson 5921d102b48SJeremy L Thompson // Create output restriction 593*d1d35e2fSjeremylt CeedInt strides[3] = {1, Q, num_active_in*num_active_out*Q}; /* *NOPAD* */ 594*d1d35e2fSjeremylt ierr = CeedElemRestrictionCreateStrided(ceed_parent, num_elem, Q, 595*d1d35e2fSjeremylt num_active_in*num_active_out, 596*d1d35e2fSjeremylt num_active_in*num_active_out*num_elem*Q, 597e15f9bd0SJeremy L Thompson strides, rstr); CeedChkBackend(ierr); 5981d102b48SJeremy L Thompson // Create assembled vector 599*d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed_parent, num_elem*Q*num_active_in*num_active_out, 600e15f9bd0SJeremy L Thompson assembled); CeedChkBackend(ierr); 601e15f9bd0SJeremy L Thompson ierr = CeedVectorSetValue(*assembled, 0.0); CeedChkBackend(ierr); 602e15f9bd0SJeremy L Thompson ierr = CeedVectorGetArray(*assembled, CEED_MEM_HOST, &a); CeedChkBackend(ierr); 6031d102b48SJeremy L Thompson 6041d102b48SJeremy L Thompson // Loop through elements 605*d1d35e2fSjeremylt for (CeedInt e=0; e<num_elem; e++) { 6061d102b48SJeremy L Thompson // Input basis apply 607*d1d35e2fSjeremylt ierr = CeedOperatorInputBasis_Ref(e, Q, qf_input_fields, op_input_fields, 608*d1d35e2fSjeremylt num_input_fields, true, impl); 609e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 6101d102b48SJeremy L Thompson 6111d102b48SJeremy L Thompson // Assemble QFunction 612*d1d35e2fSjeremylt for (CeedInt in=0; in<num_active_in; in++) { 6131d102b48SJeremy L Thompson // Set Inputs 614*d1d35e2fSjeremylt ierr = CeedVectorSetValue(active_in[in], 1.0); CeedChkBackend(ierr); 615*d1d35e2fSjeremylt if (num_active_in > 1) { 616*d1d35e2fSjeremylt ierr = CeedVectorSetValue(active_in[(in+num_active_in-1)%num_active_in], 617e15f9bd0SJeremy L Thompson 0.0); CeedChkBackend(ierr); 61842ea3801Sjeremylt } 6191d102b48SJeremy L Thompson // Set Outputs 620*d1d35e2fSjeremylt for (CeedInt out=0; out<num_output_fields; out++) { 6211d102b48SJeremy L Thompson // Get output vector 622*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetVector(op_output_fields[out], &vec); 623e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 6241d102b48SJeremy L Thompson // Check if active output 6251d102b48SJeremy L Thompson if (vec == CEED_VECTOR_ACTIVE) { 626*d1d35e2fSjeremylt CeedVectorSetArray(impl->q_vecs_out[out], CEED_MEM_HOST, 627e15f9bd0SJeremy L Thompson CEED_USE_POINTER, a); CeedChkBackend(ierr); 628*d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetSize(qf_output_fields[out], &size); 629e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 6301d102b48SJeremy L Thompson a += size*Q; // Advance the pointer by the size of the output 6311d102b48SJeremy L Thompson } 6321d102b48SJeremy L Thompson } 6331d102b48SJeremy L Thompson // Apply QFunction 634*d1d35e2fSjeremylt ierr = CeedQFunctionApply(qf, Q, impl->q_vecs_in, impl->q_vecs_out); 635e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 6361d102b48SJeremy L Thompson } 6371d102b48SJeremy L Thompson } 6381d102b48SJeremy L Thompson 6391d102b48SJeremy L Thompson // Un-set output Qvecs to prevent accidental overwrite of Assembled 640*d1d35e2fSjeremylt for (CeedInt out=0; out<num_output_fields; out++) { 6411d102b48SJeremy L Thompson // Get output vector 642*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetVector(op_output_fields[out], &vec); 643e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 6441d102b48SJeremy L Thompson // Check if active output 6451d102b48SJeremy L Thompson if (vec == CEED_VECTOR_ACTIVE) { 646*d1d35e2fSjeremylt CeedVectorTakeArray(impl->q_vecs_out[out], CEED_MEM_HOST, NULL); 647e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 6481d102b48SJeremy L Thompson } 6491d102b48SJeremy L Thompson } 6501d102b48SJeremy L Thompson 6511d102b48SJeremy L Thompson // Restore input arrays 652*d1d35e2fSjeremylt ierr = CeedOperatorRestoreInputs_Ref(num_input_fields, qf_input_fields, 653*d1d35e2fSjeremylt op_input_fields, true, impl); 654e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 6551d102b48SJeremy L Thompson 6561d102b48SJeremy L Thompson // Restore output 657e15f9bd0SJeremy L Thompson ierr = CeedVectorRestoreArray(*assembled, &a); CeedChkBackend(ierr); 6581d102b48SJeremy L Thompson 6591d102b48SJeremy L Thompson // Cleanup 660*d1d35e2fSjeremylt for (CeedInt i=0; i<num_active_in; i++) { 661*d1d35e2fSjeremylt ierr = CeedVectorDestroy(&active_in[i]); CeedChkBackend(ierr); 66242ea3801Sjeremylt } 663*d1d35e2fSjeremylt ierr = CeedFree(&active_in); CeedChkBackend(ierr); 6641d102b48SJeremy L Thompson 665e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6661d102b48SJeremy L Thompson } 6671d102b48SJeremy L Thompson 668f10650afSjeremylt //------------------------------------------------------------------------------ 669dfffd467Sjeremylt // Get Basis Emode Pointer 670dfffd467Sjeremylt //------------------------------------------------------------------------------ 671*d1d35e2fSjeremylt static inline void CeedOperatorGetBasisPointer_Ref(const CeedScalar **basis_ptr, 672*d1d35e2fSjeremylt CeedEvalMode eval_mode, const CeedScalar *identity, const CeedScalar *interp, 6736c58de82SJeremy L Thompson const CeedScalar *grad) { 674*d1d35e2fSjeremylt switch (eval_mode) { 675dfffd467Sjeremylt case CEED_EVAL_NONE: 676*d1d35e2fSjeremylt *basis_ptr = identity; 677dfffd467Sjeremylt break; 678dfffd467Sjeremylt case CEED_EVAL_INTERP: 679*d1d35e2fSjeremylt *basis_ptr = interp; 680dfffd467Sjeremylt break; 681dfffd467Sjeremylt case CEED_EVAL_GRAD: 682*d1d35e2fSjeremylt *basis_ptr = grad; 683dfffd467Sjeremylt break; 684dfffd467Sjeremylt case CEED_EVAL_WEIGHT: 685dfffd467Sjeremylt case CEED_EVAL_DIV: 686dfffd467Sjeremylt case CEED_EVAL_CURL: 687dfffd467Sjeremylt break; // Caught by QF Assembly 688dfffd467Sjeremylt } 689dfffd467Sjeremylt } 690dfffd467Sjeremylt 691dfffd467Sjeremylt //------------------------------------------------------------------------------ 692d965c7a7SJeremy L Thompson // Create point block restriction 693d965c7a7SJeremy L Thompson //------------------------------------------------------------------------------ 694868092e3SJeremy L Thompson static int CreatePBRestriction_Ref(CeedElemRestriction rstr, 695*d1d35e2fSjeremylt CeedElemRestriction *pb_rstr) { 696d965c7a7SJeremy L Thompson int ierr; 697d965c7a7SJeremy L Thompson Ceed ceed; 698e15f9bd0SJeremy L Thompson ierr = CeedElemRestrictionGetCeed(rstr, &ceed); CeedChkBackend(ierr); 699d965c7a7SJeremy L Thompson const CeedInt *offsets; 700d965c7a7SJeremy L Thompson ierr = CeedElemRestrictionGetOffsets(rstr, CEED_MEM_HOST, &offsets); 701e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 702d965c7a7SJeremy L Thompson 703d965c7a7SJeremy L Thompson // Expand offsets 704*d1d35e2fSjeremylt CeedInt num_elem, num_comp, elem_size, comp_stride, max = 1, *pbOffsets; 705*d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(rstr, &num_elem); CeedChkBackend(ierr); 706*d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumComponents(rstr, &num_comp); 707e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 708*d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(rstr, &elem_size); 709*d1d35e2fSjeremylt CeedChkBackend(ierr); 710*d1d35e2fSjeremylt ierr = CeedElemRestrictionGetCompStride(rstr, &comp_stride); 711*d1d35e2fSjeremylt CeedChkBackend(ierr); 712*d1d35e2fSjeremylt CeedInt shift = num_comp; 713*d1d35e2fSjeremylt if (comp_stride != 1) 714*d1d35e2fSjeremylt shift *= num_comp; 715*d1d35e2fSjeremylt ierr = CeedCalloc(num_elem*elem_size, &pbOffsets); CeedChkBackend(ierr); 716*d1d35e2fSjeremylt for (CeedInt i = 0; i < num_elem*elem_size; i++) { 717d965c7a7SJeremy L Thompson pbOffsets[i] = offsets[i]*shift; 718d965c7a7SJeremy L Thompson if (pbOffsets[i] > max) 719d965c7a7SJeremy L Thompson max = pbOffsets[i]; 720d965c7a7SJeremy L Thompson } 721d965c7a7SJeremy L Thompson 722d965c7a7SJeremy L Thompson // Create new restriction 723*d1d35e2fSjeremylt ierr = CeedElemRestrictionCreate(ceed, num_elem, elem_size, num_comp*num_comp, 724*d1d35e2fSjeremylt 1, 725*d1d35e2fSjeremylt max + num_comp*num_comp, CEED_MEM_HOST, 726*d1d35e2fSjeremylt CEED_OWN_POINTER, pbOffsets, pb_rstr); 727e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 728d965c7a7SJeremy L Thompson 729d965c7a7SJeremy L Thompson // Cleanup 730e15f9bd0SJeremy L Thompson ierr = CeedElemRestrictionRestoreOffsets(rstr, &offsets); CeedChkBackend(ierr); 731d965c7a7SJeremy L Thompson 732e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 733d965c7a7SJeremy L Thompson } 734d965c7a7SJeremy L Thompson 735d965c7a7SJeremy L Thompson //------------------------------------------------------------------------------ 736c04a41a7SJeremy L Thompson // Assemble diagonal common code 737f10650afSjeremylt //------------------------------------------------------------------------------ 73869af5e5fSJeremy L Thompson static inline int CeedOperatorAssembleAddDiagonalCore_Ref(CeedOperator op, 739*d1d35e2fSjeremylt CeedVector assembled, CeedRequest *request, const bool is_pointblock) { 7407172caadSjeremylt int ierr; 741c04a41a7SJeremy L Thompson Ceed ceed; 742e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChkBackend(ierr); 7437172caadSjeremylt 7447172caadSjeremylt // Assemble QFunction 7457172caadSjeremylt CeedQFunction qf; 746e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetQFunction(op, &qf); CeedChkBackend(ierr); 747*d1d35e2fSjeremylt CeedInt num_input_fields, num_output_fields; 748*d1d35e2fSjeremylt ierr= CeedQFunctionGetNumArgs(qf, &num_input_fields, &num_output_fields); 749e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 750*d1d35e2fSjeremylt CeedVector assembled_qf; 7517172caadSjeremylt CeedElemRestriction rstr; 752*d1d35e2fSjeremylt ierr = CeedOperatorLinearAssembleQFunction(op, &assembled_qf, &rstr, request); 753e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 754e15f9bd0SJeremy L Thompson ierr = CeedElemRestrictionDestroy(&rstr); CeedChkBackend(ierr); 755*d1d35e2fSjeremylt CeedScalar max_norm = 0; 756*d1d35e2fSjeremylt ierr = CeedVectorNorm(assembled_qf, CEED_NORM_MAX, &max_norm); 757e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 7587172caadSjeremylt 7597172caadSjeremylt // Determine active input basis 760*d1d35e2fSjeremylt CeedOperatorField *op_fields; 761*d1d35e2fSjeremylt CeedQFunctionField *qf_fields; 762*d1d35e2fSjeremylt ierr = CeedOperatorGetFields(op, &op_fields, NULL); CeedChkBackend(ierr); 763*d1d35e2fSjeremylt ierr = CeedQFunctionGetFields(qf, &qf_fields, NULL); CeedChkBackend(ierr); 764*d1d35e2fSjeremylt CeedInt num_eval_mode_in = 0, num_comp, dim = 1; 765*d1d35e2fSjeremylt CeedEvalMode *eval_mode_in = NULL; 766*d1d35e2fSjeremylt CeedBasis basis_in = NULL; 767*d1d35e2fSjeremylt CeedElemRestriction rstr_in = NULL; 768*d1d35e2fSjeremylt for (CeedInt i=0; i<num_input_fields; i++) { 7697172caadSjeremylt CeedVector vec; 770*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetVector(op_fields[i], &vec); CeedChkBackend(ierr); 7717172caadSjeremylt if (vec == CEED_VECTOR_ACTIVE) { 772c04a41a7SJeremy L Thompson CeedElemRestriction rstr; 773*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(op_fields[i], &basis_in); CeedChkBackend(ierr); 774*d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(basis_in, &num_comp); CeedChkBackend(ierr); 775*d1d35e2fSjeremylt ierr = CeedBasisGetDimension(basis_in, &dim); CeedChkBackend(ierr); 776*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetElemRestriction(op_fields[i], &rstr); 777e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 778*d1d35e2fSjeremylt if (rstr_in && rstr_in != rstr) 779c04a41a7SJeremy L Thompson // LCOV_EXCL_START 780e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 781c04a41a7SJeremy L Thompson "Multi-field non-composite operator diagonal assembly not supported"); 782c04a41a7SJeremy L Thompson // LCOV_EXCL_STOP 783*d1d35e2fSjeremylt rstr_in = rstr; 784*d1d35e2fSjeremylt CeedEvalMode eval_mode; 785*d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_fields[i], &eval_mode); 786e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 787*d1d35e2fSjeremylt switch (eval_mode) { 7887172caadSjeremylt case CEED_EVAL_NONE: 7897172caadSjeremylt case CEED_EVAL_INTERP: 790*d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_in + 1, &eval_mode_in); CeedChkBackend(ierr); 791*d1d35e2fSjeremylt eval_mode_in[num_eval_mode_in] = eval_mode; 792*d1d35e2fSjeremylt num_eval_mode_in += 1; 7937172caadSjeremylt break; 7947172caadSjeremylt case CEED_EVAL_GRAD: 795*d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_in + dim, &eval_mode_in); CeedChkBackend(ierr); 7967172caadSjeremylt for (CeedInt d=0; d<dim; d++) 797*d1d35e2fSjeremylt eval_mode_in[num_eval_mode_in+d] = eval_mode; 798*d1d35e2fSjeremylt num_eval_mode_in += dim; 7997172caadSjeremylt break; 8007172caadSjeremylt case CEED_EVAL_WEIGHT: 8017172caadSjeremylt case CEED_EVAL_DIV: 8027172caadSjeremylt case CEED_EVAL_CURL: 8037172caadSjeremylt break; // Caught by QF Assembly 8047172caadSjeremylt } 8057172caadSjeremylt } 8067172caadSjeremylt } 8077172caadSjeremylt 8087172caadSjeremylt // Determine active output basis 809*d1d35e2fSjeremylt ierr = CeedOperatorGetFields(op, NULL, &op_fields); CeedChkBackend(ierr); 810*d1d35e2fSjeremylt ierr = CeedQFunctionGetFields(qf, NULL, &qf_fields); CeedChkBackend(ierr); 811*d1d35e2fSjeremylt CeedInt num_eval_mode_out = 0; 812*d1d35e2fSjeremylt CeedEvalMode *eval_mode_out = NULL; 813*d1d35e2fSjeremylt CeedBasis basis_out = NULL; 814*d1d35e2fSjeremylt CeedElemRestriction rstr_out = NULL; 815*d1d35e2fSjeremylt for (CeedInt i=0; i<num_output_fields; i++) { 8167172caadSjeremylt CeedVector vec; 817*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetVector(op_fields[i], &vec); CeedChkBackend(ierr); 8187172caadSjeremylt if (vec == CEED_VECTOR_ACTIVE) { 819c04a41a7SJeremy L Thompson CeedElemRestriction rstr; 820*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(op_fields[i], &basis_out); 821e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 822*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetElemRestriction(op_fields[i], &rstr); 823*d1d35e2fSjeremylt CeedChkBackend(ierr); 824*d1d35e2fSjeremylt if (rstr_out && rstr_out != rstr) 825c04a41a7SJeremy L Thompson // LCOV_EXCL_START 826e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 827c04a41a7SJeremy L Thompson "Multi-field non-composite operator diagonal assembly not supported"); 828c04a41a7SJeremy L Thompson // LCOV_EXCL_STOP 829*d1d35e2fSjeremylt rstr_out = rstr; 830*d1d35e2fSjeremylt CeedEvalMode eval_mode; 831*d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_fields[i], &eval_mode); 832*d1d35e2fSjeremylt CeedChkBackend(ierr); 833*d1d35e2fSjeremylt switch (eval_mode) { 8347172caadSjeremylt case CEED_EVAL_NONE: 8357172caadSjeremylt case CEED_EVAL_INTERP: 836*d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_out + 1, &eval_mode_out); CeedChkBackend(ierr); 837*d1d35e2fSjeremylt eval_mode_out[num_eval_mode_out] = eval_mode; 838*d1d35e2fSjeremylt num_eval_mode_out += 1; 8397172caadSjeremylt break; 8407172caadSjeremylt case CEED_EVAL_GRAD: 841*d1d35e2fSjeremylt ierr = CeedRealloc(num_eval_mode_out + dim, &eval_mode_out); 842*d1d35e2fSjeremylt CeedChkBackend(ierr); 8437172caadSjeremylt for (CeedInt d=0; d<dim; d++) 844*d1d35e2fSjeremylt eval_mode_out[num_eval_mode_out+d] = eval_mode; 845*d1d35e2fSjeremylt num_eval_mode_out += dim; 8467172caadSjeremylt break; 8477172caadSjeremylt case CEED_EVAL_WEIGHT: 8487172caadSjeremylt case CEED_EVAL_DIV: 8497172caadSjeremylt case CEED_EVAL_CURL: 8507172caadSjeremylt break; // Caught by QF Assembly 8517172caadSjeremylt } 8527172caadSjeremylt } 8537172caadSjeremylt } 8547172caadSjeremylt 855d965c7a7SJeremy L Thompson // Assemble point-block diagonal restriction, if needed 856*d1d35e2fSjeremylt CeedElemRestriction diag_rstr = rstr_out; 857*d1d35e2fSjeremylt if (is_pointblock) { 858*d1d35e2fSjeremylt ierr = CreatePBRestriction_Ref(rstr_out, &diag_rstr); CeedChkBackend(ierr); 859d965c7a7SJeremy L Thompson } 860d965c7a7SJeremy L Thompson 8617172caadSjeremylt // Create diagonal vector 862*d1d35e2fSjeremylt CeedVector elem_diag; 863*d1d35e2fSjeremylt ierr = CeedElemRestrictionCreateVector(diag_rstr, NULL, &elem_diag); 864e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 8657172caadSjeremylt 8667172caadSjeremylt // Assemble element operator diagonals 867*d1d35e2fSjeremylt CeedScalar *elem_diag_array, *assembled_qf_array; 868*d1d35e2fSjeremylt ierr = CeedVectorSetValue(elem_diag, 0.0); CeedChkBackend(ierr); 869*d1d35e2fSjeremylt ierr = CeedVectorGetArray(elem_diag, CEED_MEM_HOST, &elem_diag_array); 870e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 871*d1d35e2fSjeremylt ierr = CeedVectorGetArray(assembled_qf, CEED_MEM_HOST, &assembled_qf_array); 872e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 873*d1d35e2fSjeremylt CeedInt num_elem, num_nodes, num_qpts; 874*d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(diag_rstr, &num_elem); 875e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 876*d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes(basis_in, &num_nodes); CeedChkBackend(ierr); 877*d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis_in, &num_qpts); 878*d1d35e2fSjeremylt CeedChkBackend(ierr); 879dfffd467Sjeremylt // Basis matrices 880*d1d35e2fSjeremylt const CeedScalar *interp_in, *interp_out, *grad_in, *grad_out; 8816c58de82SJeremy L Thompson CeedScalar *identity = NULL; 882dfffd467Sjeremylt bool evalNone = false; 883*d1d35e2fSjeremylt for (CeedInt i=0; i<num_eval_mode_in; i++) 884*d1d35e2fSjeremylt evalNone = evalNone || (eval_mode_in[i] == CEED_EVAL_NONE); 885*d1d35e2fSjeremylt for (CeedInt i=0; i<num_eval_mode_out; i++) 886*d1d35e2fSjeremylt evalNone = evalNone || (eval_mode_out[i] == CEED_EVAL_NONE); 887dfffd467Sjeremylt if (evalNone) { 888*d1d35e2fSjeremylt ierr = CeedCalloc(num_qpts*num_nodes, &identity); CeedChkBackend(ierr); 889*d1d35e2fSjeremylt for (CeedInt i=0; i<(num_nodes<num_qpts?num_nodes:num_qpts); i++) 890*d1d35e2fSjeremylt identity[i*num_nodes+i] = 1.0; 891dfffd467Sjeremylt } 892*d1d35e2fSjeremylt ierr = CeedBasisGetInterp(basis_in, &interp_in); CeedChkBackend(ierr); 893*d1d35e2fSjeremylt ierr = CeedBasisGetInterp(basis_out, &interp_out); CeedChkBackend(ierr); 894*d1d35e2fSjeremylt ierr = CeedBasisGetGrad(basis_in, &grad_in); CeedChkBackend(ierr); 895*d1d35e2fSjeremylt ierr = CeedBasisGetGrad(basis_out, &grad_out); CeedChkBackend(ierr); 896dfffd467Sjeremylt // Compute the diagonal of B^T D B 897dfffd467Sjeremylt // Each element 898*d1d35e2fSjeremylt const CeedScalar qf_value_bound = max_norm*1e-12; 899*d1d35e2fSjeremylt for (CeedInt e=0; e<num_elem; e++) { 900*d1d35e2fSjeremylt CeedInt d_out = -1; 9017172caadSjeremylt // Each basis eval mode pair 902*d1d35e2fSjeremylt for (CeedInt e_out=0; e_out<num_eval_mode_out; e_out++) { 9036c58de82SJeremy L Thompson const CeedScalar *bt = NULL; 904*d1d35e2fSjeremylt if (eval_mode_out[e_out] == CEED_EVAL_GRAD) 905*d1d35e2fSjeremylt d_out += 1; 906*d1d35e2fSjeremylt CeedOperatorGetBasisPointer_Ref(&bt, eval_mode_out[e_out], identity, interp_out, 907*d1d35e2fSjeremylt &grad_out[d_out*num_qpts*num_nodes]); 908*d1d35e2fSjeremylt CeedInt d_in = -1; 909*d1d35e2fSjeremylt for (CeedInt e_in=0; e_in<num_eval_mode_in; e_in++) { 9106c58de82SJeremy L Thompson const CeedScalar *b = NULL; 911*d1d35e2fSjeremylt if (eval_mode_in[e_in] == CEED_EVAL_GRAD) 912*d1d35e2fSjeremylt d_in += 1; 913*d1d35e2fSjeremylt CeedOperatorGetBasisPointer_Ref(&b, eval_mode_in[e_in], identity, interp_in, 914*d1d35e2fSjeremylt &grad_in[d_in*num_qpts*num_nodes]); 915efcf4563Sjeremylt // Each component 916*d1d35e2fSjeremylt for (CeedInt c_out=0; c_out<num_comp; c_out++) 917dfffd467Sjeremylt // Each qpoint/node pair 918*d1d35e2fSjeremylt for (CeedInt q=0; q<num_qpts; q++) 919*d1d35e2fSjeremylt if (is_pointblock) { 920d965c7a7SJeremy L Thompson // Point Block Diagonal 921*d1d35e2fSjeremylt for (CeedInt c_in=0; c_in<num_comp; c_in++) { 922*d1d35e2fSjeremylt const CeedScalar qf_value = 923*d1d35e2fSjeremylt assembled_qf_array[((((e*num_eval_mode_in+e_in)*num_comp+c_in)* 924*d1d35e2fSjeremylt num_eval_mode_out+e_out)*num_comp+c_out)*num_qpts+q]; 925*d1d35e2fSjeremylt if (fabs(qf_value) > qf_value_bound) 926*d1d35e2fSjeremylt for (CeedInt n=0; n<num_nodes; n++) 927*d1d35e2fSjeremylt elem_diag_array[((e*num_comp+c_out)*num_comp+c_in)*num_nodes+n] += 928*d1d35e2fSjeremylt bt[q*num_nodes+n] * qf_value * b[q*num_nodes+n]; 929d965c7a7SJeremy L Thompson } 930d965c7a7SJeremy L Thompson } else { 931d965c7a7SJeremy L Thompson // Diagonal Only 932*d1d35e2fSjeremylt const CeedScalar qf_value = 933*d1d35e2fSjeremylt assembled_qf_array[((((e*num_eval_mode_in+e_in)*num_comp+c_out)* 934*d1d35e2fSjeremylt num_eval_mode_out+e_out)*num_comp+c_out)*num_qpts+q]; 935*d1d35e2fSjeremylt if (fabs(qf_value) > qf_value_bound) 936*d1d35e2fSjeremylt for (CeedInt n=0; n<num_nodes; n++) 937*d1d35e2fSjeremylt elem_diag_array[(e*num_comp+c_out)*num_nodes+n] += 938*d1d35e2fSjeremylt bt[q*num_nodes+n] * qf_value * b[q*num_nodes+n]; 9394ff7492eSjeremylt } 9407172caadSjeremylt } 9417172caadSjeremylt } 9427172caadSjeremylt } 943*d1d35e2fSjeremylt ierr = CeedVectorRestoreArray(elem_diag, &elem_diag_array); 944*d1d35e2fSjeremylt CeedChkBackend(ierr); 945*d1d35e2fSjeremylt ierr = CeedVectorRestoreArray(assembled_qf, &assembled_qf_array); 946e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 9477172caadSjeremylt 9487172caadSjeremylt // Assemble local operator diagonal 949*d1d35e2fSjeremylt ierr = CeedElemRestrictionApply(diag_rstr, CEED_TRANSPOSE, elem_diag, 950e15f9bd0SJeremy L Thompson assembled, request); CeedChkBackend(ierr); 9517172caadSjeremylt 9527172caadSjeremylt // Cleanup 953*d1d35e2fSjeremylt if (is_pointblock) { 954*d1d35e2fSjeremylt ierr = CeedElemRestrictionDestroy(&diag_rstr); CeedChkBackend(ierr); 955d965c7a7SJeremy L Thompson } 956*d1d35e2fSjeremylt ierr = CeedVectorDestroy(&assembled_qf); CeedChkBackend(ierr); 957*d1d35e2fSjeremylt ierr = CeedVectorDestroy(&elem_diag); CeedChkBackend(ierr); 958*d1d35e2fSjeremylt ierr = CeedFree(&eval_mode_in); CeedChkBackend(ierr); 959*d1d35e2fSjeremylt ierr = CeedFree(&eval_mode_out); CeedChkBackend(ierr); 960e15f9bd0SJeremy L Thompson ierr = CeedFree(&identity); CeedChkBackend(ierr); 9617172caadSjeremylt 962e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 9637172caadSjeremylt } 9647172caadSjeremylt 965f10650afSjeremylt //------------------------------------------------------------------------------ 966c04a41a7SJeremy L Thompson // Assemble composite diagonal common code 967c04a41a7SJeremy L Thompson //------------------------------------------------------------------------------ 96869af5e5fSJeremy L Thompson static inline int CeedOperatorLinearAssembleAddDiagonalCompositeCore_Ref( 9692bba3ffaSJeremy L Thompson CeedOperator op, CeedVector assembled, CeedRequest *request, 970*d1d35e2fSjeremylt const bool is_pointblock) { 971c04a41a7SJeremy L Thompson int ierr; 972*d1d35e2fSjeremylt CeedInt num_sub; 973*d1d35e2fSjeremylt CeedOperator *suboperators; 974*d1d35e2fSjeremylt ierr = CeedOperatorGetNumSub(op, &num_sub); CeedChkBackend(ierr); 975*d1d35e2fSjeremylt ierr = CeedOperatorGetSubList(op, &suboperators); CeedChkBackend(ierr); 976*d1d35e2fSjeremylt for (CeedInt i = 0; i < num_sub; i++) { 977*d1d35e2fSjeremylt ierr = CeedOperatorAssembleAddDiagonalCore_Ref(suboperators[i], assembled, 978*d1d35e2fSjeremylt request, is_pointblock); CeedChkBackend(ierr); 979c04a41a7SJeremy L Thompson } 980e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 981c04a41a7SJeremy L Thompson } 982c04a41a7SJeremy L Thompson 983c04a41a7SJeremy L Thompson //------------------------------------------------------------------------------ 984d965c7a7SJeremy L Thompson // Assemble Linear Diagonal 985d965c7a7SJeremy L Thompson //------------------------------------------------------------------------------ 98669af5e5fSJeremy L Thompson static int CeedOperatorLinearAssembleAddDiagonal_Ref(CeedOperator op, 9872bba3ffaSJeremy L Thompson CeedVector assembled, CeedRequest *request) { 988c04a41a7SJeremy L Thompson int ierr; 989*d1d35e2fSjeremylt bool is_composite; 990*d1d35e2fSjeremylt ierr = CeedOperatorIsComposite(op, &is_composite); CeedChkBackend(ierr); 991*d1d35e2fSjeremylt if (is_composite) { 99269af5e5fSJeremy L Thompson return CeedOperatorLinearAssembleAddDiagonalCompositeCore_Ref(op, assembled, 993c04a41a7SJeremy L Thompson request, false); 994c04a41a7SJeremy L Thompson } else { 99569af5e5fSJeremy L Thompson return CeedOperatorAssembleAddDiagonalCore_Ref(op, assembled, request, false); 996c04a41a7SJeremy L Thompson } 997d965c7a7SJeremy L Thompson } 998d965c7a7SJeremy L Thompson 999d965c7a7SJeremy L Thompson //------------------------------------------------------------------------------ 1000d965c7a7SJeremy L Thompson // Assemble Linear Point Block Diagonal 1001d965c7a7SJeremy L Thompson //------------------------------------------------------------------------------ 100269af5e5fSJeremy L Thompson static int CeedOperatorLinearAssembleAddPointBlockDiagonal_Ref(CeedOperator op, 10032bba3ffaSJeremy L Thompson CeedVector assembled, CeedRequest *request) { 1004c04a41a7SJeremy L Thompson int ierr; 1005*d1d35e2fSjeremylt bool is_composite; 1006*d1d35e2fSjeremylt ierr = CeedOperatorIsComposite(op, &is_composite); CeedChkBackend(ierr); 1007*d1d35e2fSjeremylt if (is_composite) { 100869af5e5fSJeremy L Thompson return CeedOperatorLinearAssembleAddDiagonalCompositeCore_Ref(op, assembled, 1009c04a41a7SJeremy L Thompson request, true); 1010c04a41a7SJeremy L Thompson } else { 101169af5e5fSJeremy L Thompson return CeedOperatorAssembleAddDiagonalCore_Ref(op, assembled, request, true); 1012c04a41a7SJeremy L Thompson } 1013d965c7a7SJeremy L Thompson } 1014d965c7a7SJeremy L Thompson 1015d965c7a7SJeremy L Thompson //------------------------------------------------------------------------------ 1016713f43c3Sjeremylt // Create FDM Element Inverse 1017f10650afSjeremylt //------------------------------------------------------------------------------ 1018713f43c3Sjeremylt int CeedOperatorCreateFDMElementInverse_Ref(CeedOperator op, 1019*d1d35e2fSjeremylt CeedOperator *fdm_inv, CeedRequest *request) { 1020713f43c3Sjeremylt int ierr; 1021*d1d35e2fSjeremylt Ceed ceed, ceed_parent; 1022e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChkBackend(ierr); 1023*d1d35e2fSjeremylt ierr = CeedGetOperatorFallbackParentCeed(ceed, &ceed_parent); 1024e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1025*d1d35e2fSjeremylt ceed_parent = ceed_parent ? ceed_parent : ceed; 1026713f43c3Sjeremylt CeedQFunction qf; 1027e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetQFunction(op, &qf); CeedChkBackend(ierr); 1028713f43c3Sjeremylt 1029713f43c3Sjeremylt // Determine active input basis 1030713f43c3Sjeremylt bool interp = false, grad = false; 1031713f43c3Sjeremylt CeedBasis basis = NULL; 1032713f43c3Sjeremylt CeedElemRestriction rstr = NULL; 1033*d1d35e2fSjeremylt CeedOperatorField *op_fields; 1034*d1d35e2fSjeremylt CeedQFunctionField *qf_fields; 1035*d1d35e2fSjeremylt ierr = CeedOperatorGetFields(op, &op_fields, NULL); CeedChkBackend(ierr); 1036*d1d35e2fSjeremylt ierr = CeedQFunctionGetFields(qf, &qf_fields, NULL); CeedChkBackend(ierr); 1037*d1d35e2fSjeremylt CeedInt num_input_fields; 1038*d1d35e2fSjeremylt ierr = CeedQFunctionGetNumArgs(qf, &num_input_fields, NULL); 1039*d1d35e2fSjeremylt CeedChkBackend(ierr); 1040*d1d35e2fSjeremylt for (CeedInt i=0; i<num_input_fields; i++) { 1041713f43c3Sjeremylt CeedVector vec; 1042*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetVector(op_fields[i], &vec); CeedChkBackend(ierr); 1043713f43c3Sjeremylt if (vec == CEED_VECTOR_ACTIVE) { 1044*d1d35e2fSjeremylt CeedEvalMode eval_mode; 1045*d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_fields[i], &eval_mode); 1046*d1d35e2fSjeremylt CeedChkBackend(ierr); 1047*d1d35e2fSjeremylt interp = interp || eval_mode == CEED_EVAL_INTERP; 1048*d1d35e2fSjeremylt grad = grad || eval_mode == CEED_EVAL_GRAD; 1049*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(op_fields[i], &basis); CeedChkBackend(ierr); 1050*d1d35e2fSjeremylt ierr = CeedOperatorFieldGetElemRestriction(op_fields[i], &rstr); 1051e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1052713f43c3Sjeremylt } 1053713f43c3Sjeremylt } 1054713f43c3Sjeremylt if (!basis) 1055d9995aecSjeremylt // LCOV_EXCL_START 1056e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "No active field set"); 1057d9995aecSjeremylt // LCOV_EXCL_STOP 1058*d1d35e2fSjeremylt CeedInt P_1d, Q_1d, elem_size, num_qpts, dim, num_comp = 1, num_elem = 1, 1059*d1d35e2fSjeremylt l_size = 1; 1060*d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes1D(basis, &P_1d); CeedChkBackend(ierr); 1061*d1d35e2fSjeremylt ierr = CeedBasisGetNumNodes(basis, &elem_size); CeedChkBackend(ierr); 1062*d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints1D(basis, &Q_1d); CeedChkBackend(ierr); 1063*d1d35e2fSjeremylt ierr = CeedBasisGetNumQuadraturePoints(basis, &num_qpts); CeedChkBackend(ierr); 1064e15f9bd0SJeremy L Thompson ierr = CeedBasisGetDimension(basis, &dim); CeedChkBackend(ierr); 1065*d1d35e2fSjeremylt ierr = CeedBasisGetNumComponents(basis, &num_comp); CeedChkBackend(ierr); 1066*d1d35e2fSjeremylt ierr = CeedElemRestrictionGetNumElements(rstr, &num_elem); CeedChkBackend(ierr); 1067*d1d35e2fSjeremylt ierr = CeedElemRestrictionGetLVectorSize(rstr, &l_size); CeedChkBackend(ierr); 1068713f43c3Sjeremylt 1069713f43c3Sjeremylt // Build and diagonalize 1D Mass and Laplacian 1070*d1d35e2fSjeremylt bool tensor_basis; 1071*d1d35e2fSjeremylt ierr = CeedBasisIsTensor(basis, &tensor_basis); CeedChkBackend(ierr); 1072*d1d35e2fSjeremylt if (!tensor_basis) 1073d9995aecSjeremylt // LCOV_EXCL_START 1074e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 1075e15f9bd0SJeremy L Thompson "FDMElementInverse only supported for tensor " 1076713f43c3Sjeremylt "bases"); 1077d9995aecSjeremylt // LCOV_EXCL_STOP 1078713f43c3Sjeremylt CeedScalar *work, *mass, *laplace, *x, *x2, *lambda; 1079*d1d35e2fSjeremylt ierr = CeedMalloc(Q_1d*P_1d, &work); CeedChkBackend(ierr); 1080*d1d35e2fSjeremylt ierr = CeedMalloc(P_1d*P_1d, &mass); CeedChkBackend(ierr); 1081*d1d35e2fSjeremylt ierr = CeedMalloc(P_1d*P_1d, &laplace); CeedChkBackend(ierr); 1082*d1d35e2fSjeremylt ierr = CeedMalloc(P_1d*P_1d, &x); CeedChkBackend(ierr); 1083*d1d35e2fSjeremylt ierr = CeedMalloc(P_1d*P_1d, &x2); CeedChkBackend(ierr); 1084*d1d35e2fSjeremylt ierr = CeedMalloc(P_1d, &lambda); CeedChkBackend(ierr); 1085713f43c3Sjeremylt // -- Mass 1086*d1d35e2fSjeremylt const CeedScalar *interp_1d, *grad_1d, *q_weight_1d; 1087*d1d35e2fSjeremylt ierr = CeedBasisGetInterp1D(basis, &interp_1d); CeedChkBackend(ierr); 1088*d1d35e2fSjeremylt ierr = CeedBasisGetGrad1D(basis, &grad_1d); CeedChkBackend(ierr); 1089*d1d35e2fSjeremylt ierr = CeedBasisGetQWeights(basis, &q_weight_1d); CeedChkBackend(ierr); 1090*d1d35e2fSjeremylt for (CeedInt i=0; i<Q_1d; i++) 1091*d1d35e2fSjeremylt for (CeedInt j=0; j<P_1d; j++) 1092*d1d35e2fSjeremylt work[i+j*Q_1d] = interp_1d[i*P_1d+j]*q_weight_1d[i]; 10939289e5bfSjeremylt ierr = CeedMatrixMultiply(ceed, (const CeedScalar *)work, 1094*d1d35e2fSjeremylt (const CeedScalar *)interp_1d, mass, P_1d, P_1d, Q_1d); 1095e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1096713f43c3Sjeremylt // -- Laplacian 1097*d1d35e2fSjeremylt for (CeedInt i=0; i<Q_1d; i++) 1098*d1d35e2fSjeremylt for (CeedInt j=0; j<P_1d; j++) 1099*d1d35e2fSjeremylt work[i+j*Q_1d] = grad_1d[i*P_1d+j]*q_weight_1d[i]; 11009289e5bfSjeremylt ierr = CeedMatrixMultiply(ceed, (const CeedScalar *)work, 1101*d1d35e2fSjeremylt (const CeedScalar *)grad_1d, laplace, P_1d, P_1d, Q_1d); 1102e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1103713f43c3Sjeremylt // -- Diagonalize 1104*d1d35e2fSjeremylt ierr = CeedSimultaneousDiagonalization(ceed, laplace, mass, x, lambda, P_1d); 1105e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1106e15f9bd0SJeremy L Thompson ierr = CeedFree(&work); CeedChkBackend(ierr); 1107e15f9bd0SJeremy L Thompson ierr = CeedFree(&mass); CeedChkBackend(ierr); 1108e15f9bd0SJeremy L Thompson ierr = CeedFree(&laplace); CeedChkBackend(ierr); 1109*d1d35e2fSjeremylt for (CeedInt i=0; i<P_1d; i++) 1110*d1d35e2fSjeremylt for (CeedInt j=0; j<P_1d; j++) 1111*d1d35e2fSjeremylt x2[i+j*P_1d] = x[j+i*P_1d]; 1112e15f9bd0SJeremy L Thompson ierr = CeedFree(&x); CeedChkBackend(ierr); 1113713f43c3Sjeremylt 1114713f43c3Sjeremylt // Assemble QFunction 1115713f43c3Sjeremylt CeedVector assembled; 1116713f43c3Sjeremylt CeedElemRestriction rstr_qf; 111780ac2e43SJeremy L Thompson ierr = CeedOperatorLinearAssembleQFunction(op, &assembled, &rstr_qf, 1118e15f9bd0SJeremy L Thompson request); CeedChkBackend(ierr); 1119e15f9bd0SJeremy L Thompson ierr = CeedElemRestrictionDestroy(&rstr_qf); CeedChkBackend(ierr); 1120*d1d35e2fSjeremylt CeedScalar max_norm = 0; 1121*d1d35e2fSjeremylt ierr = CeedVectorNorm(assembled, CEED_NORM_MAX, &max_norm); 1122*d1d35e2fSjeremylt CeedChkBackend(ierr); 1123713f43c3Sjeremylt 1124713f43c3Sjeremylt // Calculate element averages 1125*d1d35e2fSjeremylt CeedInt num_fields = ((interp?1:0) + (grad?dim:0))*((interp?1:0) + 1126*d1d35e2fSjeremylt (grad?dim:0)); 1127*d1d35e2fSjeremylt CeedScalar *elem_avg; 1128*d1d35e2fSjeremylt const CeedScalar *assembledarray, *q_weight_array; 1129*d1d35e2fSjeremylt CeedVector q_weight; 1130*d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed_parent, num_qpts, &q_weight); CeedChkBackend(ierr); 1131713f43c3Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, CEED_EVAL_WEIGHT, 1132*d1d35e2fSjeremylt CEED_VECTOR_NONE, q_weight); CeedChkBackend(ierr); 1133713f43c3Sjeremylt ierr = CeedVectorGetArrayRead(assembled, CEED_MEM_HOST, &assembledarray); 1134e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1135*d1d35e2fSjeremylt ierr = CeedVectorGetArrayRead(q_weight, CEED_MEM_HOST, &q_weight_array); 1136e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1137*d1d35e2fSjeremylt ierr = CeedCalloc(num_elem, &elem_avg); CeedChkBackend(ierr); 1138*d1d35e2fSjeremylt for (CeedInt e=0; e<num_elem; e++) { 1139713f43c3Sjeremylt CeedInt count = 0; 1140*d1d35e2fSjeremylt for (CeedInt q=0; q<num_qpts; q++) 1141*d1d35e2fSjeremylt for (CeedInt i=0; i<num_comp*num_comp*num_fields; i++) 1142*d1d35e2fSjeremylt if (fabs(assembledarray[e*num_elem*num_qpts*num_comp*num_comp*num_fields + 1143*d1d35e2fSjeremylt i*num_qpts + q]) > max_norm*1e-12) { 1144*d1d35e2fSjeremylt elem_avg[e] += assembledarray[e*num_elem*num_qpts*num_comp*num_comp*num_fields + 1145*d1d35e2fSjeremylt i*num_qpts + q] / q_weight_array[q]; 1146713f43c3Sjeremylt count++; 1147713f43c3Sjeremylt } 1148713f43c3Sjeremylt if (count) 1149*d1d35e2fSjeremylt elem_avg[e] /= count; 1150713f43c3Sjeremylt } 1151e15f9bd0SJeremy L Thompson ierr = CeedVectorRestoreArrayRead(assembled, &assembledarray); 1152e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1153e15f9bd0SJeremy L Thompson ierr = CeedVectorDestroy(&assembled); CeedChkBackend(ierr); 1154*d1d35e2fSjeremylt ierr = CeedVectorRestoreArrayRead(q_weight, &q_weight_array); 1155e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1156*d1d35e2fSjeremylt ierr = CeedVectorDestroy(&q_weight); CeedChkBackend(ierr); 1157713f43c3Sjeremylt 1158713f43c3Sjeremylt // Build FDM diagonal 1159*d1d35e2fSjeremylt CeedVector q_data; 1160*d1d35e2fSjeremylt CeedScalar *q_data_array; 1161*d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed_parent, num_elem*num_comp*l_size, &q_data); 1162e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1163*d1d35e2fSjeremylt ierr = CeedVectorSetArray(q_data, CEED_MEM_HOST, CEED_COPY_VALUES, NULL); 1164e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1165*d1d35e2fSjeremylt ierr = CeedVectorGetArray(q_data, CEED_MEM_HOST, &q_data_array); 1166e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1167*d1d35e2fSjeremylt for (CeedInt e=0; e<num_elem; e++) 1168*d1d35e2fSjeremylt for (CeedInt c=0; c<num_comp; c++) 1169*d1d35e2fSjeremylt for (CeedInt n=0; n<l_size; n++) { 1170713f43c3Sjeremylt if (interp) 1171*d1d35e2fSjeremylt q_data_array[(e*num_comp+c)*l_size+n] = 1; 1172713f43c3Sjeremylt if (grad) 1173713f43c3Sjeremylt for (CeedInt d=0; d<dim; d++) { 1174*d1d35e2fSjeremylt CeedInt i = (n / CeedIntPow(P_1d, d)) % P_1d; 1175*d1d35e2fSjeremylt q_data_array[(e*num_comp+c)*l_size+n] += lambda[i]; 1176713f43c3Sjeremylt } 1177*d1d35e2fSjeremylt q_data_array[(e*num_comp+c)*l_size+n] = 1 / (elem_avg[e] * 1178*d1d35e2fSjeremylt q_data_array[(e*num_comp+c)*l_size+n]); 1179713f43c3Sjeremylt } 1180*d1d35e2fSjeremylt ierr = CeedFree(&elem_avg); CeedChkBackend(ierr); 1181*d1d35e2fSjeremylt ierr = CeedVectorRestoreArray(q_data, &q_data_array); CeedChkBackend(ierr); 1182713f43c3Sjeremylt 1183713f43c3Sjeremylt // Setup FDM operator 1184713f43c3Sjeremylt // -- Basis 1185713f43c3Sjeremylt CeedBasis fdm_basis; 1186*d1d35e2fSjeremylt CeedScalar *grad_dummy, *q_ref_dummy, *q_weight_dummy; 1187*d1d35e2fSjeremylt ierr = CeedCalloc(P_1d*P_1d, &grad_dummy); CeedChkBackend(ierr); 1188*d1d35e2fSjeremylt ierr = CeedCalloc(P_1d, &q_ref_dummy); CeedChkBackend(ierr); 1189*d1d35e2fSjeremylt ierr = CeedCalloc(P_1d, &q_weight_dummy); CeedChkBackend(ierr); 1190*d1d35e2fSjeremylt ierr = CeedBasisCreateTensorH1(ceed_parent, dim, num_comp, P_1d, P_1d, x2, 1191*d1d35e2fSjeremylt grad_dummy, q_ref_dummy, q_weight_dummy, 1192e15f9bd0SJeremy L Thompson &fdm_basis); CeedChkBackend(ierr); 1193*d1d35e2fSjeremylt ierr = CeedFree(&grad_dummy); CeedChkBackend(ierr); 1194*d1d35e2fSjeremylt ierr = CeedFree(&q_ref_dummy); CeedChkBackend(ierr); 1195*d1d35e2fSjeremylt ierr = CeedFree(&q_weight_dummy); CeedChkBackend(ierr); 1196e15f9bd0SJeremy L Thompson ierr = CeedFree(&x2); CeedChkBackend(ierr); 1197e15f9bd0SJeremy L Thompson ierr = CeedFree(&lambda); CeedChkBackend(ierr); 1198713f43c3Sjeremylt 1199713f43c3Sjeremylt // -- Restriction 1200713f43c3Sjeremylt CeedElemRestriction rstr_i; 1201*d1d35e2fSjeremylt CeedInt strides[3] = {1, l_size, l_size*num_comp}; 1202*d1d35e2fSjeremylt ierr = CeedElemRestrictionCreateStrided(ceed_parent, num_elem, l_size, num_comp, 1203*d1d35e2fSjeremylt l_size*num_elem*num_comp, strides, &rstr_i); 1204e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1205713f43c3Sjeremylt // -- QFunction 1206713f43c3Sjeremylt CeedQFunction mass_qf; 1207*d1d35e2fSjeremylt ierr = CeedQFunctionCreateInteriorByName(ceed_parent, "MassApply", &mass_qf); 1208e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1209713f43c3Sjeremylt // -- Operator 1210*d1d35e2fSjeremylt ierr = CeedOperatorCreate(ceed_parent, mass_qf, NULL, NULL, fdm_inv); 1211e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1212*d1d35e2fSjeremylt CeedOperatorSetField(*fdm_inv, "u", rstr_i, fdm_basis, CEED_VECTOR_ACTIVE); 1213e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1214*d1d35e2fSjeremylt CeedOperatorSetField(*fdm_inv, "qdata", rstr_i, CEED_BASIS_COLLOCATED, q_data); 1215e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1216*d1d35e2fSjeremylt CeedOperatorSetField(*fdm_inv, "v", rstr_i, fdm_basis, CEED_VECTOR_ACTIVE); 1217e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1218713f43c3Sjeremylt 1219713f43c3Sjeremylt // Cleanup 1220*d1d35e2fSjeremylt ierr = CeedVectorDestroy(&q_data); CeedChkBackend(ierr); 1221e15f9bd0SJeremy L Thompson ierr = CeedBasisDestroy(&fdm_basis); CeedChkBackend(ierr); 1222e15f9bd0SJeremy L Thompson ierr = CeedElemRestrictionDestroy(&rstr_i); CeedChkBackend(ierr); 1223e15f9bd0SJeremy L Thompson ierr = CeedQFunctionDestroy(&mass_qf); CeedChkBackend(ierr); 1224713f43c3Sjeremylt 1225e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1226713f43c3Sjeremylt } 1227713f43c3Sjeremylt 1228f10650afSjeremylt //------------------------------------------------------------------------------ 1229f10650afSjeremylt // Operator Destroy 1230f10650afSjeremylt //------------------------------------------------------------------------------ 1231f10650afSjeremylt static int CeedOperatorDestroy_Ref(CeedOperator op) { 1232f10650afSjeremylt int ierr; 1233f10650afSjeremylt CeedOperator_Ref *impl; 1234e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetData(op, &impl); CeedChkBackend(ierr); 1235f10650afSjeremylt 1236*d1d35e2fSjeremylt for (CeedInt i=0; i<impl->num_e_vecs_in+impl->num_e_vecs_out; i++) { 1237*d1d35e2fSjeremylt ierr = CeedVectorDestroy(&impl->e_vecs[i]); CeedChkBackend(ierr); 1238f10650afSjeremylt } 1239*d1d35e2fSjeremylt ierr = CeedFree(&impl->e_vecs); CeedChkBackend(ierr); 1240*d1d35e2fSjeremylt ierr = CeedFree(&impl->e_data); CeedChkBackend(ierr); 1241*d1d35e2fSjeremylt ierr = CeedFree(&impl->input_state); CeedChkBackend(ierr); 1242f10650afSjeremylt 1243*d1d35e2fSjeremylt for (CeedInt i=0; i<impl->num_e_vecs_in; i++) { 1244*d1d35e2fSjeremylt ierr = CeedVectorDestroy(&impl->e_vecs_in[i]); CeedChkBackend(ierr); 1245*d1d35e2fSjeremylt ierr = CeedVectorDestroy(&impl->q_vecs_in[i]); CeedChkBackend(ierr); 1246f10650afSjeremylt } 1247*d1d35e2fSjeremylt ierr = CeedFree(&impl->e_vecs_in); CeedChkBackend(ierr); 1248*d1d35e2fSjeremylt ierr = CeedFree(&impl->q_vecs_in); CeedChkBackend(ierr); 1249f10650afSjeremylt 1250*d1d35e2fSjeremylt for (CeedInt i=0; i<impl->num_e_vecs_out; i++) { 1251*d1d35e2fSjeremylt ierr = CeedVectorDestroy(&impl->e_vecs_out[i]); CeedChkBackend(ierr); 1252*d1d35e2fSjeremylt ierr = CeedVectorDestroy(&impl->q_vecs_out[i]); CeedChkBackend(ierr); 1253f10650afSjeremylt } 1254*d1d35e2fSjeremylt ierr = CeedFree(&impl->e_vecs_out); CeedChkBackend(ierr); 1255*d1d35e2fSjeremylt ierr = CeedFree(&impl->q_vecs_out); CeedChkBackend(ierr); 1256f10650afSjeremylt 1257e15f9bd0SJeremy L Thompson ierr = CeedFree(&impl); CeedChkBackend(ierr); 1258e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1259f10650afSjeremylt } 1260f10650afSjeremylt 1261f10650afSjeremylt //------------------------------------------------------------------------------ 1262713f43c3Sjeremylt // Operator Create 1263f10650afSjeremylt //------------------------------------------------------------------------------ 126421617c04Sjeremylt int CeedOperatorCreate_Ref(CeedOperator op) { 126521617c04Sjeremylt int ierr; 1266fe2413ffSjeremylt Ceed ceed; 1267e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChkBackend(ierr); 12684ce2993fSjeremylt CeedOperator_Ref *impl; 126921617c04Sjeremylt 1270e15f9bd0SJeremy L Thompson ierr = CeedCalloc(1, &impl); CeedChkBackend(ierr); 1271e15f9bd0SJeremy L Thompson ierr = CeedOperatorSetData(op, impl); CeedChkBackend(ierr); 1272fe2413ffSjeremylt 127380ac2e43SJeremy L Thompson ierr = CeedSetBackendFunction(ceed, "Operator", op, "LinearAssembleQFunction", 127480ac2e43SJeremy L Thompson CeedOperatorLinearAssembleQFunction_Ref); 1275e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 12769e9210b8SJeremy L Thompson ierr = CeedSetBackendFunction(ceed, "Operator", op, "LinearAssembleAddDiagonal", 127769af5e5fSJeremy L Thompson CeedOperatorLinearAssembleAddDiagonal_Ref); 1278e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1279d965c7a7SJeremy L Thompson ierr = CeedSetBackendFunction(ceed, "Operator", op, 12809e9210b8SJeremy L Thompson "LinearAssembleAddPointBlockDiagonal", 128169af5e5fSJeremy L Thompson CeedOperatorLinearAssembleAddPointBlockDiagonal_Ref); 1282e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1283713f43c3Sjeremylt ierr = CeedSetBackendFunction(ceed, "Operator", op, "CreateFDMElementInverse", 1284713f43c3Sjeremylt CeedOperatorCreateFDMElementInverse_Ref); 1285e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1286cae8b89aSjeremylt ierr = CeedSetBackendFunction(ceed, "Operator", op, "ApplyAdd", 1287e15f9bd0SJeremy L Thompson CeedOperatorApplyAdd_Ref); CeedChkBackend(ierr); 1288fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Operator", op, "Destroy", 1289e15f9bd0SJeremy L Thompson CeedOperatorDestroy_Ref); CeedChkBackend(ierr); 1290e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 129121617c04Sjeremylt } 1292c04a41a7SJeremy L Thompson 1293c04a41a7SJeremy L Thompson //------------------------------------------------------------------------------ 1294c04a41a7SJeremy L Thompson // Composite Operator Create 1295c04a41a7SJeremy L Thompson //------------------------------------------------------------------------------ 1296c04a41a7SJeremy L Thompson int CeedCompositeOperatorCreate_Ref(CeedOperator op) { 1297c04a41a7SJeremy L Thompson int ierr; 1298c04a41a7SJeremy L Thompson Ceed ceed; 1299e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChkBackend(ierr); 13009e9210b8SJeremy L Thompson ierr = CeedSetBackendFunction(ceed, "Operator", op, "LinearAssembleAddDiagonal", 130169af5e5fSJeremy L Thompson CeedOperatorLinearAssembleAddDiagonal_Ref); 1302e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1303c04a41a7SJeremy L Thompson ierr = CeedSetBackendFunction(ceed, "Operator", op, 13049e9210b8SJeremy L Thompson "LinearAssembleAddPointBlockDiagonal", 130569af5e5fSJeremy L Thompson CeedOperatorLinearAssembleAddPointBlockDiagonal_Ref); 1306e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1307e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 1308c04a41a7SJeremy L Thompson } 1309f10650afSjeremylt //------------------------------------------------------------------------------ 1310