ARTS  2.3.1285(git:92a29ea9-dirty)
zeemandata.cc
Go to the documentation of this file.
1 /* Copyright (C) 2018 Richard Larsson
2 
3  This program is free software; you can redistribute it and/or modify it
4  under the terms of the GNU General Public License as published by the
5  Free Software Foundation; either version 2, or (at your option) any
6  later version.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16  USA. */
17 
29 #include "zeemandata.h"
30 #include "abs_species_tags.h"
31 #include "species_info.h"
32 
34  const Numeric GS = get_lande_spin_constant(qid.Species());
36  const Numeric gu = SimpleG(qid.UpperQuantumNumbers(), GS, GL);
37  const Numeric gl = SimpleG(qid.LowerQuantumNumbers(), GS, GL);
38  return Model({gu, gl});
39 }
40 
42  Rational n,
43  Numeric GS,
44  Numeric GR,
45  Numeric GLE,
46  Numeric B,
47  Numeric D,
48  Numeric H,
49  Numeric gB,
50  Numeric gD,
51  Numeric gH,
52  Numeric lB,
53  Numeric lD,
54  Numeric lH) {
55  using Constant::pow2;
56  using Constant::pow3;
57  using std::atan2;
58  using std::cos;
59  using std::sin;
60  using std::sqrt;
61 
62  if (j.isUndefined() or n.isUndefined())
63  return NAN;
64  else if (j == 0)
65  return 0;
66 
67  auto J = j.toNumeric();
68 
69  auto nom = (lB + lD * (J * J + J + 1) + lH * pow2(J * J + J + 1)) * (2 * sqrt(J * J + J) / (2 * J + 1));
70 
71  auto denom =
72  B * J * (J - 1) - D * pow2(J * (J - 1)) + H * pow3(J * (J - 1)) +
73  (gB + gD * J * (J - 1) + gH * pow2(J * (J - 1))) * (J - 1) +
74  (lB + lD * J * (J - 1) + lH * pow2(J * (J - 1))) *
75  (2. / 3. - 2 * J / (2 * J + 1)) -
76  (B * (J + 2) * (J + 1) - D * pow2((J + 2) * (J + 1)) +
77  H * pow3((J + 2) * (J + 1)) -
78  (gB + gD * (J + 2) * (J + 1) + gH * pow2((J + 2) * (J + 1))) * (J + 2) +
79  (lB + lD * (J + 2) * (J + 1) + lH * pow2((J + 2) * (J + 1))) *
80  (2. / 3. - 2 * (J + 1) / (2 * J + 1)));
81 
82  auto phi = atan2(2 * nom, denom) / 2;
83 
84  if (j == n)
85  return (GS + GR) / (J * (J + 1)) - GR;
86  else if (j < n)
87  return (GS + GR) * (pow2(cos(phi)) / J - pow2(sin(phi)) / (J + 1)) +
88  2 * GLE * cos(2 * phi) / (2 * J + 1) - GR;
89  else /*if(j > n)*/
90  return (GS + GR) * (pow2(sin(phi)) / J - pow2(cos(phi)) / (J + 1)) -
91  2 * GLE * cos(2 * phi) / (2 * J + 1) - GR;
92 }
93 
95  Rational j,
96  Numeric gperp,
97  Numeric gpara)
98 {
99  if (k.isUndefined() or j.isUndefined() or j == 0)
100  return 0;
101  else
102  return gperp + (gperp + gpara) * Numeric(k*k / (j*(j+1)));
103 }
104 
106  if (qid.SpeciesName() == "O2") {
107  if (qid.Isotopologue() == SpeciesTag("O2-66").Isotopologue()) {
108  if (qid.LowerQuantumNumber(QuantumNumberType::v1) == 0 and
109  qid.UpperQuantumNumber(QuantumNumberType::v1) == 0) {
110  Numeric GS = 2.002084;
111  Numeric GLE = 2.77e-3;
112  Numeric GR = -1.16e-4;
113  Numeric B = 43100.44276e6;
114  Numeric D = 145.1271e3;
115  Numeric H = 49e-3;
116  Numeric lB = 59501.3438e6;
117  Numeric lD = 58.3680e3;
118  Numeric lH = 290.8e-3;
119  Numeric gB = -252.58634e6;
120  Numeric gD = -243.42;
121  Numeric gH = -1.46e-3;
122 
123  auto JU = qid.UpperQuantumNumber(QuantumNumberType::J);
124  auto NU = qid.UpperQuantumNumber(QuantumNumberType::N);
126  JU, NU, GS, GR, GLE, B, D, H, gB, gD, gH, lB, lD, lH);
127  auto JL = qid.LowerQuantumNumber(QuantumNumberType::J);
128  auto NL = qid.LowerQuantumNumber(QuantumNumberType::N);
130  JL, NL, GS, GR, GLE, B, D, H, gB, gD, gH, lB, lD, lH);
131  return Model({gu, gl});
132  }
133  } else if (qid.Isotopologue() == SpeciesTag("O2-68").Isotopologue()) {
134  if (qid.LowerQuantumNumber(QuantumNumberType::v1) == 0 and
135  qid.UpperQuantumNumber(QuantumNumberType::v1) == 0) {
136  Numeric GS = 2.002025;
137  Numeric GLE = 2.813e-3;
138  Numeric GR = -1.26e-4;
139  Numeric B = 40707.38657e6;
140  Numeric D = 129.4142e3;
141  Numeric H = 0;
142  Numeric lB = 59499.0375e6;
143  Numeric lD = 54.9777e3;
144  Numeric lH = 272.1e-3;
145  Numeric gB = -238.51530e6;
146  Numeric gD = -217.77;
147  Numeric gH = -1.305e-3;
148 
149  auto JU = qid.UpperQuantumNumber(QuantumNumberType::J);
150  auto NU = qid.UpperQuantumNumber(QuantumNumberType::N);
152  JU, NU, GS, GR, GLE, B, D, H, gB, gD, gH, lB, lD, lH);
153  auto JL = qid.LowerQuantumNumber(QuantumNumberType::J);
154  auto NL = qid.LowerQuantumNumber(QuantumNumberType::N);
156  JL, NL, GS, GR, GLE, B, D, H, gB, gD, gH, lB, lD, lH);
157  return Model({gu, gl});
158  }
159  }
160  } else if (qid.SpeciesName() == "CO") {
161  if (qid.Isotopologue() == SpeciesTag("CO-26").Isotopologue()) {
162  Numeric gperp = -0.2689 / Constant::mass_ratio_electrons_per_proton; // Flygare and Benson 1971
163 
164  return Model({gperp, gperp});
165  }
166  } else if (qid.SpeciesName() == "OCS") {
167  if (qid.Isotopologue() == SpeciesTag("OCS-622").Isotopologue()) {
168  Numeric gperp = -.02889 / Constant::mass_ratio_electrons_per_proton; // Flygare and Benson 1971
169  Numeric gpara = 0 / Constant::mass_ratio_electrons_per_proton; // Flygare and Benson 1971
170 
171  auto JU = qid.UpperQuantumNumber(QuantumNumberType::J);
172  auto KU = qid.UpperQuantumNumber(QuantumNumberType::Ka);
173  auto JL = qid.LowerQuantumNumber(QuantumNumberType::J);
174  auto KL = qid.LowerQuantumNumber(QuantumNumberType::Ka);
175 
176  return Model({closed_shell_trilinear(KU, JU, gperp, gpara),
177  closed_shell_trilinear(KL, JL, gperp, gpara)});
178  } else if (qid.Isotopologue() == SpeciesTag("OCS-624").Isotopologue()) {
179  Numeric gperp = -.0285 / Constant::mass_ratio_electrons_per_proton; // Flygare and Benson 1971
180  Numeric gpara = -.061 / Constant::mass_ratio_electrons_per_proton; // Flygare and Benson 1971
181 
182  auto JU = qid.UpperQuantumNumber(QuantumNumberType::J);
183  auto KU = qid.UpperQuantumNumber(QuantumNumberType::Ka);
184  auto JL = qid.LowerQuantumNumber(QuantumNumberType::J);
185  auto KL = qid.LowerQuantumNumber(QuantumNumberType::Ka);
186 
187  return Model({closed_shell_trilinear(KU, JU, gperp, gpara),
188  closed_shell_trilinear(KL, JL, gperp, gpara)});
189  }
190  } else if (qid.SpeciesName() == "CO2") {
191  if (qid.Isotopologue() == SpeciesTag("CO2-626").Isotopologue()) {
192  Numeric gperp = -.05508 / Constant::mass_ratio_electrons_per_proton; // Flygare and Benson 1971
193  Numeric gpara = 0 / Constant::mass_ratio_electrons_per_proton; // Flygare and Benson 1971
194 
195  auto JU = qid.UpperQuantumNumber(QuantumNumberType::J);
196  auto KU = qid.UpperQuantumNumber(QuantumNumberType::Ka);
197  auto JL = qid.LowerQuantumNumber(QuantumNumberType::J);
198  auto KL = qid.LowerQuantumNumber(QuantumNumberType::Ka);
199 
200  return Model({closed_shell_trilinear(KU, JU, gperp, gpara),
201  closed_shell_trilinear(KL, JL, gperp, gpara)});
202  }
203  }
204 
205  // Take care of zeroes since they do not show up in replacement databases
206  const bool upperzero = qid.UpperQuantumNumber(QuantumNumberType::J) == 0 or qid.UpperQuantumNumber(QuantumNumberType::F) == 0;
207  const bool lowerzero = qid.LowerQuantumNumber(QuantumNumberType::J) == 0 or qid.LowerQuantumNumber(QuantumNumberType::F) == 0;
208  return Model({upperzero ? 0 : NAN, lowerzero ? 0 : NAN});
209 }
210 
212  Model m = GetAdvancedModel(qid);
213  if (m.empty()) m = GetSimpleModel(qid);
214  *this = m;
215 }
216 
218 {
219  return Eigen::Vector3d(v, u, w).normalized();
220 }
221 
222 Eigen::Vector3d los_xyz_by_za_local(Numeric z, Numeric a)
223 {
224  using std::cos;
225  using std::sin;
226  return Eigen::Vector3d(cos(a)*sin(z), sin(a)*sin(z), cos(z));
227 }
228 
229 Eigen::Vector3d ev_xyz_by_za_local(Numeric z, Numeric a)
230 {
231  using std::cos;
232  using std::sin;
233  return Eigen::Vector3d(cos(a)*cos(z), sin(a)*cos(z), -sin(z));
234 }
235 
237 {
238  Derived output;
239 
240  // XYZ vectors normalized
241  const Eigen::Vector3d n = los_xyz_by_za_local(z, a);
242  const Eigen::Vector3d ev = ev_xyz_by_za_local(z, a);
243  const Eigen::Vector3d nH = los_xyz_by_uvw_local(u, v, w);
244 
245  // If there is no magnetic field, bailout quickly
246  output.H = std::hypot(std::hypot(u, v), w);
247  if (output.H == 0)
248  return FromPreDerived(0, 0, 0); // Guard against the 0-field
249 
250  // Normalized vector (which are also the magnetic field derivatives)
251  output.dH_dv = nH[0];
252  output.dH_du = nH[1];
253  output.dH_dw = nH[2];
254 
255  // Compute theta (and its derivatives if possible)
256  const Numeric cos_theta = n.dot(nH);
257  const Numeric sin_theta = std::sqrt(1 - Constant::pow2(cos_theta));
258  output.theta = std::acos(cos_theta);
259  if (sin_theta not_eq 0) {
260  const Eigen::Vector3d dtheta = (nH * cos_theta - n) / (output.H * sin_theta);
261  output.dtheta_dv = dtheta[0];
262  output.dtheta_du = dtheta[1];
263  output.dtheta_dw = dtheta[2];
264  } else {
265  output.dtheta_du = 0;
266  output.dtheta_dv = 0;
267  output.dtheta_dw = 0;
268  }
269 
270  // Compute eta (and its derivatives if possible)
271  const Eigen::Vector3d inplane = nH - nH.dot(n) * n;
272  const Numeric y = ev.cross(inplane).dot(n);
273  const Numeric x = ev.dot(inplane);
274  output.eta = std::atan2(y, x);
275  if (x not_eq 0 or y not_eq 0) {
276  const Eigen::Vector3d deta = n.cross(nH) / (output.H * (Constant::pow2(x) + Constant::pow2(y)));
277  output.deta_dv = deta[0];
278  output.deta_du = deta[1];
279  output.deta_dw = deta[2];
280  } else {
281  output.deta_du = 0;
282  output.deta_dv = 0;
283  output.deta_dw = 0;
284  }
285 
286  return output;
287 }
Numeric dtheta_dv
Definition: zeemandata.h:668
Numeric dtheta_dw
Definition: zeemandata.h:668
Numeric get_lande_spin_constant(const Index species) noexcept
Get the Lande spin constant.
Definition: species_info.cc:30
Main Zeeman Model.
Definition: zeemandata.h:358
Numeric dtheta_du
Definition: zeemandata.h:668
constexpr Model(SplittingData gs={NAN, NAN}) noexcept
Default copy/init of Model from its only private variable.
Definition: zeemandata.h:364
Model GetAdvancedModel(const QuantumIdentifier &qid) noexcept
Returns an advanced Zeeman model.
Definition: zeemandata.cc:105
cmplx FADDEEVA() w(cmplx z, double relerr)
Definition: Faddeeva.cc:680
Some molecular constants.
Eigen::Vector3d los_xyz_by_za_local(Numeric z, Numeric a)
Definition: zeemandata.cc:222
constexpr T pow2(T x)
power of two
Definition: constants.h:64
Model GetSimpleModel(const QuantumIdentifier &qid) noexcept
Returns a simple Zeeman model.
Definition: zeemandata.cc:33
Eigen::Vector3d ev_xyz_by_za_local(Numeric z, Numeric a)
Definition: zeemandata.cc:229
Implements rational numbers to work with other ARTS types.
Definition: rational.h:54
A tag group can consist of the sum of several of these.
Class to identify and match lines by their quantum numbers.
Definition: quantum.h:390
Contains derived values useful for Zeeman calculations.
Definition: zeemandata.h:667
Numeric case_b_g_coefficient_o2(Rational j, Rational n, Numeric GS, Numeric GR, Numeric GLE, Numeric B, Numeric D, Numeric H, Numeric gB, Numeric gD, Numeric gH, Numeric lB, Numeric lD, Numeric lH)
Definition: zeemandata.cc:41
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: matpack.h:33
constexpr Derived FromPreDerived(Numeric H, Numeric theta, Numeric eta) noexcept
Sets Derived from predefined Derived parameters.
Definition: zeemandata.h:712
Numeric deta_dw
Definition: zeemandata.h:668
constexpr T pow3(T x)
power of three
Definition: constants.h:70
constexpr Numeric toNumeric() const
Converts this to a Numeric.
Definition: rational.h:146
Numeric deta_dv
Definition: zeemandata.h:668
Headers and class definition of Zeeman modeling.
constexpr Numeric closed_shell_trilinear(Rational k, Rational j, Numeric gperp, Numeric gpara)
Definition: zeemandata.cc:94
Numeric deta_du
Definition: zeemandata.h:668
Header file for stuff related to absorption species tags.
constexpr bool isUndefined() const
Is the object not defined.
Definition: rational.h:110
Eigen::Vector3d los_xyz_by_uvw_local(Numeric u, Numeric v, Numeric w)
Definition: zeemandata.cc:217
Derived FromGrids(Numeric u, Numeric v, Numeric w, Numeric z, Numeric a) noexcept
Computes the derived plane from ARTS grids.
Definition: zeemandata.cc:236
bool empty() const noexcept
Returns true if the Model represents no Zeeman effect.
Definition: zeemandata.h:379
constexpr Numeric SimpleG(const QuantumNumbers &qns, const Numeric &GS, const Numeric &GL) noexcept
Computes the Zeeman splitting coefficient.
Definition: zeemandata.h:315
Index Isotopologue() const
Isotopologue species index.
Numeric get_lande_lambda_constant() noexcept
Get the Lande Lambda constant.
Definition: species_info.cc:45
Numeric sqrt(const Rational r)
Square root.
Definition: rational.h:620