.. _program_listing_file_src_pcms_field_function_space.h: Program Listing for File function_space.h ========================================= |exhale_lsh| :ref:`Return to documentation for file ` (``src/pcms/field/function_space.h``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #ifndef PCMS_FUNCTION_SPACE_H #define PCMS_FUNCTION_SPACE_H #include "pcms/field/coordinate_system.hpp" #include "pcms/field/coordinate_view.hpp" #include "evaluation_request.h" #include "field.h" #include "field_data.h" #include "field_factory.h" #include "field_layout.h" #include "pcms/field/value_view.hpp" #include "out_of_bounds_policy.h" #include "point_evaluator.h" #include "pcms/field/point_evaluator_factory.hpp" #include "pcms/discretization/discretization.h" #include "pcms/utility/arrays.h" #include "pcms/utility/memory_spaces.h" #include "pcms/utility/types.h" #include #include #include namespace pcms { // FunctionSpace is an abstract interface representing an evaluatable field // space: layout, evaluation rules, and coordinate interpretation. It produces // Functions (a Field bound to this space). // // Concrete implementations (e.g. LagrangeFunctionSpace) provide backends for // specific discretizations or mesh types, and their From* factories return a // shared_ptr. A Function co-owns its space via shared_ptr (obtained through // enable_shared_from_this), which is why concrete spaces are always // shared-owned; a stack-allocated FunctionSpace is not constructible (the // backend constructors are private and reachable only via the shared_ptr // From* factories). class FunctionSpace : public PointEvaluatorFactory , public std::enable_shared_from_this { public: virtual std::shared_ptr GetDiscretization() const noexcept { return GetLayout()->GetDiscretization(); } virtual std::shared_ptr GetLayout() const noexcept = 0; [[nodiscard]] const std::shared_ptr& GetCoordinateSystem() const override { return GetLayout()->GetCoordinateSystem(); } virtual ~FunctionSpace() noexcept = default; template [[nodiscard]] Function CreateFunction( std::string name = "", VarianceSignature variance = values::Scalar, std::optional scaling = std::nullopt) const; template [[nodiscard]] Function CreateFunction( std::string name, VarianceSignature variance, std::shared_ptr system, std::optional scaling = std::nullopt) const; // Expert API: wrap externally constructed field data into a Function for this // space. The concrete space validates backend-specific field-data type and // storage size compatibility. template [[nodiscard]] Function CreateFunction( std::string name, std::unique_ptr> data) const; protected: template static Field WrapField(std::shared_ptr layout, std::unique_ptr> data) { return Field(std::string{}, std::move(layout), std::move(data)); } template static Function WrapFunction(std::string name, std::shared_ptr layout, std::unique_ptr> data, std::shared_ptr space) { return Function(std::move(name), std::move(layout), std::move(data), std::move(space)); } virtual FieldVariant CreateFieldImpl(Type storage_type, ValueBasis basis) const = 0; virtual FieldVariant CreateFieldImpl(FieldDataVariant data) const = 0; }; template Function FunctionSpace::CreateFunction( std::string name, VarianceSignature variance, std::optional scaling) const { return CreateFunction(std::move(name), variance, nullptr, scaling); } template Function FunctionSpace::CreateFunction( std::string name, VarianceSignature variance, std::shared_ptr system, std::optional scaling) const { static_assert(is_supported_field_type_v, "T is not a supported field type"); ValueBasis basis = detail::MakeValueBasis(GetCoordinateSystem(), variance, std::move(system), scaling); detail::ValidateValueSemantics(basis, GetLayout()->GetNumComponents()); Field field = std::get>( CreateFieldImpl(TypeEnumFromType(), std::move(basis))); return WrapFunction(std::move(name), std::move(field.layout_), std::move(field.data_), shared_from_this()); } template Function FunctionSpace::CreateFunction( std::string name, std::unique_ptr> data) const { static_assert(is_supported_field_type_v, "T is not a supported field type"); if (!data) { throw pcms_error("FunctionSpace::CreateFunction: data must not be null"); } detail::ValidateValueSemantics(data->GetValueBasis(), GetLayout()->GetNumComponents()); Field field = std::get>(CreateFieldImpl(FieldDataVariant{std::move(data)})); return WrapFunction(std::move(name), std::move(field.layout_), std::move(field.data_), shared_from_this()); } inline EvaluationRequest EvaluationRequest::FromCoordinates( CoordinateView coords, OutOfBoundsPolicy policy) { return EvaluationRequest(coords, nullptr, policy); } inline EvaluationRequest EvaluationRequest::FromLayout( std::shared_ptr layout, OutOfBoundsPolicy policy) { if (layout == nullptr) { throw pcms_error("EvaluationRequest::FromLayout: layout must not be null"); } // Must evaluate GetDOFHolderCoordinates() before std::move(layout) auto coords = layout->GetDOFHolderCoordinates(); return EvaluationRequest(coords, std::move(layout), policy); } inline EvaluationRequest EvaluationRequest::FromFunctionSpace( const FunctionSpace& function_space, OutOfBoundsPolicy policy) { return FromLayout(function_space.GetLayout(), policy); } } // namespace pcms #endif // PCMS_FUNCTION_SPACE_H