Skip to content
Snippets Groups Projects
Commit d7ec1ffc authored by Cristian Lalescu's avatar Cristian Lalescu
Browse files

add basic tutorial

parent 8356ff21
No related branches found
No related tags found
No related merge requests found
================================
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.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment