Skip to content

Commit

Permalink
Remove PartialExtinction codes from Bobbert_Vlieger_BRDF_Model, Subsu…
Browse files Browse the repository at this point in the history
…rface_Bobbert_Vlieger_BRDF_Model, Axisymmetric_Particle_BRDF_Model, and Subsurface_Axisymmetric_Particle and replace them with Specular(theta).

Add 90 degree phase to Bobbert_Vlieger_BRDF_Model, Subsurface_Bobbert_Vlieger_BRDF_Model, Axisymmetric_Particle_BRDF_Model, and Subsurface_Axisymmetric_Particle, so that the optical theorem works the same as for free space scatterers.

Correct JonesMatrix::hermitian() and add JonesMatrix::conj().
  • Loading branch information
thomas-germer committed Apr 26, 2021
1 parent 82c2795 commit 278f559
Show file tree
Hide file tree
Showing 12 changed files with 219 additions and 245 deletions.
7 changes: 4 additions & 3 deletions code/axipart.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,10 @@ namespace SCATMECH {
public:
Axisymmetric_Particle_BRDF_Model();

COMPLEX PartialExtinctionS(double theta);
COMPLEX PartialExtinctionP(double theta);
MuellerMatrix Specular(double theta);

//COMPLEX PartialExtinctionS(double theta);
//COMPLEX PartialExtinctionP(double theta);

protected:
void setup();
Expand Down Expand Up @@ -114,7 +116,6 @@ namespace SCATMECH {
void calculate_Z(double thetas);
void calculate_eIP(double phis);

COMPLEX PartialExtinction(double theta,int pol);

void iterative_improvement(ScatterTMatrix& Ainv, ScatterTMatrix& A,
std::vector<COMPLEX>& b,std::vector<COMPLEX>& x);
Expand Down
164 changes: 65 additions & 99 deletions code/axipart1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -581,112 +581,78 @@ namespace SCATMECH {
MMAX = 0;
}

COMPLEX
MuellerMatrix
Axisymmetric_Particle_BRDF_Model::
PartialExtinctionS(double theta)
{
return PartialExtinction(theta,1);
}

COMPLEX
Axisymmetric_Particle_BRDF_Model::
PartialExtinctionP(double theta)
{
return PartialExtinction(theta,0);
}

COMPLEX
Axisymmetric_Particle_BRDF_Model::
PartialExtinction(double theta,int pol)
Specular(double theta)
{
SETUP();

// This function returns the partial extinction cross section for
// an incident angle of theta and polarization pol, where the "partial"
// means the following: when type=0 or type=2, the reflectance changes
// by a factor exp(-sigma*density/cos(theta)) and for type=1 or type=3, the
// transmittance changes by a factor exp(-sigma*density/cos(theta). The total
// extinction cross section is the sum of these values for type=0 and type=1,
// for light incident downward, or the sum of these values for type=2 and type=3,
// for light incident upward. The value of the partial extinction cross
// section can be negative, which is an indication that the reflectance
// or transmittance is increased by the presence of the particle.
//

pol = pol ? 1 : 0;
vector<COMPLEX>& W = pol ? Ws : Wp;
vector<COMPLEX>& Z = pol ? Zs : Zp;
// This function returns the Mueller matrix specular reflectance (for type==0 or
// type==2) or the regular transmittance (for type==1 or type==3) for an incident
// angle of theta (in radians). The result is derived from the optical theorem
// and is only valid when density is suffiently low that multiple scattering
// between spheres can be neglected.

switch (type) {
case 0:
{
set_geometry(theta,theta,0.);
COMPLEX e = E(W,Z);
COMPLEX r = stack->r12(theta,lambda,vacuum,substrate)[pol];
r *= exp(2.*cI*qq*cos(theta));
double R = norm(r);
return 4.*pi/k*COMPLEX(0.,-1.)*(e/r)*R;
}
break;
case 1:
{
double index = substrate.n(lambda);
double sint = sin(theta)/index;
if (sint>=1. || substrate.k(lambda)!=0) return 0.;
double thetat = asin(sint);
set_geometry(theta,thetat,0.);
COMPLEX e = E(W,Z);
COMPLEX phase = exp(cI*qq*(cos(theta)-index*cos(thetat)));
double factor = cos(thetat)/cos(theta);
e /= phase;
COMPLEX t = stack->t12(theta,lambda,vacuum,substrate)[pol];
double T = norm(t)*factor*index;
return 4.*pi/k/sqrt(cube(index))/factor*COMPLEX(0.,-1.)*(e/t)*T;
}
break;
case 2:
{
set_geometry(theta,theta,0.);
COMPLEX e = E(W,Z);
double index = substrate.n(lambda);

COMPLEX sint = sin(theta)*index;
COMPLEX cost = sqrt(1.-sqr(sint));
if (imag(cost)<0) cost = -cost;

COMPLEX r = stack->r21i(theta,lambda,substrate,vacuum)[pol];
double R = norm(r);

r *= exp(-2.*cI*qq*index*cos(theta));

return 4.*pi/k/index*COMPLEX(0.,-1.)*(e/r)*R;
}
break;
case 3:
{
double index = substrate.n(lambda);
double sint = sin(theta)*index;
COMPLEX cost = sqrt(1.-sqr(sint));
if (imag(cost)<0) cost = -cost;
if (sint>=1.) return 0.;
double thetat = asin(sint);

set_geometry(theta,thetat,0.);
COMPLEX e = E(W,Z);

double factor = cos(theta)/real(cost);
COMPLEX phase = exp(cI*qq*(cost-index*cos(theta)));

e /= phase;
COMPLEX t = stack->t21i(theta,lambda,substrate,vacuum)[pol];
double T = norm(t)/index/factor;
return 4.*pi/k*sqrt(index)*factor*COMPLEX(0.,-1.)*(e/t)*T;
}
break;
default:
error("Invalid type = " + to_string(type));
case 0:
{
JonesMatrix X = JonesDSC(theta, theta, 0., 0.);
JonesMatrix r = stack->r12(theta, lambda, vacuum, substrate);
r *= exp(2. * cI * qq * cos(theta));
MuellerMatrix sigma = (4. * pi / k) * ReCrossMueller(X, r);

return MuellerMatrix(r) - sigma * (density / cos(theta));
}
break;
case 1:
{
double index = substrate.n(lambda);
double sint = sin(theta) / index;
if (sint >= 1. || substrate.k(lambda) != 0) return MuellerZero();
double thetat = asin(sint);
JonesMatrix X = JonesDSC(theta, thetat, 0., 0.);
COMPLEX phase = exp(cI * qq * (cos(theta) - index * cos(thetat)));
//double factor = cos(thetat)/cos(theta);
JonesMatrix t = stack->t12(theta, lambda, vacuum, substrate);
t *= phase;
MuellerMatrix sigma = (4. * pi / k / sqrt(index)) * ReCrossMueller(X, t);

return MuellerMatrix(t) * (cos(thetat) / cos(theta) * index) - sigma * (density / cos(theta));
}
break;
case 2:
{
double index = substrate.n(lambda);
JonesMatrix X = JonesDSC(theta, theta, 0., 0.);
JonesMatrix r = stack->r21i(theta, lambda, substrate, vacuum);
r *= exp(-2. * cI * index * qq * cos(theta));
MuellerMatrix sigma = (4. * pi / k / index) * ReCrossMueller(X, r);

return MuellerMatrix(r) - sigma * (density / cos(theta));
}
break;
case 3:
{
double index = substrate.n(lambda);
double sint = sin(theta) * index;
COMPLEX cost = sqrt(1. - sqr(sint));
if (imag(cost) < 0) cost = -cost;
if (sint >= 1.) return MuellerZero();
double thetat = asin(sint);
JonesMatrix X = JonesDSC(theta, thetat, 0., 0.);
COMPLEX phase = exp(cI * qq * (cost - index * cos(theta)));
//double factor = cos(thetat)/cos(theta);
JonesMatrix t = stack->t21i(theta, lambda, substrate, vacuum);
t *= phase;
MuellerMatrix sigma = (4. * pi / k / sqrt(index)) * ReCrossMueller(X, t);

return MuellerMatrix(t) * (cos(theta) / index / cos(thetat)) - sigma * (density / cos(theta));
}
break;
default:
error("Invalid type = " + to_string(type));
}
return 0;
return MuellerZero();
}

DEFINE_MODEL(Axisymmetric_Particle_BRDF_Model,Local_BRDF_Model,
Expand Down
2 changes: 1 addition & 1 deletion code/axipart2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ namespace SCATMECH {
}
}

return E;
return COMPLEX(0, -1) * E;
}


Expand Down
16 changes: 3 additions & 13 deletions code/bobvlieg.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,9 @@ namespace SCATMECH {

public:
Bobbert_Vlieger_BRDF_Model();

// The real part of the following are the partial extinction cross
// sections for S or P polarization, respectively, where the "partial"
// means that when type=0, the downward reflectance is reduced by the
// result, when type=1, the downward transmittance is reduced by the result,
// when type=2, the upward reflectance is reduced by the result, and
// when type=3, the upward transmittance is reduced by the result.
// The total extinction cross section can be obtained by summing these
// values for type=0 and type=1 or for type=2 and type=3.
COMPLEX PartialExtinctionS(double theta);
COMPLEX PartialExtinctionP(double theta);

// The Mueller matrix specular reflectance or regular transmittance...
MuellerMatrix Specular(double theta);

protected:
void setup();
Expand Down Expand Up @@ -135,8 +127,6 @@ namespace SCATMECH {
void calculate_Z(double thetas);
void calculate_eIP(double phis);

COMPLEX PartialExtinction(double theta,int pol);

void iterative_improvement(ScatterTMatrix& Ainv, ScatterTMatrix& A,
std::vector<COMPLEX>& b,std::vector<COMPLEX>& x);
};
Expand Down
Loading

0 comments on commit 278f559

Please sign in to comment.