def add_satellite(self,satpot,sat,df_prop,integ=False,ftype='rotate', rotFreq=1.,zsun='mean',tdep=True,method='slow'): turn_physical_off(satpot) sat.turn_physical_off() self.t= sat.time() #Check if the satellite has the same time array as the disc orbits if (len(self.t) != len(self.tt)) or (np.array(self.t)!=np.array(self.tt)).any(): self.discOrb= self.integOrbits(self.t) else: pass if method!='slowest': if ftype=="static": force= self.statSatForce(satpot,sat,tdep,method=method) else: try: if (rotFreq.unit==u.km/u.s/u.kpc): rotFreq= rotFreq.value/27.5 else: rotFreq= rotFreq.to(u.km/u.s/u.kpc) rotFreq= rotFreq.value/27.5 except: pass force= self.rotSatForce(satpot,sat,rotFreq,tdep,method=method) self.add_force(force,self.t,df_prop,integ=integ,rotFreq=rotFreq,zsun=zsun, tdep=tdep,method=method) return None elif method=='slowest': dJ= np.zeros([self.znpt,self.vnpt,len(self.t)]) for i in tqdm.trange(self.znpt): #Calculate the force if ftype=="static": force= self.statSatForce(satpot,sat,tdep,method=method,tstep=i) else: try: if (rotFreq.unit==u.km/u.s/u.kpc): rotFreq= rotFreq.value/27.5 else: rotFreq= rotFreq.to(u.km/u.s/u.kpc) rotFreq= rotFreq.value/27.5 except: pass force= self.rotSatForce(satpot,sat,rotFreq,tdep,method=method) #Calculate deltaJ dJ[i]= self.calc_dJ(force,integ,tdep,method,tstep=i) self.deltaJ= dJ #calculate the perturbation (skip the add_force step) self.calc_pert(self.deltaJ,self.t,df_prop,integ=integ,rotFreq=rotFreq,zsun=zsun, tdep=tdep,method=method) return None
def MWPotentialSCFbar_nogrow(mbar,Acos,Asin,rs=1.,normalize=False,pat_speed=40.,fin_phi_deg=27.,t_stream_age=5.): a=rs/ro omegaP=pat_speed*(ro/vo) fin_phi= np.radians(fin_phi_deg) #init_phi= fin_phi - o_p*(tpal5age*Gyr_to_s) init_phi= fin_phi - omegaP*t_stream_age/bovy_conversion.time_in_Gyr(vo,ro) mrat=mbar/10.**10. #10^10 mass of bar used to compute Acos and Asin static_bar=potential.SCFPotential(amp=mrat,Acos=Acos,Asin=Asin,a=a,normalize=normalize) #Note only m=0 terms are considered static_axi_bar=potential.SCFPotential(amp=mrat,Acos=np.atleast_3d(Acos[:,:,0]),a=a) barrot=potential.SolidBodyRotationWrapperPotential(pot=static_bar,omega=omegaP,ro=ro,vo=vo,pa=init_phi) if mbar <= 5.*10**9. : MWP2014SCFbar=[MWPotential2014[0],MiyamotoNagaiPotential(amp=(6.8-mrat)*10.**10*u.Msun,a=3./8.,b=0.28/8.),MWPotential2014[2],barrot] turn_physical_off(MWP2014SCFbar) #setup the corresponding axisymmetric bar MWP2014SCFnobar= [MWPotential2014[0],MiyamotoNagaiPotential(amp=(6.8-mrat)*10.**10*u.Msun,a=3./8.,b=0.28/8.),MWPotential2014[2],static_axi_bar] turn_physical_off(MWP2014SCFnobar) else : MWP2014SCFbar=[MiyamotoNagaiPotential(amp=(6.8+0.5-mrat)*10.**10*u.Msun,a=3./8.,b=0.28/8.),MWPotential2014[2],barrot] turn_physical_off(MWP2014SCFbar) MWP2014SCFnobar= [MiyamotoNagaiPotential(amp=(6.8+0.5-mrat)*10.**10*u.Msun,a=3./8.,b=0.28/8.),MWPotential2014[2],static_axi_bar] turn_physical_off(MWP2014SCFnobar) return (MWP2014SCFbar,MWP2014SCFnobar)
def __init__(self,discpot,zlim,vlim,times=np.linspace(0,1,1001)*u.Gyr,zpt=31,vpt=31,zarray=False,varray=False): """ NAME: __init__ PURPOSE: Initialize a vertical disc in equilibrium INPUT: pot (galpy potential) - should be a 1-dimensional potential zlim (float) - maximum height of the galactic disc in kpc vlim (float) - maximum velocity of the galactic disc in km/s OPTIONAL INPUTS: times (array) - time array over which to integrate the disc orbits. Otherwise, it defaults to 1001 timesteps over 5 Gyr. zpt (int) - number of phase-space points along the z-axis vpt (int) - number of phase-space points along the vz-axis zarray (boolean) - if True, zlim is an array specifying the points along the z-axis at which to calculte the perturbation varray (boolean) - if True, vlim is an array specifying the points along the vz-axis at which to calculte the perturbation OUTPUT: instance """ turn_physical_off(discpot) #1-dimensional potential object from Galpy self.pot= discpot self.InternalUnits= get_physical(self.pot) if zarray: self.zmax=np.max(np.abs(zlim)) self.znpt= len(zlim) self.z= zlim else: self.zmax= zlim/self.InternalUnits['ro'] self.znpt= zpt self.z= np.linspace(-self.zmax,self.zmax,self.znpt) # in galpy internal units if varray: self.vmax=np.max(np.abs(vlim)) self.vnpt= len(vlim) self.v= vlim else: self.vmax= vlim/self.InternalUnits['vo'] self.vnpt= vpt self.v= np.linspace(-self.vmax,self.vmax,self.vnpt) # in galpy internal units self.tt= times self.Jz,self.Oz= self.calc_JO() self.integOrbits(self.tt)
def _coordinate_system(zmin_max, vmin_max, N, galactic_potential): """ :param zmin_max: :param vmin_max: :param N: :param galactic_potential: :return: """ _z = np.linspace(-zmin_max, zmin_max, N) _v = np.linspace(-vmin_max, vmin_max, N) turn_physical_off(galactic_potential) units = get_physical(galactic_potential) z_units_internal = _z / units['ro'] v_units_internal = _v / units['vo'] return z_units_internal, v_units_internal, galactic_potential, units
def MWPotentialSCFbar_grow(mbar, Acos, Asin, rs=1., normalize=False, pat_speed=40., fin_phi_deg=27., t_on=-2., tgrow=2, tstream=5.): ''' SCFbar starts growing at -x Gyr tstream : age of the stream/max stripping time t_on: time in Gyr in the past at which the bar acquired full strength tgrow: no of bar periods it took the bar to grow to full strength starting at tform ''' #setup the full strength bar and axisymmetric "bar" a = rs / ro omegaP = pat_speed * (ro / vo) fin_phi = np.radians(fin_phi_deg) Tbar = 2. * np.pi / np.abs(omegaP) #bar period in galpy units. t_on = t_on / bovy_conversion.time_in_Gyr(vo, ro) tsteady = tgrow * Tbar tform = t_on - tsteady #- because past is negative mrat = mbar / 10.**10. #10^10 mass of bar used to compute Acos and Asin static_bar = mySCFPotential(amp=mrat, Acos=Acos, Asin=Asin, a=a, normalize=normalize) #Note only m=0 terms are considered static_axi_bar = mySCFPotential(amp=mrat, Acos=np.atleast_3d(Acos[:, :, 0]), a=a) barrot = potential.SolidBodyRotationWrapperPotential(pot=static_bar, omega=omegaP, ro=ro, vo=vo, pa=fin_phi) if mbar <= 5. * 10**9.: MWP2014SCFbar = [ MWPotential2014[0], MiyamotoNagaiPotential(amp=(6.8 - mrat) * 10.**10 * u.Msun, a=3. / 8., b=0.28 / 8.), MWPotential2014[2], barrot ] turn_physical_off(MWP2014SCFbar) #setup the corresponding axisymmetric bar MWP2014SCFnobar = [ MWPotential2014[0], MiyamotoNagaiPotential(amp=(6.8 - mrat) * 10.**10 * u.Msun, a=3. / 8., b=0.28 / 8.), MWPotential2014[2], static_axi_bar ] turn_physical_off(MWP2014SCFnobar) else: MWP2014SCFbar = [ MiyamotoNagaiPotential(amp=(6.8 + 0.5 - mrat) * 10.**10 * u.Msun, a=3. / 8., b=0.28 / 8.), MWPotential2014[2], barrot ] turn_physical_off(MWP2014SCFbar) MWP2014SCFnobar = [ MiyamotoNagaiPotential(amp=(6.8 + 0.5 - mrat) * 10.**10 * u.Msun, a=3. / 8., b=0.28 / 8.), MWPotential2014[2], static_axi_bar ] turn_physical_off(MWP2014SCFnobar) #if t_on >= t_stream, then stream sees the bar as always on if np.abs(t_on) * bovy_conversion.time_in_Gyr(vo, ro) >= tstream: return (MWP2014SCFbar, MWP2014SCFnobar) elif np.abs(tform) * bovy_conversion.time_in_Gyr(vo, ro) >= tstream: print("tform > age of stream") elif np.abs(tform) * bovy_conversion.time_in_Gyr(vo, ro) < tstream: MWbar_grow = DehnenWrap(amp=1., pot=MWP2014SCFbar, tform=tform, tsteady=tsteady) MWaxibar_destroy = DehnenWrap(amp=-1., pot=MWP2014SCFnobar, tform=tform, tsteady=tsteady) growbarpot = [MWbar_grow, MWP2014SCFnobar, MWaxibar_destroy] turn_physical_off(growbarpot) return (growbarpot, MWP2014SCFnobar)
# Make the position arrays grid_rpoints, grid_phipoints = ast1501.df.generate_grid_radial( r_range, phi_range, delta_r, delta_phi, delta_phi_in_arc=True) # Make the potential mwpot = potential.MWPotential2014 halo_a = 1.0 halo_phi = 0.0 halo_c = 1.0 trihalo = ast1501.potential.make_MWPotential2014_triaxialNFW(halo_b=halo_b, halo_phi=halo_phi, halo_c=halo_c) tripot_grow = ast1501.potential.make_tripot_dsw(trihalo=trihalo, tform=t_form, tsteady=t_steady) potential.turn_physical_off(tripot_grow) # Action angle coordinates and the DF qdf_aA = actionAngle.actionAngleAdiabatic(pot=potential.MWPotential2014, c=True) qdf = df.quasiisothermaldf(hr=2 * apu.kpc, sr=sigma_vR * (apu.km / apu.s), sz=sigma_vZ * (apu.km / apu.s), hsr=9.8 * (apu.kpc), hsz=7.6 * (apu.kpc), pot=potential.MWPotential2014, aA=qdf_aA) # ---------------------------------------------------------------------------- # Make the log
def spiral_arms_potential(FR_frac=1., t_on=-5., tgrow=2, tstream=5., axi_pot=MWPotential2014, cos=True, N=2, pat_speed=24.5, pitch_angle=9.9, r_ref=8., Rs=7., phi0=26., H=0.3): phi0 = np.radians(phi0) omega = pat_speed * (ro / vo) alpha = numpy.radians(pitch_angle) r_ref /= ro Rs /= ro H /= ro # percentage of the radial force to set the amplitude of the spiral FR_frac = FR_frac * 0.01 if cos: Cs = [8. / (3. * numpy.pi), 0.5, 8. / (15. * numpy.pi)] else: Cs = [1] #compute max radial force for amp=1 pp = np.linspace(0., 2. * np.pi, 1000) FR_nonaxi = [] spiral_pot_amp1 = SpiralArmsPotential(amp=1., N=N, omega=omega, alpha=alpha, phi_ref=phi0, r_ref=r_ref, H=H, Rs=Rs, Cs=Cs) turn_physical_off(spiral_pot_amp1) for ii in range(len(pp)): FR_nonaxi.append( potential.evaluateRforces(spiral_pot_amp1, R=8. / ro, z=0., phi=pp[ii], t=0.)) interp_FR_nonaxi = interpolate.InterpolatedUnivariateSpline(pp, FR_nonaxi) #fmin, because radial force is negative max_phi = optimize.fmin(interp_FR_nonaxi, 0., disp=0) max_FR_nonaxi = interp_FR_nonaxi(max_phi)[0] #compute the radial force due to the axisymmetric potential FR_axi = potential.evaluateRforces(axi_pot, R=8. / ro, z=0., t=0.) #compute the correct amplitude amp = numpy.abs(FR_frac * FR_axi / max_FR_nonaxi) #setup spiral potential with correct amplitude spiralpot = SpiralArmsPotential(amp=amp, N=N, omega=omega, alpha=alpha, phi_ref=phi0, r_ref=r_ref, H=H, Rs=Rs, Cs=Cs) #grow the spirals Tspiral = 2. * np.pi / np.abs(omega) #bar period in galpy units. t_on = t_on / bovy_conversion.time_in_Gyr(vo, ro) tsteady = tgrow * Tspiral tform = t_on - tsteady #- because past is negative #if t_on >= t_pal5_age, then Pal 5 sees the spirals always on if np.abs(t_on) * bovy_conversion.time_in_Gyr(vo, ro) >= tstream: print('not growing spiral') MWspiralpot = axi_pot + [spiralpot] turn_physical_off(MWspiralpot) return (MWspiralpot) elif np.abs(tform) * bovy_conversion.time_in_Gyr(vo, ro) >= tstream: print("tform > age of stream") elif np.abs(tform) * bovy_conversion.time_in_Gyr(vo, ro) < tstream: print('growing spiral') spiralpot_grow = DehnenWrap(amp=1., pot=spiralpot, tform=tform, tsteady=tsteady) turn_physical_off(spiralpot_grow) MWspiralpot = axi_pot + [spiralpot_grow] return MWspiralpot
def MWPotentialSCFbar_invert(mbar, Acos, Asin, rs=1., normalize=False, pat_speed=40., fin_phi_deg=27., t_stream_age=5., t_on=2., tgrow=2): ''' t_stream_age : age of the stream/max stripping time tform: time in Gyr in the past at which the bar started to form tgrow: no of bar periods it took the bar to grow to full strength starting at tform ''' #setup the full strength bar and axisymmetric "bar" a = rs / ro omegaP = pat_speed * (ro / vo) fin_phi = np.radians(fin_phi_deg) mrat = mbar / 10.**10. #10^10 mass of bar used to compute Acos and Asin static_bar = potential.SCFPotential(amp=mrat, Acos=Acos, Asin=Asin, a=a, normalize=normalize) #Note only m=0 terms are considered static_axi_bar = potential.SCFPotential(amp=mrat, Acos=np.atleast_3d(Acos[:, :, 0]), a=a) #pa = final phi and omega is negative since we are going back in time barrot = potential.SolidBodyRotationWrapperPotential(pot=static_bar, omega=-omegaP, ro=ro, vo=vo, pa=fin_phi) if mbar <= 5. * 10**9.: MWP2014SCFbar = [ MWPotential2014[0], MiyamotoNagaiPotential(amp=(6.8 - mrat) * 10.**10 * u.Msun, a=3. / 8., b=0.28 / 8.), MWPotential2014[2], barrot ] turn_physical_off(MWP2014SCFbar) #setup the corresponding axisymmetric bar MWP2014SCFnobar = [ MWPotential2014[0], MiyamotoNagaiPotential(amp=(6.8 - mrat) * 10.**10 * u.Msun, a=3. / 8., b=0.28 / 8.), MWPotential2014[2], static_axi_bar ] turn_physical_off(MWP2014SCFnobar) else: MWP2014SCFbar = [ MiyamotoNagaiPotential(amp=(6.8 + 0.5 - mrat) * 10.**10 * u.Msun, a=3. / 8., b=0.28 / 8.), MWPotential2014[2], barrot ] turn_physical_off(MWP2014SCFbar) MWP2014SCFnobar = [ MiyamotoNagaiPotential(amp=(6.8 + 0.5 - mrat) * 10.**10 * u.Msun, a=3. / 8., b=0.28 / 8.), MWPotential2014[2], static_axi_bar ] turn_physical_off(MWP2014SCFnobar) #setup Dehnen smooth growth wrapper for the bar #while going back, t_on = tform, then deconstruct the bar to no bar during tsteady tform = t_on / bovy_conversion.time_in_Gyr(vo, ro) Tbar = 2. * np.pi / omegaP tsteady = tgrow * Tbar MWaxibar_grow = DehnenWrap(amp=1., pot=MWP2014SCFnobar, tform=tform, tsteady=tsteady) MWbar_destroy = DehnenWrap(amp=-1., pot=MWP2014SCFbar, tform=tform, tsteady=tsteady) growbarpot_invert = [MWP2014SCFbar, MWaxibar_grow, MWbar_destroy] turn_physical_off(growbarpot_invert) return growbarpot_invert
def MWPotentialSCFbar(mbar, Acos, Asin, rs=1., normalize=False, pat_speed=40., fin_phi_deg=27., t_stream_age=5., t_on=2., tgrow=2): ''' t_stream_age : age of the stream/max stripping time t_on: time in Gyr in the past at which the bar acquired full strength tgrow: no of bar periods it took the bar to grow to full strength starting at tform ''' #setup the full strength bar and axisymmetric "bar" a = rs / ro omegaP = pat_speed * (ro / vo) fin_phi = np.radians(fin_phi_deg) t_stream_age = t_stream_age / bovy_conversion.time_in_Gyr(vo, ro) Tbar = 2. * np.pi / omegaP #bar period in galpy units. t_on = t_on / bovy_conversion.time_in_Gyr(vo, ro) tsteady = tgrow * Tbar tform = t_on + tsteady init_phi = fin_phi - omegaP * t_stream_age / bovy_conversion.time_in_Gyr( vo, ro) mrat = mbar / 10.**10. #10^10 mass of bar used to compute Acos and Asin static_bar = SCFPotential(amp=mrat, Acos=Acos, Asin=Asin, a=a, normalize=normalize) #Note only m=0 terms are considered static_axi_bar = SCFPotential(amp=mrat, Acos=np.atleast_3d(Acos[:, :, 0]), a=a) barrot = potential.SolidBodyRotationWrapperPotential(pot=static_bar, omega=omegaP, ro=ro, vo=vo, pa=init_phi) if mbar <= 5. * 10**9.: MWP2014SCFbar = [ MWPotential2014[0], MiyamotoNagaiPotential(amp=(6.8 - mrat) * 10.**10 * u.Msun, a=3. / 8., b=0.28 / 8.), MWPotential2014[2], barrot ] turn_physical_off(MWP2014SCFbar) #setup the corresponding axisymmetric bar MWP2014SCFnobar = [ MWPotential2014[0], MiyamotoNagaiPotential(amp=(6.8 - mrat) * 10.**10 * u.Msun, a=3. / 8., b=0.28 / 8.), MWPotential2014[2], static_axi_bar ] turn_physical_off(MWP2014SCFnobar) else: MWP2014SCFbar = [ MiyamotoNagaiPotential(amp=(6.8 + 0.5 - mrat) * 10.**10 * u.Msun, a=3. / 8., b=0.28 / 8.), MWPotential2014[2], barrot ] turn_physical_off(MWP2014SCFbar) MWP2014SCFnobar = [ MiyamotoNagaiPotential(amp=(6.8 + 0.5 - mrat) * 10.**10 * u.Msun, a=3. / 8., b=0.28 / 8.), MWPotential2014[2], static_axi_bar ] turn_physical_off(MWP2014SCFnobar) #setup Dehnen smooth growth wrapper for the bar #convert to galpy units #if t_on >= t_pal5_age, then Pal 5 sees the bar as always on if t_on >= t_stream_age: return (MWP2014SCFbar, MWP2014SCFnobar) elif tform >= t_stream_age: print("tform > age of Pal 5 stream") elif tform < t_stream_age: #change tform in the past, i.e. instead of from today, to time in the future from 5 Gyr in the past tform = t_stream_age - tform MWbar_grow = DehnenWrap(amp=1., pot=MWP2014SCFbar, tform=tform, tsteady=tsteady) MWaxibar_destroy = DehnenWrap(amp=-1., pot=MWP2014SCFnobar, tform=tform, tsteady=tsteady) growbarpot = [MWbar_grow, MWP2014SCFnobar, MWaxibar_destroy] turn_physical_off(growbarpot) return (growbarpot, MWP2014SCFnobar)