inline void createBoundingBoxesForElementsInElementBlocks(const stk::mesh::BulkData &bulk, FlaotBoxVector& domainBoxes) { stk::mesh::EntityVector elements; stk::mesh::get_selected_entities(bulk.mesh_meta_data().locally_owned_part(), bulk.buckets(stk::topology::ELEM_RANK), elements); size_t numberBoundingBoxes = elements.size(); domainBoxes.resize(numberBoundingBoxes); stk::mesh::FieldBase const * coords = bulk.mesh_meta_data().coordinate_field(); std::vector<double> boxCoordinates(6); for(size_t i=0;i<elements.size();++i) { unsigned num_nodes = bulk.num_nodes(elements[i]); std::vector<double> coordinates(3*num_nodes,0); const stk::mesh::Entity* nodes = bulk.begin_nodes(elements[i]); for(unsigned j=0;j<num_nodes;++j) { double* data = static_cast<double*>(stk::mesh::field_data(*coords, nodes[j])); coordinates[3*j] = data[0]; coordinates[3*j+1] = data[1]; coordinates[3*j+2] = data[2]; } findBoundingBoxCoordinates(coordinates, boxCoordinates); unsigned id = bulk.identifier(elements[i]); Ident domainBoxId(id, bulk.parallel_rank()); domainBoxes[i] = std::make_pair(FloatBox(boxCoordinates[0], boxCoordinates[1], boxCoordinates[2], boxCoordinates[3], boxCoordinates[4], boxCoordinates[5]), domainBoxId); } }
OrdinalAndPermutation get_ordinal_and_permutation(const stk::mesh::BulkData& mesh, stk::mesh::Entity parent_entity, stk::mesh::EntityRank to_rank, const stk::mesh::EntityVector &nodes_of_sub_rank) { std::pair<stk::mesh::ConnectivityOrdinal, stk::mesh::Permutation> ordinalAndPermutation = std::make_pair(stk::mesh::INVALID_CONNECTIVITY_ORDINAL, stk::mesh::INVALID_PERMUTATION); unsigned nodes_of_sub_rank_size = nodes_of_sub_rank.size(); const Entity* elemNodes = mesh.begin_nodes(parent_entity); stk::topology elemTopology = mesh.bucket(parent_entity).topology(); unsigned num_entities_of_sub_topology = elemTopology.num_sub_topology(to_rank); unsigned max_nodes_possible = 100; stk::mesh::EntityVector nodes_of_sub_topology; nodes_of_sub_topology.reserve(max_nodes_possible); std::pair<bool, unsigned> result; for (unsigned i=0;i<num_entities_of_sub_topology;++i) { stk::topology sub_topology = elemTopology.sub_topology(to_rank, i); unsigned num_nodes = sub_topology.num_nodes(); if (num_nodes != nodes_of_sub_rank_size) { continue; } ThrowRequireMsg(num_nodes == nodes_of_sub_rank.size(), "AHA! num_nodes != nodes_of_sub_rank.size()"); ThrowRequireMsg(num_nodes<=max_nodes_possible, "Program error. Exceeded expected array dimensions. Contact sierra-help for support."); nodes_of_sub_topology.resize(num_nodes); elemTopology.sub_topology_nodes(elemNodes, to_rank, i, nodes_of_sub_topology.begin()); if (!elemTopology.is_shell() || (to_rank == stk::topology::EDGE_RANK)) { result = sub_topology.equivalent(nodes_of_sub_rank, nodes_of_sub_topology); } else { result = sub_topology.equivalent(nodes_of_sub_rank, nodes_of_sub_topology); if (result.first && result.second >= sub_topology.num_positive_permutations()) { result.first = false; } } if (result.first == true) { ordinalAndPermutation.first = static_cast<stk::mesh::ConnectivityOrdinal>(i); ordinalAndPermutation.second = static_cast<stk::mesh::Permutation>(result.second); } } return ordinalAndPermutation; }
inline void add_nodes_to_move(stk::mesh::BulkData& bulk, stk::mesh::Entity elem, int dest_proc, std::vector<stk::mesh::EntityProc>& entities_to_move) { const stk::mesh::Entity* nodes = bulk.begin_nodes(elem); for(unsigned i = 0; i < bulk.num_nodes(elem); ++i) { if(bulk.parallel_owner_rank(nodes[i]) == bulk.parallel_rank()) { entities_to_move.push_back(stk::mesh::EntityProc(nodes[i], dest_proc)); } } }
inline void createBoundingBoxesForSidesInSidesets(const stk::mesh::BulkData& bulk, std::vector<FloatBox>& domainBoxes) { stk::mesh::ExodusTranslator exoTranslator(bulk); size_t numberBoundingBoxes = 0; std::vector<int64_t> sidesetIds; exoTranslator.fill_side_set_ids(sidesetIds); for (size_t i=0;i<sidesetIds.size();i++) { numberBoundingBoxes += exoTranslator.get_local_num_entities_for_id(sidesetIds[i], bulk.mesh_meta_data().side_rank()); } domainBoxes.resize(numberBoundingBoxes); stk::mesh::FieldBase const * coords = bulk.mesh_meta_data().coordinate_field(); size_t boxCounter = 0; std::vector<double> boxCoordinates(6); for (size_t ssetCounter=0;ssetCounter<sidesetIds.size();ssetCounter++) { const stk::mesh::Part* sideset = exoTranslator.get_exodus_part_of_rank(sidesetIds[ssetCounter], bulk.mesh_meta_data().side_rank()); stk::mesh::EntityVector sides; stk::mesh::Selector sel = bulk.mesh_meta_data().locally_owned_part() & *sideset; stk::mesh::get_selected_entities(sel, bulk.buckets(bulk.mesh_meta_data().side_rank()), sides); for(size_t j=0;j<sides.size();++j) { unsigned num_nodes_per_side = bulk.num_nodes(sides[j]); const stk::mesh::Entity* nodes = bulk.begin_nodes(sides[j]); std::vector<double> coordinates(3*num_nodes_per_side,0); for(unsigned k=0;k<num_nodes_per_side;++k) { double *data = static_cast<double*>(stk::mesh::field_data(*coords, nodes[k])); coordinates[3*k] = data[0]; coordinates[3*k+1] = data[1]; coordinates[3*k+2] = data[2]; } findBoundingBoxCoordinates(coordinates, boxCoordinates); domainBoxes[boxCounter].set_box(boxCoordinates[0], boxCoordinates[1], boxCoordinates[2], boxCoordinates[3], boxCoordinates[4], boxCoordinates[5]); boxCounter++; } } ThrowRequireMsg(boxCounter == numberBoundingBoxes, "Program error. Please contact sierra-help for support"); }
void add_shell_connections_to_this_solid_if_normals_oppose(const stk::mesh::BulkData& mesh, const stk::mesh::Entity localElement, const unsigned sideOrdinal, std::vector<SideData>& connectedElementData) { std::vector<SideData> filteredConnectedElements; stk::topology localElemTopology = mesh.bucket(localElement).topology(); stk::topology localSideTopology = localElemTopology.side_topology(sideOrdinal); bool foundAnySingleElementThatIsEquivalentToLocalElement = false; const stk::mesh::Entity* localElemNodes = mesh.begin_nodes(localElement); stk::mesh::EntityVector localElemSideNodes; localElemSideNodes.resize(localSideTopology.num_nodes()); localElemTopology.side_nodes(localElemNodes, sideOrdinal, localElemSideNodes.begin()); for (const SideData & connectedElem: connectedElementData) { std::pair<bool,unsigned> result = localSideTopology.equivalent(localElemSideNodes, connectedElem.get_side_nodes()); const bool isEquivalentNodes = result.first; foundAnySingleElementThatIsEquivalentToLocalElement = foundAnySingleElementThatIsEquivalentToLocalElement || isEquivalentNodes; if (connectedElem.get_element_topology().is_shell() && isEquivalentNodes) { stk::mesh::OrdinalAndPermutation localElemOrdAndPerm = stk::mesh::get_ordinal_and_permutation(mesh, localElement, mesh.mesh_meta_data().side_rank(), connectedElem.get_side_nodes()); bool localNegativeRelativeFacePolarity = !localSideTopology.is_positive_polarity(localElemOrdAndPerm.second); if (localNegativeRelativeFacePolarity) { filteredConnectedElements.push_back(connectedElem); } } } if (!filteredConnectedElements.empty()) connectedElementData.swap(filteredConnectedElements); if (!foundAnySingleElementThatIsEquivalentToLocalElement) connectedElementData.clear(); }
void fill_sharing_data(stk::mesh::BulkData& bulkData, stk::mesh::ElemElemGraph &graph, const stk::mesh::EntityVector& sidesThatNeedFixing, std::vector<SideSharingData>& sideSharingDataThisProc, std::vector<stk::mesh::impl::IdViaSidePair>& idAndSides) { // Element 1, side 5: face 15 // Element 2, side 3: face 23 // Are these faces the same? Yes: delete face 23, then connect face 15 to element 2 with negative permutation const stk::mesh::PartOrdinal sharedOrd = bulkData.mesh_meta_data().globally_shared_part().mesh_meta_data_ordinal(); for(size_t i=0;i<sidesThatNeedFixing.size();++i) { stk::mesh::impl::ElementViaSidePair elementAndSide = get_element_and_side_ordinal(bulkData, sidesThatNeedFixing[i]); stk::mesh::impl::LocalId localElemId = graph.get_local_element_id(elementAndSide.element); for(const stk::mesh::GraphEdge& edge : graph.get_edges_for_element(localElemId)) { if(edge.side1() == elementAndSide.side && edge.elem2() < 0) { const stk::mesh::impl::ParallelInfo &pInfo = graph.get_parallel_info_for_graph_edge(edge); const stk::mesh::Entity* nodes = bulkData.begin_nodes(sidesThatNeedFixing[i]); unsigned numNodes = bulkData.num_nodes(sidesThatNeedFixing[i]); SideSharingData localTemp({bulkData.identifier(elementAndSide.element), elementAndSide.side}, sidesThatNeedFixing[i], pInfo.get_proc_rank_of_neighbor(), std::min(bulkData.parallel_rank(),pInfo.get_proc_rank_of_neighbor()), bulkData.identifier(sidesThatNeedFixing[i])); localTemp.sideNodes.resize(numNodes); for(unsigned j=0; j<numNodes; ++j) { localTemp.sideNodes[j] = bulkData.identifier(nodes[j]); } fill_part_ordinals_besides_owned_and_shared(bulkData.bucket(sidesThatNeedFixing[i]), sharedOrd, localTemp.partOrdinals); sideSharingDataThisProc.push_back(localTemp); stk::mesh::EntityId localId = -edge.elem2(); idAndSides.push_back({localId, edge.side2()}); } } } }
stk::mesh::EntityVector fill_shared_entities_that_need_fixing(const stk::mesh::BulkData& bulkData) { stk::mesh::EntityVector sides; stk::mesh::get_selected_entities(bulkData.mesh_meta_data().locally_owned_part(), bulkData.buckets(bulkData.mesh_meta_data().side_rank()), sides); stk::mesh::EntityVector sidesThatNeedFixing; for(stk::mesh::Entity side : sides) if(bulkData.state(side) == stk::mesh::Created) { unsigned num_nodes = bulkData.num_nodes(side); const stk::mesh::Entity* nodes = bulkData.begin_nodes(side); std::vector<stk::mesh::EntityKey> nodeKeys(num_nodes); for(unsigned int i=0;i<num_nodes;++i) nodeKeys[i] = bulkData.entity_key(nodes[i]); std::vector<int> shared_procs; bulkData.shared_procs_intersection(nodeKeys, shared_procs); if(!shared_procs.empty()) sidesThatNeedFixing.push_back(side); } return sidesThatNeedFixing; }
void find_ghosted_nodes_that_need_to_be_shared(const stk::mesh::BulkData & bulk, stk::mesh::EntityVector& ghosted_nodes_that_are_now_shared) { stk::mesh::EntityRank endRank = static_cast<stk::mesh::EntityRank>(bulk.mesh_meta_data().entity_rank_count()); if (endRank >= stk::topology::END_RANK) { endRank = stk::topology::END_RANK; } for (stk::mesh::EntityRank rank=stk::topology::EDGE_RANK; rank<endRank; ++rank) { const stk::mesh::BucketVector& entity_buckets = bulk.buckets(rank); for(size_t i=0; i<entity_buckets.size(); ++i) { const stk::mesh::Bucket& bucket = *entity_buckets[i]; if ( bucket.owned() ) { for(size_t n=0; n<bucket.size(); ++n) { const stk::mesh::Entity * nodes = bulk.begin_nodes(bucket[n]); unsigned num_nodes = bulk.num_nodes(bucket[n]); for (unsigned j=0;j<num_nodes;++j) { if (bulk.in_receive_ghost(bulk.entity_key(nodes[j]))) { ghosted_nodes_that_are_now_shared.push_back(nodes[j]); } } } } } } std::sort(ghosted_nodes_that_are_now_shared.begin(), ghosted_nodes_that_are_now_shared.end()); stk::mesh::EntityVector::iterator iter = std::unique(ghosted_nodes_that_are_now_shared.begin(), ghosted_nodes_that_are_now_shared.end()); ghosted_nodes_that_are_now_shared.erase(iter, ghosted_nodes_that_are_now_shared.end()); }
void fill_element_and_side_ids(Ioss::GroupingEntity & io, stk::mesh::Part * const part, const stk::mesh::BulkData & bulk_data, stk::topology stk_element_topology, const stk::mesh::Selector *subset_selector, stk::mesh::EntityVector &sides, std::vector<INT>& elem_side_ids) { if (bulk_data.has_sideset_data()) { const stk::mesh::SideSet& sset = bulk_data.get_sideset_data(part->id()); size_t num_sides = sset.size(); elem_side_ids.reserve(num_sides*2); stk::mesh::Selector selector = *part & ( bulk_data.mesh_meta_data().locally_owned_part() | bulk_data.mesh_meta_data().globally_shared_part() ); if(subset_selector) selector &= *subset_selector; for(size_t i=0;i<sset.size();++i) { stk::mesh::Entity element = sset[i].element; stk::mesh::EntityId elemId = bulk_data.identifier(element); int zero_based_side_ord = sset[i].side; stk::mesh::Entity side = stk::mesh::get_side_entity_for_elem_id_side_pair_of_rank(bulk_data, elemId, zero_based_side_ord, bulk_data.mesh_meta_data().side_rank()); if(bulk_data.is_valid(side)) { if(selector(bulk_data.bucket(side))) { if(bulk_data.bucket(element).topology() == stk_element_topology) { elem_side_ids.push_back(elemId); elem_side_ids.push_back(zero_based_side_ord+1); sides.push_back(side); } } } } } else { const stk::mesh::MetaData & meta_data = stk::mesh::MetaData::get(*part); stk::mesh::EntityRank type = part_primary_entity_rank(*part); size_t num_sides = get_entities(*part, type, bulk_data, sides, false, subset_selector); elem_side_ids.reserve(num_sides * 2); stk::mesh::EntityRank elem_rank = stk::topology::ELEMENT_RANK; for(size_t i = 0; i < num_sides; ++i) { std::vector<stk::mesh::Entity> side; side.push_back(sides[i]); std::vector<stk::mesh::Entity> side_elements; std::vector<stk::mesh::Entity> side_nodes(bulk_data.begin_nodes(sides[i]), bulk_data.end_nodes(sides[i])); get_entities_through_relations(bulk_data, side_nodes, elem_rank, side_elements); const size_t num_side_elem = side_elements.size(); std::sort(side_elements.begin(), side_elements.end(), stk::mesh::EntityLess(bulk_data)); stk::mesh::Entity suitable_elem = stk::mesh::Entity(); stk::mesh::ConnectivityOrdinal suitable_ordinal = stk::mesh::INVALID_CONNECTIVITY_ORDINAL; for(size_t j = 0; j < num_side_elem; ++j) { const stk::mesh::Entity elem = side_elements[j]; const stk::mesh::Bucket &elemBucket = bulk_data.bucket(elem); const bool isSelectingEverything = subset_selector == NULL; const bool isElementBeingOutput = (isSelectingEverything || (*subset_selector)(elemBucket)) && elemBucket.member(meta_data.locally_owned_part()); if(isElementBeingOutput) { const stk::mesh::Entity * elem_sides = bulk_data.begin(elem, type); stk::mesh::ConnectivityOrdinal const * side_ordinal = bulk_data.begin_ordinals(elem, type); const size_t num_elem_sides = bulk_data.num_connectivity(elem, type); for(size_t k = 0; k < num_elem_sides; ++k) { if(elem_sides[k] == side[0]) { suitable_elem = elem; suitable_ordinal = side_ordinal[k]; break; } } } } if(!bulk_data.is_valid(suitable_elem)) { std::ostringstream oss; oss << "ERROR, no suitable element found"; throw std::runtime_error(oss.str()); } elem_side_ids.push_back(bulk_data.identifier(suitable_elem)); elem_side_ids.push_back(suitable_ordinal + 1); // Ioss is 1-based, mesh is 0-based. } } }
Intrepid::FieldContainer<double> STKMeshHelpers::extractEntityNodeCoordinates( const Teuchos::Array<stk::mesh::Entity>& stk_entities, const stk::mesh::BulkData& bulk_data, const int space_dim ) { // Cast the field. const stk::mesh::FieldBase* coord_field_base= bulk_data.mesh_meta_data().coordinate_field(); const stk::mesh::Field<double,FieldType>* coord_field = dynamic_cast<const stk::mesh::Field<double,FieldType>* >( coord_field_base); // Allocate the coordinate array. int num_cells = stk_entities.size(); int num_nodes = 0; stk::mesh::EntityRank stk_rank = stk::topology::INVALID_RANK; if ( num_cells > 0 ) { stk_rank = bulk_data.entity_rank(stk_entities[0]); if ( stk::topology::NODE_RANK == stk_rank ) { num_nodes = 1; } else { const stk::mesh::Entity* begin = bulk_data.begin_nodes( stk_entities[0] ); const stk::mesh::Entity* end = bulk_data.end_nodes( stk_entities[0] ); num_nodes = std::distance( begin, end ); } } Intrepid::FieldContainer<double> coords( num_cells, num_nodes, space_dim ); // Extract the coordinates. double* node_coords = 0; for ( int c = 0; c < num_cells; ++c ) { if ( stk::topology::NODE_RANK == stk_rank ) { node_coords = stk::mesh::field_data( *coord_field, stk_entities[c] ); for ( int d = 0; d < space_dim; ++d ) { coords(c,0,d) = node_coords[d]; } } else { const stk::mesh::Entity* begin = bulk_data.begin_nodes( stk_entities[c] ); DTK_REMEMBER( const stk::mesh::Entity* end = bulk_data.end_nodes( stk_entities[c] ) ); DTK_CHECK( std::distance(begin,end) == num_nodes ); for ( int n = 0; n < num_nodes; ++n ) { node_coords = stk::mesh::field_data( *coord_field, begin[n] ); for ( int d = 0; d < space_dim; ++d ) { coords(c,n,d) = node_coords[d]; } } } } return coords; }
void setup_elem_entities_and_connectivity_tables(const stk::mesh::BulkData& bulk, const stk::mesh::Selector& selector) { const stk::mesh::BucketVector& elementBuckets = bulk.get_buckets(stk::topology::ELEM_RANK, selector); unsigned numElementBuckets = elementBuckets.size(); connBucketOffsets = DeviceViewIntType("D_connBucketOffsets", numElementBuckets); hostConnBucketOffsets = Kokkos::create_mirror_view(connBucketOffsets); elemBucketOffsets = DeviceViewIntType("D_elemBucketOffsets", numElementBuckets); hostElemBucketOffsets = Kokkos::create_mirror_view(elemBucketOffsets); elemsPerBucket = DeviceViewIntType("D_elemsPerBucket", numElementBuckets); hostElemsPerBucket = Kokkos::create_mirror_view(elemsPerBucket); nodesPerElement = DeviceViewIntType("D_nodesPerElement", numElementBuckets); hostNodesPerElement = Kokkos::create_mirror_view(nodesPerElement); unsigned numConnectivities = 0; unsigned numElements = 0; for (unsigned elemBucketIndex = 0; elemBucketIndex < numElementBuckets; ++elemBucketIndex) { const stk::mesh::Bucket& bucket = *elementBuckets[elemBucketIndex]; unsigned numNodesPerElem = bucket.topology().num_nodes(); unsigned numElemsInBucket = bucket.size(); hostConnBucketOffsets(elemBucketIndex) = numConnectivities; hostElemBucketOffsets(elemBucketIndex) = numElements; hostNodesPerElement(elemBucketIndex) = numNodesPerElem; hostElemsPerBucket(elemBucketIndex) = numElemsInBucket; numConnectivities += numNodesPerElem*numElemsInBucket; numElements += numElemsInBucket; } Kokkos::deep_copy(elemsPerBucket, hostElemsPerBucket); Kokkos::deep_copy(nodesPerElement, hostNodesPerElement); Kokkos::deep_copy(connBucketOffsets, hostConnBucketOffsets); Kokkos::deep_copy(elemBucketOffsets, hostElemBucketOffsets); elementNodeConnectivity = DeviceViewFlatConnectivityType("DElementNodeConnectivity", numConnectivities); hostElementNodeConnectivity = Kokkos::create_mirror_view(elementNodeConnectivity); elemEntities = DeviceViewEntitiesType("DElemEntities", numElements); hostElemEntities = Kokkos::create_mirror_view(elemEntities); for (unsigned elemBucketIndex = 0; elemBucketIndex < numElementBuckets; ++elemBucketIndex) { unsigned connBucketOffset = hostConnBucketOffsets(elemBucketIndex); unsigned elemBucketOffset = hostElemBucketOffsets(elemBucketIndex); const stk::mesh::Bucket& bucket = *elementBuckets[elemBucketIndex]; unsigned nodesPerElem = bucket.topology().num_nodes(); for(unsigned elemIndex = 0; elemIndex < bucket.size(); ++elemIndex) { unsigned connElemOffset = elemIndex*nodesPerElem + connBucketOffset; stk::mesh::Entity element = bucket[elemIndex]; hostElemEntities(elemBucketOffset + elemIndex) = element; const stk::mesh::Entity * elemNodes = bulk.begin_nodes(element); for(unsigned iNode = 0; iNode < nodesPerElem; ++iNode) { unsigned nodeOffset = connElemOffset + iNode; hostElementNodeConnectivity(nodeOffset) = elemNodes[iNode]; } } } Kokkos::deep_copy(elementNodeConnectivity, hostElementNodeConnectivity); Kokkos::deep_copy(elemEntities, hostElemEntities); }
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; } } }