The test suite is extensive. Note that LLMs were used to aid in the development of the test suite. All LLM generated code was manually reviewed.
58 lines
2.4 KiB
C++
58 lines
2.4 KiB
C++
#include <algorithm>
|
|
#include <cmath>
|
|
#include <filesystem>
|
|
#include <numbers>
|
|
#include <print>
|
|
|
|
#include "serif/utils/serialize/top.hpp"
|
|
|
|
/** @brief Write analytic inputs for an optional test against TOP's actual Fortran reader. */
|
|
int main(int argc, char** argv) {
|
|
namespace io = serif::utils::serialize;
|
|
if (argc != 2) {
|
|
std::println(stderr, "Usage: top_export_fixture OUTPUT_DIRECTORY");
|
|
return 2;
|
|
}
|
|
const std::filesystem::path directory{argv[1]};
|
|
std::filesystem::create_directories(directory);
|
|
io::TopPolytropeSource source{
|
|
.polytropic_index = 1.0, .gravitational_constant = 1.0, .mass = 1.0,
|
|
.angular_velocity = 0.0, .central_density = std::numbers::pi / 4.0, .central_enthalpy = 1.0,
|
|
.surface_radius = [](double, double) -> io::Result<double> { return 1.0; },
|
|
.enthalpy = [](double radius, double, double) -> io::Result<double> {
|
|
if (radius == 0.0) return 1.0;
|
|
if (radius == 1.0) return 0.0;
|
|
return std::sin(std::numbers::pi * radius) / (std::numbers::pi * radius);
|
|
}
|
|
};
|
|
const io::TopExportOptions options{.radial_points = 64, .maximum_degree = 8, .angular_points = 24, .azimuthal_points = 8};
|
|
const auto spherical = io::export_top(directory / "spherical", source, options);
|
|
if (!spherical) {
|
|
std::println(stderr, "{}: {}", spherical.error().path, spherical.error().message);
|
|
return 1;
|
|
}
|
|
source.angular_velocity = 0.2;
|
|
source.surface_radius = [](double mu, double) -> io::Result<double> { return 1.0 - 0.2 * mu * mu; };
|
|
source.enthalpy = [](double radius, double mu, double) -> io::Result<double> {
|
|
const double surface = 1.0 - 0.2 * mu * mu;
|
|
if (radius == 0.0) return 1.0;
|
|
if (radius >= surface) return 0.0;
|
|
double lo = 0.0, hi = 1.0;
|
|
for (int i = 0; i < 60; ++i) {
|
|
const double z = 0.5 * (lo + hi);
|
|
const double a = 0.5 * (5.0 * z * z * z - 3.0 * std::pow(z, 5));
|
|
if (0.8 * z + a * (surface - 0.8) < radius) lo = z;
|
|
else hi = z;
|
|
}
|
|
const double z = 0.5 * (lo + hi);
|
|
const double p2 = 0.5 * (3.0 * mu * mu - 1.0);
|
|
return (1.0 - z * z) * (1.0 + 0.1 * z * z * p2);
|
|
};
|
|
const auto deformed = io::export_top(directory / "deformed", source, options);
|
|
if (!deformed) {
|
|
std::println(stderr, "{}: {}", deformed.error().path, deformed.error().message);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|