Skip to content
Open
55 changes: 26 additions & 29 deletions src/pcms/capi/client.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "client.h"
#include "pcms.h"
#include "pcms/field/field_factory.h"
#include "pcms/field/function_space/xgc.h"
#include "pcms/field/data/xgc.h"
#include "pcms/field/layout/xgc.h"
Expand All @@ -23,11 +24,11 @@ namespace detail
template <typename T>
struct XGCFieldRegistration
{
XGCFunctionSpace function_space;
XGCFieldFactory function_space;
MPI_Comm plane_comm;
Rank1View<T, HostMemorySpace> data;

XGCFieldRegistration(XGCFunctionSpace fs, MPI_Comm comm,
XGCFieldRegistration(XGCFieldFactory fs, MPI_Comm comm,
Rank1View<T, HostMemorySpace> d)
: function_space(std::move(fs)), plane_comm(comm), data(d)
{
Expand All @@ -37,22 +38,22 @@ struct XGCFieldRegistration
struct DummyFieldRegistration
{};

class EmptyFunctionSpace : public FunctionSpace
class EmptyFieldFactory : public FieldFactory
{
public:
EmptyFunctionSpace() : layout_(std::make_shared<EmptyFieldLayout>()) {}
explicit EmptyFieldFactory(std::string layout_name = "")
{
auto layout = std::make_shared<EmptyFieldLayout>();
layout->SetName(std::move(layout_name));
layout_ = layout;
}

[[nodiscard]] std::shared_ptr<const FieldLayout> GetLayout()
const noexcept override
{
return layout_;
}

[[nodiscard]] CoordinateSystem GetCoordinateSystem() const noexcept override
{
return CoordinateSystem::Cartesian;
}

protected:
[[nodiscard]] FieldVariant CreateFieldImpl(
Type value_type, FieldMetadata metadata) const override
Expand All @@ -75,25 +76,19 @@ class EmptyFunctionSpace : public FunctionSpace
PCMS_ALWAYS_ASSERT(fd != nullptr);
if (dynamic_cast<const SimpleFieldData<T>*>(fd.get()) == nullptr) {
throw pcms_error(
"EmptyFunctionSpace::CreateField: requires SimpleFieldData");
"EmptyFieldFactory::CreateField: requires SimpleFieldData");
}
if (fd->GetDOFHolderDataHost().size() !=
detail::ExpectedFlatFieldDataSize(*layout_)) {
throw pcms_error(
"EmptyFunctionSpace::CreateField: field data size does not match "
"EmptyFieldFactory::CreateField: field data size does not match "
"layout");
}
return WrapField<T>(layout_, std::forward<decltype(fd)>(fd));
},
std::move(data));
}

[[nodiscard]] PointEvaluatorVariant CreatePointEvaluatorImpl(
Type /*value_type*/, const EvaluationRequest& /*request*/) const override
{
throw pcms_error("EmptyFunctionSpace does not support point evaluation");
}

private:
std::shared_ptr<const EmptyFieldLayout> layout_;
};
Expand Down Expand Up @@ -130,29 +125,31 @@ ClientState::HandleVariant RegisterField(
Application& app, std::string name,
const detail::XGCFieldRegistration<T>& registration, bool participates)
{
// The layout's coupling identity is the field name
// not the arbitrary adapter name given at creation.
registration.function_space.SetLayoutName(name);
auto field = registration.function_space.template CreateField<T>(
std::make_unique<XGCFieldData<T>>(
registration.function_space.GetXGCLayout(), FieldMetadata{},
registration.data));
app.AddLayout(name, registration.function_space.GetLayout(), participates);
std::move(name), std::make_unique<XGCFieldData<T>>(
registration.function_space.GetXGCLayout(),
FieldMetadata{}, registration.data));
std::unique_ptr<FieldSerializer<T>> serializer =
std::make_unique<XGCFieldSerializer<T>>(registration.plane_comm,
participates);
return ClientState::HandleVariant{app.AddField(
std::move(name), std::move(field), std::move(serializer), participates)};
return ClientState::HandleVariant{
app.AddField(std::move(field), std::move(serializer), participates)};
}

inline ClientState::HandleVariant RegisterField(
Application& app, std::string name, const detail::DummyFieldRegistration&,
bool participates)
{
auto function_space = detail::EmptyFunctionSpace{};
app.AddLayout(name, function_space.GetLayout(), participates);
auto field = function_space.CreateField<int>(FieldMetadata{});
auto function_space = detail::EmptyFieldFactory{name};
auto field =
function_space.CreateField<int>(std::move(name), FieldMetadata{});
std::unique_ptr<FieldSerializer<int>> serializer =
std::make_unique<FieldSerializer<int>>();
return ClientState::HandleVariant{app.AddField(
std::move(name), std::move(field), std::move(serializer), participates)};
return ClientState::HandleVariant{
app.AddField(std::move(field), std::move(serializer), participates)};
}

} // namespace pcms
Expand Down Expand Up @@ -251,7 +248,7 @@ void pcms_create_xgc_field_adapter_t(
{
PCMS_ALWAYS_ASSERT((size > 0) ? (data != nullptr) : true);
auto function_space =
pcms::XGCFunctionSpace(reverse_classification, in_overlap, size);
pcms::XGCFieldFactory(reverse_classification, in_overlap, size);
pcms::Rank1View<T, pcms::HostMemorySpace> data_view(
reinterpret_cast<T*>(data), size);
field_adapter.emplace<pcms::detail::XGCFieldRegistration<T>>(
Expand Down
45 changes: 17 additions & 28 deletions src/pcms/coupler/coupler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,23 @@
namespace pcms
{

FieldLayoutCommunicator& Application::GetLayoutCommunicator(
const FieldLayout& layout)
FieldLayoutCommunicator& Application::GetOrCreateLayoutCommunicator(
const FieldLayout& layout, bool participates)
{
PCMS_FUNCTION_TIMER;
auto it = field_layout_communicators_.find(&layout);
const std::string& name = layout.GetName();
if (name.empty()) {
throw pcms_error(
"Application: the field's layout has no name; name it at construction "
"(From*(..., layout_name)) before registering it with a coupler");
}

// Fields whose layouts share a name share one GID-exchange communicator.
auto it = field_layout_communicators_.find(name);
if (it != field_layout_communicators_.end()) {
return *it->second;
} else {
throw pcms_error("Field added with unregistered layout. Call AddLayout() "
"before AddField().");
}
}

const FieldLayout& Application::AddLayout(
std::string name, std::shared_ptr<const FieldLayout> layout,
bool participates)
{
return AddLayout(std::move(name), std::move(layout),
std::make_unique<GenericFieldExchangePlanner>(),
participates);
}

const FieldLayout& Application::AddLayout(
std::string name, std::shared_ptr<const FieldLayout> layout,
std::unique_ptr<FieldExchangePlanner> planner, bool participates)
{
MPI_Comm mpi_comm_subset = MPI_COMM_NULL;
bool own_mpi_comm = false;
PCMS_ALWAYS_ASSERT((mpi_comm_ == MPI_COMM_NULL) ? (!participates) : true);
Expand All @@ -39,21 +30,19 @@ const FieldLayout& Application::AddLayout(
&mpi_comm_subset);
own_mpi_comm = true;
}
layouts_.push_back(std::move(layout));
const FieldLayout& layout_ref = *layouts_.back();

// Check if there's an overlap mask for this layout
const OverlapMask* overlap_mask = nullptr;
auto mask_it = layout_overlap_masks_.find(name);
if (mask_it != layout_overlap_masks_.end()) {
overlap_mask = mask_it->second.get();
}

field_layout_communicators_.emplace(
&layout_ref, std::make_unique<FieldLayoutCommunicator>(
name, mpi_comm_subset, redev_, channel_, layout_ref,
std::move(planner), own_mpi_comm, overlap_mask));
return layout_ref;
auto [it2, inserted] = field_layout_communicators_.emplace(
name, std::make_unique<FieldLayoutCommunicator>(
name, mpi_comm_subset, redev_, channel_, layout,
std::make_unique<GenericFieldExchangePlanner>(), own_mpi_comm,
overlap_mask));
return *it2->second;
}

void Application::SetLayoutOverlapMask(
Expand Down
Loading
Loading