|
""" |
|
This module has all the classes and functions related to waves in optics. |
|
|
|
**Contains** |
|
|
|
* TWave |
|
""" |
|
|
|
__all__ = ['TWave'] |
|
|
|
from sympy.core.basic import Basic |
|
from sympy.core.expr import Expr |
|
from sympy.core.function import Derivative, Function |
|
from sympy.core.numbers import (Number, pi, I) |
|
from sympy.core.singleton import S |
|
from sympy.core.symbol import (Symbol, symbols) |
|
from sympy.core.sympify import _sympify, sympify |
|
from sympy.functions.elementary.exponential import exp |
|
from sympy.functions.elementary.miscellaneous import sqrt |
|
from sympy.functions.elementary.trigonometric import (atan2, cos, sin) |
|
from sympy.physics.units import speed_of_light, meter, second |
|
|
|
|
|
c = speed_of_light.convert_to(meter/second) |
|
|
|
|
|
class TWave(Expr): |
|
|
|
r""" |
|
This is a simple transverse sine wave travelling in a one-dimensional space. |
|
Basic properties are required at the time of creation of the object, |
|
but they can be changed later with respective methods provided. |
|
|
|
Explanation |
|
=========== |
|
|
|
It is represented as :math:`A \times cos(k*x - \omega \times t + \phi )`, |
|
where :math:`A` is the amplitude, :math:`\omega` is the angular frequency, |
|
:math:`k` is the wavenumber (spatial frequency), :math:`x` is a spatial variable |
|
to represent the position on the dimension on which the wave propagates, |
|
and :math:`\phi` is the phase angle of the wave. |
|
|
|
|
|
Arguments |
|
========= |
|
|
|
amplitude : Sympifyable |
|
Amplitude of the wave. |
|
frequency : Sympifyable |
|
Frequency of the wave. |
|
phase : Sympifyable |
|
Phase angle of the wave. |
|
time_period : Sympifyable |
|
Time period of the wave. |
|
n : Sympifyable |
|
Refractive index of the medium. |
|
|
|
Raises |
|
======= |
|
|
|
ValueError : When neither frequency nor time period is provided |
|
or they are not consistent. |
|
TypeError : When anything other than TWave objects is added. |
|
|
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy import symbols |
|
>>> from sympy.physics.optics import TWave |
|
>>> A1, phi1, A2, phi2, f = symbols('A1, phi1, A2, phi2, f') |
|
>>> w1 = TWave(A1, f, phi1) |
|
>>> w2 = TWave(A2, f, phi2) |
|
>>> w3 = w1 + w2 # Superposition of two waves |
|
>>> w3 |
|
TWave(sqrt(A1**2 + 2*A1*A2*cos(phi1 - phi2) + A2**2), f, |
|
atan2(A1*sin(phi1) + A2*sin(phi2), A1*cos(phi1) + A2*cos(phi2)), 1/f, n) |
|
>>> w3.amplitude |
|
sqrt(A1**2 + 2*A1*A2*cos(phi1 - phi2) + A2**2) |
|
>>> w3.phase |
|
atan2(A1*sin(phi1) + A2*sin(phi2), A1*cos(phi1) + A2*cos(phi2)) |
|
>>> w3.speed |
|
299792458*meter/(second*n) |
|
>>> w3.angular_velocity |
|
2*pi*f |
|
|
|
""" |
|
|
|
def __new__( |
|
cls, |
|
amplitude, |
|
frequency=None, |
|
phase=S.Zero, |
|
time_period=None, |
|
n=Symbol('n')): |
|
if time_period is not None: |
|
time_period = _sympify(time_period) |
|
_frequency = S.One/time_period |
|
if frequency is not None: |
|
frequency = _sympify(frequency) |
|
_time_period = S.One/frequency |
|
if time_period is not None: |
|
if frequency != S.One/time_period: |
|
raise ValueError("frequency and time_period should be consistent.") |
|
if frequency is None and time_period is None: |
|
raise ValueError("Either frequency or time period is needed.") |
|
if frequency is None: |
|
frequency = _frequency |
|
if time_period is None: |
|
time_period = _time_period |
|
|
|
amplitude = _sympify(amplitude) |
|
phase = _sympify(phase) |
|
n = sympify(n) |
|
obj = Basic.__new__(cls, amplitude, frequency, phase, time_period, n) |
|
return obj |
|
|
|
@property |
|
def amplitude(self): |
|
""" |
|
Returns the amplitude of the wave. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy import symbols |
|
>>> from sympy.physics.optics import TWave |
|
>>> A, phi, f = symbols('A, phi, f') |
|
>>> w = TWave(A, f, phi) |
|
>>> w.amplitude |
|
A |
|
""" |
|
return self.args[0] |
|
|
|
@property |
|
def frequency(self): |
|
""" |
|
Returns the frequency of the wave, |
|
in cycles per second. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy import symbols |
|
>>> from sympy.physics.optics import TWave |
|
>>> A, phi, f = symbols('A, phi, f') |
|
>>> w = TWave(A, f, phi) |
|
>>> w.frequency |
|
f |
|
""" |
|
return self.args[1] |
|
|
|
@property |
|
def phase(self): |
|
""" |
|
Returns the phase angle of the wave, |
|
in radians. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy import symbols |
|
>>> from sympy.physics.optics import TWave |
|
>>> A, phi, f = symbols('A, phi, f') |
|
>>> w = TWave(A, f, phi) |
|
>>> w.phase |
|
phi |
|
""" |
|
return self.args[2] |
|
|
|
@property |
|
def time_period(self): |
|
""" |
|
Returns the temporal period of the wave, |
|
in seconds per cycle. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy import symbols |
|
>>> from sympy.physics.optics import TWave |
|
>>> A, phi, f = symbols('A, phi, f') |
|
>>> w = TWave(A, f, phi) |
|
>>> w.time_period |
|
1/f |
|
""" |
|
return self.args[3] |
|
|
|
@property |
|
def n(self): |
|
""" |
|
Returns the refractive index of the medium |
|
""" |
|
return self.args[4] |
|
|
|
@property |
|
def wavelength(self): |
|
""" |
|
Returns the wavelength (spatial period) of the wave, |
|
in meters per cycle. |
|
It depends on the medium of the wave. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy import symbols |
|
>>> from sympy.physics.optics import TWave |
|
>>> A, phi, f = symbols('A, phi, f') |
|
>>> w = TWave(A, f, phi) |
|
>>> w.wavelength |
|
299792458*meter/(second*f*n) |
|
""" |
|
return c/(self.frequency*self.n) |
|
|
|
|
|
@property |
|
def speed(self): |
|
""" |
|
Returns the propagation speed of the wave, |
|
in meters per second. |
|
It is dependent on the propagation medium. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy import symbols |
|
>>> from sympy.physics.optics import TWave |
|
>>> A, phi, f = symbols('A, phi, f') |
|
>>> w = TWave(A, f, phi) |
|
>>> w.speed |
|
299792458*meter/(second*n) |
|
""" |
|
return self.wavelength*self.frequency |
|
|
|
@property |
|
def angular_velocity(self): |
|
""" |
|
Returns the angular velocity of the wave, |
|
in radians per second. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy import symbols |
|
>>> from sympy.physics.optics import TWave |
|
>>> A, phi, f = symbols('A, phi, f') |
|
>>> w = TWave(A, f, phi) |
|
>>> w.angular_velocity |
|
2*pi*f |
|
""" |
|
return 2*pi*self.frequency |
|
|
|
@property |
|
def wavenumber(self): |
|
""" |
|
Returns the wavenumber of the wave, |
|
in radians per meter. |
|
|
|
Examples |
|
======== |
|
|
|
>>> from sympy import symbols |
|
>>> from sympy.physics.optics import TWave |
|
>>> A, phi, f = symbols('A, phi, f') |
|
>>> w = TWave(A, f, phi) |
|
>>> w.wavenumber |
|
pi*second*f*n/(149896229*meter) |
|
""" |
|
return 2*pi/self.wavelength |
|
|
|
def __str__(self): |
|
"""String representation of a TWave.""" |
|
from sympy.printing import sstr |
|
return type(self).__name__ + sstr(self.args) |
|
|
|
__repr__ = __str__ |
|
|
|
def __add__(self, other): |
|
""" |
|
Addition of two waves will result in their superposition. |
|
The type of interference will depend on their phase angles. |
|
""" |
|
if isinstance(other, TWave): |
|
if self.frequency == other.frequency and self.wavelength == other.wavelength: |
|
return TWave(sqrt(self.amplitude**2 + other.amplitude**2 + 2 * |
|
self.amplitude*other.amplitude*cos( |
|
self.phase - other.phase)), |
|
self.frequency, |
|
atan2(self.amplitude*sin(self.phase) |
|
+ other.amplitude*sin(other.phase), |
|
self.amplitude*cos(self.phase) |
|
+ other.amplitude*cos(other.phase)) |
|
) |
|
else: |
|
raise NotImplementedError("Interference of waves with different frequencies" |
|
" has not been implemented.") |
|
else: |
|
raise TypeError(type(other).__name__ + " and TWave objects cannot be added.") |
|
|
|
def __mul__(self, other): |
|
""" |
|
Multiplying a wave by a scalar rescales the amplitude of the wave. |
|
""" |
|
other = sympify(other) |
|
if isinstance(other, Number): |
|
return TWave(self.amplitude*other, *self.args[1:]) |
|
else: |
|
raise TypeError(type(other).__name__ + " and TWave objects cannot be multiplied.") |
|
|
|
def __sub__(self, other): |
|
return self.__add__(-1*other) |
|
|
|
def __neg__(self): |
|
return self.__mul__(-1) |
|
|
|
def __radd__(self, other): |
|
return self.__add__(other) |
|
|
|
def __rmul__(self, other): |
|
return self.__mul__(other) |
|
|
|
def __rsub__(self, other): |
|
return (-self).__radd__(other) |
|
|
|
def _eval_rewrite_as_sin(self, *args, **kwargs): |
|
return self.amplitude*sin(self.wavenumber*Symbol('x') |
|
- self.angular_velocity*Symbol('t') + self.phase + pi/2, evaluate=False) |
|
|
|
def _eval_rewrite_as_cos(self, *args, **kwargs): |
|
return self.amplitude*cos(self.wavenumber*Symbol('x') |
|
- self.angular_velocity*Symbol('t') + self.phase) |
|
|
|
def _eval_rewrite_as_pde(self, *args, **kwargs): |
|
mu, epsilon, x, t = symbols('mu, epsilon, x, t') |
|
E = Function('E') |
|
return Derivative(E(x, t), x, 2) + mu*epsilon*Derivative(E(x, t), t, 2) |
|
|
|
def _eval_rewrite_as_exp(self, *args, **kwargs): |
|
return self.amplitude*exp(I*(self.wavenumber*Symbol('x') |
|
- self.angular_velocity*Symbol('t') + self.phase)) |
|
|