The main purpose of a fargo3D simulation is to track the evolution of a planetary system embedded in a disk of gas. Those two entities will be represented by a **GasDisk** and **PlanetarySystem** class respectively. A single simulation will instantiate one object of each.
That simulation is driven by an instance of the **SimulationDriver** class (currently implementing a simple [Command pattern](https://en.wikipedia.org/wiki/Command_pattern), but might evolve into a [Template Method](https://en.wikipedia.org/wiki/Template_method_pattern). It behave like a function object with perform one step of the simulation at each call.
The simulation configuration is done through a property tree.
The main sequence diagram can be seen as follow:
```plantuml
participant main
participant driver
participant gasDisk
participant planets
database storage
main -> gasDisk : load initial state
main -> driver : create
loop monitor
loop time steps
main -> driver : next step
driver -> gasDisk : sub step 1
driver -> gasDisk : sub step <N>
gasDisk -> planets : rotate
driver -> main : done
end
main -> gasDisk : write state
gasDisk -> storage : dump fields
main -> planets : monitor
planets -> storage : write position and masses
main -> storage : write disk info
end
```
The (incomplete) class diagram[^1] could be summarized as:
The most part of the program is spent manipulating **PolarGrid**[^2] instances. A polar grid is basically a 3D field of continuous floating point data organized on a grid with as `[nr radial][ni layer][ns sector]` if we use $`nr*ni*ns`$ grids.
This object only store the data as a [std::valarray<double>](http://www.cplusplus.com/reference/valarray/)[^4] object field, but also export it as an old fashioned C pointer[^3].
## The disk description
The disk geometry and physic configuration are described through a set of classes that are almost (almost) a [Singleton](https://en.wikipedia.org/wiki/Singleton_pattern) (because we do not need many of them). All object that need to have access to those information do so by referencing the appropriate instances.
The "almost" is important, as in the short term, it will allow close to trivial implementation of multi-grid decomposition by providing one instance by sub-domain.
* **DiskPhysic** provide the physical parameter of the disk. It is close to a direct mapping of the user provided property tree.
* **SystemPhysic** paly a similar role for the planetary system.
* **DiskGrid** is . It describe discretization of the (possibly flat) cylinder containing the gas. That include the grid points, aperture, etc.. and some usefull pre computed values. More than one **DiskGrid** object exist when the grid resolution is modified and a polar grid need to be re-mapped.
## Boundaries Conditions
Boundaries condition are implemented through **BoundariesHandler** [function objects](https://en.wikipedia.org/wiki/Command_pattern)[^5].
* All available handlers are registered by name in the application (user can add their own).
* In the configuration file, the user indicate the names of the requested handler.
* The application then bind those handler to the **GasDisk** object.
* The **SimulationDriver** object will then trigger them when required.
-------
[^1]: In particular, the diagram does not detail the configuration aspects in details.
[^2]: Not a very smart name, but **Field** was already used at the time. It might change in the future.
[^3]: Mostly for backward compatibility/laziness/lack of time.
[^4]: Intel has [special optimizations](https://software.intel.com/en-us/articles/using-improved-stdvalarray-with-intelr-c-compiler) for `std::valarray`, has not been tested yet.