55#include " evaluation_request.h"
66#include " field.h"
77#include " field_data.h"
8- #include " field_evaluator_factory .h"
8+ #include " field_factory .h"
99#include " field_layout.h"
1010#include " field_metadata.h"
1111#include " out_of_bounds_policy.h"
2020namespace pcms
2121{
2222
23- namespace detail
24- {
25-
26- inline size_t ExpectedFlatFieldDataSize (const FieldLayout& layout)
27- {
28- return static_cast <size_t >(layout.GetNumOwnedDofHolder ()) *
29- static_cast <size_t >(layout.GetNumComponents ());
30- }
31-
32- } // namespace detail
33-
34- // Compile-time gate: true only for the five supported field value types.
35- template <typename T>
36- inline constexpr bool is_supported_field_type_v =
37- std::is_same_v<T, int8_t > || std::is_same_v<T, int32_t > ||
38- std::is_same_v<T, int64_t > || std::is_same_v<T, float > ||
39- std::is_same_v<T, double >;
40-
4123// FunctionSpace is an abstract interface representing an evaluatable field
42- // space: layout, evaluation rules, and coordinate interpretation.
24+ // space: layout, evaluation rules, and coordinate interpretation. It produces
25+ // Functions (a Field bound to this space).
4326//
4427// Concrete implementations (e.g. LagrangeFunctionSpace) provide backends for
45- // specific discretizations or mesh types.
46- //
47- // FunctionSpace is used as the parameter type for operation objects such as
48- // Interpolator<T>, so that operations are not coupled to a specific backend.
49- //
50- // FunctionSpace inherits enable_shared_from_this because CreateFunction stamps
51- // a shared_ptr<const FunctionSpace> into each Function it produces. Concrete
52- // spaces must therefore be owned by a shared_ptr (the From* factories return
53- // one); calling CreateFunction on a stack-allocated space throws bad_weak_ptr.
28+ // specific discretizations or mesh types, and their From* factories return a
29+ // shared_ptr. A Function co-owns its space via shared_ptr (obtained through
30+ // enable_shared_from_this), which is why concrete spaces are always
31+ // shared-owned; a stack-allocated FunctionSpace is not constructible (the
32+ // backend constructors are private and reachable only via the shared_ptr
33+ // From* factories).
5434class FunctionSpace : public std ::enable_shared_from_this<FunctionSpace>
5535{
5636public:
@@ -66,28 +46,13 @@ class FunctionSpace : public std::enable_shared_from_this<FunctionSpace>
6646
6747 virtual ~FunctionSpace () noexcept = default ;
6848
69- // Create a new named field with freshly allocated data for this function
70- // space. The name is optional (empty by default) and identifies the field to
71- // consumers such as a coupler. Compile-time error for unsupported T; runtime
72- // error for T unsupported by the concrete backend.
73- template <typename T>
74- [[nodiscard]] Field<T> CreateField (std::string name = " " ,
75- FieldMetadata metadata = {}) const ;
76-
77- // Expert API: wrap externally constructed field data into a Field for this
78- // function space. The concrete function space validates backend-specific
79- // field-data type and storage size compatibility.
80- template <typename T>
81- [[nodiscard]] Field<T> CreateField (std::string name,
82- std::unique_ptr<FieldData<T>> data) const ;
83-
84- // Like CreateField, but returns a Function that retains a shared reference to
85- // this space (so it can be evaluated / used to build transfer operators).
86- // Requires this space to be owned by a shared_ptr (see class note).
8749 template <typename T>
8850 [[nodiscard]] Function<T> CreateFunction (std::string name = " " ,
8951 FieldMetadata metadata = {}) const ;
9052
53+ // Expert API: wrap externally constructed field data into a Function for this
54+ // space. The concrete space validates backend-specific field-data type and
55+ // storage size compatibility.
9156 template <typename T>
9257 [[nodiscard]] Function<T> CreateFunction (
9358 std::string name, std::unique_ptr<FieldData<T>> data) const ;
@@ -132,70 +97,30 @@ class FunctionSpace : public std::enable_shared_from_this<FunctionSpace>
13297 Type value_type, const EvaluationRequest& request) const = 0;
13398};
13499
135- // Wrap a by-value FunctionSpace (typically the result of a From* factory) in a
136- // shared_ptr so it can produce Functions and participate in transfers via
137- // AddFunction/CreateTransfer. Ordinary by-value use — CreateField, point
138- // evaluation, constructing a transfer operator directly — does not need this;
139- // only Function (which retains a shared_ptr<const FunctionSpace>) does.
140- //
141- // auto space = pcms::Share(LagrangeFunctionSpace::FromMesh(...));
142- // auto fn = space->CreateFunction<Real>();
143- template <typename Space>
144- [[nodiscard]] std::shared_ptr<Space> Share (Space&& space)
145- {
146- static_assert (
147- std::is_base_of_v<FunctionSpace, std::remove_reference_t <Space>>,
148- " Share expects a FunctionSpace-derived type" );
149- return std::make_shared<std::remove_reference_t <Space>>(
150- std::forward<Space>(space));
151- }
152-
153100template <typename T>
154- Field <T> FunctionSpace::CreateField (std::string name,
155- FieldMetadata metadata) const
101+ Function <T> FunctionSpace::CreateFunction (std::string name,
102+ FieldMetadata metadata) const
156103{
157104 static_assert (is_supported_field_type_v<T>,
158105 " T is not a supported field type" );
159106 Field<T> field =
160107 std::get<Field<T>>(CreateFieldImpl (TypeEnumFromType<T>(), metadata));
161- field. name_ = std::move (name);
162- return field;
108+ return WrapFunction<T>( std::move (name), std::move (field. layout_ ),
109+ std::move ( field. data_ ), shared_from_this ()) ;
163110}
164111
165112template <typename T>
166- Field <T> FunctionSpace::CreateField (std::string name,
167- std::unique_ptr<FieldData<T>> data) const
113+ Function <T> FunctionSpace::CreateFunction (
114+ std::string name, std::unique_ptr<FieldData<T>> data) const
168115{
169116 static_assert (is_supported_field_type_v<T>,
170117 " T is not a supported field type" );
171118 if (!data) {
172- throw pcms_error (" FunctionSpace::CreateField : data must not be null" );
119+ throw pcms_error (" FunctionSpace::CreateFunction : data must not be null" );
173120 }
174121 Field<T> field =
175122 std::get<Field<T>>(CreateFieldImpl (FieldDataVariant{std::move (data)}));
176- field.name_ = std::move (name);
177- return field;
178- }
179-
180- template <typename T>
181- Function<T> FunctionSpace::CreateFunction (std::string name,
182- FieldMetadata metadata) const
183- {
184- static_assert (is_supported_field_type_v<T>,
185- " T is not a supported field type" );
186- Field<T> field = CreateField<T>(std::move (name), metadata);
187- return WrapFunction<T>(std::move (field.name_ ), std::move (field.layout_ ),
188- std::move (field.data_ ), shared_from_this ());
189- }
190-
191- template <typename T>
192- Function<T> FunctionSpace::CreateFunction (
193- std::string name, std::unique_ptr<FieldData<T>> data) const
194- {
195- static_assert (is_supported_field_type_v<T>,
196- " T is not a supported field type" );
197- Field<T> field = CreateField<T>(std::move (name), std::move (data));
198- return WrapFunction<T>(std::move (field.name_ ), std::move (field.layout_ ),
123+ return WrapFunction<T>(std::move (name), std::move (field.layout_ ),
199124 std::move (field.data_ ), shared_from_this ());
200125}
201126
0 commit comments