//****************************************************************************** //** SCATMECH: Polarized Light Scattering C++ Class Library //** //** File: rough.cpp //** //** Thomas A. Germer //** Sensor Science Division, National Institute of Standards and Technology //** 100 Bureau Dr. Stop 8443; Gaithersburg, MD 20899-8443 //** Phone: (301) 975-2876 //** Email: thomas.germer@nist.gov //** //****************************************************************************** #include "scatmech.h" #include "rough.h" using namespace std; namespace SCATMECH { // // Routine to get the isotropic spatial frequency... // void Roughness_BRDF_Model:: Bragg_Frequency(double& fx,double& fy) { double _fx,_fy; switch (type) { case Type_DOWNUP: { _fx = sin(thetas)*cos(phis)-sin(thetai); _fy = sin(thetas)*sin(phis); } break; case Type_DOWNDOWN: { double m = substrate.n(lambda); _fx = sin(thetas)*cos(phis)*m-sin(thetai); _fy = sin(thetas)*sin(phis)*m; } break; case Type_UPDOWN: { double m = substrate.n(lambda); _fx = sin(thetas)*cos(phis)*m-sin(thetai)*m; _fy = sin(thetas)*sin(phis)*m; } break; case Type_UPUP: { double m = substrate.n(lambda); _fx = sin(thetas)*cos(phis)-sin(thetai)*m; _fy = sin(thetas)*sin(phis); } break; default: error("Invalid value for BRDF_Model::type = " + to_string(type)); } _fx = _fx/lambda; _fy = _fy/lambda; double cosrot = cos(rotation); double sinrot = sin(rotation); fx = cosrot*_fx + sinrot*_fy; fy = -sinrot*_fx + cosrot*_fy; } double ABC_PSD_Function:: psd(double f) { SETUP(); return A/pow(1+sqr(B*f),C/2); } double Table_PSD_Function:: psd(double f) { SETUP(); return T.value(f); } double Fractal_PSD_Function:: psd(double f) { SETUP(); return A/pow(f,exponent); } void Gaussian_PSD_Function:: setup() { PSD_Function::setup(); A = pi*sqr(sigma*length); B = pi*length; } double Gaussian_PSD_Function:: psd(double f) { SETUP(); return A*exp(-sqr(B*f)); } /* THIS SECTION REMOVED SINCE COMPILERS NOW INCLUDE BESSEL FUNCTIONS j0, j1, and jn ... static double poly(double x,double* coeff,int n) { double accum=0.; for (int i=0; i0) return j1pos(x); else return -j1pos(-x); } */ #ifdef _MSC_VER #define J1(x) _j1(x) #define Jn(n,x) _jn(n,x) #else #define J1(x) j1(x) #define Jn(n,x) jn(n,x) #endif double Elliptical_Mesa_PSD_Function:: psd(double fx,double fy) { SETUP(); double f = sqrt(sqr(fx*axisx/2.)+sqr(fy*axisy/2.)); double rx_ry = axisx*axisy/4.; //double temp = (f!=0) ? _j1(2*pi*f)/f : pi; double temp = (f!=0) ? J1(2*pi*f)/f : pi; return sqr(rx_ry*temp*height)*density; } static double sinc(double x) { if (x==0.) return 1; else return sin(x)/x; } double Rectangular_Mesa_PSD_Function:: psd(double fx,double fy) { SETUP(); return sqr(lengthx*lengthy*sinc(fx*lengthx*pi)*sinc(fy*lengthy*pi)*height)*density; } double Triangular_Mesa_PSD_Function:: psd(double fx,double fy) { SETUP(); static const double sqrt3=sqrt(3.); static const COMPLEX i(0,1); COMPLEX s; double eps = 1./side*0.000001; if (fabs(fy)psd(fx,fy) + psd2->psd(fx,fy); } void Register(const PSD_Function* x) { static bool Models_Registered = false; if (!Models_Registered) { Models_Registered=true; Register_Model(PSD_Function); Register_Model(Unit_PSD_Function); Register_Model(ABC_PSD_Function); Register_Model(Table_PSD_Function); Register_Model(Fractal_PSD_Function); Register_Model(Gaussian_PSD_Function); Register_Model(Elliptical_Mesa_PSD_Function); Register_Model(Rectangular_Mesa_PSD_Function); Register_Model(Triangular_Mesa_PSD_Function); Register_Model(Rectangular_Pyramid_PSD_Function); Register_Model(Triangular_Pyramid_PSD_Function); Register_Model(Parabolic_Dimple_PSD_Function); Register_Model(Double_PSD_Function); } } DEFINE_VIRTUAL_MODEL(Roughness_BRDF_Model,BRDF_Model, "Scattering by a rough surface in the smooth surface limit."); DEFINE_PTRPARAMETER(Roughness_BRDF_Model,PSD_Function_Ptr,psd,"Power spectral density function","ABC_PSD_Function",0xFF); DEFINE_VIRTUAL_MODEL(PSD_Function,Model, "Virtual class for Power Spectral Density functions"); DEFINE_MODEL(Unit_PSD_Function,PSD_Function, "Unit power spectrum"); DEFINE_MODEL(ABC_PSD_Function,PSD_Function, "PSD = A/pow(1+sqr(B*f),C/2)"); DEFINE_PARAMETER(ABC_PSD_Function,double,A,"Program assumes power spectrum S2(f) = " "A/(1+(B*f)^2)^(C/2)\n" "Power Spectrum A Parameter [um^4]","0.01",0xFF); DEFINE_PARAMETER(ABC_PSD_Function,double,B,"Power Spectrum B Parameter [um]","362",0xFF); DEFINE_PARAMETER(ABC_PSD_Function,double,C,"Power Spectrum C Parameter","2.5",0xFF); DEFINE_MODEL(Table_PSD_Function,PSD_Function, "PSD given by a table of values."); DEFINE_PARAMETER(Table_PSD_Function,Table,T,"Table of PSD versus spatial frequency","1",0xFF); DEFINE_MODEL(Fractal_PSD_Function, PSD_Function, "A PSD with a fractal behavior"); DEFINE_PARAMETER(Fractal_PSD_Function,double,A,"Power spectrum amplitude parameter","0.01",0xFF); DEFINE_PARAMETER(Fractal_PSD_Function,double,exponent,"Power spectrum exponent","2.5",0xFF); DEFINE_MODEL(Gaussian_PSD_Function, PSD_Function, "A PSD with gaussian statistics"); DEFINE_PARAMETER(Gaussian_PSD_Function,double,sigma,"Standard deviation of height [um]","0.05",0xFF); DEFINE_PARAMETER(Gaussian_PSD_Function,double,length,"Correlation length [um]","5",0xFF); DEFINE_MODEL(Elliptical_Mesa_PSD_Function, PSD_Function, "PSD for elliptical mesas or depressions"); DEFINE_PARAMETER(Elliptical_Mesa_PSD_Function,double,axisx,"Axis of mesas along x-direction [um]","1.5",0xFF); DEFINE_PARAMETER(Elliptical_Mesa_PSD_Function,double,axisy,"Axis of mesas along y-direction [um]","1.5",0xFF); DEFINE_PARAMETER(Elliptical_Mesa_PSD_Function,double,height,"Height or depth of mesas [um]","0.01",0xFF); DEFINE_PARAMETER(Elliptical_Mesa_PSD_Function,double,density,"Surface number density of mesas [um^-2]","0.01",0xFF); DEFINE_MODEL(Rectangular_Mesa_PSD_Function, PSD_Function, "PSD for rectangular mesas or depressions"); DEFINE_PARAMETER(Rectangular_Mesa_PSD_Function,double,lengthx,"Length of mesas along x-direction [um]","1.5",0xFF); DEFINE_PARAMETER(Rectangular_Mesa_PSD_Function,double,lengthy,"Length of mesas along y-direction [um]","1.5",0xFF); DEFINE_PARAMETER(Rectangular_Mesa_PSD_Function,double,height,"Height or depth of mesas [um]","0.01",0xFF); DEFINE_PARAMETER(Rectangular_Mesa_PSD_Function,double,density,"Surface number density of mesas [um^-2]","0.01",0xFF); DEFINE_MODEL(Triangular_Mesa_PSD_Function, PSD_Function, "PSD for isosceles mesas or depressions"); DEFINE_PARAMETER(Triangular_Mesa_PSD_Function,double,side,"Length of side of triangle [um]","1.5",0xFF); DEFINE_PARAMETER(Triangular_Mesa_PSD_Function,double,height,"Height or depth of mesas [um]","0.01",0xFF); DEFINE_PARAMETER(Triangular_Mesa_PSD_Function,double,density,"Surface number density of mesas [um^-2]","0.01",0xFF); DEFINE_MODEL(Rectangular_Pyramid_PSD_Function, PSD_Function, "PSD for rectangular pyramids."); DEFINE_PARAMETER(Rectangular_Pyramid_PSD_Function,double,lengthx,"Length of side of pyramid in x-direction [um]","1.5",0xFF); DEFINE_PARAMETER(Rectangular_Pyramid_PSD_Function,double,lengthy,"Length of side of pyramid in y-direction [um]","1.5",0xFF); DEFINE_PARAMETER(Rectangular_Pyramid_PSD_Function,double,height,"Height or depth of pyramid [um]","0.01",0xFF); DEFINE_PARAMETER(Rectangular_Pyramid_PSD_Function,double,density,"Surface number density of pyramids [um^-2]","0.01",0xFF); DEFINE_MODEL(Triangular_Pyramid_PSD_Function, PSD_Function, "PSD for triangular pyramids."); DEFINE_PARAMETER(Triangular_Pyramid_PSD_Function,double,length,"Length of side of base of pyramid [um]","1.5",0xFF); DEFINE_PARAMETER(Triangular_Pyramid_PSD_Function,double,height,"Height or depth of pyramid [um]","0.01",0xFF); DEFINE_PARAMETER(Triangular_Pyramid_PSD_Function,double,density,"Surface number density of pyramids [um^-2]","0.01",0xFF); DEFINE_MODEL(Parabolic_Dimple_PSD_Function, PSD_Function, "PSD for parabolic bumps or dimples"); DEFINE_PARAMETER(Parabolic_Dimple_PSD_Function,double,axisx,"Axis of feature along x-direction [um]","1.5",0xFF); DEFINE_PARAMETER(Parabolic_Dimple_PSD_Function,double,axisy,"Axis of feature along y-direction [um]","1.5",0xFF); DEFINE_PARAMETER(Parabolic_Dimple_PSD_Function,double,height,"Height or depth of features [um]","0.01",0xFF); DEFINE_PARAMETER(Parabolic_Dimple_PSD_Function,double,density,"Surface number density of features [um^-2]","0.01",0xFF); DEFINE_MODEL(Double_PSD_Function, PSD_Function, "Sum of two PSD functions"); DEFINE_PTRPARAMETER(Double_PSD_Function,PSD_Function_Ptr,psd1,"First PSD Function","ABC_PSD_Function",0xFF); DEFINE_PTRPARAMETER(Double_PSD_Function,PSD_Function_Ptr,psd2,"Second PSD Function","ABC_PSD_Function",0xFF); } // namespace SCATMECH