2222#include < omp.h>
2323#include < string>
2424#include < vector>
25+ #ifdef NEXT_MPI
26+ #include < mpi.h>
27+ #endif
28+ #include " hdf5.h"
29+
2530
2631using next::OutputFormat;
2732
33+ // Helper: only rank 0, thread 0 prints
34+ inline void log_once (int rank, const std::string &msg) {
35+ if (rank == 0 && omp_get_thread_num () == 0 ) {
36+ std::cout << msg << std::endl;
37+ }
38+ }
39+
2840int main (int argc, char **argv) {
29- auto args = next::parse_arguments (argc, argv);
41+ int rank = 0 ;
42+ int size = 1 ;
43+
44+ #ifdef NEXT_MPI
45+ MPI_Init (&argc, &argv);
46+ MPI_Comm_rank (MPI_COMM_WORLD, &rank);
47+ MPI_Comm_size (MPI_COMM_WORLD, &size);
48+ log_once (rank, " MPI mode enabled (" + std::to_string (size) + " ranks)" );
49+ #endif
3050
31- static constexpr const char *BANNER = R"NEXTBANNER(
51+ H5Eset_auto (H5E_DEFAULT, nullptr , nullptr );
52+
53+ auto args = next::parse_arguments (argc, argv, rank);
54+
55+ static constexpr const char *BANNER = R"NEXTBANNER(
3256 _ _ ________ _________
3357| \ | | ____\ \ / /__ __|
3458| \| | |__ \ V / | |
@@ -37,73 +61,60 @@ int main(int argc, char **argv) {
3761|_| \_|______/_/ \_\ |_|
3862)NEXTBANNER" ;
3963
40- std::cout << BANNER << ' \n ' ;
41-
42- // Set threads and report
43- omp_set_num_threads (args.threads );
44- std::cout << " Threads: " << args.threads << " \n " ;
64+ omp_set_num_threads (args.threads );
4565
66+ log_once (rank, BANNER);
67+ log_once (rank, " Threads: " + std::to_string (args.threads ));
4668#ifdef NEXT_FP64
47- std::cout << " Precision: FP64\n " ;
69+ log_once (rank, " Precision: FP64" ) ;
4870#elif defined(NEXT_FP32)
49- std::cout << " Precision: FP32\n " ;
71+ log_once (rank, " Precision: FP32" ) ;
5072#endif
5173
52- // --- SoA UPDATE ---
53- // LoadParticlesFromFile now returns a single 'Particle' struct
54- // which internally contains all the parallel vectors.
55- Particle particles = LoadParticlesFromFile (args.input_file );
56-
57- std::cout << " Particles: " << particles.size () << " \n " ;
58-
59- real simTime = 0 ;
60- real nextDump = 0 ;
61- int step = 0 ;
62- char command;
63-
64- while (true ) {
65- // Both computeAdaptiveDt and Step now take the SoA object by reference
66- real dtAdaptive = computeAdaptiveDt (particles, args.dt );
67- Step (particles, dtAdaptive);
68-
69- simTime += dtAdaptive;
70-
71- if (simTime >= nextDump) {
72- std::string out = " dump_" + std::to_string (step);
73-
74- switch (args.format ) {
75- case OutputFormat::VTK:
76- out += " .vtk" ;
77- SaveVTK (particles, out);
78- break ;
79-
80- case OutputFormat::VTU:
81- out += " .vtu" ;
82- SaveVTU (particles, out);
83- break ;
84-
85- case OutputFormat::HDF5:
86- out += " .hdf5" ;
87- SaveHDF5 (particles, out);
88- break ;
89- }
90-
91- std::cout << " [Dump " << step << " ] t = " << simTime
92- << " , file: " << out << " \n " ;
93-
94- nextDump += args.dump_interval ;
95- step++;
74+ // Load particles
75+ Particle particles = LoadParticlesFromFile (args.input_file );
76+ log_once (rank, " Particles: " + std::to_string (particles.size ()));
77+
78+ real simTime = 0 ;
79+ real nextDump = 0 ;
80+ int step = 0 ;
81+ char command;
82+
83+ while (true ) {
84+ real dtAdaptive = computeAdaptiveDt (particles, args.dt );
85+ Step (particles, dtAdaptive);
86+ simTime += dtAdaptive;
87+
88+ if (simTime >= nextDump) {
89+ std::string out = " dump_" + std::to_string (step);
90+
91+ switch (args.format ) {
92+ case OutputFormat::VTK: out += " .vtk" ; SaveVTK (particles, out); break ;
93+ case OutputFormat::VTU: out += " .vtu" ; SaveVTU (particles, out); break ;
94+ case OutputFormat::HDF5: out += " .hdf5" ; SaveHDF5 (particles, out); break ;
95+ }
96+
97+ log_once (rank, " [Dump " + std::to_string (step) +
98+ " ] t = " + std::to_string (simTime) +
99+ " , file: " + out);
100+
101+ nextDump += args.dump_interval ;
102+ step++;
103+ }
104+
105+ // Non-blocking exit check
106+ if (std::cin.rdbuf ()->in_avail () > 0 ) {
107+ std::cin >> command;
108+ if (command == ' q' || command == ' Q' ) {
109+ log_once (rank, " Exiting..." );
110+ break ;
111+ }
112+ }
96113 }
97114
98- // Non-blocking exit check
99- if (std::cin.rdbuf ()->in_avail () > 0 ) {
100- std::cin >> command;
101- if (command == ' q' || command == ' Q' ) {
102- std::cout << " Exiting...\n " ;
103- break ;
104- }
105- }
106- }
115+ #ifdef NEXT_MPI
116+ MPI_Finalize ();
117+ #endif
107118
108- return 0 ;
119+ return 0 ;
109120}
0 commit comments