MomentumBuoyancyBoussinesqSrcElemKernel<AlgTraits>::MomentumBuoyancyBoussinesqSrcElemKernel( const stk::mesh::BulkData& bulkData, const SolutionOptions& solnOpts, ElemDataRequests& dataPreReqs) : Kernel(), rhoRef_(solnOpts.referenceDensity_), ipNodeMap_(sierra::nalu::MasterElementRepo::get_volume_master_element(AlgTraits::topo_)->ipNodeMap()) { const stk::mesh::MetaData& metaData = bulkData.mesh_meta_data(); ScalarFieldType *temperature = metaData.get_field<ScalarFieldType>(stk::topology::NODE_RANK, "temperature"); temperatureNp1_ = &(temperature->field_of_state(stk::mesh::StateNP1)); coordinates_ = metaData.get_field<VectorFieldType>(stk::topology::NODE_RANK, solnOpts.get_coordinates_name()); const std::vector<double>& solnOptsGravity = solnOpts.get_gravity_vector(AlgTraits::nDim_); for (int i = 0; i < AlgTraits::nDim_; i++) gravity_(i) = solnOptsGravity[i]; tRef_ = solnOpts.referenceTemperature_; rhoRef_ = solnOpts.referenceDensity_; beta_ = solnOpts.thermalExpansionCoeff_; MasterElement* meSCV = sierra::nalu::MasterElementRepo::get_volume_master_element(AlgTraits::topo_); get_scv_shape_fn_data<AlgTraits>([&](double* ptr){meSCV->shape_fcn(ptr);}, v_shape_function_); // add master elements dataPreReqs.add_cvfem_volume_me(meSCV); // fields and data dataPreReqs.add_coordinates_field(*coordinates_, AlgTraits::nDim_, CURRENT_COORDINATES); dataPreReqs.add_gathered_nodal_field(*temperatureNp1_, 1); dataPreReqs.add_master_element_call(SCV_VOLUME, CURRENT_COORDINATES); }
ScratchViews::ScratchViews(const TeamHandleType& team, const stk::mesh::BulkData& bulkData, stk::topology topo, ElemDataRequests& dataNeeded) : elemNodes(nullptr), scs_areav(), dndx(), dndx_shifted(), deriv(), det_j(), scv_volume(), gijUpper(), gijLower() { /* master elements are allowed to be null if they are not required */ MasterElement *meSCS = dataNeeded.get_cvfem_surface_me(); MasterElement *meSCV = dataNeeded.get_cvfem_volume_me(); int nDim = bulkData.mesh_meta_data().spatial_dimension(); int nodesPerElem = topo.num_nodes(); int numScsIp = meSCS != nullptr ? meSCS->numIntPoints_ : 0; int numScvIp = meSCV != nullptr ? meSCV->numIntPoints_ : 0; create_needed_field_views(team, dataNeeded, bulkData, nodesPerElem); create_needed_master_element_views(team, dataNeeded, nDim, nodesPerElem, numScsIp, numScvIp); }
void ScratchViews::create_needed_master_element_views(const TeamHandleType& team, const ElemDataRequests& dataNeeded, int nDim, int nodesPerElem, int numScsIp, int numScvIp) { bool needDeriv = false; bool needDetj = false; const std::set<ELEM_DATA_NEEDED>& dataEnums = dataNeeded.get_data_enums(); for(ELEM_DATA_NEEDED data : dataEnums) { switch(data) { case SCS_AREAV: ThrowRequireMsg(numScsIp > 0, "ERROR, meSCS must be non-null if SCS_AREAV is requested."); scs_areav = get_shmem_view_2D(team, numScsIp, nDim); break; case SCS_GRAD_OP: ThrowRequireMsg(numScsIp > 0, "ERROR, meSCS must be non-null if SCS_GRAD_OP is requested."); dndx = get_shmem_view_3D(team, numScsIp, nodesPerElem, nDim); needDeriv = true; needDetj = true; break; case SCS_SHIFTED_GRAD_OP: ThrowRequireMsg(numScsIp > 0, "ERROR, meSCS must be non-null if SCS_SHIFTED_GRAD_OP is requested."); dndx_shifted = get_shmem_view_3D(team, numScsIp, nodesPerElem, nDim); needDeriv = true; needDetj = true; break; case SCS_GIJ: ThrowRequireMsg(numScsIp > 0, "ERROR, meSCS must be non-null if SCS_GIJ is requested."); gijUpper = get_shmem_view_3D(team, numScsIp, nDim, nDim); gijLower = get_shmem_view_3D(team, numScsIp, nDim, nDim); needDeriv = true; break; case SCV_VOLUME: ThrowRequireMsg(numScvIp > 0, "ERROR, meSCV must be non-null if SCV_VOLUME is requested."); scv_volume = get_shmem_view_1D(team, numScvIp); break; default: break; } } if (needDeriv) deriv = get_shmem_view_1D(team, numScsIp*nodesPerElem*nDim); if (needDetj) det_j = get_shmem_view_1D(team, numScsIp); }
MomentumWallFunctionElemKernel<BcAlgTraits>::MomentumWallFunctionElemKernel( const stk::mesh::BulkData& bulkData, const SolutionOptions& solnOpts, ElemDataRequests& dataPreReqs) : Kernel(), elog_(solnOpts.get_turb_model_constant(TM_elog)), kappa_(solnOpts.get_turb_model_constant(TM_kappa)), yplusCrit_(solnOpts.get_turb_model_constant(TM_yplus_crit)), ipNodeMap_(sierra::nalu::MasterElementRepo::get_surface_master_element(BcAlgTraits::topo_)->ipNodeMap()) { const stk::mesh::MetaData& metaData = bulkData.mesh_meta_data(); VectorFieldType *velocity = metaData.get_field<VectorFieldType>(stk::topology::NODE_RANK, "velocity"); velocityNp1_ = &(velocity->field_of_state(stk::mesh::StateNP1)); bcVelocity_ = metaData.get_field<VectorFieldType>( stk::topology::NODE_RANK, "wall_velocity_bc"); density_ = metaData.get_field<ScalarFieldType>(stk::topology::NODE_RANK, "density"); viscosity_ = metaData.get_field<ScalarFieldType>(stk::topology::NODE_RANK, "viscosity"); exposedAreaVec_ = metaData.get_field<GenericFieldType>(metaData.side_rank(), "exposed_area_vector"); wallFrictionVelocityBip_ = metaData.get_field<GenericFieldType>(metaData.side_rank(), "wall_friction_velocity_bip"); wallNormalDistanceBip_ = metaData.get_field<GenericFieldType>(metaData.side_rank(), "wall_normal_distance_bip"); VectorFieldType *coordinates = metaData.get_field<VectorFieldType>( stk::topology::NODE_RANK, solnOpts.get_coordinates_name()); MasterElement *meFC = sierra::nalu::MasterElementRepo::get_surface_master_element(BcAlgTraits::topo_); // compute and save shape function get_face_shape_fn_data<BcAlgTraits>([&](double* ptr){meFC->shape_fcn(ptr);}, vf_shape_function_); // add master elements dataPreReqs.add_cvfem_face_me(meFC); // fields and data; mdot not gathered as element data dataPreReqs.add_coordinates_field(*coordinates, BcAlgTraits::nDim_, CURRENT_COORDINATES); dataPreReqs.add_gathered_nodal_field(*velocityNp1_, BcAlgTraits::nDim_); dataPreReqs.add_gathered_nodal_field(*bcVelocity_, BcAlgTraits::nDim_); dataPreReqs.add_gathered_nodal_field(*density_, 1); dataPreReqs.add_gathered_nodal_field(*viscosity_, 1); dataPreReqs.add_face_field(*exposedAreaVec_, BcAlgTraits::numFaceIp_, BcAlgTraits::nDim_); dataPreReqs.add_face_field(*wallFrictionVelocityBip_, BcAlgTraits::numFaceIp_); dataPreReqs.add_face_field(*wallNormalDistanceBip_, BcAlgTraits::numFaceIp_); }
void ScratchViews::create_needed_field_views(const TeamHandleType& team, const ElemDataRequests& dataNeeded, const stk::mesh::BulkData& bulkData, int nodesPerElem) { const stk::mesh::MetaData& meta = bulkData.mesh_meta_data(); unsigned numFields = meta.get_fields().size(); fieldViews.resize(numFields, nullptr); const FieldSet& neededFields = dataNeeded.get_fields(); for(const FieldInfo& fieldInfo : neededFields) { stk::mesh::EntityRank fieldEntityRank = fieldInfo.field->entity_rank(); ThrowAssertMsg(fieldEntityRank == stk::topology::NODE_RANK || fieldEntityRank == stk::topology::ELEM_RANK, "Currently only node and element fields are supported."); unsigned scalarsDim1 = fieldInfo.scalarsDim1; unsigned scalarsDim2 = fieldInfo.scalarsDim2; if (fieldEntityRank==stk::topology::ELEM_RANK) { if (scalarsDim2 == 0) { fieldViews[fieldInfo.field->mesh_meta_data_ordinal()] = new ViewT<SharedMemView<double*>>(get_shmem_view_1D(team, scalarsDim1)); } else { fieldViews[fieldInfo.field->mesh_meta_data_ordinal()] = new ViewT<SharedMemView<double**>>(get_shmem_view_2D(team, scalarsDim1, scalarsDim2)); } } else if (fieldEntityRank==stk::topology::NODE_RANK) { if (scalarsDim2 == 0) { if (scalarsDim1 == 1) { fieldViews[fieldInfo.field->mesh_meta_data_ordinal()] = new ViewT<SharedMemView<double*>>(get_shmem_view_1D(team, nodesPerElem)); } else { fieldViews[fieldInfo.field->mesh_meta_data_ordinal()] = new ViewT<SharedMemView<double**>>(get_shmem_view_2D(team, nodesPerElem, scalarsDim1)); } } else { fieldViews[fieldInfo.field->mesh_meta_data_ordinal()] = new ViewT<SharedMemView<double***>>(get_shmem_view_3D(team, nodesPerElem, scalarsDim1, scalarsDim2)); } } else { ThrowRequireMsg(false,"Only elem-rank and node-rank fields supported for scratch-views currently."); } } }
ScalarAdvDiffElemKernel<AlgTraits>::ScalarAdvDiffElemKernel( const stk::mesh::BulkData& bulkData, const SolutionOptions& solnOpts, ScalarFieldType* scalarQ, ScalarFieldType* diffFluxCoeff, ElemDataRequests& dataPreReqs) : Kernel(), scalarQ_(scalarQ), diffFluxCoeff_(diffFluxCoeff), lrscv_(sierra::nalu::MasterElementRepo::get_surface_master_element(AlgTraits::topo_)->adjacentNodes()), shiftedGradOp_(solnOpts.get_shifted_grad_op(scalarQ->name())) { // Save of required fields const stk::mesh::MetaData& metaData = bulkData.mesh_meta_data(); coordinates_ = metaData.get_field<VectorFieldType>( stk::topology::NODE_RANK, solnOpts.get_coordinates_name()); massFlowRate_ = metaData.get_field<GenericFieldType>( stk::topology::ELEMENT_RANK, "mass_flow_rate_scs"); MasterElement *meSCS = sierra::nalu::MasterElementRepo::get_surface_master_element(AlgTraits::topo_); get_scs_shape_fn_data<AlgTraits>([&](double* ptr){meSCS->shape_fcn(ptr);}, v_shape_function_); const bool skewSymmetric = solnOpts.get_skew_symmetric(scalarQ->name()); get_scs_shape_fn_data<AlgTraits>([&](double* ptr){skewSymmetric ? meSCS->shifted_shape_fcn(ptr) : meSCS->shape_fcn(ptr);}, v_adv_shape_function_); dataPreReqs.add_cvfem_surface_me(meSCS); // fields and data dataPreReqs.add_coordinates_field(*coordinates_, AlgTraits::nDim_, CURRENT_COORDINATES); dataPreReqs.add_gathered_nodal_field(*scalarQ_, 1); dataPreReqs.add_gathered_nodal_field(*diffFluxCoeff_, 1); dataPreReqs.add_element_field(*massFlowRate_, AlgTraits::numScsIp_); dataPreReqs.add_master_element_call(SCS_AREAV, CURRENT_COORDINATES); if ( shiftedGradOp_ ) dataPreReqs.add_master_element_call(SCS_SHIFTED_GRAD_OP, CURRENT_COORDINATES); else dataPreReqs.add_master_element_call(SCS_GRAD_OP, CURRENT_COORDINATES); }
ContinuityMassElemSuppAlg<AlgTraits>::ContinuityMassElemSuppAlg( Realm &realm, ElemDataRequests& dataPreReqs, const bool lumpedMass) : SupplementalAlgorithm(realm), densityNm1_(NULL), densityN_(NULL), densityNp1_(NULL), coordinates_(NULL), dt_(0.0), gamma1_(0.0), gamma2_(0.0), gamma3_(0.0), lumpedMass_(lumpedMass), ipNodeMap_(realm.get_volume_master_element(AlgTraits::topo_)->ipNodeMap()) { // save off fields; shove state N into Nm1 if this is BE stk::mesh::MetaData & meta_data = realm_.meta_data(); ScalarFieldType *density = meta_data.get_field<ScalarFieldType>(stk::topology::NODE_RANK, "density"); densityNm1_ = realm_.number_of_states() == 2 ? &(density->field_of_state(stk::mesh::StateN)) : &(density->field_of_state(stk::mesh::StateNM1)); densityN_ = &(density->field_of_state(stk::mesh::StateN)); densityNp1_ = &(density->field_of_state(stk::mesh::StateNP1)); coordinates_ = meta_data.get_field<VectorFieldType>(stk::topology::NODE_RANK, realm_.get_coordinates_name()); MasterElement *meSCV = realm.get_volume_master_element(AlgTraits::topo_); // compute shape function if ( lumpedMass_ ) meSCV->shifted_shape_fcn(&v_shape_function_(0,0)); else meSCV->shape_fcn(&v_shape_function_(0,0)); // add master elements dataPreReqs.add_cvfem_volume_me(meSCV); // fields and data dataPreReqs.add_gathered_nodal_field(*coordinates_, AlgTraits::nDim_); dataPreReqs.add_gathered_nodal_field(*densityNm1_, 1); dataPreReqs.add_gathered_nodal_field(*densityN_, 1); dataPreReqs.add_gathered_nodal_field(*densityNp1_, 1); dataPreReqs.add_master_element_call(SCV_VOLUME); }
MomentumNSOKeElemKernel<AlgTraits>::MomentumNSOKeElemKernel( const stk::mesh::BulkData& bulkData, const SolutionOptions& solnOpts, VectorFieldType* , GenericFieldType* Gju, const double fourthFac, ElemDataRequests& dataPreReqs) : Kernel(), Gju_(Gju), lrscv_(sierra::nalu::MasterElementRepo::get_surface_master_element(AlgTraits::topo_)->adjacentNodes()), fourthFac_(fourthFac), shiftedGradOp_(solnOpts.get_shifted_grad_op("velocity")) { const stk::mesh::MetaData& metaData = bulkData.mesh_meta_data(); velocityNp1_ = metaData.get_field<VectorFieldType>( stk::topology::NODE_RANK, "velocity"); densityNp1_ = metaData.get_field<ScalarFieldType>( stk::topology::NODE_RANK, "density"); pressure_ = metaData.get_field<ScalarFieldType>( stk::topology::NODE_RANK, "pressure"); if (solnOpts.does_mesh_move()) velocityRTM_ = metaData.get_field<VectorFieldType>( stk::topology::NODE_RANK, "velocity_rtm"); else velocityRTM_ = metaData.get_field<VectorFieldType>( stk::topology::NODE_RANK, "velocity"); pressure_ = metaData.get_field<ScalarFieldType>( stk::topology::NODE_RANK, "pressure"); coordinates_ = metaData.get_field<VectorFieldType>( stk::topology::NODE_RANK, solnOpts.get_coordinates_name()); Gjp_ = metaData.get_field<VectorFieldType>(stk::topology::NODE_RANK, "dpdx"); MasterElement *meSCS = sierra::nalu::MasterElementRepo::get_surface_master_element(AlgTraits::topo_); get_scs_shape_fn_data<AlgTraits>([&](double* ptr){meSCS->shape_fcn(ptr);}, v_shape_function_); // add master elements dataPreReqs.add_cvfem_surface_me(meSCS); // fields dataPreReqs.add_gathered_nodal_field(*Gju_, AlgTraits::nDim_, AlgTraits::nDim_); dataPreReqs.add_coordinates_field(*coordinates_, AlgTraits::nDim_, CURRENT_COORDINATES); dataPreReqs.add_gathered_nodal_field(*velocityNp1_, AlgTraits::nDim_); dataPreReqs.add_gathered_nodal_field(*velocityRTM_, AlgTraits::nDim_); dataPreReqs.add_gathered_nodal_field(*Gjp_, AlgTraits::nDim_); dataPreReqs.add_gathered_nodal_field(*densityNp1_,1); dataPreReqs.add_gathered_nodal_field(*pressure_,1); // master element data dataPreReqs.add_master_element_call(SCS_AREAV, CURRENT_COORDINATES); if ( shiftedGradOp_ ) dataPreReqs.add_master_element_call(SCS_SHIFTED_GRAD_OP, CURRENT_COORDINATES); else dataPreReqs.add_master_element_call(SCS_GRAD_OP, CURRENT_COORDINATES); dataPreReqs.add_master_element_call(SCS_GIJ, CURRENT_COORDINATES); }
void fill_pre_req_data( ElemDataRequests& dataNeeded, const stk::mesh::BulkData& bulkData, stk::topology topo, stk::mesh::Entity elem, const stk::mesh::FieldBase* coordField, ScratchViews& prereqData) { int nodesPerElem = topo.num_nodes(); MasterElement *meSCS = dataNeeded.get_cvfem_surface_me(); MasterElement *meSCV = dataNeeded.get_cvfem_volume_me(); prereqData.elemNodes = bulkData.begin_nodes(elem); const FieldSet& neededFields = dataNeeded.get_fields(); for(const FieldInfo& fieldInfo : neededFields) { stk::mesh::EntityRank fieldEntityRank = fieldInfo.field->entity_rank(); unsigned scalarsDim1 = fieldInfo.scalarsDim1; bool isTensorField = fieldInfo.scalarsDim2 > 1; if (fieldEntityRank==stk::topology::ELEM_RANK) { if (isTensorField) { SharedMemView<double**>& shmemView = prereqData.get_scratch_view_2D(*fieldInfo.field); gather_elem_tensor_field(*fieldInfo.field, elem, scalarsDim1, fieldInfo.scalarsDim2, shmemView); } else { SharedMemView<double*>& shmemView = prereqData.get_scratch_view_1D(*fieldInfo.field); unsigned len = shmemView.dimension(0); double* fieldDataPtr = static_cast<double*>(stk::mesh::field_data(*fieldInfo.field, elem)); for(unsigned i=0; i<len; ++i) { shmemView(i) = fieldDataPtr[i]; } } } else if (fieldEntityRank == stk::topology::NODE_RANK) { if (isTensorField) { SharedMemView<double***>& shmemView3D = prereqData.get_scratch_view_3D(*fieldInfo.field); gather_elem_node_tensor_field(*fieldInfo.field, nodesPerElem, scalarsDim1, fieldInfo.scalarsDim2, bulkData.begin_nodes(elem), shmemView3D); } else { if (scalarsDim1 == 1) { SharedMemView<double*>& shmemView1D = prereqData.get_scratch_view_1D(*fieldInfo.field); gather_elem_node_field(*fieldInfo.field, nodesPerElem, prereqData.elemNodes, shmemView1D); } else { SharedMemView<double**>& shmemView2D = prereqData.get_scratch_view_2D(*fieldInfo.field); if (scalarsDim1 == 3) { gather_elem_node_field_3D(*fieldInfo.field, nodesPerElem, prereqData.elemNodes, shmemView2D); } else { gather_elem_node_field(*fieldInfo.field, nodesPerElem, scalarsDim1, prereqData.elemNodes, shmemView2D); } } } } else { ThrowRequireMsg(false, "Only node and element fields supported currently."); } } SharedMemView<double**>* coordsView = nullptr; if (coordField != nullptr) { coordsView = &prereqData.get_scratch_view_2D(*coordField); } const std::set<ELEM_DATA_NEEDED>& dataEnums = dataNeeded.get_data_enums(); double error = 0; for(ELEM_DATA_NEEDED data : dataEnums) { switch(data) { case SCS_AREAV: ThrowRequireMsg(meSCS != nullptr, "ERROR, meSCS needs to be non-null if SCS_AREAV is requested."); ThrowRequireMsg(coordsView != nullptr, "ERROR, coords null but SCS_AREAV requested."); meSCS->determinant(1, &((*coordsView)(0,0)), &prereqData.scs_areav(0,0), &error); break; case SCS_GRAD_OP: ThrowRequireMsg(meSCS != nullptr, "ERROR, meSCS needs to be non-null if SCS_GRAD_OP is requested."); ThrowRequireMsg(coordsView != nullptr, "ERROR, coords null but SCS_GRAD_OP requested."); meSCS->grad_op(1, &((*coordsView)(0,0)), &prereqData.dndx(0,0,0), &prereqData.deriv(0), &prereqData.det_j(0), &error); break; case SCS_SHIFTED_GRAD_OP: ThrowRequireMsg(meSCS != nullptr, "ERROR, meSCS needs to be non-null if SCS_GRAD_OP is requested."); ThrowRequireMsg(coordsView != nullptr, "ERROR, coords null but SCS_GRAD_OP requested."); meSCS->shifted_grad_op(1, &((*coordsView)(0,0)), &prereqData.dndx_shifted(0,0,0), &prereqData.deriv(0), &prereqData.det_j(0), &error); break; case SCS_GIJ: ThrowRequireMsg(meSCS != nullptr, "ERROR, meSCS needs to be non-null if SCS_GIJ is requested."); ThrowRequireMsg(coordsView != nullptr, "ERROR, coords null but SCS_GIJ requested."); meSCS->gij(&((*coordsView)(0,0)), &prereqData.gijUpper(0,0,0), &prereqData.gijLower(0,0,0), &prereqData.deriv(0)); break; case SCV_VOLUME: ThrowRequireMsg(meSCV != nullptr, "ERROR, meSCV needs to be non-null if SCV_VOLUME is requested."); ThrowRequireMsg(coordsView != nullptr, "ERROR, coords null but SCV_VOLUME requested."); meSCV->determinant(1, &((*coordsView)(0,0)), &prereqData.scv_volume(0), &error); break; default: break; } } }
int get_num_bytes_pre_req_data(ElemDataRequests& dataNeededBySuppAlgs, int nDim) { /* master elements are allowed to be null if they are not required */ MasterElement *meSCS = dataNeededBySuppAlgs.get_cvfem_surface_me(); MasterElement *meSCV = dataNeededBySuppAlgs.get_cvfem_volume_me(); const int nodesPerElem = meSCS != nullptr ? meSCS->nodesPerElement_ : 0; const int numScsIp = meSCS != nullptr ? meSCS->numIntPoints_ : 0; const int numScvIp = meSCV != nullptr ? meSCV->numIntPoints_ : 0; int numBytes = 0; const FieldSet& neededFields = dataNeededBySuppAlgs.get_fields(); for(const FieldInfo& fieldInfo : neededFields) { stk::mesh::EntityRank fieldEntityRank = fieldInfo.field->entity_rank(); ThrowAssertMsg(fieldEntityRank == stk::topology::NODE_RANK || fieldEntityRank == stk::topology::ELEM_RANK, "Currently only node and element fields are supported."); unsigned scalarsPerEntity = fieldInfo.scalarsDim1; unsigned entitiesPerElem = fieldEntityRank==stk::topology::ELEM_RANK ? 1 : nodesPerElem; if (fieldInfo.scalarsDim2 > 1) { scalarsPerEntity *= fieldInfo.scalarsDim2; } numBytes += entitiesPerElem*scalarsPerEntity*sizeof(double); } const std::set<ELEM_DATA_NEEDED>& dataEnums = dataNeededBySuppAlgs.get_data_enums(); int dndxLength = 0, gUpperLength = 0, gLowerLength = 0; // Updated logic for data sharing of deriv and det_j bool needDeriv = false; bool needDetj = false; for(ELEM_DATA_NEEDED data : dataEnums) { switch(data) { case SCS_AREAV: numBytes += nDim * numScsIp * sizeof(double); break; case SCS_GRAD_OP: case SCS_SHIFTED_GRAD_OP: dndxLength = nodesPerElem*numScsIp*nDim; needDeriv = true; needDetj = true; numBytes += dndxLength * sizeof(double); break; case SCV_VOLUME: numBytes += numScvIp * sizeof(double); break; case SCS_GIJ: gUpperLength = nDim*nDim*numScsIp; gLowerLength = nDim*nDim*numScsIp; needDeriv = true; numBytes += (gUpperLength + gLowerLength ) * sizeof(double); break; default: break; } } if (needDeriv) numBytes += nodesPerElem*numScsIp*nDim * sizeof(double); if (needDetj) numBytes += numScsIp * sizeof(double); return numBytes*2; }