コード例 #1
0
 def test_constraint(self):
     for ang in np.linspace(-8 * pi, 8 * pi, 100):
         c_ang = util.constrain_angle(ang)
         self.assertAlmostEqual(abs(np.sin(ang)), abs(np.sin(c_ang)))
         self.assertAlmostEqual(abs(np.cos(ang)), abs(np.cos(c_ang)))
         self.assertLessEqual(c_ang, 2 * pi)
         self.assertGreaterEqual(c_ang, 0)
コード例 #2
0
ファイル: test_utilities.py プロジェクト: tarvos14/pytpc
 def test_constraint(self):
     for ang in np.linspace(-8*pi, 8*pi, 100):
         c_ang = util.constrain_angle(ang)
         self.assertAlmostEqual(abs(np.sin(ang)), abs(np.sin(c_ang)))
         self.assertAlmostEqual(abs(np.cos(ang)), abs(np.cos(c_ang)))
         self.assertLessEqual(c_ang, 2*pi)
         self.assertGreaterEqual(c_ang, 0)
コード例 #3
0
ファイル: relativity.py プロジェクト: tarvos14/pytpc
def elastic_scatter(proj, target, cm_angle, azi):
    """Perform the special relativity calculation needed for elastic scattering.

    This takes two particles and scatters them elastically at the given center-of-mass angle and azimuthal angle.
    These two angles are free parameters in the special relativity calculation, so they need to be given to the
    function.

    These equations are based on those at http://skisickness.com/2010/04/25/

    Parameters
    ----------
    proj : pytpc.simulation.Particle
        The projectile particle
    target : pytpc.simulation.Particle
        The target particle
    cm_angle : number
        The scattering angle in the center-of-momentum frame, in radians
    azi : number
        The final azimuthal angle for the scattered particles. The ejectile will be given this azimuthal angle, and
        the recoil particle will be given this angle + pi.

    Returns
    -------
    ejec : pytpc.simulation.Particle
        The ejectile particle
    recoil : pytpc.simulation.Particle
        The recoil particle
    """

    recoil = copy.copy(target)
    ejec = copy.copy(proj)
    m1 = target.mass
    m2 = proj.mass
    m3 = ejec.mass
    m4 = recoil.mass
    T1 = proj.energy  # Note: This is the kinetic energy only

    s = (m1 + m2) ** 2 + 2 * m1 * T1  # The Lorentz invariant. We don't need c's since the mass & mom are in MeV
    pcm = sqrt(((s - m1 ** 2 - m2 ** 2) ** 2 - 4 * m1 ** 2 * m2 ** 2) / (4 * s))  # COM momentum of the reactants
    ppcm = sqrt(((s - m3 ** 2 - m4 ** 2) ** 2 - 4 * m3 ** 2 * m4 ** 2) / (4 * s))  # COM momentum of the products

    chi = log((sqrt(pcm ** 2 + m1 ** 2) + pcm) / m1)  # rapidity of the COM frame

    T3 = sqrt(ppcm ** 2 + m3 ** 2) * cosh(chi) + ppcm * cos(cm_angle) * sinh(chi) - m3  # ejectile KE
    T4 = sqrt(ppcm ** 2 + m4 ** 2) * cosh(chi) - ppcm * cos(cm_angle) * sinh(chi) - m4  # recoil KE

    E3cm = sqrt(ppcm ** 2 + m3 ** 2)  # ejectile COM total energy
    E4cm = sqrt(ppcm ** 2 + m4 ** 2)  # recoil COM total energy

    pol3 = atan(ppcm * sin(cm_angle) / (sinh(chi) * E3cm + cosh(chi) * ppcm * cos(cm_angle)))  # ejectile lab polar ang
    pol4 = atan(ppcm * sin(cm_angle) / (sinh(chi) * E4cm - cosh(chi) * ppcm * cos(cm_angle)))  # recoil lab polar angle

    ejec.energy = T3
    ejec.polar = pol3
    ejec.azimuth = 0
    ejec.position = proj.position

    recoil.energy = T4
    recoil.polar = pol4
    recoil.azimuth = pi
    recoil.position = proj.position

    # These angles are relative to the projectile's original trajectory, and need to be rotated into the lab frame.
    # This can be done with the Euler angle rotations. We need to use the transpose of the Euler matrix here.
    # (I'm not sure why. It just seems to be what works...)

    eulermat = euler_matrix(phi=proj.azimuth, theta=proj.polar, psi=azi).T  # the transpose is the inverse (ortho. mat.)

    recoil.momentum = eulermat.dot(recoil.momentum)
    ejec.momentum = eulermat.dot(ejec.momentum)

    assert ejec.polar >= 0, "ejectile polar angle < 0"
    assert recoil.polar >= 0, "recoil polar angle < 0"

    # The Euler angle rotation might have pushed the azimuthal angles outside [0, 2*pi), so fix them.

    recoil.azimuth = constrain_angle(recoil.azimuth)
    ejec.azimuth = constrain_angle(ejec.azimuth)

    assert 0 <= recoil.azimuth <= 2 * pi, "recoil azimuth out of bounds"
    assert 0 <= ejec.azimuth <= 2 * pi, "ejectile azimuth out of bounds"

    assert ejec.energy - T3 < 1e-2, "ejectile energy was changed by rotation: {} -> {}".format(T3, ejec.energy)
    assert recoil.energy - T4 < 1e-2, "recoil energy was changed by rotation: {} -> {}".format(T4, recoil.energy)

    return ejec, recoil
コード例 #4
0
ファイル: test_relativity.py プロジェクト: tarvos14/pytpc
 def test_azimuth(self):
     for azi in numpy.linspace(0, 2*pi, 20):
         ejec, recoil = rel.elastic_scatter(self.proj, self.target, self.cm_angle, azi)
         self.assertAlmostEqual(ejec.azimuth, azi)
         self.assertAlmostEqual(recoil.azimuth, constrain_angle(azi + pi))