17#include "matpack_data.h"
18#include "matpack_math.h"
24 const auto var_type = LineShape::toVariableOrThrow(var);
27 const auto coeff_type = Options::toLineShapeCoeffOrThrow(coeff);
30#define ReturnJacPropMatType(ID) \
31 case LineShape::Variable::ID: \
32 switch (coeff_type) { \
33 case Options::LineShapeCoeff::X0: \
34 return Jacobian::Line::Shape##ID##X0; \
35 case Options::LineShapeCoeff::X1: \
36 return Jacobian::Line::Shape##ID##X1; \
37 case Options::LineShapeCoeff::X2: \
38 return Jacobian::Line::Shape##ID##X2; \
39 case Options::LineShapeCoeff::X3: \
40 return Jacobian::Line::Shape##ID##X3; \
41 case Options::LineShapeCoeff::FINAL: \
42 return Jacobian::Line::FINAL; \
55 case LineShape::Variable::FINAL: {
59#undef ReturnJacPropMatType
61 return Jacobian::Line::FINAL;
75 m.
mdata = std::vector<SingleSpeciesModel>(7);
79 species[1] = Species::fromShortName(
"N2");
80 species[2] = Species::fromShortName(
"O2");
81 species[3] = Species::fromShortName(
"H2O");
82 species[4] = Species::fromShortName(
"CO2");
83 species[5] = Species::fromShortName(
"H2");
84 species[6] = Species::fromShortName(
"He");
88 v.G0().type = TemperatureModel::T1;
89 v.D0().type = TemperatureModel::T5;
98 v.D0().X1 =
v.G0().X1;
102 m.
mdata.front().D0().X0 = 0;
103 for (
int k = 1; k < 7; k++)
107 for (
int k = 1; k < 7; k++) {
108 if (qid.
Species() == species[k]) {
110 m.
mdata.front().G0().X1 not_eq m.
mdata[k].G0().X1 or
111 m.
mdata.front().D0().X1 not_eq m.
mdata[k].D0().X1,
112 "Species is ", qid.
Isotopologue(),
" and this is a broadening species in ARTSCAT-4.\n"
113 "Despite this, values representing self and ", qid.
Isotopologue(),
" does not match "
139 const auto shapeparams =
140 LegacyLineFunctionData::lineshapetag2variablesvector(
toString(mtype));
146 const auto mixingparams =
147 LegacyLineFunctionData::linemixingtag2variablesvector(s);
151 species.resize(specs);
152 m.
mdata.resize(specs);
155 "Need at least one species for non-Doppler line shapes");
158 for (Index i = 0; i < specs; i++) {
165 "Self broadening must be first, it is not\n");
169 species[i] = Species::Species::Bath;
171 "Air/bath broadening must be last, it is not\n");
174 species[i] = Species::fromShortName(s);
176 "Encountered ", s,
" in a position where a species should have been "
177 "defined.\nPlease check your pressure broadening data structure and ensure "
178 "that it follows the correct conventions.\n")
182 for (
auto& params : {shapeparams, mixingparams}) {
183 for (
auto& param : params) {
186 const auto type = toTemperatureModel(s);
188 LegacyLineFunctionData::temperaturemodel2legacynelem(type);
190 m.
mdata[i].Data()[Index(param)].type = type;
191 if (ntemp <= ModelParameters::N) {
198 m.
mdata[i].Data()[Index(param)].X1;
202 m.
mdata[i].Data()[Index(param)].X1 >>
203 m.
mdata[i].Data()[Index(param)].X2;
209 "Unknown number of input parameters in Legacy mode.");
213 "Too many input parameters in interpolation results Legacy mode.");
231 LineShape::Type& mtype,
240 const auto type = LegacyPressureBroadeningData::string2typepb(s);
241 const auto n = LegacyPressureBroadeningData::typepb2nelem(type);
242 const auto self_in_list = LegacyPressureBroadeningData::self_listed(qid, type);
247 LegacyPressureBroadeningData::vector2modelpb(mtype,
265 const auto type = LegacyLineMixingData::string2typelm(s);
266 const auto n = LegacyLineMixingData::typelm2nelem(type);
271 lsc = LegacyLineMixingData::vector2modellm(x, type);
276#pragma GCC diagnostic push
277#pragma GCC diagnostic ignored "-Wreturn-type"
279 LineShape::Type& mtype,
287 Species::Species self_spec) {
289 case TypePB::PB_NONE:
290 mtype = LineShape::Type::DP;
295 case TypePB::PB_AIR_BROADENING:
296 mtype = LineShape::Type::VP;
298 m =
Model(x[0], x[1], x[2], x[3], x[4]);
300 species[0] = self_spec;
301 species[1] = Species::Species::Bath;
303 case TypePB::PB_AIR_AND_WATER_BROADENING:
305 mtype = LineShape::Type::VP;
309 m.
Data()[0].G0() = {TemperatureModel::T1, x[0], x[1], 0, 0};
310 m.
Data()[0].D0() = {TemperatureModel::T5, x[2], x[1], 0, 0};
311 m.
Data()[1].G0() = {TemperatureModel::T1, x[3], x[4], 0, 0};
312 m.
Data()[1].D0() = {TemperatureModel::T5, x[5], x[4], 0, 0};
314 species[0] = Species::fromShortName(
"H2O");
315 species[1] = Species::Species::Bath;
318 mtype = LineShape::Type::VP;
321 m.
Data()[0].G0() = {TemperatureModel::T1, x[0], x[1], 0, 0};
322 m.
Data()[0].D0() = {TemperatureModel::T5, x[2], x[1], 0, 0};
323 m.
Data()[2].G0() = {TemperatureModel::T1, x[3], x[4], 0, 0};
324 m.
Data()[2].D0() = {TemperatureModel::T5, x[5], x[4], 0, 0};
325 m.
Data()[1].G0() = {TemperatureModel::T1, x[6], x[7], 0, 0};
326 m.
Data()[1].D0() = {TemperatureModel::T5, x[8], x[7], 0, 0};
328 species[0] = self_spec;
329 species[1] = Species::fromShortName(
"H2O");
330 species[2] = Species::Species::Bath;
333 case TypePB::PB_PLANETARY_BROADENING:
335 mtype = LineShape::Type::VP;
338 m.
Data()[0].G0() = {TemperatureModel::T1, x[1], x[8], 0, 0};
339 m.
Data()[0].D0() = {TemperatureModel::T5, x[14], x[8], 0, 0};
340 m.
Data()[1].G0() = {TemperatureModel::T1, x[2], x[9], 0, 0};
341 m.
Data()[1].D0() = {TemperatureModel::T5, x[15], x[9], 0, 0};
342 m.
Data()[2].G0() = {TemperatureModel::T1, x[3], x[10], 0, 0};
343 m.
Data()[2].D0() = {TemperatureModel::T5, x[16], x[10], 0, 0};
344 m.
Data()[3].G0() = {TemperatureModel::T1, x[4], x[11], 0, 0};
345 m.
Data()[3].D0() = {TemperatureModel::T5, x[17], x[11], 0, 0};
346 m.
Data()[4].G0() = {TemperatureModel::T1, x[5], x[12], 0, 0};
347 m.
Data()[4].D0() = {TemperatureModel::T5, x[18], x[12], 0, 0};
348 m.
Data()[5].G0() = {TemperatureModel::T1, x[6], x[13], 0, 0};
349 m.
Data()[5].D0() = {TemperatureModel::T5, x[19], x[13], 0, 0};
350 species = {Species::fromShortName(
"N2"),
351 Species::fromShortName(
"O2"),
352 Species::fromShortName(
"H2O"),
353 Species::fromShortName(
"CO2"),
354 Species::fromShortName(
"H2"),
355 Species::fromShortName(
"He")};
358 mtype = LineShape::Type::VP;
362 m.
Data()[0].G0() = {TemperatureModel::T1, x[0], x[7], 0, 0};
364 m.
Data()[1].G0() = {TemperatureModel::T1, x[1], x[8], 0, 0};
365 m.
Data()[1].D0() = {TemperatureModel::T5, x[14], x[8], 0, 0};
366 m.
Data()[2].G0() = {TemperatureModel::T1, x[2], x[9], 0, 0};
367 m.
Data()[2].D0() = {TemperatureModel::T5, x[15], x[9], 0, 0};
368 m.
Data()[3].G0() = {TemperatureModel::T1, x[3], x[10], 0, 0};
369 m.
Data()[3].D0() = {TemperatureModel::T5, x[16], x[10], 0, 0};
370 m.
Data()[4].G0() = {TemperatureModel::T1, x[4], x[11], 0, 0};
371 m.
Data()[4].D0() = {TemperatureModel::T5, x[17], x[11], 0, 0};
372 m.
Data()[5].G0() = {TemperatureModel::T1, x[5], x[12], 0, 0};
373 m.
Data()[5].D0() = {TemperatureModel::T5, x[18], x[12], 0, 0};
374 m.
Data()[6].G0() = {TemperatureModel::T1, x[6], x[13], 0, 0};
375 m.
Data()[6].D0() = {TemperatureModel::T5, x[19], x[13], 0, 0};
377 species[0] = self_spec;
378 species[1] = Species::fromShortName(
"N2");
379 species[2] = Species::fromShortName(
"O2");
380 species[3] = Species::fromShortName(
"H2O");
381 species[4] = Species::fromShortName(
"CO2");
382 species[5] = Species::fromShortName(
"H2");
383 species[6] = Species::fromShortName(
"He");
388#pragma GCC diagnostic pop
394 case TypeLM::LM_NONE:
396 case TypeLM::LM_LBLRTM:
397 y.
Data().front().Y().type = LineShape::TemperatureModel::LM_AER;
398 y.
Data().front().G().type = LineShape::TemperatureModel::LM_AER;
399 y.
Data().front().Y().X0 = x[4];
400 y.
Data().front().Y().X1 = x[5];
401 y.
Data().front().Y().X2 = x[6];
402 y.
Data().front().Y().X3 = x[7];
403 y.
Data().front().G().X0 = x[8];
404 y.
Data().front().G().X1 = x[9];
405 y.
Data().front().G().X2 = x[10];
406 y.
Data().front().G().X3 = x[11];
408 case TypeLM::LM_LBLRTM_O2NonResonant:
409 y.
Data().front().G().type = LineShape::TemperatureModel::T0;
410 y.
Data().front().G().X0 = x[0];
412 case TypeLM::LM_2NDORDER:
413 y.
Data().front().Y().type = LineShape::TemperatureModel::T4;
414 y.
Data().front().Y().X0 = x[0];
415 y.
Data().front().Y().X1 = x[1];
416 y.
Data().front().Y().X2 = x[7];
417 y.
Data().front().G().type = LineShape::TemperatureModel::T4;
418 y.
Data().front().G().X0 = x[2];
419 y.
Data().front().G().X1 = x[3];
420 y.
Data().front().G().X2 = x[8];
421 y.
Data().front().DV().type = LineShape::TemperatureModel::T4;
422 y.
Data().front().DV().X0 = x[4];
423 y.
Data().front().DV().X1 = x[5];
424 y.
Data().front().DV().X2 = x[9];
426 case TypeLM::LM_1STORDER:
427 y.
Data().front().Y().type = LineShape::TemperatureModel::T1;
428 y.
Data().front().Y().X0 = x[1];
429 y.
Data().front().Y().X1 = x[2];
431 case TypeLM::LM_BYBAND:
441 ARTS_ASSERT (atmospheric_species.nelem() == atmospheric_vmrs.nelem(),
"Bad atmospheric inputs");
443 const Index n = lineshape_species.nelem();
446 Vector line_vmrs(n, 0);
449 const bool bath = n and lineshape_species.back() == Species::Species::Bath;
452 for (Index i = 0; i < n - bath; i++) {
453 const Species::Species target = lineshape_species[i];
456 Index this_species_index = -1;
457 for (Index j = 0; j < atmospheric_species.nelem(); j++) {
458 if (atmospheric_species[j].
Species() == target) {
459 this_species_index = j;
464 if (this_species_index not_eq -1) {
465 line_vmrs[i] = atmospheric_vmrs[this_species_index];
470 if (
auto sl = sum(line_vmrs); bath) {
471 line_vmrs[n - 1] = 1.0 - sl;
484 ARTS_ASSERT (atmospheric_species.nelem() == atmospheric_vmrs.nelem(),
485 "Bad atmospheric inputs");
487 const Index n = lineshape_species.nelem();
490 Vector line_vmrs(n, 0);
491 Vector line_mass(n, 0);
494 const bool bath = n and lineshape_species.back() == Species::Species::Bath;
497 for (Index i = 0; i < n - bath; i++) {
499 const Species::Species target = lineshape_species[i];
502 Index this_species_index = -1;
503 for (Index j = 0; j < atmospheric_species.nelem(); j++) {
504 if (atmospheric_species[j].
Species() == target) {
505 this_species_index = j;
510 if (this_species_index not_eq -1) {
511 line_vmrs[i] = atmospheric_vmrs[this_species_index];
517 if(
auto sl = sum(line_vmrs); sl == 0) {
519 line_mass[n - 1] = (line_vmrs * line_mass) / sl;
527 for (
auto& data : m.
Data()) os << data;
532 for (
auto& data : m.
Data()) is >> data;
538 const auto& vars = enumtyps::VariableTypes;
540 for (
auto& var : vars) {
541 if (std::any_of(m.
Data().cbegin(), m.
Data().cend(), [var](
auto& x) {
542 return x.Get(var).type not_eq TemperatureModel::None;
545 for (
auto& ssm : m.
Data())
550 if (out.size()) out.pop_back();
556 if (s.
nelem() == 0)
return {};
558 const auto& names = enumstrs::VariableNames;
560 std::istringstream str(s);
562 Variable var = Variable::ETA;
563 TemperatureModel tm = TemperatureModel::None;
566 std::vector<SingleSpeciesModel> ssms(0);
567 while (not str.eof()) {
569 if (std::any_of(names.cbegin(), names.cend(), [part](
auto x) {
573 var = toVariable(part);
576 tm = toTemperatureModel(part);
580 if (i < Index(ssms.size()))
585 auto mp = ssms[i].Get(var);
587 ssms[i].Set(var, mp);
595 std::ostringstream os;
597 case TemperatureModel::None:
600 case TemperatureModel::T0:
603 case TemperatureModel::T1:
604 os << mp.
X0 <<
" * (" << T0 <<
"/T)^" << mp.
X1;
606 case TemperatureModel::T2:
607 os << mp.
X0 <<
" * (" << T0 <<
"/T)^" << mp.
X1 <<
" / (1 + " << mp.
X2
608 <<
" * log(T/" << T0 <<
"))";
610 case TemperatureModel::T3:
611 os << mp.
X0 <<
" + " << mp.
X1 <<
" * (" << T0 <<
" - T)";
613 case TemperatureModel::T4:
614 os <<
"(" << mp.
X0 <<
" + " << mp.
X1 <<
" * (" << T0 <<
"/T - 1)) * ("
615 << T0 <<
"/T)^" << mp.
X2;
617 case TemperatureModel::T5:
618 os << mp.
X0 <<
" * (" << T0 <<
"/T)^(0.25 + 1.5 * " << mp.
X1 <<
")";
620 case TemperatureModel::LM_AER:
622 <<
"Linear interpolation to y(x) from x-ref = [200, 250, 296, 340] and y-ref = ["
623 << mp.
X0 <<
", " << mp.
X1 <<
", " << mp.
X2 <<
", " << mp.
X3 <<
']'
626 case TemperatureModel::DPL:
627 os <<
'(' << mp.
X0 <<
" * (" << T0 <<
"/T)^" << mp.
X1 <<
" + " << mp.
X2
628 <<
" * (" << T0 <<
"/T)^" << mp.
X3 <<
')';
630 case TemperatureModel::POLY:
631 os <<
'(' << mp.
X0 <<
" + " << mp.
X1 <<
" * T + " << mp.
X2
632 <<
" * T * T + " << mp.
X3 <<
" * T * T * T)";
633 case TemperatureModel::FINAL:
644 const auto& vars = enumtyps::VariableTypes;
647 for (Index i = 0; i < Index(Variable::FINAL); i++) {
648 Variable var = vars[i];
650 if (std::any_of(m.
Data().cbegin(), m.
Data().cend(), [var](
auto& x) {
651 return x.Get(var).type not_eq TemperatureModel::None;
653 std::ostringstream os;
655 for (Index j = 0; j < sts.
nelem(); j++) {
660 os <<
"VMR(" << toShortName(sts[j]) <<
") * "
663 if (sts[j] not_eq sts.back()) os <<
" + ";
665 as.push_back(os.str());
672#pragma GCC diagnostic push
673#pragma GCC diagnostic ignored "-Wreturn-type"
684 "Type: ", type,
", is not accepted. "
685 "See documentation for accepted types\n")
687#pragma GCC diagnostic pop
690 os << mp.
type <<
' ' << mp.
X0 <<
' ' << mp.
X1 <<
' '
691 << mp.
X2 <<
' ' << mp.
X3 <<
' ';
705 case TemperatureModel::None:
707 case TemperatureModel::T0:
709 case TemperatureModel::T1:
710 return X0 * pow(T0 / T, X1);
711 case TemperatureModel::T2:
712 return X0 * pow(T0 / T, X1) * (1 + X2 * log(T / T0));
713 case TemperatureModel::T3:
714 return X0 + X1 * (T - T0);
715 case TemperatureModel::T4:
716 return (X0 + X1 * (T0 / T - 1.)) * pow(T0 / T, X2);
717 case TemperatureModel::T5:
718 return X0 * pow(T0 / T, 0.25 + 1.5 * X1);
719 case TemperatureModel::LM_AER:
720 return special_linemixing_aer(T);
721 case TemperatureModel::DPL:
722 return X0 * pow(T0 / T, X1) + X2 * pow(T0 / T, X3);
723 case TemperatureModel::POLY:
724 return X0 + X1 * T + X2 * T * T + X3 * T * T * T;
725 case TemperatureModel::FINAL: { }
727 return std::numeric_limits<Numeric>::quiet_NaN();
735 case TemperatureModel::None:
737 case TemperatureModel::T0:
739 case TemperatureModel::T1:
740 return pow(T0 / T, X1);
741 case TemperatureModel::T2:
742 return pow(T0 / T, X1) * (1 + X2 * log(T / T0));
743 case TemperatureModel::T3:
745 case TemperatureModel::T4:
746 return pow(T0 / T, X2);
747 case TemperatureModel::T5:
748 return pow(T0 / T, 1.5 * X1 + 0.25);
749 case TemperatureModel::LM_AER:
750 return special_linemixing_aer_dX0(T);
751 case TemperatureModel::DPL:
752 return pow(T0 / T, X1);
753 case TemperatureModel::POLY:
755 case TemperatureModel::FINAL: { }
757 return std::numeric_limits<Numeric>::quiet_NaN();
765 case TemperatureModel::None:
767 case TemperatureModel::T0:
769 case TemperatureModel::T1:
770 return X0 * pow(T0 / T, X1) * log(T0 / T);
771 case TemperatureModel::T2:
772 return X0 * pow(T0 / T, X1) * (X2 * log(T / T0) + 1.) * log(T0 / T);
773 case TemperatureModel::T3:
775 case TemperatureModel::T4:
776 return pow(T0 / T, X2) * (T0 / T - 1.);
777 case TemperatureModel::T5:
778 return 1.5 * X0 * pow(T0 / T, 1.5 * X1 + 0.25) * log(T0 / T);
779 case TemperatureModel::LM_AER:
780 return special_linemixing_aer_dX1(T);
781 case TemperatureModel::DPL:
782 return X0 * pow(T0 / T, X1) * log(T0 / T);
783 case TemperatureModel::POLY:
785 case TemperatureModel::FINAL: { }
787 return std::numeric_limits<Numeric>::quiet_NaN();
795 case TemperatureModel::None:
797 case TemperatureModel::T0:
799 case TemperatureModel::T1:
801 case TemperatureModel::T2:
802 return X0 * pow(T0 / T, X1) * log(T / T0);
803 case TemperatureModel::T3:
805 case TemperatureModel::T4:
806 return pow(T0 / T, X2) * (X0 + X1 * (T0 / T - 1)) * log(T0 / T);
807 case TemperatureModel::T5:
809 case TemperatureModel::LM_AER:
810 return special_linemixing_aer_dX2(T);
811 case TemperatureModel::DPL:
812 return pow(T0 / T, X3);
813 case TemperatureModel::POLY:
815 case TemperatureModel::FINAL: { }
817 return std::numeric_limits<Numeric>::quiet_NaN();
825 case TemperatureModel::None:
827 case TemperatureModel::T0:
829 case TemperatureModel::T1:
831 case TemperatureModel::T2:
833 case TemperatureModel::T3:
835 case TemperatureModel::T4:
837 case TemperatureModel::T5:
839 case TemperatureModel::LM_AER:
840 return special_linemixing_aer_dX3(T);
841 case TemperatureModel::DPL:
842 return X2 * pow(T0 / T, X3) * log(T0 / T);
843 case TemperatureModel::POLY:
845 case TemperatureModel::FINAL: { }
847 return std::numeric_limits<Numeric>::quiet_NaN();
855 case TemperatureModel::None:
857 case TemperatureModel::T0:
859 case TemperatureModel::T1:
860 return -X0 * X1 * pow(T0 / T, X1) / T;
861 case TemperatureModel::T2:
862 return -X0 * X1 * pow(T0 / T, X1) * (X2 * log(T / T0) + 1.) / T +
863 X0 * X2 * pow(T0 / T, X1) / T;
864 case TemperatureModel::T3:
866 case TemperatureModel::T4:
867 return -X2 * pow(T0 / T, X2) * (X0 + X1 * (T0 / T - 1.)) / T -
868 T0 * X1 * pow(T0 / T, X2) / pow(T, 2);
869 case TemperatureModel::T5:
870 return -X0 * pow(T0 / T, 1.5 * X1 + 0.25) * (1.5 * X1 + 0.25) / T;
871 case TemperatureModel::LM_AER:
872 return special_linemixing_aer_dT(T);
873 case TemperatureModel::DPL:
874 return -X0 * X1 * pow(T0 / T, X1) / T + -X2 * X3 * pow(T0 / T, X3) / T;
875 case TemperatureModel::POLY:
876 return X1 + 2 * X2 * T + 3 * X3 * T * T;
877 case TemperatureModel::FINAL: { }
879 return std::numeric_limits<Numeric>::quiet_NaN();
887 case TemperatureModel::None:
889 case TemperatureModel::T0:
891 case TemperatureModel::T1:
892 return X0 * X1 * pow(T0 / T, X1) / T0;
893 case TemperatureModel::T2:
894 return X0 * X1 * pow(T0 / T, X1) * (X2 * log(T / T0) + 1.) / T0 -
895 X0 * X2 * pow(T0 / T, X1) / T0;
896 case TemperatureModel::T3:
898 case TemperatureModel::T4:
899 return X2 * pow(T0 / T, X2) * (X0 + X1 * (T0 / T - 1.)) / T0 +
900 X1 * pow(T0 / T, X2) / T;
901 case TemperatureModel::T5:
902 return X0 * pow(T0 / T, 1.5 * X1 + 0.25) * (1.5 * X1 + 0.25) / T0;
903 case TemperatureModel::LM_AER:
905 case TemperatureModel::DPL:
906 return X0 * X1 * pow(T0 / T, X1) / T0 + X2 * X3 * pow(T0 / T, X3) / T0;
907 case TemperatureModel::POLY:
909 case TemperatureModel::FINAL: { }
911 return std::numeric_limits<Numeric>::quiet_NaN();
915 for (
auto& data:
X) {
917 bif >> x >> data.X0 >> data.X1 >> data.X2 >> data.X3;
918 data.type = TemperatureModel(x);
924 for (
auto& data:
X) {
925 bof << Index(data.type) << data.X0 << data.X1 << data.X2 << data.X3;
931 static_assert(
nVars == 9);
932 return {P *
G0().at(T, T0), P *
D0().at(T, T0), P *
G2().at(T, T0),
933 P *
D2().at(T, T0), P *
FVC().at(T, T0),
ETA().at(T, T0),
934 P *
Y().at(T, T0), P * P *
G().at(T, T0), P * P * DV().at(T, T0)};
938 Jacobian::Line target)
const noexcept {
939 static_assert(
nVars == 9,
"Only has support for 9 variables");
942#define FourParams(A, B, p) \
944 return p * A().d##B(T, T0)
946#define NineVars(A, p) \
947 FourParams(A, X0, p); \
948 FourParams(A, X1, p); \
949 FourParams(A, X2, p); \
952 using enum Jacobian::Line;
964 return std::numeric_limits<Numeric>::signaling_NaN();
972 static_assert(
nVars == 9);
973 return {P *
G0().dT(T, T0), P *
D0().dT(T, T0), P *
G2().dT(T, T0),
974 P *
D2().dT(T, T0), P *
FVC().dT(T, T0),
ETA().dT(T, T0),
975 P *
Y().dT(T, T0), P * P *
G().dT(T, T0), P * P * DV().dT(T, T0)};
979 Numeric P)
const noexcept {
980 static_assert(
nVars == 9);
981 return {P *
G0().dT0(T, T0), P *
D0().dT0(T, T0), P *
G2().dT0(T, T0),
982 P *
D2().dT0(T, T0), P *
FVC().dT0(T, T0),
ETA().dT0(T, T0),
983 P *
Y().dT0(T, T0), P * P *
G().dT0(T, T0), P * P * DV().dT0(T, T0)};
986#define FUNC(X, PVAR) \
987 Numeric Model::X(Numeric T, Numeric T0, Numeric P [[maybe_unused]], \
988 const Vector &vmrs) const ARTS_NOEXCEPT { \
989 ARTS_ASSERT(nelem() == vmrs.nelem()) \
991 return PVAR * std::transform_reduce(begin(), end(), vmrs.data_handle(), \
992 0.0, std::plus<>(), \
993 [T, T0](auto &ls, auto &xi) { \
994 return xi * ls.X().at(T, T0); \
1008#define FUNC(X, PVAR) \
1009 Numeric Model::d##X##dT(Numeric T, Numeric T0, Numeric P [[maybe_unused]], \
1010 const Vector &vmrs) const ARTS_NOEXCEPT { \
1011 ARTS_ASSERT(nelem() == vmrs.nelem()) \
1013 return PVAR * std::transform_reduce(begin(), end(), vmrs.data_handle(), \
1014 0.0, std::plus<>(), \
1015 [T, T0](auto &ls, auto &xi) { \
1016 return xi * ls.X().dT(T, T0); \
1031 bool match=
true, nullable=
true;
1032 for (Index i=0; i<
nVars; i++) {
1033 match = match and other.X[i].type == X[i].type;
1036 return {match, nullable};
1040 for (
const auto& mp : ssm.
Data())
1041 if (mp.type not_eq TemperatureModel::None)
1042 os << mp.X0 <<
' ' << mp.X1 <<
' ' << mp.X2 <<
' ' << mp.X3 <<
' ';
1047 for (
auto& mp : ssm.
Data())
1048 if(mp.type not_eq TemperatureModel::None)
1054 return os <<
"G0: " << x.
G0 <<
" D0: " << x.
D0 <<
" G2: " << x.
G2
1055 <<
" D2: " << x.
D2 <<
" FVC: " << x.
FVC <<
" ETA: " << x.
ETA
1056 <<
" Y: " << x.
Y <<
" G: " << x.
G <<
" DV: " << x.
DV;
1064 std::array<Numeric, 12> aer_interp) noexcept : mdata(2) {
1065 mdata.front().G0() = {TemperatureModel::T1, sgam, nself, 0, 0};
1066 mdata.front().D0() = {TemperatureModel::T5, psf, nair, 0, 0};
1068 mdata.back().G0() = {TemperatureModel::T1, agam, nair, 0, 0};
1069 mdata.back().D0() = {TemperatureModel::T5, psf, nair, 0, 0};
1071 if (std::any_of(aer_interp.cbegin(), aer_interp.cend(), [](
auto x){return x not_eq 0;})) {
1072 mdata.front().Y().type = TemperatureModel::LM_AER;
1073 mdata.front().Y().X0 = aer_interp[4];
1074 mdata.front().Y().X1 = aer_interp[5];
1075 mdata.front().Y().X2 = aer_interp[6];
1076 mdata.front().Y().X3 = aer_interp[7];
1077 mdata.front().G().type = TemperatureModel::LM_AER;
1078 mdata.front().G().X0 = aer_interp[8];
1079 mdata.front().G().X1 = aer_interp[9];
1080 mdata.front().G().X2 = aer_interp[10];
1081 mdata.front().G().X3 = aer_interp[11];
1083 mdata.back().Y().type = TemperatureModel::LM_AER;
1084 mdata.back().Y().X0 = aer_interp[4];
1085 mdata.back().Y().X1 = aer_interp[5];
1086 mdata.back().Y().X2 = aer_interp[6];
1087 mdata.back().Y().X3 = aer_interp[7];
1088 mdata.back().G().type = TemperatureModel::LM_AER;
1089 mdata.back().G().X0 = aer_interp[8];
1090 mdata.back().G().X1 = aer_interp[9];
1091 mdata.back().G().X2 = aer_interp[10];
1092 mdata.back().G().X3 = aer_interp[11];
1103 m.
Data().front().G0() = {TemperatureModel::T1, sgam, nself, 0, 0};
1104 m.
Data().front().D0() = {TemperatureModel::T0, psf, 0, 0, 0};
1106 m.
Data().back().G0() = {TemperatureModel::T1, agam, nair, 0, 0};
1107 m.
Data().back().D0() = {TemperatureModel::T0, psf, 0, 0, 0};
1117 std::array<Numeric, 12> aer_interp) {
1120 m.
Data().front().G0() = {TemperatureModel::T1, sgam, nself, 0, 0};
1121 m.
Data().front().D0() = {TemperatureModel::T0, psf, 0, 0, 0};
1123 m.
Data().back().G0() = {TemperatureModel::T1, agam, nair, 0, 0};
1124 m.
Data().back().D0() = {TemperatureModel::T0, psf, 0, 0, 0};
1126 if (std::any_of(aer_interp.cbegin(), aer_interp.cend(), [](
auto x){return x not_eq 0;})) {
1127 m.
Data().front().Y().type = TemperatureModel::LM_AER;
1128 m.
Data().front().Y().X0 = aer_interp[4];
1129 m.
Data().front().Y().X1 = aer_interp[5];
1130 m.
Data().front().Y().X2 = aer_interp[6];
1131 m.
Data().front().Y().X3 = aer_interp[7];
1132 m.
Data().front().G().type = TemperatureModel::LM_AER;
1133 m.
Data().front().G().X0 = aer_interp[8];
1134 m.
Data().front().G().X1 = aer_interp[9];
1135 m.
Data().front().G().X2 = aer_interp[10];
1136 m.
Data().front().G().X3 = aer_interp[11];
1138 m.
Data().back().Y().type = TemperatureModel::LM_AER;
1139 m.
Data().back().Y().X0 = aer_interp[4];
1140 m.
Data().back().Y().X1 = aer_interp[5];
1141 m.
Data().back().Y().X2 = aer_interp[6];
1142 m.
Data().back().Y().X3 = aer_interp[7];
1143 m.
Data().back().G().type = TemperatureModel::LM_AER;
1144 m.
Data().back().G().X0 = aer_interp[8];
1145 m.
Data().back().G().X1 = aer_interp[9];
1146 m.
Data().back().G().X2 = aer_interp[10];
1147 m.
Data().back().G().X3 = aer_interp[11];
1154 const std::size_t nspecies)
const noexcept {
1155 Index n = mdata.size();
1156 Index m = Index(self) + Index(bath);
1157 bool needs_any = type not_eq Type::DP;
1158 return not (n not_eq Index(nspecies) or m > n or (needs_any and not n));
1163 specs.erase(specs.begin() + i);
1168 specs.erase(specs.begin() + i);
1172 for (
auto& ssm :
mdata) {
1180 const Index n = nelem();
1181 if (other.nelem() not_eq n)
return {
false,
false};
1183 bool match =
true, nullable =
true;
1184 for (Index i=0; i<n; i++) {
1185 const auto x = mdata[i].MatchTypes(other[i]);
1186 match = match and x.first;
1187 nullable = nullable and x.second;
1190 return {match, nullable};
1194 for (
auto& data:
mdata)
1200 for (
auto& data:
mdata)
1205namespace LegacyLineFunctionData {
1207 if (type ==
String(
"DP"))
1209 if (type ==
String(
"LP"))
1210 return {Variable::G0, Variable::D0};
1211 if (type ==
String(
"VP"))
1212 return {Variable::G0, Variable::D0};
1213 if (type ==
String(
"SDVP"))
1214 return {Variable::G0, Variable::D0, Variable::G2, Variable::D2};
1215 if (type ==
String(
"HTP"))
1216 return {Variable::G0,
1223 "Type: ", type,
", is not accepted. "
1224 "See documentation for accepted types\n")
1231 return {Variable::Y};
1233 return {Variable::Y, Variable::G, Variable::DV};
1236 if (type ==
"ConstG")
1237 return {Variable::G};
1239 "Type: ", type,
", is not accepted. "
1240 "See documentation for accepted types\n")
1244namespace LegacyLineMixingData {
1259 "Type: ", type,
", is not accepted. "
1260 "See documentation for accepted types\n")
1265namespace LegacyPressureBroadeningData {
1276 "Type: ", type,
", is not accepted. "
1277 "See documentation for accepted types\n")
1283 (qid.
Species() == Species::fromShortName(
"N2") or
1284 qid.
Species() == Species::fromShortName(
"O2") or
1285 qid.
Species() == Species::fromShortName(
"H2O") or
1286 qid.
Species() == Species::fromShortName(
"CO2") or
1287 qid.
Species() == Species::fromShortName(
"H2") or
1288 qid.
Species() == Species::fromShortName(
"He")))
Index nelem() const ARTS_NOEXCEPT
Main line shape model class.
void SetLineMixingModel(SingleSpeciesModel x)
Sets the same line mixing model to all species.
void Remove(Index i, ArrayOfSpeciesTag &specs)
Remove species and data at position.
std::vector< SingleSpeciesModel > mdata
Model(Index n=0) noexcept
Default init just sets the size.
bool OK(Type type, bool self, bool bath, const std::size_t nspecies) const noexcept
The Model is good to use.
bifstream & read(bifstream &bif)
Binary read for Model.
bofstream & write(bofstream &bof) const
Binary write for Model.
const std::vector< SingleSpeciesModel > & Data() const noexcept
The line shape model data.
std::pair< bool, bool > Match(const Model &other) const noexcept
Compute the line shape parameters for a single broadening species.
constexpr std::array< ModelParameters, nVars > & Data() noexcept
Get internal Data reference.
Output dT0(Numeric T, Numeric T0, Numeric P) const noexcept
Output at(Numeric T, Numeric T0, Numeric P) const noexcept
Numeric dX(Numeric T, Numeric T0, Numeric P, Jacobian::Line) const noexcept
std::array< ModelParameters, nVars > X
bofstream & write(bofstream &bof) const
Binary write for SingleSpeciesModel.
bifstream & read(bifstream &bif)
Binary read for SingleSpeciesModel.
std::pair< bool, bool > MatchTypes(const SingleSpeciesModel &other) const noexcept
Output dT(Numeric T, Numeric T0, Numeric P) const noexcept
Binary output file stream class.
Binary output file stream class.
Input manipulator class for doubles to enable nan and inf parsing.
Helper macros for debugging.
#define ARTS_ASSERT(condition,...)
#define ARTS_USER_ERROR(...)
#define ARTS_USER_ERROR_IF(condition,...)
constexpr std::string_view toString(EnergyLevelMapType x) noexcept
constexpr void check_enum_error(EnumType type, Messages... args)
Checks if the enum class type is good and otherwise throws an error message composed by variadic inpu...
constexpr bool good_enum(EnumType x) noexcept
Checks if the enum number is good.
Array< Species::Species > ArrayOfSpecies
#define ReturnJacPropMatType(ID)
Jacobian::Line select_derivativeLineShape(const String &var, const String &coeff)
Return the derivative type based on string input.
Contains the line shape namespace.
my_basic_string< char > String
The String type for ARTS.
std::vector< Variable > linemixingtag2variablesvector(String type)
Line mixing models from string.
std::vector< Variable > lineshapetag2variablesvector(String type)
Line shape models from string.
LegacyLineMixingData::TypeLM string2typelm(String type)
Line mixing types from string.
Model vector2modellm(Vector x, LegacyLineMixingData::TypeLM type)
LineShape::Model from legacy input vector.
TypeLM
Line mixing types that used to exist.
@ LM_LBLRTM_O2NonResonant
Index self_listed(const QuantumIdentifier &qid, LegacyPressureBroadeningData::TypePB t)
Pressure broadening if self exist.
void vector2modelpb(LineShape::Type &mtype, bool &self, bool &bath, Model &m, ArrayOfSpecies &species, Vector x, LegacyPressureBroadeningData::TypePB type, bool self_in_list, Species::Species self_spec)
LineShape::Model from legacy input vector.
LegacyPressureBroadeningData::TypePB string2typepb(String type)
Pressure broadening types from string.
TypePB
Pressure broadening types that used to exist.
@ PB_AIR_AND_WATER_BROADENING
@ PB_PLANETARY_BROADENING
Computations of line shape derived parameters.
Model lblrtm_model(Numeric sgam, Numeric nself, Numeric agam, Numeric nair, Numeric psf, std::array< Numeric, 12 > aer_interp)
Numeric & SingleModelParameter(ModelParameters &mp, const String &type)
Get a coefficient from ModelParameters by name.
constexpr std::string_view bath_broadening
Name for bath broadening in printing and reading user input.
Model MetaData2ModelShape(const String &s)
std::istream & from_linefunctiondata(std::istream &data, Type &type, bool &self, bool &bath, Model &m, ArrayOfSpecies &species)
constexpr bool modelparameterEmpty(const ModelParameters mp) noexcept
Model hitran_model(Numeric sgam, Numeric nself, Numeric agam, Numeric nair, Numeric psf)
Vector mass(const ConstVectorView &atmospheric_vmrs, const ArrayOfArrayOfSpeciesTag &atmospheric_species, const ArrayOfSpecies &lineshape_species, const SpeciesIsotopologueRatios &ir) ARTS_NOEXCEPT
Returns a mass vector for this model's main calculations.
constexpr std::string_view self_broadening
Name for self broadening in printing and reading user input.
std::istream & from_pressurebroadeningdata(std::istream &data, LineShape::Type &type, bool &self, bool &bath, Model &m, ArrayOfSpecies &species, const QuantumIdentifier &qid)
Legacy reading of old deprecated PressureBroadeningData class.
ArrayOfString ModelMetaDataArray(const LineShape::Model &m, const bool self, const ArrayOfSpecies &sts, const Numeric T0)
String modelparameters2metadata(const ModelParameters mp, const Numeric T0)
std::istream & operator>>(std::istream &is, Model &m)
String ModelShape2MetaData(const Model &m)
std::istream & from_artscat4(std::istream &is, Type &type, bool &self, bool &bath, Model &m, ArrayOfSpecies &species, const QuantumIdentifier &qid)
std::ostream & operator<<(std::ostream &os, const Model &m)
std::istream & from_linemixingdata(std::istream &data, Model &lsc)
Legacy reading of old deprecated LineMixingData class.
constexpr Index nVars
Current max number of line shape variables.
Vector vmrs(const ConstVectorView &atmospheric_vmrs, const ArrayOfArrayOfSpeciesTag &atmospheric_species, const ArrayOfSpecies &lineshape_species) ARTS_NOEXCEPT
Returns a VMR vector for this model's main calculations.
constexpr Numeric mean_mass(Species spec, const IsotopologueRatios &ir) noexcept
Coefficients and temperature model for SingleSpeciesModel.
Numeric dT0(Numeric T, Numeric T0) const noexcept
Numeric dX0(Numeric T, Numeric T0) const noexcept
Numeric dT(Numeric T, Numeric T0) const noexcept
Numeric at(Numeric T, Numeric T0) const noexcept
Numeric dX1(Numeric T, Numeric T0) const noexcept
Numeric dX3(Numeric T, Numeric T0) const noexcept
Numeric dX2(Numeric T, Numeric T0) const noexcept
A logical struct for global quantum numbers with species identifiers.
Species::Species Species() const noexcept
Species::IsotopeRecord Isotopologue() const noexcept