.. _pyover-example-powered-nacelle:

--------------------------------
OVERFLOW Powered Nacelle Example
--------------------------------

This pyOver example shows how to use ``pyover`` to run one of the simple test
cases that come with the OVERFLOW source code. This example starts with the
grids and inputs files that are created within the OVERFLOW examples, and
documents how to create the pyOver setup, run matrix, how to run several
OVERFLOW cases, covers some post-processing. This example is located in a
git repo. After cloning this repo, enter the resulting folder


    .. code-block:: console

        $ git clone https://github.com/nasa-ddalle/pyover02-powered_nacelle.git
        $ cd pyover02-powered_nacelle

the folder has the required input files, but it's recommended to copy them to a
working folder so that it's easy to reset. Just run the following command:

    .. code-block:: console

        $ ./copy_files.py
        $ cd work/

This example shows how to use pyOver for a test case with two related
configurations, a flow-through axisymmetric nacelle, and a powered axisymmetric
nacelle. The example comes with the grids and input files ready to run
OVERFLOW.


Flow-Through Nacelle Case
-------------------------

Given the grid and input files created by the OVERFLOW scripts, the only two
files that are required to run the flow-through example using pyOver are
``flowthrough.json`` and ``inputs/matrix/flowthrough.csv``.

To execute and duplicate the OVERFLOW Mach 0.8 flow-through example, simply run
the command ``pyover -f flowthrough.json -I 1``. This simple problem
will run in a matter of seconds:

    .. code-block:: console

        pyover -f flowthrough.json -I 1
        Case Config/Run Directory  Status  Iterations  Que CPU Time 
        ---- --------------------- ------- ----------- --- --------
        1    flowthrough/m0.8      ---     /           .            
          Case name: 'flowthrough/m0.8' (index 1)
             Starting case 'flowthrough/m0.8'
         > overrunmpi -np 8 run 01
             (PWD = 'flowthrough/m0.8')
             (STDOUT = 'overrun.out')
           Wall time used: 0.00 hrs (phase 0)
           Wall time used: 0.00 hrs
           Previous phase: 0.00 hrs
         > overrunmpi -np 8 run 02
             (PWD = 'flowthrough/m0.8')
             (STDOUT = 'overrun.out')
           Wall time used: 0.00 hrs (phase 1)
        
        Submitted or ran 1 job(s).
        
        ---=1, 

This ran the MPI version of OVERFLOW locally, (without submitting a PBS job or
similar) using 8 processors (cores). The actions that pyOver takes are
summarized here:

    #. Create the directory ``flowthrough/m0.8/``
    #. Create symbolic links pointing to some files in ``common_flowthrough``
    #. Create two OVERFLOW inputs files ``run.01.inp`` and ``run.02.inp``
    #. Execute ``overrunmpi -np 8 run 01``
    #. Execute ``overrunmpi -np 8 run 02``


The sections in ``flowthrough.json`` that control the execution of
OVERFLOW are shown here:

    .. code-block:: javascript


        // Namelist template
        "OverNamelist": "common_flowthrough/overflow.inp",
        // Options for overall run control and command-line inputs
        "RunControl": {
            // Run sequence
            "PhaseSequence": [0,   1],
            "PhaseIters":    [600, 1400],
            // Operation modes
            "Prefix": "run",
            "MPI": true,
            "qsub": false,
            "Resubmit": [false, true],
            "Continue": true,
            "mpicmd": null,
            "nProc": 8,
            // Dictionary of environment variables
            "Environ": {
                "F_UFMTENDIAN": "little"
            },

            // OVERFLOW command-line interface
            "overrun": {
                "cmd": "overrunmpi",
                "aux": null
            }
        },


The *PhaseSequence* and *PhaseIters* specify how many times and how long the
code is run. The first specifies that OVERFLOW will run for phase ``0`` and
phase ``1``, (which are labeled as ``01`` and ``02`` for ``overrunmpi``
execution). These phases run until there are 600 and 1400 total global steps
in OVERFLOW. For these and other inputs in the .json file, the sequential
list of arguments are applied to sequentially to each phase. Note that
if only one value is given, that value is applied for all phases. Also note
that if the number of phases are greater than the number of inputs in a
sequential list, the latter phases will use the last value given in the list.

Setting *MPI* to ``true`` instructs pyOver to use the MPI version
of OVERFLOW, but setting *mpicmd* to ``null`` is required because we want
pyOver to use the ``overrunmpi`` script, as specified by the *cmd* value in
the *overrun* section.

Note that the actual number of iterations in one run of each phase is not set
in the *RunControl* section above. These are controlled by the OVERFLOW input
variable *NSTEPS* in the *GLOBAL* namelist. In the first phase we are also
running full-multi-grid (FMG) iterations with ``FMGCYC = [[300, 300]]`` and
*NSTEPS[0]* = 0, thus 600 total iterations in the first phase. 

Here are the sections in ``flowthrough.json`` that control the *GLOBAL*
and *OMIGLB* namelists:

    .. code-block:: javascript

        // Namelist inputs
        "Overflow": {
            "GLOBAL": {
                "NQT": 102,
                "NSTEPS": [0,   800],
                "NSAVE":  [0,  2000],
                "FMG": [true, false],
                "FMGCYC": [[300,300]],
                "NGLVL": 3,
                "ISTART_QAVG": 15000,
                "WALLDIST": [2],
                "DTPHYS": [0.0, 0.0, 0.0, 0.0, 1.0],
                "NITNWT": [0,   0,   0,     0,   5]
            },
            "OMIGLB": {
                "IRUN": 0
            }
        },

Here are the sections in ``flowthrough.json`` that control the namelists
for each individual mesh.  The *"ALL":* section is applied to all grids. 
If one wants to specify different input values for a single grid, duplicate
this section and replace *"ALL"* with the name of that grid in double quotes.

    .. code-block:: javascript

        // Namelist parameters for each grid
        "Grids": {
            // Settings applied to all grids
            "ALL": {
                // Solver parameters
                "METPRM": {
                    "IRHS": 0,
                    "ILHS": 2
                },
                "TIMACU": {
                    "ITIME": 1,
                    "DT": 0.10,
                    "CFLMIN": 5.0,
                    "CFLMAX": 0.0
                },
                "SMOACU": {
                    "DIS2": 2.0,
                    "DIS4": 0.04,
                    "DELTA": 1.0
                }
            }
        },
        
Here is the *MESH* section, which tells pyOver which files to copy and which
files to create symbolic links for.

    .. code-block:: javascript

        // Mesh
        "Mesh": {
            // Folder containing definition files
            "ConfigDir": "common_flowthrough",
            // Grid type, dcf or peg5
            "Type": "dcf",
            // List or dictionary of files to link
            "LinkFiles": [
                "grid.in",
                "xrays.in",
                "fomo/grid.ib",
                "fomo/grid.ibi",
                "fomo/grid.nsf",
                "fomo/grid.map"
            ],
            // List of files to copy instead of linking
            "CopyFiles": [
                "Config.xml",
                "fomo/mixsur.fmp"
            ]
        },



One very important section of ``flowthrough.json`` is the *RunMatrix*
section, shown here:

    .. code-block:: javascript

        // RunMatrix description
        "RunMatrix": {
            // If a file is specified, and it exists, trajectory values will be
            // read from it.  RunMatrix values can also be specified locally.
            "File": "inputs/matrix/flowthrough.csv",
            "Keys": ["mach"],
            // Copy the mesh
            "GroupMesh": true,
            // Configuration name [default]
            "GroupPrefix": "flowthrough"
        }

This describes an extremely simple run matrix file, whose only primary input
variable (listed in the *Keys* input) is *mach*. Because the flow-through
nacelle is an axisymmetric flow problem, one cannot run different angles of
incidence, therefore *alpha* and *beta* are not listed as input variables.

Run Mach Sweep
--------------

Having defined the *RunMatrix* section in the json file, we can see that the
run matrix given in the ``inputs/matrix/flowthrough.csv`` file looks
like this:

  .. code-block:: console

    # mach, config, Label
      0.75, flowthrough, 
      0.80, flowthrough, 
      0.85, flowthrough, 
      0.90, flowthrough, 

The run matrix consists of four cases with different Mach numbers. These cases
can all be run using just the command ``pyover``.  Doing this will execute the
three remaining cases (since we ran case 1 in the beginning).  Afterwards, 
check the status of the cases using ``pyover -c``, which should produce a list
showing all the cases with a status of ``DONE``:

  .. code-block:: console

    Case Config/Run Directory  Status  Iterations  Que CPU Time 
    ---- --------------------- ------- ----------- --- --------
    0    flowthrough/m0.75     DONE    1400/1400   .        0.0 
    1    flowthrough/m0.8      DONE    1400/1400   .        0.0 
    2    flowthrough/m0.85     DONE    1400/1400   .        0.0 
    3    flowthrough/m0.9      DONE    1400/1400   .        0.0 
    
    DONE=4, 


Report Generation
-----------------

After running all four cases in the run matrix, the next thing to do is
examine the convergence and view the flow. This can be accomplished for our
case using the command:

    .. code-block:: console

        pyover --report -I 0:4

This will create the report in the file ``report/report-flowthrough.pdf``.
There should be two pages for each case, one page with a table of aerodynamic
data and several convergence plots, and one page with two flow-visualization
figures.

Convergence Plots
^^^^^^^^^^^^^^^^^

Nine different convergence plots are shown on the first page of the report for
each case.  In addition to plotting the history of the three force coefficients
and the three moment coefficients, the plot of the residual history, two
different views are added zooming into the tail end of the axial force
coefficient convergence.  The *force_CAzoom1* and *force_CAzoom2* subfigures
show the last 800 and last 400 iterations of the convergence history. 
The definition of the subfigures used to view the convergence is relatively
straightforward. The following shows the these subfigure definitions in
``flowthrough.json``:


    .. code-block:: javascript

        // Definitions for subfigures
        "Subfigures": {
            ...
            ...
            // Iterative history
            "force": {
                "Type": "PlotCoeff",
                "Component": "TOTAL FORCE",
                "nPlotFirst": 0,
                "FigWidth": 4.5,
                "FigHeight": 3.4,
                "Width": 0.33,
                "StandardDeviation": 1.0
            },
            "force_CA": {"Type": "force", "Coefficient": "CA"},
            "force_CY": {"Type": "force", "Coefficient": "CY"},
            "force_CN": {"Type": "force", "Coefficient": "CN"},
            "force_CLL": {"Type": "force", "Coefficient": "CLL"},
            "force_CLM": {"Type": "force", "Coefficient": "CLM"},
            "force_CLN": {"Type": "force", "Coefficient": "CLN"},
            "force_CAzoom1": {
                "Type": "force", 
                "Coefficient": "CA",
                "nPlotFirst": -800
            },
            "force_CAzoom2": {
                "Type": "force", 
                "Coefficient": "CA",
                "nPlotFirst": -400
            },
            // Residual history
            "L2": {
                "Type": "PlotL2",
                "FigWidth": 5.5,
                "FigHeight": 6,
                "Width": 0.33,
                "nPlotFirst": 1,
                "Caption": "$L_2$ Density Residual"
            }
        }

When viewing the convergence and showing the entire history it can appear that
the forces are very tightly converged. But when viewing the tail end, one can
see that the axial force is still dropping slightly. The following figures show
four of the convergence plots illustrating the three views of *CA* as well
as the history of the L2 norm of the residual of the mean-flow quantities.

    .. _tab-pyover-nacelle-01:
    .. table:: Convergence plots for the m0.75 case

        +-----------------------------+-----------------------------+
        |.. image:: force_CA.*        |.. image:: force_CAzoom1.*   |
        |     :width: 3.2in           |     :width: 3.2in           |
        |                             |                             |
        |TOTAL FORCE/*CA*             |TOTAL FORCE/*CA*             |
        +-----------------------------+-----------------------------+
        |.. image:: force_CAzoom2.*   |.. image:: L2.*              |
        |     :width: 3.2in           |     :width: 3.2in           |
        |                             |                             |
        |TOTAL FORCE/*CA*             |*L2* Residual                |
        +-----------------------------+-----------------------------+




Flow Visualization
^^^^^^^^^^^^^^^^^^

In the *Report* section of ``flowthrough.json``, the subfigures for the 
flow visualization use Tecplot® subfigures. Here we re-use the contour and 
color map settings from the ``01-bullet`` pyover example. The *MachSlice*
subfigure uses tecplot and the supplied layout file in 
``inputs/flowthrough-mach.lay`` to create Mach contours in the *Y=0* plane
of the nacelle. Note that the *MaxLevel* for the contours is dependant
upon the freestream Mach number. The color map break points are also a function
of the freestream Mach. 

At the end of this section, the *MachSlice-mesh* subfigure is defined. This
subfigure inherits all of the settings from the *MachSlice* subfigure, but
uses a different layout file. The only difference between the two layout
files is that the addition of the mesh overlay on the Mach contours.


    .. code-block:: javascript

        // Definitions for subfigures
        "Subfigures": {
            // Tecplot figures
            "MachSlice": {
                "Type": "Tecplot",
                "Layout": "inputs/flowthrough-mach.lay",
                "FigWidth": 1024,
                "Width": 0.65,
                "Caption": "Mach slice $y=0$",
                "ContourLevels": [
                    {
                        "NContour": 1,
                        "MinLevel": 0,
                        "MaxLevel": "max(1.4, 1.4*$mach)",
                        "Delta": 0.05
                    }
                ],
                "ColorMaps": [
                    {
                        "Name": "Diverging - Purple/Green modified",
                        "NContour": 2,
                        "ColorMap": {
                            "0.0": "purple",
                            "$mach": "white",
                            "1.0": ["green", "orange"],
                            "max(1.4,1.4*$mach)": "red"
                        }
                    }
                ],
                "Keys": {
                    "GLOBALCONTOUR": {
                        "LABELS": {
                            "Value": {
                                "AUTOLEVELSKIP": 2,
                                "NUMFORMAT": {
                                    "FORMATTING": "'FIXEDFLOAT'",
                                    "PRECISION": 1,
                                    "TIMEDATEFORMAT": "''"
                                }
                            },
                            "Parameter": 1
                        }
                    }
                }
            },
            "MachSlice-mesh": {
                "Type": "MachSlice",
                "Layout": "inputs/flowthrough-mach-mesh.lay"
            },
          ...
          ...
        }

The resulting *MachSlice* subfigures for each of the four cases are shown here:

    .. _tab-pyover-nacelle-02:
    .. table:: Tecplot® Mach contour plots for each case

        +------------------------------+------------------------------+
        |.. image:: MachSlice_m075.png |.. image:: MachSlice_m080.png |
        |    :width: 3.2in             |    :width: 3.2in             |
        |                              |                              |
        |Mach slice m0.75              |Mach slice m0.80              |
        +------------------------------+------------------------------+
        |.. image:: MachSlice_m080.png |.. image:: MachSlice_m090.png |
        |    :width: 3.2in             |    :width: 3.2in             |
        |                              |                              |
        |Mach slice m0.80              |Mach slice m0.90              |
        +------------------------------+------------------------------+



Powered Nacelle Cases
---------------------

The powered nacelle test cases that come with Overflow also include three cases
simulating the effect of an engine inside of the nacelle. This adds two
boundaries inside of the nacelle. The first simulates the effect of the forward
fan face in the inlet side of the nacelle. At this boundary the air is flowing
out of the CFD domain. The second boundary simulates the flow exiting the
engine. At this boundary the air is flowing into the CFD domain.  

pyover Setup
^^^^^^^^^^^^

To create this test case in pyover, we have created these new files:

    - ``powered.json``
    - ``inputs/matrix/powered.csv``
    - ``inputs/powered-mach.lay``
    - ``inputs/powered-mach-mesh.lay``

These were created by merely copying the flowthrough versions of the files and
making slight modifications. You can compare the powered with the flowthrough
versions of each file to see the modifications that were made. However, there
is one more step, and it requires something new.

Note that three different overflow input files are provided in the OVERFLOW
source code for this case. These three input files have been installed in the
pyover example as:

    - ``common_powered/overflow_test01.inp``
    - ``common_powered/overflow_test02.inp``
    - ``common_powered/overflow_test03.inp``

The basic pyover setup only allows one to specify one OVERFLOW input file for
the template input file, but we have three different input files that we want
to use.  This example will show how to incorporate a python module that will
customize the behavior of pyover in order to specify different OVERFLOW input
files. To enable this we will make use of the ``Label`` column in the input
run matrix file.  The ``Label`` values will be used in the naming of the
run directories.  Here are the first four lines in the input file:
``inputs/matrix/powered.csv``.

    .. code-block:: console

        # mach, config,  Label
          0.80, powered, test01
          0.80, powered, test02
          0.80, powered, test03

Here is the corresponding *RunMatrix* entry in the ``powered.json`` file:

    .. code-block:: javascript

        // RunMatrix description
        "RunMatrix": {
            // If a file is specified, and it exists, trajectory values will be
            // read from it.  RunMatrix values can also be specified locally.
            "File": "inputs/matrix/powered.csv",
            "Keys": ["mach", "config", "Label"],
            // Copy the mesh
            "GroupMesh": true,
            // Configuration name [default]
            "GroupPrefix": "powered"
        }

In order to customize the pyover behavior, we have added some python code
in a file called ``tools/nacelle.py``, and have added these lines to the
``powered.json`` file:

    .. code-block:: javascript

        // Module settings
        "PythonPath": ["tools"],
        "Modules": ["nacelle"],
        "InitFunction": ["nacelle.InitNAC1"],
        "CaseFunction": ["nacelle.ApplyLabel"],

This notifies pyover to look in the ``tools`` directory for a python module
called ``nacelle.py``. It also identifies two functions in the ``nacelle.py``
module that will be executed by pyover. The first function ``InitNac1()`` will
be called when pyover first starts running.  The second function ``ApplyLabel``
will be called during the process of creating each of the runs.  These two
functions have been written in the ``tools/nacelle.py`` file.  The
``InitNac1()`` does not actually do anything in this example, but this function
can be used customize certain behaviors at the beginning of a pyover run. The
``ApplyLabel()`` function is shown here:

    .. code-block:: python

        # Apply options based on the *Label* RunMatrix key
        def ApplyLabel(cntl, i):
            """Modify settings for each case using value of *Label*
        
            This method is programmed to specify a different OVERFLOW input
            file based on the value of *Label* for a given case. This is used
            to run each of the three input files that come with the
            powered_nacelle test problem that comes with the OVERFLOW source
            code.
        
            :Call:
                >>> ApplyLabel(cntl, i)
            :Inputs:
                *cntl*: :class:`pyOver.overflow.Overflow`
                    OVERFLOW settings interface
                *i*: :class:`int`
                    Case number
            :Versions:
                * 2020-01-28 ``@serogers``: First version
            """
        
            # Get the specified label
            lbl = cntl.x['Label'][i]
            # Set the overflow input file as a function of the Label
            if 'test01' in lbl:
                cntl.opts['OverNamelist'] = 'common_powered/overflow_test01.inp'
            elif 'test02' in lbl:
                cntl.opts['OverNamelist'] = 'common_powered/overflow_test02.inp'
            elif 'test03' in lbl:
                cntl.opts['OverNamelist'] = 'common_powered/overflow_test03.inp'


Executing pyover
^^^^^^^^^^^^^^^^

This completes the setup, the next step is to run pyover and run all three test
cases:

    .. code-block:: console

        > pyover -f powered.json
        Importing module 'nacelle'
          InitFunction: nacelle.InitNAC1()
        Case Config/Run Directory  Status  Iterations  Que CPU Time 
        ---- --------------------- ------- ----------- --- --------
        0    powered/m0.8_test01   ---     /           .            
          Case Function: cntl.nacelle.ApplyLabel(0)
          Case name: 'powered/m0.8_test01' (index 0)
             Starting case 'powered/m0.8_test01'
         > overrunmpi -np 8 run 01
             (PWD = '/u/wk/serogers/usr/cape/examples/pyover/02_powered_nacelle/powered/m0.8_test01')
             (STDOUT = 'overrun.out')
           Wall time used: 0.00 hrs (phase 0)
           Wall time used: 0.00 hrs
           Previous phase: 0.00 hrs
         > overrunmpi -np 8 run 02
             (PWD = '/u/wk/serogers/usr/cape/examples/pyover/02_powered_nacelle/powered/m0.8_test01')
             (STDOUT = 'overrun.out')
           Wall time used: 0.00 hrs (phase 1)
        1    powered/m0.8_test02   ---     /           .            
          Case Function: cntl.nacelle.ApplyLabel(1)
          Case name: 'powered/m0.8_test02' (index 1)
             Starting case 'powered/m0.8_test02'
         > overrunmpi -np 8 run 01
             (PWD = '/u/wk/serogers/usr/cape/examples/pyover/02_powered_nacelle/powered/m0.8_test02')
             (STDOUT = 'overrun.out')
           Wall time used: 0.00 hrs (phase 0)
           Wall time used: 0.00 hrs
           Previous phase: 0.00 hrs
         > overrunmpi -np 8 run 02
             (PWD = '/u/wk/serogers/usr/cape/examples/pyover/02_powered_nacelle/powered/m0.8_test02')
             (STDOUT = 'overrun.out')
           Wall time used: 0.00 hrs (phase 1)
        2    powered/m0.8_test03   ---     /           .            
          Case Function: cntl.nacelle.ApplyLabel(2)
          Case name: 'powered/m0.8_test03' (index 2)
             Starting case 'powered/m0.8_test03'
         > overrunmpi -np 8 run 01
             (PWD = '/u/wk/serogers/usr/cape/examples/pyover/02_powered_nacelle/powered/m0.8_test03')
             (STDOUT = 'overrun.out')
           Wall time used: 0.00 hrs (phase 0)
           Wall time used: 0.01 hrs
           Previous phase: 0.00 hrs
         > overrunmpi -np 8 run 02
             (PWD = '/u/wk/serogers/usr/cape/examples/pyover/02_powered_nacelle/powered/m0.8_test03')
             (STDOUT = 'overrun.out')
           Wall time used: 0.00 hrs (phase 1)
        
        Submitted or ran 3 job(s).
        
        ---=3, 

Note that the output informs you that it is excuting the *Case Function*
``cntl.nacelle.ApplyLabel()`` before each case is run, passing the case number
as the argument.


Report Generation
^^^^^^^^^^^^^^^^^

Generate the report for these three cases using ``pyover -f powered.json
--report``. The powered runs plot different convergence history plots than the
flowthrough example.  The plots now include the axial force coefficient for
both the *INLET* and the *EXIT* components. At this time, pyover does not have
the capability to plot convergence history for the mass-flow rate.

Convergence plots for the *INLET* and *EXIT* axial force coefficients for
each of the three case are shown here. 


    .. _tab-pyover-nacelle-03:
    .. table:: Convergence plots for *INLET* and *EXIT* axial force

        +-----------------------------+-----------------------------+
        |.. image:: test01_inlet_CA.* |.. image:: test01_exit_CA.*  |
        |     :width: 3.2in           |     :width: 3.2in           |
        |                             |                             |
        |INLET/*CA* *test01*          |EXIT/*CA* *test01*           |
        +-----------------------------+-----------------------------+
        |.. image:: test02_inlet_CA.* |.. image:: test02_exit_CA.*  |
        |     :width: 3.2in           |     :width: 3.2in           |
        |                             |                             |
        |INLET/*CA* *test02*          |EXIT/*CA* *test02*           |
        +-----------------------------+-----------------------------+
        |.. image:: test03_inlet_CA.* |.. image:: test03_exit_CA.*  |
        |     :width: 3.2in           |     :width: 3.2in           |
        |                             |                             |
        |INLET/*CA* *test03*          |EXIT/*CA* *test03*           |
        +-----------------------------+-----------------------------+


The report also includes *MachSlice* subfigures. Each case shows the Mach
contours with and without the grid included. All three test cases show very
similar Mach contours, the subfigures for *test01* are shown here:


    .. _tab-pyover-nacelle-04:
    .. table:: Tecplot® Mach contour plots for test01

        +------------------------------+
        |.. image:: test01_Mach.png    |
        |    :width: 6.0in             |
        |                              |
        |Mach slice test01             |
        +------------------------------+
        |.. image:: test01_Machg.png   |
        |    :width: 6.0in             |
        |                              |
        |Mach slice with grid          |
        +------------------------------+


Powered Boundary Conditions
---------------------------

This example comes with one more configuration using the powered-nacelle
setup that comes with OVERFLOW. This configuration illustrates the ability
to manipulate the nacelle boundary conditions in the run matrix file. This
can be very useful for developing simulations where the thrust or engine
conditions are changed as part of the run matrix. This configuration setup
uses the following files:

    - inputs/matrix/bcpower.json
    - bcpower.json
    - tools/bcpower.py

The ``inputs/matrix/bcpower.json`` file contains the new run matrix. This file
contains the following:

    .. code-block:: console

        # mach, InletBC, ExitBC, config,   Label
          0.80, 1.258,    1.200,  bcpower, test01
          0.80, 1.358,    2.000,  bcpower, test01
          0.80, 1.458,    4.000,  bcpower, test01

This has added two new columns called *InletBC* and *ExitBC*. These are defined
in the *RunMatrix* section in the ``bcpower.json`` file:

    .. code-block:: javascript

        // RunMatrix description
        "RunMatrix": {
            "File": "inputs/matrix/bcpower.csv",
            "Keys": ["mach", "InletBC", "ExitBC", "config", "Label"],
            // Copy the mesh
            "GroupMesh": true,
            // Configuration name [default]
            "GroupPrefix": "powered",
            "Definitions": {
                // InletBC
                "InletBC": {
                    "Type": "CaseFunction",
                    "Function": "self.bcnacelle.ApplyInletBC",
                    "Value": "float",
                    "Label": true,
                    "Format": "%05.3f_",
                    "Abbreviation": "I",
                    "Grids": "Inlet"
                },
                // ExitBC
                "ExitBC": {
                    "Type": "CaseFunction",
                    "Function": "self.bcnacelle.ApplyExitBC",
                    "Value": "float",
                    "Label": true,
                    "Format": "%05.3f",
                    "Abbreviation": "E",
                    "Grids": "Exit"
                }
            }
        }

The new columns are assigned the with ``"Type": "CaseFunction"``, and has
an attribute assigned for ``"Function"``. This will cause 
*pyover* to execute that function when it is time to build the OVERFLOW 
input file for each case. It will pass the value from the column in the 
RunMatrix to that function for each individual case. Thus when it starts the
first case, it will pass a value of *1.258* to the ``bcnacelle.ApplyInletBC``
function. This is a user-defined function that is located in the
``tools/bcnacelle.py`` python module. Let us examine the contents of this
function:

    .. code-block:: python

        def ApplyInletBC(cntl, v, i):
            """Modify BCINP for nacelle inlet face
        
            This method is modifies the BCINP namelist in the OVERFLOW input file 
            for the boundary conditions on the Inlet grid
        
            The IBTYP=33 boundary condition applies a contant pressure outflow
            at the engine inlet face. This uses the value of BCPAR1 to set the
            ratio of the boundary static pressure to freestream pressure.
        
            The IBTYP=34 boundary condition applies a constant mass-flow rate
            at the engine inlet face. This uses the value of BCPAR1 to set the
            target mass-flow rate.  BCPAR2 sets the update rate and relaxation factor.
            BCFILE is used to supply the FOMOCO component and Aref.
        
            :Call:
                >>> ApplyInletBC(cntl, v, i)
            :Inputs:
                *cntl*: :class:`pyOver.overflow.Overflow`
                    OVERFLOW settings interface
                *v*: :class:`float`
                    Run-matrix value in the InletBC column for case i
                *i*: :class:`int`
                    Case number
            :Versions:
                * 2020-01-30 ``@serogers``: First version
            """
        
            ## Inlet grid: set boundary conditions
            grid = 'Inlet'
            bci = 3
            print("\n\nIn function ApplyInletBC, v = ", v)
            # Extract the BCINP from the template for this grid
            IBTYP = cntl.Namelist.GetKeyFromGrid(grid, 'BCINP', 'IBTYP')
        
            #################################################
            # Process the pressure BC
            if IBTYP.count(33) > 0:
                # Get the column for ibtyp=33
                bci = IBTYP.index(33)
                # Change bci to 1-based index
                bci += 1
                # Set the BCPAR1 value for this case
                cntl.Namelist.SetKeyForGrid(grid, 'BCINP', 'BCPAR1', v, i=bci)
                BCPAR1 = cntl.Namelist.GetKeyFromGrid(grid, 'BCINP', 'BCPAR1', i=bci)


This function is programmed to change the value of *BCPAR1* associated with
the boundary condition entry that uses IBTYP=33 for the grid named
*Inlet* in the OVERFLOW input file.  For IBTYP=33, the *BCPAR1* value is used
to set the static pressure ratio at an outflow boundary. In other words, it
sets the static pressure at the boundary of the engine fan face in our 
nacelle example.  The run matrix is set up to run three different values of
static-pressure ratio for the three different cases.

Note that the ``ApplyInletBC`` function only changes the boundary condition 
if it finds an entry with IBTYP=33 in the OVERFLOW template input file.
It is left as an exercise to the reader to add python code that will change
the boundary condition if IBTYP=34, which controls the mass-flow rate instead
of the pressure.

Similarly, the run-matrix column for *ExitBC* is tied to a function called
``ApplyExitBC``, contained in the ``tools/bcnacelle.py`` file. This function
sets the value of *BCPAR1* for the IBTYP=141 boundary condition.  This sets
the total pressure value used at the boundary condition for the nacelle
exit. By varying the values in the *ExitBC* column of the run matrix, this
changes the total pressure in the flow coming out of the engine, changing
the resulting engine thrust.


The commands to run the three cases and generating the report for this
configuration are:

    .. code-block:: console

        pyover -f bcpower.json -I 0,1,2
        pyover -f bcpower.json --report

The report is setup to create the same force and moment convergence plots as
the ``powered.json`` configuration. The flow-field contour plots include the
same Mach contour figures, and additionally a figure of pressure coefficient
(Cp) contours.  The effect of the changes of the Inlet and Exit boundary conditions
are illustrated in these contour plots. The following table combines the
Cp and Mach contour images for the three cases for each comparison. 

The change to flow into the inlet is seen for the InletBC values of
1.258, 1.358, and 1.458. The increasing static pressure on the boundary
can be seen in the Cp contours, and its effect of reducing the Mach
number of the flow into the inlet boundary.

The total pressure values of 1.2, 2.0, and 4.0 prescribed in the run matrix
in the ExitBC column are also evident. The increasing total pressure creates
higher exit pressures and higher Mach numbers as the flow exits the nacelle.

    .. _tab-pyover-nacelle-05:
    .. table:: Tecplot® Cp and Mach contour plots for each case

        +---------------------------------+----------------------------------+
        |.. image:: CpSlice_bcpower1.png  |.. image:: MachSlice_bcpower1.png |
        |     :width: 3.5in               |     :width: 3.5in                |
        |                                 |                                  |
        |Cp slice bc_power_1.258_E1.200   |Mach slice  bc_power_1.258_E1.200 |
        +---------------------------------+----------------------------------+
        |.. image:: CpSlice_bcpower2.png  |.. image:: MachSlice_bcpower2.png |
        |     :width: 3.5in               |     :width: 3.5in                |
        |                                 |                                  |
        |Cp slice bc_power_1.358_E2.000   |Mach slice  bc_power_1.358_E2.000 |
        +---------------------------------+----------------------------------+
        |.. image:: CpSlice_bcpower3.png  |.. image:: MachSlice_bcpower3.png |
        |     :width: 3.5in               |     :width: 3.5in                |
        |                                 |                                  |
        |Cp slice bc_power_1.458_E4.000   |Mach slice  bc_power_1.458_E4.000 |
        +---------------------------------+----------------------------------+