21#include <shared_mutex>
24#include <unordered_map>
27namespace fs = std::filesystem;
30std::shared_mutex marty_artifact_mutex;
31std::mutex marty_legacy_csv_mutex;
32std::atomic<std::uint64_t> marty_run_counter {0};
34constexpr const char* kMartyCacheAbi =
"HYPERISO_MARTY_CACHE_ABI: pyhyperiso-1.0.3-v5";
36std::string sanitize_path_component(std::string value) {
37 for (
char& c : value) {
38 const auto uc =
static_cast<unsigned char>(c);
39 if (!std::isalnum(uc) && c !=
'-' && c !=
'_') {
43 return value.empty() ? std::string(
"unnamed") : value;
46fs::path make_invocation_directory(
const std::shared_ptr<FileNameManager>& files,
47 const std::string& wilson,
48 const std::string& model) {
49 static const std::uint64_t process_nonce = [] {
50 std::random_device random;
51 return (
static_cast<std::uint64_t
>(random()) << 32)
52 ^
static_cast<std::uint64_t
>(random());
54 const auto counter = marty_run_counter.fetch_add(1, std::memory_order_relaxed);
55 const auto now = std::chrono::steady_clock::now().time_since_epoch().count();
56 const auto thread_hash = std::hash<std::thread::id>{}(std::this_thread::get_id());
58 std::ostringstream
name;
59 name << sanitize_path_component(model) <<
"_"
60 << sanitize_path_component(wilson) <<
"_"
61 << std::hex << process_nonce <<
"_" << now <<
"_"
62 << thread_hash <<
"_" << counter;
64 const fs::path dir = fs::path(files->getOutputDir()) /
"runs" /
name.str();
66 fs::create_directories(dir, ec);
68 throw std::runtime_error(
69 "Cannot create invocation-local MARTY directory: " + dir.string()
70 +
" (" + ec.message() +
")"
76void write_parameter_snapshot(
const fs::path& path,
77 const std::unordered_map<std::string, double>& params) {
78 std::ofstream output(path, std::ios::trunc);
80 throw std::runtime_error(
"Cannot write MARTY parameter snapshot: " + path.string());
91 throw std::runtime_error(
"Failed while writing MARTY parameter snapshot: " + path.string());
95void publish_legacy_csv(
const fs::path& isolated,
const fs::path& legacy) {
96 std::lock_guard<std::mutex> lock(marty_legacy_csv_mutex);
98 const auto split_csv_line = [](
const std::string& line) {
99 std::vector<std::string> cells;
100 std::stringstream stream(line);
102 while (std::getline(stream, cell,
',')) {
103 cells.push_back(cell);
109 std::vector<std::string> headers;
110 std::vector<std::vector<std::string>> rows;
113 const auto read_table = [&](
const fs::path& path,
bool required) {
115 std::ifstream input(path);
118 throw std::runtime_error(
"Cannot read MARTY CSV: " + path.string());
123 if (std::getline(input, line)) {
124 table.headers = split_csv_line(line);
126 while (std::getline(input, line)) {
128 table.rows.push_back(split_csv_line(line));
134 CsvTable incoming = read_table(isolated,
true);
135 if (incoming.headers.empty() || incoming.headers.front() !=
"Q_match") {
136 throw std::runtime_error(
"Invalid invocation-local MARTY CSV: " + isolated.string());
139 CsvTable merged = read_table(legacy,
false);
140 if (merged.headers.empty()) {
141 merged.headers = {
"Q_match"};
143 if (merged.headers.front() !=
"Q_match") {
144 throw std::runtime_error(
"Invalid legacy MARTY CSV: " + legacy.string());
147 std::unordered_map<std::string, std::size_t> merged_columns;
148 for (std::size_t i = 0; i < merged.headers.size(); ++i) {
149 merged_columns.emplace(merged.headers[i], i);
151 for (std::size_t i = 1; i < incoming.headers.size(); ++i) {
152 if (!merged_columns.contains(incoming.headers[i])) {
153 merged_columns.emplace(incoming.headers[i], merged.headers.size());
154 merged.headers.push_back(incoming.headers[i]);
155 for (
auto& row : merged.rows) {
156 row.resize(merged.headers.size(),
"NaN");
161 std::map<double, std::size_t> merged_rows;
162 for (std::size_t i = 0; i < merged.rows.size(); ++i) {
163 merged.rows[i].resize(merged.headers.size(),
"NaN");
164 if (!merged.rows[i].empty()) {
165 merged_rows[std::stod(merged.rows[i][0])] = i;
169 for (
const auto& incoming_row : incoming.rows) {
170 if (incoming_row.empty()) {
173 const double q_match = std::stod(incoming_row[0]);
174 std::size_t row_index = 0;
175 const auto existing = merged_rows.find(q_match);
176 if (existing == merged_rows.end()) {
177 row_index = merged.rows.size();
178 merged.rows.emplace_back(merged.headers.size(),
"NaN");
179 merged.rows.back()[0] = incoming_row[0];
180 merged_rows.emplace(q_match, row_index);
182 row_index = existing->second;
185 for (std::size_t i = 1; i < incoming.headers.size() && i < incoming_row.size(); ++i) {
186 merged.rows[row_index][merged_columns.at(incoming.headers[i])] = incoming_row[i];
191 fs::create_directories(legacy.parent_path(), ec);
193 throw std::runtime_error(
"Cannot create MARTY CSV directory: " + ec.message());
196 const fs::path tmp = legacy.string() +
".tmp." + std::to_string(
197 marty_run_counter.fetch_add(1, std::memory_order_relaxed)
200 std::ofstream output(tmp, std::ios::trunc);
202 throw std::runtime_error(
"Cannot write temporary MARTY CSV: " + tmp.string());
204 for (std::size_t i = 0; i < merged.headers.size(); ++i) {
205 output << merged.headers[i] << (i + 1 == merged.headers.size() ?
'\n' :
',');
207 for (
const auto& row : merged.rows) {
208 for (std::size_t i = 0; i < merged.headers.size(); ++i) {
209 output << (i < row.size() ? row[i] :
"NaN")
210 << (i + 1 == merged.headers.size() ?
'\n' :
',');
215 std::error_code cleanup_ec;
216 fs::remove(tmp, cleanup_ec);
217 throw std::runtime_error(
"Failed while writing temporary MARTY CSV: " + tmp.string());
221 fs::rename(tmp, legacy, ec);
223 std::error_code cleanup_ec;
224 fs::remove(tmp, cleanup_ec);
225 throw std::runtime_error(
"Cannot atomically publish MARTY CSV: " + ec.message());
229std::string template_signature(
const std::string& wilson,
230 const std::shared_ptr<FileNameManager>& files);
231std::string generation_mode_marker(
const std::string& wilson,
233 bool bsm_only_generation,
234 bool full_target_generation);
235void append_cache_metadata_if_missing(
const fs::path& generated_file,
236 const std::string& model_signature,
237 const std::string& template_signature_value,
238 const std::string& mode_marker);
239bool template_needs_generic_tree_first(
const std::string& wilson,
240 const std::shared_ptr<FileNameManager>& files);
245 core_api = std::make_shared<ModelAPI>();
248 ports = std::make_shared<DefaultInterpreterPortsFactory>();
259 if (!this->already_run(files->getExecutableFileName())) {
260 compiler.
compile_run(files->getGeneratedFileName(), files->getExecutableFileName());
265 generate(std::move(wilson), model, model, std::move(model_path),
false,
false,
false);
269 std::string output_model,
270 std::string target_model,
271 std::string model_path,
273 bool bsm_split_generation,
274 bool full_target_generation) {
279 const auto model_template_index = resolve_model_template_index(target_model);
281 const bool tree_first_fallback = template_needs_generic_tree_first(wilson, files);
282 invalidate_template_model_cache_if_needed(
283 wilson, output_model, target_model, model_path, model_template_index,
284 sm_like_filter, bsm_split_generation, full_target_generation
287 std::unique_ptr<ModelModifier> smModifier;
288 smModifier = std::make_unique<GeneralModelModifier>(
289 wilson, output_model, target_model, model_path, model_template_index,
290 sm_like_filter, bsm_split_generation, full_target_generation,
294 std::unique_ptr<TemplateManagerBase> templateManager = std::make_unique<NonNumericTemplateManager>(files->getTemplateDir());
295 templateManager->setModelAndWilson(output_model, wilson);
296 templateManager->setModelModifier(std::move(smModifier));
300 codeGenerator.
generate(wilson, files->getGeneratedFileName());
301 append_cache_metadata_if_missing(
302 files->getGeneratedFileName(),
304 template_signature(wilson, files),
305 generation_mode_marker(wilson, sm_like_filter, bsm_split_generation, full_target_generation)
314 std::string output_model,
315 std::string target_model,
316 bool bsm_split_generation,
317 bool full_target_generation) {
322 bool forceMode =
false;
324 const std::string cinematic_template = file_names->getGeneratedFileName();
326 std::unique_ptr<SMParamSetter> sm_p_setter = std::make_unique<SMParamSetter>(
334 std::unique_ptr<GeneralNumModelModifier>
ModelModifier = std::make_unique<GeneralNumModelModifier>(
338 std::move(sm_p_setter),
342 bsm_split_generation,
343 full_target_generation
346 std::unique_ptr<TemplateManagerBase> templateManager = std::make_unique<NumericTemplateManager>(file_names->getLibDir());
347 templateManager->setModelAndWilson(output_model, wilson);
348 templateManager->setNumModelModifier(std::move(
ModelModifier));
349 const auto discovered_dependencies = templateManager->get_dependencies();
350 auto& cached_dependencies = this->dependencies[wilson];
351 cached_dependencies.insert(discovered_dependencies.begin(), discovered_dependencies.end());
353 std::string file_path = file_names->getNumGeneratedFileName();
354 codeGenerator.
generate(file_path, file_path);
368 calculate(std::move(wilson), model, model, Q_match, std::move(model_path),
false,
false,
false);
372 std::string output_model,
373 std::string target_model,
375 std::string model_path,
377 bool bsm_split_generation,
378 bool full_target_generation) {
390 bsm_split_generation,
391 full_target_generation
393 if (isolated_csv.empty()) {
399 publish_legacy_csv(isolated_csv, legacy_csv);
401 std::error_code cleanup_ec;
402 fs::remove_all(isolated_csv.parent_path(), cleanup_ec);
406 std::error_code cleanup_ec;
407 fs::remove_all(isolated_csv.parent_path(), cleanup_ec);
410void MartyInterface::compile_numlib(
const std::string& wilson,
const std::string& model) {
413 if (!compiler.check_if_compile(files->getNumExecutableFileName())) {
414 compiler.compile(files->getLibDir(), files->getNumExecutableFileName());
418std::unordered_map<std::string, double> MartyInterface::snapshot_numeric_params(
419 const std::string& wilson,
420 const std::string& output_model,
421 const std::string& target_model,
422 bool bsm_split_generation,
423 bool full_target_generation
426 auto setter = std::make_unique<SMParamSetter>(
431 files->getGeneratedFileName()
441 bsm_split_generation,
442 full_target_generation
444 return modifier.get_params();
447void MartyInterface::ensure_built(
const std::string& wilson,
448 const std::string& output_model,
449 const std::string& target_model,
450 const std::string& model_path,
452 bool bsm_split_generation,
453 bool full_target_generation) {
460 bsm_split_generation,
461 full_target_generation
468 bsm_split_generation,
469 full_target_generation
471 compile_numlib(wilson, output_model);
474bool MartyInterface::artifacts_ready(
const std::string& wilson,
475 const std::string& output_model,
476 const std::string& target_model,
477 const std::string& model_path,
479 bool bsm_split_generation,
480 bool full_target_generation)
const {
482 const auto model_template_index = resolve_model_template_index(target_model);
488 const std::string expected_template_signature = template_signature(wilson, files);
489 const std::string expected_mode = generation_mode_marker(
492 bsm_split_generation,
493 full_target_generation
496 std::ifstream generated(files->getGeneratedFileName());
501 bool has_cache_abi =
false;
502 bool has_model_signature =
false;
503 bool has_template_signature =
false;
504 bool has_generation_mode =
false;
506 while (std::getline(generated, line)) {
507 has_cache_abi = has_cache_abi || line.find(kMartyCacheAbi) != std::string::npos;
508 has_model_signature = has_model_signature || line.find(expected_model_signature) != std::string::npos;
509 has_template_signature = has_template_signature || line.find(expected_template_signature) != std::string::npos;
510 has_generation_mode = has_generation_mode || line.find(expected_mode) != std::string::npos;
513 const auto non_empty_file = [](
const fs::path& path) {
515 return fs::is_regular_file(path, ec) && !ec && fs::file_size(path, ec) > 0 && !ec;
517 const auto has_generation_marker = [](
const fs::path& path) {
518 std::ifstream input(path);
520 for (
int i = 0; i < 16 && std::getline(input, header); ++i) {
521 if (header.find(
"//42") != std::string::npos) {
529 && has_model_signature
530 && has_template_signature
531 && has_generation_mode
532 && non_empty_file(files->getExecutableFileName())
533 && non_empty_file(files->getNumGeneratedFileName())
534 && has_generation_marker(files->getNumGeneratedFileName())
535 && non_empty_file(files->getNumExecutableFileName())
536 && this->dependencies.contains(wilson);
540 std::string output_model,
541 std::string target_model,
543 std::string model_path,
545 bool bsm_split_generation,
546 bool full_target_generation) {
551 const auto execute_isolated = [&]() -> std::string {
553 const fs::path run_dir = make_invocation_directory(files, wilson, output_model);
554 const fs::path param_file = run_dir /
"paramlist.csv";
555 const fs::path output_file = run_dir /
"wilson.csv";
558 write_parameter_snapshot(
560 snapshot_numeric_params(
564 bsm_split_generation,
565 full_target_generation
573 compiler.
compile_run(files->getLibDir(), files->getNumExecutableFileName());
576 if (!fs::is_regular_file(output_file, ec) || ec || fs::file_size(output_file, ec) == 0 || ec) {
577 throw std::runtime_error(
578 "MARTY numeric execution did not create a non-empty invocation-local CSV: "
579 + output_file.string()
582 return output_file.string();
584 std::error_code cleanup_ec;
585 fs::remove_all(run_dir, cleanup_ec);
591 std::shared_lock<std::shared_mutex> read_lock(marty_artifact_mutex);
598 bsm_split_generation,
599 full_target_generation
601 return execute_isolated();
605 std::unique_lock<std::shared_mutex> build_lock(marty_artifact_mutex);
606 if (!artifacts_ready(
612 bsm_split_generation,
613 full_target_generation
621 bsm_split_generation,
622 full_target_generation
625 return execute_isolated();
629std::optional<int> MartyInterface::resolve_model_template_index(
const std::string& model)
const {
630 std::string model_upper = model;
631 std::transform(model_upper.begin(), model_upper.end(), model_upper.begin(), [](
unsigned char c) {
632 return static_cast<char>(std::toupper(c));
635 if (model_upper !=
"THDM") {
639 if (!param_proxy_bsm) {
640 LOG_ERROR(
"MartyConfigError",
"Cannot instantiate the templated THDM MARTY model: no BSM parameter proxy is available to read MINPAR(24). ",
641 "Set the THDM Yukawa type in the LHA card or provide a BSM parameter provider before MARTY generation.");
644 const double raw_type = (*param_proxy_bsm)(
"MINPAR",
LhaID(24));
645 const int type =
static_cast<int>(std::lround(raw_type));
647 if (std::abs(raw_type -
static_cast<double>(type)) > 1e-9 || type < 1 || type > 4) {
648 LOG_ERROR(
"MartyConfigError",
"Invalid THDM Yukawa type MINPAR(24)=", raw_type,
649 ". MARTY THDM generation expects an integer type in {1,2,3,4}.");
652 LOG_INFO(
"MartyInterface",
"Using THDM Yukawa type ", type,
" from MINPAR(24) for MARTY generation.");
658std::string stable_file_fingerprint(
const fs::path& path) {
659 std::ifstream input(path, std::ios::binary);
661 throw std::runtime_error(
"Cannot fingerprint MARTY template file: " + path.string());
664 std::uint64_t hash = 14695981039346656037ULL;
666 while (input.read(buffer,
sizeof(buffer)) || input.gcount() > 0) {
667 const auto count = input.gcount();
668 for (std::streamsize i = 0; i < count; ++i) {
669 hash ^=
static_cast<unsigned char>(buffer[i]);
670 hash *= 1099511628211ULL;
674 std::ostringstream result;
675 result << std::hex << std::setw(16) << std::setfill(
'0') << hash;
679std::string normalized_path(
const fs::path& path) {
681 fs::path normalized = fs::weakly_canonical(path, ec);
684 normalized = fs::absolute(path, ec);
686 return normalized.lexically_normal().string();
689std::string template_signature(
const std::string& wilson,
690 const std::shared_ptr<FileNameManager>& files) {
691 const fs::path path = fs::path(files->getTemplateDir()) / (wilson +
".cpp");
692 return "HYPERISO_MARTY_TEMPLATE_SIGNATURE: path=" + normalized_path(path)
693 +
"; fnv1a64=" + stable_file_fingerprint(path);
696bool uses_split_regprop_policy(
const std::string& wilson) {
697 return wilson ==
"C9" || wilson ==
"CP9" || wilson ==
"CP10";
700bool template_needs_generic_tree_first(
const std::string& wilson,
701 const std::shared_ptr<FileNameManager>& files) {
702 if (uses_split_regprop_policy(wilson)) {
706 const fs::path path = fs::path(files->getTemplateDir()) / (wilson +
".cpp");
707 std::ifstream input(path);
709 throw std::runtime_error(
"Cannot inspect MARTY template order policy: " + path.string());
712 const std::string source(
713 (std::istreambuf_iterator<char>(input)),
714 std::istreambuf_iterator<char>()
716 static const std::regex tree_call(
717 R
"(computeWilsonCoefficients\s*\(\s*(?:mty::Order::)?TreeLevel)"
719 static const std::regex loop_call(
720 R
"(computeWilsonCoefficients\s*\(\s*(?:mty::Order::)?OneLoop)"
723 return std::regex_search(source, loop_call) && !std::regex_search(source, tree_call);
726std::string generation_mode(
const std::string& wilson,
728 bool bsm_only_generation,
729 bool full_target_generation) {
730 if (sm_like_filter) {
733 if (full_target_generation && bsm_only_generation && uses_split_regprop_policy(wilson)) {
734 return "target-regprop-split";
736 if (full_target_generation) {
737 return "target-full";
739 if (bsm_only_generation && uses_split_regprop_policy(wilson)) {
740 return "bsm-regprop-split";
742 if (bsm_only_generation) {
748std::string generation_mode_marker(
const std::string& wilson,
750 bool bsm_only_generation,
751 bool full_target_generation) {
752 return "HYPERISO_MARTY_GENERATION_MODE: "
757 full_target_generation
761void append_cache_metadata_if_missing(
const fs::path& generated_file,
762 const std::string& model_signature,
763 const std::string& template_signature_value,
764 const std::string& mode_marker) {
765 std::ifstream input(generated_file);
767 throw std::runtime_error(
768 "MARTY source generation did not create the expected file: " + generated_file.string()
772 bool has_cache_abi =
false;
774 while (std::getline(input, line)) {
775 if (line.find(kMartyCacheAbi) != std::string::npos) {
776 has_cache_abi =
true;
784 std::ofstream output(generated_file, std::ios::app);
786 throw std::runtime_error(
787 "Cannot append MARTY cache metadata to: " + generated_file.string()
790 output <<
"\n// " << kMartyCacheAbi <<
"\n";
791 output <<
"// " << model_signature <<
"\n";
792 output <<
"// " << template_signature_value <<
"\n";
793 output <<
"// " << mode_marker <<
"\n";
798void MartyInterface::invalidate_template_model_cache_if_needed(
const std::string& wilson,
799 const std::string& output_model,
800 const std::string& target_model,
801 const std::string& model_path,
802 std::optional<int> model_template_index,
804 bool bsm_split_generation,
805 bool full_target_generation)
const {
812 const std::string expected_template_signature = template_signature(wilson, files);
813 const std::string expected_mode = generation_mode_marker(
816 bsm_split_generation,
817 full_target_generation
820 bool file_present =
false;
821 bool has_cache_abi =
false;
822 bool has_model_signature =
false;
823 bool has_template_signature =
false;
824 bool has_generation_mode =
false;
827 std::ifstream in(files->getGeneratedFileName());
828 file_present =
static_cast<bool>(in);
830 while (std::getline(in, line)) {
831 has_cache_abi = has_cache_abi || line.find(kMartyCacheAbi) != std::string::npos;
832 has_model_signature = has_model_signature || line.find(expected_model_signature) != std::string::npos;
833 has_template_signature = has_template_signature || line.find(expected_template_signature) != std::string::npos;
834 has_generation_mode = has_generation_mode || line.find(expected_mode) != std::string::npos;
838 const bool stale = !file_present
840 || !has_model_signature
841 || !has_template_signature
842 || !has_generation_mode;
849 fs::remove(files->getGeneratedFileName(), ec);
851 fs::remove(files->getExecutableFileName(), ec);
853 fs::remove_all(files->getLibDir(), ec);
855 fs::remove(files->getCsvWilsonFileName(), ec);
859 reason =
"generated file is missing";
860 }
else if (!has_cache_abi) {
861 reason =
"cache ABI mismatch";
862 }
else if (!has_model_signature) {
863 reason =
"model path/content signature mismatch";
864 }
else if (!has_template_signature) {
865 reason =
"template content signature mismatch";
866 }
else if (!has_generation_mode) {
867 reason =
"generation mode mismatch";
869 reason =
"cache metadata mismatch";
872 LOG_INFO(
"MartyInterface",
"Invalidated stale MARTY cache for ", wilson,
" / ", output_model,
873 " because ", reason,
". Expected mode: ", expected_mode,
874 "; expected model signature: ", expected_model_signature);
878 std::shared_lock<std::shared_mutex> read_lock(marty_artifact_mutex);
879 if (!this->dependencies.contains(wilson)) {
880 LOG_ERROR(
"KeyError",
"Trying to access dependencies for unknown wilson coefficient", wilson,
"in WilsonInterface.");
883 return this->dependencies.at(wilson);
886bool MartyInterface::already_run(std::string&& outputBinary) {
888 if (stat(outputBinary.c_str(), &buffer) != 0) {
891 if (buffer.st_size == 0) {
898std::string MartyInterface::output_binary_name(std::string& wilson, std::string& model) {
899 return "generated_" + wilson+
"_" + model +
".cpp";
903 return this->specials_block;
Declares the default factory for interpreter ports.
#define LOG_ERROR(type,...)
Macro for logging error messages and terminating the application.
#define LOG_INFO(...)
Macro for logging informational messages.
#define LOG_DEBUG(...)
Macro for logging debug messages.
High-level façade around MARTY-based code generation and compilation.
Concrete parameter proxy that reads values from Hyperiso Parameters.
Declares a small helper to write parameter maps to CSV files.
A class that generates code using a template manager.
void generate(const std::string &templateName, const std::string &outputPath)
Generates a code file based on a specified template.
static std::shared_ptr< FileNameManager > getInstance(const std::string &wilson="", const std::string &model="")
Retrieves a FileNameManager for a given (wilson, model) pair.
static std::string modelSignature(const std::string &model, const std::string &model_path, std::optional< int > model_template_index=std::nullopt)
Build the cache signature written in generated analytical files.
High-level orchestrator for numeric MARTY model generation.
Compilation strategy using the g++ compiler.
void compile_run(const std::string &sourceFile, const std::string &outputBinary) override
Compiles if necessary and then runs the resulting binary.
Compilation strategy using a make-based build system.
void compile_run(const std::string &sourceFile, const std::string &outputBinary) override
Compiles if necessary and then runs the resulting binary.
void set_output_file(std::filesystem::path path)
void set_param_file(std::filesystem::path path)
void set_Q_match(double Q_match)
Sets the matching scale passed to the binary.
void compile_run_libs(std::string wilson, std::string model, double Q_match)
Compiles and runs the numeric libraries.
std::set< std::string > get_special_blocks()
Returns the special blocks handled with custom logic.
std::string calculate_isolated(std::string wilson, std::string output_model, std::string target_model, double Q_match, std::string model_path, bool sm_like_filter, bool bsm_split_generation=false, bool full_target_generation=false)
Thread-safe calculation using invocation-local parameter and CSV files.
void generate(std::string wilson, std::string model, std::string model_path)
Generates a non-numeric MARTY-powered C++ template.
std::unordered_set< InterpretedParam > get_dependencies(std::string wilson)
Retrieves the set of parameter dependencies for a given Wilson basis.
void compile_run(std::string wilson, std::string model)
Compiles and runs the non-numeric generated code.
MartyInterface()
Default constructor wiring default implementations.
void calculate(std::string wilson, std::string model, double Q_match, std::string model_path)
Convenience shortcut to generate, compile, and run the full pipeline.
void generate_numlib(std::string wilson, std::string model)
Generates the numeric library wrapper for a given (Wilson, model) pair.
static InstallInfo require_available(const std::string &context)
Validate and return the active MARTY installation.
Abstract base class for model source modifiers.
Helper class to serialize parameter values to a text stream.
void writeParams(std::ofstream &outputFile, const std::unordered_map< std::string, double > ¶ms)
Writes a map of parameters to an output stream.
Represents an identifier of a LHA element, possibly containing several sub-ids.