def dW_orbit_track(W0, Ep, Emw, fmw, t0, tstop, Wlim): """Returns last obs, list of obs after each orbit""" track = pd.DataFrame() # fist orbit n = 0 ti = t0 Wi = np.NaN Wf = W0 tt = tab.tt_up(Wf, Ep) tf = t0 + tt obs = {'n': n, 'ti': ti, 'Wi': Wi, 'tf': tf, 'Wf': Wf} track = track.append(obs, ignore_index=True) # MW exchange and orbit while tf <= tstop and Wf > Wlim: # new conditions n = n + 1 ti = tf Wi = Wf phi = np.random.random() * 2 * np.pi # random phase Wf = Wi + dWs(phi, Emw, fmw) # new energy # orbit # tt = tab.tt_up(Wf, Ep) Wint = int(Wf * 1e8) if (Wint <= 15198) and (Wint >= -9119): tt = lut_up_f[Wint] elif Wint < -9119: # below Wlim tt = np.NaN elif Wint > 15198: # max of lut tt = tab.tt_up(Wf, Ep) tf = ti + 2 * tt obs = {'n': n, 'ti': ti, 'Wi': Wi, 'tf': tf, 'Wf': Wf} track = track.append(obs, ignore_index=True) return obs, track
def lookup_tt_f(W, Ep): Wint = int(W * 1e8) if (Wint <= 15198) and (Wint >= -9119): tt = lut_up_f[Wint] elif Wint < -9119: # below Wlim tt = np.NaN elif Wint > 15198: # max of lut tt = tab.tt_up(W, Ep) return tt
def lookup_tt_f(W, Ep, dup, lut_up_f, lut_down_f): """For before 20ns, turning time from lut_up/down_f.""" Wint = int(W*1e8) if (Wint <= 15198) and (Wint >= -9119) and dup: tt = lut_up_f[Wint] elif (Wint <= 15198) and (Wint >= -9119) and not dup: tt = lut_down_f[Wint] elif Wint < -9119: # below Wlim tt = math.nan elif (Wint > 15198) and dup: # max of lut tt = tab.tt_up(W, Ep) elif (Wint > 15198) and not dup: tt = tab.tt_down(W, Ep) return tt
def catch_at_20ns(W, y, ti, dup): """When field turns off, how long does e- take to return to the core. If r is NaN, then previous steps exited because W < Wlim, tf = NaN. Otherwise, determine if e- is outgoing or returning. If returning, tf is the time it takes to get from zi to r (trf). If outgoing, if W >= 0 then never returns and tf = NaN. If W < 0, then e- returns at ti + tt + (tt - trf) = ti + 2*tt - trf non-keyword arguments: W -- float: e- energy (a.u.) y -- [float, float]: [radius, velocity] e- initial state (a.u.) ti -- float: starting time (a.u.), should be 20 ns dup -- Bool: True/False means up/down hill e- returns: tf -- float: time (a.u.) when e- returns to the core. """ [r, v] = y # unpack if math.isnan(r): # exited because W < Wfinal t = math.nan # indicate this is the final energy else: zi = math.copysign(6, r) # get zi on the correct side. # how long does it take to get from core to current position if dup is True: trf = quad(tab.intg_up, zi, r, args=(W, 0))[0] else: trf = quad(tab.intg_down, zi, r, args=(W, 0))[0] # returning or not returning? if (r > 0) != (v > 0): # r and v different signs, e- returning t = trf elif (r > 0) == (v > 0): # r and v same signs, e- outgoing # Leaving, or up/downhill turning time? if W >= 0: # e- never returns t = math.nan elif dup is True: tt = tab.tt_up(W, 0) # turning time in zero field t = 2*tt - trf # has to turn, and then come back to r elif dup is False: tt = tab.tt_down(W, 0) # turning time in zero field t = 2*tt - trf # has to turn, and then come back to r else: print("catch_at_20ns() A: Something went wrong.") else: print("catch_at_20ns() B: Something went wrong.") return t + ti # start time plus elapsed time
def catch_at_20ns(W, y, ti): """When field turns off, how long does e- take to return to the core. If r is NaN, then previous steps exited because W < Wlim, tf = NaN. Otherwise, determine if e- is outgoing or returning. If returning, tf is the time it takes to get from zi to r (trf). If outgoing, if W >= 0 then never returns and tf = NaN. If W < 0, then e- returns at ti + tt + (tt - trf) = ti + 2*tt - trf non-keyword arguments: W -- float: e- energy (a.u.) y -- array: [radius, velocity] e- initial state (a.u.) ti -- starting time (a.u.), should be 20 ns returns: tf -- float: time (a.u.) when e- returns to the core. """ [r, v] = y # unpack if np.isnan(r): # exited because W < Wfinal t = np.NaN # indicate this is the final energy else: zi = math.copysign(6, r) # get zi on the correct side. # how long does it take to get from core to current position trf = quad(tab.intg_up, zi, r, args=(W, 0))[0] if (r > 0) != (v > 0): # r and v different signs, e- returning t = trf elif (r > 0) == (v > 0): # r and v same signs, e- outgoing if W >= 0: # e- never returns t = np.NaN else: tt = tab.tt_up(W, 0) # turning time in zero field t = 2 * tt - trf # has to turn, and then come back to r # au = atomic_units() # rstring = ("catch():\n" + # "W = {0} GHz\t" + "ti = {3} ns\n" + # "r = {1} a.u.\t" + "v = {2} a.u.\n" + # "trf = {4} ns\t" + "t = {5} ns\t" + "tf = {6} ns") # rstring = rstring.format( # W/au['GHz'], r, v, ti/au['ns'], trf/au['ns'], t/au['ns'], # (t + ti)/au['ns']) # print(rstring) return t + ti # start time plus elapsed time
def dW_orbit_Epoff_track(W0, Emw, fmw, t0, tstop, Wlim, tring): """Returns last obs, list of obs after each orbit""" # set up start n = 0 ti = np.NaN Wi = np.NaN tf = t0 Wf = W0 obs = {'n': n, 'ti': ti, 'Wi': Wi, 'tf': tf, 'Wf': Wf} track = pd.DataFrame(obs, index=[0]) while tf <= tstop and Wf > Wlim: # new conditions n = n + 1 ti = tf Wi = Wf phi = np.random.random() * 2 * np.pi # random phase Emw_t = Emw * math.exp(-ti / tring) # ringing down Wf = Wi + dWs(phi, Emw_t, fmw) # new energy # orbit tt = tab.tt_up(Wf, 0) # field is turned off tf = ti + 2 * tt obs = {'n': n, 'ti': ti, 'Wi': Wi, 'tf': tf, 'Wf': Wf} track = track.append(obs, ignore_index=True) return obs, track