Пример #1
0
 def cycper(self):
     """Return the cyclotron period value at the final position."""
     t, r, mom = self.trajectory[-1, 0], self.trajectory[
         -1, 1:4], self.trajectory[-1, 4:]
     gm = np.sqrt(self.mass**2 + np.dot(mom, mom) / c**2)  # gamma * mass
     v = mom / gm
     return ru.cyclotron_period(t, r, v, self.field, self.mass, self.charge)
Пример #2
0
 def cycper(self):
     """Return the cyclotron period value at the final position."""
     t, r, mom = self.trajectory[-1, 0], self.trajectory[-1, 1:4], self.trajectory[-1, 4:]
     gm = np.sqrt(self.mass**2 + np.dot(mom,mom)/c**2) # gamma * mass
     v = mom/gm
     return ru.cyclotron_period(t, r, v, self.field, self.mass, self.charge)
Пример #3
0
    def advance(self, delta):
        """
        Advance the particle position and momentum for a given duration.
        
        The trajectory is initialized at the latest state of the particle and 
        integrated for an additional `delta` seconds. Uses the `scipy.integrate.ode`
        class with `"dop853"` solver.
        
        This method can be called many times.
        
        Parameters
        ----------
        delta : float
            The number of seconds to advance the trajectory.
        
        Raises
        -------
        Adiabatic
            Only if the `check_adiabaticity` attribute is set to True.
            
        Notes
        -----
        The particle is subject to the Newton-Lorentz equation of motion.
        
        .. math::
        
            \\frac{\mathrm{d}\\vec{x}}{\mathrm{d}t} = \\frac{\\vec{p}}{\gamma m} \\\\

            \\frac{\mathrm{d}\\vec{p}}{\mathrm{d}t} = q\\vec{E} + q\\vec{v}\\times\\vec{B}

        where :math:`\gamma = \sqrt{1 + (|\\vec{p}|/mc)^2}` is the relativistic factor.
        
        The explicit runge-kutta method of order 8(5,3) due to Dormand & Prince
        with stepsize control is used to solve for the motion. The relative 
        tolerance `rtol` and the absolute tolerance `atol` of the solver can be
        set with: `rapt.params["solvertolerances"] = (rtol, atol)`
        
        The `beta` parameter to the `scipy.integrate.ode.setintegrator` method
        serves to stabilize the solution in gridded fields.
        """
        rtol, atol = params["solvertolerances"]        
        t0 = self.trajectory[-1,0]        
        pos = self.trajectory[-1,1:4]
        mom = self.trajectory[-1,4:]
        gm = np.sqrt(self.mass**2 + np.dot(mom,mom)/c**2) # gamma * mass
        vel = mom/gm
        # set resolution of cyclotron motion
        if params["Ptimestep"] != 0:
            dt = params["Ptimestep"]
        else:
            dt = self.cycper()/params["cyclotronresolution"]

        dt = ru.cyclotron_period(t0, pos, vel, self.field, self.mass, self.charge) / params['cyclotronresolution']
        
        def eom(t, Y):  # The Newton-Lorenz equation of motion
            # Y = x,y,z,px,py,pz
            nonlocal gm
            tpos = np.concatenate(([t],Y[:3]))
            mom = Y[3:]
            out = np.zeros(6)
            if not self.field.static:  # don't reevaluate gamma every time, if it is not supposed to change.
                gm = np.sqrt(self.mass**2 + np.dot(mom,mom)/c**2) # gamma * mass        
            # d(pos)/dt = vel = mom / (gamma*m) :
            out[0:3] = Y[3:]/gm    
            # dp/dt = q(E(t, pos) + (p/gamma*m) x B(t, pos)) :      
            out[3:] = self.charge * (self.field.E(tpos) + np.cross(Y[3:], self.field.B(tpos))/gm)
            if params["enforce equatorial"]:
                out[2] = out[5] = 0
            return out

        r = ode(eom).set_integrator("dop853",beta=0.1, rtol=rtol, atol=atol) 
        # Setting beta is necessary to reduce the error.
        
        r.set_initial_value(self.trajectory[-1,1:], self.trajectory[-1,0])
        while r.successful() and r.t < t0+delta:
            next = np.hstack(([r.t+dt],r.integrate(r.t+dt)))
            self.tcur = r.t+dt
            self.trajectory = np.vstack((self.trajectory,next))
            if self.check_adiabaticity and self.isadiabatic():
                raise Adiabatic
Пример #4
0
    def advance(self, delta):
        """
        Advance the particle position and momentum for a given duration.
        
        The trajectory is initialized at the latest state of the particle and 
        integrated for an additional `delta` seconds. Uses the `scipy.integrate.ode`
        class with `"dop853"` solver.
        
        This method can be called many times.
        
        Parameters
        ----------
        delta : float
            The number of seconds to advance the trajectory.
        
        Raises
        -------
        Adiabatic
            Only if the `check_adiabaticity` attribute is set to True.
            
        Notes
        -----
        The particle is subject to the Newton-Lorentz equation of motion.
        
        .. math::
        
            \\frac{\mathrm{d}\\vec{x}}{\mathrm{d}t} = \\frac{\\vec{p}}{\gamma m} \\\\

            \\frac{\mathrm{d}\\vec{p}}{\mathrm{d}t} = q\\vec{E} + q\\vec{v}\\times\\vec{B}

        where :math:`\gamma = \sqrt{1 + (|\\vec{p}|/mc)^2}` is the relativistic factor.
        
        The explicit runge-kutta method of order 8(5,3) due to Dormand & Prince
        with stepsize control is used to solve for the motion. The relative 
        tolerance `rtol` and the absolute tolerance `atol` of the solver can be
        set with: `rapt.params["solvertolerances"] = (rtol, atol)`
        
        The `beta` parameter to the `scipy.integrate.ode.setintegrator` method
        serves to stabilize the solution in gridded fields.
        """
        rtol, atol = params["solvertolerances"]
        t0 = self.trajectory[-1, 0]
        pos = self.trajectory[-1, 1:4]
        mom = self.trajectory[-1, 4:]
        gm = np.sqrt(self.mass**2 + np.dot(mom, mom) / c**2)  # gamma * mass
        vel = mom / gm
        # set resolution of cyclotron motion
        if params["Ptimestep"] != 0:
            dt = params["Ptimestep"]
        else:
            dt = self.cycper() / params["cyclotronresolution"]

        dt = ru.cyclotron_period(t0, pos, vel, self.field, self.mass,
                                 self.charge) / params['cyclotronresolution']

        def eom(t, Y):  # The Newton-Lorenz equation of motion
            # Y = x,y,z,px,py,pz
            nonlocal gm
            tpos = np.concatenate(([t], Y[:3]))
            mom = Y[3:]
            out = np.zeros(6)
            if not self.field.static:  # don't reevaluate gamma every time, if it is not supposed to change.
                gm = np.sqrt(self.mass**2 +
                             np.dot(mom, mom) / c**2)  # gamma * mass
            # d(pos)/dt = vel = mom / (gamma*m) :
            out[0:3] = Y[3:] / gm
            # dp/dt = q(E(t, pos) + (p/gamma*m) x B(t, pos)) :
            out[3:] = self.charge * (self.field.E(tpos) +
                                     np.cross(Y[3:], self.field.B(tpos)) / gm)
            if params["enforce equatorial"]:
                out[2] = out[5] = 0
            return out

        r = ode(eom).set_integrator("dop853", beta=0.1, rtol=rtol, atol=atol)
        # Setting beta is necessary to reduce the error.

        r.set_initial_value(self.trajectory[-1, 1:], self.trajectory[-1, 0])
        while r.successful() and r.t < t0 + delta:
            next = np.hstack(([r.t + dt], r.integrate(r.t + dt)))
            self.tcur = r.t + dt
            self.trajectory = np.vstack((self.trajectory, next))
            if self.check_adiabaticity and self.isadiabatic():
                raise Adiabatic