5#include <fast_float/fast_float.h>
19constexpr void trim(std::string_view &text) {
21 text.remove_prefix(1);
23 text.remove_suffix(1);
26constexpr std::string_view
next(std::string_view &text) {
27 std::string_view
next = text.substr(
28 0, text.find_first_of(
'-', text.size() > 0 and text.front() ==
'-'));
29 text.remove_prefix(std::min(text.size(),
next.size()+1));
35constexpr std::string_view
next_tag(std::string_view &text) {
36 std::string_view
next = text.substr(0, text.find_first_of(
','));
37 text.remove_prefix(std::min(text.size(),
next.size()+1));
44 std::string_view orig [[maybe_unused]]) {
45 Species s = fromShortName(part);
49 "The original tag reads ",
55 std::string_view orig [[maybe_unused]]) {
58 "\nValid options are:\n",
60 "\nThe original tag reads ", std::quoted(orig))
64constexpr Numeric
freq(std::string_view part,
65 std::string_view orig [[maybe_unused]]) {
67 if (part.size() == 1 and part.front() ==
'*')
71 fast_float::from_chars(part.data(), part.data() + part.size(), f);
73 "Invalid argument: ", std::quoted(part),
74 "\nThe original tag reads ", std::quoted(orig));
76 "Out-of-range: ", std::quoted(part),
77 "\nThe original tag reads ", std::quoted(orig));
82constexpr void check(std::string_view text, std::string_view orig) {
85 " remains to be parsed at end of a complete species tag\n"
86 "The original tag reads ", std::quoted(orig))
91 using namespace detail;
94 const std::string_view orig = text;
98 const Species species = spec(next(text), orig);
102 if (species == Species::free_electrons) {
103 constexpr Index ind =
106 tag.type = TagType::FreeElectrons;
111 if (species == Species::particles) {
114 tag.type = TagType::Particles;
119 if (text.size() == 0) {
120 if (tag.type == TagType::FINAL) {
121 tag.spec_ind = isot(species,
Joker, orig);
122 tag.type = TagType::Plain;
126 if (
const std::string_view tag_key = next(text); tag_key.front() ==
'Z') {
127 tag.spec_ind = isot(species, next(text), orig);
128 tag.type = TagType::Zeeman;
131 "Bad Zeeman tag using predefined model in tag: ", std::quoted(orig))
132 }
else if (tag_key ==
"CIA") {
133 tag.spec_ind = isot(species,
Joker, orig);
134 tag.cia_2nd_species = spec(next(text), orig);
135 tag.type = TagType::Cia;
137 }
else if (tag_key ==
"XFIT") {
138 tag.spec_ind = isot(species,
Joker, orig);
139 tag.type = TagType::XsecFit;
142 tag.spec_ind = isot(species, tag_key, orig);
144 ? TagType::Predefined
150 tag.lower_freq = freq(next(text), orig);
151 tag.upper_freq = freq(next(text), orig);
153 tag.upper_freq <= tag.lower_freq,
154 "Invalid frequency range [", tag.lower_freq,
", ",
155 tag.upper_freq,
"]\nOriginal tag: ", std::quoted(orig))
163 using namespace detail;
167 while (text.size()) {
168 tags.emplace_back(
parse_tag(next_tag(text)));
174Numeric Tag::Q(Numeric T)
const {
178Numeric Tag::dQdT(Numeric T)
const {
182Tag::Tag(std::string_view text) : Tag(
parse_tag(text)) {}
198 std::ostringstream os;
201 os << toShortName(Isotopologue().spec) <<
"-";
204 if (type == TagType::Cia) {
205 os <<
"CIA-" << toShortName(cia_2nd_species);
207 }
else if (type == TagType::FreeElectrons || type == TagType::Particles) {
208 os << toShortName(Isotopologue().spec);
211 else if (type == TagType::XsecFit) {
215 if (type == TagType::Zeeman) os <<
"Z-";
218 os << Isotopologue().isotname <<
'-';
225 constexpr int precision = std::same_as<Numeric, double> ? DBL_DIG : FLT_DIG;
227 if (0 > lower_freq) {
231 os << std::setprecision(precision);
232 os << lower_freq <<
"-";
235 if (0 > upper_freq) {
239 os << std::setprecision(precision);
251 std::any_of(begin(), end(),
252 [front_species = front().Spec()](
const SpeciesTag &tag) {
253 return tag.Spec() not_eq front_species;
255 "All species in a group of tags must be the same\n"
256 "Your list of tags have been parsed as: ",
257 *
this,
"\nThe original tags-list read ", std::quoted(text))
263 [front_is_zeeman = front().type == Species::TagType::Zeeman](
265 return front_is_zeeman ? tag.type != Species::TagType::Zeeman
266 : tag.type == Species::TagType::Zeeman;
268 "All species in a group of tags must be Zeeman-tagged if any one is\n"
269 "Your list of tags have been parsed as: ",
270 *
this,
"\nThe original tags-list read ", std::quoted(text)) {}
274 Species::Species spec,
276 const Index n = specs.nelem();
278 if (specs[i].
Species() == spec)
return i;
283 Species::Species spec)
noexcept {
289 for (Index i = 0; i < specs.nelem(); i++) {
290 if (
auto ptr = std::find(specs[i].cbegin(), specs[i].cend(), tag);
291 ptr not_eq specs[i].cend())
292 return {i, std::distance(specs[i].cbegin(), ptr)};
300 for (Index i = 0; i < specs.nelem(); i++) {
302 std::find_if(specs[i].cbegin(),
304 [&](
auto& tag) {
return tag.Isotopologue() == isot; });
305 ptr not_eq specs[i].cend())
306 return {i, std::distance(specs[i].cbegin(), ptr)};
312 Index num_free_electrons = 0;
313 for (Index i = 0; i < abs_species.
nelem(); ++i) {
314 bool has_free_electrons =
false;
315 bool has_particles =
false;
316 bool has_hitran_xsec =
false;
317 for (Index s = 0; s < abs_species[i].
nelem(); ++s) {
318 if (abs_species[i][s].Type() == Species::TagType::FreeElectrons) {
319 num_free_electrons++;
320 has_free_electrons =
true;
323 if (abs_species[i][s].Type() == Species::TagType::Particles) {
324 has_particles =
true;
327 if (abs_species[i][s].Type() == Species::TagType::XsecFit) {
328 has_hitran_xsec =
true;
333 "'free_electrons' must not be combined "
334 "with other tags in the same group.");
336 "'free_electrons' must not be defined "
340 "'particles' must not be combined "
341 "with other tags in the same group.");
344 "'hitran_xsec' must not be combined "
345 "with other tags in the same group.");
349String ArrayOfSpeciesTag::Name()
const {
352 for (
auto& x : *this) {
353 if (not first) out +=
", ";
362 std::set<Species::Species> unique_species;
363 for (
auto& specs : abs_species) {
364 if (specs.RequireLines()) unique_species.insert(specs.front().Spec());
366 return unique_species;
370 const Vector& rtp_vmr,
372 ARTS_ASSERT(abs_species.nelem() == rtp_vmr.nelem())
375 std::find_if(abs_species.begin(),
378 return tag_group.nelem() and tag_group.Species() == spec;
380 return pos == abs_species.end()
382 : rtp_vmr[std::distance(abs_species.begin(), pos)];
386 for (
auto& species_list : abs_species) {
387 for (
auto& tag : species_list) {
389 case Species::TagType::Plain:
392 case Species::TagType::Zeeman:
395 case Species::TagType::Predefined:
398 case Species::TagType::Cia:
401 case Species::TagType::FreeElectrons:
404 case Species::TagType::Particles:
407 case Species::TagType::XsecFit:
410 case Species::TagType::FINAL: {
418 Species::TagType x{Species::TagType::FINAL};
420 case Species::TagType::FINAL:
421 os <<
"Species tag types:\n";
423 case Species::TagType::Plain:
424 os <<
" Plain: " << val.
Plain <<
'\n';
426 case Species::TagType::Zeeman:
427 os <<
" Zeeman: " << val.
Zeeman <<
'\n';
429 case Species::TagType::Predefined:
430 os <<
" Predefined: " << val.
Predefined <<
'\n';
432 case Species::TagType::Cia:
433 os <<
" Cia: " << val.
Cia <<
'\n';
435 case Species::TagType::FreeElectrons:
438 case Species::TagType::Particles:
439 os <<
" Particles: " << val.
Particles <<
'\n';
441 case Species::TagType::XsecFit:
442 os <<
" XsecFit: " << val.
XsecFit <<
'\n';
ArrayOfSpeciesTag() noexcept
This can be used to make arrays out of anything.
Index nelem() const ARTS_NOEXCEPT
Helper macros for debugging.
#define ARTS_ASSERT(condition,...)
#define ARTS_USER_ERROR_IF(condition,...)
constexpr bool good_enum(EnumType x) noexcept
Checks if the enum number is good.
Numeric dQdT(Numeric T, const Species::IsotopeRecord &ir)
Numeric Q(Numeric T, const Species::IsotopeRecord &ir)
constexpr Index isot(Species species, std::string_view isot, std::string_view orig)
constexpr void check(std::string_view text, std::string_view orig)
constexpr std::string_view next_tag(std::string_view &text)
constexpr void trim(std::string_view &text)
constexpr std::string_view next(std::string_view &text)
constexpr Numeric freq(std::string_view part, std::string_view orig)
constexpr Species spec(std::string_view part, std::string_view orig)
String isotopologues_names(Species spec)
Array< Tag > parse_tags(std::string_view text)
Parse a list of species tags into an Array<Tag>
constexpr bool is_predefined_model(const IsotopeRecord &ir) noexcept
constexpr std::array Isotopologues
A list of all ARTS isotopologues, note how the species enum class input HAS to be sorted.
Numeric first_vmr(const ArrayOfArrayOfSpeciesTag &abs_species, const Vector &rtp_vmr, const Species spec) ARTS_NOEXCEPT
constexpr Index find_species_index(const Species spec, const std::string_view isot) noexcept
constexpr std::string_view Joker
SpeciesTag parse_tag(std::string_view text)
Implements Zeeman modeling.
constexpr int isspace(int ch) noexcept
Returns 1 if x is a standard space-character.
Struct to test of an ArrayOfArrayOfSpeciesTag contains a tagtype.
SpeciesTagTypeStatus(const ArrayOfArrayOfSpeciesTag &abs_species)
Struct containing all information needed about one isotope.