ARTS  2.4.0(git:4fb77825)
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 }
gu
gu
Definition: arts_api_classes.cc:181
Zeeman::Model
Main Zeeman Model.
Definition: zeemandata.h:358
QuantumNumberType::N
@ N
QuantumIdentifier
Class to identify and match lines by their quantum numbers.
Definition: quantum.h:390
Zeeman::Model::Model
constexpr Model(SplittingData gs={NAN, NAN}) noexcept
Default copy/init of Model from its only private variable.
Definition: zeemandata.h:364
w
Complex w(Complex z) noexcept
The Faddeeva function.
Definition: linefunctions.cc:42
los_xyz_by_uvw_local
Eigen::Vector3d los_xyz_by_uvw_local(Numeric u, Numeric v, Numeric w)
Definition: zeemandata.cc:217
QuantumNumberType::F
@ F
get_lande_lambda_constant
Numeric get_lande_lambda_constant() noexcept
Get the Lande Lambda constant.
Definition: species_info.cc:45
Zeeman::Derived::dH_dw
Numeric dH_dw
Definition: zeemandata.h:668
Zeeman::Derived::dH_dv
Numeric dH_dv
Definition: zeemandata.h:668
Zeeman::FromGrids
Derived FromGrids(Numeric u, Numeric v, Numeric w, Numeric z, Numeric a) noexcept
Computes the derived plane from ARTS grids.
Definition: zeemandata.cc:236
ARTS::Var::y
Vector y(Workspace &ws) noexcept
Definition: autoarts.h:7401
get_lande_spin_constant
Numeric get_lande_spin_constant(const Index species) noexcept
Get the Lande spin constant.
Definition: species_info.cc:30
zeemandata.h
Headers and class definition of Zeeman modeling.
Zeeman::Derived::dH_du
Numeric dH_du
Definition: zeemandata.h:668
QuantumNumberType::v1
@ v1
Zeeman::GetSimpleModel
Model GetSimpleModel(const QuantumIdentifier &qid) noexcept
Returns a simple Zeeman model.
Definition: zeemandata.cc:33
Zeeman::GetAdvancedModel
Model GetAdvancedModel(const QuantumIdentifier &qid) noexcept
Returns an advanced Zeeman model.
Definition: zeemandata.cc:105
sqrt
Numeric sqrt(const Rational r)
Square root.
Definition: rational.h:620
ev_xyz_by_za_local
Eigen::Vector3d ev_xyz_by_za_local(Numeric z, Numeric a)
Definition: zeemandata.cc:229
SpeciesTag
A tag group can consist of the sum of several of these.
Definition: abs_species_tags.h:44
Zeeman::Derived::eta
Numeric eta
Definition: zeemandata.h:668
Zeeman::SimpleG
constexpr Numeric SimpleG(const QuantumNumbers &qns, const Numeric &GS, const Numeric &GL) noexcept
Computes the Zeeman splitting coefficient.
Definition: zeemandata.h:315
Rational::toNumeric
constexpr Numeric toNumeric() const
Converts this to a Numeric.
Definition: rational.h:146
Zeeman::Derived::dtheta_dv
Numeric dtheta_dv
Definition: zeemandata.h:668
species_info.h
Some molecular constants.
Numeric
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: matpack.h:33
Zeeman::Derived::deta_dv
Numeric deta_dv
Definition: zeemandata.h:669
Zeeman::Derived::deta_dw
Numeric deta_dw
Definition: zeemandata.h:669
abs_species_tags.h
Header file for stuff related to absorption species tags.
los_xyz_by_za_local
Eigen::Vector3d los_xyz_by_za_local(Numeric z, Numeric a)
Definition: zeemandata.cc:222
Isotopologue
QuantumIdentifier::QType Isotopologue
Definition: arts_api_classes.cc:242
Constant::pow3
constexpr T pow3(T x)
power of three
Definition: constants.h:70
Zeeman::Model::empty
bool empty() const noexcept
Returns true if the Model represents no Zeeman effect.
Definition: zeemandata.h:379
Zeeman::Derived::theta
Numeric theta
Definition: zeemandata.h:668
Zeeman::Derived::dtheta_dw
Numeric dtheta_dw
Definition: zeemandata.h:668
closed_shell_trilinear
constexpr Numeric closed_shell_trilinear(Rational k, Rational j, Numeric gperp, Numeric gpara)
Definition: zeemandata.cc:94
SpeciesTag::Isotopologue
Index Isotopologue() const
Isotopologue species index.
Definition: abs_species_tags.h:87
Rational::isUndefined
constexpr bool isUndefined() const
Is the object not defined.
Definition: rational.h:110
Constant::pow2
constexpr T pow2(T x)
power of two
Definition: constants.h:64
ARTS::Var::x
Vector x(Workspace &ws) noexcept
Definition: autoarts.h:7346
Zeeman::Derived::dtheta_du
Numeric dtheta_du
Definition: zeemandata.h:668
Zeeman::Derived::deta_du
Numeric deta_du
Definition: zeemandata.h:669
case_b_g_coefficient_o2
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
Zeeman::Derived::H
Numeric H
Definition: zeemandata.h:668
Rational
Implements rational numbers to work with other ARTS types.
Definition: rational.h:54
Zeeman::FromPreDerived
constexpr Derived FromPreDerived(Numeric H, Numeric theta, Numeric eta) noexcept
Sets Derived from predefined Derived parameters.
Definition: zeemandata.h:712
Zeeman::Derived
Contains derived values useful for Zeeman calculations.
Definition: zeemandata.h:667
QuantumNumberType::J
@ J