23#include "InitUtils.hpp"
25#include <TDirectory.h>
32#include <TSystemDirectory.h>
42#ifndef MUSIC_TALYS_BIN
43#define MUSIC_TALYS_BIN ""
45#ifndef MUSIC_TALYS_ATOMKI_V2_DIR
46#define MUSIC_TALYS_ATOMKI_V2_DIR ""
53const Double_t kEcmStep = 0.25;
54const Double_t kEcmMargin = 1.0;
58TGraph *ReadResidual(
const TString &path, Double_t cm_per_lab) {
59 std::ifstream in(path.Data());
62 std::vector<Double_t> e, xs;
64 while (std::getline(in, line)) {
65 if (line.empty() || line[0] ==
'#')
67 std::istringstream ss(line);
68 Double_t el = 0.0, s = 0.0;
71 e.push_back(el * cm_per_lab);
76 return new TGraph(Int_t(e.size()), &e[0], &xs[0]);
80 for (Int_t k = 0; k < Int_t(model.
keywords.size()); k++) {
81 std::istringstream ss(model.
keywords[k].Data());
84 if ((ss >> key >> value) && key ==
"alphaomp" && value == 9)
90void ClearWorkDir(
const TString &work) {
91 TSystemDirectory sd(
"work", work);
92 TList *files = sd.GetListOfFiles();
95 for (TIter it(files); TObject *o = it();) {
96 const TString name = o->GetName();
97 if (name.EndsWith(
".tot") || name ==
"talys.out" ||
98 name ==
"alphaomp9real.gnu")
99 gSystem->Unlink(work +
"/" + name);
104Bool_t TalysSucceeded(
const TString &out_path) {
105 std::ifstream in(out_path.Data());
107 while (std::getline(in, line))
108 if (line.find(
"congratulates you with this successful calculation") !=
114TString TalysErrorLine(
const TString &out_path) {
115 std::ifstream in(out_path.Data());
117 while (std::getline(in, line))
118 if (line.find(
"TALYS-error") != std::string::npos)
119 return TString(line.c_str()).Strip(TString::kBoth);
120 return "no TALYS-error line found";
125Int_t RunModel(
const TalysModel &model,
const TString &work,
126 const TString &talys,
const TString &energies,
127 Double_t cm_per_lab, TDirectory *dir) {
129 gSystem->mkdir(work, kTRUE);
131 if (WantsAtomkiV2(model)) {
132 const Char_t *env = gSystem->Getenv(
"TALYS_ATOMKI_V2_DIR");
133 const TString pot_dir = (env && env[0] !=
'\0')
136 if (pot_dir.IsNull()) {
137 std::cerr <<
"talys-xs: " << model.
label
138 <<
" needs alphaomp 9 but TALYS_ATOMKI_V2_DIR is not set"
142 const TString pot = pot_dir + Form(
"/z%03da%03da_talys_alphaomp9real.gnu",
144 if (gSystem->AccessPathName(pot, kReadPermission)) {
145 std::cerr <<
"talys-xs: no Atomki-V2 potential for Z=" << X.
BEAM_Z
146 <<
" A=" << X.
BEAM_A <<
" at " << pot << std::endl;
149 if (gSystem->Symlink(pot, work +
"/alphaomp9real.gnu") != 0) {
150 std::cerr <<
"talys-xs: cannot link " << pot <<
" into " << work
155 std::ostringstream input_ss;
157 << model.
label << std::endl;
158 input_ss <<
"projectile a" << std::endl;
160 input_ss << Form(
"mass %d", X.
BEAM_A) << std::endl;
161 input_ss <<
"energy energies" << std::endl;
165 input_ss <<
"#" << std::endl;
166 input_ss <<
"# common settings (CROSS_SECTION_CONFIG.TALYS_COMMON_KEYWORDS)"
171 input_ss <<
"#" << std::endl;
172 input_ss <<
"# model: " << model.
label << std::endl;
173 for (Int_t k = 0; k < Int_t(model.
keywords.size()); k++)
174 input_ss << model.
keywords[k] << std::endl;
175 const TString input = input_ss.str();
177 std::ofstream en((work +
"/energies").Data());
179 std::ofstream inp((work +
"/talys.inp").Data());
182 for (Int_t k = 0; k < Int_t(model.
keywords.size()); k++)
183 std::cout <<
" " << model.
keywords[k] << std::endl;
184 const TString cmd = Form(
"cd '%s' && '%s' < talys.inp > talys.out 2>&1",
185 work.Data(), talys.Data());
186 if (std::system(cmd.Data()) != 0 || !TalysSucceeded(work +
"/talys.out")) {
187 std::cerr <<
"talys-xs: TALYS failed for " << model.
label <<
": "
188 << TalysErrorLine(work +
"/talys.out") <<
"; see " << work
189 <<
"/talys.out" << std::endl;
194 TNamed(
"label", model.
label.Data()).Write();
195 TNamed(
"input", input.Data()).Write();
197 TSystemDirectory sd(
"work", work);
198 TList *files = sd.GetListOfFiles();
199 for (TIter it(files); TObject *o = it();) {
200 const TString name = o->GetName();
202 if (!name.EndsWith(
".tot") || sscanf(name.Data(),
"rp%3d%3d", &z, &a) != 2)
204 TGraph *g = ReadResidual(work +
"/" + name, cm_per_lab);
207 g->SetName(Form(
"rp%03d%03d", z, a));
208 g->SetTitle(Form(
"Z=%d A=%d residual production;E_{c.m.} [MeV];#sigma "
222 InitUtils::SetROOTPreferences(PlotSaveFormat::kPNG,
228 std::cerr <<
"talys-xs: this dataset's CROSS_SECTION_CONFIG needs BEAM_A, "
229 "BEAM_Z, BEAM_ELEMENT, BEAM_SIM_FILE and at least one "
234 const Char_t *env = gSystem->Getenv(
"TALYS_BIN");
235 TString talys = (env && env[0] !=
'\0') ? TString(env) :
MUSIC_TALYS_BIN;
242 Double_t e_strip0 = 0.0;
244 std::cerr <<
"talys-xs: cannot read the simulated beam at "
251 const Double_t lab_per_cm =
256 Double_t e_lo = TMath::Max(
262 for (Int_t c = 0; c < Int_t(X.
CHANNELS.size()); c++)
263 for (Int_t k = 0; k < Int_t(X.
CHANNELS[c].reference_xs.size()); k++) {
264 e_lo = TMath::Min(e_lo, X.
CHANNELS[c].reference_xs[k][0] - kEcmMargin);
265 e_hi = TMath::Max(e_hi, X.
CHANNELS[c].reference_xs[k][0] + kEcmMargin);
267 const Double_t ecm_lo =
268 kEcmStep * std::floor(TMath::Max(kEcmStep, e_lo) / kEcmStep);
269 const Double_t ecm_hi = kEcmStep * std::ceil(e_hi / kEcmStep);
270 std::ostringstream energies_ss;
271 for (Double_t ecm = ecm_lo; ecm <= ecm_hi + 1.0e-9; ecm += kEcmStep)
272 energies_ss << Form(
"%.4f", ecm * lab_per_cm) << std::endl;
273 const TString energies = energies_ss.str();
278 const TString out_path = talys_dir +
"/talys_xs.root";
279 gSystem->mkdir(talys_dir, kTRUE);
280 TFile out(out_path,
"RECREATE");
281 if (out.IsZombie()) {
282 std::cerr <<
"talys-xs: cannot write " << out_path << std::endl;
285 TNamed(
"talys", talys.Data()).Write();
287 << ecm_lo <<
".." << ecm_hi <<
" MeV (strips " << X.
XS_STRIP_MIN
289 <<
" model(s), " << talys << std::endl;
290 for (Int_t m = 0; m < Int_t(X.
TALYS_MODELS.size()); m++) {
292 std::cout <<
" m" << m <<
": " << model.
label << std::endl;
293 TDirectory *dir = out.mkdir(Form(
"m%d", m));
294 const Int_t n = RunModel(model, talys_dir + Form(
"/work/m%d", m), talys,
295 energies, 1.0 / lab_per_cm, dir);
298 std::cerr <<
"talys-xs: no residual-production files for "
299 << model.
label << std::endl;
302 std::cout <<
" " << n <<
" residual channels" << std::endl;
305 std::cout <<
"talys-xs: -> " << out_path << std::endl;
Int_t TargetGasA(TargetGas gas)
Mass number of the target nucleus in a fill gas.
static TString DatasetName()
The dataset's isotope name, e.g.
static TString ResultsDir()
Absolute path to the directory receiving generated output.
#define MUSIC_TALYS_ATOMKI_V2_DIR
#define MUSIC_TALYS_BIN
talys-xs: Hauser-Feshbach cross sections from TALYS for this dataset's reaction, written as ROOT grap...
Double_t LabAtStrip(const Double_t *dE, Double_t e_strip0, Int_t reac)
Lab energy entering a given strip.
Bool_t Profile(const TString &path, Double_t *dE, Double_t &e_strip0)
Read the per-strip energy loss profile from a beam simulation.
Double_t CmFraction()
Centre-of-mass energy fraction for this dataset's reaction.
TString SimPath()
Path to the dataset's beam simulation file.
const DatasetConfig & cfg
The active dataset's configuration, flat block.
Experimental details needed to properly calculate the cross section.
Int_t XS_STRIP_MIN
Reaction strips for which to calculate a cross-section.
TString BEAM_SIM_FILE
Simulated unreacted beam, read for the energy at each strip.
Int_t BEAM_A
Beam mass number, for the lab-to-centre-of-mass conversion; its Z and element symbol name it to a rea...
std::vector< TalysModel > TALYS_MODELS
Hauser-Feshbach predictions from TALYS.
std::vector< CrossSectionChannel > CHANNELS
The reaction channels measured on this dataset.
std::vector< TString > TALYS_COMMON_KEYWORDS
Input lines written into every model's TALYS input, after the projectile, target and energies and bef...
One TALYS model variant to compare against.
TString label
Legend label for this model's curve.
std::vector< TString > keywords
TALYS keywords selecting the variant.