Refactoring
This commit is contained in:
1 parent
fd2e4f265c
commit
1b9044325b
7 files changed
+30
-97
No files matched your search
+2
-4
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
struct SolverParameters{
|
||||
@@ -50,11 +49,10 @@ using solver_run_fn = void (*)(
|
||||
);
|
||||
using output_write_fn = int (*)(const OutputParameters*);
|
||||
|
||||
inline constexpr const char* SYMBOL_API_VERSION =
|
||||
"plugin_api_version";
|
||||
inline constexpr const char* SYMBOL_API_VERSION = "plugin_api_version";
|
||||
inline constexpr const char* SYMBOL_TYPE = "plugin_type";
|
||||
inline constexpr const char* SYMBOL_NAME = "plugin_name";
|
||||
inline constexpr const char* SYMBOL_DESCRIPTION = "plugin_description";
|
||||
inline constexpr const char* SYMBOL_TRANSFORM = "transform";
|
||||
inline constexpr const char* SYMBOL_SOLVER = "solver";
|
||||
inline constexpr const char* SYMBOL_WRITE_OUTPUT = "write_output";
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "api.hpp"
|
||||
|
||||
// x1, x2, x3
|
||||
struct State
|
||||
{
|
||||
double x1;
|
||||
|
||||
@@ -19,39 +19,28 @@ PLUGIN_EXPORT const char* plugin_description(){
|
||||
return "Explicit second-order Adams-Bashforth method with an RK4 start";
|
||||
}
|
||||
|
||||
PLUGIN_EXPORT void transform(const SolverParameters* parameters,
|
||||
PLUGIN_EXPORT void solver(const SolverParameters* parameters,
|
||||
SolutionPoint* output,
|
||||
size_t output_size){
|
||||
if (parameters == nullptr || output == nullptr || output_size == 0)
|
||||
return;
|
||||
|
||||
const State initial_state{1.0, 0.0, 0.0};
|
||||
State initial_state{1.0, 0.0, 0.0};
|
||||
output[0] = make_step(parameters->t_begin, initial_state);
|
||||
|
||||
if (output_size == 1)
|
||||
return;
|
||||
|
||||
State first_state = runge_kutta_step(initial_state, *parameters);
|
||||
output[1] = make_step(parameters->t_begin + parameters->step, first_state);
|
||||
|
||||
for (size_t index = 1; index + 1 < output_size; ++index){
|
||||
for (size_t index = 1; index + 1 < output_size; index++){
|
||||
State current = state_from_point(output[index]);
|
||||
State previous = state_from_point(output[index - 1]);
|
||||
State current_derivative = derivative(current, *parameters);
|
||||
State previous_derivative = derivative(previous, *parameters);
|
||||
double h = parameters->step;
|
||||
|
||||
State next{
|
||||
current.x1 + h * (1.5 * current_derivative.x1 -
|
||||
0.5 * previous_derivative.x1),
|
||||
current.x2 + h * (1.5 * current_derivative.x2 -
|
||||
0.5 * previous_derivative.x2),
|
||||
current.x3 + h * (1.5 * current_derivative.x3 -
|
||||
0.5 * previous_derivative.x3),
|
||||
State next{current.x1 + h * (1.5 * current_derivative.x1 - 0.5 * previous_derivative.x1),
|
||||
current.x2 + h * (1.5 * current_derivative.x2 - 0.5 * previous_derivative.x2),
|
||||
current.x3 + h * (1.5 * current_derivative.x3 - 0.5 * previous_derivative.x3),
|
||||
};
|
||||
|
||||
const double next_time = parameters->t_begin +
|
||||
static_cast<double>(index + 1) * h;
|
||||
double next_time = parameters->t_begin + static_cast<double>(index + 1) * h;
|
||||
output[index + 1] = make_step(next_time, next);
|
||||
}
|
||||
}
|
||||
@@ -22,8 +22,6 @@ PLUGIN_EXPORT const char* plugin_description(){
|
||||
}
|
||||
|
||||
PLUGIN_EXPORT int write_output(const OutputParameters* parameters){
|
||||
if (parameters == nullptr || parameters->solver_name == nullptr || parameters->points == nullptr)
|
||||
return 1;
|
||||
|
||||
std::cout << "\nSolver: " << parameters->solver_name << '\n'
|
||||
<< std::setw(12) << "t"
|
||||
@@ -41,5 +39,5 @@ PLUGIN_EXPORT int write_output(const OutputParameters* parameters){
|
||||
}
|
||||
|
||||
std::cout.flush();
|
||||
return std::cout ? 0 : 2;
|
||||
return std::cout ? 0 : 1;
|
||||
}
|
||||
@@ -23,25 +23,20 @@ PLUGIN_EXPORT const char* plugin_description(){
|
||||
}
|
||||
|
||||
PLUGIN_EXPORT int write_output(const OutputParameters* parameters){
|
||||
if (parameters == nullptr || parameters->destination_path == nullptr ||
|
||||
parameters->points == nullptr)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::ofstream stream(parameters->destination_path);
|
||||
if (!stream)
|
||||
return 2;
|
||||
return 1;
|
||||
|
||||
stream.imbue(std::locale::classic());
|
||||
stream << std::setprecision(17);
|
||||
stream << "t,x1,x2,x3\n";
|
||||
|
||||
for (size_t index = 0; index < parameters->point_count; ++index){
|
||||
const SolutionPoint& point = parameters->points[index];
|
||||
SolutionPoint point = parameters->points[index];
|
||||
stream << point.t << ',' << point.x1 << ','
|
||||
<< point.x2 << ',' << point.x3 << '\n';
|
||||
}
|
||||
|
||||
return stream ? 0 : 3;
|
||||
return stream ? 0 : 2;
|
||||
}
|
||||
@@ -19,19 +19,15 @@ PLUGIN_EXPORT const char* plugin_description(){
|
||||
return "Explicit fourth-order Runge-Kutta method";
|
||||
}
|
||||
|
||||
PLUGIN_EXPORT void transform(const SolverParameters* parameters,
|
||||
PLUGIN_EXPORT void solver(const SolverParameters* parameters,
|
||||
SolutionPoint* output,
|
||||
size_t output_size){
|
||||
if (parameters == nullptr || output == nullptr || output_size == 0)
|
||||
return;
|
||||
|
||||
State state{1, 0, 0};
|
||||
output[0] = make_step(parameters->t_begin, state);
|
||||
|
||||
for (size_t index = 1; index < output_size; ++index){
|
||||
state = runge_kutta_step(state, *parameters);
|
||||
const double t = parameters->t_begin +
|
||||
static_cast<double>(index) * parameters->step;
|
||||
double t = parameters->t_begin + static_cast<double>(index) * parameters->step;
|
||||
output[index] = make_step(t, state);
|
||||
}
|
||||
}
|
||||
+14
-58
@@ -1,8 +1,6 @@
|
||||
#include "api.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
@@ -115,8 +113,7 @@ std::vector<fs::path> find_candidates(const fs::path& directory){
|
||||
if (!fs::exists(directory) || !fs::is_directory(directory))
|
||||
return candidates;
|
||||
|
||||
for (const auto& entry : fs::directory_iterator(directory))
|
||||
{
|
||||
for (const auto& entry : fs::directory_iterator(directory)){
|
||||
if (entry.is_regular_file() && is_library_candidate(entry.path()))
|
||||
candidates.push_back(fs::absolute(entry.path()));
|
||||
}
|
||||
@@ -130,36 +127,12 @@ size_t calculate_point_count(const SolverParameters& parameters){
|
||||
const double interval = parameters.t_end - parameters.t_begin;
|
||||
const double step_count = std::floor(interval / parameters.step + 1e-12);
|
||||
|
||||
if (!std::isfinite(step_count) ||
|
||||
step_count > static_cast<double>(max_point_count - 1))
|
||||
{
|
||||
if (!std::isfinite(step_count) || step_count > static_cast<double>(max_point_count - 1))
|
||||
throw std::runtime_error("the selected h creates too many solution points");
|
||||
}
|
||||
|
||||
return static_cast<size_t>(step_count) + 1;
|
||||
}
|
||||
|
||||
void validate_solution(const std::vector<SolutionPoint>& solution,
|
||||
const SolverParameters& parameters)
|
||||
{
|
||||
for (size_t index = 0; index < solution.size(); ++index)
|
||||
{
|
||||
const SolutionPoint& point = solution[index];
|
||||
if (!std::isfinite(point.t) || !std::isfinite(point.x1) ||
|
||||
!std::isfinite(point.x2) || !std::isfinite(point.x3))
|
||||
{
|
||||
throw std::runtime_error("solver returned a non-finite value");
|
||||
}
|
||||
|
||||
const double expected_time = parameters.t_begin +
|
||||
static_cast<double>(index) * parameters.step;
|
||||
const double tolerance =
|
||||
1e-10 * (std::max)(1.0, std::abs(expected_time));
|
||||
if (std::abs(point.t - expected_time) > tolerance)
|
||||
throw std::runtime_error("solver returned an invalid time grid");
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
try {
|
||||
std::string plugin_directory_text;
|
||||
@@ -205,30 +178,21 @@ int main() {
|
||||
try {
|
||||
SharedLibrary library(candidate);
|
||||
|
||||
const auto api_version =
|
||||
library.require<plugin_api_version_fn>(SYMBOL_API_VERSION);
|
||||
const auto type =
|
||||
library.require<plugin_type_fn>(SYMBOL_TYPE);
|
||||
const auto name =
|
||||
library.require<plugin_text_fn>(SYMBOL_NAME);
|
||||
const auto description =
|
||||
library.require<plugin_text_fn>(SYMBOL_DESCRIPTION);
|
||||
const auto api_version = library.require<plugin_api_version_fn>(SYMBOL_API_VERSION);
|
||||
const auto type = library.require<plugin_type_fn>(SYMBOL_TYPE);
|
||||
const auto name = library.require<plugin_text_fn>(SYMBOL_NAME);
|
||||
const auto description = library.require<plugin_text_fn>(SYMBOL_DESCRIPTION);
|
||||
|
||||
if (api_version() != PLUGIN_API_VERSION){
|
||||
throw std::runtime_error(
|
||||
"unsupported API version " +
|
||||
std::to_string(api_version()));
|
||||
}
|
||||
if (api_version() != PLUGIN_API_VERSION)
|
||||
throw std::runtime_error("unsupported API version " + std::to_string(api_version()));
|
||||
|
||||
|
||||
const PluginType plugin_type = type();
|
||||
const char* plugin_name = name();
|
||||
const char* plugin_description = description();
|
||||
|
||||
if (plugin_type != PluginType::Solver &&
|
||||
plugin_type != PluginType::Output)
|
||||
{
|
||||
if (plugin_type != PluginType::Solver && plugin_type != PluginType::Output)
|
||||
throw std::runtime_error("unknown plugin type");
|
||||
}
|
||||
if (plugin_name == nullptr || plugin_description == nullptr)
|
||||
throw std::runtime_error("plugin returned null metadata");
|
||||
|
||||
@@ -287,21 +251,15 @@ int main() {
|
||||
continue;
|
||||
|
||||
try {
|
||||
std::vector<SolutionPoint> solution(point_count, SolutionPoint{ 0, 0, 0, 0 });
|
||||
SharedLibrary solver_library(solver.path);
|
||||
const auto solve =
|
||||
solver_library.require<solver_run_fn>(SYMBOL_TRANSFORM);
|
||||
|
||||
std::vector<SolutionPoint> solution(
|
||||
point_count,
|
||||
SolutionPoint{0, 0, 0, 0});
|
||||
const auto solve = solver_library.require<solver_run_fn>(SYMBOL_SOLVER);
|
||||
|
||||
solve(¶meters, solution.data(), solution.size());
|
||||
validate_solution(solution, parameters);
|
||||
|
||||
fs::path csv_filename = solver.path.stem();
|
||||
csv_filename += ".csv";
|
||||
const fs::path destination_path =
|
||||
result_directory / csv_filename;
|
||||
const fs::path destination_path = result_directory / csv_filename;
|
||||
const std::string destination = destination_path.string();
|
||||
|
||||
OutputParameters output_parameters{
|
||||
@@ -317,9 +275,7 @@ int main() {
|
||||
|
||||
try {
|
||||
SharedLibrary output_library(output.path);
|
||||
const auto write =
|
||||
output_library.require<output_write_fn>(
|
||||
SYMBOL_WRITE_OUTPUT);
|
||||
const auto write = output_library.require<output_write_fn>(SYMBOL_WRITE_OUTPUT);
|
||||
|
||||
const int status = write(&output_parameters);
|
||||
if (status != 0){
|
||||
|
||||
Reference in new issue
Block a user