Skip to content

Commit be29bb8

Browse files
authored
Merge pull request #336 from SCOREC/jacobmerson/field-function-split
Field/Function split: FieldFactory + two-level naming, remove AddLayout
2 parents af3d7d9 + 3d25c46 commit be29bb8

40 files changed

Lines changed: 821 additions & 578 deletions

src/pcms/capi/client.cpp

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "client.h"
22
#include "pcms.h"
3+
#include "pcms/field/field_factory.h"
34
#include "pcms/field/function_space/xgc.h"
45
#include "pcms/field/data/xgc.h"
56
#include "pcms/field/layout/xgc.h"
@@ -23,11 +24,11 @@ namespace detail
2324
template <typename T>
2425
struct XGCFieldRegistration
2526
{
26-
XGCFunctionSpace function_space;
27+
XGCFieldFactory function_space;
2728
MPI_Comm plane_comm;
2829
Rank1View<T, HostMemorySpace> data;
2930

30-
XGCFieldRegistration(XGCFunctionSpace fs, MPI_Comm comm,
31+
XGCFieldRegistration(XGCFieldFactory fs, MPI_Comm comm,
3132
Rank1View<T, HostMemorySpace> d)
3233
: function_space(std::move(fs)), plane_comm(comm), data(d)
3334
{
@@ -37,22 +38,22 @@ struct XGCFieldRegistration
3738
struct DummyFieldRegistration
3839
{};
3940

40-
class EmptyFunctionSpace : public FunctionSpace
41+
class EmptyFieldFactory : public FieldFactory
4142
{
4243
public:
43-
EmptyFunctionSpace() : layout_(std::make_shared<EmptyFieldLayout>()) {}
44+
explicit EmptyFieldFactory(std::string layout_name = "")
45+
{
46+
auto layout = std::make_shared<EmptyFieldLayout>();
47+
layout->SetName(std::move(layout_name));
48+
layout_ = layout;
49+
}
4450

4551
[[nodiscard]] std::shared_ptr<const FieldLayout> GetLayout()
4652
const noexcept override
4753
{
4854
return layout_;
4955
}
5056

51-
[[nodiscard]] CoordinateSystem GetCoordinateSystem() const noexcept override
52-
{
53-
return CoordinateSystem::Cartesian;
54-
}
55-
5657
protected:
5758
[[nodiscard]] FieldVariant CreateFieldImpl(
5859
Type value_type, FieldMetadata metadata) const override
@@ -75,25 +76,19 @@ class EmptyFunctionSpace : public FunctionSpace
7576
PCMS_ALWAYS_ASSERT(fd != nullptr);
7677
if (dynamic_cast<const SimpleFieldData<T>*>(fd.get()) == nullptr) {
7778
throw pcms_error(
78-
"EmptyFunctionSpace::CreateField: requires SimpleFieldData");
79+
"EmptyFieldFactory::CreateField: requires SimpleFieldData");
7980
}
8081
if (fd->GetDOFHolderDataHost().size() !=
8182
detail::ExpectedFlatFieldDataSize(*layout_)) {
8283
throw pcms_error(
83-
"EmptyFunctionSpace::CreateField: field data size does not match "
84+
"EmptyFieldFactory::CreateField: field data size does not match "
8485
"layout");
8586
}
8687
return WrapField<T>(layout_, std::forward<decltype(fd)>(fd));
8788
},
8889
std::move(data));
8990
}
9091

91-
[[nodiscard]] PointEvaluatorVariant CreatePointEvaluatorImpl(
92-
Type /*value_type*/, const EvaluationRequest& /*request*/) const override
93-
{
94-
throw pcms_error("EmptyFunctionSpace does not support point evaluation");
95-
}
96-
9792
private:
9893
std::shared_ptr<const EmptyFieldLayout> layout_;
9994
};
@@ -130,29 +125,31 @@ ClientState::HandleVariant RegisterField(
130125
Application& app, std::string name,
131126
const detail::XGCFieldRegistration<T>& registration, bool participates)
132127
{
128+
// The layout's coupling identity is the field name
129+
// not the arbitrary adapter name given at creation.
130+
registration.function_space.SetLayoutName(name);
133131
auto field = registration.function_space.template CreateField<T>(
134-
std::make_unique<XGCFieldData<T>>(
135-
registration.function_space.GetXGCLayout(), FieldMetadata{},
136-
registration.data));
137-
app.AddLayout(name, registration.function_space.GetLayout(), participates);
132+
std::move(name), std::make_unique<XGCFieldData<T>>(
133+
registration.function_space.GetXGCLayout(),
134+
FieldMetadata{}, registration.data));
138135
std::unique_ptr<FieldSerializer<T>> serializer =
139136
std::make_unique<XGCFieldSerializer<T>>(registration.plane_comm,
140137
participates);
141-
return ClientState::HandleVariant{app.AddField(
142-
std::move(name), std::move(field), std::move(serializer), participates)};
138+
return ClientState::HandleVariant{
139+
app.AddField(std::move(field), std::move(serializer), participates)};
143140
}
144141

145142
inline ClientState::HandleVariant RegisterField(
146143
Application& app, std::string name, const detail::DummyFieldRegistration&,
147144
bool participates)
148145
{
149-
auto function_space = detail::EmptyFunctionSpace{};
150-
app.AddLayout(name, function_space.GetLayout(), participates);
151-
auto field = function_space.CreateField<int>(FieldMetadata{});
146+
auto function_space = detail::EmptyFieldFactory{name};
147+
auto field =
148+
function_space.CreateField<int>(std::move(name), FieldMetadata{});
152149
std::unique_ptr<FieldSerializer<int>> serializer =
153150
std::make_unique<FieldSerializer<int>>();
154-
return ClientState::HandleVariant{app.AddField(
155-
std::move(name), std::move(field), std::move(serializer), participates)};
151+
return ClientState::HandleVariant{
152+
app.AddField(std::move(field), std::move(serializer), participates)};
156153
}
157154

158155
} // namespace pcms
@@ -251,7 +248,7 @@ void pcms_create_xgc_field_adapter_t(
251248
{
252249
PCMS_ALWAYS_ASSERT((size > 0) ? (data != nullptr) : true);
253250
auto function_space =
254-
pcms::XGCFunctionSpace(reverse_classification, in_overlap, size);
251+
pcms::XGCFieldFactory(reverse_classification, in_overlap, size);
255252
pcms::Rank1View<T, pcms::HostMemorySpace> data_view(
256253
reinterpret_cast<T*>(data), size);
257254
field_adapter.emplace<pcms::detail::XGCFieldRegistration<T>>(

src/pcms/coupler/coupler.cpp

Lines changed: 17 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,23 @@
33
namespace pcms
44
{
55

6-
FieldLayoutCommunicator& Application::GetLayoutCommunicator(
7-
const FieldLayout& layout)
6+
FieldLayoutCommunicator& Application::GetOrCreateLayoutCommunicator(
7+
const FieldLayout& layout, bool participates)
88
{
99
PCMS_FUNCTION_TIMER;
10-
auto it = field_layout_communicators_.find(&layout);
10+
const std::string& name = layout.GetName();
11+
if (name.empty()) {
12+
throw pcms_error(
13+
"Application: the field's layout has no name; name it at construction "
14+
"(From*(..., layout_name)) before registering it with a coupler");
15+
}
16+
17+
// Fields whose layouts share a name share one GID-exchange communicator.
18+
auto it = field_layout_communicators_.find(name);
1119
if (it != field_layout_communicators_.end()) {
1220
return *it->second;
13-
} else {
14-
throw pcms_error("Field added with unregistered layout. Call AddLayout() "
15-
"before AddField().");
1621
}
17-
}
1822

19-
const FieldLayout& Application::AddLayout(
20-
std::string name, std::shared_ptr<const FieldLayout> layout,
21-
bool participates)
22-
{
23-
return AddLayout(std::move(name), std::move(layout),
24-
std::make_unique<GenericFieldExchangePlanner>(),
25-
participates);
26-
}
27-
28-
const FieldLayout& Application::AddLayout(
29-
std::string name, std::shared_ptr<const FieldLayout> layout,
30-
std::unique_ptr<FieldExchangePlanner> planner, bool participates)
31-
{
3223
MPI_Comm mpi_comm_subset = MPI_COMM_NULL;
3324
bool own_mpi_comm = false;
3425
PCMS_ALWAYS_ASSERT((mpi_comm_ == MPI_COMM_NULL) ? (!participates) : true);
@@ -39,21 +30,19 @@ const FieldLayout& Application::AddLayout(
3930
&mpi_comm_subset);
4031
own_mpi_comm = true;
4132
}
42-
layouts_.push_back(std::move(layout));
43-
const FieldLayout& layout_ref = *layouts_.back();
4433

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

52-
field_layout_communicators_.emplace(
53-
&layout_ref, std::make_unique<FieldLayoutCommunicator>(
54-
name, mpi_comm_subset, redev_, channel_, layout_ref,
55-
std::move(planner), own_mpi_comm, overlap_mask));
56-
return layout_ref;
40+
auto [it2, inserted] = field_layout_communicators_.emplace(
41+
name, std::make_unique<FieldLayoutCommunicator>(
42+
name, mpi_comm_subset, redev_, channel_, layout,
43+
std::make_unique<GenericFieldExchangePlanner>(), own_mpi_comm,
44+
overlap_mask));
45+
return *it2->second;
5746
}
5847

5948
void Application::SetLayoutOverlapMask(

0 commit comments

Comments
 (0)