Select Git revision
ConnectivityDispatcher.hpp
-
Stéphane Del Pino authoredStéphane Del Pino authored
ConnectivityDispatcher.hpp 11.38 KiB
#ifndef CONNECTIVITY_DISPATCHER_HPP
#define CONNECTIVITY_DISPATCHER_HPP
#include <Mesh.hpp>
#include <ItemValue.hpp>
#include <ItemValueUtils.hpp>
#include <unordered_map>
#include <ConnectivityDescriptor.hpp>
template <int Dimension>
class ConnectivityDispatcher
{
public:
using ConnectivityType = Connectivity<Dimension>;
private:
const ConnectivityType& m_connectivity;
ConnectivityDescriptor m_new_descriptor;
std::shared_ptr<ConnectivityType> m_dispatched_connectivity;
template <ItemType item_type>
struct DispatchedItemInfo
{
using ItemId = ItemIdT<item_type>;
ItemValue<const int, item_type> m_new_owner;
Array<const unsigned int> m_list_to_send_size_by_proc;
std::vector<Array<const ItemId>> m_list_to_send_by_proc;
Array<const unsigned int> m_list_to_recv_size_by_proc;
std::unordered_map<int, int> m_number_to_id_map;
std::vector<Array<const ItemId>> m_recv_id_correspondance_by_proc;
};
DispatchedItemInfo<ItemType::cell> m_dispatched_cell_info;
DispatchedItemInfo<ItemType::face> m_dispatched_face_info;
DispatchedItemInfo<ItemType::edge> m_dispatched_edge_info;
DispatchedItemInfo<ItemType::node> m_dispatched_node_info;
template <ItemType item_type>
PASTIS_INLINE
DispatchedItemInfo<item_type>& _dispatchedInfo()
{
if constexpr (item_type == ItemType::cell) {
return m_dispatched_cell_info;
} else if constexpr (item_type == ItemType::face) {
return m_dispatched_face_info;
} else if constexpr (item_type == ItemType::edge) {
return m_dispatched_edge_info;
} else {
return m_dispatched_node_info;
}
}
template <ItemType item_type>
PASTIS_INLINE
const DispatchedItemInfo<item_type>& _dispatchedInfo() const
{
if constexpr (item_type == ItemType::cell) {
return m_dispatched_cell_info;
} else if constexpr (item_type == ItemType::face) {
return m_dispatched_face_info;
} else if constexpr (item_type == ItemType::edge) {
return m_dispatched_edge_info;
} else {
return m_dispatched_node_info;
}
}
template <typename ItemToItem>
struct DispatchedItemOfItemInfo
{
std::vector<Array<const int>> m_number_of_sub_item_per_item_to_recv_by_proc;
std::vector<Array<const int>> m_sub_item_numbers_to_recv_by_proc;
};
DispatchedItemOfItemInfo<NodeOfCell> m_dispatched_node_of_cell_info;
DispatchedItemOfItemInfo<EdgeOfCell> m_dispatched_edge_of_cell_info;
DispatchedItemOfItemInfo<FaceOfCell> m_dispatched_face_of_cell_info;
DispatchedItemOfItemInfo<NodeOfEdge> m_dispatched_node_of_edge_info;
DispatchedItemOfItemInfo<FaceOfEdge> m_dispatched_face_of_edge_info;
DispatchedItemOfItemInfo<CellOfEdge> m_dispatched_cell_of_edge_info;
DispatchedItemOfItemInfo<NodeOfFace> m_dispatched_node_of_face_info;
DispatchedItemOfItemInfo<EdgeOfFace> m_dispatched_edge_of_face_info;
DispatchedItemOfItemInfo<CellOfFace> m_dispatched_cell_of_face_info;
DispatchedItemOfItemInfo<EdgeOfNode> m_dispatched_edge_of_node_info;
DispatchedItemOfItemInfo<FaceOfNode> m_dispatched_face_of_node_info;
DispatchedItemOfItemInfo<CellOfNode> m_dispatched_cell_of_node_info;
template <typename ItemOfItem>
PASTIS_INLINE
DispatchedItemOfItemInfo<ItemOfItem>& _dispatchedInfo()
{
if constexpr (std::is_same_v<NodeOfCell, ItemOfItem>) {
return m_dispatched_node_of_cell_info;
} else if constexpr (std::is_same_v<EdgeOfCell, ItemOfItem>) {
return m_dispatched_edge_of_cell_info;
} else if constexpr (std::is_same_v<FaceOfCell, ItemOfItem>) {
return m_dispatched_face_of_cell_info;
} else if constexpr (std::is_same_v<NodeOfEdge, ItemOfItem>) {
return m_dispatched_node_of_edge_info;
} else if constexpr (std::is_same_v<FaceOfEdge, ItemOfItem>) {
return m_dispatched_face_of_edge_info;
} else if constexpr (std::is_same_v<CellOfEdge, ItemOfItem>) {
return m_dispatched_cell_of_edge_info;
} else if constexpr (std::is_same_v<NodeOfFace, ItemOfItem>) {
return m_dispatched_node_of_face_info;
} else if constexpr (std::is_same_v<EdgeOfFace, ItemOfItem>) {
return m_dispatched_edge_of_face_info;
} else if constexpr (std::is_same_v<CellOfFace, ItemOfItem>) {
return m_dispatched_cell_of_face_info;
} else if constexpr (std::is_same_v<EdgeOfNode, ItemOfItem>) {
return m_dispatched_edge_of_node_info;
} else if constexpr (std::is_same_v<FaceOfNode, ItemOfItem>) {
return m_dispatched_face_of_node_info;
} else if constexpr (std::is_same_v<CellOfNode, ItemOfItem>) {
return m_dispatched_cell_of_node_info;
} else {
static_assert(is_false_v<ItemOfItem>, "Unexpected ItemOfItem type");
}
}
template <typename ItemOfItem>
PASTIS_INLINE
const DispatchedItemOfItemInfo<ItemOfItem>& _dispatchedInfo() const
{
if constexpr (std::is_same_v<NodeOfCell, ItemOfItem>) {
return m_dispatched_node_of_cell_info;
} else if constexpr (std::is_same_v<EdgeOfCell, ItemOfItem>) {
return m_dispatched_edge_of_cell_info;
} else if constexpr (std::is_same_v<FaceOfCell, ItemOfItem>) {
return m_dispatched_face_of_cell_info;
} else if constexpr (std::is_same_v<NodeOfEdge, ItemOfItem>) {
return m_dispatched_node_of_edge_info;
} else if constexpr (std::is_same_v<FaceOfEdge, ItemOfItem>) {
return m_dispatched_face_of_edge_info;
} else if constexpr (std::is_same_v<CellOfEdge, ItemOfItem>) {
return m_dispatched_cell_of_edge_info;
} else if constexpr (std::is_same_v<NodeOfFace, ItemOfItem>) {
return m_dispatched_node_of_face_info;
} else if constexpr (std::is_same_v<EdgeOfFace, ItemOfItem>) {
return m_dispatched_edge_of_face_info;
} else if constexpr (std::is_same_v<CellOfFace, ItemOfItem>) {
return m_dispatched_cell_of_face_info;
} else if constexpr (std::is_same_v<EdgeOfNode, ItemOfItem>) {
return m_dispatched_edge_of_node_info;
} else if constexpr (std::is_same_v<FaceOfNode, ItemOfItem>) {
return m_dispatched_face_of_node_info;
} else if constexpr (std::is_same_v<CellOfNode, ItemOfItem>) {
return m_dispatched_cell_of_node_info;
} else {
static_assert(is_false_v<ItemOfItem>, "Unexpected ItemOfItem type");
}
}
template <ItemType item_type>
void _buildNewOwner();
template <ItemType item_type>
void _buildItemListToSend();
void _buildCellNumberIdMap();
template <typename ItemOfItemT>
void _buildSubItemNumberToIdMap();
template <ItemType item_type>
void _buildItemToExchangeLists();
template <ItemType item_type>
void _buildNumberOfItemToExchange();
template <typename ItemOfItemT>
void _buildItemToSubItemDescriptor();
void _dispatchEdges();
void _dispatchFaces();
template<typename DataType, ItemType item_type, typename ConnectivityPtr>
void _gatherFrom(const ItemValue<DataType, item_type, ConnectivityPtr>& data_to_gather,
std::vector<std::remove_const_t<DataType>>& gathered_vector);
template<typename DataType, typename ItemOfItem, typename ConnectivityPtr>
void _gatherFrom(const SubItemValuePerItem<DataType, ItemOfItem, ConnectivityPtr>& data_to_gather,
std::vector<Array<std::remove_const_t<DataType>>>& gathered_vector);
template <typename SubItemOfItemT>
void _buildNumberOfSubItemPerItemToRecvByProc();
template <typename SubItemOfItemT>
void _buildSubItemNumbersToRecvByProc();
template <ItemType item_type>
void _buildRecvItemIdCorrespondanceByProc();
template <ItemType item_type>
void _buildItemReferenceList();
public:
std::shared_ptr<const ConnectivityType>
dispatchedConnectivity() const
{
return m_dispatched_connectivity;
}
template<typename DataType, ItemType item_type, typename ConnectivityPtr>
std::vector<Array<const DataType>>
exchange(ItemValue<DataType, item_type, ConnectivityPtr> item_value) const
{
using ItemId = ItemIdT<item_type>;
using MutableDataType = std::remove_const_t<DataType>;
std::vector<Array<const DataType>> item_value_to_send_by_proc(parallel::size());
const auto& item_list_to_send_by_proc = this->_dispatchedInfo<item_type>().m_list_to_send_by_proc;
for (size_t i=0; i<parallel::size(); ++i) {
const Array<const ItemId>& item_list = item_list_to_send_by_proc[i];
Array<MutableDataType> item_value_list(item_list.size());
parallel_for (item_list.size(), PASTIS_LAMBDA(const ItemId& item_id) {
item_value_list[item_id] = item_value[item_list[item_id]];
});
item_value_to_send_by_proc[i] = item_value_list;
}
std::vector<Array<MutableDataType>> recv_item_value_by_proc(parallel::size());
{
const auto& list_to_recv_size_by_proc = this->_dispatchedInfo<item_type>().m_list_to_recv_size_by_proc;
for (size_t i=0; i<parallel::size(); ++i) {
recv_item_value_by_proc[i] = Array<MutableDataType>(list_to_recv_size_by_proc[i]);
}
}
parallel::exchange(item_value_to_send_by_proc, recv_item_value_by_proc);
std::vector<Array<const DataType>> const_recv_item_value_by_proc(parallel::size());
for (size_t i=0; i<parallel::size(); ++i) {
const_recv_item_value_by_proc[i] = recv_item_value_by_proc[i];
}
return const_recv_item_value_by_proc;
}
template<typename DataType, ItemType item_type, typename ConnectivityPtr>
ItemValue<std::remove_const_t<DataType>, item_type, ConnectivityPtr>
dispatch(ItemValue<DataType, item_type, ConnectivityPtr> item_value) const
{
using ItemId = ItemIdT<item_type>;
Assert(m_dispatched_connectivity.use_count()> 0,
"cannot dispatch quantity before connectivity");
const auto& item_list_to_send_by_proc = this->_dispatchedInfo<item_type>().m_list_to_send_by_proc;
using MutableDataType = std::remove_const_t<DataType>;
std::vector<Array<DataType>> item_value_to_send_by_proc(parallel::size());
for (size_t i=0; i<parallel::size(); ++i) {
const Array<const ItemId>& item_list = item_list_to_send_by_proc[i];
Array<MutableDataType> item_value_list(item_list.size());
parallel_for (item_list.size(), PASTIS_LAMBDA(const ItemId& item_id) {
item_value_list[item_id] = item_value[item_list[item_id]];
});
item_value_to_send_by_proc[i] = item_value_list;
}
const auto& item_list_to_recv_size_by_proc = this->_dispatchedInfo<item_type>().m_list_to_recv_size_by_proc;
std::vector<Array<MutableDataType>> recv_item_value_by_proc(parallel::size());
for (size_t i=0; i<parallel::size(); ++i) {
recv_item_value_by_proc[i] = Array<MutableDataType>(item_list_to_recv_size_by_proc[i]);
}
parallel::exchange(item_value_to_send_by_proc, recv_item_value_by_proc);
const auto& recv_item_id_correspondance_by_proc =
this->_dispatchedInfo<item_type>().m_recv_id_correspondance_by_proc;
ItemValue<MutableDataType, item_type> new_item_value(*m_dispatched_connectivity);
for (size_t i_rank=0; i_rank<parallel::size(); ++i_rank) {
const auto& recv_item_id_correspondance = recv_item_id_correspondance_by_proc[i_rank];
const auto& recv_item_value = recv_item_value_by_proc[i_rank];
parallel_for(recv_item_value.size(), PASTIS_LAMBDA(size_t r) {
const ItemId& item_id = recv_item_id_correspondance[r];
new_item_value[item_id] = recv_item_value[r];
});
}
return new_item_value;
}
ConnectivityDispatcher(const ConnectivityType& mesh);
ConnectivityDispatcher(const ConnectivityDispatcher&) = delete;
~ConnectivityDispatcher() = default;
};
#endif // CONNECTIVITY_DISPATCHER_HPP