1*3d8e8822SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors. 2*3d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 321617c04Sjeremylt // 4*3d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause 521617c04Sjeremylt // 6*3d8e8822SJeremy L Thompson // This file is part of CEED: http://github.com/ceed 721617c04Sjeremylt 8ec3da8bcSJed Brown #include <ceed/ceed.h> 9ec3da8bcSJed Brown #include <ceed/backend.h> 103d576824SJeremy L Thompson #include <math.h> 113d576824SJeremy L Thompson #include <stdbool.h> 123d576824SJeremy L Thompson #include <stddef.h> 133d576824SJeremy L Thompson #include <stdint.h> 1421617c04Sjeremylt #include "ceed-ref.h" 1521617c04Sjeremylt 16f10650afSjeremylt //------------------------------------------------------------------------------ 17f10650afSjeremylt // Setup Input/Output Fields 18f10650afSjeremylt //------------------------------------------------------------------------------ 19fe2413ffSjeremylt static int CeedOperatorSetupFields_Ref(CeedQFunction qf, CeedOperator op, 204fc1f125SJeremy L Thompson bool is_input, CeedVector *e_vecs_full, 214fc1f125SJeremy L Thompson CeedVector *e_vecs, CeedVector *q_vecs, 224fc1f125SJeremy L Thompson CeedInt start_e, CeedInt num_fields, 234fc1f125SJeremy L Thompson CeedInt Q) { 24ebbcc8a3SJeremy L Thompson CeedInt ierr, num_comp, size, P; 25aedaa0e5Sjeremylt Ceed ceed; 26e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChkBackend(ierr); 27d1bcdac9Sjeremylt CeedBasis basis; 28d1d35e2fSjeremylt CeedElemRestriction elem_restr; 29d1d35e2fSjeremylt CeedOperatorField *op_fields; 30d1d35e2fSjeremylt CeedQFunctionField *qf_fields; 314fc1f125SJeremy L Thompson if (is_input) { 327e7773b5SJeremy L Thompson ierr = CeedOperatorGetFields(op, NULL, &op_fields, NULL, NULL); 337e7773b5SJeremy L Thompson CeedChkBackend(ierr); 347e7773b5SJeremy L Thompson ierr = CeedQFunctionGetFields(qf, NULL, &qf_fields, NULL, NULL); 357e7773b5SJeremy L Thompson CeedChkBackend(ierr); 364fc1f125SJeremy L Thompson } else { 374fc1f125SJeremy L Thompson ierr = CeedOperatorGetFields(op, NULL, NULL, NULL, &op_fields); 384fc1f125SJeremy L Thompson CeedChkBackend(ierr); 394fc1f125SJeremy L Thompson ierr = CeedQFunctionGetFields(qf, NULL, NULL, NULL, &qf_fields); 404fc1f125SJeremy L Thompson CeedChkBackend(ierr); 41fe2413ffSjeremylt } 4221617c04Sjeremylt 43885ac19cSjeremylt // Loop over fields 44d1d35e2fSjeremylt for (CeedInt i=0; i<num_fields; i++) { 45d1d35e2fSjeremylt CeedEvalMode eval_mode; 46d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_fields[i], &eval_mode); 47e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 48d1d35e2fSjeremylt 49d1d35e2fSjeremylt if (eval_mode != CEED_EVAL_WEIGHT) { 50d1d35e2fSjeremylt ierr = CeedOperatorFieldGetElemRestriction(op_fields[i], &elem_restr); 51d1d35e2fSjeremylt CeedChkBackend(ierr); 52d1d35e2fSjeremylt ierr = CeedElemRestrictionCreateVector(elem_restr, NULL, 534fc1f125SJeremy L Thompson &e_vecs_full[i+start_e]); 54e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 55135a076eSjeremylt } 56135a076eSjeremylt 57d1d35e2fSjeremylt switch(eval_mode) { 58885ac19cSjeremylt case CEED_EVAL_NONE: 59d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetSize(qf_fields[i], &size); CeedChkBackend(ierr); 60d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed, Q*size, &q_vecs[i]); CeedChkBackend(ierr); 61aedaa0e5Sjeremylt break; 62aedaa0e5Sjeremylt case CEED_EVAL_INTERP: 63885ac19cSjeremylt case CEED_EVAL_GRAD: 64d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(op_fields[i], &basis); CeedChkBackend(ierr); 65d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetSize(qf_fields[i], &size); CeedChkBackend(ierr); 66ebbcc8a3SJeremy L Thompson ierr = CeedBasisGetNumNodes(basis, &P); CeedChkBackend(ierr); 67ebbcc8a3SJeremy L Thompson ierr = CeedBasisGetNumComponents(basis, &num_comp); CeedChkBackend(ierr); 68ebbcc8a3SJeremy L Thompson ierr = CeedVectorCreate(ceed, P*num_comp, &e_vecs[i]); CeedChkBackend(ierr); 69d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed, Q*size, &q_vecs[i]); CeedChkBackend(ierr); 70885ac19cSjeremylt break; 71885ac19cSjeremylt case CEED_EVAL_WEIGHT: // Only on input fields 72d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(op_fields[i], &basis); CeedChkBackend(ierr); 73d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed, Q, &q_vecs[i]); CeedChkBackend(ierr); 74d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, CEED_EVAL_WEIGHT, 75d1d35e2fSjeremylt CEED_VECTOR_NONE, q_vecs[i]); CeedChkBackend(ierr); 76885ac19cSjeremylt break; 77885ac19cSjeremylt case CEED_EVAL_DIV: 784d537eeaSYohann break; // Not implemented 79885ac19cSjeremylt case CEED_EVAL_CURL: 804d537eeaSYohann break; // Not implemented 8121617c04Sjeremylt } 82885ac19cSjeremylt } 83e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 8421617c04Sjeremylt } 8521617c04Sjeremylt 86f10650afSjeremylt //------------------------------------------------------------------------------ 87f10650afSjeremylt // Setup Operator 88f10650afSjeremylt //------------------------------------------------------------------------------/* 89885ac19cSjeremylt static int CeedOperatorSetup_Ref(CeedOperator op) { 9021617c04Sjeremylt int ierr; 918c1105f8SJeremy L Thompson bool is_setup_done; 928c1105f8SJeremy L Thompson ierr = CeedOperatorIsSetupDone(op, &is_setup_done); CeedChkBackend(ierr); 938c1105f8SJeremy L Thompson if (is_setup_done) return CEED_ERROR_SUCCESS; 94aedaa0e5Sjeremylt Ceed ceed; 95e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChkBackend(ierr); 964ce2993fSjeremylt CeedOperator_Ref *impl; 97e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetData(op, &impl); CeedChkBackend(ierr); 984ce2993fSjeremylt CeedQFunction qf; 99e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetQFunction(op, &qf); CeedChkBackend(ierr); 100d1d35e2fSjeremylt CeedInt Q, num_input_fields, num_output_fields; 101e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChkBackend(ierr); 1020b454692Sjeremylt ierr = CeedQFunctionIsIdentity(qf, &impl->is_identity_qf); CeedChkBackend(ierr); 103d1d35e2fSjeremylt CeedOperatorField *op_input_fields, *op_output_fields; 1047e7773b5SJeremy L Thompson ierr = CeedOperatorGetFields(op, &num_input_fields, &op_input_fields, 1057e7773b5SJeremy L Thompson &num_output_fields, &op_output_fields); 106e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 107d1d35e2fSjeremylt CeedQFunctionField *qf_input_fields, *qf_output_fields; 1087e7773b5SJeremy L Thompson ierr = CeedQFunctionGetFields(qf, NULL, &qf_input_fields, NULL, 1097e7773b5SJeremy L Thompson &qf_output_fields); 110e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 111885ac19cSjeremylt 112885ac19cSjeremylt // Allocate 1134fc1f125SJeremy L Thompson ierr = CeedCalloc(num_input_fields + num_output_fields, &impl->e_vecs_full); 114e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 115885ac19cSjeremylt 1164fc1f125SJeremy L Thompson ierr = CeedCalloc(CEED_FIELD_MAX, &impl->input_states); CeedChkBackend(ierr); 117bf4cb664SJeremy L Thompson ierr = CeedCalloc(CEED_FIELD_MAX, &impl->e_vecs_in); CeedChkBackend(ierr); 118bf4cb664SJeremy L Thompson ierr = CeedCalloc(CEED_FIELD_MAX, &impl->e_vecs_out); CeedChkBackend(ierr); 119bf4cb664SJeremy L Thompson ierr = CeedCalloc(CEED_FIELD_MAX, &impl->q_vecs_in); CeedChkBackend(ierr); 120bf4cb664SJeremy L Thompson ierr = CeedCalloc(CEED_FIELD_MAX, &impl->q_vecs_out); CeedChkBackend(ierr); 121885ac19cSjeremylt 1224fc1f125SJeremy L Thompson impl->num_inputs = num_input_fields; 1234fc1f125SJeremy L Thompson impl->num_outputs = num_output_fields; 124885ac19cSjeremylt 125d1d35e2fSjeremylt // Set up infield and outfield e_vecs and q_vecs 126885ac19cSjeremylt // Infields 1274fc1f125SJeremy L Thompson ierr = CeedOperatorSetupFields_Ref(qf, op, true, impl->e_vecs_full, 128d1d35e2fSjeremylt impl->e_vecs_in, impl->q_vecs_in, 0, 129d1d35e2fSjeremylt num_input_fields, Q); 130e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 131885ac19cSjeremylt // Outfields 1324fc1f125SJeremy L Thompson ierr = CeedOperatorSetupFields_Ref(qf, op, false, impl->e_vecs_full, 133d1d35e2fSjeremylt impl->e_vecs_out, impl->q_vecs_out, 134d1d35e2fSjeremylt num_input_fields, num_output_fields, Q); 135e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 136885ac19cSjeremylt 13716911fdaSjeremylt // Identity QFunctions 1380b454692Sjeremylt if (impl->is_identity_qf) { 139d1d35e2fSjeremylt CeedEvalMode in_mode, out_mode; 140d1d35e2fSjeremylt CeedQFunctionField *in_fields, *out_fields; 1417e7773b5SJeremy L Thompson ierr = CeedQFunctionGetFields(qf, NULL, &in_fields, NULL, &out_fields); 142e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1430b454692Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(in_fields[0], &in_mode); 144d1d35e2fSjeremylt CeedChkBackend(ierr); 1450b454692Sjeremylt ierr = CeedQFunctionFieldGetEvalMode(out_fields[0], &out_mode); 146d1d35e2fSjeremylt CeedChkBackend(ierr); 147d1d35e2fSjeremylt 1480b454692Sjeremylt if (in_mode == CEED_EVAL_NONE && out_mode == CEED_EVAL_NONE) { 1490b454692Sjeremylt impl->is_identity_restr_op = true; 1500b454692Sjeremylt } else { 1510b454692Sjeremylt ierr = CeedVectorDestroy(&impl->q_vecs_out[0]); CeedChkBackend(ierr); 1520b454692Sjeremylt impl->q_vecs_out[0] = impl->q_vecs_in[0]; 1530b454692Sjeremylt ierr = CeedVectorAddReference(impl->q_vecs_in[0]); CeedChkBackend(ierr); 15416911fdaSjeremylt } 15516911fdaSjeremylt } 15616911fdaSjeremylt 157e15f9bd0SJeremy L Thompson ierr = CeedOperatorSetSetupDone(op); CeedChkBackend(ierr); 158885ac19cSjeremylt 159e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 160885ac19cSjeremylt } 161885ac19cSjeremylt 162f10650afSjeremylt //------------------------------------------------------------------------------ 163f10650afSjeremylt // Setup Operator Inputs 164f10650afSjeremylt //------------------------------------------------------------------------------ 165d1d35e2fSjeremylt static inline int CeedOperatorSetupInputs_Ref(CeedInt num_input_fields, 166d1d35e2fSjeremylt CeedQFunctionField *qf_input_fields, CeedOperatorField *op_input_fields, 1674fc1f125SJeremy L Thompson CeedVector in_vec, const bool skip_active, 1684fc1f125SJeremy L Thompson CeedScalar *e_data_full[2*CEED_FIELD_MAX], 169a0162de9SJeremy L Thompson CeedOperator_Ref *impl, CeedRequest *request) { 1701d102b48SJeremy L Thompson CeedInt ierr; 171d1d35e2fSjeremylt CeedEvalMode eval_mode; 172d1bcdac9Sjeremylt CeedVector vec; 173d1d35e2fSjeremylt CeedElemRestriction elem_restr; 1748d713cf6Sjeremylt uint64_t state; 175885ac19cSjeremylt 176d1d35e2fSjeremylt for (CeedInt i=0; i<num_input_fields; i++) { 177d1bcdac9Sjeremylt // Get input vector 178d1d35e2fSjeremylt ierr = CeedOperatorFieldGetVector(op_input_fields[i], &vec); 179d1d35e2fSjeremylt CeedChkBackend(ierr); 1801d102b48SJeremy L Thompson if (vec == CEED_VECTOR_ACTIVE) { 181d1d35e2fSjeremylt if (skip_active) 1821d102b48SJeremy L Thompson continue; 1831d102b48SJeremy L Thompson else 184d1d35e2fSjeremylt vec = in_vec; 1851d102b48SJeremy L Thompson } 1861d102b48SJeremy L Thompson 187d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_input_fields[i], &eval_mode); 188e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 1891d102b48SJeremy L Thompson // Restrict and Evec 190d1d35e2fSjeremylt if (eval_mode == CEED_EVAL_WEIGHT) { // Skip 1911d102b48SJeremy L Thompson } else { 192668048e2SJed Brown // Restrict 193e15f9bd0SJeremy L Thompson ierr = CeedVectorGetState(vec, &state); CeedChkBackend(ierr); 1948d713cf6Sjeremylt // Skip restriction if input is unchanged 1954fc1f125SJeremy L Thompson if (state != impl->input_states[i] || vec == in_vec) { 196d1d35e2fSjeremylt ierr = CeedOperatorFieldGetElemRestriction(op_input_fields[i], &elem_restr); 197e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 198d1d35e2fSjeremylt ierr = CeedElemRestrictionApply(elem_restr, CEED_NOTRANSPOSE, vec, 1994fc1f125SJeremy L Thompson impl->e_vecs_full[i], request); 2004fc1f125SJeremy L Thompson CeedChkBackend(ierr); 2014fc1f125SJeremy L Thompson impl->input_states[i] = state; 2028d713cf6Sjeremylt } 203668048e2SJed Brown // Get evec 2044fc1f125SJeremy L Thompson ierr = CeedVectorGetArrayRead(impl->e_vecs_full[i], CEED_MEM_HOST, 2054fc1f125SJeremy L Thompson (const CeedScalar **) &e_data_full[i]); 206e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 207885ac19cSjeremylt } 208885ac19cSjeremylt } 209e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 210885ac19cSjeremylt } 211885ac19cSjeremylt 212f10650afSjeremylt //------------------------------------------------------------------------------ 213f10650afSjeremylt // Input Basis Action 214f10650afSjeremylt //------------------------------------------------------------------------------ 2151d102b48SJeremy L Thompson static inline int CeedOperatorInputBasis_Ref(CeedInt e, CeedInt Q, 216d1d35e2fSjeremylt CeedQFunctionField *qf_input_fields, CeedOperatorField *op_input_fields, 217a0162de9SJeremy L Thompson CeedInt num_input_fields, const bool skip_active, 2184fc1f125SJeremy L Thompson CeedScalar *e_data_full[2*CEED_FIELD_MAX], CeedOperator_Ref *impl) { 2191d102b48SJeremy L Thompson CeedInt ierr; 220d1d35e2fSjeremylt CeedInt dim, elem_size, size; 221d1d35e2fSjeremylt CeedElemRestriction elem_restr; 222d1d35e2fSjeremylt CeedEvalMode eval_mode; 2231d102b48SJeremy L Thompson CeedBasis basis; 2241d102b48SJeremy L Thompson 225d1d35e2fSjeremylt for (CeedInt i=0; i<num_input_fields; i++) { 2261d102b48SJeremy L Thompson // Skip active input 227d1d35e2fSjeremylt if (skip_active) { 2281d102b48SJeremy L Thompson CeedVector vec; 229d1d35e2fSjeremylt ierr = CeedOperatorFieldGetVector(op_input_fields[i], &vec); 230d1d35e2fSjeremylt CeedChkBackend(ierr); 2311d102b48SJeremy L Thompson if (vec == CEED_VECTOR_ACTIVE) 2321d102b48SJeremy L Thompson continue; 2331d102b48SJeremy L Thompson } 234d1d35e2fSjeremylt // Get elem_size, eval_mode, size 235d1d35e2fSjeremylt ierr = CeedOperatorFieldGetElemRestriction(op_input_fields[i], &elem_restr); 236e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 237d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(elem_restr, &elem_size); 238e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 239d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_input_fields[i], &eval_mode); 240e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 241d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetSize(qf_input_fields[i], &size); 242d1d35e2fSjeremylt CeedChkBackend(ierr); 243885ac19cSjeremylt // Basis action 244d1d35e2fSjeremylt switch(eval_mode) { 245885ac19cSjeremylt case CEED_EVAL_NONE: 246d1d35e2fSjeremylt ierr = CeedVectorSetArray(impl->q_vecs_in[i], CEED_MEM_HOST, 2474fc1f125SJeremy L Thompson CEED_USE_POINTER, &e_data_full[i][e*Q*size]); 248d1d35e2fSjeremylt CeedChkBackend(ierr); 249885ac19cSjeremylt break; 250885ac19cSjeremylt case CEED_EVAL_INTERP: 251d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(op_input_fields[i], &basis); 252e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 253d1d35e2fSjeremylt ierr = CeedVectorSetArray(impl->e_vecs_in[i], CEED_MEM_HOST, 2544fc1f125SJeremy L Thompson CEED_USE_POINTER, &e_data_full[i][e*elem_size*size]); 255e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 256d1d35e2fSjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, CEED_EVAL_INTERP, 257d1d35e2fSjeremylt impl->e_vecs_in[i], impl->q_vecs_in[i]); CeedChkBackend(ierr); 258885ac19cSjeremylt break; 259885ac19cSjeremylt case CEED_EVAL_GRAD: 260d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(op_input_fields[i], &basis); 261e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 262e15f9bd0SJeremy L Thompson ierr = CeedBasisGetDimension(basis, &dim); CeedChkBackend(ierr); 263d1d35e2fSjeremylt ierr = CeedVectorSetArray(impl->e_vecs_in[i], CEED_MEM_HOST, 2644fc1f125SJeremy L Thompson CEED_USE_POINTER, &e_data_full[i][e*elem_size*size/dim]); 265e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 266d1bcdac9Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_NOTRANSPOSE, 267d1d35e2fSjeremylt CEED_EVAL_GRAD, impl->e_vecs_in[i], 268d1d35e2fSjeremylt impl->q_vecs_in[i]); CeedChkBackend(ierr); 269885ac19cSjeremylt break; 270885ac19cSjeremylt case CEED_EVAL_WEIGHT: 271885ac19cSjeremylt break; // No action 272bbfacfcdSjeremylt // LCOV_EXCL_START 273885ac19cSjeremylt case CEED_EVAL_DIV: 2741d102b48SJeremy L Thompson case CEED_EVAL_CURL: { 275d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(op_input_fields[i], &basis); 276e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 2771d102b48SJeremy L Thompson Ceed ceed; 278e15f9bd0SJeremy L Thompson ierr = CeedBasisGetCeed(basis, &ceed); CeedChkBackend(ierr); 279e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 280e15f9bd0SJeremy L Thompson "Ceed evaluation mode not implemented"); 281bbfacfcdSjeremylt // LCOV_EXCL_STOP 282885ac19cSjeremylt } 283885ac19cSjeremylt } 284885ac19cSjeremylt } 285e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 286885ac19cSjeremylt } 287885ac19cSjeremylt 288f10650afSjeremylt //------------------------------------------------------------------------------ 289f10650afSjeremylt // Output Basis Action 290f10650afSjeremylt //------------------------------------------------------------------------------ 2911d102b48SJeremy L Thompson static inline int CeedOperatorOutputBasis_Ref(CeedInt e, CeedInt Q, 292d1d35e2fSjeremylt CeedQFunctionField *qf_output_fields, CeedOperatorField *op_output_fields, 293d1d35e2fSjeremylt CeedInt num_input_fields, CeedInt num_output_fields, CeedOperator op, 2944fc1f125SJeremy L Thompson CeedScalar *e_data_full[2*CEED_FIELD_MAX], CeedOperator_Ref *impl) { 2951d102b48SJeremy L Thompson CeedInt ierr; 296d1d35e2fSjeremylt CeedInt dim, elem_size, size; 297d1d35e2fSjeremylt CeedElemRestriction elem_restr; 298d1d35e2fSjeremylt CeedEvalMode eval_mode; 2991d102b48SJeremy L Thompson CeedBasis basis; 3001d102b48SJeremy L Thompson 301d1d35e2fSjeremylt for (CeedInt i=0; i<num_output_fields; i++) { 302d1d35e2fSjeremylt // Get elem_size, eval_mode, size 303d1d35e2fSjeremylt ierr = CeedOperatorFieldGetElemRestriction(op_output_fields[i], &elem_restr); 304e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 305d1d35e2fSjeremylt ierr = CeedElemRestrictionGetElementSize(elem_restr, &elem_size); 306e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 307d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_output_fields[i], &eval_mode); 308e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 309d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetSize(qf_output_fields[i], &size); 310e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 311885ac19cSjeremylt // Basis action 312d1d35e2fSjeremylt switch(eval_mode) { 313885ac19cSjeremylt case CEED_EVAL_NONE: 314885ac19cSjeremylt break; // No action 315885ac19cSjeremylt case CEED_EVAL_INTERP: 316d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(op_output_fields[i], &basis); 317e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 318d1d35e2fSjeremylt ierr = CeedVectorSetArray(impl->e_vecs_out[i], CEED_MEM_HOST, 319aedaa0e5Sjeremylt CEED_USE_POINTER, 3204fc1f125SJeremy L Thompson &e_data_full[i + num_input_fields][e*elem_size*size]); 321e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 322aedaa0e5Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, 323d1d35e2fSjeremylt CEED_EVAL_INTERP, impl->q_vecs_out[i], 324d1d35e2fSjeremylt impl->e_vecs_out[i]); CeedChkBackend(ierr); 325885ac19cSjeremylt break; 326885ac19cSjeremylt case CEED_EVAL_GRAD: 327d1d35e2fSjeremylt ierr = CeedOperatorFieldGetBasis(op_output_fields[i], &basis); 328e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 329e15f9bd0SJeremy L Thompson ierr = CeedBasisGetDimension(basis, &dim); CeedChkBackend(ierr); 330d1d35e2fSjeremylt ierr = CeedVectorSetArray(impl->e_vecs_out[i], CEED_MEM_HOST, 331aedaa0e5Sjeremylt CEED_USE_POINTER, 3324fc1f125SJeremy L Thompson &e_data_full[i + num_input_fields][e*elem_size*size/dim]); 333e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 334aedaa0e5Sjeremylt ierr = CeedBasisApply(basis, 1, CEED_TRANSPOSE, 335d1d35e2fSjeremylt CEED_EVAL_GRAD, impl->q_vecs_out[i], 336d1d35e2fSjeremylt impl->e_vecs_out[i]); CeedChkBackend(ierr); 337885ac19cSjeremylt break; 338c042f62fSJeremy L Thompson // LCOV_EXCL_START 339bbfacfcdSjeremylt case CEED_EVAL_WEIGHT: { 3404ce2993fSjeremylt Ceed ceed; 341e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChkBackend(ierr); 342e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 343e15f9bd0SJeremy L Thompson "CEED_EVAL_WEIGHT cannot be an output " 3441d102b48SJeremy L Thompson "evaluation mode"); 3454ce2993fSjeremylt } 346885ac19cSjeremylt case CEED_EVAL_DIV: 3471d102b48SJeremy L Thompson case CEED_EVAL_CURL: { 3481d102b48SJeremy L Thompson Ceed ceed; 349e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChkBackend(ierr); 350e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 351e15f9bd0SJeremy L Thompson "Ceed evaluation mode not implemented"); 3521d102b48SJeremy L Thompson // LCOV_EXCL_STOP 353885ac19cSjeremylt } 354885ac19cSjeremylt } 355885ac19cSjeremylt } 356e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3571d102b48SJeremy L Thompson } 3581d102b48SJeremy L Thompson 359f10650afSjeremylt //------------------------------------------------------------------------------ 360f10650afSjeremylt // Restore Input Vectors 361f10650afSjeremylt //------------------------------------------------------------------------------ 362d1d35e2fSjeremylt static inline int CeedOperatorRestoreInputs_Ref(CeedInt num_input_fields, 363d1d35e2fSjeremylt CeedQFunctionField *qf_input_fields, CeedOperatorField *op_input_fields, 3644fc1f125SJeremy L Thompson const bool skip_active, CeedScalar *e_data_full[2*CEED_FIELD_MAX], 365a0162de9SJeremy L Thompson CeedOperator_Ref *impl) { 3661d102b48SJeremy L Thompson CeedInt ierr; 367d1d35e2fSjeremylt CeedEvalMode eval_mode; 3681d102b48SJeremy L Thompson 369d1d35e2fSjeremylt for (CeedInt i=0; i<num_input_fields; i++) { 3701d102b48SJeremy L Thompson // Skip active inputs 371d1d35e2fSjeremylt if (skip_active) { 3721d102b48SJeremy L Thompson CeedVector vec; 373d1d35e2fSjeremylt ierr = CeedOperatorFieldGetVector(op_input_fields[i], &vec); 374d1d35e2fSjeremylt CeedChkBackend(ierr); 3751d102b48SJeremy L Thompson if (vec == CEED_VECTOR_ACTIVE) 3761d102b48SJeremy L Thompson continue; 3771d102b48SJeremy L Thompson } 3781d102b48SJeremy L Thompson // Restore input 379d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_input_fields[i], &eval_mode); 380e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 381d1d35e2fSjeremylt if (eval_mode == CEED_EVAL_WEIGHT) { // Skip 3821d102b48SJeremy L Thompson } else { 3834fc1f125SJeremy L Thompson ierr = CeedVectorRestoreArrayRead(impl->e_vecs_full[i], 3844fc1f125SJeremy L Thompson (const CeedScalar **) &e_data_full[i]); 385e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 3861d102b48SJeremy L Thompson } 3871d102b48SJeremy L Thompson } 388e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 3891d102b48SJeremy L Thompson } 3901d102b48SJeremy L Thompson 391f10650afSjeremylt //------------------------------------------------------------------------------ 392f10650afSjeremylt // Operator Apply 393f10650afSjeremylt //------------------------------------------------------------------------------ 394d1d35e2fSjeremylt static int CeedOperatorApplyAdd_Ref(CeedOperator op, CeedVector in_vec, 395d1d35e2fSjeremylt CeedVector out_vec, CeedRequest *request) { 3961d102b48SJeremy L Thompson int ierr; 3971d102b48SJeremy L Thompson CeedOperator_Ref *impl; 398e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetData(op, &impl); CeedChkBackend(ierr); 3991d102b48SJeremy L Thompson CeedQFunction qf; 400e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetQFunction(op, &qf); CeedChkBackend(ierr); 401d1d35e2fSjeremylt CeedInt Q, num_elem, num_input_fields, num_output_fields, size; 402e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChkBackend(ierr); 403d1d35e2fSjeremylt ierr = CeedOperatorGetNumElements(op, &num_elem); CeedChkBackend(ierr); 404d1d35e2fSjeremylt CeedOperatorField *op_input_fields, *op_output_fields; 4057e7773b5SJeremy L Thompson ierr = CeedOperatorGetFields(op, &num_input_fields, &op_input_fields, 4067e7773b5SJeremy L Thompson &num_output_fields, &op_output_fields); 407e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 408d1d35e2fSjeremylt CeedQFunctionField *qf_input_fields, *qf_output_fields; 4097e7773b5SJeremy L Thompson ierr = CeedQFunctionGetFields(qf, NULL, &qf_input_fields, NULL, 4107e7773b5SJeremy L Thompson &qf_output_fields); 411e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 412d1d35e2fSjeremylt CeedEvalMode eval_mode; 4131d102b48SJeremy L Thompson CeedVector vec; 414d1d35e2fSjeremylt CeedElemRestriction elem_restr; 4154fc1f125SJeremy L Thompson CeedScalar *e_data_full[2*CEED_FIELD_MAX] = {0}; 4161d102b48SJeremy L Thompson 4171d102b48SJeremy L Thompson // Setup 418e15f9bd0SJeremy L Thompson ierr = CeedOperatorSetup_Ref(op); CeedChkBackend(ierr); 4191d102b48SJeremy L Thompson 4200b454692Sjeremylt // Restriction only operator 4210b454692Sjeremylt if (impl->is_identity_restr_op) { 4220b454692Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(op_input_fields[0], &elem_restr); 4230b454692Sjeremylt CeedChkBackend(ierr); 4240b454692Sjeremylt ierr = CeedElemRestrictionApply(elem_restr, CEED_NOTRANSPOSE, in_vec, 4254fc1f125SJeremy L Thompson impl->e_vecs_full[0], request); 4264fc1f125SJeremy L Thompson CeedChkBackend(ierr); 4270b454692Sjeremylt ierr = CeedOperatorFieldGetElemRestriction(op_output_fields[0], &elem_restr); 4280b454692Sjeremylt CeedChkBackend(ierr); 4294fc1f125SJeremy L Thompson ierr = CeedElemRestrictionApply(elem_restr, CEED_TRANSPOSE, 4304fc1f125SJeremy L Thompson impl->e_vecs_full[0], 4310b454692Sjeremylt out_vec, request); CeedChkBackend(ierr); 4320b454692Sjeremylt return CEED_ERROR_SUCCESS; 4330b454692Sjeremylt } 4340b454692Sjeremylt 4351d102b48SJeremy L Thompson // Input Evecs and Restriction 436d1d35e2fSjeremylt ierr = CeedOperatorSetupInputs_Ref(num_input_fields, qf_input_fields, 4374fc1f125SJeremy L Thompson op_input_fields, in_vec, false, e_data_full, impl, 438e15f9bd0SJeremy L Thompson request); CeedChkBackend(ierr); 4391d102b48SJeremy L Thompson 4401d102b48SJeremy L Thompson // Output Evecs 441d1d35e2fSjeremylt for (CeedInt i=0; i<num_output_fields; i++) { 4429c774eddSJeremy L Thompson ierr = CeedVectorGetArrayWrite(impl->e_vecs_full[i+impl->num_inputs], 4439c774eddSJeremy L Thompson CEED_MEM_HOST, &e_data_full[i + num_input_fields]); 4449c774eddSJeremy L Thompson CeedChkBackend(ierr); 4451d102b48SJeremy L Thompson } 4461d102b48SJeremy L Thompson 4471d102b48SJeremy L Thompson // Loop through elements 448d1d35e2fSjeremylt for (CeedInt e=0; e<num_elem; e++) { 4491d102b48SJeremy L Thompson // Output pointers 450d1d35e2fSjeremylt for (CeedInt i=0; i<num_output_fields; i++) { 451d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetEvalMode(qf_output_fields[i], &eval_mode); 452e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 453d1d35e2fSjeremylt if (eval_mode == CEED_EVAL_NONE) { 454d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetSize(qf_output_fields[i], &size); 455e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 456d1d35e2fSjeremylt ierr = CeedVectorSetArray(impl->q_vecs_out[i], CEED_MEM_HOST, 4571d102b48SJeremy L Thompson CEED_USE_POINTER, 4584fc1f125SJeremy L Thompson &e_data_full[i + num_input_fields][e*Q*size]); 459e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 4601d102b48SJeremy L Thompson } 4611d102b48SJeremy L Thompson } 4621d102b48SJeremy L Thompson 46316911fdaSjeremylt // Input basis apply 464d1d35e2fSjeremylt ierr = CeedOperatorInputBasis_Ref(e, Q, qf_input_fields, op_input_fields, 4654fc1f125SJeremy L Thompson num_input_fields, false, e_data_full, impl); 466e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 46716911fdaSjeremylt 4681d102b48SJeremy L Thompson // Q function 4690b454692Sjeremylt if (!impl->is_identity_qf) { 470d1d35e2fSjeremylt ierr = CeedQFunctionApply(qf, Q, impl->q_vecs_in, impl->q_vecs_out); 471e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 47216911fdaSjeremylt } 4731d102b48SJeremy L Thompson 4741d102b48SJeremy L Thompson // Output basis apply 475d1d35e2fSjeremylt ierr = CeedOperatorOutputBasis_Ref(e, Q, qf_output_fields, op_output_fields, 476a0162de9SJeremy L Thompson num_input_fields, num_output_fields, op, 4774fc1f125SJeremy L Thompson e_data_full, impl); CeedChkBackend(ierr); 4781d102b48SJeremy L Thompson } 479885ac19cSjeremylt 480885ac19cSjeremylt // Output restriction 481d1d35e2fSjeremylt for (CeedInt i=0; i<num_output_fields; i++) { 482d1d35e2fSjeremylt // Restore Evec 4834fc1f125SJeremy L Thompson ierr = CeedVectorRestoreArray(impl->e_vecs_full[i+impl->num_inputs], 4844fc1f125SJeremy L Thompson &e_data_full[i + num_input_fields]); 485e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 486d1bcdac9Sjeremylt // Get output vector 487d1d35e2fSjeremylt ierr = CeedOperatorFieldGetVector(op_output_fields[i], &vec); 488e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 489668048e2SJed Brown // Active 490d1bcdac9Sjeremylt if (vec == CEED_VECTOR_ACTIVE) 491d1d35e2fSjeremylt vec = out_vec; 4927ca8db16Sjeremylt // Restrict 493d1d35e2fSjeremylt ierr = CeedOperatorFieldGetElemRestriction(op_output_fields[i], &elem_restr); 494e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 495d1d35e2fSjeremylt ierr = CeedElemRestrictionApply(elem_restr, CEED_TRANSPOSE, 4964fc1f125SJeremy L Thompson impl->e_vecs_full[i+impl->num_inputs], 4974fc1f125SJeremy L Thompson vec, request); CeedChkBackend(ierr); 498885ac19cSjeremylt } 499885ac19cSjeremylt 5007ca8db16Sjeremylt // Restore input arrays 501d1d35e2fSjeremylt ierr = CeedOperatorRestoreInputs_Ref(num_input_fields, qf_input_fields, 5024fc1f125SJeremy L Thompson op_input_fields, false, e_data_full, impl); 503e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 5047ca8db16Sjeremylt 505e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 50621617c04Sjeremylt } 50721617c04Sjeremylt 508f10650afSjeremylt //------------------------------------------------------------------------------ 50970a7ffb3SJeremy L Thompson // Core code for assembling linear QFunction 510f10650afSjeremylt //------------------------------------------------------------------------------ 51170a7ffb3SJeremy L Thompson static inline int CeedOperatorLinearAssembleQFunctionCore_Ref(CeedOperator op, 51270a7ffb3SJeremy L Thompson bool build_objects, CeedVector *assembled, CeedElemRestriction *rstr, 51370a7ffb3SJeremy L Thompson CeedRequest *request) { 5141d102b48SJeremy L Thompson int ierr; 5151d102b48SJeremy L Thompson CeedOperator_Ref *impl; 516e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetData(op, &impl); CeedChkBackend(ierr); 5171d102b48SJeremy L Thompson CeedQFunction qf; 518e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetQFunction(op, &qf); CeedChkBackend(ierr); 519d1d35e2fSjeremylt CeedInt Q, num_elem, num_input_fields, num_output_fields, size; 520e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetNumQuadraturePoints(op, &Q); CeedChkBackend(ierr); 521d1d35e2fSjeremylt ierr = CeedOperatorGetNumElements(op, &num_elem); CeedChkBackend(ierr); 522d1d35e2fSjeremylt CeedOperatorField *op_input_fields, *op_output_fields; 5237e7773b5SJeremy L Thompson ierr = CeedOperatorGetFields(op, &num_input_fields, &op_input_fields, 5247e7773b5SJeremy L Thompson &num_output_fields, &op_output_fields); 525e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 526d1d35e2fSjeremylt CeedQFunctionField *qf_input_fields, *qf_output_fields; 5277e7773b5SJeremy L Thompson ierr = CeedQFunctionGetFields(qf, NULL, &qf_input_fields, NULL, 5287e7773b5SJeremy L Thompson &qf_output_fields); 529e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 5301d102b48SJeremy L Thompson CeedVector vec; 5314fc1f125SJeremy L Thompson CeedInt num_active_in = impl->num_active_in, 5324fc1f125SJeremy L Thompson num_active_out = impl->num_active_out; 533bb219a0fSJeremy L Thompson CeedVector *active_in = impl->qf_active_in; 5341d102b48SJeremy L Thompson CeedScalar *a, *tmp; 535d1d35e2fSjeremylt Ceed ceed, ceed_parent; 536e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChkBackend(ierr); 537d1d35e2fSjeremylt ierr = CeedGetOperatorFallbackParentCeed(ceed, &ceed_parent); 538e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 539d1d35e2fSjeremylt ceed_parent = ceed_parent ? ceed_parent : ceed; 5404fc1f125SJeremy L Thompson CeedScalar *e_data_full[2*CEED_FIELD_MAX] = {0}; 5411d102b48SJeremy L Thompson 5421d102b48SJeremy L Thompson // Setup 543e15f9bd0SJeremy L Thompson ierr = CeedOperatorSetup_Ref(op); CeedChkBackend(ierr); 5441d102b48SJeremy L Thompson 54516911fdaSjeremylt // Check for identity 5460b454692Sjeremylt if (impl->is_identity_qf) 54716911fdaSjeremylt // LCOV_EXCL_START 548e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 549e15f9bd0SJeremy L Thompson "Assembling identity QFunctions not supported"); 55016911fdaSjeremylt // LCOV_EXCL_STOP 55116911fdaSjeremylt 5521d102b48SJeremy L Thompson // Input Evecs and Restriction 553d1d35e2fSjeremylt ierr = CeedOperatorSetupInputs_Ref(num_input_fields, qf_input_fields, 5544fc1f125SJeremy L Thompson op_input_fields, NULL, true, e_data_full, 555a0162de9SJeremy L Thompson impl, request); CeedChkBackend(ierr); 5561d102b48SJeremy L Thompson 5571d102b48SJeremy L Thompson // Count number of active input fields 558bb219a0fSJeremy L Thompson if (!num_active_in) { 559d1d35e2fSjeremylt for (CeedInt i=0; i<num_input_fields; i++) { 5601d102b48SJeremy L Thompson // Get input vector 561d1d35e2fSjeremylt ierr = CeedOperatorFieldGetVector(op_input_fields[i], &vec); 562d1d35e2fSjeremylt CeedChkBackend(ierr); 5631d102b48SJeremy L Thompson // Check if active input 5641d102b48SJeremy L Thompson if (vec == CEED_VECTOR_ACTIVE) { 565d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetSize(qf_input_fields[i], &size); 566e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 567d1d35e2fSjeremylt ierr = CeedVectorSetValue(impl->q_vecs_in[i], 0.0); CeedChkBackend(ierr); 568d1d35e2fSjeremylt ierr = CeedVectorGetArray(impl->q_vecs_in[i], CEED_MEM_HOST, &tmp); 569d1d35e2fSjeremylt CeedChkBackend(ierr); 570d1d35e2fSjeremylt ierr = CeedRealloc(num_active_in + size, &active_in); CeedChkBackend(ierr); 5711d102b48SJeremy L Thompson for (CeedInt field=0; field<size; field++) { 572d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed, Q, &active_in[num_active_in+field]); 573e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 574d1d35e2fSjeremylt ierr = CeedVectorSetArray(active_in[num_active_in+field], CEED_MEM_HOST, 57542ea3801Sjeremylt CEED_USE_POINTER, &tmp[field*Q]); 576e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 5771d102b48SJeremy L Thompson } 578d1d35e2fSjeremylt num_active_in += size; 579d1d35e2fSjeremylt ierr = CeedVectorRestoreArray(impl->q_vecs_in[i], &tmp); CeedChkBackend(ierr); 5801d102b48SJeremy L Thompson } 5811d102b48SJeremy L Thompson } 5824fc1f125SJeremy L Thompson impl->num_active_in = num_active_in; 583bb219a0fSJeremy L Thompson impl->qf_active_in = active_in; 584bb219a0fSJeremy L Thompson } 5851d102b48SJeremy L Thompson 5861d102b48SJeremy L Thompson // Count number of active output fields 587bb219a0fSJeremy L Thompson if (!num_active_out) { 588d1d35e2fSjeremylt for (CeedInt i=0; i<num_output_fields; i++) { 5891d102b48SJeremy L Thompson // Get output vector 590d1d35e2fSjeremylt ierr = CeedOperatorFieldGetVector(op_output_fields[i], &vec); 591e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 5921d102b48SJeremy L Thompson // Check if active output 5931d102b48SJeremy L Thompson if (vec == CEED_VECTOR_ACTIVE) { 594d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetSize(qf_output_fields[i], &size); 595e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 596d1d35e2fSjeremylt num_active_out += size; 5971d102b48SJeremy L Thompson } 5981d102b48SJeremy L Thompson } 5994fc1f125SJeremy L Thompson impl->num_active_out = num_active_out; 600bb219a0fSJeremy L Thompson } 6011d102b48SJeremy L Thompson 6021d102b48SJeremy L Thompson // Check sizes 603d1d35e2fSjeremylt if (!num_active_in || !num_active_out) 604138d4072Sjeremylt // LCOV_EXCL_START 605e15f9bd0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, 606e15f9bd0SJeremy L Thompson "Cannot assemble QFunction without active inputs " 607138d4072Sjeremylt "and outputs"); 608138d4072Sjeremylt // LCOV_EXCL_STOP 6091d102b48SJeremy L Thompson 61070a7ffb3SJeremy L Thompson // Build objects if needed 61170a7ffb3SJeremy L Thompson if (build_objects) { 6121d102b48SJeremy L Thompson // Create output restriction 613d1d35e2fSjeremylt CeedInt strides[3] = {1, Q, num_active_in*num_active_out*Q}; /* *NOPAD* */ 614d1d35e2fSjeremylt ierr = CeedElemRestrictionCreateStrided(ceed_parent, num_elem, Q, 615d1d35e2fSjeremylt num_active_in*num_active_out, 616d1d35e2fSjeremylt num_active_in*num_active_out*num_elem*Q, 617e15f9bd0SJeremy L Thompson strides, rstr); CeedChkBackend(ierr); 6181d102b48SJeremy L Thompson // Create assembled vector 619d1d35e2fSjeremylt ierr = CeedVectorCreate(ceed_parent, num_elem*Q*num_active_in*num_active_out, 620e15f9bd0SJeremy L Thompson assembled); CeedChkBackend(ierr); 62170a7ffb3SJeremy L Thompson } 62270a7ffb3SJeremy L Thompson // Clear output vector 623e15f9bd0SJeremy L Thompson ierr = CeedVectorSetValue(*assembled, 0.0); CeedChkBackend(ierr); 624e15f9bd0SJeremy L Thompson ierr = CeedVectorGetArray(*assembled, CEED_MEM_HOST, &a); CeedChkBackend(ierr); 6251d102b48SJeremy L Thompson 6261d102b48SJeremy L Thompson // Loop through elements 627d1d35e2fSjeremylt for (CeedInt e=0; e<num_elem; e++) { 6281d102b48SJeremy L Thompson // Input basis apply 629d1d35e2fSjeremylt ierr = CeedOperatorInputBasis_Ref(e, Q, qf_input_fields, op_input_fields, 6304fc1f125SJeremy L Thompson num_input_fields, true, e_data_full, impl); 631e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 6321d102b48SJeremy L Thompson 6331d102b48SJeremy L Thompson // Assemble QFunction 634d1d35e2fSjeremylt for (CeedInt in=0; in<num_active_in; in++) { 6351d102b48SJeremy L Thompson // Set Inputs 636d1d35e2fSjeremylt ierr = CeedVectorSetValue(active_in[in], 1.0); CeedChkBackend(ierr); 637d1d35e2fSjeremylt if (num_active_in > 1) { 638d1d35e2fSjeremylt ierr = CeedVectorSetValue(active_in[(in+num_active_in-1)%num_active_in], 639e15f9bd0SJeremy L Thompson 0.0); CeedChkBackend(ierr); 64042ea3801Sjeremylt } 6411d102b48SJeremy L Thompson // Set Outputs 642d1d35e2fSjeremylt for (CeedInt out=0; out<num_output_fields; out++) { 6431d102b48SJeremy L Thompson // Get output vector 644d1d35e2fSjeremylt ierr = CeedOperatorFieldGetVector(op_output_fields[out], &vec); 645e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 6461d102b48SJeremy L Thompson // Check if active output 6471d102b48SJeremy L Thompson if (vec == CEED_VECTOR_ACTIVE) { 648d1d35e2fSjeremylt CeedVectorSetArray(impl->q_vecs_out[out], CEED_MEM_HOST, 649e15f9bd0SJeremy L Thompson CEED_USE_POINTER, a); CeedChkBackend(ierr); 650d1d35e2fSjeremylt ierr = CeedQFunctionFieldGetSize(qf_output_fields[out], &size); 651e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 6521d102b48SJeremy L Thompson a += size*Q; // Advance the pointer by the size of the output 6531d102b48SJeremy L Thompson } 6541d102b48SJeremy L Thompson } 6551d102b48SJeremy L Thompson // Apply QFunction 656d1d35e2fSjeremylt ierr = CeedQFunctionApply(qf, Q, impl->q_vecs_in, impl->q_vecs_out); 657e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 6581d102b48SJeremy L Thompson } 6591d102b48SJeremy L Thompson } 6601d102b48SJeremy L Thompson 6611d102b48SJeremy L Thompson // Un-set output Qvecs to prevent accidental overwrite of Assembled 662d1d35e2fSjeremylt for (CeedInt out=0; out<num_output_fields; out++) { 6631d102b48SJeremy L Thompson // Get output vector 664d1d35e2fSjeremylt ierr = CeedOperatorFieldGetVector(op_output_fields[out], &vec); 665e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 6661d102b48SJeremy L Thompson // Check if active output 6671d102b48SJeremy L Thompson if (vec == CEED_VECTOR_ACTIVE) { 668d1d35e2fSjeremylt CeedVectorTakeArray(impl->q_vecs_out[out], CEED_MEM_HOST, NULL); 669e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 6701d102b48SJeremy L Thompson } 6711d102b48SJeremy L Thompson } 6721d102b48SJeremy L Thompson 6731d102b48SJeremy L Thompson // Restore input arrays 674d1d35e2fSjeremylt ierr = CeedOperatorRestoreInputs_Ref(num_input_fields, qf_input_fields, 6754fc1f125SJeremy L Thompson op_input_fields, true, e_data_full, impl); 676e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 6771d102b48SJeremy L Thompson 6781d102b48SJeremy L Thompson // Restore output 679e15f9bd0SJeremy L Thompson ierr = CeedVectorRestoreArray(*assembled, &a); CeedChkBackend(ierr); 6801d102b48SJeremy L Thompson 681e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 6821d102b48SJeremy L Thompson } 6831d102b48SJeremy L Thompson 684f10650afSjeremylt //------------------------------------------------------------------------------ 68570a7ffb3SJeremy L Thompson // Assemble Linear QFunction 68670a7ffb3SJeremy L Thompson //------------------------------------------------------------------------------ 68770a7ffb3SJeremy L Thompson static int CeedOperatorLinearAssembleQFunction_Ref(CeedOperator op, 68870a7ffb3SJeremy L Thompson CeedVector *assembled, CeedElemRestriction *rstr, CeedRequest *request) { 68970a7ffb3SJeremy L Thompson return CeedOperatorLinearAssembleQFunctionCore_Ref(op, true, assembled, rstr, 69070a7ffb3SJeremy L Thompson request); 69170a7ffb3SJeremy L Thompson } 69270a7ffb3SJeremy L Thompson 69370a7ffb3SJeremy L Thompson //------------------------------------------------------------------------------ 69470a7ffb3SJeremy L Thompson // Update Assembled Linear QFunction 69570a7ffb3SJeremy L Thompson //------------------------------------------------------------------------------ 69670a7ffb3SJeremy L Thompson static int CeedOperatorLinearAssembleQFunctionUpdate_Ref(CeedOperator op, 69770a7ffb3SJeremy L Thompson CeedVector assembled, CeedElemRestriction rstr, CeedRequest *request) { 69870a7ffb3SJeremy L Thompson return CeedOperatorLinearAssembleQFunctionCore_Ref(op, false, &assembled, 69970a7ffb3SJeremy L Thompson &rstr, request); 70070a7ffb3SJeremy L Thompson } 70170a7ffb3SJeremy L Thompson 70270a7ffb3SJeremy L Thompson //------------------------------------------------------------------------------ 703f10650afSjeremylt // Operator Destroy 704f10650afSjeremylt //------------------------------------------------------------------------------ 705f10650afSjeremylt static int CeedOperatorDestroy_Ref(CeedOperator op) { 706f10650afSjeremylt int ierr; 707f10650afSjeremylt CeedOperator_Ref *impl; 708e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetData(op, &impl); CeedChkBackend(ierr); 709f10650afSjeremylt 7104fc1f125SJeremy L Thompson for (CeedInt i=0; i<impl->num_inputs+impl->num_outputs; i++) { 7114fc1f125SJeremy L Thompson ierr = CeedVectorDestroy(&impl->e_vecs_full[i]); CeedChkBackend(ierr); 712f10650afSjeremylt } 7134fc1f125SJeremy L Thompson ierr = CeedFree(&impl->e_vecs_full); CeedChkBackend(ierr); 7144fc1f125SJeremy L Thompson ierr = CeedFree(&impl->input_states); CeedChkBackend(ierr); 715f10650afSjeremylt 7164fc1f125SJeremy L Thompson for (CeedInt i=0; i<impl->num_inputs; i++) { 717d1d35e2fSjeremylt ierr = CeedVectorDestroy(&impl->e_vecs_in[i]); CeedChkBackend(ierr); 718d1d35e2fSjeremylt ierr = CeedVectorDestroy(&impl->q_vecs_in[i]); CeedChkBackend(ierr); 719f10650afSjeremylt } 720d1d35e2fSjeremylt ierr = CeedFree(&impl->e_vecs_in); CeedChkBackend(ierr); 721d1d35e2fSjeremylt ierr = CeedFree(&impl->q_vecs_in); CeedChkBackend(ierr); 722f10650afSjeremylt 7234fc1f125SJeremy L Thompson for (CeedInt i=0; i<impl->num_outputs; i++) { 724d1d35e2fSjeremylt ierr = CeedVectorDestroy(&impl->e_vecs_out[i]); CeedChkBackend(ierr); 725d1d35e2fSjeremylt ierr = CeedVectorDestroy(&impl->q_vecs_out[i]); CeedChkBackend(ierr); 726f10650afSjeremylt } 727d1d35e2fSjeremylt ierr = CeedFree(&impl->e_vecs_out); CeedChkBackend(ierr); 728d1d35e2fSjeremylt ierr = CeedFree(&impl->q_vecs_out); CeedChkBackend(ierr); 729f10650afSjeremylt 730bb219a0fSJeremy L Thompson // QFunction assembly 7314fc1f125SJeremy L Thompson for (CeedInt i=0; i<impl->num_active_in; i++) { 732bb219a0fSJeremy L Thompson ierr = CeedVectorDestroy(&impl->qf_active_in[i]); CeedChkBackend(ierr); 733bb219a0fSJeremy L Thompson } 734bb219a0fSJeremy L Thompson ierr = CeedFree(&impl->qf_active_in); CeedChkBackend(ierr); 735bb219a0fSJeremy L Thompson 736e15f9bd0SJeremy L Thompson ierr = CeedFree(&impl); CeedChkBackend(ierr); 737e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 738f10650afSjeremylt } 739f10650afSjeremylt 740f10650afSjeremylt //------------------------------------------------------------------------------ 741713f43c3Sjeremylt // Operator Create 742f10650afSjeremylt //------------------------------------------------------------------------------ 74321617c04Sjeremylt int CeedOperatorCreate_Ref(CeedOperator op) { 74421617c04Sjeremylt int ierr; 745fe2413ffSjeremylt Ceed ceed; 746e15f9bd0SJeremy L Thompson ierr = CeedOperatorGetCeed(op, &ceed); CeedChkBackend(ierr); 7474ce2993fSjeremylt CeedOperator_Ref *impl; 74821617c04Sjeremylt 749e15f9bd0SJeremy L Thompson ierr = CeedCalloc(1, &impl); CeedChkBackend(ierr); 750e15f9bd0SJeremy L Thompson ierr = CeedOperatorSetData(op, impl); CeedChkBackend(ierr); 751fe2413ffSjeremylt 75280ac2e43SJeremy L Thompson ierr = CeedSetBackendFunction(ceed, "Operator", op, "LinearAssembleQFunction", 75380ac2e43SJeremy L Thompson CeedOperatorLinearAssembleQFunction_Ref); 754e15f9bd0SJeremy L Thompson CeedChkBackend(ierr); 75570a7ffb3SJeremy L Thompson ierr = CeedSetBackendFunction(ceed, "Operator", op, 75670a7ffb3SJeremy L Thompson "LinearAssembleQFunctionUpdate", 75770a7ffb3SJeremy L Thompson CeedOperatorLinearAssembleQFunctionUpdate_Ref); 75870a7ffb3SJeremy L Thompson CeedChkBackend(ierr); 759cae8b89aSjeremylt ierr = CeedSetBackendFunction(ceed, "Operator", op, "ApplyAdd", 760e15f9bd0SJeremy L Thompson CeedOperatorApplyAdd_Ref); CeedChkBackend(ierr); 761fe2413ffSjeremylt ierr = CeedSetBackendFunction(ceed, "Operator", op, "Destroy", 762e15f9bd0SJeremy L Thompson CeedOperatorDestroy_Ref); CeedChkBackend(ierr); 763e15f9bd0SJeremy L Thompson return CEED_ERROR_SUCCESS; 76421617c04Sjeremylt } 765