USGS

Isis 3.0 Object Programmers' Reference

Home

AlbedoAtm.cpp

00001 #include <cmath>
00002 #include "AlbedoAtm.h"
00003 #include "NumericalApproximation.h"
00004 #include "iException.h"
00005 
00006 #define MIN(x,y) (((x) < (y)) ? (x) : (y))
00007 #define MAX(x,y) (((x) > (y)) ? (x) : (y))
00008 
00009 namespace Isis {
00022   AlbedoAtm::AlbedoAtm (Pvl &pvl, PhotoModel &pmodel, AtmosModel &amodel) :
00023       NormModel(pvl,pmodel,amodel) {
00024     PvlGroup &algo = pvl.FindObject("NormalizationModel")
00025                      .FindGroup("Algorithm",Pvl::Traverse);
00026     // Set default value
00027     SetNormIncref(0.0);
00028     // Get value from user
00029     if (algo.HasKeyword("Incref")) {
00030       SetNormIncref(algo["Incref"]);
00031     }
00032 
00033     // First-time setup:
00034     // Calculate normalization at standard conditions
00035     GetPhotoModel()->SetStandardConditions(true);
00036     p_normPsurfref = GetPhotoModel()->CalcSurfAlbedo(p_normIncref, p_normIncref,0.0);
00037     GetPhotoModel()->SetStandardConditions(false);
00038 
00039     // Get reference hemispheric albedo
00040     GetAtmosModel()->GenerateAhTable();
00041 
00042     p_normAhref = (GetAtmosModel()->AtmosAhSpline()).Evaluate(p_normIncref, NumericalApproximation::Extrapolate);
00043 
00044     p_normMunotref = cos((PI/180.0)*p_normIncref);
00045 
00046     // Now calculate atmosphere at standard conditions
00047     GetAtmosModel()->SetStandardConditions(true);
00048     GetAtmosModel()->CalcAtmEffect(p_normIncref,p_normIncref,0.0,
00049                                    &p_normPstdref,&p_normTransref,
00050                                    &p_normTrans0ref,&p_normSbar);
00051     GetAtmosModel()->SetStandardConditions(false);
00052   }
00053 
00067   void AlbedoAtm::NormModelAlgorithm (double phase, double incidence, 
00068       double emission, double dn, double &albedo, double &mult, double &base)
00069   {
00070     double psurf;
00071     double ahInterp;
00072     double munot;
00073     double pstd;
00074     double trans;
00075     double trans0;
00076     double rho;
00077     double dpo;
00078     double q;
00079     double dpm;
00080     double firsterm;
00081     double secondterm;
00082     double thirdterm;
00083     double fourthterm;
00084     double fifthterm;
00085 
00086     psurf = GetPhotoModel()->CalcSurfAlbedo(phase,incidence,
00087         emission);
00088 
00089     ahInterp = (GetAtmosModel()->AtmosAhSpline()).Evaluate(incidence, NumericalApproximation::Extrapolate);
00090 
00091     munot = cos(incidence*(PI/180.0));
00092     GetAtmosModel()->CalcAtmEffect(phase,incidence,emission,&pstd,&trans,&trans0,&p_normSbar);
00093 
00094     // With model at actual geometry, calculate rho from dn
00095     dpo = dn - pstd;
00096     dpm = (psurf - ahInterp * munot) * trans0;
00097     q = ahInterp * munot * trans + GetAtmosModel()->AtmosAb() * p_normSbar * dpo + dpm;
00098 
00099     if (dpo <= 0.0 && GetAtmosModel()->AtmosNulneg()) {
00100       rho = 0.0;
00101     }
00102     else {
00103       firsterm = GetAtmosModel()->AtmosAb() * p_normSbar;
00104       secondterm = dpo * dpm;
00105       thirdterm = firsterm * secondterm;
00106       fourthterm = pow(q,2.0) - 4.0 * thirdterm;
00107 
00108       if (fourthterm < 0.0) {
00109         std::string msg = "Square root of negative encountered";
00110         throw iException::Message(iException::Math,msg,_FILEINFO_);
00111       }
00112       else {
00113         fifthterm = q + sqrt(fourthterm);
00114       }
00115 
00116       rho = 2 * dpo / fifthterm;
00117     }
00118 
00119     // Now use rho and reference geometry to calculate output dnout
00120     if ((1.0-rho*GetAtmosModel()->AtmosAb()*p_normSbar) <= 0.0) {
00121       std::string msg = "Divide by zero encountered";
00122       throw iException::Message(iException::Math,msg,_FILEINFO_);
00123     }
00124     else {
00125       albedo = p_normPstdref + rho * (p_normAhref * p_normMunotref * 
00126           p_normTransref / (1.0 - rho * GetAtmosModel()->AtmosAb() * 
00127                 p_normSbar) + (p_normPsurfref - p_normAhref * 
00128                 p_normMunotref) * p_normTrans0ref);
00129     }
00130   }
00131 
00141   void AlbedoAtm::SetNormIncref (const double incref) {
00142     if (incref < 0.0 || incref >= 90.0) {
00143       std::string msg = "Invalid value of normalization incref [" +
00144           iString(incref) + "]";
00145       throw iException::Message(iException::User,msg,_FILEINFO_);
00146     }
00147 
00148     p_normIncref = incref;
00149   }
00150 }
00151 
00152 extern "C" Isis::NormModel *AlbedoAtmPlugin (Isis::Pvl &pvl, Isis::PhotoModel &pmodel, Isis::AtmosModel &amodel) {
00153   return new Isis::AlbedoAtm(pvl,pmodel,amodel);
00154 }