40 return {
"G0",
"D0",
"G2",
"D2",
"FVC",
"ETA",
"Y",
"G",
"DV"};
49 if (
var == v) var_OK =
true;
53 bool coeff_OK =
false;
54 for (
auto& c : coeffs)
55 if (coeff == c) coeff_OK =
true;
58 if (not var_OK or not coeff_OK) {
59 std::ostringstream os;
60 os <<
"At least one of your variable and/or your coefficient is not OK\n";
61 os <<
"Your variable: \"" <<
var <<
"\". OK variables include: " << vars
63 os <<
"Your coefficient: \"" << coeff
64 <<
"\". OK coefficients include: " << coeffs <<
"\n";
65 throw std::runtime_error(os.str());
69 #define ReturnJacPropMatType(ID) \
72 return JacPropMatType::LineShape##ID##X0; \
73 else if (coeff == "X1") \
74 return JacPropMatType::LineShape##ID##X1; \
75 else if (coeff == "X2") \
76 return JacPropMatType::LineShape##ID##X2; \
77 else if (coeff == "X3") \
78 return JacPropMatType::LineShape##ID##X3; \
90 #undef ReturnJacPropMatType
106 m.
mdata = std::vector<SingleSpeciesModel>(7);
118 for (
auto& v : m.
mdata) {
119 v.G0().type = TemperatureModel::T1;
120 v.D0().type = TemperatureModel::T5;
124 for (
auto& v : m.
mdata) is >> v.G0().X0;
127 for (
auto& v : m.
mdata) {
129 v.D0().X1 = v.G0().X1;
133 m.
mdata.front().D0().X0 = 0;
134 for (
int k = 1; k < 7; k++)
135 is >> m.
mdata[k].D0().X0;
138 for (
int k = 1; k < 7; k++) {
139 if (qid.
Species() == species[k].Species()) {
140 if(m.
mdata.front().G0().X0 not_eq m.
mdata[k].G0().X0 or
141 m.
mdata.front().G0().X1 not_eq m.
mdata[k].G0().X1 or
142 m.
mdata.front().D0().X1 not_eq m.
mdata[k].D0().X1) {
143 std::ostringstream os;
144 os <<
"Species is " << qid.
SpeciesName() <<
" and this is a broadening species in ARTSCAT-4.\n"
145 <<
"Despite this, values representing self and " << qid.
SpeciesName() <<
" does not match "
146 <<
"in input string\n";
147 throw std::runtime_error(os.str());
173 const auto shapeparams =
180 const auto mixingparams =
185 species.resize(specs);
186 m.
mdata.resize(specs);
188 if (not specs and mtype not_eq Type::DP)
189 throw std::runtime_error(
190 "Need at least one species for non-Doppler line shapes");
193 for (
Index i = 0; i < specs; i++) {
196 if (s == self_broadening) {
200 throw std::runtime_error(
"Self broadening must be first, it is not\n");
203 else if (s == bath_broadening) {
208 throw std::runtime_error(
209 "Air/bath broadening must be last, it is not\n");
214 }
catch (
const std::runtime_error& e) {
216 os <<
"Encountered " << s
217 <<
" in a position where a species should have been ";
218 os <<
"defined.\nPlease check your pressure broadening data structure and ensure ";
219 os <<
"that it follows the correct conventions.\n";
220 os <<
"SpeciesTag error reads: " << e.what();
221 throw std::runtime_error(os.str());
226 for (
auto& params : {shapeparams, mixingparams}) {
227 for (
auto& param : params) {
252 throw std::runtime_error(
253 "Unknown number of input parameters in Legacy mode.");
257 throw std::runtime_error(
258 "Too many input parameters in interpolation results Legacy mode.");
288 const auto self_in_list =
292 for (
auto& num :
x)
data >> num;
315 for (
auto& num :
x)
data >> num;
332 case TypePB::PB_NONE:
333 mtype = LineShape::Type::DP;
338 case TypePB::PB_AIR_BROADENING:
339 mtype = LineShape::Type::VP;
344 case TypePB::PB_AIR_AND_WATER_BROADENING:
346 mtype = LineShape::Type::VP;
350 m.
Data()[0].G0() = {TemperatureModel::T1,
x[0],
x[1], 0, 0};
351 m.
Data()[0].D0() = {TemperatureModel::T5,
x[2],
x[1], 0, 0};
352 m.
Data()[1].G0() = {TemperatureModel::T1,
x[3],
x[4], 0, 0};
353 m.
Data()[1].D0() = {TemperatureModel::T5,
x[5],
x[4], 0, 0};
358 mtype = LineShape::Type::VP;
361 m.
Data()[0].G0() = {TemperatureModel::T1,
x[0],
x[1], 0, 0};
362 m.
Data()[0].D0() = {TemperatureModel::T5,
x[2],
x[1], 0, 0};
363 m.
Data()[2].G0() = {TemperatureModel::T1,
x[3],
x[4], 0, 0};
364 m.
Data()[2].D0() = {TemperatureModel::T5,
x[5],
x[4], 0, 0};
365 m.
Data()[1].G0() = {TemperatureModel::T1,
x[6],
x[7], 0, 0};
366 m.
Data()[1].D0() = {TemperatureModel::T5,
x[8],
x[7], 0, 0};
371 case TypePB::PB_PLANETARY_BROADENING:
373 mtype = LineShape::Type::VP;
376 m.
Data()[0].G0() = {TemperatureModel::T1,
x[1],
x[8], 0, 0};
377 m.
Data()[0].D0() = {TemperatureModel::T5,
x[14],
x[8], 0, 0};
378 m.
Data()[1].G0() = {TemperatureModel::T1,
x[2],
x[9], 0, 0};
379 m.
Data()[1].D0() = {TemperatureModel::T5,
x[15],
x[9], 0, 0};
380 m.
Data()[2].G0() = {TemperatureModel::T1,
x[3],
x[10], 0, 0};
381 m.
Data()[2].D0() = {TemperatureModel::T5,
x[16],
x[10], 0, 0};
382 m.
Data()[3].G0() = {TemperatureModel::T1,
x[4],
x[11], 0, 0};
383 m.
Data()[3].D0() = {TemperatureModel::T5,
x[17],
x[11], 0, 0};
384 m.
Data()[4].G0() = {TemperatureModel::T1,
x[5],
x[12], 0, 0};
385 m.
Data()[4].D0() = {TemperatureModel::T5,
x[18],
x[12], 0, 0};
386 m.
Data()[5].G0() = {TemperatureModel::T1,
x[6],
x[13], 0, 0};
387 m.
Data()[5].D0() = {TemperatureModel::T5,
x[19],
x[13], 0, 0};
396 mtype = LineShape::Type::VP;
400 m.
Data()[0].G0() = {TemperatureModel::T1,
x[0],
x[7], 0, 0};
402 m.
Data()[1].G0() = {TemperatureModel::T1,
x[1],
x[8], 0, 0};
403 m.
Data()[1].D0() = {TemperatureModel::T5,
x[14],
x[8], 0, 0};
404 m.
Data()[2].G0() = {TemperatureModel::T1,
x[2],
x[9], 0, 0};
405 m.
Data()[2].D0() = {TemperatureModel::T5,
x[15],
x[9], 0, 0};
406 m.
Data()[3].G0() = {TemperatureModel::T1,
x[3],
x[10], 0, 0};
407 m.
Data()[3].D0() = {TemperatureModel::T5,
x[16],
x[10], 0, 0};
408 m.
Data()[4].G0() = {TemperatureModel::T1,
x[4],
x[11], 0, 0};
409 m.
Data()[4].D0() = {TemperatureModel::T5,
x[17],
x[11], 0, 0};
410 m.
Data()[5].G0() = {TemperatureModel::T1,
x[5],
x[12], 0, 0};
411 m.
Data()[5].D0() = {TemperatureModel::T5,
x[18],
x[12], 0, 0};
412 m.
Data()[6].G0() = {TemperatureModel::T1,
x[6],
x[13], 0, 0};
413 m.
Data()[6].D0() = {TemperatureModel::T5,
x[19],
x[13], 0, 0};
431 case TypeLM::LM_NONE:
433 case TypeLM::LM_LBLRTM:
434 y.Data().front().Y().
type = LineShape::TemperatureModel::LM_AER;
435 y.Data().front().G().
type = LineShape::TemperatureModel::LM_AER;
436 y.Data().front().Y().X0 =
x[4];
437 y.Data().front().Y().X1 =
x[5];
438 y.Data().front().Y().X2 =
x[6];
439 y.Data().front().Y().X3 =
x[7];
440 y.Data().front().G().X0 =
x[8];
441 y.Data().front().G().X1 =
x[9];
442 y.Data().front().G().X2 =
x[10];
443 y.Data().front().G().X3 =
x[11];
445 case TypeLM::LM_LBLRTM_O2NonResonant:
447 y.Data().front().G().X0 =
x[0];
449 case TypeLM::LM_2NDORDER:
451 y.Data().front().Y().X0 =
x[0];
452 y.Data().front().Y().X1 =
x[1];
453 y.Data().front().Y().X2 =
x[7];
455 y.Data().front().G().X0 =
x[2];
456 y.Data().front().G().X1 =
x[3];
457 y.Data().front().G().X2 =
x[8];
459 y.Data().front().DV().X0 =
x[4];
460 y.Data().front().DV().X1 =
x[5];
461 y.Data().front().DV().X2 =
x[9];
463 case TypeLM::LM_1STORDER:
465 y.Data().front().Y().X0 =
x[1];
466 y.Data().front().Y().X1 =
x[2];
468 case TypeLM::LM_BYBAND:
481 if (atmospheric_species.
nelem() != atmospheric_vmrs.
nelem())
482 throw std::runtime_error(
"Bad atmospheric inputs");
486 const Index back = lineshape_species.
nelem() - 1;
488 if (type == Type::DP)
return line_vmrs;
491 for (
Index i = 0; i < lineshape_species.
nelem()-bath_in_list; i++) {
494 (self_in_list and &lineshape_species[i] == &lineshape_species.front()) ?
self.
Species() : lineshape_species[i].Species();
497 Index this_species_index = -1;
498 for (
Index j = 0; j < atmospheric_species.
nelem(); j++)
499 if (atmospheric_species[j][0].
Species() == target)
500 this_species_index = j;
503 if (this_species_index not_eq -1)
504 line_vmrs[i] = atmospheric_vmrs[this_species_index];
509 line_vmrs[back] = 1.0 - line_vmrs.
sum();
510 else if(line_vmrs.
sum() == 0)
513 line_vmrs /= line_vmrs.
sum();
516 if (not std::isnormal(line_vmrs.
sum()))
517 throw std::runtime_error(
518 "Bad VMRs, your atmosphere does not support the line of interest");
543 std::vector<Variable> vars(0);
547 for (
auto&
var: vars) {
548 if (std::any_of(m.
Data().cbegin(), m.
Data().cend(),
549 [
var](
auto&
x){return x.Get(var).type not_eq TemperatureModel::None;})) {
551 for (
auto& ssm: m.
Data())
570 std::istringstream str(s);
576 std::vector<SingleSpeciesModel> ssms(0);
577 while (not str.eof()) {
579 if(std::any_of(names.cbegin(), names.cend(),
580 [part](
auto x){return part == x;})) {
591 else if (i <
Index(ssms.size()))
596 auto mp = ssms[i].Get(
var);
598 ssms[i].Set(
var, mp);
602 return Model(std::move(ssms));
607 std::ostringstream os;
609 case TemperatureModel::None:
612 case TemperatureModel::T0:
615 case TemperatureModel::T1:
616 os << mp.
X0 <<
" * (" << T0 <<
"/T)^" << mp.
X1;
618 case TemperatureModel::T2:
619 os << mp.
X0 <<
" * (" << T0 <<
"/T)^" << mp.
X1 <<
" / (1 + " << mp.
X2 <<
" * log(T/" << T0 <<
"))";
621 case TemperatureModel::T3:
622 os << mp.
X0 <<
" + " << mp.
X1 <<
" * (" << T0 <<
" - T)";
624 case TemperatureModel::T4:
625 os <<
"(" << mp.
X0 <<
" + " << mp.
X1 <<
" * (" << T0 <<
"/T - 1)) * (" << T0 <<
"/T)^" << mp.
X2;
627 case TemperatureModel::T5:
628 os << mp.
X0 <<
" * (" << T0 <<
"/T)^(0.25 + 1.5 * " << mp.
X1 <<
")";
630 case TemperatureModel::LM_AER:
631 os <<
'(' <<
"Linear interpolation to y(x) from x-ref = [200, 250, 296, 340] and y-ref = [" << mp.
X0 <<
", " << mp.
X1 <<
", " << mp.
X2 <<
", " << mp.
X3 <<
']' <<
')';
633 case TemperatureModel::DPL:
634 os <<
'(' << mp.
X0 <<
" * (" << T0 <<
"/T)^" << mp.
X1 <<
" + " << mp.
X2 <<
" * (" << T0 <<
"/T)^" << mp.
X3 <<
')';
648 std::vector<Variable> vars(0);
654 for (
Index i=0; i<names.nelem(); i++) {
657 if (std::any_of(m.
Data().cbegin(), m.
Data().cend(),
658 [
var](
auto&
x){return x.Get(var).type not_eq TemperatureModel::None;})) {
660 std::ostringstream os;
661 os << names[i] <<
" ~ ";
663 if (&sts[j] == &sts.front() and
self)
664 os <<
"VMR(" << self_broadening <<
") * "
666 else if (&sts[j] == &sts.back() and bath)
667 os <<
"VMR(" << bath_broadening <<
") * "
670 os <<
"VMR(" << sts[j].SpeciesNameMain() <<
") * "
673 if (&sts[j] not_eq &sts.back())
676 as.push_back(os.str());