Bridge

Code

bridge-like integrator for amuse

the bridge class provides a bridge like coupling between different gravitational integrators. In this way a system composed of multiple components can be evolved taking account of the self gravity of the whole system self consistently, while choosing the most appropiate integrator for the self-gravity of the component systems. This is mainly useful for systems consist of two or more components that are either well separated spatially or have different scales (otherwise using a single integrator is more efficient)

The main idea is that systems experience each others gravity through periodic velocty kicks with ordinary evolution in between - the evolution is thus described by an alternation of drift (D) and kick (K) operators, here chosen as:

K(1/2 dt) D(dt) K(1/2 dt)

K(dt) denotes a kick of the velocities over a timestep dt, while D(dt) denotes a drift, meaning secular evolution using self gravity of the system, over dt.

implementation notes:

In order to use bridge the component systems should be initialized as usual, then a bridge systems is initialized, after which one or more systems are added:

from amuse.ext.bridge import bridge

bridgesys=bridge(verbose=False) bridgesys.add_system(galaxy, (cluster,), False) bridgesys.add_system(cluster, (galaxy,), True )

bridge builds on the full gravity interface, so unit handling etc is guaranteed. Bridge itself is a (somewhat incomplete) gravity interface, so the usual evolve, get_potential methods work (and bridge can be a component in a bridge systems). Note that a single coordinate system should be used at the moment for all the components systems (different units are allowed though). The call to add systems, for example:

bridgesys.add_system(galaxy, (cluster,), False)

has three arguments: the system, a set with interaction partners and a flag to specify whether synchronization is needed . The interaction partners indicate which systems will kick the system. In the most simple case these would be the set of other systems that are added, but usually this is not what you want to get good performace. In some cases you want to ignore one direction of interaction (eg. in a combined simulation of a galaxy and a comet orbits around a star you may want the ignore the gravity of the comet), in other cases you want to use a different force calculator (eg integrating a cluster in a galaxy where the galaxy is evolved with a tree code and the cluster with a direct sum code, one also would want to use a tree code to calculate the cluster gravity for the galaxy. In such a case one can derive a skeleton gravity interface from the cluster system. A module is provided with some examples of such derived systems, derived_grav_systems.py

Hints for good use:

The bridgesys is flexible but care should be taken in order to obtain valid results. For one thing, there is no restriction or check on the validity of the assumption of well seperated dynamics: for example any system could be split up and put together in bridge, but if the timestep is chosen to be larger than the timestep criterion of the code, the integration will show errors.

For good performance one should use derived systems to reduce the complexity where possible.

There is an issue with the synchronization: some codes do not end on the exact time of an evolve, or need an explicit sync call. In these cases it is up to the user to determine whether bridge can be used (an explicit sync call may induce extra errors that degrade the order of the integrator).

class amuse.couple.bridge.Bridge(timestep=None, verbose=False, use_threading=True, method=None)
add_system(interface, partners={}, do_sync=True, radius_is_eps=False, h_smooth_is_eps=False, zero_smoothing=False)

add a system to bridge integrator

evolve_model(tend, timestep=None)

evolve combined system to tend, timestep fixes timestep

synchronize_model()

explicitly synchronize all components

class amuse.couple.bridge.AbstractCalculateFieldForCodes(input_codes, verbose=False, required_attributes=None)

Calculated gravity and potential fields using the particles of other codes with the code provided.

evolve_model(tend, timestep=None)
class amuse.couple.bridge.CalculateFieldForCodes(code_factory_function, input_codes, *args, **kwargs)

Calculated gravity and potential fields using the particles of other codes with the code provided. The code is created for every calculation.

class amuse.couple.bridge.CalculateFieldForCodesUsingReinitialize(code, input_codes, *args, **kwargs)

Calculated gravity and potential fields using the particles of other codes with the code provided. The code is created for every calculation.

class amuse.couple.bridge.CalculateFieldForCodesUsingRemove(code, input_codes, *args, **kwargs)

Calculated gravity and potential fields using the particles of other codes with the code provided. The code is created for every calculation.

class amuse.couple.bridge.CalculateFieldForParticles(particles=None, gravity_constant=None, softening_mode='shared', G=None)

Calculates an field for a set of particles, the set of particles can be from another code.

evolve_model(tend, timestep=None)
class amuse.couple.bridge.GravityCodeInField(code, field_codes, do_sync=True, verbose=False, radius_is_eps=False, h_smooth_is_eps=False, zero_smoothing=False)
cannot_kick()

check if the code is capable of kicking other particles, please do not try to optimize this, I know it is called every kick but only calculating it at the start causes an annoying bug in certain uses of the code.

evolve_model(tend, timestep=None)

evolve combined system to tend, timestep fixes timestep

synchronize_model()

explicitly synchronize all components