ARTS 2.5.10 (git: 2f1c442c)
lineshapemodel.cc
Go to the documentation of this file.
1/* Copyright (C) 2018
2 Richard Larsson <ric.larsson@gmail.com>
3
4
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option) any
8 later version.
9
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 USA. */
21
35#include "arts_conversions.h"
36#include "debug.h"
37#include "lineshapemodel.h"
38#include "matpackI.h"
39#include <limits>
40
41Jacobian::Line select_derivativeLineShape(const String& var,
42 const String& coeff) {
43 // Test viability of model variables
44 const auto var_type = LineShape::toVariableOrThrow(var);
45
46 // Test viability of model coefficients
47 const auto coeff_type = Options::toLineShapeCoeffOrThrow(coeff);
48
49// Define a repetitive pattern. Update if/when there are more coefficients in the future
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; \
63 } break
64
65 switch (var_type) {
75 case LineShape::Variable::FINAL: {
76 /* Leave last */ }
77 }
78
79#undef ReturnJacPropMatType
80
81 return Jacobian::Line::FINAL;
82}
83
84std::istream& LineShape::from_artscat4(std::istream& is,
85 Type& mtype,
86 bool& self,
87 bool& bath,
88 Model& m,
89 ArrayOfSpecies& species,
90 const QuantumIdentifier& qid) {
91 // Set or reset variables
92 mtype = Type::VP;
93 self = true;
94 bath = false;
95 m.mdata = std::vector<SingleSpeciesModel>(7);
96 species = ArrayOfSpecies(7);
97
98 // Set species
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");
105
106 // Temperature types
107 for (auto& v : m.mdata) {
108 v.G0().type = TemperatureModel::T1;
109 v.D0().type = TemperatureModel::T5;
110 }
111
112 // G0 main coefficient
113 for (auto& v : m.mdata) is >> double_imanip() >> v.G0().X0;
114
115 // G0 exponent is same as D0 exponent
116 for (auto& v : m.mdata) {
117 is >> double_imanip() >> v.G0().X1;
118 v.D0().X1 = v.G0().X1;
119 }
120
121 // D0 coefficient
122 m.mdata.front().D0().X0 = 0;
123 for (int k = 1; k < 7; k++)
124 is >> double_imanip() >> m.mdata[k].D0().X0;
125
126 // Special case when self is part of this list, it needs to be removed
127 for (int k = 1; k < 7; k++) {
128 if (qid.Species() == species[k]) {
129 ARTS_USER_ERROR_IF(m.mdata.front().G0().X0 not_eq m.mdata[k].G0().X0 or
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 "
134 "in input string\n")
135 m.mdata.front().D0().X0 = m.mdata[k].D0().X0;
136 m.Remove(k, species);
137 break;
138 }
139 }
140
141 return is;
142}
143
144std::istream& LineShape::from_linefunctiondata(std::istream& data,
145 Type& mtype,
146 bool& self,
147 bool& bath,
148 Model& m,
149 ArrayOfSpecies& species) {
150 self = bath = false;
151 Index specs;
152 String s;
153
154 // The first tag should give the line shape scheme
155 data >> mtype;
156 check_enum_error(mtype, "Bad Data");
157
158 // Order of elements for line shape
159 const auto shapeparams =
160 LegacyLineFunctionData::lineshapetag2variablesvector(toString(mtype));
161
162 // The second tag should give the line mixing scheme
163 data >> s;
164
165 // Order of elements for line mixing
166 const auto mixingparams =
167 LegacyLineFunctionData::linemixingtag2variablesvector(s);
168
169 // The third tag should contain the number of species
170 data >> specs;
171 species.resize(specs);
172 m.mdata.resize(specs);
173
174 ARTS_USER_ERROR_IF (not specs and mtype not_eq Type::DP,
175 "Need at least one species for non-Doppler line shapes");
176
177 // For all species, we need to set the methods to compute them
178 for (Index i = 0; i < specs; i++) {
179 // This should be a species tag or one of the specials, SELF or BATH
180 data >> s;
181 if (s == self_broadening) {
182 // If the species is self, then we need to flag this
183 self = true;
184 ARTS_USER_ERROR_IF (i not_eq 0,
185 "Self broadening must be first, it is not\n");
186 } else if (s == bath_broadening) {
187 // If the species is air, then we need to flag this
188 bath = true;
189 species[i] = Species::Species::Bath;
190 ARTS_USER_ERROR_IF (i not_eq specs - 1,
191 "Air/bath broadening must be last, it is not\n");
192 } else {
193 // Otherwise, we hope we find a species
194 species[i] = Species::fromShortName(s);
195 ARTS_USER_ERROR_IF (not good_enum(species[i]),
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")
199 }
200
201 // For all parameters
202 for (auto& params : {shapeparams, mixingparams}) {
203 for (auto& param : params) {
204 data >> s; // Should contain a temperature tag
205
206 const auto type = toTemperatureModel(s);
207 const Index ntemp =
208 LegacyLineFunctionData::temperaturemodel2legacynelem(type);
209
210 m.mdata[i].Data()[Index(param)].type = type;
211 if (ntemp <= ModelParameters::N) {
212 switch (ntemp) {
213 case 1:
214 data >> double_imanip() >> m.mdata[i].Data()[Index(param)].X0;
215 break;
216 case 2:
217 data >> double_imanip() >> m.mdata[i].Data()[Index(param)].X0 >>
218 m.mdata[i].Data()[Index(param)].X1;
219 break;
220 case 3:
221 data >> double_imanip() >> m.mdata[i].Data()[Index(param)].X0 >>
222 m.mdata[i].Data()[Index(param)].X1 >>
223 m.mdata[i].Data()[Index(param)].X2;
224 break;
225 case 0:
226 break;
227 default:
229 "Unknown number of input parameters in Legacy mode.");
230 }
231 } else { // Has to be the only allowed interpolation case
232 ARTS_USER_ERROR_IF (ntemp > 12,
233 "Too many input parameters in interpolation results Legacy mode.");
234 Numeric temp;
235 data >> double_imanip() >> temp; // should be 200
236 data >> double_imanip() >> temp; // should be 250
237 data >> double_imanip() >> temp; // should be 296
238 data >> double_imanip() >> temp; // should be 340
239 data >> double_imanip() >> m.mdata[i].Y().X0 >> m.mdata[i].Y().X1 >> m.mdata[i].Y().X2 >> m.mdata[i].Y().X3
240 >> m.mdata[i].G().X0 >> m.mdata[i].G().X1 >> m.mdata[i].G().X2 >> m.mdata[i].G().X3;
241 }
242 }
243 }
244 }
245
246 return data;
247}
248
250 std::istream& data,
251 LineShape::Type& mtype,
252 bool& self,
253 bool& bath,
254 Model& m,
255 ArrayOfSpecies& species,
256 const QuantumIdentifier& qid) {
257 String s;
258 data >> s;
259
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);
263
264 Vector x(n);
265 for (auto& num : x) data >> double_imanip() >> num;
266
267 LegacyPressureBroadeningData::vector2modelpb(mtype,
268 self,
269 bath,
270 m,
271 species,
272 x,
273 type,
274 self_in_list,
275 qid.Species());
276
277 return data;
278}
279
280std::istream& LineShape::from_linemixingdata(std::istream& data,
281 LineShape::Model& lsc) {
282 String s;
283 data >> s;
284
285 const auto type = LegacyLineMixingData::string2typelm(s);
286 const auto n = LegacyLineMixingData::typelm2nelem(type);
287
288 Vector x(n);
289 for (auto& num : x) data >> double_imanip() >> num;
290
291 lsc = LegacyLineMixingData::vector2modellm(x, type);
292
293 return data;
294}
295
296#pragma GCC diagnostic push
297#pragma GCC diagnostic ignored "-Wreturn-type"
299 LineShape::Type& mtype,
300 bool& self,
301 bool& bath,
302 Model& m,
303 ArrayOfSpecies& species,
304 Vector x,
306 bool self_in_list,
307 Species::Species self_spec) {
308 switch (type) {
309 case TypePB::PB_NONE:
310 mtype = LineShape::Type::DP;
311 self = bath = false;
312 m = Model();
313 species.resize(0);
314 return;
315 case TypePB::PB_AIR_BROADENING:
316 mtype = LineShape::Type::VP;
317 self = bath = true;
318 m = Model(x[0], x[1], x[2], x[3], x[4]);
319 species.resize(2);
320 species[0] = self_spec;
321 species[1] = Species::Species::Bath;
322 return;
323 case TypePB::PB_AIR_AND_WATER_BROADENING:
324 if (self_in_list) {
325 mtype = LineShape::Type::VP;
326 self = false;
327 bath = true;
328 m.Data().resize(2);
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};
333 species.resize(2);
334 species[0] = Species::fromShortName("H2O");
335 species[1] = Species::Species::Bath;
336 return;
337 } else {
338 mtype = LineShape::Type::VP;
339 self = bath = true;
340 m.Data().resize(2);
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};
347 species.resize(3);
348 species[0] = self_spec;
349 species[1] = Species::fromShortName("H2O");
350 species[2] = Species::Species::Bath;
351 return;
352 }
353 case TypePB::PB_PLANETARY_BROADENING:
354 if (self_in_list) {
355 mtype = LineShape::Type::VP;
356 self = bath = false;
357 m.Data().resize(6);
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")};
376 return;
377 } else {
378 mtype = LineShape::Type::VP;
379 self = true;
380 bath = false;
381 m.Data().resize(7);
382 m.Data()[0].G0() = {TemperatureModel::T1, x[0], x[7], 0, 0};
383 // ssm[0].D0() = ...
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};
396 species.resize(7);
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");
404 return;
405 }
406 }
407}
408#pragma GCC diagnostic pop
409
412 Model y(1);
413 switch (type) {
414 case TypeLM::LM_NONE:
415 break;
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];
427 break;
428 case TypeLM::LM_LBLRTM_O2NonResonant:
429 y.Data().front().G().type = LineShape::TemperatureModel::T0;
430 y.Data().front().G().X0 = x[0];
431 break;
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];
445 break;
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];
450 break;
451 case TypeLM::LM_BYBAND:
452 break;
453 }
454 return y;
455}
456
457
458Vector LineShape::vmrs(const ConstVectorView& atmospheric_vmrs,
459 const ArrayOfArrayOfSpeciesTag& atmospheric_species,
460 const ArrayOfSpecies& lineshape_species) ARTS_NOEXCEPT {
461 ARTS_ASSERT (atmospheric_species.nelem() == atmospheric_vmrs.nelem(), "Bad atmospheric inputs");
462
463 const Index n = lineshape_species.nelem();
464
465 // Initialize list of VMRS to 0
466 Vector line_vmrs(n, 0);
467
468 // We need to know if bath is an actual species
469 const bool bath = n and lineshape_species.back() == Species::Species::Bath;
470
471 // Loop species
472 for (Index i = 0; i < n - bath; i++) {
473 const Species::Species target = lineshape_species[i];
474
475 // Find species in list or do nothing at all
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;
480 }
481 }
482
483 // Set to non-zero in-case species exists
484 if (this_species_index not_eq -1) {
485 line_vmrs[i] = atmospheric_vmrs[this_species_index];
486 }
487 }
488
489 // Renormalize, if bath-species exist this is automatic.
490 if (bath) {
491 line_vmrs[n - 1] = 1.0 - line_vmrs.sum();
492 } else if(line_vmrs.sum() == 0) { // Special case
493 } else {
494 line_vmrs /= line_vmrs.sum();
495 }
496
497 return line_vmrs;
498}
499
500Vector LineShape::mass(const ConstVectorView& atmospheric_vmrs,
501 const ArrayOfArrayOfSpeciesTag& atmospheric_species,
502 const ArrayOfSpecies& lineshape_species,
504 ARTS_ASSERT (atmospheric_species.nelem() == atmospheric_vmrs.nelem(),
505 "Bad atmospheric inputs");
506
507 const Index n = lineshape_species.nelem();
508
509 // Initialize list of VMRS to 0
510 Vector line_vmrs(n, 0);
511 Vector line_mass(n, 0);
512
513 // We need to know if bath is an actual species
514 const bool bath = n and lineshape_species.back() == Species::Species::Bath;
515
516 // Loop species ignoring self and bath
517 for (Index i = 0; i < n - bath; i++) {
518 // Select target in-case this is self-broadening
519 const Species::Species target = lineshape_species[i];
520
521 // Find species in list or do nothing at all
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;
526 }
527 }
528
529 // Set to non-zero in-case species exists
530 if (this_species_index not_eq -1) {
531 line_vmrs[i] = atmospheric_vmrs[this_species_index];
532 line_mass[i] = Species::mean_mass(target, ir);
533 }
534 }
535
536 // Renormalize, if bath-species exist this is automatic.
537 if(line_vmrs.sum() == 0) { // Special case
538 } else if (bath) {
539 line_mass[n - 1] = (line_vmrs * line_mass) / line_vmrs.sum();
540 }
541
542 return line_mass;
543}
544
545namespace LineShape {
546std::ostream& operator<<(std::ostream& os, const Model& m) {
547 for (auto& data : m.Data()) os << data;
548 return os;
549}
550
551std::istream& operator>>(std::istream& is, Model& m) {
552 for (auto& data : m.Data()) is >> data;
553 return is;
554}
555
557 String out = "";
558 const auto& vars = enumtyps::VariableTypes;
559
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;
563 })) {
564 out += String(toString(var)) + ' ';
565 for (auto& ssm : m.Data())
566 out += String(toString(ssm.Get(var).type)) + ' ';
567 }
568 }
569
570 if (out.size()) out.pop_back();
571
572 return out;
573}
574
576 if (s.nelem() == 0) return {};
577
578 const auto& names = enumstrs::VariableNames;
579
580 std::istringstream str(s);
581 String part;
582 Variable var = Variable::ETA;
583 TemperatureModel tm = TemperatureModel::None;
584 Index i = -100000;
585
586 std::vector<SingleSpeciesModel> ssms(0);
587 while (not str.eof()) {
588 str >> part;
589 if (std::any_of(names.cbegin(), names.cend(), [part](auto x) {
590 return part == x;
591 })) {
592 i = -1;
593 var = toVariable(part);
594 } else {
595 i++;
596 tm = toTemperatureModel(part);
597 }
598
599 if (i < 0) continue;
600 if (i < Index(ssms.size()))
601 goto add_var;
602 else {
603 ssms.emplace_back();
604 add_var:
605 auto mp = ssms[i].Get(var);
606 mp.type = tm;
607 ssms[i].Set(var, mp);
608 }
609 }
610
611 return Model(ssms);
612}
613
615 std::ostringstream os;
616 switch (mp.type) {
617 case TemperatureModel::None:
618 os << 0;
619 break;
620 case TemperatureModel::T0:
621 os << mp.X0;
622 break;
623 case TemperatureModel::T1:
624 os << mp.X0 << " * (" << T0 << "/T)^" << mp.X1;
625 break;
626 case TemperatureModel::T2:
627 os << mp.X0 << " * (" << T0 << "/T)^" << mp.X1 << " / (1 + " << mp.X2
628 << " * log(T/" << T0 << "))";
629 break;
630 case TemperatureModel::T3:
631 os << mp.X0 << " + " << mp.X1 << " * (" << T0 << " - T)";
632 break;
633 case TemperatureModel::T4:
634 os << "(" << mp.X0 << " + " << mp.X1 << " * (" << T0 << "/T - 1)) * ("
635 << T0 << "/T)^" << mp.X2;
636 break;
637 case TemperatureModel::T5:
638 os << mp.X0 << " * (" << T0 << "/T)^(0.25 + 1.5 * " << mp.X1 << ")";
639 break;
640 case TemperatureModel::LM_AER:
641 os << '('
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 << ']'
644 << ')';
645 break;
646 case TemperatureModel::DPL:
647 os << '(' << mp.X0 << " * (" << T0 << "/T)^" << mp.X1 << " + " << mp.X2
648 << " * (" << T0 << "/T)^" << mp.X3 << ')';
649 break;
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:
654 break;
655 }
656
657 return os.str();
658}
659
661 const bool self,
662 const ArrayOfSpecies& sts,
663 const Numeric T0) {
664 const auto& vars = enumtyps::VariableTypes;
665 ArrayOfString as(0);
666
667 for (Index i = 0; i < Index(Variable::FINAL); i++) {
668 Variable var = vars[i];
669
670 if (std::any_of(m.Data().cbegin(), m.Data().cend(), [var](auto& x) {
671 return x.Get(var).type not_eq TemperatureModel::None;
672 })) {
673 std::ostringstream os;
674 os << var << " ~ ";
675 for (Index j = 0; j < sts.nelem(); j++) {
676 if (j == 0 and self)
677 os << "VMR(" << self_broadening << ") * "
678 << modelparameters2metadata(m.Data().front().Get(var), T0);
679 else
680 os << "VMR(" << toShortName(sts[j]) << ") * "
681 << modelparameters2metadata(m.Data()[j].Get(var), T0);
682
683 if (sts[j] not_eq sts.back()) os << " + ";
684 }
685 as.push_back(os.str());
686 }
687 }
688
689 return as;
690}
691
692#pragma GCC diagnostic push
693#pragma GCC diagnostic ignored "-Wreturn-type"
695 if (type == "X0")
696 return mp.X0;
697 if (type == "X1")
698 return mp.X1;
699 if (type == "X2")
700 return mp.X2;
701 if (type == "X3")
702 return mp.X3;
704 "Type: ", type, ", is not accepted. "
705 "See documentation for accepted types\n")
706}
707#pragma GCC diagnostic pop
708
709std::ostream& operator<<(std::ostream& os, const ModelParameters& mp) {
710 os << mp.type << ' ' << mp.X0 << ' ' << mp.X1 << ' '
711 << mp.X2 << ' ' << mp.X3 << ' ';
712 return os;
713}
714
715std::istream& operator>>(std::istream& is, ModelParameters& mp) {
716 is >> mp.type >> double_imanip() >> mp.X0 >> mp.X1 >> mp.X2 >> mp.X3;
717 return is;
718}
719
721 using std::log;
722 using std::pow;
723
724 switch (type) {
725 case TemperatureModel::None:
726 return 0;
727 case TemperatureModel::T0:
728 return X0;
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: { /* Leave last */ }
746 }
747 return std::numeric_limits<Numeric>::quiet_NaN();
748}
749
751 using std::log;
752 using std::pow;
753
754 switch (type) {
755 case TemperatureModel::None:
756 return 0;
757 case TemperatureModel::T0:
758 return 1;
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:
764 return 1;
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:
774 return 1;
775 case TemperatureModel::FINAL: { /* Leave last */ }
776 }
777 return std::numeric_limits<Numeric>::quiet_NaN();
778}
779
781 using std::log;
782 using std::pow;
783
784 switch (type) {
785 case TemperatureModel::None:
786 return 0;
787 case TemperatureModel::T0:
788 return 0;
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:
794 return (T - T0);
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:
804 return T;
805 case TemperatureModel::FINAL: {/* Leave last */ }
806 }
807 return std::numeric_limits<Numeric>::quiet_NaN();
808}
809
811 using std::log;
812 using std::pow;
813
814 switch (type) {
815 case TemperatureModel::None:
816 return 0;
817 case TemperatureModel::T0:
818 return 0;
819 case TemperatureModel::T1:
820 return 0;
821 case TemperatureModel::T2:
822 return X0 * pow(T0 / T, X1) * log(T / T0);
823 case TemperatureModel::T3:
824 return 0;
825 case TemperatureModel::T4:
826 return pow(T0 / T, X2) * (X0 + X1 * (T0 / T - 1)) * log(T0 / T);
827 case TemperatureModel::T5:
828 return 0;
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:
834 return T * T;
835 case TemperatureModel::FINAL: {/* Leave last */ }
836 }
837 return std::numeric_limits<Numeric>::quiet_NaN();
838}
839
841 using std::log;
842 using std::pow;
843
844 switch (type) {
845 case TemperatureModel::None:
846 return 0;
847 case TemperatureModel::T0:
848 return 0;
849 case TemperatureModel::T1:
850 return 0;
851 case TemperatureModel::T2:
852 return 0;
853 case TemperatureModel::T3:
854 return 0;
855 case TemperatureModel::T4:
856 return 0;
857 case TemperatureModel::T5:
858 return 0;
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:
864 return T * T * T;
865 case TemperatureModel::FINAL: {/* Leave last */ }
866 }
867 return std::numeric_limits<Numeric>::quiet_NaN();
868}
869
871 using std::log;
872 using std::pow;
873
874 switch (type) {
875 case TemperatureModel::None:
876 return 0;
877 case TemperatureModel::T0:
878 return 0;
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:
885 return X1;
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: {/* Leave last */ }
898 }
899 return std::numeric_limits<Numeric>::quiet_NaN();
900}
901
903 using std::log;
904 using std::pow;
905
906 switch (type) {
907 case TemperatureModel::None:
908 return 0;
909 case TemperatureModel::T0:
910 return 0;
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:
917 return -X1;
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:
924 return 0;
925 case TemperatureModel::DPL:
926 return X0 * X1 * pow(T0 / T, X1) / T0 + X2 * X3 * pow(T0 / T, X3) / T0;
927 case TemperatureModel::POLY:
928 return 0;
929 case TemperatureModel::FINAL: {/* Leave last */ }
930 }
931 return std::numeric_limits<Numeric>::quiet_NaN();
932}
933
935 for (auto& data: X) {
936 Index x;
937 bif >> x >> data.X0 >> data.X1 >> data.X2 >> data.X3;
938 data.type = TemperatureModel(x);
939 }
940 return bif;
941}
942
944 for (auto& data: X) {
945 bof << Index(data.type) << data.X0 << data.X1 << data.X2 << data.X3;
946 }
947 return bof;
948}
949
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)};
955}
956
958 Jacobian::Line target) const noexcept {
959 static_assert(nVars == 9, "Only has support for 9 variables");
960 static_assert(ModelParameters::N == 4, "Only supports 4 targets per target");
961
962#define FourParams(A, B, p) \
963 case Shape##A##B: \
964 return p * A().d##B(T, T0)
965
966#define NineVars(A, p) \
967 FourParams(A, X0, p); \
968 FourParams(A, X1, p); \
969 FourParams(A, X2, p); \
970 FourParams(A, X3, p)
971
972 using enum Jacobian::Line;
973 switch (target) {
974 NineVars(G0, P);
975 NineVars(D0, P);
976 NineVars(G2, P);
977 NineVars(D2, P);
978 NineVars(FVC, P);
979 NineVars(ETA, 1);
980 NineVars(Y, P);
981 NineVars(G, P * P);
982 NineVars(DV, P * P);
983 default:
984 return std::numeric_limits<Numeric>::signaling_NaN();
985 }
986
987#undef NineVars
988#undef FourParams
989}
990
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)};
996}
997
999 Numeric P) const noexcept {
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)};
1004}
1005
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()) \
1010 \
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); \
1015 }); \
1016 }
1017FUNC(G0, P)
1018FUNC(D0, P)
1019FUNC(G2, P)
1020FUNC(D2, P)
1021FUNC(ETA, 1)
1022FUNC(FVC, P)
1023FUNC(Y, P)
1024FUNC(G, P *P)
1025FUNC(DV, P *P)
1026#undef FUNC
1027
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()) \
1032 \
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); \
1037 }); \
1038 }
1039FUNC(G0, P)
1040FUNC(D0, P)
1041FUNC(G2, P)
1042FUNC(D2, P)
1043FUNC(ETA, 1)
1044FUNC(FVC, P)
1045FUNC(Y, P)
1046FUNC(G, P *P)
1047FUNC(DV, P *P)
1048#undef FUNC
1049
1050std::pair<bool, bool> SingleSpeciesModel::MatchTypes(const SingleSpeciesModel& other) const noexcept {
1051 bool match=true, nullable=true;
1052 for (Index i=0; i<nVars; i++) {
1053 match = match and other.X[i].type == X[i].type;
1054 nullable = nullable and (modelparameterEmpty(other.X[i]) or modelparameterEmpty(X[i]) or other.X[i].type == X[i].type);
1055 }
1056 return {match, nullable};
1057}
1058
1059std::ostream& operator<<(std::ostream& os, const SingleSpeciesModel& ssm) {
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 << ' ';
1063 return os;
1064}
1065
1066std::istream& operator>>(std::istream& is, SingleSpeciesModel& ssm) {
1067 for (auto& mp : ssm.Data())
1068 if(mp.type not_eq TemperatureModel::None)
1069 is >> double_imanip() >> mp.X0 >> mp.X1 >> mp.X2 >> mp.X3;
1070 return is;
1071}
1072
1073std::ostream& operator<<(std::ostream& os, Output x) {
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;
1077}
1078
1080 Numeric nself,
1081 Numeric agam,
1082 Numeric nair,
1083 Numeric psf,
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};
1087
1088 mdata.back().G0() = {TemperatureModel::T1, agam, nair, 0, 0};
1089 mdata.back().D0() = {TemperatureModel::T5, psf, nair, 0, 0};
1090
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];
1102
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];
1113 }
1114}
1115
1117 Numeric nself,
1118 Numeric agam,
1119 Numeric nair,
1120 Numeric psf) {
1121 Model m(2);
1122
1123 m.Data().front().G0() = {TemperatureModel::T1, sgam, nself, 0, 0};
1124 m.Data().front().D0() = {TemperatureModel::T0, psf, 0, 0, 0};
1125
1126 m.Data().back().G0() = {TemperatureModel::T1, agam, nair, 0, 0};
1127 m.Data().back().D0() = {TemperatureModel::T0, psf, 0, 0, 0};
1128
1129 return m;
1130}
1131
1133 Numeric nself,
1134 Numeric agam,
1135 Numeric nair,
1136 Numeric psf,
1137 std::array<Numeric, 12> aer_interp) {
1138 Model m(2);
1139
1140 m.Data().front().G0() = {TemperatureModel::T1, sgam, nself, 0, 0};
1141 m.Data().front().D0() = {TemperatureModel::T0, psf, 0, 0, 0};
1142
1143 m.Data().back().G0() = {TemperatureModel::T1, agam, nair, 0, 0};
1144 m.Data().back().D0() = {TemperatureModel::T0, psf, 0, 0, 0};
1145
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];
1157
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];
1168 }
1169
1170 return m;
1171}
1172
1173bool Model::OK(Type type, bool self, bool bath,
1174 const std::size_t nspecies) const noexcept {
1175 Index n = mdata.size();
1176 Index m = Index(self) + Index(bath);
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));
1179}
1180
1182 mdata.erase(mdata.begin() + i);
1183 specs.erase(specs.begin() + i);
1184}
1185
1187 mdata.erase(mdata.begin() + i);
1188 specs.erase(specs.begin() + i);
1189}
1190
1192 for (auto& ssm : mdata) {
1193 ssm.Y() = x.Y();
1194 ssm.G() = x.G();
1195 ssm.DV() = x.DV();
1196 }
1197}
1198
1199std::pair<bool, bool> Model::Match(const Model& other) const noexcept {
1200 const Index n = nelem();
1201 if (other.nelem() not_eq n) return {false, false};
1202
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;
1208 }
1209
1210 return {match, nullable};
1211}
1212
1214 for (auto& data: mdata)
1215 data.read(bif);
1216 return bif;
1217}
1218
1220 for (auto& data: mdata)
1221 data.write(bof);
1222 return bof;
1223}
1224
1225namespace LegacyLineFunctionData {
1226std::vector<Variable> lineshapetag2variablesvector(String type) {
1227 if (type == String("DP"))
1228 return {};
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,
1237 Variable::D0,
1238 Variable::G2,
1239 Variable::D2,
1240 Variable::FVC,
1241 Variable::ETA};
1243 "Type: ", type, ", is not accepted. "
1244 "See documentation for accepted types\n")
1245}
1246
1247std::vector<Variable> linemixingtag2variablesvector(String type) {
1248 if (type == "#")
1249 return {};
1250 if (type == "LM1")
1251 return {Variable::Y};
1252 if (type == "LM2")
1253 return {Variable::Y, Variable::G, Variable::DV};
1254 if (type == "INT")
1255 return {};
1256 if (type == "ConstG")
1257 return {Variable::G};
1259 "Type: ", type, ", is not accepted. "
1260 "See documentation for accepted types\n")
1261}
1262} // namespace LegacyLineFunctionData
1263
1264namespace LegacyLineMixingData {
1266 if (type == "NA") // The standard case
1267 return TypeLM::LM_NONE;
1268 if (type == "LL") // The LBLRTM case
1269 return TypeLM::LM_LBLRTM;
1270 if (type == "NR") // The LBLRTM O2 non-resonant case
1272 if (type == "L2") // The 2nd order case
1273 return TypeLM::LM_2NDORDER;
1274 if (type == "L1") // The 2nd order case
1275 return TypeLM::LM_1STORDER;
1276 if (type == "BB") // The band class
1277 return TypeLM::LM_BYBAND;
1279 "Type: ", type, ", is not accepted. "
1280 "See documentation for accepted types\n")
1281}
1282} // namespace LegacyLineMixingData
1283
1284
1285namespace LegacyPressureBroadeningData {
1287 if (type == "NA") // The none case
1288 return TypePB::PB_NONE;
1289 if (type == "N2") // Air Broadening is N2 broadening mostly...
1291 if (type == "WA") // Water and Air Broadening
1293 if (type == "AP") // Planetary broadening
1296 "Type: ", type, ", is not accepted. "
1297 "See documentation for accepted types\n")
1298}
1299
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")))
1309 return true;
1310 if (t == TypePB::PB_AIR_AND_WATER_BROADENING and qid.Species() == Species::fromShortName("H2O"))
1311 return true;
1312 return false;
1313}
1314} // namespace LegacyPressureBroadeningData
1315} // namespace LineShape
Common ARTS conversions.
Index nelem() const ARTS_NOEXCEPT
Definition: array.h:92
A constant view of a Vector.
Definition: matpackI.h:521
Numeric sum() const ARTS_NOEXCEPT
The sum of all elements of a Vector.
Definition: matpackI.cc:48
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
The Vector class.
Definition: matpackI.h:910
Binary output file stream class.
Definition: bifstream.h:43
Binary output file stream class.
Definition: bofstream.h:42
Input manipulator class for doubles to enable nan and inf parsing.
Definition: double_imanip.h:42
Index nelem() const
Definition: mystring.h:189
Helper macros for debugging.
#define ARTS_NOEXCEPT
Definition: debug.h:99
#define ARTS_ASSERT(condition,...)
Definition: debug.h:102
#define ARTS_USER_ERROR(...)
Definition: debug.h:169
#define ARTS_USER_ERROR_IF(condition,...)
Definition: debug.h:153
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.
Implementation of Matrix, Vector, and such stuff.
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: matpack.h:33
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
my_basic_string< char > String
The String type for ARTS.
Definition: mystring.h:216
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
Numeric pow(const Rational base, Numeric exp)
Power of.
Definition: rational.h:713
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