Commit d7ec1ffc authored by Cristian Lalescu's avatar Cristian Lalescu
Browse files

add basic tutorial

parent 8356ff21
================================
Big Fluid and Particle Simulator
================================
......@@ -20,6 +21,9 @@ I plan on adding documentation on the procedure as when other people
show interest in using the code, or when time permits.
.. _sec-installation:
------------
Installation
------------
......@@ -54,6 +58,7 @@ Also, in order to run the C++ code you need to have an MPI compiler
installed, the HDF5 C library as well as FFTW 3 (at least 3.3 I think).
--------
Comments
--------
......
......@@ -699,6 +699,12 @@ class NavierStokes(bfps.fluid_base.fluid_particle_base):
self,
field_name = 'vorticity',
iteration = 0):
"""read the Fourier representation of a vector field.
Read the binary file containing iteration ``iteration`` of the
field ``field_name``, and return it as a properly shaped
``numpy.memmap`` object.
"""
return np.memmap(
os.path.join(self.work_dir,
self.simname + '_{0}_i{1:0>5x}'.format('c' + field_name, iteration)),
......
......@@ -113,6 +113,7 @@ def padd_with_zeros(
:param odtype: data type to use --- in principle conversion between
single and double precision can be performed with this
function as well.
If ``None``, then use ``a.dtype``.
:type n0: int
:type n1: int
:type n2: int
......
===
API
===
bfps.NavierStokes
-----------------
----------
bfps.tools
----------
.. autoclass:: NavierStokes.NavierStokes
.. automodule:: tools
:members:
:undoc-members:
:inherited-members:
:show-inheritance:
bfps.tools
----------
.. automodule:: tools
-----------------
bfps.NavierStokes
-----------------
.. autoclass:: NavierStokes.NavierStokes
:members:
:undoc-members:
:inherited-members:
......
===========
Development
===========
---------------------
Versioning guidelines
---------------------
......@@ -47,6 +49,7 @@ projects, these may change.
forked from `vX.Y`, and then rule 3 is adapted accordingly.
------------
Code testing
------------
......
=====================
Overview and Tutorial
=====================
---------
Equations
---------
......@@ -22,6 +24,126 @@ In fact, the code solves the vorticity formulation of these equations:
\mathbf{\omega} \cdot \nabla \mathbf{u} +
\nu \Delta \mathbf{\omega} + \nabla \times \mathbf{f}
-----------
Conventions
-----------
The C++ backend is based on ``FFTW``, therefore the Fourier
representations are *transposed*.
In brief, this is the way the fields are represented on disk and in
memory (both in the C++ backend and in Python postprocessing):
* real space representations of 3D vector fields consist of
contiguous arrays, with the shape ``(nz, ny, nx, 3)``:
:math:`n_z \times n_y \times n_x` triplets, where :math:`z` is the
slowest coordinate, :math:`x` the fastest; each triplet is then
the sequence of :math:`x` component, :math:`y` component and
:math:`z` component.
* Fourier space representations of 3D vector fields consist of
contiguous arrays, with the shape ``(ny, nz, nx/2+1, 3)``:
:math:`k_y` is the slowest coordinate, :math:`k_x` the fastest;
each triplet of 3 complex numbers is then the :math:`(x, y, z)`
components, as ``FFTW`` requires for the correspondence with the
real space representations.
:func:`read_cfield <NavierStokes.NavierStokes.read_cfield>` will return
a properly shaped ``numpy.array`` containing a snapshot of the Fourier
representation of a 3D field.
If you'd like to construct the corresponding wave numbers, you can
follow this procedure:
.. code:: python
import numpy as np
from bfps import NavierStokes
c = NavierStokes(
work_dir = '/location/of/simulation/data',
simname = 'simulation_name_goes_here')
df = c.get_data_file()
kx = df['kspace/kx'].value
ky = df['kspace/ky'].value
kz = df['kspace/kz'].value
df.close()
kval = np.zeros(kz.shape + ky.shape + kx.shape + (3,),
dtype = kx.dtype)
kval[..., 0] = kx[None, None, :]
kval[..., 1] = ky[:, None, None]
kval[..., 2] = kz[None, :, None]
``kval`` will have the same shape as the result of
:func:`read_cfield <NavierStokes.NavierStokes.read_cfield>`.
Obviously, the machine being used should have enough RAM to hold the
field...
--------
Tutorial
--------
First DNS
---------
Installing ``bfps`` is not trivial, and the instructions are in
:ref:`sec-installation`.
After installing, you should have a new executable script
available, called ``bfps``, that you can execute.
Just executing it will run a small test DNS on a real space grid of size
:math:`32 \times 32 \times 32`, in the ``N0032`` folder in your current
folder, with the simulation name ``test``.
So, open a console, and type ``bfps``:
.. code:: bash
# depending on how curious you are, you may have a look at the
# options first:
bfps --help
# or you may just run it:
bfps
The simulation itself should not take more than a few seconds, since
this is just a :math:`32^3` simulation run for 8 iterations.
First thing you can do afterwards is open up a python console, and type
the following:
.. code:: python
import numpy as np
from bfps import NavierStokes
c = NavierStokes(
work_dir = '/location/of/simulation/data',
simname = 'simulation_name_goes_here')
c.compute_statistics()
print ('Rlambda = {0:.0f}, kMeta = {1:.4f}, CFL = {2:.4f}'.format(
c.statistics['Rlambda'],
c.statistics['kMeta'],
(c.parameters['dt']*c.statistics['vel_max'] /
(2*np.pi/c.parameters['nx']))))
print ('Tint = {0:.4e}, tauK = {1:.4e}'.format(c.statistics['Tint'],
c.statistics['tauK']))
print ('total time simulated is = {0:.4e} Tint, {1:.4e} tauK'.format(
c.data_file['iteration'].value*c.parameters['dt'] / c.statistics['Tint'],
c.data_file['iteration'].value*c.parameters['dt'] / c.statistics['tauK']))
:func:`compute_statistics <NavierStokes.NavierStokes.compute_statistics>`
will read the data
file generated by the DNS, compute a bunch of basic statistics, for
example the Taylor scale Reynolds number :math:`R_\lambda` that we're
printing in the example code.
What happens is that the DNS will have generated an ``HDF5`` file
containing a bunch of specific datasets (spectra, moments of real space
representations, etc).
The function
:func:`compute_statistics <NavierStokes.NavierStokes.compute_statistics>`
performs simple postprocessing that may however be expensive, therefore
it also saves some data into a ``<simname>_postprocess.h5`` file, and
then it also performs some time averages, yielding the ``statistics``
dictionary that is used in the above code.
What happened
-------------
Behind the scenes, something more complicated took place.
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment