From ed52596b00ccf648fb3adaf679850760c4f3e70f Mon Sep 17 00:00:00 2001 From: elkogerville Date: Wed, 22 Apr 2026 17:43:07 +0200 Subject: [PATCH 1/6] fixed bug in Tupan interface where values passed to ParticleSystem where ndarrays of dim 0 instead of floats --- src/amuse_tupan/interface.py | 61 +++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/src/amuse_tupan/interface.py b/src/amuse_tupan/interface.py index 2fc65c5c13..b1ebab3199 100644 --- a/src/amuse_tupan/interface.py +++ b/src/amuse_tupan/interface.py @@ -1,5 +1,5 @@ - +from amuse.datamodel.particles import Particle, Particles from amuse.community import * from amuse.community.interface.gd import GravitationalDynamicsInterface from amuse.community.interface.gd import GravitationalDynamics @@ -38,7 +38,7 @@ def __init__(self): self.integrator_method = "sia21h.dkd" self.pn_order = 0 self.clight = None - self.particles = [] + self.particles = Particles() self.particles_initialized = False def initialize_code(self): @@ -60,43 +60,52 @@ def commit_parameters(self): return 0 def commit_particles(self): - num = len(self.particles) - ps = ParticleSystem(nstars=num) + ps = ParticleSystem(nstars=len(self.particles)) for (i, p) in enumerate(self.particles): ps.id[i] = i ps.mass[i] = p.mass ps.radius[i] = p.radius # XXX: 'radius' is not yet used in Tupan. ps.eps2[i] = self.eps2/2 - ps.rx[i] = p.rx - ps.ry[i] = p.ry - ps.rz[i] = p.rz + ps.rx[i] = p.x + ps.ry[i] = p.y + ps.rz[i] = p.z ps.vx[i] = p.vx ps.vy[i] = p.vy ps.vz[i] = p.vz - self.integrator = Integrator(self.eta, - self.time_begin, - ps, - method=self.integrator_method, - pn_order=self.pn_order, - clight=self.clight) + + self.integrator = Integrator( + self.eta, + self.time_begin, + ps, + method=self.integrator_method, + pn_order=self.pn_order, + clight=self.clight + ) return 0 def synchronize_model(self): return 0 - def new_particle(self, index_of_the_particle, - mass, radius, x, y, z, vx, vy, vz): - ps = ParticleSystem(nstars=1) - ps.mass[0] = mass - ps.radius[0] = radius - ps.rx[0] = x - ps.ry[0] = y - ps.rz[0] = z - ps.vx[0] = vx - ps.vy[0] = vy - ps.vz[0] = vz - self.particles.append(ps) - index_of_the_particle.value = len(self.particles)-1 + def new_particle( + self, + index_of_the_particle, + mass, + radius, + x, y, z, + vx, vy, vz, + ): + ps = Particle() + ps.mass = mass + ps.radius = radius + ps.x = x + ps.y = y + ps.z = z + ps.vx = vx + ps.vy = vy + ps.vz = vz + index_of_the_particle.value = len(self.particles) + self.particles.add_particle(ps) + return 0 def set_state(self, index_of_the_particle, From 419a4f2d630529108249515395e7177b1e538883 Mon Sep 17 00:00:00 2001 From: elkogerville Date: Wed, 22 Apr 2026 17:54:29 +0200 Subject: [PATCH 2/6] Tupan: remove get/set_eta from methods since it is a parameter --- src/amuse_tupan/interface.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/amuse_tupan/interface.py b/src/amuse_tupan/interface.py index b1ebab3199..b8534d0bef 100644 --- a/src/amuse_tupan/interface.py +++ b/src/amuse_tupan/interface.py @@ -572,17 +572,17 @@ def define_parameters(self, handler): def define_methods(self, handler): GravitationalDynamics.define_methods(self, handler) - handler.add_method( - "get_eta", - (), - (handler.NO_UNIT, handler.ERROR_CODE,) - ) - - handler.add_method( - "set_eta", - (handler.NO_UNIT,), - (handler.ERROR_CODE,) - ) + # handler.add_method( + # "get_eta", + # (), + # (handler.NO_UNIT, handler.ERROR_CODE,) + # ) + + # handler.add_method( + # "set_eta", + # (handler.NO_UNIT,), + # (handler.ERROR_CODE,) + # ) handler.add_method( "get_time", From 77bd9f3aa0356b8815b958a9629e8d91b4328ea4 Mon Sep 17 00:00:00 2001 From: elkogerville Date: Wed, 22 Apr 2026 17:54:44 +0200 Subject: [PATCH 3/6] Tupan: remove get/set_eta from methods since it is a parameter --- src/amuse_tupan/interface.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/amuse_tupan/interface.py b/src/amuse_tupan/interface.py index b8534d0bef..a4fcfe8f48 100644 --- a/src/amuse_tupan/interface.py +++ b/src/amuse_tupan/interface.py @@ -572,18 +572,6 @@ def define_parameters(self, handler): def define_methods(self, handler): GravitationalDynamics.define_methods(self, handler) - # handler.add_method( - # "get_eta", - # (), - # (handler.NO_UNIT, handler.ERROR_CODE,) - # ) - - # handler.add_method( - # "set_eta", - # (handler.NO_UNIT,), - # (handler.ERROR_CODE,) - # ) - handler.add_method( "get_time", (), From 4a1eefd6f67f7a3c4552360694edd1552ff85c45 Mon Sep 17 00:00:00 2001 From: elkogerville Date: Wed, 22 Apr 2026 17:55:11 +0200 Subject: [PATCH 4/6] remove tupan as a dependency of tupan in toml --- src/amuse_tupan/packages/amuse-tupan/pyproject.toml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/amuse_tupan/packages/amuse-tupan/pyproject.toml b/src/amuse_tupan/packages/amuse-tupan/pyproject.toml index 55893152f3..c1daff5126 100644 --- a/src/amuse_tupan/packages/amuse-tupan/pyproject.toml +++ b/src/amuse_tupan/packages/amuse-tupan/pyproject.toml @@ -3,8 +3,7 @@ name = "amuse-tupan" dynamic = ["version"] requires-python = ">=3.7" dependencies = [ - "amuse-framework", - "amuse_tupan" + "amuse-framework" ] [build-system] @@ -44,4 +43,3 @@ pythonpath = ["amuse_tupan/tests/"] testpaths = ["amuse_tupan/tests"] addopts = "--import-mode=append" # test the installed package - From 39f16a072ef84f58d34e79b692a2d4130c175f86 Mon Sep 17 00:00:00 2001 From: elkogerville Date: Wed, 22 Apr 2026 17:55:45 +0200 Subject: [PATCH 5/6] fix TestTupan::test02 from testing obsolete parameters --- src/amuse_tupan/tests/test_tupan.py | 54 +++++++---------------------- 1 file changed, 13 insertions(+), 41 deletions(-) diff --git a/src/amuse_tupan/tests/test_tupan.py b/src/amuse_tupan/tests/test_tupan.py index bc488f1f2d..f6c32bdfab 100644 --- a/src/amuse_tupan/tests/test_tupan.py +++ b/src/amuse_tupan/tests/test_tupan.py @@ -174,52 +174,24 @@ def test01(self): instance.cleanup_code() instance.stop() - def xtest02(self): + def test02(self): if MODULES_MISSING: self.skip("Failed to import a module required for Tupan") - print("Testing Tupan parameters") + print("Testing Tupan default parameters") instance = self.new_instance_of_an_optional_code(Tupan, self.default_converter) instance.initialize_code() - self.assertEqual(instance.parameters.epsilon_squared, - instance.unit_converter.to_si(0.0 | nbody_system.length**2)) - self.assertEqual(instance.parameters.timestep_parameter, 0.125) - - for par, value in [('epsilon_squared_star_star', 0.0 | nbody_system.length**2), - ('epsilon_squared_star_blackhole', 0.0 | nbody_system.length**2), - ('epsilon_squared_blackhole_blackhole', 0.0 | nbody_system.length**2), - ('initial_timestep_parameter', 1.0e-4), - ('timestep_parameter_stars', 0.1), - ('timestep_parameter_supermassive_black_holes', 0.4), - ('timestep_parameter_intermediate_mass_black_holes', 0.4), - ('max_relative_energy_error', 5.0e-5), - ('maximum_timestep', 1.0/1024.0 | nbody_system.time), - ('smbh_mass', 1.0 | nbody_system.mass)]: - self.assertEqual(instance.unit_converter.to_si(value), - getattr(instance.parameters, par)) - setattr(instance.parameters, par, 3.0 | value.unit) - self.assertEqual(instance.unit_converter.to_si(3.0 | value.unit), - getattr(instance.parameters, par)) - - # epsilon_squared is an alias for epsilon_squared_star_star, so epsilon_squared also has become 3: - self.assertEqual(instance.parameters.epsilon_squared, - instance.unit_converter.to_si(3.0 | nbody_system.length**2)) - instance.parameters.epsilon_squared = 0.1 | nbody_system.length**2 - self.assertEqual(instance.parameters.epsilon_squared, - instance.unit_converter.to_si(0.1 | nbody_system.length**2)) - # timestep_parameter is an alias for timestep_parameter_stars, so timestep_parameter also has become 3: - self.assertEqual(instance.parameters.timestep_parameter, 3.0) - instance.parameters.timestep_parameter = 0.01 - self.assertEqual(instance.parameters.timestep_parameter, 0.01) - - self.assertEqual(instance.parameters.include_smbh, False) - instance.parameters.include_smbh = True - self.assertEqual(instance.parameters.include_smbh, True) - self.assertEqual(instance.parameters.calculate_postnewtonian, True) - instance.parameters.calculate_postnewtonian = False - self.assertEqual(instance.parameters.calculate_postnewtonian, False) - - self.assertEqual(instance.parameters.drink, "Vodka martini. Shaken, not stirred.") + self.assertEquals(instance.parameters.timestep_parameter, 0.03125) + self.assertEquals( + instance.parameters.epsilon_squared, + instance.unit_converter.to_si(0.0 | nbody_system.length**2) + ) + self.assertEquals( + instance.parameters.begin_time, + instance.unit_converter.to_si(0.0 | nbody_system.time) + ) + self.assertEquals(instance.parameters.integrator_method, 'sia21h.dkd') + self.assertEquals(instance.parameters.pn_order, 0) instance.stop() From a566a9b1334416bf97df6830a45db00715749957 Mon Sep 17 00:00:00 2001 From: elkogerville Date: Wed, 22 Apr 2026 18:32:38 +0200 Subject: [PATCH 6/6] cleaned up id assignment logic in TupanImplementation new_particle and commit_particles --- src/amuse_tupan/interface.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/amuse_tupan/interface.py b/src/amuse_tupan/interface.py index a4fcfe8f48..62d09acda4 100644 --- a/src/amuse_tupan/interface.py +++ b/src/amuse_tupan/interface.py @@ -1,10 +1,10 @@ -from amuse.datamodel.particles import Particle, Particles from amuse.community import * from amuse.community.interface.gd import GravitationalDynamicsInterface from amuse.community.interface.gd import GravitationalDynamics from amuse.community.interface.gd import SinglePointGravityFieldInterface from amuse.community.interface.gd import GravityFieldCode +from amuse.datamodel.particles import Particle, Particles from amuse.rfi.core import PythonCodeInterface import sys @@ -62,7 +62,7 @@ def commit_parameters(self): def commit_particles(self): ps = ParticleSystem(nstars=len(self.particles)) for (i, p) in enumerate(self.particles): - ps.id[i] = i + ps.id[i] = p.id ps.mass[i] = p.mass ps.radius[i] = p.radius # XXX: 'radius' is not yet used in Tupan. ps.eps2[i] = self.eps2/2 @@ -95,6 +95,7 @@ def new_particle( vx, vy, vz, ): ps = Particle() + ps.id = len(self.particles) ps.mass = mass ps.radius = radius ps.x = x @@ -103,7 +104,7 @@ def new_particle( ps.vx = vx ps.vy = vy ps.vz = vz - index_of_the_particle.value = len(self.particles) + index_of_the_particle.value = ps.id self.particles.add_particle(ps) return 0