Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions src/pcms/coupler/field_communicator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ class FieldCommunicator
PCMS_FUNCTION_TIMER;
PCMS_ALWAYS_ASSERT(layout_comm_.GetChannel().InSendCommunicationPhase());
auto buffer = make_array_view(comm_buffer_);
serializer_->Serialize(field_.GetData(), field_.GetLayout(), buffer,
layout_comm_.GetPermutationArray());
serializer_->Serialize(field_, buffer, layout_comm_.GetPermutationArray());
comm_.Send(buffer.data_handle(), mode);
}

Expand All @@ -64,8 +63,7 @@ class FieldCommunicator
// mode because we make an immediate call to deserialize after a call to
// receive.
auto data = comm_.Recv(redev::Mode::Synchronous);
serializer_->Deserialize(field_.GetData(), field_.GetLayout(),
make_const_array_view(data),
serializer_->Deserialize(field_, make_const_array_view(data),
layout_comm_.GetPermutationArray());
}

Expand Down
13 changes: 3 additions & 10 deletions src/pcms/coupler/field_serializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,15 @@ template <typename T>
class FieldSerializer
{
public:
virtual int Serialize(const FieldData<T>& field, const FieldLayout& layout,
virtual int Serialize(const Field<T>& field,
Rank1View<T, HostMemorySpace> buffer,
Rank1View<const LO, HostMemorySpace> permutation) const
{
auto data = field.GetDOFHolderDataHost();
auto owned = layout.GetOwnedHost();
// The exchange plan is per DOF holder: owned[i] and permutation[i] are
// indexed by holder. All num_components components of a holder share its
// location, so they occupy one contiguous block permutation[i]*num_comp in
// the wire buffer.
if (buffer.size() > 0) {
const LO num_dof = static_cast<LO>(data.extent(0));
const LO num_comp = static_cast<LO>(data.extent(1));
for (LO i = 0; i < num_dof; ++i) {
// A negative permutation entry marks a holder outside the exchange
// (non-owned, or owned but outside the overlap region); it has no slot.
if (permutation[i] >= 0) {
for (LO c = 0; c < num_comp; ++c) {
buffer[permutation[i] * num_comp + c] = data(i, c);
Expand All @@ -41,10 +34,10 @@ class FieldSerializer
}

virtual void Deserialize(
FieldData<T>& field, const FieldLayout& layout,
Rank1View<const T, HostMemorySpace> buffer,
Field<T>& field, Rank1View<const T, HostMemorySpace> buffer,
Rank1View<const LO, HostMemorySpace> permutation) const
{
const auto& layout = field.GetLayout();
const LO num_dof = layout.GetNumOwnedDofHolder();
const LO num_comp = layout.GetNumComponents();
Kokkos::View<T*, HostMemorySpace> sorted("sorted", layout.OwnedSize());
Expand Down
15 changes: 6 additions & 9 deletions src/pcms/coupler/serializer/xgc.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,20 @@ class XGCFieldSerializer : public FieldSerializer<T>
{
}

int Serialize(const FieldData<T>& field, const FieldLayout& layout,
Rank1View<T, HostMemorySpace> buffer,
int Serialize(const Field<T>& field, Rank1View<T, HostMemorySpace> buffer,
Rank1View<const LO, HostMemorySpace> permutation) const override
{
if (!rank_participates_) {
return 0;
}

auto const* xgc_field = dynamic_cast<const XGCFieldData<T>*>(&field);
auto const* xgc_field =
dynamic_cast<const XGCFieldData<T>*>(&field.GetData());
if (!xgc_field) {
throw pcms_error("XGCFieldSerializer::Serialize: incompatible FieldData");
}

auto data = xgc_field->GetDOFHolderDataHost();
auto owned = layout.GetOwnedHost();
// Per-holder plan: owned[i]/permutation[i] index holders; a holder's
// num_components values form one contiguous block in the wire buffer.
if (buffer.size() > 0) {
const LO num_dof = static_cast<LO>(data.extent(0));
const LO num_comp = static_cast<LO>(data.extent(1));
Expand All @@ -54,17 +51,17 @@ class XGCFieldSerializer : public FieldSerializer<T>
}

void Deserialize(
FieldData<T>& field, const FieldLayout& layout,
Rank1View<const T, HostMemorySpace> buffer,
Field<T>& field, Rank1View<const T, HostMemorySpace> buffer,
Rank1View<const LO, HostMemorySpace> permutation) const override
{
auto* xgc_field = dynamic_cast<XGCFieldData<T>*>(&field);
auto* xgc_field = dynamic_cast<XGCFieldData<T>*>(&field.GetData());
if (!xgc_field) {
throw pcms_error(
"XGCFieldSerializer::Deserialize: incompatible FieldData");
}

auto current = xgc_field->GetDOFHolderDataHost();
const auto& layout = field.GetLayout();
const LO num_dof = static_cast<LO>(current.extent(0));
const LO num_comp = static_cast<LO>(current.extent(1));
std::vector<T> full_data(current.size());
Expand Down
3 changes: 2 additions & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,8 @@ if(Catch2_FOUND)
message(
STATUS "Found Catch2: ${Catch2_DIR} (found version ${Catch2_VERSION})")
set(PCMS_UNIT_TEST_SOURCES unit_test_main.cpp test_coordinate_transform.cpp
test_coordinate.cpp test_bounding_box.cpp)
test_coordinate.cpp test_bounding_box.cpp
test_field_serializer.cpp)
if(PCMS_ENABLE_XGC)
list(APPEND PCMS_UNIT_TEST_SOURCES test_xgc_reverse_classification.cpp
test_xgc_field_data.cpp)
Expand Down
34 changes: 0 additions & 34 deletions test/field_test_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include "pcms/field/evaluation_request.h"
#include "pcms/field/point_evaluator.h"
#include "pcms/field/out_of_bounds_policy.h"
#include "pcms/coupler/field_serializer.h"
#include "pcms/field/coordinate_system.h"
#include "pcms/utility/arrays.h"
#include "pcms/utility/memory_spaces.h"
Expand Down Expand Up @@ -366,39 +365,6 @@ inline void SetField(FieldData<Real>& field, const FieldLayout& layout,
SetField<ExecutionSpace>(layout, field, func);
}

// Check that serialize followed by deserialize round-trips the data.
// Uses an identity permutation so permutation[i] = i.
inline void CheckSerializeDeserialize(const FieldLayout& layout,
FieldData<Real>& field)
{
auto data_before = FlattenToRank1View(field.GetDOFHolderDataHost());
int n = static_cast<int>(data_before.size());

std::vector<Real> buffer(n);
std::vector<LO> perm(n);
for (int i = 0; i < n; ++i)
perm[i] = i;

Rank1View<Real, HostMemorySpace> buf_view(buffer.data(), n);
Rank1View<const LO, HostMemorySpace> perm_view(perm.data(), n);

FieldSerializer<Real> serializer;
serializer.Serialize(field, layout, buf_view, perm_view);
serializer.Deserialize(
field, layout, Rank1View<const Real, HostMemorySpace>(buf_view), perm_view);

auto data_after = FlattenToRank1View(field.GetDOFHolderDataHost());
REQUIRE(data_after.size() == data_before.size());
for (int i = 0; i < n; ++i) {
REQUIRE(data_after[i] == Catch::Approx(data_before[i]));
}
}

inline void CheckSerializeDeserialize(Field<Real>& field)
{
CheckSerializeDeserialize(field.GetLayout(), field.GetData());
}

// Helper structure to hold device coordinates with proper lifetime management
struct DeviceCoordinates
{
Expand Down
Loading
Loading