====================
Setting up a problem
====================

Defining a test matrix with :code:`xarray`
------------------------------------------

The shortest way to set the parameters of the potential flow problems to be solved is to build a `xarray <http://xarray.pydata.org>`_ dataset.
Then the function :meth:`fill_dataset <capytaine.bem.solver.BEMSolver.fill_dataset>` will automatically make all the simulations defined in the test matrix.

::

    import numpy as np
    import xarray as xr
    import capytaine as cpt

    body = ...  # Set up the body and its dofs here.

    test_matrix = xr.Dataset(coords={
        'omega': np.linspace(0.1, 4, 40),
        'wave_direction': [0, np.pi/2],
        'radiating_dof': list(body.dofs),
        'water_depth': [np.inf],
    })
    dataset = cpt.BEMSolver().fill_dataset(test_matrix, body)

The first argument of :code:`fill_dataset` is an :code:`xarray.Dataset`
specifying the cases to be run. When a parameter is not specified in the
dataset, the default value is used (see next section).

The second argument is either a single :code:`FloatingBody` or a list of
:code:`FloatingBody`. In the latter case, each body in the list is studied
independently and the output dataset contains one dimension more.

:code:`fill_dataset` returns an :code:`xarray.Dataset` with the same
coordinates as its input but filled with additional output data.
See :doc:`export_output` for methods to export this dataset in
various formats.

If the coordinate :code:`theta` is added to the test matrix, the code will
compute the Kochin function for these values of :math:`\theta`.


The :class:`~capytaine.problems.LinearPotentialFlowProblem` class
-----------------------------------------------------------------

For a finer grain control of the problems to be solved, a list of :code:`LinearPotentialFlowProblem` should be defined.
It is defined as, e.g.::

    problem = cpt.RadiationProblem(body=my_body, omega=1.0, radiating_dof="Heave")
    other_problem = cpt.DiffractionProblem(body=my_body, omega=1.0, wave_direction=pi/2)

Besides the body, all the parameters are optional.
The table below gives their definitions and their default values.

+------------------------+----------------------------------------------------+----------------------+
| Parameter              | Description (unit)                                 | Default value        |
+========================+====================================================+======================+
| :code:`free_surface`   | Position of the free surface [#]_ (m)              | :math:`0.0` m        |
+------------------------+----------------------------------------------------+----------------------+
| :code:`water_depth`    | Constant depth of water (m)                        | :math:`\infty` m     |
+------------------------+----------------------------------------------------+----------------------+
| :code:`g`              | Acceleration of gravity :math:`g` (m/s²)           | :math:`9.81` m/s²    |
+------------------------+----------------------------------------------------+----------------------+
| :code:`rho`            | Water density (kg/m³)                              | :math:`1000.0` kg/m³ |
+------------------------+----------------------------------------------------+----------------------+
| :code:`wave_direction` | Direction of the incoming waves (rad)              | :math:`0.0` rad [#]_ |
|                        | (for diffraction or forward speed)                 |                      |
+------------------------+----------------------------------------------------+----------------------+
| :code:`radiating_dof`  | Name of radiating dof                              | first one found      |
|                        | (only for radiation)                               |                      |
+------------------------+----------------------------------------------------+----------------------+
| :code:`forward_speed`  | Speed of the body in the :math:`x` direction (m/s) | :math:`0.0` m/s      |
+------------------------+----------------------------------------------------+----------------------+

.. [#] Only two positions are accepted for the free surface: :math:`z=0.0` and
       :math:`z= +\infty`. The former is the usual case for linear potential
       flow. The latter corresponds to an object in an infinite
       potential flow domain with no free surface.

.. [#] A wave direction of :math:`0` rad corresponds to a wave propagating along
       the :math:`x`-axis from :math:`x = -\infty` to :math:`x= + \infty`.

.. warning::
   Unlike other software such as Nemoh, the wave direction in Capytaine is expressed in radians.

The wave height is implicitly assumed to be :math:`1` m.
Since all computations are linear, any wave height or motion amplitude can be
retrieved by multiplying the result by the desired value.

Setting the frequency is done by passing **one and only one** of the following magnitude.

+--------------------+-------------------------------------------------------------+
| Parameter          | Description (unit)                                          |
+====================+=============================================================+
| :code:`omega`      | Angular frequency :math:`\omega` (rad/s)                    |
+--------------------+-------------------------------------------------------------+
| :code:`freq`       | Frequency :math:`f` (Hz)                                    |
+--------------------+-------------------------------------------------------------+
| :code:`period`     | Period :math:`T = \frac{2\pi}{\omega}` (s)                  |
+--------------------+-------------------------------------------------------------+
| :code:`wavelength` | Wavelength :math:`\lambda` (m)                              |
+--------------------+-------------------------------------------------------------+
| :code:`wavenumber` | Angular wavenumber :math:`k = \frac{2\pi}{\lambda}` (rad/m) |
+--------------------+-------------------------------------------------------------+

If no frequency is provided, a frequency :code:`omega = 1.0` rad/s is used by default.
Once the problem has been initialized, the other parameters can be retrieved as::

    problem.omega
    problem.freq
    problem.period
    problem.wavelength
    problem.wavenumber

When forward speed is non zero, the encounter frequency is computed and can be retrieved as::

    problem.encounter_omega
    problem.encounter_freq
    problem.encounter_period
    problem.encounter_wavelength
    problem.encounter_wavenumber


For radiation problems, setting the frequency to zero or infinity is possible.
Simply pass the value `0.0` or `float('inf')` to one of the above magnitude.
The default Green function supports zero and infinite frequency in infinite
depth, and infinite frequency in finite depth (but not zero frequency in finite
depth).


Importing a dataset from Bemio
------------------------------

A DataFrame or a Dataset can also be created from data structures generated
using the `Bemio <https://wec-sim.github.io/bemio/>`_ package, which reads
hydrodynamic output data from NEMOH, WAMIT, and AQWA. This allows for Capytaine
post-processing of hydrodynamic data generated from other BEM codes.

Bemio does not come packaged with Capytaine and needs to to be installed independently.
Note that `the base repository of Bemio <https://github.com/WEC-Sim/bemio/>`_ has been
archived and is only compatible with Python 2.7.x, so using a Python 3 compatible fork is
recommended, available `here <https://github.com/mancellin/bemio>`_ or installed with::

  pip install git+https://github.com/mancellin/bemio.git

To build the xarray dataset using Capytaine, the output files from the BEM program in
question must be read into a Bemio :code:`data_structures.ben.HydrodynamicData` class, which is
then called by `assemble_dataframe` or `assemble_dataset`. For example, to
create an xarray dataset from a WAMIT :code:`.out` file::

  from bemio.io.wamit import read as read_wamit
  import capytaine as cpt
  bemio_data = read_wamit("myfile.out")
  my_dataset = cpt.assemble_dataset(bemio_data, hydrostatics=False)

.. warning:: The created dataset will only contain quantities that can be directly calculated
             from the values given in the original dataset. Because of this, there may be minor
             differences between the variable names in an xarray dataset build with Bemio and one created
             using :code:`LinearPotentialFlowResult`, even though the format will be identical. For
             example, WAMIT :code:`.out` files do not contain the radii of gyration needed to calculate
             the moments of inertia, so the `my_dataset['inertia_matrix']` variable would not be included
             in the above example since the rigid body mass matrix cannot be calculated.


Legacy Nemoh.cal parameters files
---------------------------------

The `legacy parameters files from Nemoh <https://lheea.ec-nantes.fr/logiciels-et-brevets/nemoh-running-192930.kjsp>`_ can be read by a dedicated function::

    from capytaine.io.legacy import import_cal_file

    list_of_problems = import_cal_file("path/to/Nemoh.cal")

The function returns a list of :code:`LinearPotentialFlowProblems`.

.. warning:: This feature is experimental.
    Some of the settings in the files (such as the free surface computation or the Kochin function) are ignored for the moment.
    See the example :code:`Nemoh.cal` below.

.. literalinclude:: Nemoh.cal

.. note:: The line setting up the frequencies is slightly different in Nemoh v2 and Nemoh v3.
   Both format are supported by Capytaine.

Command-line interface
----------------------

.. warning:: This feature is experimental.

Capytaine comes with a command-line command :code:`capytaine` which can be used as::

    $ capytaine path/to/directory/parameter.cal

The parameter file (in :code:`Nemoh.cal` format) passed as argument is read and legacy tecplot output file are written in the directory :code:`path/to/directory/results/`.

.. warning:: If results files already exist, they will be overwritten!

If no argument is provided to the command, the code looks for a file :code:`Nemoh.cal` in the current directory.
