def __init__(self, pos=None, vel=None, t0=0, mass=None, charge=None, field=None): """ Object constructor. Parameters ---------- pos: list or array The initial position (x,y,z) of the particle, in meters. vel: list or array The initial velocity (vx, vy, vz) of the particle, in m/s. t0: float The time of simulation at the beginning (seconds), ignored for fields that do not depend on time. mass: float The mass of the particle, in kg. charge: float The charge of the particle, in Coulombs. field: Field object The field object that provides electric and magnetic field vectors and related quantities. """ self.pos = np.array(pos) # initial position array self.vel = np.array(vel) # initial velocity array self.tcur = t0 # current time self.mass = mass # mass of the particle self.charge = charge # charge of the particle self.field = field # the field object self.p = Particle(pos,vel,t0,mass,charge,field) # Store for referencing in setpa and setKE self.p.check_adiabaticity = True if self.p.isadiabatic(): g = GuidingCenter() g.check_adiabaticity = True g.init(self.p) self.trajlist = [g] else: self.trajlist = [self.p]
def setke(self, ke, unit="ev"): """ Scale the velocity vector with the speed corresponding to the given kinetic energy. Reinitializes the object. Parameters ----------- ke : float The kinetic energy of the particle (eV by default). Can be relativistic. unit : str, optional The unit of the energy. If "ev", electron volts, otherwise Joule. """ self.p.setke(ke, unit) self.p.check_adiabaticity = True if self.p.isadiabatic(): g = GuidingCenter() g.init(self.p) g.check_adiabaticity = True self.trajlist = [g] else: self.trajlist = [self.p]
def setpa(self, pa): """ Reinitialize the object with the given pitch angle (in degrees). Modifies the velocity vector while keeping the energy constant so that the particle's pitch angle (angle between the velocity and magnetic field vectors) is `pa` degrees. Previous data is lost. Parameters ----------- pa : float The new pitch angle in degrees. """ self.p.setpa(pa) self.p.check_adiabaticity = True if self.p.isadiabatic(): g = GuidingCenter() g.init(self.p) g.check_adiabaticity = True self.trajlist = [g] else: self.trajlist = [self.p]
def advance(self,delta): """ Advance the tracer position and the relevant momentum for a given duration. The trajectory is initialized at the latest state of the current tracer and integrated for an additional `delta` seconds. Uses the settings specific to the current tracer. This method can be called many times. Parameters ---------- delta : float The number of seconds to advance the trajectory. """ t = 0 current = self.trajlist[-1] assert current.check_adiabaticity == True while t < delta: try: current.advance(delta-t) except NonAdiabatic: p = Particle() p.init(current) p.check_adiabaticity = True self.trajlist.append(p) current = self.trajlist[-1] print("Switched to particle mode at time", current.tcur,flush=True) except Adiabatic: g = GuidingCenter() g.init(current) g.check_adiabaticity = True self.trajlist.append(g) current = self.trajlist[-1] print("Switched to guiding center mode at time", current.tcur,flush=True) t = current.tcur