Loading [MathJax]/jax/output/NativeMML/config.js
Isis 3 Programmer Reference
NumericalAtmosApprox.cpp
1 
6 /* SPDX-License-Identifier: CC0-1.0 */
7 #include <cmath>
8 #include "AtmosModel.h"
9 #include "NumericalAtmosApprox.h"
10 #include "NumericalApproximation.h"
11 #include "IException.h"
12 #include "IString.h"
13 
14 using namespace std;
15 namespace Isis {
52  double NumericalAtmosApprox::RombergsMethod(AtmosModel *am, IntegFunc sub, double a, double b) {
53  // This method was derived from an algorithm in the text
54  // Numerical Recipes in C: The Art of Scientific Computing
55  // Section 4.3 by Flannery, Press, Teukolsky, and Vetterling
56  int maxits = 20; // maximium number of iterations allowed to converge
57  double dss = 0; // error estimate for
58  double h[maxits+1]; // relative stepsizes for trap
59  double trap[maxits+1]; // successive trapeziodal approximations
60  double epsilon; // desired fractional accuracy
61  double epsilon2; // desired fractional accuracy
62  double ss; // result
63 
64  epsilon = 1.0e-4;
65  epsilon2 = 1.0e-6;
66 
67  h[0] = 1.0;
68  try {
69  NumericalApproximation interp(NumericalApproximation::PolynomialNeville);
70  for(int i = 0; i < maxits; i++) {
71  // i will determine number of trapezoidal partitions of area
72  // under curve for "integration" using refined trapezoidal rule
73  trap[i] = RefineExtendedTrap(am, sub, a, b, trap[i], i + 1); // validates data here
74  if(i >= 4) {
75  interp.AddData(5, &h[i-4], &trap[i-4]);
76  ss = interp.Evaluate(0.0, NumericalApproximation::Extrapolate);
77  dss = interp.PolynomialNevilleErrorEstimate()[0];
78  interp.Reset();
79  // we work only until our necessary accuracy is achieved
80  if(fabs(dss) <= epsilon * fabs(ss)) return ss;
81  if(fabs(dss) <= epsilon2) return ss;
82  }
83  trap[i+1] = trap[i];
84  h[i+1] = 0.25 * h[i];
85  // This is a key step: the factor is 0.25d0 even though
86  // the stepsize is decreased by 0.5d0. This makes the
87  // extraplolation a polynomial in h-squared as allowed
88  // by the equation from Numerical Recipes 4.2.1 pg.132,
89  // not just a polynomial in h.
90  }
91  }
92  catch(IException &e) { // catch error from RefineExtendedTrap, Constructor, Evaluate, PolynomialNevilleErrorEstimate
93  throw IException(e,
94  e.errorType(),
95  "NumericalAtmosApprox::RombergsMethod() - Caught the following error: ",
96  _FILEINFO_);
97  }
98  throw IException(IException::Programmer,
99  "NumericalAtmosApprox::RombergsMethod() - Failed to converge in "
100  + IString(maxits) + " iterations.",
101  _FILEINFO_);
102  }
103 
136  double NumericalAtmosApprox::RefineExtendedTrap(AtmosModel *am, IntegFunc sub, double a, double b, double s, unsigned int n) {
137  // This method was derived from an algorithm in the text
138  // Numerical Recipes in C: The Art of Scientific Computing
139  // Section 4.2 by Flannery, Press, Teukolsky, and Vetterling
140  try {
141  if(n == 1) {
142  double begin;
143  double end;
144  if(sub == InnerFunction) {
145  begin = InrFunc2Bint(am, a);
146  end = InrFunc2Bint(am, b);
147  }
148  else {
149  begin = OutrFunc2Bint(am, a);
150  end = OutrFunc2Bint(am, b);
151  }
152  return (0.5 * (b - a) * (begin + end));
153  }
154  else {
155  int it;
156  double delta, tnm, x, sum;
157  it = (int)(pow(2.0, (double)(n - 2)));
158  tnm = it;
159  delta = (b - a) / tnm; // spacing of the points to be added
160  x = a + 0.5 * delta;
161  sum = 0.0;
162  for(int i = 0; i < it; i++) {
163  if(sub == InnerFunction) {
164  sum = sum + InrFunc2Bint(am, x);
165  }
166  else {
167  sum = sum + OutrFunc2Bint(am, x);
168  }
169  x = x + delta;
170  }
171  return (0.5 * (s + (b - a) * sum / tnm));// replace s with refined value
172  }
173  }
174  catch(IException &e) { // catch exception from Evaluate()
175  throw IException(e,
176  e.errorType(),
177  "NumericalAtmosApprox::RefineExtendedTrap() - Caught the following error: ",
178  _FILEINFO_);
179  }
180  }
181 
201  double NumericalAtmosApprox::OutrFunc2Bint(AtmosModel *am, double phi) {
202  double result;
204  sub = NumericalAtmosApprox::InnerFunction;
205 
206  am->p_atmosPhi = phi;
207  am->p_atmosCosphi = cos((PI / 180.0) * phi);
208 
209  NumericalAtmosApprox qromb;
210  try {
211  result = qromb.RombergsMethod(am, sub, 1.0e-6, 1.0);
212  return result;
213  }
214  catch(IException &e) { // catch exception from RombergsMethod()
215  throw IException(e,
216  e.errorType(),
217  "NumericalAtmosApprox::OutrFunc2Bint() - Caught the following error: ",
218  _FILEINFO_);
219  }
220  }
221 
250  double NumericalAtmosApprox::InrFunc2Bint(AtmosModel *am, double mu) {
251  double ema; //pass in mu, get emission angle
252  double sine; //sin(ema)
253  double alpha;
254  double phase; //angle between sun and camera
255  double result;
256  double phasefn;//Henyey-Greenstein phase fn
257  double xx; //temp var to calculate emunot, emu
258  double emunot; //exp(-tau/munot)
259  double emu; //exp(-tau/mu)
260  double tfac; //factor that occurs in the integrals for transmission
261 
262  // calculate the phase angle
263  // also calculate any of the other redundant parameters
264  ema = acos(mu) * (180.0 / PI);
265  sine = sin(ema * (PI / 180.0));
266  if((am->p_atmosAtmSwitch == 0) || (am->p_atmosAtmSwitch == 2)) { // Reflection phase <= 90
267  alpha = am->p_atmosSini * sine * am->p_atmosCosphi +
268  am->p_atmosMunot * mu;
269  }
270  else { // Transmission phase <= 90
271  alpha = am->p_atmosSini * sine * am->p_atmosCosphi -
272  am->p_atmosMunot * mu;
273  }
274  phase = acos(alpha) * (180.0 / PI);
275  // now evaluate the integrand; all needed parameters
276  // have been hidden separately and passed to it in COMMON.
277  if(am->p_atmosAtmSwitch == 0) {
278  // integrand for hemispheric albedo
279  result = mu * am->p_atmosPM->CalcSurfAlbedo(phase, am->p_atmosInc, ema);
280  }
281  else {
282  phasefn = (1.0 - am->AtmosHga() * am->AtmosHga()) / pow((1.0 + 2.0 * am->AtmosHga() * alpha + am->AtmosHga() * am->AtmosHga()), 1.5);
283  xx = -am->AtmosTau() / max(am->p_atmosMunot, 1.0e-30);
284  if(xx < -69.0) {
285  emunot = 0.0;
286  }
287  else if(xx > 69.0) {
288  emunot = 1.0e30;
289  }
290  else {
291  emunot = exp(xx);
292  }
293  xx = -am->AtmosTau() / max(mu, 1.0e-30);
294 
295  if(xx < -69.0) {
296  emu = 0.0;
297  }
298  else if(xx > 69.0) {
299  emu = 1.0e30;
300  }
301  else {
302  emu = exp(xx);
303  }
304  if(mu == am->p_atmosMunot) {
305  tfac = am->AtmosTau() * emunot / (am->p_atmosMunot * am->p_atmosMunot);
306  }
307  else {
308  tfac = (emunot - emu) / (am->p_atmosMunot - mu);
309  }
310  if(am->p_atmosAtmSwitch == 1) {
311  result = mu * (phasefn - 1.0) * tfac;
312  }
313  else if(am->p_atmosAtmSwitch == 2) {
314  result = am->p_atmosMunot * mu * (phasefn - 1.0) * (1.0 - emunot * emu) / (am->p_atmosMunot + mu);
315  }
316  else if(am->p_atmosAtmSwitch == 3) {
317  result = -sine * am->p_atmosCosphi * (phasefn - 1.0) * tfac;
318  }
319  else {
320  string msg = "NumericalAtmosApprox::InrFunc2Bint() - Invalid value of atmospheric ";
321  msg += "switch used as argument to this function";
322  throw IException(IException::Programmer, msg, _FILEINFO_);
323  }
324  }
325  return result;
326  }
327 }//end NumericalAtmosApprox.cpp
Isis::NumericalAtmosApprox::IntegFunc
IntegFunc
This enum defines function to be integrated by Romberg's method.
Definition: NumericalAtmosApprox.h:43
Isis::NumericalApproximation::PolynomialNevilleErrorEstimate
vector< double > PolynomialNevilleErrorEstimate()
Retrieves the error estimate for the Neville's polynomial interpolation type.
Definition: NumericalApproximation.cpp:970
Isis::PI
const double PI
The mathematical constant PI.
Definition: Constants.h:40
Isis::NumericalAtmosApprox
This class extends Isis::NumericalApproximation.
Definition: NumericalAtmosApprox.h:32
Isis::AtmosModel
Isotropic atmos scattering model.
Definition: AtmosModel.h:60
Isis::PhotoModel::CalcSurfAlbedo
double CalcSurfAlbedo(double pha, double inc, double ema)
Calculate the surface brightness using photometric angle information.
Definition: PhotoModel.cpp:177
Isis::AtmosModel::AtmosHga
double AtmosHga() const
Return atmospheric Hga value.
Definition: AtmosModel.h:127
Isis::IException
Isis exception class.
Definition: IException.h:91
Isis::IException::errorType
ErrorType errorType() const
Returns the source of the error for this exception.
Definition: IException.cpp:430
std
Namespace for the standard library.
Isis::AtmosModel::AtmosTau
double AtmosTau() const
Return atmospheric Tau value.
Definition: AtmosModel.h:119
Isis::NumericalApproximation::AddData
void AddData(const double x, const double y)
Add a datapoint to the set.
Definition: NumericalApproximation.cpp:440
Isis::NumericalApproximation::Evaluate
double Evaluate(const double a, const ExtrapType &etype=ThrowError)
Calculates interpolated or extrapolated value of tabulated data set for given domain value.
Definition: NumericalApproximation.cpp:836
Isis::IString
Adds specific functionality to C++ strings.
Definition: IString.h:165
Isis::NumericalAtmosApprox::RombergsMethod
double RombergsMethod(AtmosModel *am, IntegFunc sub, double a, double b)
This variation on the NumericalApproximation method integrates a specified AtmosModel function rather...
Definition: NumericalAtmosApprox.cpp:52
Isis::NumericalApproximation::Reset
void Reset()
Resets the state of the object.
Definition: NumericalApproximation.cpp:2251
Isis::NumericalApproximation
NumericalApproximation provides various numerical analysis methods of interpolation,...
Definition: NumericalApproximation.h:726
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16

U.S. Department of the Interior | U.S. Geological Survey
ISIS | Privacy & Disclaimers | Astrogeology Research Program
To contact us, please post comments and questions on the USGS Astrogeology Discussion Board
To report a bug, or suggest a feature go to: ISIS Github
File Modified: 07/13/2023 15:16:57