1. Ade Miller
  2. NBody

Wiki

Clone wiki

NBody / Home

Welcome

This project contains some example code taken from the NBody.net project I work on in my spare time.

License: The code is licensed under the Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html) with the exception of the Mersenne Twister implmentation which is licensed under the Artistic license.

Example 1: NBody.DomainModel.Common

This contains many of the interfaces and attributes use by other parts of the application. It also includes some core data types used throughout the rest of the application, notably:

VectorFloat & VectorDouble - 3D Euclidean vectors with X, Y, Z components. These are dynamically generated from a T4 template for single and double precision floating point values; double and float. I'm using this in preference to Vector3D.

Body - Specifies the mass, position, velocity and accelleration for each body in the system.

Example 2: NBody.DomainModel.FSharp

Integrator implementations written in F#. A leapfrog integrator and a much more complex Barnes-Hut tree code integrator which can use other (faster) integrators to do the actual number crunching.

Example 3: NBody.DomainModel

Example 4: NBody.DomainModel.Native and NBody.DomainModel.Native.Ppl

Getting Started

Building the Code

  1. Sync the code from BitBucket $ hg clone http://bitbucket.org/ademiller/nbody/
  2. Open the NBody.sln solution in Visual Studio 2010

Where are the unit tests?! Yeah... Where are the unit tests? They exist, trust me. Overall the code coverage is in excess of 80%. Where it drops below this the difference can largely be accounted for by shortcomings in the coverage tool I'm using (NCover) which doesn't entirely grok F# or C++/CLI generated IL.

Running Models

Currently the code is just that, code. There is no application to show how to plug all the bits together I'm afraid. I'm hoping to add an example of how to do this in the future. However it's very easy to link to the assemblies provided and build a model with the initializers provided.

The following sample builds a uniform cluster and runs it.

IInitialize initializer = new UniformClusterParallelInitializer()
    .OfSize(50)
    .WithRadius(1.0)
    .Build();
IIntegrate integrator = new LeapfrogIntegrator() { SofteningLength = 0.001f };
IUniverse universe = new FixedTimestepUniverse(initializer, integrator, 0.002);

universe.Initialize();

while (universe.Time < 1.0)
{
	universe.Update();
	Console.WriteLine("T = {0}", universe.Time);
}

This is the most basic scenario. It uses a fluent interface in part which I'm still working on so this may change somewhat. You have been warned! You can also use UniverseFactory to configure the IUniverse from a configuration specified with in code or through a Unity configuration file. The C# code looks like this.

UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Configure(config);
UniverseFactory factory = new UniverseFactory();
IUniverse universe = factory.CreateInstance(config);

universe.Initialize();

while (universe.Time < 1.0)
{
	universe.Update();
	Console.WriteLine("T = {0}", universe.Time);
}

The application configuration would look like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="unity"
             type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, 
                        Microsoft.Practices.Unity.Configuration" />
  </configSections>
  <unity xmlns="">
    <!--
      Namespace and assembly mappings to make the container configuration simpler
    -->
    <namespace name="NBody.DomainModel" />
    <namespace name="NBody.DomainModel.Integrators" />
    <namespace name="NBody.DomainModel.Initializers" />
    <namespace name="NBody.DomainModel.Universes" />
    <assembly name="NBody.DomainModel" />
    <assembly name="NBody.DomainModel.Cuda" />
    <assembly name="NBody.DomainModel.Native" />
    <assembly name="NBody.DomainModel.Common" />

    <!--
      Actual configuration
    -->
    <container>
      <register type="IUniverse" mapTo="FixedTimestepUniverse" />
      <register type="IInitialize" mapTo="UniformClusterParallelInitializer" />
      <register type="IIntegrate" mapTo="ForwardEulerIntegrator" />
      <instance name="Size" type="int" value="50" />
      <instance name="Radius" type="double" value="1.0" />
      <instance name="SofteningLength" type="float" value="0.01" />
      <instance name="Timestep" type="float" value="0.001" />
    </container>
  </unity>
</configuration>

using a configuration file would allow you to load canned configurations by name, rather than having the user specify them each time.

Code formatting with the vast library of Pygment lexers.

Updated