ARTS  2.3.1285(git:92a29ea9-dirty)
linefunctiondata.cc
Go to the documentation of this file.
1 /* Copyright (C) 2018
2  Richard Larsson <larsson@mps.mpg.de>
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 
30 #include "linefunctiondata.h"
31 
33 ArrayOfString all_coefficientsLineFunctionData() {return {"X0", "X1", "X2"};}
34 
36 ArrayOfString all_variablesLineFunctionData() {return {"G0", "D0", "G2", "D2", "FVC", "ETA", "Y", "G", "DV"};}
37 
39 {
40  // Test viability of model variables
41  static const ArrayOfString vars = all_variablesLineFunctionData();
42  bool var_OK = false;
43  for(auto& v: vars) if(var == v) var_OK = true;
44 
45  // Test viability of model coefficients
46  static const ArrayOfString coeffs = all_coefficientsLineFunctionData();
47  bool coeff_OK = false;
48  for(auto& c: coeffs) if(coeff == c) coeff_OK = true;
49 
50  // Fails either when the user has bad input or when the developer fails to update all_variablesLineFunctionData or all_coefficientsLineFunctionData
51  if(not var_OK or not coeff_OK) {
53  os << "At least one of your variable and/or your coefficient is not OK\n";
54  os << "Your variable: \"" << var << "\". OK variables include: " << vars << "\n";
55  os << "Your coefficient: \"" << coeff << "\". OK coefficients include: " << coeffs << "\n";
56  throw std::runtime_error(os.str());
57  }
58 
59  // Define a repetitive pattern. Update if/when there are more coefficients in the future
60  #define ReturnJacPropMatType(ID) \
61  (var == #ID) { if(coeff == "X0") return JacPropMatType::LineShape ## ID ## X0; \
62  else if(coeff == "X1") return JacPropMatType::LineShape ## ID ## X1; \
63  else if(coeff == "X2") return JacPropMatType::LineShape ## ID ## X2; }
64 
65 
66  if ReturnJacPropMatType(G0 )
67  else if ReturnJacPropMatType(D0 )
68  else if ReturnJacPropMatType(G2 )
69  else if ReturnJacPropMatType(D2 )
70  else if ReturnJacPropMatType(FVC)
71  else if ReturnJacPropMatType(ETA)
72  else if ReturnJacPropMatType(Y )
73  else if ReturnJacPropMatType(G )
74  else if ReturnJacPropMatType(DV )
75  #undef ReturnJacPropMatType
76 
77  std::terminate();
78 }
79 
80 
81 std::istream& LineShape::from_artscat4(std::istream& is, Model& m, const QuantumIdentifier& qid) {
82  // Special case when self is part of this
83  auto self_in_list = LegacyPressureBroadeningData::self_listed(qid, LegacyPressureBroadeningData::TypePB::PB_PLANETARY_BROADENING);
84  auto i = self_in_list ? 1 : 0;
85 
86  // Set or reset variables
87  m.mtype = Type::VP;
88  m.mself = bool(i);
89  m.mbath = false;
90  m.mdata = std::vector<SingleSpeciesModel>(6+i);
92 
93  // Set species
94  m.mspecies[i+1] = SpeciesTag(String("N2"));
95  m.mspecies[i+2] = SpeciesTag(String("O2"));
96  m.mspecies[i+3] = SpeciesTag(String("H2O"));
97  m.mspecies[i+4] = SpeciesTag(String("CO2"));
98  m.mspecies[i+5] = SpeciesTag(String("H2"));
99  m.mspecies[i+6] = SpeciesTag(String("He"));
100 
101  // Temperature types
102  for(auto& v: m.mdata) {
103  v.G0().type = TemperatureModel::T1;
104  v.D0().type = TemperatureModel::T5;
105  }
106 
107  // ARTSCAT-4 has self variables that are copied even
108  // if you have the same species as part of the list
109  // above. This is thrown away to keep the type and
110  // the code simpler in this ARTSCAT-5 formulation iff
111  // this species is not a self species
112  Numeric throwaways;
113 
114  // G0 main coefficient
115  if(self_in_list) is >> throwaways;
116  for(auto& v: m.mdata) is >> v.G0().X0;
117 
118  // G0 exponent is same as D0 exponent
119  if(self_in_list) is >> throwaways;
120  for(auto& v: m.mdata) {
121  is >> v.G0().X1;
122  v.D0().X1 = v.G0().X1;
123  }
124 
125  // D0 coefficient
126  for(std::vector<SingleSpeciesModel>::size_type k=i; k<m.mdata.size(); k++)
127  is >> m.mdata[i].D0().X0;
128 
129  return is;
130 }
131 
132 
133 std::istream& LineShape::from_linefunctiondata(std::istream& data, Model& m) {
134  m.mself = m.mbath = false;
135  Index specs;
136  String s;
137 
138  // The first tag should give the line shape scheme
139  data >> s;
141 
142  // Order of elements for line shape
143  const auto shapeparams = LegacyLineFunctionData::lineshapetag2variablesvector(s);
144 
145  // The second tag should give the line mixing scheme
146  data >> s;
147 
148  // Order of elements for line mixing
149  const auto mixingparams = LegacyLineFunctionData::linemixingtag2variablesvector(s);
150 
151  // The third tag should contain the number of species
152  data >> specs;
153  m.mspecies.resize(specs);
154  m.mdata.resize(specs);
155 
156  if(not specs and m.mtype not_eq Type::DP)
157  throw std::runtime_error("Need at least one species for non-Doppler line shapes");
158 
159  // For all species, we need to set the methods to compute them
160  for(Index i=0; i<specs; i++) {
161 
162  // This should be a species tag or one of the specials, SELF or BATH
163  data >> s;
164  if(s == self_broadening) {
165  // If the species is self, then we need to flag this
166  m.mself = true;
167  if(i not_eq 0) // but self has to be first for consistent behavior
168  throw std::runtime_error("Self broadening must be first, it is not\n");
169  }
170 
171  else if(s == bath_broadening) {
172  // If the species is air, then we need to flag this
173  m.mbath = true;
174  if(i not_eq specs - 1) // but air has to be last because it needs the rest's VMR
175  throw std::runtime_error("Air/bath broadening must be last, it is not\n");
176  }
177  else {
178  // Otherwise, we hope we find a species
179  try {
180  m.mspecies[i] = SpeciesTag(s);
181  }
182  catch(const std::runtime_error& e) {
183  ostringstream os;
184  os << "Encountered " << s << " in a position where a species should have been ";
185  os << "defined.\nPlease check your pressure broadening data structure and ensure ";
186  os << "that it follows the correct conventions.\n";
187  os << "SpeciesTag error reads: " << e.what();
188  throw std::runtime_error(os.str());
189  }
190  }
191 
192  // For all parameters
193  for(auto& params: {shapeparams, mixingparams}) {
194  for(auto& param: params) {
195  data >> s; // Should contain a temperature tag
196 
197  const auto type = string2temperaturemodel(s);
199 
200  m.mdata[i].Data()[Index(param)].type = type;
201  if(ntemp <= nmaxTempModelParams) {
202  switch(ntemp) {
203  case 1:
204  data >> m.mdata[i].Data()[Index(param)].X0;
205  break;
206  case 2:
207  data >> m.mdata[i].Data()[Index(param)].X0
208  >> m.mdata[i].Data()[Index(param)].X1;
209  break;
210  case 3:
211  data >> m.mdata[i].Data()[Index(param)].X0
212  >> m.mdata[i].Data()[Index(param)].X1
213  >> m.mdata[i].Data()[Index(param)].X2;
214  break;
215  case 0:
216  break;
217  default:
218  throw std::runtime_error("Unknown number of input parameters in Legacy mode.");
219  }
220  }
221  else { // Has to be the only allowed interpolation case
222  if(ntemp > nmaxInterpModels)
223  throw std::runtime_error("Too many input parameters in interpolation results Legacy mode.");
224  for(Index k=0; k<ntemp; k++)
225  data >> m.mdata[i].Interp()[k];
226  }
227  }
228  }
229  }
230 
231  return data;
232 }
233 
234 
235 std::istream & LineShape::from_pressurebroadeningdata(std::istream& data, LineShape::Model& lsc, const QuantumIdentifier& qid)
236 {
237  String s;
238  data >> s;
239 
240  const auto type = LegacyPressureBroadeningData::string2typepb(s);
242  const auto self_in_list = LegacyPressureBroadeningData::self_listed(qid, type);
243 
244  Vector x(n);
245  for(auto& num: x)
246  data >> num;
247 
248  lsc = LegacyPressureBroadeningData::vector2modelpb(x, type, self_in_list);
249 
250  return data;
251 }
252 
253 
254 std::istream& LineShape::from_linemixingdata(std::istream& data, LineShape::Model& lsc)
255 {
256  String s;
257  data >> s;
258 
259  const auto type = LegacyLineMixingData::string2typelm(s);
260  const auto n = LegacyLineMixingData::typelm2nelem(type);
261 
262  Vector x(n); for(auto& num: x) data >> num;
263 
265 
266  return data;
267 }
268 
269 
271 {
272  switch(type) {
273  case TypePB::PB_NONE:
274  return Model();
275  case TypePB::PB_AIR_BROADENING:
276  return Model(x[0], x[1], x[2], x[3], x[4]);
277  case TypePB::PB_AIR_AND_WATER_BROADENING:
278  if(self_in_list) {
279  ArrayOfSpeciesTag spec(2); spec[0] = SpeciesTag("H2O");
280  std::vector<SingleSpeciesModel> ssm(2);
281  ssm[0].G0() = {TemperatureModel::T1, x[0], x[1], 0};
282  ssm[0].D0() = {TemperatureModel::T5, x[2], x[1], 0};
283  ssm[1].G0() = {TemperatureModel::T1, x[3], x[4], 0};
284  ssm[1].D0() = {TemperatureModel::T5, x[5], x[4], 0};
285  return Model(LineShape::Type::VP, false, true, spec, ssm);
286  }
287  else {
288  ArrayOfSpeciesTag spec(3); spec[1] = SpeciesTag("H2O");
289  std::vector<SingleSpeciesModel> ssm(3);
290  ssm[0].G0() = {TemperatureModel::T1, x[0], x[1], 0};
291  ssm[0].D0() = {TemperatureModel::T5, x[2], x[1], 0};
292  ssm[2].G0() = {TemperatureModel::T1, x[3], x[4], 0};
293  ssm[2].D0() = {TemperatureModel::T5, x[5], x[4], 0};
294  ssm[1].G0() = {TemperatureModel::T1, x[6], x[7], 0};
295  ssm[1].D0() = {TemperatureModel::T5, x[8], x[7], 0};
296  return Model(LineShape::Type::VP, true, true, spec, ssm);
297  }
298  case TypePB::PB_PLANETARY_BROADENING:
299  if(self_in_list) {
300  const ArrayOfSpeciesTag spec = {SpeciesTag(String("N2")),
301  SpeciesTag(String("O2")),
302  SpeciesTag(String("H2O")),
303  SpeciesTag(String("CO2")),
304  SpeciesTag(String("H2")),
305  SpeciesTag(String("He"))};
306  std::vector<SingleSpeciesModel> ssm(6);
307  ssm[0].G0() = {TemperatureModel::T1, x[1 ], x[8 ], 0};
308  ssm[0].D0() = {TemperatureModel::T5, x[14], x[8 ], 0};
309  ssm[1].G0() = {TemperatureModel::T1, x[2 ], x[9 ], 0};
310  ssm[1].D0() = {TemperatureModel::T5, x[15], x[9 ], 0};
311  ssm[2].G0() = {TemperatureModel::T1, x[3 ], x[10], 0};
312  ssm[2].D0() = {TemperatureModel::T5, x[16], x[10], 0};
313  ssm[3].G0() = {TemperatureModel::T1, x[4 ], x[11], 0};
314  ssm[3].D0() = {TemperatureModel::T5, x[17], x[11], 0};
315  ssm[4].G0() = {TemperatureModel::T1, x[5 ], x[12], 0};
316  ssm[4].D0() = {TemperatureModel::T5, x[18], x[12], 0};
317  ssm[5].G0() = {TemperatureModel::T1, x[6 ], x[13], 0};
318  ssm[5].D0() = {TemperatureModel::T5, x[19], x[13], 0};
319  return Model(LineShape::Type::VP, false, false, spec, ssm);
320  }
321  else {
322  ArrayOfSpeciesTag spec(7);
323  spec[1] = SpeciesTag(String("N2"));
324  spec[2] = SpeciesTag(String("O2"));
325  spec[3] = SpeciesTag(String("H2O"));
326  spec[4] = SpeciesTag(String("CO2"));
327  spec[5] = SpeciesTag(String("H2"));
328  spec[6] = SpeciesTag(String("He"));
329  std::vector<SingleSpeciesModel> ssm(7);
330  ssm[0].G0() = {TemperatureModel::T1, x[0 ], x[7 ], 0};
331  // ssm[0].D0() = ...
332  ssm[1].G0() = {TemperatureModel::T1, x[1 ], x[8 ], 0};
333  ssm[1].D0() = {TemperatureModel::T5, x[14], x[8 ], 0};
334  ssm[2].G0() = {TemperatureModel::T1, x[2 ], x[9 ], 0};
335  ssm[2].D0() = {TemperatureModel::T5, x[15], x[9 ], 0};
336  ssm[3].G0() = {TemperatureModel::T1, x[3 ], x[10], 0};
337  ssm[3].D0() = {TemperatureModel::T5, x[16], x[10], 0};
338  ssm[4].G0() = {TemperatureModel::T1, x[4 ], x[11], 0};
339  ssm[4].D0() = {TemperatureModel::T5, x[17], x[11], 0};
340  ssm[5].G0() = {TemperatureModel::T1, x[5 ], x[12], 0};
341  ssm[5].D0() = {TemperatureModel::T5, x[18], x[12], 0};
342  ssm[6].G0() = {TemperatureModel::T1, x[6 ], x[13], 0};
343  ssm[6].D0() = {TemperatureModel::T5, x[19], x[13], 0};
344  return Model(LineShape::Type::VP, true, false, spec, ssm);
345  }
346  }
347  std::terminate();
348 }
349 
350 
352 {
353  auto y = Model();
354  y.resize(1);
355  switch(type) {
356  case TypeLM::LM_NONE:
357  break;
358  case TypeLM::LM_LBLRTM:
359  y.Data()[0].Y().type = LineShape::TemperatureModel::LM_AER;
360  y.Data()[0].G().type = LineShape::TemperatureModel::LM_AER;
361  std::copy(x.begin(), x.end(), y.Data()[0].Interp().begin());
362  break;
363  case TypeLM::LM_LBLRTM_O2NonResonant:
364  y.Data()[0].G().type = LineShape::TemperatureModel::T0;
365  y.Data()[0].G().X0 = x[0];
366  break;
367  case TypeLM::LM_2NDORDER:
368  y.Data()[0].Y().type = LineShape::TemperatureModel::T4;
369  y.Data()[0].Y().X0 = x[0];
370  y.Data()[0].Y().X1 = x[1];
371  y.Data()[0].Y().X2 = x[7];
372  y.Data()[0].G().type = LineShape::TemperatureModel::T4;
373  y.Data()[0].G().X0 = x[2];
374  y.Data()[0].G().X1 = x[3];
375  y.Data()[0].G().X2 = x[8];
376  y.Data()[0].DV().type = LineShape::TemperatureModel::T4;
377  y.Data()[0].DV().X0 = x[4];
378  y.Data()[0].DV().X1 = x[5];
379  y.Data()[0].DV().X2 = x[9];
380  break;
381  case TypeLM::LM_1STORDER:
382  y.Data()[0].Y().type = LineShape::TemperatureModel::T1;
383  y.Data()[0].Y().X0 = x[1];
384  y.Data()[0].Y().X1 = x[2];
385  break;
386  case TypeLM::LM_BYBAND:
387  break;
388  }
389  return y;
390 }
391 
392 
394 {
395  bool self = spec == self_broadening;
396  bool bath = spec == bath_broadening;
397  if(mself and self)
398  mdata.front().Set(var, param);
399  else if(self)
400  throw std::runtime_error("No self species but trying to set self in line shape model");
401  else if(mbath and bath) {
402  mdata.back().Set(var, param);
403  }
404  else if(bath)
405  throw std::runtime_error("No bath species but trying to set bath in line shape model");
406  else {
407  const SpeciesTag sp(spec);
408  bool found=false;
409  for(Index i=Index(mself); i<nelem()-Index(mbath); i++) {
410  if(sp.Species() == mspecies[i].Species()) {
411  found = true;
412  mdata[i].Set(var, param);
413  }
414  }
415  if(not found) {
417  os << "No species of type " << spec << " found in line shape model\n";
418  os << "Available species are: " << mspecies << "\n";
419  throw std::runtime_error(os.str());
420  }
421  }
422 }
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
void copy(ConstComplexIterator1D origin, const ConstComplexIterator1D &end, ComplexIterator1D target)
Copy data between begin and end to target.
Definition: complex.cc:478
void var(VectorView var, const Vector &y, const ArrayOfVector &ys, const Index start=0, const Index end=-1)
Compute the variance of the ranged ys.
Definition: raw.cc:49
TemperatureModel string2temperaturemodel(const String &type)
Turns predefined strings into a TemperatureModel type.
LegacyLineMixingData::TypeLM string2typelm(String type)
Line mixing types from string.
std::istream & from_linefunctiondata(std::istream &data, Model &lsc)
Index typepb2nelem(LegacyPressureBroadeningData::TypePB type)
Pressure broadening types to number of elements.
std::vector< Variable > linemixingtag2variablesvector(String type)
Line mixing models.
Index temperaturemodel2legacynelem(TemperatureModel type) noexcept
Length per variable.
ArrayOfSpeciesTag mspecies
std::vector< SingleSpeciesModel > mdata
The Vector class.
Definition: matpackI.h:860
Model vector2modellm(Vector x, LegacyLineMixingData::TypeLM type)
LineShape::Model from legacy input vector.
Index Species() const
Molecular species index.
Main line shape model class.
Index typelm2nelem(LegacyLineMixingData::TypeLM type)
Line mixing types to number.
#define ReturnJacPropMatType(ID)
Model vector2modelpb(Vector x, LegacyPressureBroadeningData::TypePB type, bool self_in_list)
G0 G2 FVC Y DV Numeric Numeric Numeric Zeeman LowerQuantumNumbers void * data
void Set(const ModelParameters &param, const String &spec, const Variable var)
ArrayOfString all_variablesLineFunctionData()
{"G0", "D0", "G2", "D2", "ETA", "FVC", "Y", "G", "DV"}
Contains the line function data class.
JacPropMatType
List of Jacobian properties for analytical line shape related derivatives.
Definition: jacobian.h:46
Iterator1D begin()
Return iterator to first element.
Definition: matpackI.cc:144
Iterator1D end()
Return iterator behind last element.
Definition: matpackI.cc:148
bool self_listed(const QuantumIdentifier &qid, LegacyPressureBroadeningData::TypePB t)
Pressure broadening if self exist.
std::istream & from_artscat4(std::istream &is, Model &lsc, const QuantumIdentifier &qid)
_CS_string_type str() const
Definition: sstream.h:491
constexpr Index nmaxTempModelParams
Current max number of coefficients.
constexpr Index nmaxInterpModels
A tag group can consist of the sum of several of these.
Variable
List of possible shape variables.
Coefficients and temperature model for SingleSpeciesModel.
LegacyPressureBroadeningData::TypePB string2typepb(String type)
Pressure broadening types from string.
Class to identify and match lines by their quantum numbers.
Definition: quantum.h:390
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: matpack.h:33
std::istream & from_linemixingdata(std::istream &data, Model &lsc)
Legacy reading of old deprecated LineMixingData class.
basic_ostringstream< char, string_char_traits< char >, alloc > ostringstream
Definition: sstream.h:204
This can be used to make arrays out of anything.
Definition: array.h:40
ArrayOfString all_coefficientsLineFunctionData()
{"X0", "X1", "X2"}
Index nelem() const
std::istream & from_pressurebroadeningdata(std::istream &data, Model &lsc, const QuantumIdentifier &qid)
Array< SpeciesTag > ArrayOfSpeciesTag
A tag group is an array of SpeciesTags.
JacPropMatType select_derivativeLineShape(const String &var, const String &coeff)
Select the derivative that will be used in Jacobian calculations — also checks validity of var and c...
Type string2shapetype(const String &type)
Turns predefined strings into a Type.
my_basic_string< char > String
The String type for ARTS.
Definition: mystring.h:280
std::vector< Variable > lineshapetag2variablesvector(String type)
Line shape models.