Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions Sim_Engine/Engine.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)EngineLib;$(SolutionDir)EngineLib\include;$SolutionDir)External\GLFW;$(SolutionDir)External\GLAD;$(SolutionDir)External\GLM;$(SolutionDir)External\assimp;$(SolutionDir)External\MathLib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)EngineLib;$(SolutionDir)EngineLib\include;$SolutionDir)External\GLFW;$(SolutionDir)External\GLAD;$(SolutionDir)External\GLM;$(SolutionDir)External\assimp;$(SolutionDir)External\MathLib\include;$(SolutionDir)Engine\include;$(SolutionDir)External\Eigen;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp20</LanguageStandard>
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
<ObjectFileName>$(IntDir)%(FileName).obj</ObjectFileName>
Expand Down Expand Up @@ -87,7 +87,7 @@ echo D | xcopy /E /Y /D "$(ProjectDir)Engine\configs\*" "$(TargetDir)configs\"
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)EngineLib;$(SolutionDir)EngineLib\include;$SolutionDir)External\GLFW;$(SolutionDir)External\GLAD;$(SolutionDir)External\GLM;$(SolutionDir)External\assimp;$(SolutionDir)External\MathLib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)EngineLib;$(SolutionDir)EngineLib\include;$SolutionDir)External\GLFW;$(SolutionDir)External\GLAD;$(SolutionDir)External\GLM;$(SolutionDir)External\assimp;$(SolutionDir)External\MathLib\include;$(SolutionDir)Engine\include;$(SolutionDir)External\Eigen;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp20</LanguageStandard>
<PreprocessToFile>false</PreprocessToFile>
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
Expand All @@ -111,6 +111,7 @@ echo D | xcopy /E /Y /D "$(ProjectDir)Engine\configs\*" "$(TargetDir)configs\"
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="Engine\src\BatchMain.cpp" />
<ClCompile Include="Engine\src\Main.cpp" />
<ClCompile Include="External\stb\stb_image_write_impl.cpp" />
</ItemGroup>
Expand Down Expand Up @@ -138,6 +139,10 @@ echo D | xcopy /E /Y /D "$(ProjectDir)Engine\configs\*" "$(TargetDir)configs\"
<None Include="assets\shaders\world_grid.frag.glsl" />
<None Include="assets\shaders\world_grid.vert.glsl" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Engine\include\BatchArgs.h" />
<ClInclude Include="Engine\include\BatchEntry.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
Expand Down
14 changes: 14 additions & 0 deletions Sim_Engine/Engine.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
<ClCompile Include="External\stb\stb_image_write_impl.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="Engine\src\BatchMain.cpp">
<Filter>src</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="src">
Expand All @@ -15,6 +18,9 @@
<Filter Include="Shaders">
<UniqueIdentifier>{383daa6b-14af-40d3-b6df-31732d4d7a6a}</UniqueIdentifier>
</Filter>
<Filter Include="include">
<UniqueIdentifier>{146d8cfd-be4d-41a3-bc59-546deb084dc0}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="assets\shaders\brdf_lut.frag.glsl">
Expand Down Expand Up @@ -84,4 +90,12 @@
<Filter>Shaders</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Engine\include\BatchEntry.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="Engine\include\BatchArgs.h">
<Filter>include</Filter>
</ClInclude>
</ItemGroup>
</Project>
19 changes: 19 additions & 0 deletions Sim_Engine/Engine/include/BatchArgs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once
#include <string>
#include <vector>
#include <optional>

// Struct to hold command-line arguments for batch mode
struct BatchArgs {
std::string testPath;
// Base configuration for batch runs (if not provided, defaults will be used)
std::optional<std::string> baseDtRaw;
std::optional<double> baseDt;
std::optional<std::string> baseInt;
// Lists for sweep parameters (if not provided, defaults will be used)
std::vector<std::string> sweepDtRaw;
std::vector<double> sweepDt;
std::vector<std::string> sweepInt;
// Run name for output organisation
std::optional<std::string> runName;
};
3 changes: 3 additions & 0 deletions Sim_Engine/Engine/include/BatchEntry.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma once
struct BatchArgs;
int runBatchMode(const BatchArgs& args);
132 changes: 132 additions & 0 deletions Sim_Engine/Engine/src/BatchMain.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// BatchMain.cpp
#include "pch.h"
#include <EngineCore.h>
#include "BatchEntry.h"
#include "BatchArgs.h"
#include "Platform/StudyRunner.h"
#include "Numerics/IntegrationMethods.h"
#include "Platform/Paths.h"

#include <chrono>
#include <cstdio>
#include <fstream>
#include <sstream>
#include <algorithm>

// Integration method parser from string (throws if unknown)
static integration::eIntegrationMethod parseMethod(const std::string& name) {
if (name == "euler") return integration::eIntegrationMethod::Euler;
if (name == "midpoint") return integration::eIntegrationMethod::Midpoint;
if (name == "heun") return integration::eIntegrationMethod::Heun;
if (name == "ralston") return integration::eIntegrationMethod::Ralston;
if (name == "rk4") return integration::eIntegrationMethod::RK4;
if (name == "rk45") return integration::eIntegrationMethod::RK45;
throw std::runtime_error("Unknown integrator: " + name);
}

// Helper to format a timestep (dt) as a string for use in tags and filenames
static std::string formatDtForFile(const std::string& raw) {
std::string out;
out.reserve(raw.size() + 4);
for (char c : raw) {
if (c == '.') { out += "p"; }
if (c == '/') { out += "over"; }
else { out += c; }
}
return out;
}

// Core factory function for StudyRunner
static CorePtr makeCoreFactory() {
core::ISimulationCore* raw = CreateSimulationCore_v1();
if (!raw) { return CorePtr(nullptr, [](core::ISimulationCore*) {}); }
return CorePtr(raw, [](core::ISimulationCore* p) { DestroySimulationCore(p); });
}

// Batch mode entry point
int runBatchMode(const BatchArgs& args) {
paths::init();
fprintf(stdout, "BATCH MODE ENTERED\n");
fflush(stdout);
// Basic validation and setup
try {
// Validate required baseline
if (!args.baseDt.has_value() || !args.baseInt.has_value()) { throw std::runtime_error("Baseline (--basedt and --baseint) required."); }
if (args.testPath.empty()) { throw std::runtime_error("No test script provided."); }

// Load script
std::ifstream file(args.testPath);
if (!file) { throw std::runtime_error("Failed to open test file: " + args.testPath); }
std::ostringstream buffer;
buffer << file.rdbuf();
std::string scriptText = buffer.str();

// Build configs
std::vector<StudyRunner::config> configs;

// Baseline (always first)
{
StudyRunner::config base;
base.method = parseMethod(args.baseInt.value());
base.dt = args.baseDt.value();
base.len_min = 1.0; // Fixed simulation duration (consistent across runs)
base.tag =
(args.runName.has_value() ? args.runName.value() + "_" : "") +
"base_dt" + formatDtForFile(args.baseDtRaw.value()) +
"_int_" + args.baseInt.value();
configs.push_back(base);
}

// Sweep grid
for (size_t i = 0; i < args.sweepDt.size(); ++i) {
double dt = args.sweepDt[i];
const std::string& dtRaw = args.sweepDtRaw[i];
for (const auto& intName : args.sweepInt) {
StudyRunner::config c;
c.method = parseMethod(intName);
c.dt = dt;
c.len_min = 1.0;
c.tag =
(args.runName.has_value() ? args.runName.value() + "_" : "") +
"dt" + formatDtForFile(dtRaw) +
"_int_" + intName;
configs.push_back(c);
}
}

// Worker configuration
size_t workers = 1; // stable mode (parallel logging disabled)
StudyRunner runner(makeCoreFactory, workers);

// Execute
auto T0 = std::chrono::high_resolution_clock::now();
auto results = runner.runStudies(configs, scriptText);
auto T1 = std::chrono::high_resolution_clock::now();

double total = std::chrono::duration<double>(T1 - T0).count();
fprintf(stderr, "TOTAL BATCH TIME = %.3f sec\n", total);

// Sort results by tag
std::sort(results.begin(), results.end(),
[](const StudyResult& a, const StudyResult& b) {
return a.tag < b.tag;
});

// Print summary
for (const auto& r : results) {
std::cout
<< "tag=" << r.tag
<< " success=" << (r.success ? "yes" : "no")
<< " int=" << r.intName
<< " time=" << r.simTime
<< " samples=" << r.samples
<< "\n";
}
}
// Catch any exceptions that escaped from the batch processing and log them
catch (const std::exception& e) {
std::cerr << "Batch mode exception: " << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Loading