ARTS  2.3.1285(git:92a29ea9-dirty)
zeeman.cc
Go to the documentation of this file.
1 /* Copyright (C) 2014
2  Richard Larsson <ric.larsson@gmail.com>
3 
4  This program is free software; you can redistribute it and/or modify it
5  under the terms of the GNU General Public License as published by the
6  Free Software Foundation; either version 2, or (at your option) any
7  later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17  USA. */
30 #include "zeeman.h"
31 #include "constants.h"
32 #include "linefunctions.h"
33 #include "linescaling.h"
34 #include "species_info.h"
35 
37 template <class T>
39  const Vector& f_grid,
40  const Index sd = 4) {
41  const Index nf = f_grid.nelem();
42  for (auto& var : main) {
43  const bool bad_stokes = sd not_eq var.StokesDimensions();
44  const bool bad_freq = nf not_eq var.NumberOfFrequencies();
45  if (bad_freq or bad_stokes) return true;
46  }
47  return false;
48 }
49 
51 bool bad_abs_species(const ArrayOfArrayOfSpeciesTag& abs_species) {
52  for (auto& species : abs_species) {
53  if (species.nelem()) {
54  for (auto& spec : species)
55  if (species[0].Species() not_eq spec.Species() or
56  species[0].Isotopologue() not_eq spec.Isotopologue() or
57  species[0].Type() not_eq spec.Type())
58  return true;
59  } else
60  return true;
61  }
62  return false;
63 }
64 
66 bool any_negative(const Vector& var) {
67  if (var.empty())
68  return false;
69  else if (min(var) < 0)
70  return true;
71  else
72  return false;
73 }
74 
76 bool any_negative(const Tensor4& var) {
77  if (var.empty())
78  return false;
79  else if (min(var) < 0)
80  return true;
81  else
82  return false;
83 }
84 
86  ArrayOfPropagationMatrix& propmat_clearsky,
87  ArrayOfStokesVector& nlte_source,
88  ArrayOfPropagationMatrix& dpropmat_clearsky_dx,
89  ArrayOfStokesVector& dnlte_dx_source,
90  ArrayOfStokesVector& nlte_dsource_dx,
91  const ArrayOfArrayOfSpeciesTag& abs_species,
92  const ArrayOfRetrievalQuantity& jacobian_quantities,
93  const ArrayOfArrayOfAbsorptionLines& abs_lines_per_species,
94  const SpeciesAuxData& isotopologue_ratios,
95  const SpeciesAuxData& partition_functions,
96  const Vector& f_grid,
97  const Vector& rtp_vmr,
98  const EnergyLevelMap& rtp_nlte,
99  const Vector& rtp_mag,
100  const Vector& rtp_los,
101  const Numeric& rtp_pressure,
102  const Numeric& rtp_temperature,
103  const Index& manual_tag,
104  const Numeric& H0,
105  const Numeric& theta0,
106  const Numeric& eta0) try {
107  // Find relevant derivatives in retrieval quantities positions
108  const ArrayOfIndex jacobian_quantities_positions =
109  equivalent_propmattype_indexes(jacobian_quantities);
110 
111  // Size of problem
112  const Index nf = f_grid.nelem();
113  const Index nq = jacobian_quantities_positions.nelem();
114  const Index ns = abs_species.nelem();
115  const Index nn = rtp_nlte.Levels().nelem();
116 
117  // Possible things that can go wrong in this code (excluding line parameters)
118  const bool do_src = not nlte_source.empty();
119  const bool do_jac = not jacobian_quantities_positions.nelem();
120  if (bad_abs_species(abs_species))
121  throw "*abs_species* sub-arrays must have the same species, isotopologue, and type as first sub-array.";
122  if ((rtp_mag.nelem() not_eq 3) and (not manual_tag))
123  throw "Only for 3D *rtp_mag* or a manual magnetic field";
124  if (rtp_vmr.nelem() not_eq abs_species.nelem())
125  throw "*rtp_vmr* must match *abs_species*";
126  if (abs_species.nelem() not_eq propmat_clearsky.nelem())
127  throw "*abs_species* must match *propmat_clearsky*";
128  if (bad_propmat(propmat_clearsky, f_grid))
129  throw "*propmat_clearsky* must have *stokes_dim* 4 and frequency dim same as *f_grid*";
130  if (do_src and (nlte_source.nelem() not_eq abs_species.nelem()))
131  throw "*abs_species* must match *nlte_source* when non-LTE is on";
132  if (do_src and bad_propmat(nlte_source, f_grid))
133  throw "*nlte_source* must have *stokes_dim* 4 and frequency dim same as *f_grid* when non-LTE is on";
134  if (do_jac and (nq not_eq dpropmat_clearsky_dx.nelem()))
135  throw "*dpropmat_clearsky_dx* must match derived form of *jacobian_quantities*";
136  if (do_jac and bad_propmat(dpropmat_clearsky_dx, f_grid))
137  throw "*dpropmat_clearsky_dx* must have Stokes dim 4 and frequency dim same as *f_grid*";
138  if (do_jac and do_src and (nq not_eq dnlte_dx_source.nelem()))
139  throw "*dnlte_dx_source* must match derived form of *jacobian_quantities* when non-LTE is on";
140  if (do_jac and do_src and bad_propmat(dnlte_dx_source, f_grid))
141  throw "*dnlte_dx_source* must have Stokes dim 4 and frequency dim same as *f_grid* when non-LTE is on";
142  if (do_jac and do_src and (nq not_eq nlte_dsource_dx.nelem()))
143  throw "*nlte_dsource_dx* must match derived form of *jacobian_quantities* when non-LTE is on";
144  if (do_jac and do_src and bad_propmat(nlte_dsource_dx, f_grid))
145  throw "*nlte_dsource_dx* must have Stokes dim 4 and frequency dim same as *f_grid* when non-LTE is on";
146  if (any_negative(f_grid)) throw "Negative frequency (at least one value).";
147  if (any_negative(rtp_vmr)) throw "Negative VMR (at least one value).";
148  if (any_negative(rtp_nlte.Data())) throw "Negative NLTE (at least one value).";
149  if (rtp_temperature <= 0) throw "Non-positive temperature";
150  if (rtp_pressure <= 0) throw "Non-positive pressure";
151  if (manual_tag and H0 < 0) throw "Negative manual magnetic field strength";
152 
153  // Pressure information
154  const Numeric dnumdens_dmvr = number_density(rtp_pressure, rtp_temperature);
155  const Numeric dnumdens_dt_dmvr =
156  dnumber_density_dt(rtp_pressure, rtp_temperature);
157 
158  // Main compute vectors
159  Linefunctions::InternalData scratch(nf, nq), sum(nf, nq);
160 
161  // Magnetic field internals and derivatives...
162  const auto X =
163  manual_tag
165  H0, Conversion::deg2rad(theta0), Conversion::deg2rad(eta0))
166  : Zeeman::FromGrids(rtp_mag[0],
167  rtp_mag[1],
168  rtp_mag[2],
169  Conversion::deg2rad(rtp_los[0]),
170  Conversion::deg2rad(rtp_los[1]));
171 
172  // Polarization
173  const auto polarization_scale_data = Zeeman::AllPolarization(X.theta, X.eta);
174  const auto polarization_scale_dtheta_data =
175  Zeeman::AllPolarization_dtheta(X.theta, X.eta);
176  const auto polarization_scale_deta_data =
177  Zeeman::AllPolarization_deta(X.theta, X.eta);
178 
179  // Non-LTE
180  Vector B(nn?nf:0);
181  Vector dBdT(nn?nf:0);
182  if (nn) {
183  planck(B, f_grid, rtp_temperature);
184  dplanck_dt(dBdT, f_grid, rtp_temperature);
185  }
186  const auto eB = MapToEigen(B);
187  const auto edBdT = MapToEigen(dBdT);
188 
189  for (auto polar : {Zeeman::Polarization::SigmaMinus,
192  auto& pol = Zeeman::SelectPolarization(polarization_scale_data, polar);
193  auto& dpol_dtheta =
194  Zeeman::SelectPolarization(polarization_scale_dtheta_data, polar);
195  auto& dpol_deta =
196  Zeeman::SelectPolarization(polarization_scale_deta_data, polar);
197 
198  for (Index ispecies = 0; ispecies < ns; ispecies++) {
199 
200  // Skip it if there are no species or there is no Zeeman
201  if (not abs_species[ispecies].nelem() or not is_zeeman(abs_species[ispecies]) or not abs_lines_per_species[ispecies].nelem())
202  continue;
203 
204  for (auto& band : abs_lines_per_species[ispecies]) {
205  // Constants for these lines
206  const Numeric QT0 = single_partition_function(band.T0(),
207  partition_functions.getParamType(band.QuantumIdentity()),
208  partition_functions.getParam(band.QuantumIdentity()));
209  const Numeric QT = single_partition_function(rtp_temperature,
210  partition_functions.getParamType(band.QuantumIdentity()),
211  partition_functions.getParam(band.QuantumIdentity()));
212  const Numeric dQTdT = dsingle_partition_function_dT(QT, rtp_temperature, temperature_perturbation(jacobian_quantities),
213  partition_functions.getParamType(band.QuantumIdentity()),
214  partition_functions.getParam(band.QuantumIdentity()));
215  const Numeric DC = Linefunctions::DopplerConstant(rtp_temperature, band.SpeciesMass());
216  const Numeric dDCdT = Linefunctions::dDopplerConstant_dT(rtp_temperature, DC);
217  const Vector line_shape_vmr = band.BroadeningSpeciesVMR(rtp_vmr, abs_species);
218  const Numeric numdens = rtp_vmr[ispecies] * dnumdens_dmvr;
219  const Numeric dnumdens_dT = rtp_vmr[ispecies] * dnumdens_dt_dmvr;
220  const Numeric isotop_ratio = isotopologue_ratios.getIsotopologueRatio(band.QuantumIdentity());
221 
223  scratch,
224  sum,
225  f_grid,
226  band,
227  jacobian_quantities,
228  jacobian_quantities_positions,
229  line_shape_vmr,
230  rtp_nlte, // This must be turned into a map of some kind...
231  rtp_pressure,
232  rtp_temperature,
233  isotop_ratio,
234  X.H,
235  DC,
236  dDCdT,
237  QT,
238  dQTdT,
239  QT0,
240  false,
241  true,
242  polar);
243 
244  auto pol_real = pol.attenuation();
245  auto pol_imag = pol.dispersion();
246  auto abs = propmat_clearsky[ispecies].Data()(0, 0, joker, joker);
247 
248  // Propagation matrix calculations
249  MapToEigen(abs).leftCols<4>().noalias() += numdens * sum.F.real() * pol_real;
250  MapToEigen(abs).rightCols<3>().noalias() += numdens * sum.F.imag() * pol_imag;
251 
252  if (nq) {
253  for (Index j = 0; j < nq; j++) {
254  const auto& deriv = jacobian_quantities[jacobian_quantities_positions[j]];
255  Eigen::Map<
256  Eigen::Matrix<Numeric, Eigen::Dynamic, 7, Eigen::RowMajor>>
257  dabs(dpropmat_clearsky_dx[j].Data().get_c_array(),
258  f_grid.nelem(), 7);
259 
260  if (deriv == JacPropMatType::Temperature) {
261  dabs.leftCols<4>().noalias() +=
262  numdens * sum.dF.col(j).real() * pol_real +
263  dnumdens_dT * sum.F.real() * pol_real;
264  dabs.rightCols<3>().noalias() +=
265  numdens * sum.dF.col(j).imag() * pol_imag +
266  dnumdens_dT * sum.F.imag() * pol_imag;
267  } else if (deriv == JacPropMatType::MagneticU) {
268  dabs.leftCols<4>().noalias() +=
269  numdens * X.dH_du * sum.dF.col(j).real() * pol_real +
270  numdens * X.deta_du * sum.F.real() *
271  dpol_deta.attenuation() +
272  numdens * X.dtheta_du * sum.F.real() *
273  dpol_dtheta.attenuation();
274  dabs.rightCols<3>().noalias() +=
275  numdens * X.dH_du * sum.dF.col(j).imag() * pol_imag +
276  numdens * X.deta_du * sum.F.imag() *
277  dpol_deta.dispersion() +
278  numdens * X.dtheta_du * sum.F.imag() *
279  dpol_dtheta.dispersion();
280  } else if (deriv == JacPropMatType::MagneticV) {
281  dabs.leftCols<4>().noalias() +=
282  numdens * X.dH_dv * sum.dF.col(j).real() * pol_real +
283  numdens * X.deta_dv * sum.F.real() *
284  dpol_deta.attenuation() +
285  numdens * X.dtheta_dv * sum.F.real() *
286  dpol_dtheta.attenuation();
287  dabs.rightCols<3>().noalias() +=
288  numdens * X.dH_dv * sum.dF.col(j).imag() * pol_imag +
289  numdens * X.deta_dv * sum.F.imag() *
290  dpol_deta.dispersion() +
291  numdens * X.dtheta_dv * sum.F.imag() *
292  dpol_dtheta.dispersion();
293  } else if (deriv == JacPropMatType::MagneticW) {
294  dabs.leftCols<4>().noalias() +=
295  numdens * X.dH_dw * sum.dF.col(j).real() * pol_real +
296  numdens * X.deta_dw * sum.F.real() *
297  dpol_deta.attenuation() +
298  numdens * X.dtheta_dw * sum.F.real() *
299  dpol_dtheta.attenuation();
300  dabs.rightCols<3>().noalias() +=
301  numdens * X.dH_dw * sum.dF.col(j).imag() * pol_imag +
302  numdens * X.deta_dw * sum.F.imag() *
303  dpol_deta.dispersion() +
304  numdens * X.dtheta_dw * sum.F.imag() *
305  dpol_dtheta.dispersion();
306  } else if (deriv == JacPropMatType::VMR and
307  deriv.QuantumIdentity().In(band.QuantumIdentity())) {
308  dabs.leftCols<4>().noalias() +=
309  numdens * sum.dF.col(j).real() * pol_real +
310  dnumdens_dmvr * sum.F.real() * pol_real;
311  dabs.rightCols<3>().noalias() +=
312  numdens * sum.dF.col(j).imag() * pol_imag +
313  dnumdens_dmvr * sum.F.imag() * pol_imag;
314  } else {
315  dabs.leftCols<4>().noalias() +=
316  numdens * sum.dF.col(j).real() * pol_real;
317  dabs.rightCols<3>().noalias() +=
318  numdens * sum.dF.col(j).imag() * pol_imag;
319  }
320  }
321  }
322 
323  // Source vector calculations
324  if (nn) {
325  auto nlte_src =
326  nlte_source[ispecies].Data()(0, 0, joker, joker);
327 
328  MapToEigen(nlte_src)
329  .leftCols<4>()
330  .noalias() += numdens * eB.cwiseProduct(sum.N.real()) * pol_real;
331 
332  for (Index j = 0; j < nq; j++) {
333  const auto& deriv =
334  jacobian_quantities[jacobian_quantities_positions[j]];
335 
336  Eigen::Map<
337  Eigen::Matrix<Numeric, Eigen::Dynamic, 4, Eigen::RowMajor>>
338  dnlte_dx_src(dnlte_dx_source[j].Data().get_c_array(),
339  f_grid.nelem(), 4),
340  nlte_dsrc_dx(nlte_dsource_dx[j].Data().get_c_array(),
341  f_grid.nelem(), 4);
342 
343  if (deriv == JacPropMatType::Temperature) {
344  dnlte_dx_src.noalias() +=
345  dnumdens_dT * eB.cwiseProduct(sum.N.real()) * pol_real +
346  numdens * eB.cwiseProduct(sum.dN.col(j).real()) * pol_real;
347 
348  nlte_dsrc_dx.noalias() +=
349  numdens * edBdT.cwiseProduct(sum.N.real()) * pol_real;
350  } else if (deriv == JacPropMatType::MagneticU)
351  dnlte_dx_src.noalias() +=
352  numdens * X.dH_du * eB.cwiseProduct(sum.dN.col(j).real()) * pol_real +
353  numdens * X.deta_du * eB.cwiseProduct(sum.N.real()) *
354  dpol_deta.attenuation() +
355  numdens * X.dtheta_du * eB.cwiseProduct(sum.N.real()) *
356  dpol_dtheta.attenuation();
357  else if (deriv == JacPropMatType::MagneticV)
358  dnlte_dx_src.noalias() +=
359  numdens * X.dH_dv * eB.cwiseProduct(sum.dN.col(j).real()) * pol_real +
360  numdens * X.deta_dv * eB.cwiseProduct(sum.N.real()) *
361  dpol_deta.attenuation() +
362  numdens * X.dtheta_dv * eB.cwiseProduct(sum.N.real()) *
363  dpol_dtheta.attenuation();
364  else if (deriv == JacPropMatType::MagneticW)
365  dnlte_dx_src.noalias() +=
366  numdens * X.dH_dw * eB.cwiseProduct(sum.dN.col(j).real()) * pol_real +
367  numdens * X.deta_dw * eB.cwiseProduct(sum.N.real()) *
368  dpol_deta.attenuation() +
369  numdens * X.dtheta_dw * eB.cwiseProduct(sum.N.real()) *
370  dpol_dtheta.attenuation();
371  else if (deriv == JacPropMatType::VMR and
372  deriv.QuantumIdentity().In(band.QuantumIdentity()))
373  dnlte_dx_src.noalias() +=
374  dnumdens_dmvr * eB.cwiseProduct(sum.N.real()) * pol_real +
375  numdens * eB.cwiseProduct(sum.dN.col(j).real()) * pol_real;
376  else
377  dnlte_dx_src.noalias() +=
378  numdens * eB.cwiseProduct(sum.dN.col(j).real()) * pol_real;
379  }
380  }
381  }
382  }
383  }
384 } catch (const char* e) {
386  os << "Errors raised by *zeeman_on_the_fly* internal function:\n";
387  os << "\tError: " << e << '\n';
388  throw std::runtime_error(os.str());
389 } catch (const std::exception& e) {
390  // Initialize an error message:
392  os << "Errors in calls by *zeeman_on_the_fly* internal function:\n";
393  os << e.what();
394  throw std::runtime_error(os.str());
395 }
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
ArrayOfIndex equivalent_propmattype_indexes(const ArrayOfRetrievalQuantity &js)
Returns a list of positions for the derivatives in Propagation Matrix calculations.
Definition: jacobian.cc:1099
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
bool bad_abs_species(const ArrayOfArrayOfSpeciesTag &abs_species)
Checks if abs_species is acceptable.
Definition: zeeman.cc:51
#define ns
Index nelem() const
Number of elements.
Definition: array.h:195
QuantumIdentifier::QType Index LowerQuantumNumbers Species
The Vector class.
Definition: matpackI.h:860
#define abs(x)
const Tensor4 & Data() const noexcept
Energy level type.
Constants of physical expressions as constexpr.
void set_cross_section_of_band(InternalData &scratch, InternalData &sum, const ConstVectorView f_grid, const AbsorptionLines &band, const ArrayOfRetrievalQuantity &derivatives_data, const ArrayOfIndex &derivatives_data_active, const Vector &vmrs, const EnergyLevelMap &nlte, const Numeric &P, const Numeric &T, const Numeric &isot_ratio, const Numeric &H, const Numeric &DC, const Numeric &dDCdT, const Numeric &QT, const Numeric &dQTdT, const Numeric &QT0, const bool no_negatives=false, const bool zeeman=false, const Zeeman::Polarization zeeman_polarization=Zeeman::Polarization::Pi)
Computes the cross-section of an absorption band.
The Tensor4 class.
Definition: matpackIV.h:421
const PolarizationVector & SelectPolarization(const AllPolarizationVectors &data, Polarization type) noexcept
Selects the polarization vector depending on polarization type.
Definition: zeemandata.h:646
constexpr Numeric deg2rad(T x)
Converts degrees to radians.
Definition: constants.h:327
bool empty() const
Returns true if variable size is zero.
Definition: matpackI.cc:49
Some molecular constants.
Numeric dsingle_partition_function_dT(const Numeric &QT, const Numeric &T, const Numeric &dT, const SpeciesAuxData::AuxType &partition_type, const ArrayOfGriddedField1 &partition_data)
Computes the partition function temperature derivative.
Definition: linescaling.cc:87
bool is_zeeman(const ArrayOfSpeciesTag &tg)
Is this a Zeeman tag group?
#define min(a, b)
AllPolarizationVectors AllPolarization_deta(Numeric theta, Numeric eta) noexcept
The derivative of AllPolarization wrt eta.
Definition: zeemandata.h:625
Numeric number_density(const Numeric &p, const Numeric &t)
number_density
Index nelem() const
Returns the number of elements.
Definition: matpackI.cc:51
bool any_negative(const Vector &var)
Checks for negative values.
Definition: zeeman.cc:66
Stuff related to lineshape functions.
const AuxType & getParamType(const Index species, const Index isotopologue) const
Return a constant reference to the parameter types.
Definition: absorption.h:276
Numeric dplanck_dt(const Numeric &f, const Numeric &t)
dplanck_dt
#define dabs(x)
Numeric getIsotopologueRatio(const SpeciesTag &st) const
Returns mparams[st.Species()][st.Isotopologue()][0].data[0] if st.Isotopologue() > 0...
Definition: absorption.cc:150
const ArrayOfQuantumIdentifier & Levels() const noexcept
Energy level type.
Numeric temperature_perturbation(const ArrayOfRetrievalQuantity &js) noexcept
Returns the temperature perturbation if it exists.
Definition: jacobian.cc:1304
const Joker joker
const ArrayOfGriddedField1 & getParam(const Index species, const Index isotopologue) const
Return a constant reference to the parameters.
Definition: absorption.cc:145
Numeric dnumber_density_dt(const Numeric &p, const Numeric &t)
dnumber_density_dT
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 dDopplerConstant_dT(const Numeric &T, const Numeric &dc)
Returns the temperature derivative of the frequency-independent part of the Doppler broadening...
int main(int argc, char **argv)
This is the main function of ARTS.
Definition: main.cc:612
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
Constains various line scaling functions.
bool empty() const
Check if variable is empty.
Definition: matpackIV.cc:52
Numeric DopplerConstant(Numeric T, Numeric mass)
Returns the frequency-independent part of the Doppler broadening.
Index nelem(const Lines &l)
Number of lines.
Numeric planck(const Numeric &f, const Numeric &t)
planck
Derived FromGrids(Numeric u, Numeric v, Numeric w, Numeric z, Numeric a) noexcept
Computes the derived plane from ARTS grids.
Definition: zeemandata.cc:236
Numeric single_partition_function(const Numeric &T, const SpeciesAuxData::AuxType &partition_type, const ArrayOfGriddedField1 &partition_data)
Computes the partition function at one temperature.
Definition: linescaling.cc:72
AllPolarizationVectors AllPolarization_dtheta(Numeric theta, const Numeric eta) noexcept
The derivative of AllPolarization wrt theta.
Definition: zeemandata.h:601
Auxiliary data for isotopologues.
Definition: absorption.h:217
ComplexConstMatrixViewMap MapToEigen(const ConstComplexMatrixView &A)
Definition: complex.cc:1655
void zeeman_on_the_fly(ArrayOfPropagationMatrix &propmat_clearsky, ArrayOfStokesVector &nlte_source, ArrayOfPropagationMatrix &dpropmat_clearsky_dx, ArrayOfStokesVector &dnlte_dx_source, ArrayOfStokesVector &nlte_dsource_dx, const ArrayOfArrayOfSpeciesTag &abs_species, const ArrayOfRetrievalQuantity &jacobian_quantities, const ArrayOfArrayOfAbsorptionLines &abs_lines_per_species, const SpeciesAuxData &isotopologue_ratios, const SpeciesAuxData &partition_functions, const Vector &f_grid, const Vector &rtp_vmr, const EnergyLevelMap &rtp_nlte, const Vector &rtp_mag, const Vector &rtp_los, const Numeric &rtp_pressure, const Numeric &rtp_temperature, const Index &manual_tag, const Numeric &H0, const Numeric &theta0, const Numeric &eta0)
Main and only way to compute Zeeman effect.
Definition: zeeman.cc:85
bool bad_propmat(const Array< T > &main, const Vector &f_grid, const Index sd=4)
Checks if a Propagation Matrix or something similar has good grids.
Definition: zeeman.cc:38
AllPolarizationVectors AllPolarization(Numeric theta, Numeric eta) noexcept
Computes the polarization of each polarization type.
Definition: zeemandata.h:578