Add a bar potential to MWPotential2014 in AMUSE #666
stevenalfonso
started this conversation in
General
Replies: 1 comment 1 reply
-
Thanks for the detailed example! I think the issue is that AMUSE expects the potential to be able to be evaluated at multiple points simultaneously, while |
Beta Was this translation helpful? Give feedback.
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Hello,
I am trying to add a bar to the MWPotential2014 as pot = MWPotential2014+SoftenedNeedleBarPotential(), and then convert it to AMUSE mwp_amuse=to_amuse(pot, reverse=True). However, when added to the AMUSE integration, there is an error due to potential shape, I guess.
Below is the code:
from amuse.lab import *
from amuse.couple import bridge
from amuse.datamodel import Particles
from galpy.potential import to_amuse, SoftenedNeedleBarPotential, MWPotential2014
from galpy.util import plot as galpy_plot
from amuse.community.bhtree.interface import BHTree
from amuse.units import quantities
from tqdm import tqdm
Convert galpy MWPotential2014 to AMUSE representation
pot = MWPotential2014 + SoftenedNeedleBarPotential()
mwp_amuse= to_amuse(pot, reverse=True)
Set initial cluster parameters
N= 1000
Mcluster= 1000. | units.MSun
Rcluster= 10. | units.parsec
Rinit = [x_init.value, y_init.value, z_init.value] | units.pc
Vinit = [-vx_init.value, -vy_init.value, -vz_init.value] | units.km/units.s # flip velocities
Setup star cluster simulation
def setup_cluster(N,Mcluster,Rcluster,Rinit,Vinit):
converter= nbody_system.nbody_to_si(Mcluster,Rcluster)
stars= new_plummer_sphere(N,converter)
stars.x+= Rinit[0]
stars.y+= Rinit[1]
stars.z+= Rinit[2]
stars.vx+= Vinit[0]
stars.vy+= Vinit[1]
stars.vz+= Vinit[2]
return stars, converter
tend = 120.0 | units.Myr
dt = 1.0 | units.Myr
times = quantities.arange(0.0 | units.Myr, tend, dt)
Setup cluster
stars,converter= setup_cluster(N,Mcluster,Rcluster,Rinit,Vinit)
cluster_code= BHTree(converter,number_of_workers=1) #Change number of workers depending no. of CPUs
cluster_code.parameters.epsilon_squared= (3. | units.parsec)**2
cluster_code.parameters.opening_angle= 0.6
cluster_code.parameters.timestep= dt
cluster_code.particles.add_particles(stars)
Setup channels between stars particle dataset and the cluster code
channel_from_stars_to_cluster_code= stars.new_channel_to(cluster_code.particles,
attributes=["mass", "x", "y", "z", "vx", "vy", "vz"])
channel_from_cluster_code_to_stars= cluster_code.particles.new_channel_to(stars,
attributes=["mass", "x", "y", "z", "vx", "vy", "vz"])
Setup gravity bridge
gravity= bridge.Bridge(use_threading=False)
Stars in cluster_code depend on gravity from external potential mwp_amuse (i.e., MWPotential2014)
gravity.add_system(cluster_code, (mwp_amuse,))
External potential mwp_amuse still needs to be added to system so it evolves with time
gravity.add_system(mwp_amuse,)
Set how often to update external potential
gravity.timestep= cluster_code.parameters.timestep/2.
Evolve
time= 0.0 | tend.unit
for i in tqdm(times):
gravity.evolve_model(i)
channel_from_cluster_code_to_stars.copy()
gravity.stop()
galpy_plot.plot(stars.x.value_in(units.kpc),stars.y.value_in(units.kpc),'.', xlabel=r'$X,(\mathrm{kpc})$',ylabel=r'$Y,(\mathrm{kpc})$')
The error comes when evolving the gravity code, this is the fuller error message:
ValueError Traceback (most recent call last)
time= 0.0 | tend.unit
for i in tqdm(times):
--> gravity.evolve_model(i)
channel_from_cluster_code_to_stars.copy()
gravity.stop()
File ~/.local/lib/python3.8/site-packages/amuse/couple/bridge.py:555, in Bridge.evolve_model(self, tend, timestep)
timestep = self.timestep
if self.method is None:
--> return self.evolve_joined_leapfrog(tend,timestep)
else:
return self.evolve_simple_steps(tend,timestep)
File ~/.local/lib/python3.8/site-packages/amuse/couple/bridge.py:570, in Bridge.evolve_joined_leapfrog(self, tend, timestep)
while self.time < (tend-timestep/2.):
if first:
--> self.kick_codes(timestep/2.)
first=False
else:
File ~/.local/lib/python3.8/site-packages/amuse/couple/bridge.py:711, in Bridge.kick_codes(self, dt)
for x in self.codes:
if hasattr(x,"kick"):
--> de += x.kick(dt)
self.kick_energy += de
File ~/.local/lib/python3.8/site-packages/amuse/couple/bridge.py:454, in GravityCodeInField.kick(self, dt)
if(self.verbose):
print(self.code.class.name,"receives kick from",field_code.class.name, end=' ')
--> self.kick_with_field_code(
particles,
field_code,
dt
if(self.verbose):
print(".. done")
File ~/.local/lib/python3.8/site-packages/amuse/couple/bridge.py:490, in GravityCodeInField.kick_with_field_code(self, particles, field_code, dt)
def kick_with_field_code(self, particles, field_code, dt):
--> ax,ay,az=field_code.get_gravity_at_point(
self._softening_lengths(particles),
particles.x,
particles.y,
particles.z
self.update_velocities(particles, dt, ax, ay, az)
File ~/.local/lib/python3.8/site-packages/galpy/potential/amuse.py:159, in galpy_profile.get_gravity_at_point(self, eps, x, y, z)
phi = numpy.arctan2(y.value_in(units.kpc), x.value_in(units.kpc))
Cylindrical force
--> Rforce = potential.evaluateRforces(
self.pot,
R / self.ro,
zed / self.ro,
phi=phi,
t=self.tgalpy,
use_physical=False,
)
phitorque = potential.evaluatephitorques(
self.pot,
R / self.ro,
(...)
use_physical=False,
) / (R / self.ro)
zforce = potential.evaluatezforces(
self.pot,
R / self.ro,
(...)
use_physical=False,
)
File ~/.local/lib/python3.8/site-packages/galpy/potential/Potential.py:82, in potential_positional_arg..wrapper(Pot, *args, **kwargs)
@wraps(func)
def wrapper(Pot, /, *args, **kwargs):
--> return func(Pot, *args, **kwargs)
File ~/.local/lib/python3.8/site-packages/galpy/util/conversion.py:1113, in potential_physical_input..wrapper(*args, **kwargs)
if (
"zmax" in kwargs
and _APY_LOADED
and isinstance(kwargs["zmax"], units.Quantity)
kwargs["zmax"] = kwargs["zmax"].to(units.kpc).value / ro
--> return method(*args, **kwargs)
File ~/.local/lib/python3.8/site-packages/galpy/util/conversion.py:1008, in physical_conversion..wrapper..wrapped(*args, **kwargs)
if use_physical_explicitly_set:
warnings.warn(
"Returning output(s) in internal units even though use_physical=True, because ro and/or vo not set"
)
return method(*args, **kwargs)
File ~/.local/lib/python3.8/site-packages/galpy/potential/Potential.py:2168, in evaluateRforces(Pot, R, z, phi, t, v)
@potential_positional_arg
@potential_physical_input
@physical_conversion("force", pop=True)
def evaluateRforces(Pot, R, z, phi=None, t=0.0, v=None):
"""
Evaluate the radial force F_R(R,z,phi,t) of a potential, force or a list of potentials/forces.
(...)
"""
--> return _evaluateRforces(Pot, R, z, phi=phi, t=t, v=v)
File ~/.local/lib/python3.8/site-packages/galpy/potential/Potential.py:2190, in _evaluateRforces(Pot, R, z, phi, t, v)
out += pot._Rforce_nodecorator(R, z, phi=phi, t=t, v=v)
else:
--> out += pot._Rforce_nodecorator(R, z, phi=phi, t=t)
return out
elif isinstance(Pot, Potential):
File ~/.local/lib/python3.8/site-packages/galpy/potential/Potential.py:204, in Potential._Rforce_nodecorator(self, R, z, phi, t)
def _Rforce_nodecorator(self, R, z, phi=0.0, t=0.0):
# Separate, so it can be used during orbit integration
try:
--> return self._amp * self._Rforce(R, z, phi=phi, t=t)
except AttributeError: # pragma: no cover
raise PotentialError(
"'_Rforce' function not implemented for this potential"
)
File ~/.local/lib/python3.8/site-packages/galpy/potential/SoftenedNeedleBarPotential.py:98, in SoftenedNeedleBarPotential._Rforce(self, R, z, phi, t)
def _Rforce(self, R, z, phi=0.0, t=0.0):
--> self._compute_xyzforces(R, z, phi, t)
return numpy.cos(phi) * self._cached_Fx + numpy.sin(phi) * self._cached_Fy
File ~/.local/lib/python3.8/site-packages/galpy/potential/SoftenedNeedleBarPotential.py:126, in SoftenedNeedleBarPotential._compute_xyzforces(self, R, z, phi, t)
def _compute_xyzforces(self, R, z, phi, t):
# Compute all rectangular forces
--> new_hash = hashlib.md5(numpy.array([R, phi, z, t])).hexdigest()
if new_hash != self._force_hash:
x, y, z = self._compute_xyz(R, phi, z, t)
ValueError: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (4,) + inhomogeneous part.
How can I solve this? Or is something that I am doing wrong?
Thanks!
Beta Was this translation helpful? Give feedback.
All reactions