Skip to content

Commit

Permalink
clean up Phong scattering examples
Browse files Browse the repository at this point in the history
  • Loading branch information
phoebe-p committed Sep 21, 2024
1 parent 5d189ad commit afa8b02
Show file tree
Hide file tree
Showing 11 changed files with 264 additions and 157 deletions.
8 changes: 8 additions & 0 deletions docs/Examples/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,12 @@ structure are treated separately and can be simulated with different methods.
compare_models_3Jsolarcell_profile.ipynb
HIT_emissivity.ipynb

Full list of GitHub examples
-----------------------------

These examples are available in the `GitHub repository <https://github.com/qpv-research-group/rayflare/tree/devel/examples>`_; a list
is provided here to give an overview of what is covered in each example.



.. _solcore-education: https://qpv-research-group.github.io/solcore-education/solcore-workshop-2/schedule.html
62 changes: 50 additions & 12 deletions docs/Theory/polarization.rst
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
Treatment of polarization in ray-tracing
==========================================
Treatment of polarization
==========================

Note: for ray-tracing, the below applies to RayFlare version 2.0.0 (August 2024) and later.
Note: for ray-tracing, the below applies to RayFlare version 2.0.0 (September 2024) and later.

The polarization of light is a vector quantity that describes the orientation of the electric field of an electromagnetic
wave. In the context of ray-tracing, the polarization of light is important when considering the reflection and
transmission of light at interfaces. Across all methods (ray-tracing, RCWA and TMM) we decompose the polarization into two orthogonal components, *s* and *p*, following
transmission of light at interfaces. Across all methods (ray-tracing, RCWA and TMM) we decompose the polarization into
two orthogonal components, *s* and *p*, following
the standard convention: the s-polarization component is perpendicular to the plane of incidence (i.e. the plane which
contains the ray and the surface normal), while the p-polarization component is parallel to the plane of incidence.
This is defined with respect to the x-y plane, with the following convention for the direction of the incident ray and
Expand All @@ -26,12 +27,49 @@ The treatment of polarization in TMM and RCWA are described in the relevant publ
the original packages which are used by RayFlare for these methods (modified versions of the `tmm` Python package originally
developed by Steven Byrnes and :math:`\S^4`, originally developed by Victor Liu), and will not be discussed here.

For planar surfaces, the s and p planes directions stay the same throughout a simulations. However,
in ray-tracing, the s and p components of a ray relative to the surface it is hitting change depending on the
orientation of the ray and the surface, and so it is necessary to calculate the component of the ray which lies
in the s and p direction of the ray-surface plane. This is done by projecting the ray vector onto the s and p
directions
For planar surfaces, the *s* and *p* planes directions stay the same throughout a simulations. However,
for textured surfaces, the *s and *p* components of a ray relative to the surface it is hitting change depending on the
orientation of the ray and the surface. RayFlare stores information on the *s* and *p* components of the ray and the
vector directions of these polarizations (relative to the incidence definition, or the previous surface the ray interacted
with), in the ray object. Each time a ray interacts with a surface, the following steps happen:

1. Project the ray's current polarization vector directions onto the new vectors which define
the *s* and *p* directions for the ray-plane system for the ray's current interaction:

.. math::
\begin{aligned}
& \text{pol} = (s, p) \\
& \mathbf{\hat{s}}_{\text {new }}=\mathbf{\hat{d}} \times \mathbf{\hat{N}} \\
& f_s=s\left|\mathbf{\hat{s}} \cdot \mathbf{\hat{s}}_{\text {new }}\right|^2+p\left|\mathbf{p} \cdot \mathbf{\hat{s}}_{\text {new }}\right|^2 \\
& f_p=1-f_s
\end{aligned}
Here, the new *s* direction is given by the cross product of the rays incident direction and the normal
to the surface. We then project the two old polarization vectors onto this new *s* directions,
weighted by the old *s* and *p* components of the ray.

2. Calculate/look up :math:`R_s`, :math:`R_p`, :math:`T_s`, :math:`T_p`, which are the reflection and transmission coefficients
for *s* and *p* polarization (in the reference frame of the ray-plane system for the current surface interaction).
These can be calculated either with the Fresnel equations, or using the transfer-matrix method, but this does not
affect the treatment of polarization. The total reflection probability :math:`R = f_s R_s + f_p R_p` and total transmission
probability :math:`T = f_s T_s + f_p T_p` determine the probability the ray is reflected or transmitted.

3. After deciding whether the ray is transmitted or reflected, the new direction of the *p* vector is then given by the
cross product of the new *s* direction and the new ray direction, after reflection/refraction,
and the new *s* and *p* components of the ray are calculated from :math:`R_s` and :math:`R_p` (reflection) or
:math:`T_s` and :math:`T_p` (transmission):

.. math::
\begin{aligned}
& \mathbf{\hat{p}}_{\text {new }}=\mathbf{\hat{s}}_{\text {new }} \times \mathbf{\hat{d}_\text{new}} \\
& \text{pol}_{\text {new }}=(\frac{f_s R_s}{R}, \frac{f_p R_p}{R}) \qquad \text{or} \qquad (\frac{f_s T_s}{T}, \frac{f_p T_p}{T})\\
\end{aligned}
and the ray object is updated with the new polarization components and directions.





:math:`R_s`, :math:`R_s`, :math:`T_s`, :math:`T_p` are the reflection and transmission coefficients for s and p polarization.
These can be calculated either with the Fresnel equations, or using the transfer-matrix method, but this does
not affect the treatment of polarization
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
news
Installation/installation
Theory/theory
Theory/polarization
Examples/examples.rst
Matrix/matrix_method
Ray_tracing/ray_tracing
Expand Down
18 changes: 18 additions & 0 deletions docs/news.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,24 @@ To update to the latest version of RayFlare, run the following command in your t
pip install rayflare --upgrade
Version 2.0.0 released (2024-09-22)
------------------------------------
**Highlights:**

- Speed improvements for all ray-tracing calculations, using numba and more efficient lookup of TMM values.
- New analytical method for ray-tracing, which is much faster than full ray-tracing and can be used with full
accuracy for surfaces where the number of ray interactions is known exactly in advance (e.g. upright pyramids with
opening angles between 45 and 54 degrees).
- Rigorous treatment of polarization in ray-tracing (no changes to treatment of polarization in TMM and RCWA calculations).
- More detailed output from ray-tracing calculations
- More detailed output from RCWA calculations

**Possible backwards compatibility issues:**

- The (previously undocumented) returns from rt_structure.calculate with details on final ray directions and intensities
have been reorganized. See the docstring here.


Version 1.2.1 released (2023-11-19)
------------------------------------
**Highlights:**
Expand Down
4 changes: 2 additions & 2 deletions examples/analytical_rt_comparison.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from solcore.structure import Layer
from time import time

# TODO: fix
options = default_options()
wl = np.linspace(300, 1000, 30) * 1e-9

Expand All @@ -19,7 +20,6 @@
# options.x_limits = [2.5, 7.5]
# options.y_limits = [2.5, 7.5]
options.project_name = 'surface_comparison'
options.lambertian_approximation = 0
options.randomize_surface = True
options.phi_in = 20 * np.pi / 180
options.I_thresh = 0.0002
Expand Down Expand Up @@ -63,7 +63,7 @@
options.theta_in = degrees_in * np.pi / 180

start = time()
options.analytical_ray_tracing = 4

rat_a = rtstr_text.calculate(options)
print("analytical time taken: ", time() - start)

Expand Down
8 changes: 3 additions & 5 deletions examples/glass_GaAs_Si.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from solcore.structure import Layer
from rayflare.transfer_matrix_method import tmm_structure

# TODO: fix
options = default_options()
wl = np.linspace(300, 1150, 40) * 1e-9

Expand All @@ -21,7 +22,7 @@
options.project_name = 'thin_textured_Si'
options.lambertian_approximation = 0
options.randomize_surface = True
options.analytical_ray_tracing = True

options.theta_in = 30 * np.pi / 180
options.phi_in = 0 * np.pi / 180
options.I_thresh = 0.0002
Expand All @@ -34,8 +35,6 @@
GaAs = material("GaAs")()
glass = material("BK7")()

options.analytical_ray_tracing = 0

layers = [Layer(70e-9, SiN), Layer(100e-9, GaAs)]
# layers = [Layer(70e-9, SiN)]
# textured front, absorbing layer: A int 0 looks the same, but R is too high
Expand All @@ -59,10 +58,9 @@
)

options.pol = 'u'
options.analytical_ray_tracing = 2

RAT_u_a = rtstr_text.calculate(options)

options.analytical_ray_tracing = 0
RAT_u_f = rtstr_text.calculate(options)

titles = ['s', 'p', 'u']
Expand Down
Loading

0 comments on commit afa8b02

Please sign in to comment.