|
Isis 3.0 Object Programmers' Reference |
Home |
00001 #include <cmath> 00002 #include "Anisotropic1.h" 00003 #include "AtmosModel.h" 00004 #include "iException.h" 00005 #include "iString.h" 00006 00007 using std::max; 00008 00009 namespace Isis { 00010 Anisotropic1::Anisotropic1 (Pvl &pvl, PhotoModel &pmodel) : AtmosModel(pvl,pmodel) { 00011 00012 // Set default values 00013 p_atmosAlpha0_0 = 0.0; 00014 p_atmosAlpha1_0 = 0.0; 00015 p_atmosBeta0_0 = 0.0; 00016 p_atmosBeta1_0 = 0.0; 00017 p_atmosDelta_0 = 0.0; 00018 p_atmosDelta_1 = 0.0; 00019 p_atmosDen = 0.0; 00020 p_atmosE2 = 0.0; 00021 p_atmosE3 = 0.0; 00022 p_atmosE4 = 0.0; 00023 p_atmosE5 = 0.0; 00024 p_atmosFac = 0.0; 00025 p_atmosHnorm = 0.003; 00026 p_atmosP0 = 0.0; 00027 p_atmosP1 = 0.0; 00028 p_atmosQ0 = 0.0; 00029 p_atmosQ02p02 = 0.0; 00030 p_atmosQ1 = 0.0; 00031 p_atmosQ12p12 = 0.0; 00032 p_atmosWha2 = 0.0; 00033 p_atmosWham = 0.0; 00034 p_atmosX0_0 = 0.0; 00035 p_atmosX0_1 = 0.0; 00036 p_atmosY0_0 = 0.0; 00037 p_atmosY0_1 = 0.0; 00038 00039 } 00040 00051 void Anisotropic1::SetAtmosHnorm (const double hnorm) { 00052 if (hnorm < 0.0) { 00053 std::string msg = "Invalid value of Atmospheric hnorm [" + 00054 iString(hnorm) + "]"; 00055 throw iException::Message(iException::User,msg,_FILEINFO_); 00056 } 00057 00058 p_atmosHnorm = hnorm; 00059 } 00060 00082 void Anisotropic1::AtmosModelAlgorithm (double phase, double incidence, double emission) 00083 { 00084 double hpsq1; 00085 double munot,munotp; 00086 double maxval; 00087 double mu,mup; 00088 double xx; 00089 double emunot,emu; 00090 double gmunot,gmu; 00091 double sum,prod; 00092 double cosazss; 00093 double xmunot_0,ymunot_0; 00094 double xmu_0,ymu_0; 00095 double xmunot_1,ymunot_1; 00096 double xmu_1,ymu_1; 00097 double cxx,cyy; 00098 double xystuff; 00099 00100 if (p_atmosBha == 0.0) { 00101 p_atmosBha = 1.0e-6; 00102 } 00103 00104 if (p_atmosTau == 0.0) { 00105 p_pstd = 0.0; 00106 p_trans = 1.0; 00107 p_trans0 = 1.0; 00108 p_sbar = 0.0; 00109 return; 00110 } 00111 00112 if (p_atmosWha == 1.0) { 00113 std::string msg = "Anisotropic conservative case not implemented yet"; 00114 throw iException::Message(iException::User,msg,_FILEINFO_); 00115 } 00116 00117 if (TauOrWhaChanged()) { 00118 // preparation includes exponential integrals e sub 2 through 5 00119 p_atmosWha2 = 0.5 * p_atmosWha; 00120 p_atmosWham = 1.0 - p_atmosWha; 00121 p_atmosE2 = AtmosModel::En(2,p_atmosTau); 00122 p_atmosE3 = AtmosModel::En(3,p_atmosTau); 00123 p_atmosE4 = AtmosModel::En(4,p_atmosTau); 00124 p_atmosE5 = AtmosModel::En(5,p_atmosTau); 00125 // first, get the required quantities for the axisymmetric m=0 part 00126 // zeroth moments of (uncorrected) x and y times characteristic fn 00127 p_atmosX0_0 = p_atmosWha2 * (1.0 + (1.0/3.0) * p_atmosBha * 00128 p_atmosWham); 00129 p_atmosY0_0 = p_atmosWha2 * (p_atmosE2 + p_atmosBha * p_atmosWham * 00130 p_atmosE4); 00131 // higher-order correction term for x and y 00132 p_atmosDelta_0 = (1.0 - (p_atmosX0_0 + p_atmosY0_0) - (1.0 - p_atmosWha * 00133 (1.0 + (1.0/3.0) * p_atmosBha * p_atmosWham)) / (1.0 - 00134 (p_atmosX0_0 - p_atmosY0_0))) / (p_atmosWha * (0.5 - p_atmosE3 + 00135 p_atmosBha * p_atmosWham * (0.25 - p_atmosE5))); 00136 00137 // moments of (corrected) x and y 00138 p_atmosAlpha0_0 = 1.0 + p_atmosDelta_0 * (0.5 - p_atmosE3); 00139 p_atmosAlpha1_0 = 0.5 + p_atmosDelta_0 * ((1.0/3.0) - p_atmosE4); 00140 p_atmosBeta0_0 = p_atmosE2 + p_atmosDelta_0 * (0.5 - p_atmosE3); 00141 p_atmosBeta1_0 = p_atmosE3 + p_atmosDelta_0 * ((1.0/3.0) - p_atmosE4); 00142 // gamma will be a weighted sum of m=0 x and y functions 00143 // but unlike before, call the weights q1 and p1, and we also 00144 // need additional weights q0 and p0 00145 p_atmosFac = 2.0 - p_atmosWha * p_atmosAlpha0_0; 00146 p_atmosDen = pow(p_atmosFac,2.0) - pow(p_atmosWha*p_atmosBeta0_0,2.0); 00147 p_atmosQ0 = p_atmosBha * p_atmosWha * p_atmosWham * (p_atmosFac * 00148 p_atmosAlpha1_0 - p_atmosWha * p_atmosBeta0_0 * p_atmosBeta1_0) / 00149 p_atmosDen; 00150 p_atmosP0 = p_atmosBha * p_atmosWha * p_atmosWham * (-p_atmosFac * 00151 p_atmosBeta1_0 - p_atmosWha * p_atmosBeta0_0 * p_atmosAlpha1_0) / 00152 p_atmosDen; 00153 p_atmosQ02p02 = p_atmosQ0 * p_atmosQ0 - p_atmosP0 * p_atmosP0; 00154 p_atmosQ1 = (2.0 * p_atmosWham * p_atmosFac) / p_atmosDen; 00155 p_atmosP1 = (2.0 * p_atmosWham * p_atmosWha * p_atmosBeta0_0) / 00156 p_atmosDen; 00157 p_atmosQ12p12 = p_atmosQ1 * p_atmosQ1 - p_atmosP1 * p_atmosP1; 00158 // sbar is total diffuse illumination and comes from moments 00159 p_sbar = 1.0 - 2.0 * (p_atmosQ1 * p_atmosAlpha1_0 + p_atmosP1 * 00160 p_atmosBeta1_0); 00161 // we're not done yet! still have to calculate the m=1 portion 00162 // zeroth moments of (uncorrected) x and y times characteristic fn 00163 p_atmosX0_1 = 0.5 * p_atmosWha2 * p_atmosBha * (1.0 - (1.0/3.0)); 00164 p_atmosY0_1 = 0.5 * p_atmosWha2 * p_atmosBha * (p_atmosE2 - p_atmosE4); 00165 // higher-order correction term for x and y 00166 p_atmosDelta_1 = (1.0 - (p_atmosX0_1 + p_atmosY0_1) - (1.0 - 00167 (1.0/3.0) * p_atmosWha * p_atmosBha) / (1.0 - (p_atmosX0_1 - 00168 p_atmosY0_1))) / (p_atmosWha2 * p_atmosBha * ((0.5 - 0.25) - 00169 (p_atmosE3 - p_atmosE5))); 00170 // moments of (corrected) x and y are not needed for m=1, so we're done 00171 SetOldTau(p_atmosTau); 00172 SetOldWha(p_atmosWha); 00173 } 00174 00175 // correct the path lengths for planetary curvature 00176 hpsq1 = pow((1.0+p_atmosHnorm),2.0) - 1.0; 00177 00178 if (incidence == 90.0) { 00179 munot = 0.0; 00180 } 00181 else { 00182 munot = cos((PI/180.0)*incidence); 00183 } 00184 00185 maxval = max(1.0e-30,hpsq1+munot*munot); 00186 munotp = p_atmosHnorm / (sqrt(maxval) - munot); 00187 munotp = max(munotp,p_atmosTau/69.0); 00188 if (emission == 90.0) { 00189 mu = 0.0; 00190 } 00191 else { 00192 mu = cos((PI/180.0)*emission); 00193 } 00194 00195 maxval = max(1.0e-30,hpsq1+mu*mu); 00196 mup = p_atmosHnorm / (sqrt(maxval) - mu); 00197 mup = max(mup,p_atmosTau/69.0); 00198 // build the x and y functions of mu0 and mu 00199 maxval = max(1.0e-30,munotp); 00200 xx = -p_atmosTau / maxval; 00201 00202 if (xx < -69.0) { 00203 emunot = 0.0; 00204 } 00205 else if (xx > 69.0) { 00206 emunot = 1.0e30; 00207 } 00208 else { 00209 emunot = exp(-p_atmosTau/munotp); 00210 } 00211 00212 maxval = max(1.0e-30,mup); 00213 xx = -p_atmosTau / maxval; 00214 00215 if (xx < -69.0) { 00216 emu = 0.0; 00217 } 00218 else if (xx > 69.0) { 00219 emu = 1.0e30; 00220 } 00221 else { 00222 emu = exp(-p_atmosTau/mup); 00223 } 00224 00225 // first for m=0 00226 xmunot_0 = 1.0 + p_atmosDelta_0 * munotp * (1.0 - emunot); 00227 ymunot_0 = emunot + p_atmosDelta_0 * munotp * (1.0 - emunot); 00228 xmu_0 = 1.0 + p_atmosDelta_0 * mup * (1.0 - emu); 00229 ymu_0 = emu + p_atmosDelta_0 * mup * (1.0 - emu); 00230 00231 // then for m=1 00232 xmunot_1 = 1.0 + p_atmosDelta_1 * munotp * (1.0 - emunot); 00233 ymunot_1 = emunot + p_atmosDelta_1 * munotp * (1.0 - emunot); 00234 xmu_1 = 1.0 + p_atmosDelta_1 * mup * (1.0 - emu); 00235 ymu_1 = emu + p_atmosDelta_1 * mup * (1.0 - emu); 00236 00237 // gamma1 functions come from x and y with m=0 00238 gmunot = p_atmosP1 * xmunot_0 + p_atmosQ1 * ymunot_0; 00239 gmu = p_atmosP1 * xmu_0 + p_atmosQ1 * ymu_0; 00240 00241 // purely atmos term uses x and y of both orders and is complex 00242 sum = munot + mu; 00243 prod = munot * mu; 00244 cxx = 1.0 - p_atmosQ0 * sum + (p_atmosQ02p02 - p_atmosBha * 00245 p_atmosQ12p12) * prod; 00246 cyy = 1.0 + p_atmosQ0 * sum + (p_atmosQ02p02 - p_atmosBha * 00247 p_atmosQ12p12) * prod; 00248 00249 if (phase == 90.0) { 00250 cosazss = 0.0 - munot * mu; 00251 } 00252 else { 00253 cosazss = cos((PI/180.0)*phase) - munot * mu; 00254 } 00255 00256 xystuff = cxx * xmunot_0 * xmu_0 - cyy * ymunot_0 * 00257 ymu_0 - p_atmosP0 * sum * (xmu_0 * ymunot_0 + ymu_0 * 00258 xmunot_0) + cosazss * p_atmosBha * (xmu_1 * 00259 xmunot_1 - ymu_1 * ymunot_1); 00260 p_pstd = 0.25 * p_atmosWha * munotp / (munotp + mup) * xystuff; 00261 00262 // xmitted surface term uses gammas from m=0 00263 p_trans = gmunot * gmu; 00264 00265 // finally, never-scattered term is given by pure attenuation 00266 p_trans0 = emunot * emu; 00267 } 00268 } 00269 00270 extern "C" Isis::AtmosModel *Anisotropic1Plugin (Isis::Pvl &pvl, Isis::PhotoModel &pmodel) { 00271 return new Isis::Anisotropic1(pvl,pmodel); 00272 }