.. _program_listing_file_include_interfaces_integration_interface.hpp: Program Listing for File integration_interface.hpp ================================================== |exhale_lsh| :ref:`Return to documentation for file ` (``include/interfaces/integration_interface.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #pragma once #include #include #include #include #include #include #include #include namespace diffeq::interfaces { template class IntegrationInterface { public: using state_type = StateType; using time_type = TimeType; using signal_processor_type = signal::SignalProcessor; enum class InfluenceMode { DISCRETE_EVENT, // Signal causes instantaneous state jump CONTINUOUS_SHIFT, // Signal modifies ODE trajectory continuously PARAMETER_UPDATE, // Signal updates integration parameters OUTPUT_TRIGGER // Signal triggers output/logging }; struct SignalInfluence { InfluenceMode mode; std::string signal_type; std::function handler; double priority = 1.0; bool is_active = true; }; struct OutputStream { std::string stream_id; std::function output_func; std::chrono::microseconds interval{1000}; // Output frequency std::chrono::steady_clock::time_point last_output; bool is_active = true; }; private: std::shared_ptr signal_processor_; std::vector signal_influences_; std::vector output_streams_; // Current integration state std::optional current_state_; time_type current_time_ = {}; // Trajectory modification functions std::vector> trajectory_modifiers_; public: explicit IntegrationInterface(std::shared_ptr processor = nullptr) : signal_processor_(processor ? processor : signal::make_signal_processor()) { setup_signal_handling(); } template void register_signal_influence( std::string_view signal_type, InfluenceMode mode, std::function handler, double priority = 1.0) { SignalInfluence influence{ .mode = mode, .signal_type = std::string(signal_type), .handler = [h = std::move(handler)](const std::any& signal_data, state_type& state, time_type t) { try { const auto& typed_data = std::any_cast(signal_data); h(typed_data, state, t); } catch (const std::bad_any_cast&) { // Type mismatch - ignore silently } }, .priority = priority, .is_active = true }; signal_influences_.push_back(std::move(influence)); // Register with signal processor signal_processor_->template register_handler(signal_type, [this, signal_type_str = std::string(signal_type)](const signal::Signal& sig) { handle_signal(signal_type_str, sig.data); }); } void register_output_stream( std::string_view stream_id, std::function output_func, std::chrono::microseconds interval = std::chrono::microseconds{1000}) { OutputStream stream{ .stream_id = std::string(stream_id), .output_func = std::move(output_func), .interval = interval, .last_output = std::chrono::steady_clock::now(), .is_active = true }; output_streams_.push_back(std::move(stream)); } void add_trajectory_modifier( std::function modifier) { trajectory_modifiers_.push_back(std::move(modifier)); } template auto make_signal_aware_ode(OriginalODE&& original_ode) { return [this, ode = std::forward(original_ode)] (time_type t, const state_type& y, state_type& dydt) { // Update current state for signal handling current_state_ = y; current_time_ = t; // Compute original dynamics ode(t, y, dydt); // Apply trajectory modifiers from continuous signal influences state_type modified_state = y; for (auto& modifier : trajectory_modifiers_) { modifier(t, modified_state, dydt); } // Handle real-time outputs process_output_streams(y, t); }; } void apply_discrete_event(const std::string& signal_type, const std::any& signal_data) { if (!current_state_) return; for (auto& influence : signal_influences_) { if (influence.signal_type == signal_type && influence.mode == InfluenceMode::DISCRETE_EVENT && influence.is_active) { influence.handler(signal_data, *current_state_, current_time_); } } } std::optional get_current_state() const { return current_state_; } time_type get_current_time() const { return current_time_; } void set_signal_influence_active(const std::string& signal_type, bool active) { for (auto& influence : signal_influences_) { if (influence.signal_type == signal_type) { influence.is_active = active; } } } void set_output_stream_active(const std::string& stream_id, bool active) { for (auto& stream : output_streams_) { if (stream.stream_id == stream_id) { stream.is_active = active; } } } std::shared_ptr get_signal_processor() { return signal_processor_; } private: void setup_signal_handling() { // Basic signal handling is set up when influences are registered } void handle_signal(const std::string& signal_type, const std::any& signal_data) { // Handle different influence modes for (auto& influence : signal_influences_) { if (influence.signal_type == signal_type && influence.is_active) { if (influence.mode == InfluenceMode::DISCRETE_EVENT && current_state_) { // Apply immediate state modification influence.handler(signal_data, *current_state_, current_time_); } else if (influence.mode == InfluenceMode::CONTINUOUS_SHIFT) { // Add to trajectory modifiers for continuous influence add_trajectory_modifier([influence, signal_data] (time_type t, state_type& state, state_type& /* dydt */) { influence.handler(signal_data, state, t); }); } else if (influence.mode == InfluenceMode::PARAMETER_UPDATE) { // Handle parameter updates (integrator-specific) if (current_state_) { influence.handler(signal_data, *current_state_, current_time_); } } else if (influence.mode == InfluenceMode::OUTPUT_TRIGGER && current_state_) { // Trigger immediate output for (auto& stream : output_streams_) { if (stream.is_active) { stream.output_func(*current_state_, current_time_); } } } } } } void process_output_streams(const state_type& state, time_type t) { auto now = std::chrono::steady_clock::now(); for (auto& stream : output_streams_) { if (!stream.is_active) continue; if (now - stream.last_output >= stream.interval) { stream.output_func(state, t); stream.last_output = now; } } } }; template auto make_integration_interface( std::shared_ptr> processor) { return std::make_unique>(processor); } template auto make_integration_interface() { return std::make_unique>(); } } // namespace diffeq::interfaces