ARTS 2.5.11 (git: 725533f0)
lineshapemodel.cc
Go to the documentation of this file.
1
14#include "arts_conversions.h"
15#include "debug.h"
16#include "lineshapemodel.h"
17#include "matpack_data.h"
18#include "matpack_math.h"
19#include <limits>
20
21Jacobian::Line select_derivativeLineShape(const String& var,
22 const String& coeff) {
23 // Test viability of model variables
24 const auto var_type = LineShape::toVariableOrThrow(var);
25
26 // Test viability of model coefficients
27 const auto coeff_type = Options::toLineShapeCoeffOrThrow(coeff);
28
29// Define a repetitive pattern. Update if/when there are more coefficients in the future
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; \
43 } break
44
45 switch (var_type) {
55 case LineShape::Variable::FINAL: {
56 /* Leave last */ }
57 }
58
59#undef ReturnJacPropMatType
60
61 return Jacobian::Line::FINAL;
62}
63
64std::istream& LineShape::from_artscat4(std::istream& is,
65 Type& mtype,
66 bool& self,
67 bool& bath,
68 Model& m,
69 ArrayOfSpecies& species,
70 const QuantumIdentifier& qid) {
71 // Set or reset variables
72 mtype = Type::VP;
73 self = true;
74 bath = false;
75 m.mdata = std::vector<SingleSpeciesModel>(7);
76 species = ArrayOfSpecies(7);
77
78 // Set species
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");
85
86 // Temperature types
87 for (auto& v : m.mdata) {
88 v.G0().type = TemperatureModel::T1;
89 v.D0().type = TemperatureModel::T5;
90 }
91
92 // G0 main coefficient
93 for (auto& v : m.mdata) is >> double_imanip() >> v.G0().X0;
94
95 // G0 exponent is same as D0 exponent
96 for (auto& v : m.mdata) {
97 is >> double_imanip() >> v.G0().X1;
98 v.D0().X1 = v.G0().X1;
99 }
100
101 // D0 coefficient
102 m.mdata.front().D0().X0 = 0;
103 for (int k = 1; k < 7; k++)
104 is >> double_imanip() >> m.mdata[k].D0().X0;
105
106 // Special case when self is part of this list, it needs to be removed
107 for (int k = 1; k < 7; k++) {
108 if (qid.Species() == species[k]) {
109 ARTS_USER_ERROR_IF(m.mdata.front().G0().X0 not_eq m.mdata[k].G0().X0 or
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 "
114 "in input string\n")
115 m.mdata.front().D0().X0 = m.mdata[k].D0().X0;
116 m.Remove(k, species);
117 break;
118 }
119 }
120
121 return is;
122}
123
124std::istream& LineShape::from_linefunctiondata(std::istream& data,
125 Type& mtype,
126 bool& self,
127 bool& bath,
128 Model& m,
129 ArrayOfSpecies& species) {
130 self = bath = false;
131 Index specs;
132 String s;
133
134 // The first tag should give the line shape scheme
135 data >> mtype;
136 check_enum_error(mtype, "Bad Data");
137
138 // Order of elements for line shape
139 const auto shapeparams =
140 LegacyLineFunctionData::lineshapetag2variablesvector(toString(mtype));
141
142 // The second tag should give the line mixing scheme
143 data >> s;
144
145 // Order of elements for line mixing
146 const auto mixingparams =
147 LegacyLineFunctionData::linemixingtag2variablesvector(s);
148
149 // The third tag should contain the number of species
150 data >> specs;
151 species.resize(specs);
152 m.mdata.resize(specs);
153
154 ARTS_USER_ERROR_IF (not specs and mtype not_eq Type::DP,
155 "Need at least one species for non-Doppler line shapes");
156
157 // For all species, we need to set the methods to compute them
158 for (Index i = 0; i < specs; i++) {
159 // This should be a species tag or one of the specials, SELF or BATH
160 data >> s;
161 if (s == self_broadening) {
162 // If the species is self, then we need to flag this
163 self = true;
164 ARTS_USER_ERROR_IF (i not_eq 0,
165 "Self broadening must be first, it is not\n");
166 } else if (s == bath_broadening) {
167 // If the species is air, then we need to flag this
168 bath = true;
169 species[i] = Species::Species::Bath;
170 ARTS_USER_ERROR_IF (i not_eq specs - 1,
171 "Air/bath broadening must be last, it is not\n");
172 } else {
173 // Otherwise, we hope we find a species
174 species[i] = Species::fromShortName(s);
175 ARTS_USER_ERROR_IF (not good_enum(species[i]),
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")
179 }
180
181 // For all parameters
182 for (auto& params : {shapeparams, mixingparams}) {
183 for (auto& param : params) {
184 data >> s; // Should contain a temperature tag
185
186 const auto type = toTemperatureModel(s);
187 const Index ntemp =
188 LegacyLineFunctionData::temperaturemodel2legacynelem(type);
189
190 m.mdata[i].Data()[Index(param)].type = type;
191 if (ntemp <= ModelParameters::N) {
192 switch (ntemp) {
193 case 1:
194 data >> double_imanip() >> m.mdata[i].Data()[Index(param)].X0;
195 break;
196 case 2:
197 data >> double_imanip() >> m.mdata[i].Data()[Index(param)].X0 >>
198 m.mdata[i].Data()[Index(param)].X1;
199 break;
200 case 3:
201 data >> double_imanip() >> m.mdata[i].Data()[Index(param)].X0 >>
202 m.mdata[i].Data()[Index(param)].X1 >>
203 m.mdata[i].Data()[Index(param)].X2;
204 break;
205 case 0:
206 break;
207 default:
209 "Unknown number of input parameters in Legacy mode.");
210 }
211 } else { // Has to be the only allowed interpolation case
212 ARTS_USER_ERROR_IF (ntemp > 12,
213 "Too many input parameters in interpolation results Legacy mode.");
214 Numeric temp;
215 data >> double_imanip() >> temp; // should be 200
216 data >> double_imanip() >> temp; // should be 250
217 data >> double_imanip() >> temp; // should be 296
218 data >> double_imanip() >> temp; // should be 340
219 data >> double_imanip() >> m.mdata[i].Y().X0 >> m.mdata[i].Y().X1 >> m.mdata[i].Y().X2 >> m.mdata[i].Y().X3
220 >> m.mdata[i].G().X0 >> m.mdata[i].G().X1 >> m.mdata[i].G().X2 >> m.mdata[i].G().X3;
221 }
222 }
223 }
224 }
225
226 return data;
227}
228
230 std::istream& data,
231 LineShape::Type& mtype,
232 bool& self,
233 bool& bath,
234 Model& m,
235 ArrayOfSpecies& species,
236 const QuantumIdentifier& qid) {
237 String s;
238 data >> s;
239
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);
243
244 Vector x(n);
245 for (auto& num : x) data >> double_imanip() >> num;
246
247 LegacyPressureBroadeningData::vector2modelpb(mtype,
248 self,
249 bath,
250 m,
251 species,
252 x,
253 type,
254 self_in_list,
255 qid.Species());
256
257 return data;
258}
259
260std::istream& LineShape::from_linemixingdata(std::istream& data,
261 LineShape::Model& lsc) {
262 String s;
263 data >> s;
264
265 const auto type = LegacyLineMixingData::string2typelm(s);
266 const auto n = LegacyLineMixingData::typelm2nelem(type);
267
268 Vector x(n);
269 for (auto& num : x) data >> double_imanip() >> num;
270
271 lsc = LegacyLineMixingData::vector2modellm(x, type);
272
273 return data;
274}
275
276#pragma GCC diagnostic push
277#pragma GCC diagnostic ignored "-Wreturn-type"
279 LineShape::Type& mtype,
280 bool& self,
281 bool& bath,
282 Model& m,
283 ArrayOfSpecies& species,
284 Vector x,
286 bool self_in_list,
287 Species::Species self_spec) {
288 switch (type) {
289 case TypePB::PB_NONE:
290 mtype = LineShape::Type::DP;
291 self = bath = false;
292 m = Model();
293 species.resize(0);
294 return;
295 case TypePB::PB_AIR_BROADENING:
296 mtype = LineShape::Type::VP;
297 self = bath = true;
298 m = Model(x[0], x[1], x[2], x[3], x[4]);
299 species.resize(2);
300 species[0] = self_spec;
301 species[1] = Species::Species::Bath;
302 return;
303 case TypePB::PB_AIR_AND_WATER_BROADENING:
304 if (self_in_list) {
305 mtype = LineShape::Type::VP;
306 self = false;
307 bath = true;
308 m.Data().resize(2);
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};
313 species.resize(2);
314 species[0] = Species::fromShortName("H2O");
315 species[1] = Species::Species::Bath;
316 return;
317 } else {
318 mtype = LineShape::Type::VP;
319 self = bath = true;
320 m.Data().resize(2);
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};
327 species.resize(3);
328 species[0] = self_spec;
329 species[1] = Species::fromShortName("H2O");
330 species[2] = Species::Species::Bath;
331 return;
332 }
333 case TypePB::PB_PLANETARY_BROADENING:
334 if (self_in_list) {
335 mtype = LineShape::Type::VP;
336 self = bath = false;
337 m.Data().resize(6);
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")};
356 return;
357 } else {
358 mtype = LineShape::Type::VP;
359 self = true;
360 bath = false;
361 m.Data().resize(7);
362 m.Data()[0].G0() = {TemperatureModel::T1, x[0], x[7], 0, 0};
363 // ssm[0].D0() = ...
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};
376 species.resize(7);
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");
384 return;
385 }
386 }
387}
388#pragma GCC diagnostic pop
389
392 Model y(1);
393 switch (type) {
394 case TypeLM::LM_NONE:
395 break;
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];
407 break;
408 case TypeLM::LM_LBLRTM_O2NonResonant:
409 y.Data().front().G().type = LineShape::TemperatureModel::T0;
410 y.Data().front().G().X0 = x[0];
411 break;
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];
425 break;
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];
430 break;
431 case TypeLM::LM_BYBAND:
432 break;
433 }
434 return y;
435}
436
437
438Vector LineShape::vmrs(const ConstVectorView& atmospheric_vmrs,
439 const ArrayOfArrayOfSpeciesTag& atmospheric_species,
440 const ArrayOfSpecies& lineshape_species) ARTS_NOEXCEPT {
441 ARTS_ASSERT (atmospheric_species.nelem() == atmospheric_vmrs.nelem(), "Bad atmospheric inputs");
442
443 const Index n = lineshape_species.nelem();
444
445 // Initialize list of VMRS to 0
446 Vector line_vmrs(n, 0);
447
448 // We need to know if bath is an actual species
449 const bool bath = n and lineshape_species.back() == Species::Species::Bath;
450
451 // Loop species
452 for (Index i = 0; i < n - bath; i++) {
453 const Species::Species target = lineshape_species[i];
454
455 // Find species in list or do nothing at all
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;
460 }
461 }
462
463 // Set to non-zero in-case species exists
464 if (this_species_index not_eq -1) {
465 line_vmrs[i] = atmospheric_vmrs[this_species_index];
466 }
467 }
468
469 // Renormalize, if bath-species exist this is automatic.
470 if (auto sl = sum(line_vmrs); bath) {
471 line_vmrs[n - 1] = 1.0 - sl;
472 } else if(sl == 0) { // Special case
473 } else {
474 line_vmrs /= sl;
475 }
476
477 return line_vmrs;
478}
479
480Vector LineShape::mass(const ConstVectorView& atmospheric_vmrs,
481 const ArrayOfArrayOfSpeciesTag& atmospheric_species,
482 const ArrayOfSpecies& lineshape_species,
484 ARTS_ASSERT (atmospheric_species.nelem() == atmospheric_vmrs.nelem(),
485 "Bad atmospheric inputs");
486
487 const Index n = lineshape_species.nelem();
488
489 // Initialize list of VMRS to 0
490 Vector line_vmrs(n, 0);
491 Vector line_mass(n, 0);
492
493 // We need to know if bath is an actual species
494 const bool bath = n and lineshape_species.back() == Species::Species::Bath;
495
496 // Loop species ignoring self and bath
497 for (Index i = 0; i < n - bath; i++) {
498 // Select target in-case this is self-broadening
499 const Species::Species target = lineshape_species[i];
500
501 // Find species in list or do nothing at all
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;
506 }
507 }
508
509 // Set to non-zero in-case species exists
510 if (this_species_index not_eq -1) {
511 line_vmrs[i] = atmospheric_vmrs[this_species_index];
512 line_mass[i] = Species::mean_mass(target, ir);
513 }
514 }
515
516 // Renormalize, if bath-species exist this is automatic.
517 if(auto sl = sum(line_vmrs); sl == 0) { // Special case
518 } else if (bath) {
519 line_mass[n - 1] = (line_vmrs * line_mass) / sl;
520 }
521
522 return line_mass;
523}
524
525namespace LineShape {
526std::ostream& operator<<(std::ostream& os, const Model& m) {
527 for (auto& data : m.Data()) os << data;
528 return os;
529}
530
531std::istream& operator>>(std::istream& is, Model& m) {
532 for (auto& data : m.Data()) is >> data;
533 return is;
534}
535
537 String out = "";
538 const auto& vars = enumtyps::VariableTypes;
539
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;
543 })) {
544 out += String(toString(var)) + ' ';
545 for (auto& ssm : m.Data())
546 out += String(toString(ssm.Get(var).type)) + ' ';
547 }
548 }
549
550 if (out.size()) out.pop_back();
551
552 return out;
553}
554
556 if (s.nelem() == 0) return {};
557
558 const auto& names = enumstrs::VariableNames;
559
560 std::istringstream str(s);
561 String part;
562 Variable var = Variable::ETA;
563 TemperatureModel tm = TemperatureModel::None;
564 Index i = -100000;
565
566 std::vector<SingleSpeciesModel> ssms(0);
567 while (not str.eof()) {
568 str >> part;
569 if (std::any_of(names.cbegin(), names.cend(), [part](auto x) {
570 return part == x;
571 })) {
572 i = -1;
573 var = toVariable(part);
574 } else {
575 i++;
576 tm = toTemperatureModel(part);
577 }
578
579 if (i < 0) continue;
580 if (i < Index(ssms.size()))
581 goto add_var;
582 else {
583 ssms.emplace_back();
584 add_var:
585 auto mp = ssms[i].Get(var);
586 mp.type = tm;
587 ssms[i].Set(var, mp);
588 }
589 }
590
591 return Model(ssms);
592}
593
595 std::ostringstream os;
596 switch (mp.type) {
597 case TemperatureModel::None:
598 os << 0;
599 break;
600 case TemperatureModel::T0:
601 os << mp.X0;
602 break;
603 case TemperatureModel::T1:
604 os << mp.X0 << " * (" << T0 << "/T)^" << mp.X1;
605 break;
606 case TemperatureModel::T2:
607 os << mp.X0 << " * (" << T0 << "/T)^" << mp.X1 << " / (1 + " << mp.X2
608 << " * log(T/" << T0 << "))";
609 break;
610 case TemperatureModel::T3:
611 os << mp.X0 << " + " << mp.X1 << " * (" << T0 << " - T)";
612 break;
613 case TemperatureModel::T4:
614 os << "(" << mp.X0 << " + " << mp.X1 << " * (" << T0 << "/T - 1)) * ("
615 << T0 << "/T)^" << mp.X2;
616 break;
617 case TemperatureModel::T5:
618 os << mp.X0 << " * (" << T0 << "/T)^(0.25 + 1.5 * " << mp.X1 << ")";
619 break;
620 case TemperatureModel::LM_AER:
621 os << '('
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 << ']'
624 << ')';
625 break;
626 case TemperatureModel::DPL:
627 os << '(' << mp.X0 << " * (" << T0 << "/T)^" << mp.X1 << " + " << mp.X2
628 << " * (" << T0 << "/T)^" << mp.X3 << ')';
629 break;
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:
634 break;
635 }
636
637 return os.str();
638}
639
641 const bool self,
642 const ArrayOfSpecies& sts,
643 const Numeric T0) {
644 const auto& vars = enumtyps::VariableTypes;
645 ArrayOfString as(0);
646
647 for (Index i = 0; i < Index(Variable::FINAL); i++) {
648 Variable var = vars[i];
649
650 if (std::any_of(m.Data().cbegin(), m.Data().cend(), [var](auto& x) {
651 return x.Get(var).type not_eq TemperatureModel::None;
652 })) {
653 std::ostringstream os;
654 os << var << " ~ ";
655 for (Index j = 0; j < sts.nelem(); j++) {
656 if (j == 0 and self)
657 os << "VMR(" << self_broadening << ") * "
658 << modelparameters2metadata(m.Data().front().Get(var), T0);
659 else
660 os << "VMR(" << toShortName(sts[j]) << ") * "
661 << modelparameters2metadata(m.Data()[j].Get(var), T0);
662
663 if (sts[j] not_eq sts.back()) os << " + ";
664 }
665 as.push_back(os.str());
666 }
667 }
668
669 return as;
670}
671
672#pragma GCC diagnostic push
673#pragma GCC diagnostic ignored "-Wreturn-type"
674Numeric& SingleModelParameter(ModelParameters& mp, const String& type) {
675 if (type == "X0")
676 return mp.X0;
677 if (type == "X1")
678 return mp.X1;
679 if (type == "X2")
680 return mp.X2;
681 if (type == "X3")
682 return mp.X3;
684 "Type: ", type, ", is not accepted. "
685 "See documentation for accepted types\n")
686}
687#pragma GCC diagnostic pop
688
689std::ostream& operator<<(std::ostream& os, const ModelParameters& mp) {
690 os << mp.type << ' ' << mp.X0 << ' ' << mp.X1 << ' '
691 << mp.X2 << ' ' << mp.X3 << ' ';
692 return os;
693}
694
695std::istream& operator>>(std::istream& is, ModelParameters& mp) {
696 is >> mp.type >> double_imanip() >> mp.X0 >> mp.X1 >> mp.X2 >> mp.X3;
697 return is;
698}
699
700Numeric ModelParameters::at(Numeric T, Numeric T0) const noexcept {
701 using std::log;
702 using std::pow;
703
704 switch (type) {
705 case TemperatureModel::None:
706 return 0;
707 case TemperatureModel::T0:
708 return X0;
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: { /* Leave last */ }
726 }
727 return std::numeric_limits<Numeric>::quiet_NaN();
728}
729
730Numeric ModelParameters::dX0(Numeric T, Numeric T0) const noexcept {
731 using std::log;
732 using std::pow;
733
734 switch (type) {
735 case TemperatureModel::None:
736 return 0;
737 case TemperatureModel::T0:
738 return 1;
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:
744 return 1;
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:
754 return 1;
755 case TemperatureModel::FINAL: { /* Leave last */ }
756 }
757 return std::numeric_limits<Numeric>::quiet_NaN();
758}
759
760Numeric ModelParameters::dX1(Numeric T, Numeric T0) const noexcept {
761 using std::log;
762 using std::pow;
763
764 switch (type) {
765 case TemperatureModel::None:
766 return 0;
767 case TemperatureModel::T0:
768 return 0;
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:
774 return (T - T0);
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:
784 return T;
785 case TemperatureModel::FINAL: {/* Leave last */ }
786 }
787 return std::numeric_limits<Numeric>::quiet_NaN();
788}
789
790Numeric ModelParameters::dX2(Numeric T, Numeric T0) const noexcept {
791 using std::log;
792 using std::pow;
793
794 switch (type) {
795 case TemperatureModel::None:
796 return 0;
797 case TemperatureModel::T0:
798 return 0;
799 case TemperatureModel::T1:
800 return 0;
801 case TemperatureModel::T2:
802 return X0 * pow(T0 / T, X1) * log(T / T0);
803 case TemperatureModel::T3:
804 return 0;
805 case TemperatureModel::T4:
806 return pow(T0 / T, X2) * (X0 + X1 * (T0 / T - 1)) * log(T0 / T);
807 case TemperatureModel::T5:
808 return 0;
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:
814 return T * T;
815 case TemperatureModel::FINAL: {/* Leave last */ }
816 }
817 return std::numeric_limits<Numeric>::quiet_NaN();
818}
819
820Numeric ModelParameters::dX3(Numeric T, Numeric T0) const noexcept {
821 using std::log;
822 using std::pow;
823
824 switch (type) {
825 case TemperatureModel::None:
826 return 0;
827 case TemperatureModel::T0:
828 return 0;
829 case TemperatureModel::T1:
830 return 0;
831 case TemperatureModel::T2:
832 return 0;
833 case TemperatureModel::T3:
834 return 0;
835 case TemperatureModel::T4:
836 return 0;
837 case TemperatureModel::T5:
838 return 0;
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:
844 return T * T * T;
845 case TemperatureModel::FINAL: {/* Leave last */ }
846 }
847 return std::numeric_limits<Numeric>::quiet_NaN();
848}
849
850Numeric ModelParameters::dT(Numeric T, Numeric T0) const noexcept {
851 using std::log;
852 using std::pow;
853
854 switch (type) {
855 case TemperatureModel::None:
856 return 0;
857 case TemperatureModel::T0:
858 return 0;
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:
865 return X1;
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: {/* Leave last */ }
878 }
879 return std::numeric_limits<Numeric>::quiet_NaN();
880}
881
882Numeric ModelParameters::dT0(Numeric T, Numeric T0) const noexcept {
883 using std::log;
884 using std::pow;
885
886 switch (type) {
887 case TemperatureModel::None:
888 return 0;
889 case TemperatureModel::T0:
890 return 0;
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:
897 return -X1;
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:
904 return 0;
905 case TemperatureModel::DPL:
906 return X0 * X1 * pow(T0 / T, X1) / T0 + X2 * X3 * pow(T0 / T, X3) / T0;
907 case TemperatureModel::POLY:
908 return 0;
909 case TemperatureModel::FINAL: {/* Leave last */ }
910 }
911 return std::numeric_limits<Numeric>::quiet_NaN();
912}
913
915 for (auto& data: X) {
916 Index x;
917 bif >> x >> data.X0 >> data.X1 >> data.X2 >> data.X3;
918 data.type = TemperatureModel(x);
919 }
920 return bif;
921}
922
924 for (auto& data: X) {
925 bof << Index(data.type) << data.X0 << data.X1 << data.X2 << data.X3;
926 }
927 return bof;
928}
929
930Output SingleSpeciesModel::at(Numeric T, Numeric T0, Numeric P) const noexcept {
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)};
935}
936
937Numeric SingleSpeciesModel::dX(Numeric T, Numeric T0, Numeric P,
938 Jacobian::Line target) const noexcept {
939 static_assert(nVars == 9, "Only has support for 9 variables");
940 static_assert(ModelParameters::N == 4, "Only supports 4 targets per target");
941
942#define FourParams(A, B, p) \
943 case Shape##A##B: \
944 return p * A().d##B(T, T0)
945
946#define NineVars(A, p) \
947 FourParams(A, X0, p); \
948 FourParams(A, X1, p); \
949 FourParams(A, X2, p); \
950 FourParams(A, X3, p)
951
952 using enum Jacobian::Line;
953 switch (target) {
954 NineVars(G0, P);
955 NineVars(D0, P);
956 NineVars(G2, P);
957 NineVars(D2, P);
958 NineVars(FVC, P);
959 NineVars(ETA, 1);
960 NineVars(Y, P);
961 NineVars(G, P * P);
962 NineVars(DV, P * P);
963 default:
964 return std::numeric_limits<Numeric>::signaling_NaN();
965 }
966
967#undef NineVars
968#undef FourParams
969}
970
971Output SingleSpeciesModel::dT(Numeric T, Numeric T0, Numeric P) const noexcept {
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)};
976}
977
978Output SingleSpeciesModel::dT0(Numeric T, Numeric 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)};
984}
985
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()) \
990 \
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); \
995 }); \
996 }
997FUNC(G0, P)
998FUNC(D0, P)
999FUNC(G2, P)
1000FUNC(D2, P)
1001FUNC(ETA, 1)
1002FUNC(FVC, P)
1003FUNC(Y, P)
1004FUNC(G, P *P)
1005FUNC(DV, P *P)
1006#undef FUNC
1007
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()) \
1012 \
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); \
1017 }); \
1018 }
1019FUNC(G0, P)
1020FUNC(D0, P)
1021FUNC(G2, P)
1022FUNC(D2, P)
1023FUNC(ETA, 1)
1024FUNC(FVC, P)
1025FUNC(Y, P)
1026FUNC(G, P *P)
1027FUNC(DV, P *P)
1028#undef FUNC
1029
1030std::pair<bool, bool> SingleSpeciesModel::MatchTypes(const SingleSpeciesModel& other) const noexcept {
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;
1034 nullable = nullable and (modelparameterEmpty(other.X[i]) or modelparameterEmpty(X[i]) or other.X[i].type == X[i].type);
1035 }
1036 return {match, nullable};
1037}
1038
1039std::ostream& operator<<(std::ostream& os, const SingleSpeciesModel& ssm) {
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 << ' ';
1043 return os;
1044}
1045
1046std::istream& operator>>(std::istream& is, SingleSpeciesModel& ssm) {
1047 for (auto& mp : ssm.Data())
1048 if(mp.type not_eq TemperatureModel::None)
1049 is >> double_imanip() >> mp.X0 >> mp.X1 >> mp.X2 >> mp.X3;
1050 return is;
1051}
1052
1053std::ostream& operator<<(std::ostream& os, Output x) {
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;
1057}
1058
1059Model::Model(Numeric sgam,
1060 Numeric nself,
1061 Numeric agam,
1062 Numeric nair,
1063 Numeric psf,
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};
1067
1068 mdata.back().G0() = {TemperatureModel::T1, agam, nair, 0, 0};
1069 mdata.back().D0() = {TemperatureModel::T5, psf, nair, 0, 0};
1070
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];
1082
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];
1093 }
1094}
1095
1096Model hitran_model(Numeric sgam,
1097 Numeric nself,
1098 Numeric agam,
1099 Numeric nair,
1100 Numeric psf) {
1101 Model m(2);
1102
1103 m.Data().front().G0() = {TemperatureModel::T1, sgam, nself, 0, 0};
1104 m.Data().front().D0() = {TemperatureModel::T0, psf, 0, 0, 0};
1105
1106 m.Data().back().G0() = {TemperatureModel::T1, agam, nair, 0, 0};
1107 m.Data().back().D0() = {TemperatureModel::T0, psf, 0, 0, 0};
1108
1109 return m;
1110}
1111
1112Model lblrtm_model(Numeric sgam,
1113 Numeric nself,
1114 Numeric agam,
1115 Numeric nair,
1116 Numeric psf,
1117 std::array<Numeric, 12> aer_interp) {
1118 Model m(2);
1119
1120 m.Data().front().G0() = {TemperatureModel::T1, sgam, nself, 0, 0};
1121 m.Data().front().D0() = {TemperatureModel::T0, psf, 0, 0, 0};
1122
1123 m.Data().back().G0() = {TemperatureModel::T1, agam, nair, 0, 0};
1124 m.Data().back().D0() = {TemperatureModel::T0, psf, 0, 0, 0};
1125
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];
1137
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];
1148 }
1149
1150 return m;
1151}
1152
1153bool Model::OK(Type type, bool self, bool bath,
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));
1159}
1160
1161void Model::Remove(Index i, ArrayOfSpeciesTag& specs) {
1162 mdata.erase(mdata.begin() + i);
1163 specs.erase(specs.begin() + i);
1164}
1165
1166void Model::Remove(Index i, ArrayOfSpecies& specs) {
1167 mdata.erase(mdata.begin() + i);
1168 specs.erase(specs.begin() + i);
1169}
1170
1172 for (auto& ssm : mdata) {
1173 ssm.Y() = x.Y();
1174 ssm.G() = x.G();
1175 ssm.DV() = x.DV();
1176 }
1177}
1178
1179std::pair<bool, bool> Model::Match(const Model& other) const noexcept {
1180 const Index n = nelem();
1181 if (other.nelem() not_eq n) return {false, false};
1182
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;
1188 }
1189
1190 return {match, nullable};
1191}
1192
1194 for (auto& data: mdata)
1195 data.read(bif);
1196 return bif;
1197}
1198
1200 for (auto& data: mdata)
1201 data.write(bof);
1202 return bof;
1203}
1204
1205namespace LegacyLineFunctionData {
1206std::vector<Variable> lineshapetag2variablesvector(String type) {
1207 if (type == String("DP"))
1208 return {};
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,
1217 Variable::D0,
1218 Variable::G2,
1219 Variable::D2,
1220 Variable::FVC,
1221 Variable::ETA};
1223 "Type: ", type, ", is not accepted. "
1224 "See documentation for accepted types\n")
1225}
1226
1227std::vector<Variable> linemixingtag2variablesvector(String type) {
1228 if (type == "#")
1229 return {};
1230 if (type == "LM1")
1231 return {Variable::Y};
1232 if (type == "LM2")
1233 return {Variable::Y, Variable::G, Variable::DV};
1234 if (type == "INT")
1235 return {};
1236 if (type == "ConstG")
1237 return {Variable::G};
1239 "Type: ", type, ", is not accepted. "
1240 "See documentation for accepted types\n")
1241}
1242} // namespace LegacyLineFunctionData
1243
1244namespace LegacyLineMixingData {
1246 if (type == "NA") // The standard case
1247 return TypeLM::LM_NONE;
1248 if (type == "LL") // The LBLRTM case
1249 return TypeLM::LM_LBLRTM;
1250 if (type == "NR") // The LBLRTM O2 non-resonant case
1252 if (type == "L2") // The 2nd order case
1253 return TypeLM::LM_2NDORDER;
1254 if (type == "L1") // The 2nd order case
1255 return TypeLM::LM_1STORDER;
1256 if (type == "BB") // The band class
1257 return TypeLM::LM_BYBAND;
1259 "Type: ", type, ", is not accepted. "
1260 "See documentation for accepted types\n")
1261}
1262} // namespace LegacyLineMixingData
1263
1264
1265namespace LegacyPressureBroadeningData {
1267 if (type == "NA") // The none case
1268 return TypePB::PB_NONE;
1269 if (type == "N2") // Air Broadening is N2 broadening mostly...
1271 if (type == "WA") // Water and Air Broadening
1273 if (type == "AP") // Planetary broadening
1276 "Type: ", type, ", is not accepted. "
1277 "See documentation for accepted types\n")
1278}
1279
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")))
1289 return true;
1290 if (t == TypePB::PB_AIR_AND_WATER_BROADENING and qid.Species() == Species::fromShortName("H2O"))
1291 return true;
1292 return false;
1293}
1294} // namespace LegacyPressureBroadeningData
1295} // namespace LineShape
Common ARTS conversions.
Index nelem() const ARTS_NOEXCEPT
Definition array.h:75
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.
Definition bifstream.h:26
Binary output file stream class.
Definition bofstream.h:25
Input manipulator class for doubles to enable nan and inf parsing.
Index nelem() const
Definition mystring.h:172
Helper macros for debugging.
#define ARTS_NOEXCEPT
Definition debug.h:83
#define ARTS_ASSERT(condition,...)
Definition debug.h:86
#define ARTS_USER_ERROR(...)
Definition debug.h:153
#define ARTS_USER_ERROR_IF(condition,...)
Definition debug.h:137
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...
Definition enums.h:90
constexpr bool good_enum(EnumType x) noexcept
Checks if the enum number is good.
Definition enums.h:21
Array< Species::Species > ArrayOfSpecies
#define ReturnJacPropMatType(ID)
#define NineVars(A, p)
#define FUNC(X, PVAR)
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.
Definition mystring.h:199
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.
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.
Computations of line shape derived parameters.
Definition lineshape.cc:27
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
static constexpr Index N
Numeric dX2(Numeric T, Numeric T0) const noexcept
Main output of Model.
A logical struct for global quantum numbers with species identifiers.
Species::Species Species() const noexcept
Species::IsotopeRecord Isotopologue() const noexcept
#define v