Isis 3 Programmer Reference
Anisotropic1.cpp
1 
6 /* SPDX-License-Identifier: CC0-1.0 */
7 #include <cmath>
8 #include "Anisotropic1.h"
9 #include "AtmosModel.h"
10 #include "IException.h"
11 #include "IString.h"
12 
13 using std::max;
14 
15 namespace Isis {
22  Anisotropic1::Anisotropic1(Pvl &pvl, PhotoModel &pmodel) : AtmosModel(pvl, pmodel) {
23 
24  // Set default values
25  p_atmosAlpha0_0 = 0.0;
26  p_atmosAlpha1_0 = 0.0;
27  p_atmosBeta0_0 = 0.0;
28  p_atmosBeta1_0 = 0.0;
29  p_atmosDelta_0 = 0.0;
30  p_atmosDelta_1 = 0.0;
31  p_atmosDen = 0.0;
32  p_atmosE2 = 0.0;
33  p_atmosE3 = 0.0;
34  p_atmosE4 = 0.0;
35  p_atmosE5 = 0.0;
36  p_atmosFac = 0.0;
37  p_atmosP0 = 0.0;
38  p_atmosP1 = 0.0;
39  p_atmosQ0 = 0.0;
40  p_atmosQ02p02 = 0.0;
41  p_atmosQ1 = 0.0;
42  p_atmosQ12p12 = 0.0;
43  p_atmosWha2 = 0.0;
44  p_atmosWham = 0.0;
45  p_atmosX0_0 = 0.0;
46  p_atmosX0_1 = 0.0;
47  p_atmosY0_0 = 0.0;
48  p_atmosY0_1 = 0.0;
49 
50  }
51 
78  void Anisotropic1::AtmosModelAlgorithm(double phase, double incidence, double emission) {
79  double hpsq1;
80  double munot, munotp;
81  double maxval;
82  double mu, mup;
83  double xx;
84  double emunot, emu;
85  double gmunot, gmu;
86  double sum, prod;
87  double cosazss;
88  double xmunot_0, ymunot_0;
89  double xmu_0, ymu_0;
90  double xmunot_1, ymunot_1;
91  double xmu_1, ymu_1;
92  double cxx, cyy;
93  double xystuff;
94 
95  if(p_atmosBha == 0.0) {
96  p_atmosBha = 1.0e-6;
97  }
98 
99  if(p_atmosTau == 0.0) {
100  p_pstd = 0.0;
101  p_trans = 1.0;
102  p_trans0 = 1.0;
103  p_sbar = 0.0;
104  p_transs = 1.0;
105  return;
106  }
107 
108  if(p_atmosWha == 1.0) {
109  QString msg = "Anisotropic conservative case not implemented yet - WHA parameter cannot be set to 1.0";
110  msg += "This will cause negative planetary curvature to occur.";
111  throw IException(IException::User, msg, _FILEINFO_);
112  }
113 
114  if(TauOrWhaChanged()) {
115  // preparation includes exponential integrals e sub 2 through 5
116  p_atmosWha2 = 0.5 * p_atmosWha;
117  p_atmosWham = 1.0 - p_atmosWha;
118  p_atmosE2 = AtmosModel::En(2, p_atmosTau);
119  p_atmosE3 = AtmosModel::En(3, p_atmosTau);
120  p_atmosE4 = AtmosModel::En(4, p_atmosTau);
121  p_atmosE5 = AtmosModel::En(5, p_atmosTau);
122  // first, get the required quantities for the axisymmetric m=0 part
123  // zeroth moments of (uncorrected) x and y times characteristic fn
124  p_atmosX0_0 = p_atmosWha2 * (1.0 + (1.0 / 3.0) * p_atmosBha *
125  p_atmosWham);
126  p_atmosY0_0 = p_atmosWha2 * (p_atmosE2 + p_atmosBha * p_atmosWham *
127  p_atmosE4);
128  // higher-order correction term for x and y
129  p_atmosDelta_0 = (1.0 - (p_atmosX0_0 + p_atmosY0_0) - (1.0 - p_atmosWha *
130  (1.0 + (1.0 / 3.0) * p_atmosBha * p_atmosWham)) / (1.0 -
131  (p_atmosX0_0 - p_atmosY0_0))) / (p_atmosWha * (0.5 - p_atmosE3 +
132  p_atmosBha * p_atmosWham * (0.25 - p_atmosE5)));
133 
134  // moments of (corrected) x and y
135  p_atmosAlpha0_0 = 1.0 + p_atmosDelta_0 * (0.5 - p_atmosE3);
136  p_atmosAlpha1_0 = 0.5 + p_atmosDelta_0 * ((1.0 / 3.0) - p_atmosE4);
138  p_atmosBeta1_0 = p_atmosE3 + p_atmosDelta_0 * ((1.0 / 3.0) - p_atmosE4);
139  // gamma will be a weighted sum of m=0 x and y functions
140  // but unlike before, call the weights q1 and p1, and we also
141  // need additional weights q0 and p0
142  p_atmosFac = 2.0 - p_atmosWha * p_atmosAlpha0_0;
143  p_atmosDen = pow(p_atmosFac, 2.0) - pow(p_atmosWha * p_atmosBeta0_0, 2.0);
144  p_atmosQ0 = p_atmosBha * p_atmosWha * p_atmosWham * (p_atmosFac *
145  p_atmosAlpha1_0 - p_atmosWha * p_atmosBeta0_0 * p_atmosBeta1_0) /
146  p_atmosDen;
147  p_atmosP0 = p_atmosBha * p_atmosWha * p_atmosWham * (-p_atmosFac *
148  p_atmosBeta1_0 - p_atmosWha * p_atmosBeta0_0 * p_atmosAlpha1_0) /
149  p_atmosDen;
152  p_atmosP1 = (2.0 * p_atmosWham * p_atmosWha * p_atmosBeta0_0) /
153  p_atmosDen;
155  // sbar is total diffuse illumination and comes from moments
156  p_sbar = 1.0 - 2.0 * (p_atmosQ1 * p_atmosAlpha1_0 + p_atmosP1 *
158  // we're not done yet! still have to calculate the m=1 portion
159  // zeroth moments of (uncorrected) x and y times characteristic fn
160  p_atmosX0_1 = 0.5 * p_atmosWha2 * p_atmosBha * (1.0 - (1.0 / 3.0));
161  p_atmosY0_1 = 0.5 * p_atmosWha2 * p_atmosBha * (p_atmosE2 - p_atmosE4);
162  // higher-order correction term for x and y
163  p_atmosDelta_1 = (1.0 - (p_atmosX0_1 + p_atmosY0_1) - (1.0 -
164  (1.0 / 3.0) * p_atmosWha * p_atmosBha) / (1.0 - (p_atmosX0_1 -
165  p_atmosY0_1))) / (p_atmosWha2 * p_atmosBha * ((0.5 - 0.25) -
166  (p_atmosE3 - p_atmosE5)));
167  // moments of (corrected) x and y are not needed for m=1, so we're done
168  SetOldTau(p_atmosTau);
169  SetOldWha(p_atmosWha);
170  }
171 
172  // correct the path lengths for planetary curvature
173  hpsq1 = pow((1.0 + p_atmosHnorm), 2.0) - 1.0;
174 
175  if(incidence == 90.0) {
176  munot = 0.0;
177  }
178  else {
179  munot = cos((PI / 180.0) * incidence);
180  }
181 
182  maxval = max(1.0e-30, hpsq1 + munot * munot);
183  munotp = p_atmosHnorm / (sqrt(maxval) - munot);
184  munotp = max(munotp, p_atmosTau / 69.0);
185  if(emission == 90.0) {
186  mu = 0.0;
187  }
188  else {
189  mu = cos((PI / 180.0) * emission);
190  }
191 
192  maxval = max(1.0e-30, hpsq1 + mu * mu);
193  mup = p_atmosHnorm / (sqrt(maxval) - mu);
194  mup = max(mup, p_atmosTau / 69.0);
195  // build the x and y functions of mu0 and mu
196  maxval = max(1.0e-30, munotp);
197  xx = -p_atmosTau / maxval;
198 
199  if(xx < -69.0) {
200  emunot = 0.0;
201  }
202  else if(xx > 69.0) {
203  emunot = 1.0e30;
204  }
205  else {
206  emunot = exp(-p_atmosTau / munotp);
207  }
208 
209  maxval = max(1.0e-30, mup);
210  xx = -p_atmosTau / maxval;
211 
212  if(xx < -69.0) {
213  emu = 0.0;
214  }
215  else if(xx > 69.0) {
216  emu = 1.0e30;
217  }
218  else {
219  emu = exp(-p_atmosTau / mup);
220  }
221 
222  // first for m=0
223  xmunot_0 = 1.0 + p_atmosDelta_0 * munotp * (1.0 - emunot);
224  ymunot_0 = emunot + p_atmosDelta_0 * munotp * (1.0 - emunot);
225  xmu_0 = 1.0 + p_atmosDelta_0 * mup * (1.0 - emu);
226  ymu_0 = emu + p_atmosDelta_0 * mup * (1.0 - emu);
227 
228  // then for m=1
229  xmunot_1 = 1.0 + p_atmosDelta_1 * munotp * (1.0 - emunot);
230  ymunot_1 = emunot + p_atmosDelta_1 * munotp * (1.0 - emunot);
231  xmu_1 = 1.0 + p_atmosDelta_1 * mup * (1.0 - emu);
232  ymu_1 = emu + p_atmosDelta_1 * mup * (1.0 - emu);
233 
234  // gamma1 functions come from x and y with m=0
235  gmunot = p_atmosP1 * xmunot_0 + p_atmosQ1 * ymunot_0;
236  gmu = p_atmosP1 * xmu_0 + p_atmosQ1 * ymu_0;
237 
238  // purely atmos term uses x and y of both orders and is complex
239  sum = munot + mu;
240  prod = munot * mu;
241  cxx = 1.0 - p_atmosQ0 * sum + (p_atmosQ02p02 - p_atmosBha *
242  p_atmosQ12p12) * prod;
243  cyy = 1.0 + p_atmosQ0 * sum + (p_atmosQ02p02 - p_atmosBha *
244  p_atmosQ12p12) * prod;
245 
246  if(phase == 90.0) {
247  cosazss = 0.0 - munot * mu;
248  }
249  else {
250  cosazss = cos((PI / 180.0) * phase) - munot * mu;
251  }
252 
253  xystuff = cxx * xmunot_0 * xmu_0 - cyy * ymunot_0 *
254  ymu_0 - p_atmosP0 * sum * (xmu_0 * ymunot_0 + ymu_0 *
255  xmunot_0) + cosazss * p_atmosBha * (xmu_1 *
256  xmunot_1 - ymu_1 * ymunot_1);
257  p_pstd = 0.25 * p_atmosWha * munotp / (munotp + mup) * xystuff;
258 
259  // xmitted surface term uses gammas from m=0
260  p_trans = gmunot * gmu;
261 
262  // finally, never-scattered term is given by pure attenuation
263  p_trans0 = emunot * emu;
264 
265  // Calculate the transmission of light that must be subtracted from a
266  // shadow. This includes direct flux and the scattered flux in the
267  // upsun half of the sky downwelling onto the surface, and the usual
268  // transmission upward. NOTE: We need to derive the analytic expression
269  // for the light from half the sky in the Legendre scattering model. Until
270  // we do so, we are setting the shadow transmission to the purely
271  // unscattered part (same as trans0). This will give a result but is
272  // not fully consistent with how the other scattering models are
273  // implemented.
274  p_transs = p_trans0;
275  }
276 }
277 
278 extern "C" Isis::AtmosModel *Anisotropic1Plugin(Isis::Pvl &pvl, Isis::PhotoModel &pmodel) {
279  return new Isis::Anisotropic1(pvl, pmodel);
280 }
Isis::Anisotropic1::p_atmosP0
double p_atmosP0
???
Definition: Anisotropic1.h:71
Isis::Anisotropic1::p_atmosE4
double p_atmosE4
???
Definition: Anisotropic1.h:53
Isis::Anisotropic1::p_atmosX0_0
double p_atmosX0_0
???
Definition: Anisotropic1.h:63
Isis::AtmosModel::TauOrWhaChanged
bool TauOrWhaChanged() const
Checks whether tau or wha have changed.
Definition: AtmosModel.cpp:954
Isis::PhotoModel
Definition: PhotoModel.h:41
Isis::PI
const double PI
The mathematical constant PI.
Definition: Constants.h:40
Isis::Anisotropic1::p_atmosDen
double p_atmosDen
???
Definition: Anisotropic1.h:68
Isis::AtmosModel::p_pstd
double p_pstd
Pure atmospheric-scattering term.
Definition: AtmosModel.h:258
Isis::Anisotropic1::p_atmosQ0
double p_atmosQ0
???
Definition: Anisotropic1.h:69
Isis::Anisotropic1::p_atmosE5
double p_atmosE5
???
Definition: Anisotropic1.h:54
Isis::AtmosModel::En
static double En(unsigned int n, double x)
This routine evaluates the generalized exponential integral, En(x).
Definition: AtmosModel.cpp:370
Isis::Anisotropic1::p_atmosWham
double p_atmosWham
???
Definition: Anisotropic1.h:62
Isis::Anisotropic1::p_atmosE2
double p_atmosE2
???
Definition: Anisotropic1.h:51
Isis::AtmosModel
Isotropic atmos scattering model.
Definition: AtmosModel.h:60
Isis::Pvl
Container for cube-like labels.
Definition: Pvl.h:119
Isis::Anisotropic1::p_atmosFac
double p_atmosFac
???
Definition: Anisotropic1.h:67
Isis::Anisotropic1::AtmosModelAlgorithm
virtual void AtmosModelAlgorithm(double phase, double incidence, double emission)
Anisotropic atmospheric scattering with P1 single-particle phase fn, in the second approximation.
Definition: Anisotropic1.cpp:78
Isis::Anisotropic1
Definition: Anisotropic1.h:41
Isis::Anisotropic1::Anisotropic1
Anisotropic1(Pvl &pvl, PhotoModel &pmodel)
Constructs an Anisotropic1 object.
Definition: Anisotropic1.cpp:22
Isis::AtmosModel::p_trans
double p_trans
Transmission of surface reflected light through the atmosphere overall.
Definition: AtmosModel.h:259
Isis::Anisotropic1::p_atmosDelta_1
double p_atmosDelta_1
???
Definition: Anisotropic1.h:56
Isis::Anisotropic1::p_atmosBeta0_0
double p_atmosBeta0_0
???
Definition: Anisotropic1.h:59
Isis::AtmosModel::p_transs
double p_transs
Transmission of light that must be subtracted from the flat surface model to get the shadow model.
Definition: AtmosModel.h:261
Isis::Anisotropic1::p_atmosAlpha0_0
double p_atmosAlpha0_0
???
Definition: Anisotropic1.h:57
Isis::Anisotropic1::p_atmosY0_1
double p_atmosY0_1
???
Definition: Anisotropic1.h:66
Isis::Anisotropic1::p_atmosAlpha1_0
double p_atmosAlpha1_0
???
Definition: Anisotropic1.h:58
Isis::IException
Isis exception class.
Definition: IException.h:91
Isis::Anisotropic1::p_atmosBeta1_0
double p_atmosBeta1_0
???
Definition: Anisotropic1.h:60
Isis::Anisotropic1::p_atmosY0_0
double p_atmosY0_0
???
Definition: Anisotropic1.h:64
Isis::AtmosModel::p_atmosHnorm
double p_atmosHnorm
Atmospheric shell thickness normalized to planet radius.
Definition: AtmosModel.h:267
Isis::Anisotropic1::p_atmosX0_1
double p_atmosX0_1
???
Definition: Anisotropic1.h:65
Isis::Anisotropic1::p_atmosQ12p12
double p_atmosQ12p12
???
Definition: Anisotropic1.h:74
Isis::Anisotropic1::p_atmosP1
double p_atmosP1
???
Definition: Anisotropic1.h:72
Isis::Anisotropic1::p_atmosDelta_0
double p_atmosDelta_0
???
Definition: Anisotropic1.h:55
Isis::Anisotropic1::p_atmosQ1
double p_atmosQ1
???
Definition: Anisotropic1.h:70
Isis::Anisotropic1::p_atmosQ02p02
double p_atmosQ02p02
???
Definition: Anisotropic1.h:73
Isis::AtmosModel::p_sbar
double p_sbar
Illumination of the ground by the sky.
Definition: AtmosModel.h:262
Isis::Anisotropic1::p_atmosE3
double p_atmosE3
???
Definition: Anisotropic1.h:52
Isis::AtmosModel::p_trans0
double p_trans0
Transmission of surface reflected light through the atmosphere with no scatterings in the atmosphere.
Definition: AtmosModel.h:260
Isis::Anisotropic1::p_atmosWha2
double p_atmosWha2
???
Definition: Anisotropic1.h:61
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16
Isis::IException::User
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
Definition: IException.h:126