Hyperiso 1.0.3
Modular flavour-physics calculations, Wilson coefficients and statistical inference
Loading...
Searching...
No Matches
SoftSusy.cpp
Go to the documentation of this file.
1#include "SoftSusy.h"
2
3#include <cstdlib>
4#include <filesystem>
5#include <sstream>
6#include <stdexcept>
7#include <string>
8#include <system_error>
9#include <vector>
10
11#include "Logger.h"
12#include "config.hpp"
13
14namespace fs = std::filesystem;
15
16namespace {
17
18std::optional<fs::path>& external_softsusy_path()
19{
20 static std::optional<fs::path> path;
21 return path;
22}
23
24std::string shell_quote(const std::string& value)
25{
26 std::string quoted = "'";
27 for (char c : value) {
28 if (c == '\'') {
29 quoted += "'\\''";
30 } else {
31 quoted += c;
32 }
33 }
34 quoted += "'";
35 return quoted;
36}
37
38bool is_existing_file(const fs::path& path)
39{
40 std::error_code ec;
41 return fs::exists(path, ec) && fs::is_regular_file(path, ec);
42}
43
44fs::path normalize_path(const fs::path& path)
45{
46 std::error_code ec;
47 const fs::path canonical = fs::weakly_canonical(path, ec);
48 return ec ? fs::absolute(path) : canonical;
49}
50
51std::vector<fs::path> softsusy_candidates_from(const fs::path& raw)
52{
53 std::vector<fs::path> candidates;
54 candidates.push_back(raw);
55
56 std::error_code ec;
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");
62 }
63
64 return candidates;
65}
66
67SoftsusyRuntimeConfig::Resolution resolve_from_path(const fs::path& raw)
68{
69 for (const auto& candidate : softsusy_candidates_from(raw)) {
70 if (is_existing_file(candidate)) {
72 out.valid = true;
73 out.executable = normalize_path(candidate);
74 return out;
75 }
76 }
77
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();
84 return out;
85}
86
87std::optional<fs::path> environment_softsusy_path()
88{
89 if (const char* env = std::getenv("HYPERISO_SOFTSUSY")) {
90 if (std::string(env).empty() == false) {
91 return fs::path(env);
92 }
93 }
94 return std::nullopt;
95}
96
97std::optional<fs::path> path_softsusy_executable()
98{
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)) {
108 return candidate;
109 }
110 }
111 if (end == std::string::npos) {
112 break;
113 }
114 start = end + 1;
115 }
116 }
117 return std::nullopt;
118}
119
120#ifdef BUILD_WITH_SOFTSUSY
121std::optional<fs::path> bundled_softsusy_executable()
122{
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"
128 };
129
130 for (const auto& candidate : candidates) {
131 if (is_existing_file(candidate)) {
132 return candidate;
133 }
134 }
135 return std::nullopt;
136}
137#endif
138
139fs::path resolve_input_path(const std::string& inputFilePath)
140{
141 const fs::path input(inputFilePath);
142 if (input.is_absolute()) {
143 return input;
144 }
145 return fs::path(project_assets_root.data()) / input;
146}
147
148} // namespace
149
151
152Resolution set_external_path(const std::string& path)
153{
154 const auto resolved = resolve_from_path(fs::path(path));
155 if (resolved.valid) {
156 external_softsusy_path() = resolved.executable;
157 }
158 return resolved;
159}
160
162{
163 if (external_softsusy_path().has_value()) {
164 return resolve_from_path(*external_softsusy_path());
165 }
166
167 if (auto env_path = environment_softsusy_path()) {
168 auto resolved = resolve_from_path(*env_path);
169 if (resolved.valid) {
170 return resolved;
171 }
172 }
173
174 if (auto path_candidate = path_softsusy_executable()) {
175 auto resolved = resolve_from_path(*path_candidate);
176 if (resolved.valid) {
177 return resolved;
178 }
179 }
180
181#ifdef BUILD_WITH_SOFTSUSY
182 if (auto bundled = bundled_softsusy_executable()) {
183 auto resolved = resolve_from_path(*bundled);
184 if (resolved.valid) {
185 return resolved;
186 }
187 }
188#endif
189
190 Resolution out;
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.";
199#endif
200 oss << " If your LHA file already contains a spectrum, set IS_LHA_SPECTRUM=True.";
201 out.error = oss.str();
202 return out;
203}
204
206{
207 const auto resolved = resolve_executable();
208 if (resolved.valid) {
209 return "SOFTSUSY executable: " + resolved.executable.string();
210 }
211 return resolved.error;
212}
213
214} // namespace SoftsusyRuntimeConfig
215
216void SoftsusyCalculator::calculateSpectrum(const std::string& inputFilePath, const std::string& outputFilePath)
217{
218 const auto resolved = SoftsusyRuntimeConfig::resolve_executable();
219 if (!resolved.valid) {
220 throw std::runtime_error(resolved.error);
221 }
222
223 const fs::path input = resolve_input_path(inputFilePath);
224 const fs::path output(outputFilePath);
225
226 std::error_code ec;
227 if (output.has_parent_path()) {
228 fs::create_directories(output.parent_path(), ec);
229 if (ec) {
230 throw std::runtime_error("Cannot create SOFTSUSY output directory '" + output.parent_path().string() + "': " + ec.message());
231 }
232 }
233
234 const std::string command = shell_quote(resolved.executable.string()) +
235 " leshouches < " + shell_quote(input.string()) +
236 " > " + shell_quote(output.string());
237
238 LOG_DEBUG("SOFTSUSY COMMAND : " + command);
239
240 const int result = std::system(command.c_str());
241 if (result != 0) {
242 throw std::runtime_error("SOFTSUSY execution failed with code " + std::to_string(result) +
243 ". Command was: " + command);
244 }
245
246 LOG_INFO("SOFTSUSY execution successful.");
247}
#define LOG_INFO(...)
Macro for logging informational messages.
Definition Logger.h:39
#define LOG_DEBUG(...)
Macro for logging debug messages.
Definition Logger.h:45
void calculateSpectrum(const std::string &inputFilePath, const std::string &outputFilePath) override
Performs the spectrum calculation.
Definition SoftSusy.cpp:216
std::string availability_message()
Definition SoftSusy.cpp:205
Resolution set_external_path(const std::string &path)
Definition SoftSusy.cpp:152
Resolution resolve_executable()
Definition SoftSusy.cpp:161
std::filesystem::path executable
Definition SoftSusy.h:14