
"""PKTron Physics — Wave Mechanics"""
import numpy as np
_R = np.float32

def wave_speed(frequency, wavelength):
    return _R(frequency)*_R(wavelength)

def wave_equation(A, k, omega, x, t, phi=0.0):
    """y = A*sin(k*x - omega*t + phi)"""
    x = np.asarray(x,dtype=_R); t = np.asarray(t,dtype=_R)
    return _R(A)*np.sin(_R(k)*x - _R(omega)*t + _R(phi))

def frequency_from_wavelength(v, wavelength):
    return _R(v)/_R(wavelength)

def wavelength_from_frequency(v, frequency):
    return _R(v)/_R(frequency)

def doppler_effect(f0, v_observer, v_source, v_sound=343.0):
    """Doppler shifted frequency."""
    return _R(f0)*(_R(v_sound)+_R(v_observer))/(_R(v_sound)+_R(v_source))

def standing_wave(A, k, omega, x, t):
    """Superposition of two counter-propagating waves."""
    x=np.asarray(x,dtype=_R); t=np.asarray(t,dtype=_R)
    return 2*_R(A)*np.sin(_R(k)*x)*np.cos(_R(omega)*t)

def intensity(power, area):
    return _R(power)/_R(area)

def sound_level_db(I, I0=1e-12):
    return float(10*np.log10(max(float(I)/float(I0), 1e-30)))

def snell_law(n1, theta1_deg, n2):
    """Return refraction angle in degrees."""
    s2 = _R(n1)*np.sin(np.radians(_R(theta1_deg)))/_R(n2)
    s2 = float(np.clip(s2,-1,1))
    return float(np.degrees(np.arcsin(s2)))

def refractive_index(c_medium, c=3e8):
    return float(_R(c)/_R(c_medium))

def diffraction_minima(wavelength, slit_width, order=1):
    """Angle of m-th diffraction minimum (degrees)."""
    return float(np.degrees(np.arcsin(order*_R(wavelength)/_R(slit_width))))
