.. _sliding_interface:
.. |deg|    unicode:: U+000B0 .. DEGREE SIGN

Time-accurate RANS CFD on a propeller using a sliding interface: the XV-15 rotor geometry
==========================================================================================

The `XV-15 tiltotor aircraft <https://en.wikipedia.org/wiki/Bell_XV-15>`__ is a commonly used test bed for propeller validation work. As you can see from the following papers, we have done extensive validation work on this geometry. We will now use it to show you how to analyze a propeller-type geometry using a sliding mesh interface.

*   :ref:`Rotor5: Rotor analysis under 5 hours using ultra-fast and high-fidelity CFD simulation and automatic meshing<rotor5Paper>`
*   :ref:`Assessment of Detached Eddy Simulation and Sliding Mesh Interface in Predicting Tiltrotor Performance in Helicopter and Airplane Modes<DESXV15>`

This same geometry and case was already used in a :ref:`Quick Start <sliding_interface_quickstart>` example. Here we will go more in depth into how to get a sliding interface case setup.

Rotational and stationary volumes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In order to run a rotating geometry we need to set up a mesh with two blocks, an inner “rotational volume” and an outer “stationary volume”. The interface between those two volumes needs to be a solid of revolution (i.e., sphere, cylinder, etc.).

.. figure:: Figures/rotInterfaceView.png
    :width: 600px
    :align: center
    :alt: Inner block enclosing the XV-15 3-bladed prop

    Inner block enclosing the XV-15 3-bladed prop

.. figure:: Figures/farfieldView.png
        :width: 600px
        :align: center
        :alt: Farfield volume enclosing inner block

        Farfield volume enclosing inner block

.. _nestedInterfaces:

.. figure:: Figures/fig4.png
        :width: 600px
        :align: center
        :alt: Body-fitted cylinder blocks inside a larger nearfield domain

        Body-fitted cylinder blocks inside a larger nearfield domain

Please note that it is possible, just like in the figure above, to set up nested sliding interfaces to simulate, for example, a rotating propeller with blades that pitch as they rotate (i.e., a helicopter\'s cyclical). We could also put many rotating blocks inside the stationary farfield block to simulate multiple rotors.

Sliding interface requirements
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. versionadded:: release-23.3.2.0

   Starting from release 23.3.2.0 of flow360, sliding interfaces no longer need to be constructed with concentric rings. Instead, they can be made of any unstructured mesh that includes triangular and/or quadrilateral elements. Please see :ref:`the mesh sliding interface entry <knowledge_base_mesh_sliding_interface>`

.. figure:: Figures/arbitrarily_unstructured_sliding_interface.png
    :width: 600px
    :align: center
    :alt: Arbitrarily unstructured sliding interface mesh. (Half of the interface is made transluscent to show the enclosed blades)

    Arbitrarily unstructured sliding interface mesh. (Half of the interface is made transluscent to show the enclosed blades)

XV-15 setup
~~~~~~~~~~~

The rotor has a 150” (inches) radius and the blades have a chord of roughly 11”. For simplicity's sake we will use the SI system and convert these to 3.81 m radius and 0.279 m chord.

A complete `CGNS mesh is available here <https://simcloud-public-1.s3.amazonaws.com/xv15/XV15_Hover_ascent_coarse_v2.cgns>`_.

.. attention:: The mesh file must be in the CGNS format if it contains multiple volume zones.

The **XV15_Hover_ascent_coarse_v2.cgns** mesh contains the following blocks and associated boundaries and zone grid connectivities. See :ref:`CGNS Knowledge Base <knowledge_base_cgnsMeshFormat>` for more details .

.. code-block:: python

    farField
        <Boundaries>:
            farField
        <ZoneGridConnectivity>:
            innerRotating
    innerRotating
        <Boundaries>:
            blade
        <ZoneGridConnectivity>:
            farField

This shows us that we have two volume mesh zones (*farField* and *innerRotating*). Inside *innerRotating* we have the *blade* NoSlipWall boundary. Associated with the *farField* zone is the *farField* boundary. Each zone also has information about zone grid connectivity, which tells Flow360 that *innerRotating* and *farField* volume zones are adjacent to each other.


Uploading your mesh
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

With the mesh file and its associated mesh configuration json file. You can upload the mesh either by using the :ref:`Web UI <quick_start_geometry>` or the :ref:`Python API <quick_start_pyAPI>`.

Defining a case using Flow360 Python API.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Once your mesh has been uploaded, the last step before launching a run is to create a python script with all the information needed by Flow360 to run your case. Here a sample :download:`Python Script <../../../../Flow360/examples/advanced_simulations/rotorcraft/RANS_xv15.py>` is provided. Please refer to the :ref:`Python API Guide <python_API_guide>` and :ref:`Reference <python_API_reference>` sections for details about how to create the python script.

Case input conditions
~~~~~~~~~~~~~~~~~~~~~~

For our case we have the following operating conditions:

-   Airspeed = 5 m/s
-   Rotation rate = 600 RPM
-   Speed of sound = 340.2 m/s
-   Density = 1.225 kg/m\ :sup:`3`
-   Alpha = -90 |deg|, air coming down from above (i.e., an ascent case)

Other key considerations:

-   The reference velocity magnitude is arbitrarily set to the tip velocity magnitude of the blades, with an estimated :math:`\text{Mach} \approx 0.7` (238.14 m/s)
-   For simulation, we will do 5 revolutions at 3 |deg| per time step, thus 600 physical time steps in total

We use the Flow360 Python API to set up the rotation zone, operating condition, time stepping, volume and surface models as follows:


.. _XV15_tutorial_case_python_script:
.. code-block:: python
    :linenos:

    rotation_zone = volume_mesh["innerRotating"]
    rotation_zone.center = (0, 0, 0) * fl.u.m
    rotation_zone.axis = (0, 0, -1)
    operating_condition=fl.AerospaceCondition(
        velocity_magnitude=5 * fl.u.m / fl.u.s,
        alpha=-90 * fl.u.deg,
        reference_velocity_magnitude=238.14 * fl.u.m / fl.u.s,
    )
    time_stepping=fl.Unsteady(
        max_pseudo_steps=35,
        steps=600,
        step_size=0.5 / 600 * fl.u.s,
        CFL=fl.AdaptiveCFL(),
    )
    models=[
        fl.Fluid(
            navier_stokes_solver=fl.NavierStokesSolver(
                absolute_tolerance=1e-9,
                linear_solver=fl.LinearSolver(max_iterations=35),
            ),
            turbulence_model_solver=fl.SpalartAllmaras(
                absolute_tolerance=1e-8,
                linear_solver=fl.LinearSolver(max_iterations=25),
                DDES=True,
                rotation_correction=True,
                equation_evaluation_frequency=1,
            ),
        ),
        fl.Rotation(
            volumes=rotation_zone,
            spec=fl.AngularVelocity(600 * fl.u.rpm),
        ),
        fl.Freestream(surfaces=volume_mesh["farField/farField"], name="Freestream"),
        fl.Wall(surfaces=volume_mesh["innerRotating/blade"], name="NoSlipWall"),
    ]


Case running
~~~~~~~~~~~~~~~~~~~~~~
As mentioned in the :ref:`Quick Start <sliding_interface_quickstart>` example, using either the :ref:`Web UI <quick_start_geometry>` or the :ref:`Python API <quick_start_pyAPI>` please launch a new case using the mesh you have uploaded :ref:`above <uploadXV15meshFile>` and the python script you have :ref:`just downloaded <xv15jsondownload>`. The simulation takes about 3.5 to 4 minutes to run 5 revolutions. 

For a time accurate case to be considered well converged we like to have at least 2 orders of magnitude in the residuals within each time step.

.. figure:: Figures/residuals_convergence.png
    :width: 1000px
    :align: center
    :alt: convergence of residuals

    Convergence plot showing more then 2 orders of magnitude decrease in the residuals for each time step.

The forces also seem to have stabilized after running for 5 revolutions.

.. figure:: Figures/force_convergence.png
    :width: 600px
    :align: center
    :alt: convergence of forces

    Force history plot showing good stabilization of the forces.

Congratulations. You have now run your first propeller using a sliding interface in Flow360.
