def bounceperiod(self): """Return the bounce period at the current position.""" tpos, ppar = self.trajectory[-1, 0:4], self.trajectory[-1, 4] Bmag = self.field.magB(tpos) gamma = np.sqrt(1 + 2*self.mu*Bmag/(self.mass*c*c) + (ppar/(self.mass*c))**2) if gamma-1 < 1e-6: #nonrelativistic p = np.sqrt(2*self.mass*self.mu*Bmag + ppar**2) # total momentum v = p/self.mass Bmirror = (p**2) / (2*self.mass*self.mu) else: # relativistic p = self.mass * c *np.sqrt((gamma+1)*(gamma-1)) # momentum Bmirror = p**2 / ((p-ppar)*(p+ppar)) * Bmag v = p/self.mass/gamma return rfu.bounceperiod(tpos,self.field,Bmirror,v)
def advance(self, delta): """ Advance the particle position for the given duration. The trajectory is initialized at the latest state of the object and integrated for an additional `delta` seconds. Uses the `scipy.integrate.ode` class with `"dopri5"` solver. This method can be called many times. Parameters ---------- delta : float The number of seconds to advance the trajectory. Notes ----- The explicit runge-kutta method of order 4(5) 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)` """ v = self.v gamma = 1.0 / np.sqrt(1 - (v / c)**2) Bm = self.mass * gamma**2 * v**2 / (2 * self.mu) bp = bounceperiod(self.trajectory[-1, :4], self.field, Bm, v) dt = params['BCtimestep'] * bp def deriv(t, Y): tpos = np.concatenate(([t], Y)) if self.isequatorial: return self._v_grad(Y[:4]) + self._v_inert(Y[:4]) else: Bvec = self.field.B(tpos) magBsq = np.dot(Bvec, Bvec) Sb = halfbouncepath(tpos, self.field, Bm) gI = gradI(tpos, self.field, Bm) return gamma * self.mass * v * v / ( self.charge * Sb * magBsq) * np.cross(gI, Bvec) rtol, atol = params["solvertolerances"] r = ode(deriv).set_integrator("dopri5", atol=atol, rtol=rtol) r.set_initial_value(self.trajectory[-1, 1:], self.trajectory[-1, 0]) for t in np.arange(self.tcur, self.tcur + delta, dt): nextpt = np.hstack(([t], r.integrate(r.t + dt))) self.trajectory = np.vstack((self.trajectory, nextpt)) self.tcur = self.trajectory[-1, 0]
def advance(self, delta): """ Advance the particle position for the given duration. The trajectory is initialized at the latest state of the object and integrated for an additional `delta` seconds. Uses the `scipy.integrate.ode` class with `"dopri5"` solver. This method can be called many times. Parameters ---------- delta : float The number of seconds to advance the trajectory. Notes ----- The explicit runge-kutta method of order 4(5) 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)` """ v = self.v gamma = 1.0/np.sqrt(1 - (v / c)**2) Bm = self.mass*gamma**2*v**2/(2*self.mu) bp = bounceperiod(self.trajectory[-1,:4], self.field, Bm, v) dt = params['BCtimestep'] * bp def deriv(t,Y): tpos = np.concatenate(([t],Y)) if self.isequatorial: return self._v_grad(Y[:4])+self._v_inert(Y[:4]) else: Bvec = self.field.B(tpos) magBsq = np.dot(Bvec, Bvec) Sb = halfbouncepath(tpos, self.field, Bm) gI = gradI(tpos, self.field, Bm) return gamma*self.mass*v*v/(self.charge*Sb*magBsq) * np.cross(gI,Bvec) rtol, atol = params["solvertolerances"] r = ode(deriv).set_integrator("dopri5", atol=atol, rtol=rtol) r.set_initial_value(self.trajectory[-1,1:], self.trajectory[-1,0]) for t in np.arange(self.tcur, self.tcur+delta, dt): nextpt = np.hstack(([t],r.integrate(r.t+dt))) self.trajectory = np.vstack((self.trajectory,nextpt)) self.tcur = self.trajectory[-1,0]