1+ #include < execution/parallelism_facade_clean.hpp>
2+ #include < execution/parallel_builder.hpp>
3+ #include < integrators/ode/rk4.hpp>
4+ #include < integrators/ode/euler.hpp>
5+ #include < integrators/ode/rk45.hpp>
6+ #include < iostream>
7+ #include < vector>
8+ #include < chrono>
9+ #include < random>
10+ #include < cmath>
11+
12+ /* *
13+ * @brief Integration Example with Enhanced Parallelism
14+ *
15+ * This example demonstrates how the new parallelism capabilities
16+ * integrate seamlessly with existing diffeq integrators.
17+ */
18+
19+ int main () {
20+ std::cout << " === Enhanced Parallelism Integration with ODE Solvers ===\n\n " ;
21+
22+ // Example 1: Parallel integration of multiple initial conditions
23+ std::cout << " 1. Parallel Integration of Multiple Initial Conditions\n " ;
24+ std::cout << " Solving harmonic oscillator: d²x/dt² = -ω²x with different initial conditions\n\n " ;
25+
26+ // Define the harmonic oscillator system
27+ auto harmonic_oscillator = [](double /* t*/ , const std::vector<double >& state, std::vector<double >& derivative) {
28+ const double omega = 1.0 ; // Natural frequency
29+ derivative[0 ] = state[1 ]; // dx/dt = v
30+ derivative[1 ] = -omega * omega * state[0 ]; // dv/dt = -ω²x
31+ };
32+
33+ // Create multiple initial conditions
34+ std::vector<std::vector<double >> initial_conditions = {
35+ {1.0 , 0.0 }, // x=1, v=0
36+ {0.0 , 1.0 }, // x=0, v=1
37+ {0.5 , 0.5 }, // x=0.5, v=0.5
38+ {-1.0 , 0.0 }, // x=-1, v=0
39+ {0.0 , -1.0 }, // x=0, v=-1
40+ {2.0 , 0.0 }, // x=2, v=0
41+ {0.0 , 2.0 }, // x=0, v=2
42+ {1.5 , -0.5 } // x=1.5, v=-0.5
43+ };
44+
45+ // Configure parallelism for optimal performance
46+ auto parallel_facade = diffeq::execution::parallel_execution ()
47+ .target_cpu ()
48+ .use_thread_pool ()
49+ .workers (std::thread::hardware_concurrency ())
50+ .normal_priority ()
51+ .enable_load_balancing ()
52+ .build ();
53+
54+ std::cout << " Using " << parallel_facade->get_max_concurrency () << " worker threads\n " ;
55+
56+ const double dt = 0.01 ;
57+ const double end_time = 2.0 * M_PI; // One full period
58+
59+ auto start_time = std::chrono::high_resolution_clock::now ();
60+
61+ // Parallel integration using the facade
62+ parallel_facade->parallel_for_each (initial_conditions.begin (), initial_conditions.end (),
63+ [&](std::vector<double >& state) {
64+ // Create integrator for this thread (RK4 for accuracy)
65+ auto integrator = diffeq::integrators::ode::RK4Integrator<std::vector<double >, double >(harmonic_oscillator);
66+
67+ double t = 0.0 ;
68+ while (t < end_time) {
69+ double step_size = std::min (dt, end_time - t);
70+ integrator.step (state, step_size);
71+ t += step_size;
72+ }
73+ });
74+
75+ auto end_time_chrono = std::chrono::high_resolution_clock::now ();
76+ auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time_chrono - start_time);
77+
78+ std::cout << " Integration completed in " << duration.count () << " ms\n " ;
79+ std::cout << " Final states (should be close to initial due to periodicity):\n " ;
80+ for (size_t i = 0 ; i < initial_conditions.size (); ++i) {
81+ const auto & state = initial_conditions[i];
82+ std::cout << " Condition " << i+1 << " : x=" << state[0 ] << " , v=" << state[1 ] << " \n " ;
83+ }
84+
85+ // Example 2: Monte Carlo simulation with stochastic differential equations
86+ std::cout << " \n 2. Monte Carlo SDE Simulation with GPU-Style Parallelism\n " ;
87+ std::cout << " Simulating geometric Brownian motion for financial modeling\n\n " ;
88+
89+ // Configure for high-throughput Monte Carlo
90+ auto monte_carlo_facade = diffeq::execution::presets::monte_carlo ().build ();
91+
92+ const size_t num_simulations = 1000 ; // Reduced for demo
93+ const double S0 = 100.0 ; // Initial stock price
94+ const double mu = 0.05 ; // Drift
95+ const double sigma = 0.2 ; // Volatility
96+ const double T = 1.0 ; // Time horizon
97+
98+ std::cout << " Running " << num_simulations << " Monte Carlo simulations...\n " ;
99+
100+ // Create storage for results
101+ std::vector<double > final_prices (num_simulations);
102+ std::vector<std::future<double >> simulation_futures;
103+
104+ start_time = std::chrono::high_resolution_clock::now ();
105+
106+ // Launch parallel simulations
107+ for (size_t i = 0 ; i < num_simulations; ++i) {
108+ simulation_futures.push_back (monte_carlo_facade->async ([=]() {
109+ // Each simulation uses its own random number generator
110+ std::mt19937 rng (std::random_device{}() + i);
111+ std::normal_distribution<double > normal (0.0 , 1.0 );
112+
113+ // Simple Geometric Brownian Motion system
114+ auto gbm_system = [mu](double /* t*/ , const std::vector<double >& state, std::vector<double >& derivative) {
115+ derivative[0 ] = mu * state[0 ]; // Drift term
116+ };
117+
118+ auto integrator = diffeq::integrators::ode::EulerIntegrator<std::vector<double >, double >(gbm_system);
119+
120+ std::vector<double > state = {S0};
121+ double t = 0.0 ;
122+ const double dt_sim = 0.01 ;
123+
124+ while (t < T) {
125+ // Deterministic step
126+ integrator.step (state, dt_sim);
127+
128+ // Add stochastic component (simplified Euler-Maruyama)
129+ double dW = normal (rng) * std::sqrt (dt_sim);
130+ state[0 ] += sigma * state[0 ] * dW;
131+
132+ t += dt_sim;
133+ }
134+
135+ return state[0 ]; // Return final price
136+ }));
137+ }
138+
139+ // Collect results
140+ for (size_t i = 0 ; i < num_simulations; ++i) {
141+ final_prices[i] = simulation_futures[i].get ();
142+ }
143+
144+ end_time_chrono = std::chrono::high_resolution_clock::now ();
145+ duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time_chrono - start_time);
146+
147+ // Calculate statistics
148+ double mean_price = 0.0 ;
149+ double min_price = final_prices[0 ];
150+ double max_price = final_prices[0 ];
151+
152+ for (double price : final_prices) {
153+ mean_price += price;
154+ min_price = std::min (min_price, price);
155+ max_price = std::max (max_price, price);
156+ }
157+ mean_price /= num_simulations;
158+
159+ double variance = 0.0 ;
160+ for (double price : final_prices) {
161+ variance += (price - mean_price) * (price - mean_price);
162+ }
163+ variance /= (num_simulations - 1 );
164+
165+ std::cout << " Monte Carlo Results:\n " ;
166+ std::cout << " Simulation time: " << duration.count () << " ms\n " ;
167+ std::cout << " Throughput: " << (num_simulations * 1000.0 ) / duration.count () << " simulations/second\n " ;
168+ std::cout << " Mean final price: $" << mean_price << " \n " ;
169+ std::cout << " Price range: $" << min_price << " - $" << max_price << " \n " ;
170+ std::cout << " Standard deviation: $" << std::sqrt (variance) << " \n " ;
171+ std::cout << " Expected price (theoretical): $" << S0 * std::exp (mu * T) << " \n " ;
172+
173+ // Example 3: Real-time integration for control systems
174+ std::cout << " \n 3. Real-time Integration for Control Systems\n " ;
175+ std::cout << " Simulating a controlled pendulum with real-time constraints\n\n " ;
176+
177+ // Configure for real-time execution
178+ auto realtime_facade = diffeq::execution::presets::real_time_systems ().build ();
179+
180+ // Controlled pendulum system
181+ auto controlled_pendulum = [](double t, const std::vector<double >& state, std::vector<double >& derivative) {
182+ const double g = 9.81 ; // Gravity
183+ const double L = 1.0 ; // Pendulum length
184+ const double b = 0.1 ; // Damping
185+
186+ double theta = state[0 ]; // Angle
187+ double theta_dot = state[1 ]; // Angular velocity
188+
189+ // Simple PD controller
190+ double u = -10.0 * theta - 2.0 * theta_dot; // Control torque
191+
192+ derivative[0 ] = theta_dot;
193+ derivative[1 ] = -(g/L) * std::sin (theta) - b * theta_dot + u;
194+ };
195+
196+ std::vector<double > pendulum_state = {0.5 , 0.0 }; // Initial angle 0.5 rad, no initial velocity
197+ const double control_dt = 0.001 ; // 1ms control loop (1kHz)
198+ const double control_time = 1.0 ; // 1 second of control (reduced for demo)
199+
200+ std::cout << " Running real-time control loop at 1kHz for " << control_time << " seconds...\n " ;
201+
202+ start_time = std::chrono::high_resolution_clock::now ();
203+ auto integrator = diffeq::integrators::ode::RK4Integrator<std::vector<double >, double >(controlled_pendulum);
204+
205+ size_t steps = 0 ;
206+ for (double t = 0.0 ; t < control_time; t += control_dt) {
207+ // Execute one control step with real-time priority
208+ auto control_future = realtime_facade->async ([&]() {
209+ integrator.step (pendulum_state, control_dt);
210+ });
211+
212+ control_future.wait ();
213+ steps++;
214+
215+ // Log every 200ms
216+ if (steps % 200 == 0 ) {
217+ std::cout << " t=" << t << " s, angle=" << pendulum_state[0 ]
218+ << " rad, velocity=" << pendulum_state[1 ] << " rad/s\n " ;
219+ }
220+ }
221+
222+ end_time_chrono = std::chrono::high_resolution_clock::now ();
223+ duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time_chrono - start_time);
224+
225+ std::cout << " Control loop completed in " << duration.count () << " ms\n " ;
226+ std::cout << " Average loop time: " << (duration.count () * 1000.0 ) / steps << " microseconds\n " ;
227+ std::cout << " Final pendulum state: angle=" << pendulum_state[0 ]
228+ << " rad, velocity=" << pendulum_state[1 ] << " rad/s\n " ;
229+
230+ // Example 4: Parallel pattern usage
231+ std::cout << " \n 4. Parallel Pattern Demonstration\n " ;
232+ std::cout << " Using parallel_map and parallel_reduce with ODE solutions\n\n " ;
233+
234+ // Create a range of parameters for parametric study
235+ std::vector<double > damping_values = {0.01 , 0.05 , 0.1 , 0.2 , 0.5 , 1.0 , 2.0 , 5.0 };
236+
237+ // Parallel map: solve ODE for each damping value
238+ auto final_energies = diffeq::execution::patterns::parallel_map (
239+ damping_values.begin (), damping_values.end (),
240+ [](double damping) {
241+ // Damped harmonic oscillator
242+ auto damped_oscillator = [damping](double /* t*/ , const std::vector<double >& state, std::vector<double >& derivative) {
243+ derivative[0 ] = state[1 ]; // dx/dt = v
244+ derivative[1 ] = -state[0 ] - 2.0 * damping * state[1 ]; // dv/dt = -x - 2γv
245+ };
246+
247+ auto integrator = diffeq::integrators::ode::RK45Integrator<std::vector<double >, double >(damped_oscillator);
248+
249+ std::vector<double > state = {1.0 , 0.0 }; // Initial: x=1, v=0
250+ double t = 0.0 ;
251+ const double dt = 0.01 ;
252+ const double end_time = 10.0 ;
253+
254+ while (t < end_time) {
255+ integrator.step (state, dt);
256+ t += dt;
257+ }
258+
259+ // Calculate final energy: E = 0.5 * (x² + v²)
260+ return 0.5 * (state[0 ] * state[0 ] + state[1 ] * state[1 ]);
261+ }
262+ );
263+
264+ std::cout << " Parallel parametric study results:\n " ;
265+ for (size_t i = 0 ; i < damping_values.size (); ++i) {
266+ std::cout << " Damping γ=" << damping_values[i]
267+ << " , Final energy=" << final_energies[i] << " \n " ;
268+ }
269+
270+ // Parallel reduce: calculate total energy dissipated
271+ double total_energy_dissipated = diffeq::execution::patterns::parallel_reduce (
272+ final_energies.begin (), final_energies.end (),
273+ 0.0 ,
274+ [](double acc, double energy) { return acc + (0.5 - energy); } // Initial energy was 0.5
275+ );
276+
277+ std::cout << " Total energy dissipated across all cases: " << total_energy_dissipated << " \n " ;
278+
279+ std::cout << " \n === Enhanced Parallelism Integration Complete ===\n " ;
280+ std::cout << " The parallelism facade seamlessly integrates with existing diffeq integrators,\n " ;
281+ std::cout << " providing transparent acceleration for various computational patterns.\n " ;
282+
283+ return 0 ;
284+ }
0 commit comments