differt.em.sp_directions#
- sp_directions(k_i, k_r, normals)[source]#
Compute the directions of the local s and p components, before and after reflection, relative to the propagation direction and a local normal.
- Parameters:
k_i (
Float[ArrayLike, '*#batch 3']) –The array of propagation direction of incident fields.
Each vector must have a unit length.
k_r (
Float[ArrayLike, '*#batch 3']) –The array of propagation direction of reflected fields.
Each vector must have a unit length.
normals (
Float[ArrayLike, '*#batch 3']) –The array of local normals.
Each vector must have a unit length.
- Return type:
tuple[tuple[Float[Array, '*batch 3'],Float[Array, '*batch 3']],tuple[Float[Array, '*batch 3'],Float[Array, '*batch 3']]]- Returns:
The array of s and p directions, before and after reflection.
Examples
The following example shows how to compute and display the direction of the s and p components before and after reflection on a spherical surface.
>>> import plotly.graph_objects as go >>> from differt.geometry import normalize, spherical_to_cartesian >>> from differt.em import ( ... sp_directions, ... )
We generate a grid of points on a spherical surface.
>>> u, v = jnp.meshgrid( ... jnp.linspace(3 * jnp.pi / 8, 5 * jnp.pi / 8, 100), ... jnp.linspace(-jnp.pi / 8, jnp.pi / 8), ... ) >>> pa = jnp.stack((u, v), axis=-1) >>> xyz = spherical_to_cartesian(pa) >>> fig = go.Figure() >>> fig.add_trace( ... go.Surface( ... x=xyz[..., 0], ... y=xyz[..., 1], ... z=xyz[..., 2], ... colorscale=["blue", "blue"], ... opacity=0.5, ... showscale=False, ... ) ... )
Plotly does not provide a nice function to draw 3D vectors, so we create one.
>>> def add_vector(fig, orig, dest, color="red", name=None, dashed=False): ... dir = dest - orig ... end = orig + 0.9 * dir ... fig.add_trace( ... go.Scatter3d( ... x=[orig[0], end[0]], ... y=[orig[1], end[1]], ... z=[orig[2], end[2]], ... mode="lines", ... line_color=color, ... showlegend=False, ... line_dash="dashdot" if dashed else None, ... legendgroup=name, ... ) ... ) ... dir = 0.1 * dir ... fig.add_trace( ... go.Cone( ... x=[end[0]], ... y=[end[1]], ... z=[end[2]], ... u=[dir[0]], ... v=[dir[1]], ... w=[dir[2]], ... colorscale=[color, color], ... sizemode="raw", ... showscale=False, ... showlegend=True, ... name=name, ... hoverinfo="name", ... opacity=0.5 if dashed else None, ... legendgroup=name, ... ) ... )
We then place TX and RX points, and determine direction vectors, as well as direction of local s and p components.
>>> reflection_point = jnp.array([1.0, 0.0, 0.0]) >>> angle = jnp.pi / 4 >>> cos = jnp.cos(angle) >>> sin = jnp.sin(angle) >>> normal = jnp.array([1.0, 0.0, 0.0]) >>> tx = reflection_point + jnp.array([cos, 0.0, +sin]) >>> rx = reflection_point + jnp.array([cos, 0.0, -sin]) >>> k_i = reflection_point - tx >>> k_r = rx - reflection_point >>> (e_i_s, e_i_p), (e_r_s, e_r_p) = sp_directions(k_i, k_r, normal)
Finally, we draw all the vectors and markers.
>>> fig.add_trace( ... go.Scatter3d( ... x=[tx[0], rx[0]], ... y=[tx[1], rx[1]], ... z=[tx[2], rx[2]], ... mode="markers+text", ... text=["TX", "RX"], ... marker_color="black", ... showlegend=False, ... ) ... ) >>> add_vector(fig, tx, reflection_point, color="magenta", name="incident") >>> add_vector(fig, reflection_point, rx, color="magenta", name="reflected") >>> add_vector( ... fig, ... reflection_point, ... reflection_point + normal, ... color="blue", ... name="normal", ... ) >>> add_vector( ... fig, ... reflection_point, ... reflection_point + 0.5 * e_i_s, ... color="orange", ... name="s-component (incident)", ... ) >>> add_vector( ... fig, ... reflection_point, ... reflection_point + 0.5 * e_i_p, ... color="orange", ... name="p-component (incident)", ... )
We do the same, but for the reflected field.
>>> add_vector( ... fig, ... reflection_point, ... reflection_point + 0.5 * e_r_s, ... color="green", ... name="s-component (reflected)", ... dashed=True, ... ) >>> add_vector( ... fig, ... reflection_point, ... reflection_point + 0.5 * e_r_p, ... color="green", ... name="p-component (reflected)", ... ) >>> fig