Select Git revision
ItemValueUtils.hpp
ItemValueUtils.hpp 7.88 KiB
#ifndef ITEM_VALUE_UTILS_HPP
#define ITEM_VALUE_UTILS_HPP
#include <ItemValue.hpp>
#include <Messenger.hpp>
#include <Connectivity.hpp>
#include <Synchronizer.hpp>
#include <SynchronizerManager.hpp>
#include <iostream>
template <typename DataType, ItemType item_type>
std::remove_const_t<DataType>
min(const ItemValue<DataType, item_type>& item_value)
{
using ItemValueType = ItemValue<DataType, item_type>;
using data_type = std::remove_const_t<typename ItemValueType::data_type>;
using index_type = typename ItemValueType::index_type;
const auto& is_owned = [&](const IConnectivity& connectivity) {
Assert((connectivity.dimension() > 0) and (connectivity.dimension() <= 3), "unexpected connectivity dimension");
switch (connectivity.dimension()) {
case 1: {
const auto& connectivity_1d = static_cast<const Connectivity1D&>(connectivity);
return connectivity_1d.isOwned<item_type>();
break;
}
case 2: {
const auto& connectivity_2d = static_cast<const Connectivity2D&>(connectivity);
return connectivity_2d.isOwned<item_type>();
break;
}
case 3: {
const auto& connectivity_3d = static_cast<const Connectivity3D&>(connectivity);
return connectivity_3d.isOwned<item_type>();
break;
}
default: {
std::cerr << __FILE__ << ':' << __LINE__ << ": unexpected dimension\n";
std::terminate();
}
}
}(*item_value.connectivity_ptr());
using IsOwnedType = std::remove_reference_t<decltype(is_owned)>;
class ItemValueMin
{
private:
const ItemValueType& m_item_value;
const IsOwnedType& m_is_owned;
public:
PUGS_INLINE
operator data_type()
{
data_type reduced_value;
parallel_reduce(m_item_value.size(), *this, reduced_value);
return reduced_value;
}
PUGS_INLINE
void
operator()(const index_type& i, data_type& data) const
{
if ((m_is_owned[i]) and (m_item_value[i] < data)) {
data = m_item_value[i];
}
}
PUGS_INLINE
void
join(volatile data_type& dst, const volatile data_type& src) const
{
if (src < dst) {
dst = src;
}
}
PUGS_INLINE
void
init(data_type& value) const
{
value = std::numeric_limits<data_type>::max();
}
PUGS_INLINE
ItemValueMin(const ItemValueType& item_value, const IsOwnedType& is_owned)
: m_item_value(item_value), m_is_owned(is_owned)
{
;
}
PUGS_INLINE
~ItemValueMin() = default;
};
const DataType local_min = ItemValueMin{item_value, is_owned};
return parallel::allReduceMin(local_min);
}
template <typename DataType, ItemType item_type>
std::remove_const_t<DataType>
max(const ItemValue<DataType, item_type>& item_value)
{
using ItemValueType = ItemValue<DataType, item_type>;
using data_type = std::remove_const_t<typename ItemValueType::data_type>;
using index_type = typename ItemValueType::index_type;
const auto& is_owned = [&](const IConnectivity& connectivity) {
Assert((connectivity.dimension() > 0) and (connectivity.dimension() <= 3), "unexpected connectivity dimension");
switch (connectivity.dimension()) {
case 1: {
const auto& connectivity_1d = static_cast<const Connectivity1D&>(connectivity);
return connectivity_1d.isOwned<item_type>();
break;
}
case 2: {
const auto& connectivity_2d = static_cast<const Connectivity2D&>(connectivity);
return connectivity_2d.isOwned<item_type>();
break;
}
case 3: {
const auto& connectivity_3d = static_cast<const Connectivity3D&>(connectivity);
return connectivity_3d.isOwned<item_type>();
break;
}
default: {
std::cerr << __FILE__ << ':' << __LINE__ << ": unexpected dimension\n";
std::terminate();
}
}
}(*item_value.connectivity_ptr());
using IsOwnedType = std::remove_reference_t<decltype(is_owned)>;
class ItemValueMax
{
private:
const ItemValueType& m_item_value;
const IsOwnedType& m_is_owned;
public:
PUGS_INLINE
operator data_type()
{
data_type reduced_value;
parallel_reduce(m_item_value.size(), *this, reduced_value);
return reduced_value;
}
PUGS_INLINE
void
operator()(const index_type& i, data_type& data) const
{
if ((m_is_owned[i]) and (m_item_value[i] > data)) {
data = m_item_value[i];
}
}
PUGS_INLINE
void
join(volatile data_type& dst, const volatile data_type& src) const
{
if (src > dst) {
dst = src;
}
}
PUGS_INLINE
void
init(data_type& value) const
{
value = std::numeric_limits<data_type>::min();
}
PUGS_INLINE
ItemValueMax(const ItemValueType& item_value, const IsOwnedType& is_owned)
: m_item_value(item_value), m_is_owned(is_owned)
{
;
}
PUGS_INLINE
~ItemValueMax() = default;
};
const DataType local_max = ItemValueMax{item_value};
return parallel::allReduceMax(local_max);
}
template <typename DataType, ItemType item_type>
std::remove_const_t<DataType>
sum(const ItemValue<DataType, item_type>& item_value)
{
using ItemValueType = ItemValue<DataType, item_type>;
using data_type = std::remove_const_t<typename ItemValueType::data_type>;
using index_type = typename ItemValueType::index_type;
const auto& is_owned = [&](const IConnectivity& connectivity) {
Assert((connectivity.dimension() > 0) and (connectivity.dimension() <= 3), "unexpected connectivity dimension");
switch (connectivity.dimension()) {
case 1: {
const auto& connectivity_1d = static_cast<const Connectivity1D&>(connectivity);
return connectivity_1d.isOwned<item_type>();
break;
}
case 2: {
const auto& connectivity_2d = static_cast<const Connectivity2D&>(connectivity);
return connectivity_2d.isOwned<item_type>();
break;
}
case 3: {
const auto& connectivity_3d = static_cast<const Connectivity3D&>(connectivity);
return connectivity_3d.isOwned<item_type>();
break;
}
default: {
std::cerr << __FILE__ << ':' << __LINE__ << ": unexpected dimension\n";
std::terminate();
}
}
}(*item_value.connectivity_ptr());
using IsOwnedType = std::remove_reference_t<decltype(is_owned)>;
class ItemValueSum
{
private:
const ItemValueType& m_item_value;
const IsOwnedType& m_is_owned;
public:
PUGS_INLINE
operator data_type()
{
data_type reduced_value;
parallel_reduce(m_item_value.size(), *this, reduced_value);
return reduced_value;
}
PUGS_INLINE
void
operator()(const index_type& i, data_type& data) const
{
if (m_is_owned[i]) {
data += m_item_value[i];
}
}
PUGS_INLINE
void
join(volatile data_type& dst, const volatile data_type& src) const
{
dst += src;
}
PUGS_INLINE
void
init(data_type& value) const
{
if constexpr (std::is_arithmetic_v<data_type>) {
value = 0;
} else {
value = zero;
}
}
PUGS_INLINE
ItemValueSum(const ItemValueType& item_value, const IsOwnedType& is_owned)
: m_item_value(item_value), m_is_owned(is_owned)
{
;
}
PUGS_INLINE
~ItemValueSum() = default;
};
const DataType local_sum = ItemValueSum{item_value, is_owned};
return parallel::allReduceSum(local_sum);
}
template <typename DataType, ItemType item_type, typename ConnectivityPtr>
void
synchronize(ItemValue<DataType, item_type, ConnectivityPtr>& item_value)
{
static_assert(not std::is_const_v<DataType>, "cannot synchronize ItemValue of const data");
if (parallel::size() > 1) {
auto& manager = SynchronizerManager::instance();
const IConnectivity* connectivity = item_value.connectivity_ptr().get();
Synchronizer& synchronizer = manager.getConnectivitySynchronizer(connectivity);
synchronizer.synchronize(item_value);
}
}
#endif // ITEM_VALUE_UTILS_HPP