6 #include "NumericalApproximation.h"    17 #define MAX(x,y) (((x) > (y)) ? (x) : (y))    36     p_atmosAlgorithmName = 
"Unknown";
    39     p_atmosIncTable.resize(91);
    40     p_atmosAhTable.resize(91);
    41     p_atmosHahgtTable.resize(91);
    42     p_atmosHahgt0Table.resize(91);
    46     p_atmosEulgam = 0.5772156;
    58     p_atmosWhaold = 1.0e30;
    66     p_standardConditions = 
false;
    68     PvlGroup &algorithm = pvl.
findObject(
"AtmosphericModel").findGroup(
"Algorithm", Pvl::Traverse);
    71       SetAtmosNulneg(algorithm[
"Nulneg"][0] == 
"YES");
    74       p_atmosNulneg = 
false;
    78       SetAtmosTau(algorithm[
"Tau"]);
    80     p_atmosTausave = p_atmosTau;
    83       SetAtmosTauref(algorithm[
"Tauref"]);
    87       SetAtmosWha(algorithm[
"Wha"]);
    89     p_atmosWhasave = p_atmosWha;
    92       SetAtmosHga(algorithm[
"Hga"]);
    94     p_atmosHgasave = p_atmosHga;
    97       SetAtmosBha(algorithm[
"Bha"]);
    99     p_atmosBhasave = p_atmosBha;
   102       SetAtmosInc(algorithm[
"Inc"]);
   106       SetAtmosPhi(algorithm[
"Phi"]);
   110       SetAtmosHnorm(algorithm[
"Hnorm"]);
   114       SetAtmosIord(algorithm[
"Iord"][0] == 
"YES");
   117       p_atmosAddOffset = 
false;
   121       SetAtmosEstTau(algorithm[
"EstTau"][0] == 
"YES");
   124       p_atmosEstTau = 
false;
   147   double AtmosModel::G11Prime(
double tau) {
   166     while(fabs(term) > fabs(sum)*tol) {
   170       fac = fac * (-tau) / fi;
   171       term = fac / (fi * fi);
   173     elog = log(MAX(1.0e-30, tau)) + eulgam;
   174     e1_2 = sum + 
PI * 
PI / 12.0 + 0.5 *
   176     result = 2.0 * (AtmosModel::En(1, tau)
   177                     + elog * AtmosModel::En(2, tau)
   223   double AtmosModel::Ei(
double x) {
   233     double sum, fact, term, prev;
   242                        "AtmosModel::Ei() - Invalid argument. Definition requires x > 0.0. Entered x = "   247       result = log(x) + euler;
   249     else if(x <= -log(epsilon)) {  
   252       for(
int k = 1; k <= maxit; k++) {
   256         if(term < epsilon * sum) {
   257           result = sum + log(x) + euler;
   262                        "AtmosModel::Ei() - Power series failed to converge in "   263                        + 
IString(maxit) + 
" iterations. Unable to calculate exponential integral.",
   269       for(
int k = 1; k <= maxit; k++) {
   273           result = exp(x) * (1.0 + sum) / x;
   282             result = exp(x) * (1.0 + sum) / x;
   287       result = exp(x) * (1.0 + sum) / x;
   364   double AtmosModel::En(
unsigned int n, 
double x) {
   371     double a, b, c, d, h;
   383     euler = 0.5772156649;
   386     if((x < 0.0) || (x == 0.0 && (n == 0 || n == 1))) {
   387       IString msg = 
"AtmosModel::En() - Invalid arguments. ";
   388       msg += 
"Definition requires (x > 0.0 and n >=0 ) or (x >= 0.0 and n > 1). ";
   389       msg += 
"Entered x = " + 
IString(x) + 
" and n = " + 
IString((
int) n);
   393       result = exp(-x) / x;
   403       for(
int i = 1; i <= maxit; i++) {
   406         d = 1.0 / (a * d + b);
   410         if(fabs(delta - 1.0) < epsilon) {
   411           result = h * exp(-x);
   416                        "AtmosModel::En() - Continued fraction failed to converge in "   417                        + 
IString(maxit) + 
" iterations. Unable to calculate exponential integral.",
   425         result = -log(x) - euler;
   428       for(
int i = 1; i <= maxit; i++) {
   429         fact = -fact * x / i;
   431           delta = -fact / (i - nm1);
   435           for(
int ii = 1; ii <= nm1; ii++) {
   436             psi = psi + 1.0 / ii;
   438           delta = fact * (-log(x) + psi);
   440         result = result + delta;
   441         if(fabs(delta) < fabs(result)*epsilon) {
   446                        "AtmosModel::En() - Series representation failed to converge in "   447                        + 
IString(maxit) + 
" iterations. Unable to calculate exponential integral.",
   469   void AtmosModel::CalcAtmEffect(
double pha, 
double inc, 
double ema,
   470                                  double *pstd, 
double *trans, 
double *trans0, 
double *sbar,
   481     AtmosModelAlgorithm(pha, inc, ema);
   492   void AtmosModel::SetStandardConditions(
bool standard) {
   493     p_standardConditions = standard;
   494     if(p_standardConditions) {
   495       p_atmosTausave = p_atmosTau;
   496       p_atmosTau = p_atmosTauref;
   499       p_atmosTau = p_atmosTausave;
   531   void AtmosModel::GenerateAhTable() {
   538     sub = NumericalAtmosApprox::OuterFunction;
   545     for(inccnt = 0; inccnt < p_atmosNinc; inccnt++) {
   546       p_atmosInc = (double) inccnt;
   547       p_atmosIncTable[inccnt] = p_atmosInc;
   548       p_atmosMunot = cos((
PI / 180.0) * p_atmosInc);
   549       p_atmosSini = sin((
PI / 180.0) * p_atmosInc);
   551       IString phtName = p_atmosPM->AlgorithmName();
   553       if(p_atmosInc == 90.0) {
   554         p_atmosAhTable[inccnt] = 0.0;
   556       else if(phtName == 
"LAMBERT") {
   557         p_atmosAhTable[inccnt] = 1.0;
   559       else if(phtName == 
"LOMMELSEELIGER") {
   560         p_atmosAhTable[inccnt] = 2.0 * log((1.0 / p_atmosMunot) / p_atmosMunot);
   562       else if(phtName == 
"MINNAERT") {
   563         p_atmosAhTable[inccnt] = (pow(p_atmosMunot, ((
Minnaert *)p_atmosPM)->PhotoK())) / ((
Minnaert *)p_atmosPM)->PhotoK();
   565       else if(phtName == 
"LUNARLAMBERT") {
   566         p_atmosAhTable[inccnt] = 2.0 * ((
LunarLambert *)p_atmosPM)->PhotoL() *
   567                                  log((1.0 + p_atmosMunot) / p_atmosMunot) + 1.0 -
   573         p_atmosAtmSwitch = 0;
   577         p_atmosAhTable[inccnt] = fun_temp / (90.0 * p_atmosMunot);
   581       if((inccnt == 0) || (inccnt == p_atmosNinc - 1)) {
   588       p_atmosAb = p_atmosAb + p_atmosAhTable[inccnt] * p_atmosMunot * p_atmosSini * factor;
   591     factor = 2.0 * 
PI / 180.0;
   592     p_atmosAb = p_atmosAb * factor;
   597     p_atmosAhSpline.Reset();
   598     p_atmosAhSpline.SetInterpType(NumericalApproximation::CubicClamped);
   599     p_atmosAhSpline.AddData(p_atmosIncTable, p_atmosAhTable);
   600     p_atmosAhSpline.SetCubicClampedEndptDeriv(yp1, yp2);
   631   void AtmosModel::GenerateHahgTables() {
   639     sub = NumericalAtmosApprox::OuterFunction;
   644     for(inccnt = 0; inccnt < p_atmosNinc; inccnt++) {
   645       p_atmosInc = (double) inccnt;
   646       p_atmosIncTable[inccnt] = p_atmosInc;
   647       p_atmosMunot = cos((
PI / 180.0) * p_atmosInc);
   648       p_atmosSini = sin((
PI / 180.0) * p_atmosInc);
   650       p_atmosAtmSwitch = 1;
   655       p_atmosHahgtTable[inccnt] = fun_temp * AtmosWha() / 360.0;
   656       p_atmosAtmSwitch = 2;
   660       hahgsb_temp = fun_temp * AtmosWha() / 360.0;
   662       if((inccnt == 0) || (inccnt == p_atmosNinc - 1)) {
   669       p_atmosHahgsb = p_atmosHahgsb + p_atmosSini * factor * hahgsb_temp;
   670       if(p_atmosInc == 0.0) {
   671         p_atmosHahgt0Table[inccnt] = 0.0;
   674         p_atmosAtmSwitch = 3;
   676         p_atmosHahgt0Table[inccnt] = fun_temp * AtmosWha() * p_atmosMunot / (360.0 * p_atmosSini);
   680     factor = 2.0 * 
PI / 180.0;
   681     p_atmosHahgsb = p_atmosHahgsb * factor;
   686     p_atmosHahgtSpline.Reset();
   687     p_atmosHahgtSpline.SetInterpType(NumericalApproximation::CubicClamped);
   688     p_atmosHahgtSpline.AddData(p_atmosIncTable, p_atmosHahgtTable);
   689     p_atmosHahgtSpline.SetCubicClampedEndptDeriv(yp1, yp2);
   691     p_atmosHahgt0Spline.Reset();
   692     p_atmosHahgt0Spline.SetInterpType(NumericalApproximation::CubicClamped);
   693     p_atmosHahgt0Spline.AddData(p_atmosIncTable, p_atmosHahgt0Table);
   694     p_atmosHahgt0Spline.SetCubicClampedEndptDeriv(yp1, yp2);
   720   void AtmosModel::GenerateHahgTablesShadow() {
   728     sub = NumericalAtmosApprox::OuterFunction;
   732     deltaInc = 90.0/(double)(nincl-1.0);
   734     for(inccnt = 0; inccnt < nincl; inccnt++) {
   735       p_atmosInc = deltaInc * (double) inccnt;
   736       p_atmosMunot = cos((
PI / 180.0) * p_atmosInc);
   737       p_atmosSini = sin((
PI / 180.0) * p_atmosInc);
   739       p_atmosAtmSwitch = 2;
   742       if (p_atmosInc >= 90.0) {
   748       if((inccnt == 0) || (inccnt == nincl - 1)) {
   754       p_atmosHahgsb = p_atmosHahgsb + p_atmosSini * factor * fun_temp *
   758     factor = 2.0 * deltaInc * 
PI / 180.0;
   759     p_atmosHahgsb = p_atmosHahgsb * factor;
   773   void AtmosModel::SetAtmosAtmSwitch(
const int atmswitch) {
   774     if(atmswitch < 0 || atmswitch > 3) {
   775       string msg = 
"Invalid value of atmospheric atmswitch [" + 
IString(atmswitch) + 
"]";
   779     p_atmosAtmSwitch = atmswitch;
   793   void AtmosModel::SetAtmosBha(
const double bha) {
   794     if(bha < -1.0 || bha > 1.0) {
   795       string msg = 
"Invalid value of Anisotropic atmospheric bha [" +
   814   void AtmosModel::SetAtmosHga(
const double hga) {
   815     if(hga <= -1.0 || hga >= 1.0) {
   816       string msg = 
"Invalid value of Hapke atmospheric hga [" + 
IString(hga) + 
"]";
   833   void AtmosModel::SetAtmosInc(
const double inc) {
   834     if(inc < 0.0 || inc > 90.0) {
   835       string msg = 
"Invalid value of atmospheric inc [" + 
IString(inc) + 
"]";
   840     p_atmosMunot = cos(inc * 
PI / 180.0);
   841     p_atmosSini = sin(inc * 
PI / 180.0);
   855   void AtmosModel::SetAtmosNulneg(
const string nulneg) {
   859     if(temp != 
"NO" && temp != 
"YES") {
   860       string msg = 
"Invalid value of Atmospheric nulneg [" + temp + 
"]";
   864     SetAtmosNulneg(temp.compare(
"YES") == 0);
   878   void AtmosModel::SetAtmosPhi(
const double phi) {
   879     if(phi < 0.0 || phi > 360.0) {
   880       string msg = 
"Invalid value of atmospheric phi [" + 
IString(phi) + 
"]";
   885     p_atmosCosphi = cos(phi * 
PI / 180.0);
   897   void AtmosModel::SetAtmosTau(
const double tau) {
   899       string msg = 
"Invalid value of Atmospheric tau [" + 
IString(tau) + 
"]";
   916   void AtmosModel::SetAtmosTauref(
const double tauref) {
   918       string msg = 
"Invalid value of Atmospheric tauref [" + 
IString(tauref) + 
"]";
   922     p_atmosTauref = tauref;
   935   void AtmosModel::SetAtmosWha(
const double wha) {
   936     if(wha <= 0.0 || wha > 1.0) {
   937       string msg = 
"Invalid value of Atmospheric wha [" + 
IString(wha) + 
"]";
   948   bool AtmosModel::TauOrWhaChanged()
 const {
   949     return (AtmosTau() != p_atmosTauold) || (AtmosWha() != p_atmosWhaold);
   962   void AtmosModel::SetAtmosHnorm(
const double hnorm) {
   964       QString msg = 
"Invalid value of Atmospheric hnorm [" + 
toString(hnorm) + 
"]";
   967     p_atmosHnorm = hnorm;
   977   void AtmosModel::SetAtmosIord(
const string offset) {
   981     if(temp != 
"NO" && temp != 
"YES") {
   982       string msg = 
"Invalid value of Atmospheric additive offset[" + temp + 
"]";
   986     SetAtmosIord(temp.compare(
"YES") == 0);
   996   void AtmosModel::SetAtmosEstTau(
const string esttau) {
  1000     if(temp != 
"NO" && temp != 
"YES") {
  1001       string msg = 
"Invalid value of Atmospheric optical depth estimation[" + temp + 
"]";
  1005     SetAtmosEstTau(temp.compare(
"YES") == 0);
 bool hasKeyword(const QString &name) const
Check to see if a keyword exists. 
 
const double PI
The mathematical constant PI. 
 
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes. 
 
Namespace for the standard library. 
 
QString toString(bool boolToConvert)
Global function to convert a boolean to a string. 
 
double RombergsMethod(AtmosModel *am, IntegFunc sub, double a, double b)
This variation on the NumericalApproximation method integrates a specified AtmosModel function rather...
 
void Reset()
Resets the state of the object. 
 
Contains multiple PvlContainers. 
 
#define _FILEINFO_
Macro for the filename and line number. 
 
Container for cube-like labels. 
 
Minnaert photometric model Derive model albedo using Minnaert equation. 
 
IntegFunc
This enum defines function to be integrated by Romberg's method. 
 
Adds specific functionality to C++ strings. 
 
Namespace for ISIS/Bullet specific routines. 
 
Lunar (Lommel-Seeliger)-Lambert law photometric model Derive model albedo for Lunar (Lommel-Seeliger)...
 
IString UpCase()
Converst any lower case characters in the object IString with uppercase characters. 
 
This class extends Isis::NumericalApproximation.