44 const auto var_type = LineShape::toVariableOrThrow(var);
47 const auto coeff_type = Options::toLineShapeCoeffOrThrow(coeff);
50#define ReturnJacPropMatType(ID) \
51 case LineShape::Variable::ID: \
52 switch (coeff_type) { \
53 case Options::LineShapeCoeff::X0: \
54 return Jacobian::Line::Shape##ID##X0; \
55 case Options::LineShapeCoeff::X1: \
56 return Jacobian::Line::Shape##ID##X1; \
57 case Options::LineShapeCoeff::X2: \
58 return Jacobian::Line::Shape##ID##X2; \
59 case Options::LineShapeCoeff::X3: \
60 return Jacobian::Line::Shape##ID##X3; \
61 case Options::LineShapeCoeff::FINAL: \
62 return Jacobian::Line::FINAL; \
75 case LineShape::Variable::FINAL: {
79#undef ReturnJacPropMatType
81 return Jacobian::Line::FINAL;
95 m.
mdata = std::vector<SingleSpeciesModel>(7);
99 species[1] = Species::fromShortName(
"N2");
100 species[2] = Species::fromShortName(
"O2");
101 species[3] = Species::fromShortName(
"H2O");
102 species[4] = Species::fromShortName(
"CO2");
103 species[5] = Species::fromShortName(
"H2");
104 species[6] = Species::fromShortName(
"He");
108 v.G0().type = TemperatureModel::T1;
109 v.D0().type = TemperatureModel::T5;
118 v.D0().X1 =
v.G0().X1;
122 m.
mdata.front().D0().X0 = 0;
123 for (
int k = 1; k < 7; k++)
127 for (
int k = 1; k < 7; k++) {
128 if (qid.
Species() == species[k]) {
130 m.
mdata.front().G0().X1 not_eq m.
mdata[k].G0().X1 or
131 m.
mdata.front().D0().X1 not_eq m.
mdata[k].D0().X1,
132 "Species is ", qid.
Isotopologue(),
" and this is a broadening species in ARTSCAT-4.\n"
133 "Despite this, values representing self and ", qid.
Isotopologue(),
" does not match "
159 const auto shapeparams =
160 LegacyLineFunctionData::lineshapetag2variablesvector(
toString(mtype));
166 const auto mixingparams =
167 LegacyLineFunctionData::linemixingtag2variablesvector(s);
171 species.resize(specs);
172 m.
mdata.resize(specs);
175 "Need at least one species for non-Doppler line shapes");
178 for (
Index i = 0; i < specs; i++) {
185 "Self broadening must be first, it is not\n");
189 species[i] = Species::Species::Bath;
191 "Air/bath broadening must be last, it is not\n");
194 species[i] = Species::fromShortName(s);
196 "Encountered ", s,
" in a position where a species should have been "
197 "defined.\nPlease check your pressure broadening data structure and ensure "
198 "that it follows the correct conventions.\n")
202 for (
auto& params : {shapeparams, mixingparams}) {
203 for (
auto& param : params) {
206 const auto type = toTemperatureModel(s);
208 LegacyLineFunctionData::temperaturemodel2legacynelem(type);
211 if (ntemp <= ModelParameters::N) {
229 "Unknown number of input parameters in Legacy mode.");
233 "Too many input parameters in interpolation results Legacy mode.");
251 LineShape::Type& mtype,
260 const auto type = LegacyPressureBroadeningData::string2typepb(s);
261 const auto n = LegacyPressureBroadeningData::typepb2nelem(type);
262 const auto self_in_list = LegacyPressureBroadeningData::self_listed(qid, type);
267 LegacyPressureBroadeningData::vector2modelpb(mtype,
285 const auto type = LegacyLineMixingData::string2typelm(s);
286 const auto n = LegacyLineMixingData::typelm2nelem(type);
291 lsc = LegacyLineMixingData::vector2modellm(x, type);
296#pragma GCC diagnostic push
297#pragma GCC diagnostic ignored "-Wreturn-type"
299 LineShape::Type& mtype,
307 Species::Species self_spec) {
309 case TypePB::PB_NONE:
310 mtype = LineShape::Type::DP;
315 case TypePB::PB_AIR_BROADENING:
316 mtype = LineShape::Type::VP;
318 m =
Model(x[0], x[1], x[2], x[3], x[4]);
320 species[0] = self_spec;
321 species[1] = Species::Species::Bath;
323 case TypePB::PB_AIR_AND_WATER_BROADENING:
325 mtype = LineShape::Type::VP;
329 m.
Data()[0].G0() = {TemperatureModel::T1, x[0], x[1], 0, 0};
330 m.
Data()[0].D0() = {TemperatureModel::T5, x[2], x[1], 0, 0};
331 m.
Data()[1].G0() = {TemperatureModel::T1, x[3], x[4], 0, 0};
332 m.
Data()[1].D0() = {TemperatureModel::T5, x[5], x[4], 0, 0};
334 species[0] = Species::fromShortName(
"H2O");
335 species[1] = Species::Species::Bath;
338 mtype = LineShape::Type::VP;
341 m.
Data()[0].G0() = {TemperatureModel::T1, x[0], x[1], 0, 0};
342 m.
Data()[0].D0() = {TemperatureModel::T5, x[2], x[1], 0, 0};
343 m.
Data()[2].G0() = {TemperatureModel::T1, x[3], x[4], 0, 0};
344 m.
Data()[2].D0() = {TemperatureModel::T5, x[5], x[4], 0, 0};
345 m.
Data()[1].G0() = {TemperatureModel::T1, x[6], x[7], 0, 0};
346 m.
Data()[1].D0() = {TemperatureModel::T5, x[8], x[7], 0, 0};
348 species[0] = self_spec;
349 species[1] = Species::fromShortName(
"H2O");
350 species[2] = Species::Species::Bath;
353 case TypePB::PB_PLANETARY_BROADENING:
355 mtype = LineShape::Type::VP;
358 m.
Data()[0].G0() = {TemperatureModel::T1, x[1], x[8], 0, 0};
359 m.
Data()[0].D0() = {TemperatureModel::T5, x[14], x[8], 0, 0};
360 m.
Data()[1].G0() = {TemperatureModel::T1, x[2], x[9], 0, 0};
361 m.
Data()[1].D0() = {TemperatureModel::T5, x[15], x[9], 0, 0};
362 m.
Data()[2].G0() = {TemperatureModel::T1, x[3], x[10], 0, 0};
363 m.
Data()[2].D0() = {TemperatureModel::T5, x[16], x[10], 0, 0};
364 m.
Data()[3].G0() = {TemperatureModel::T1, x[4], x[11], 0, 0};
365 m.
Data()[3].D0() = {TemperatureModel::T5, x[17], x[11], 0, 0};
366 m.
Data()[4].G0() = {TemperatureModel::T1, x[5], x[12], 0, 0};
367 m.
Data()[4].D0() = {TemperatureModel::T5, x[18], x[12], 0, 0};
368 m.
Data()[5].G0() = {TemperatureModel::T1, x[6], x[13], 0, 0};
369 m.
Data()[5].D0() = {TemperatureModel::T5, x[19], x[13], 0, 0};
370 species = {Species::fromShortName(
"N2"),
371 Species::fromShortName(
"O2"),
372 Species::fromShortName(
"H2O"),
373 Species::fromShortName(
"CO2"),
374 Species::fromShortName(
"H2"),
375 Species::fromShortName(
"He")};
378 mtype = LineShape::Type::VP;
382 m.
Data()[0].G0() = {TemperatureModel::T1, x[0], x[7], 0, 0};
384 m.
Data()[1].G0() = {TemperatureModel::T1, x[1], x[8], 0, 0};
385 m.
Data()[1].D0() = {TemperatureModel::T5, x[14], x[8], 0, 0};
386 m.
Data()[2].G0() = {TemperatureModel::T1, x[2], x[9], 0, 0};
387 m.
Data()[2].D0() = {TemperatureModel::T5, x[15], x[9], 0, 0};
388 m.
Data()[3].G0() = {TemperatureModel::T1, x[3], x[10], 0, 0};
389 m.
Data()[3].D0() = {TemperatureModel::T5, x[16], x[10], 0, 0};
390 m.
Data()[4].G0() = {TemperatureModel::T1, x[4], x[11], 0, 0};
391 m.
Data()[4].D0() = {TemperatureModel::T5, x[17], x[11], 0, 0};
392 m.
Data()[5].G0() = {TemperatureModel::T1, x[5], x[12], 0, 0};
393 m.
Data()[5].D0() = {TemperatureModel::T5, x[18], x[12], 0, 0};
394 m.
Data()[6].G0() = {TemperatureModel::T1, x[6], x[13], 0, 0};
395 m.
Data()[6].D0() = {TemperatureModel::T5, x[19], x[13], 0, 0};
397 species[0] = self_spec;
398 species[1] = Species::fromShortName(
"N2");
399 species[2] = Species::fromShortName(
"O2");
400 species[3] = Species::fromShortName(
"H2O");
401 species[4] = Species::fromShortName(
"CO2");
402 species[5] = Species::fromShortName(
"H2");
403 species[6] = Species::fromShortName(
"He");
408#pragma GCC diagnostic pop
414 case TypeLM::LM_NONE:
416 case TypeLM::LM_LBLRTM:
417 y.
Data().front().Y().type = LineShape::TemperatureModel::LM_AER;
418 y.
Data().front().G().type = LineShape::TemperatureModel::LM_AER;
419 y.
Data().front().Y().X0 = x[4];
420 y.
Data().front().Y().X1 = x[5];
421 y.
Data().front().Y().X2 = x[6];
422 y.
Data().front().Y().X3 = x[7];
423 y.
Data().front().G().X0 = x[8];
424 y.
Data().front().G().X1 = x[9];
425 y.
Data().front().G().X2 = x[10];
426 y.
Data().front().G().X3 = x[11];
428 case TypeLM::LM_LBLRTM_O2NonResonant:
429 y.
Data().front().G().type = LineShape::TemperatureModel::T0;
430 y.
Data().front().G().X0 = x[0];
432 case TypeLM::LM_2NDORDER:
433 y.
Data().front().Y().type = LineShape::TemperatureModel::T4;
434 y.
Data().front().Y().X0 = x[0];
435 y.
Data().front().Y().X1 = x[1];
436 y.
Data().front().Y().X2 = x[7];
437 y.
Data().front().G().type = LineShape::TemperatureModel::T4;
438 y.
Data().front().G().X0 = x[2];
439 y.
Data().front().G().X1 = x[3];
440 y.
Data().front().G().X2 = x[8];
441 y.
Data().front().DV().type = LineShape::TemperatureModel::T4;
442 y.
Data().front().DV().X0 = x[4];
443 y.
Data().front().DV().X1 = x[5];
444 y.
Data().front().DV().X2 = x[9];
446 case TypeLM::LM_1STORDER:
447 y.
Data().front().Y().type = LineShape::TemperatureModel::T1;
448 y.
Data().front().Y().X0 = x[1];
449 y.
Data().front().Y().X1 = x[2];
451 case TypeLM::LM_BYBAND:
461 ARTS_ASSERT (atmospheric_species.nelem() == atmospheric_vmrs.nelem(),
"Bad atmospheric inputs");
463 const Index n = lineshape_species.nelem();
469 const bool bath = n and lineshape_species.back() == Species::Species::Bath;
472 for (
Index i = 0; i < n - bath; i++) {
473 const Species::Species target = lineshape_species[i];
476 Index this_species_index = -1;
477 for (
Index j = 0; j < atmospheric_species.nelem(); j++) {
478 if (atmospheric_species[j].
Species() == target) {
479 this_species_index = j;
484 if (this_species_index not_eq -1) {
485 line_vmrs[i] = atmospheric_vmrs[this_species_index];
491 line_vmrs[n - 1] = 1.0 - line_vmrs.
sum();
492 }
else if(line_vmrs.
sum() == 0) {
494 line_vmrs /= line_vmrs.
sum();
504 ARTS_ASSERT (atmospheric_species.nelem() == atmospheric_vmrs.nelem(),
505 "Bad atmospheric inputs");
507 const Index n = lineshape_species.nelem();
514 const bool bath = n and lineshape_species.back() == Species::Species::Bath;
517 for (
Index i = 0; i < n - bath; i++) {
519 const Species::Species target = lineshape_species[i];
522 Index this_species_index = -1;
523 for (
Index j = 0; j < atmospheric_species.nelem(); j++) {
524 if (atmospheric_species[j].
Species() == target) {
525 this_species_index = j;
530 if (this_species_index not_eq -1) {
531 line_vmrs[i] = atmospheric_vmrs[this_species_index];
537 if(line_vmrs.
sum() == 0) {
539 line_mass[n - 1] = (line_vmrs * line_mass) / line_vmrs.
sum();
547 for (
auto& data : m.
Data()) os << data;
552 for (
auto& data : m.
Data()) is >> data;
558 const auto& vars = enumtyps::VariableTypes;
560 for (
auto& var : vars) {
561 if (std::any_of(m.
Data().cbegin(), m.
Data().cend(), [var](
auto& x) {
562 return x.Get(var).type not_eq TemperatureModel::None;
565 for (
auto& ssm : m.
Data())
570 if (out.size()) out.pop_back();
576 if (s.
nelem() == 0)
return {};
578 const auto& names = enumstrs::VariableNames;
580 std::istringstream str(s);
582 Variable var = Variable::ETA;
583 TemperatureModel tm = TemperatureModel::None;
586 std::vector<SingleSpeciesModel> ssms(0);
587 while (not str.eof()) {
589 if (std::any_of(names.cbegin(), names.cend(), [part](
auto x) {
593 var = toVariable(part);
596 tm = toTemperatureModel(part);
600 if (i <
Index(ssms.size()))
605 auto mp = ssms[i].Get(var);
607 ssms[i].Set(var, mp);
615 std::ostringstream os;
617 case TemperatureModel::None:
620 case TemperatureModel::T0:
623 case TemperatureModel::T1:
624 os << mp.
X0 <<
" * (" << T0 <<
"/T)^" << mp.
X1;
626 case TemperatureModel::T2:
627 os << mp.
X0 <<
" * (" << T0 <<
"/T)^" << mp.
X1 <<
" / (1 + " << mp.
X2
628 <<
" * log(T/" << T0 <<
"))";
630 case TemperatureModel::T3:
631 os << mp.
X0 <<
" + " << mp.
X1 <<
" * (" << T0 <<
" - T)";
633 case TemperatureModel::T4:
634 os <<
"(" << mp.
X0 <<
" + " << mp.
X1 <<
" * (" << T0 <<
"/T - 1)) * ("
635 << T0 <<
"/T)^" << mp.
X2;
637 case TemperatureModel::T5:
638 os << mp.
X0 <<
" * (" << T0 <<
"/T)^(0.25 + 1.5 * " << mp.
X1 <<
")";
640 case TemperatureModel::LM_AER:
642 <<
"Linear interpolation to y(x) from x-ref = [200, 250, 296, 340] and y-ref = ["
643 << mp.
X0 <<
", " << mp.
X1 <<
", " << mp.
X2 <<
", " << mp.
X3 <<
']'
646 case TemperatureModel::DPL:
647 os <<
'(' << mp.
X0 <<
" * (" << T0 <<
"/T)^" << mp.
X1 <<
" + " << mp.
X2
648 <<
" * (" << T0 <<
"/T)^" << mp.
X3 <<
')';
650 case TemperatureModel::POLY:
651 os <<
'(' << mp.
X0 <<
" + " << mp.
X1 <<
" * T + " << mp.
X2
652 <<
" * T * T + " << mp.
X3 <<
" * T * T * T)";
653 case TemperatureModel::FINAL:
664 const auto& vars = enumtyps::VariableTypes;
667 for (
Index i = 0; i <
Index(Variable::FINAL); i++) {
668 Variable var = vars[i];
670 if (std::any_of(m.
Data().cbegin(), m.
Data().cend(), [var](
auto& x) {
671 return x.Get(var).type not_eq TemperatureModel::None;
673 std::ostringstream os;
680 os <<
"VMR(" << toShortName(sts[j]) <<
") * "
683 if (sts[j] not_eq sts.back()) os <<
" + ";
685 as.push_back(os.str());
692#pragma GCC diagnostic push
693#pragma GCC diagnostic ignored "-Wreturn-type"
704 "Type: ", type,
", is not accepted. "
705 "See documentation for accepted types\n")
707#pragma GCC diagnostic pop
710 os << mp.
type <<
' ' << mp.
X0 <<
' ' << mp.
X1 <<
' '
711 << mp.
X2 <<
' ' << mp.
X3 <<
' ';
725 case TemperatureModel::None:
727 case TemperatureModel::T0:
729 case TemperatureModel::T1:
730 return X0 *
pow(T0 / T, X1);
731 case TemperatureModel::T2:
732 return X0 *
pow(T0 / T, X1) * (1 + X2 * log(T / T0));
733 case TemperatureModel::T3:
734 return X0 + X1 * (T - T0);
735 case TemperatureModel::T4:
736 return (X0 + X1 * (T0 / T - 1.)) *
pow(T0 / T, X2);
737 case TemperatureModel::T5:
738 return X0 *
pow(T0 / T, 0.25 + 1.5 * X1);
739 case TemperatureModel::LM_AER:
740 return special_linemixing_aer(T);
741 case TemperatureModel::DPL:
742 return X0 *
pow(T0 / T, X1) + X2 *
pow(T0 / T, X3);
743 case TemperatureModel::POLY:
744 return X0 + X1 * T + X2 * T * T + X3 * T * T * T;
745 case TemperatureModel::FINAL: { }
747 return std::numeric_limits<Numeric>::quiet_NaN();
755 case TemperatureModel::None:
757 case TemperatureModel::T0:
759 case TemperatureModel::T1:
760 return pow(T0 / T, X1);
761 case TemperatureModel::T2:
762 return pow(T0 / T, X1) * (1 + X2 * log(T / T0));
763 case TemperatureModel::T3:
765 case TemperatureModel::T4:
766 return pow(T0 / T, X2);
767 case TemperatureModel::T5:
768 return pow(T0 / T, 1.5 * X1 + 0.25);
769 case TemperatureModel::LM_AER:
770 return special_linemixing_aer_dX0(T);
771 case TemperatureModel::DPL:
772 return pow(T0 / T, X1);
773 case TemperatureModel::POLY:
775 case TemperatureModel::FINAL: { }
777 return std::numeric_limits<Numeric>::quiet_NaN();
785 case TemperatureModel::None:
787 case TemperatureModel::T0:
789 case TemperatureModel::T1:
790 return X0 *
pow(T0 / T, X1) * log(T0 / T);
791 case TemperatureModel::T2:
792 return X0 *
pow(T0 / T, X1) * (X2 * log(T / T0) + 1.) * log(T0 / T);
793 case TemperatureModel::T3:
795 case TemperatureModel::T4:
796 return pow(T0 / T, X2) * (T0 / T - 1.);
797 case TemperatureModel::T5:
798 return 1.5 * X0 *
pow(T0 / T, 1.5 * X1 + 0.25) * log(T0 / T);
799 case TemperatureModel::LM_AER:
800 return special_linemixing_aer_dX1(T);
801 case TemperatureModel::DPL:
802 return X0 *
pow(T0 / T, X1) * log(T0 / T);
803 case TemperatureModel::POLY:
805 case TemperatureModel::FINAL: { }
807 return std::numeric_limits<Numeric>::quiet_NaN();
815 case TemperatureModel::None:
817 case TemperatureModel::T0:
819 case TemperatureModel::T1:
821 case TemperatureModel::T2:
822 return X0 *
pow(T0 / T, X1) * log(T / T0);
823 case TemperatureModel::T3:
825 case TemperatureModel::T4:
826 return pow(T0 / T, X2) * (X0 + X1 * (T0 / T - 1)) * log(T0 / T);
827 case TemperatureModel::T5:
829 case TemperatureModel::LM_AER:
830 return special_linemixing_aer_dX2(T);
831 case TemperatureModel::DPL:
832 return pow(T0 / T, X3);
833 case TemperatureModel::POLY:
835 case TemperatureModel::FINAL: { }
837 return std::numeric_limits<Numeric>::quiet_NaN();
845 case TemperatureModel::None:
847 case TemperatureModel::T0:
849 case TemperatureModel::T1:
851 case TemperatureModel::T2:
853 case TemperatureModel::T3:
855 case TemperatureModel::T4:
857 case TemperatureModel::T5:
859 case TemperatureModel::LM_AER:
860 return special_linemixing_aer_dX3(T);
861 case TemperatureModel::DPL:
862 return X2 *
pow(T0 / T, X3) * log(T0 / T);
863 case TemperatureModel::POLY:
865 case TemperatureModel::FINAL: { }
867 return std::numeric_limits<Numeric>::quiet_NaN();
875 case TemperatureModel::None:
877 case TemperatureModel::T0:
879 case TemperatureModel::T1:
880 return -X0 * X1 *
pow(T0 / T, X1) / T;
881 case TemperatureModel::T2:
882 return -X0 * X1 *
pow(T0 / T, X1) * (X2 * log(T / T0) + 1.) / T +
883 X0 * X2 *
pow(T0 / T, X1) / T;
884 case TemperatureModel::T3:
886 case TemperatureModel::T4:
887 return -X2 *
pow(T0 / T, X2) * (X0 + X1 * (T0 / T - 1.)) / T -
888 T0 * X1 *
pow(T0 / T, X2) /
pow(T, 2);
889 case TemperatureModel::T5:
890 return -X0 *
pow(T0 / T, 1.5 * X1 + 0.25) * (1.5 * X1 + 0.25) / T;
891 case TemperatureModel::LM_AER:
892 return special_linemixing_aer_dT(T);
893 case TemperatureModel::DPL:
894 return -X0 * X1 *
pow(T0 / T, X1) / T + -X2 * X3 *
pow(T0 / T, X3) / T;
895 case TemperatureModel::POLY:
896 return X1 + 2 * X2 * T + 3 * X3 * T * T;
897 case TemperatureModel::FINAL: { }
899 return std::numeric_limits<Numeric>::quiet_NaN();
907 case TemperatureModel::None:
909 case TemperatureModel::T0:
911 case TemperatureModel::T1:
912 return X0 * X1 *
pow(T0 / T, X1) / T0;
913 case TemperatureModel::T2:
914 return X0 * X1 *
pow(T0 / T, X1) * (X2 * log(T / T0) + 1.) / T0 -
915 X0 * X2 *
pow(T0 / T, X1) / T0;
916 case TemperatureModel::T3:
918 case TemperatureModel::T4:
919 return X2 *
pow(T0 / T, X2) * (X0 + X1 * (T0 / T - 1.)) / T0 +
920 X1 *
pow(T0 / T, X2) / T;
921 case TemperatureModel::T5:
922 return X0 *
pow(T0 / T, 1.5 * X1 + 0.25) * (1.5 * X1 + 0.25) / T0;
923 case TemperatureModel::LM_AER:
925 case TemperatureModel::DPL:
926 return X0 * X1 *
pow(T0 / T, X1) / T0 + X2 * X3 *
pow(T0 / T, X3) / T0;
927 case TemperatureModel::POLY:
929 case TemperatureModel::FINAL: { }
931 return std::numeric_limits<Numeric>::quiet_NaN();
935 for (
auto& data:
X) {
937 bif >> x >> data.X0 >> data.X1 >> data.X2 >> data.X3;
938 data.type = TemperatureModel(x);
944 for (
auto& data:
X) {
945 bof <<
Index(data.type) << data.X0 << data.X1 << data.X2 << data.X3;
951 static_assert(
nVars == 9);
952 return {P *
G0().at(T, T0), P *
D0().at(T, T0), P *
G2().at(T, T0),
953 P *
D2().at(T, T0), P *
FVC().at(T, T0),
ETA().at(T, T0),
954 P *
Y().at(T, T0), P * P *
G().at(T, T0), P * P * DV().at(T, T0)};
958 Jacobian::Line target)
const noexcept {
959 static_assert(
nVars == 9,
"Only has support for 9 variables");
962#define FourParams(A, B, p) \
964 return p * A().d##B(T, T0)
966#define NineVars(A, p) \
967 FourParams(A, X0, p); \
968 FourParams(A, X1, p); \
969 FourParams(A, X2, p); \
972 using enum Jacobian::Line;
984 return std::numeric_limits<Numeric>::signaling_NaN();
992 static_assert(
nVars == 9);
993 return {P *
G0().dT(T, T0), P *
D0().dT(T, T0), P *
G2().dT(T, T0),
994 P *
D2().dT(T, T0), P *
FVC().dT(T, T0),
ETA().dT(T, T0),
995 P *
Y().dT(T, T0), P * P *
G().dT(T, T0), P * P * DV().dT(T, T0)};
1000 static_assert(
nVars == 9);
1001 return {P *
G0().dT0(T, T0), P *
D0().dT0(T, T0), P *
G2().dT0(T, T0),
1002 P *
D2().dT0(T, T0), P *
FVC().dT0(T, T0),
ETA().dT0(T, T0),
1003 P *
Y().dT0(T, T0), P * P *
G().dT0(T, T0), P * P * DV().dT0(T, T0)};
1006#define FUNC(X, PVAR) \
1007 Numeric Model::X(Numeric T, Numeric T0, Numeric P [[maybe_unused]], \
1008 const Vector &vmrs) const ARTS_NOEXCEPT { \
1009 ARTS_ASSERT(nelem() == vmrs.nelem()) \
1011 return PVAR * std::transform_reduce(begin(), end(), vmrs.get_c_array(), \
1012 0.0, std::plus<>(), \
1013 [T, T0](auto &ls, auto &xi) { \
1014 return xi * ls.X().at(T, T0); \
1028#define FUNC(X, PVAR) \
1029 Numeric Model::d##X##dT(Numeric T, Numeric T0, Numeric P [[maybe_unused]], \
1030 const Vector &vmrs) const ARTS_NOEXCEPT { \
1031 ARTS_ASSERT(nelem() == vmrs.nelem()) \
1033 return PVAR * std::transform_reduce(begin(), end(), vmrs.get_c_array(), \
1034 0.0, std::plus<>(), \
1035 [T, T0](auto &ls, auto &xi) { \
1036 return xi * ls.X().dT(T, T0); \
1051 bool match=
true, nullable=
true;
1053 match = match and other.X[i].type == X[i].type;
1056 return {match, nullable};
1060 for (
const auto& mp : ssm.
Data())
1061 if (mp.type not_eq TemperatureModel::None)
1062 os << mp.X0 <<
' ' << mp.X1 <<
' ' << mp.X2 <<
' ' << mp.X3 <<
' ';
1067 for (
auto& mp : ssm.
Data())
1068 if(mp.type not_eq TemperatureModel::None)
1074 return os <<
"G0: " << x.
G0 <<
" D0: " << x.
D0 <<
" G2: " << x.
G2
1075 <<
" D2: " << x.
D2 <<
" FVC: " << x.
FVC <<
" ETA: " << x.
ETA
1076 <<
" Y: " << x.
Y <<
" G: " << x.
G <<
" DV: " << x.
DV;
1084 std::array<Numeric, 12> aer_interp) noexcept : mdata(2) {
1085 mdata.front().G0() = {TemperatureModel::T1, sgam, nself, 0, 0};
1086 mdata.front().D0() = {TemperatureModel::T5, psf, nair, 0, 0};
1088 mdata.back().G0() = {TemperatureModel::T1, agam, nair, 0, 0};
1089 mdata.back().D0() = {TemperatureModel::T5, psf, nair, 0, 0};
1091 if (std::any_of(aer_interp.cbegin(), aer_interp.cend(), [](
auto x){return x not_eq 0;})) {
1092 mdata.front().Y().type = TemperatureModel::LM_AER;
1093 mdata.front().Y().X0 = aer_interp[4];
1094 mdata.front().Y().X1 = aer_interp[5];
1095 mdata.front().Y().X2 = aer_interp[6];
1096 mdata.front().Y().X3 = aer_interp[7];
1097 mdata.front().G().type = TemperatureModel::LM_AER;
1098 mdata.front().G().X0 = aer_interp[8];
1099 mdata.front().G().X1 = aer_interp[9];
1100 mdata.front().G().X2 = aer_interp[10];
1101 mdata.front().G().X3 = aer_interp[11];
1103 mdata.back().Y().type = TemperatureModel::LM_AER;
1104 mdata.back().Y().X0 = aer_interp[4];
1105 mdata.back().Y().X1 = aer_interp[5];
1106 mdata.back().Y().X2 = aer_interp[6];
1107 mdata.back().Y().X3 = aer_interp[7];
1108 mdata.back().G().type = TemperatureModel::LM_AER;
1109 mdata.back().G().X0 = aer_interp[8];
1110 mdata.back().G().X1 = aer_interp[9];
1111 mdata.back().G().X2 = aer_interp[10];
1112 mdata.back().G().X3 = aer_interp[11];
1123 m.
Data().front().G0() = {TemperatureModel::T1, sgam, nself, 0, 0};
1124 m.
Data().front().D0() = {TemperatureModel::T0, psf, 0, 0, 0};
1126 m.
Data().back().G0() = {TemperatureModel::T1, agam, nair, 0, 0};
1127 m.
Data().back().D0() = {TemperatureModel::T0, psf, 0, 0, 0};
1137 std::array<Numeric, 12> aer_interp) {
1140 m.
Data().front().G0() = {TemperatureModel::T1, sgam, nself, 0, 0};
1141 m.
Data().front().D0() = {TemperatureModel::T0, psf, 0, 0, 0};
1143 m.
Data().back().G0() = {TemperatureModel::T1, agam, nair, 0, 0};
1144 m.
Data().back().D0() = {TemperatureModel::T0, psf, 0, 0, 0};
1146 if (std::any_of(aer_interp.cbegin(), aer_interp.cend(), [](
auto x){return x not_eq 0;})) {
1147 m.
Data().front().Y().type = TemperatureModel::LM_AER;
1148 m.
Data().front().Y().X0 = aer_interp[4];
1149 m.
Data().front().Y().X1 = aer_interp[5];
1150 m.
Data().front().Y().X2 = aer_interp[6];
1151 m.
Data().front().Y().X3 = aer_interp[7];
1152 m.
Data().front().G().type = TemperatureModel::LM_AER;
1153 m.
Data().front().G().X0 = aer_interp[8];
1154 m.
Data().front().G().X1 = aer_interp[9];
1155 m.
Data().front().G().X2 = aer_interp[10];
1156 m.
Data().front().G().X3 = aer_interp[11];
1158 m.
Data().back().Y().type = TemperatureModel::LM_AER;
1159 m.
Data().back().Y().X0 = aer_interp[4];
1160 m.
Data().back().Y().X1 = aer_interp[5];
1161 m.
Data().back().Y().X2 = aer_interp[6];
1162 m.
Data().back().Y().X3 = aer_interp[7];
1163 m.
Data().back().G().type = TemperatureModel::LM_AER;
1164 m.
Data().back().G().X0 = aer_interp[8];
1165 m.
Data().back().G().X1 = aer_interp[9];
1166 m.
Data().back().G().X2 = aer_interp[10];
1167 m.
Data().back().G().X3 = aer_interp[11];
1174 const std::size_t nspecies)
const noexcept {
1175 Index n = mdata.size();
1177 bool needs_any = type not_eq Type::DP;
1178 return not (n not_eq
Index(nspecies) or m > n or (needs_any and not n));
1183 specs.erase(specs.begin() + i);
1188 specs.erase(specs.begin() + i);
1192 for (
auto& ssm :
mdata) {
1200 const Index n = nelem();
1201 if (other.nelem() not_eq n)
return {
false,
false};
1203 bool match =
true, nullable =
true;
1204 for (
Index i=0; i<n; i++) {
1205 const auto x = mdata[i].MatchTypes(other[i]);
1206 match = match and x.first;
1207 nullable = nullable and x.second;
1210 return {match, nullable};
1214 for (
auto& data:
mdata)
1220 for (
auto& data:
mdata)
1225namespace LegacyLineFunctionData {
1227 if (type ==
String(
"DP"))
1229 if (type ==
String(
"LP"))
1230 return {Variable::G0, Variable::D0};
1231 if (type ==
String(
"VP"))
1232 return {Variable::G0, Variable::D0};
1233 if (type ==
String(
"SDVP"))
1234 return {Variable::G0, Variable::D0, Variable::G2, Variable::D2};
1235 if (type ==
String(
"HTP"))
1236 return {Variable::G0,
1243 "Type: ", type,
", is not accepted. "
1244 "See documentation for accepted types\n")
1251 return {Variable::Y};
1253 return {Variable::Y, Variable::G, Variable::DV};
1256 if (type ==
"ConstG")
1257 return {Variable::G};
1259 "Type: ", type,
", is not accepted. "
1260 "See documentation for accepted types\n")
1264namespace LegacyLineMixingData {
1279 "Type: ", type,
", is not accepted. "
1280 "See documentation for accepted types\n")
1285namespace LegacyPressureBroadeningData {
1296 "Type: ", type,
", is not accepted. "
1297 "See documentation for accepted types\n")
1303 (qid.
Species() == Species::fromShortName(
"N2") or
1304 qid.
Species() == Species::fromShortName(
"O2") or
1305 qid.
Species() == Species::fromShortName(
"H2O") or
1306 qid.
Species() == Species::fromShortName(
"CO2") or
1307 qid.
Species() == Species::fromShortName(
"H2") or
1308 qid.
Species() == Species::fromShortName(
"He")))
Index nelem() const ARTS_NOEXCEPT
A constant view of a Vector.
Numeric sum() const ARTS_NOEXCEPT
The sum of all elements of a Vector.
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.
Implementation of Matrix, Vector, and such stuff.
NUMERIC Numeric
The type to use for all floating point numbers.
INDEX Index
The type to use for all integer numbers and indices.
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
Numeric pow(const Rational base, Numeric exp)
Power of.
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