14namespace fs = std::filesystem;
18std::optional<fs::path>& external_softsusy_path()
20 static std::optional<fs::path> path;
24std::string shell_quote(
const std::string& value)
26 std::string quoted =
"'";
27 for (
char c : value) {
38bool is_existing_file(
const fs::path& path)
41 return fs::exists(path, ec) && fs::is_regular_file(path, ec);
44fs::path normalize_path(
const fs::path& path)
47 const fs::path canonical = fs::weakly_canonical(path, ec);
48 return ec ? fs::absolute(path) : canonical;
51std::vector<fs::path> softsusy_candidates_from(
const fs::path& raw)
53 std::vector<fs::path> candidates;
54 candidates.push_back(raw);
57 if (fs::exists(raw, ec) && fs::is_directory(raw, ec)) {
58 candidates.push_back(raw /
"softpoint.x");
59 candidates.push_back(raw /
"bin" /
"softpoint.x");
60 candidates.push_back(raw /
"src" /
"SOFTSUSY" /
"softpoint.x");
61 candidates.push_back(raw /
"SOFTSUSY" /
"softpoint.x");
69 for (
const auto& candidate : softsusy_candidates_from(raw)) {
70 if (is_existing_file(candidate)) {
79 std::ostringstream oss;
80 oss <<
"No SOFTSUSY executable found from path '" << raw.string() <<
"'. "
81 <<
"Expected a softpoint.x executable, or a directory containing "
82 <<
"softpoint.x, bin/softpoint.x, or src/SOFTSUSY/softpoint.x.";
83 out.
error = oss.str();
87std::optional<fs::path> environment_softsusy_path()
89 if (
const char* env = std::getenv(
"HYPERISO_SOFTSUSY")) {
90 if (std::string(env).empty() ==
false) {
97std::optional<fs::path> path_softsusy_executable()
99 if (
const char* env_path = std::getenv(
"PATH")) {
100 std::string paths(env_path);
101 std::size_t start = 0;
102 while (start <= paths.size()) {
103 const std::size_t end = paths.find(
':', start);
104 const std::string entry = paths.substr(start, end == std::string::npos ? std::string::npos : end - start);
105 if (!entry.empty()) {
106 fs::path candidate = fs::path(entry) /
"softpoint.x";
107 if (is_existing_file(candidate)) {
111 if (end == std::string::npos) {
120#ifdef BUILD_WITH_SOFTSUSY
121std::optional<fs::path> bundled_softsusy_executable()
123 const fs::path root_tp_file(project_tp_root.data());
124 const std::vector<fs::path> candidates = {
125 root_tp_file /
"SOFTSUSY" /
"src" /
"SOFTSUSY" /
"softpoint.x",
126 root_tp_file /
"SOFTSUSY" /
"softpoint.x",
127 root_tp_file /
"SOFTSUSY" /
"bin" /
"softpoint.x"
130 for (
const auto& candidate : candidates) {
131 if (is_existing_file(candidate)) {
139fs::path resolve_input_path(
const std::string& inputFilePath)
141 const fs::path input(inputFilePath);
142 if (input.is_absolute()) {
145 return fs::path(project_assets_root.data()) / input;
154 const auto resolved = resolve_from_path(fs::path(path));
155 if (resolved.valid) {
156 external_softsusy_path() = resolved.executable;
163 if (external_softsusy_path().has_value()) {
164 return resolve_from_path(*external_softsusy_path());
167 if (
auto env_path = environment_softsusy_path()) {
168 auto resolved = resolve_from_path(*env_path);
169 if (resolved.valid) {
174 if (
auto path_candidate = path_softsusy_executable()) {
175 auto resolved = resolve_from_path(*path_candidate);
176 if (resolved.valid) {
181#ifdef BUILD_WITH_SOFTSUSY
182 if (
auto bundled = bundled_softsusy_executable()) {
183 auto resolved = resolve_from_path(*bundled);
184 if (resolved.valid) {
191 std::ostringstream oss;
192 oss <<
"Cannot compute a SUSY spectrum because SOFTSUSY softpoint.x was not found. "
193 <<
"Provide an executable before initialization with "
194 <<
"HyperisoMaster::pre_init_set_softsusy_path('/path/to/softpoint.x') "
195 <<
"or set HYPERISO_SOFTSUSY=/path/to/softpoint.x.";
196#ifndef BUILD_WITH_SOFTSUSY
197 oss <<
" This Hyperiso build was not configured with BUILD_WITH_SOFTSUSY=ON, "
198 <<
"so no bundled SOFTSUSY fallback is available.";
200 oss <<
" If your LHA file already contains a spectrum, set IS_LHA_SPECTRUM=True.";
201 out.
error = oss.str();
208 if (resolved.valid) {
209 return "SOFTSUSY executable: " + resolved.executable.string();
211 return resolved.error;
219 if (!resolved.valid) {
220 throw std::runtime_error(resolved.error);
223 const fs::path input = resolve_input_path(inputFilePath);
224 const fs::path output(outputFilePath);
227 if (output.has_parent_path()) {
228 fs::create_directories(output.parent_path(), ec);
230 throw std::runtime_error(
"Cannot create SOFTSUSY output directory '" + output.parent_path().string() +
"': " + ec.message());
234 const std::string command = shell_quote(resolved.executable.string()) +
235 " leshouches < " + shell_quote(input.string()) +
236 " > " + shell_quote(output.string());
238 LOG_DEBUG(
"SOFTSUSY COMMAND : " + command);
240 const int result = std::system(command.c_str());
242 throw std::runtime_error(
"SOFTSUSY execution failed with code " + std::to_string(result) +
243 ". Command was: " + command);
246 LOG_INFO(
"SOFTSUSY execution successful.");
#define LOG_INFO(...)
Macro for logging informational messages.
#define LOG_DEBUG(...)
Macro for logging debug messages.
void calculateSpectrum(const std::string &inputFilePath, const std::string &outputFilePath) override
Performs the spectrum calculation.
std::string availability_message()
Resolution set_external_path(const std::string &path)
Resolution resolve_executable()
std::filesystem::path executable