4.1.6. Demo 6: Line Loads on the Arrow Example

Note

This example requires Chimera Grid Tools to calculate sectional loads. Specifically, the triload command is used. To acquire Chimera Grid Tools, free software from NASA, use the NASA Software Catalog.

Using the geometry from Example 2, this case continues the analysis and adds computation of sectional loads. To get started, clone this repository and run the following easy commands:

$ git clone https://github.com/nasa-ddalle/pycart05-adapt_bJet.git
$ cd pycart06-lineload_arrow
$ ./copy-files.py
$ cd work/

This will copy all of the files into a newly created work/ folder. Follow the instructions below by entering that work/ folder; the purpose is that you can easily delete the work/ folder and restart the tutorial at any time.

The geometry used for this shape is a capped cylinder with four fins and 9216 faces and seven components. The surface triangulation, arrow.tri, is shown below.

../../../_images/arrow01.png

Figure 4.6 Simple bullet shape triangulation with four fins

This example is set up with a small run matrix to demonstrate line loads on a few related cases.

$ pycart -c
Case Config/Run Directory   Status  Iterations  Que CPU Time
---- ---------------------- ------- ----------- --- --------
0    poweroff/m1.25a0.0b0.0 ---     /           .
1    poweroff/m1.25a2.0b0.0 ---     /           .
2    poweroff/m1.25a0.0b2.0 ---     /           .

4.1.6.1. Running Cases

When doing post-processing of Cart3D results, it is often desirable to perform time-averaging or iteration-averaging before doing analysis. When Cart3D exits (either flowCart or mpix_flowCart called with the -clic option), it writes a Components.i.triq file. This is a surface triangulation with some results from the last iteration. It contains the pressure coefficient and the five native Cart3D state variables at each node of the triangulation.

To get a triq file with averaged results, we have to run flowCart a few iterations at a time and manually perform averaging. The -stats option performs a similar task, but it is not quite consistent with what’s needed for an averaged line load. To get pyCart to perform this unusual task, we have the following "RunControl" section in pyCart.json.

// Iteration control and command-line inputs
"RunControl": {
    // Run sequence
    "PhaseSequece": [0],
    "PhaseIters": [200],
    // System configuration
    "nProc": 4,
    "MPI": 0,
    "Adaptive": 0,
    // Options for ``flowCart``
    "flowCart": {
        "it_fc": 200,
        "it_avg": 10,
        "it_start": 100,
        "cfl": 1.1,
        "mg_fc": 3,
        "y_is_spanwise": true
    },
    // Defines the flow domain automatically
    "autoInputs": {"r": 6},
    // Volume mesh options
    "cubes": {
        "maxR": 8,
        "pre": "preSpec.c3d.cntl",
        "cubes_a": 8,
        "cubes_b": 2,
        "reorder": true
    }
}

As previously, the RunControl>flowCart>it_fc option controls how many iterations flowCart runs for. The it_avg and it_start are new options. The idea is that Cart3D will be run for it_avg iterations at a time. pyCart then calculates a cumulative average triq file that updates after each it_avg iterations. However, it first runs it_start iterations before initiating this start-stop behavior. This prevents initial iterations from corrupting the average.

If we run one case, there is a lot of output printed to STDOUT, and it looks something like this. The output has been truncated.

Note: This is set up to run on four threads and take less than one minute.

$ pycart -I 0
Case Config/Run Directory   Status  Iterations  Que CPU Time
---- ---------------------- ------- ----------- --- --------
0    poweroff/m1.25a0.0b0.0 ---     /           .
  Group name: 'poweroff' (index 0)
  Preparing surface triangulation...
  Reading tri file(s) from root directory.
 > autoInputs -r 6 -t Components.i.tri -maxR 8 -nDiv 4
 > cubes -pre preSpec.c3d.cntl -maxR 8 -reorder -a 8 -b 2
 > mgPrep -n 3
     Starting case 'poweroff/m1.25a0.0b0.0'
 > flowCart -his -clic -N 100 ...
 > flowCart -his -clic -restart -N 110 ...
 > flowCart -his -clic -restart -N 120 ...
 > flowCart -his -clic -restart -N 130 ...
 > flowCart -his -clic -restart -N 140 ...
 > flowCart -his -clic -restart -N 150 ...
 > flowCart -his -clic -restart -N 160 ...
 > flowCart -his -clic -restart -N 170 ...
 > flowCart -his -clic -restart -N 180 ...
 > flowCart -his -clic -restart -N 190 ...
 > flowCart -his -clic -restart -N 200 ...
     Writing triangulation: 'Components.11.100.200.triq'

Submitted or ran 1 job(s).

---=1,

This lengthy output explains more clearly what is meant by running flowCart 10 iterations at a time. The iteration-averaged surface file that gets created at the end, Components.11.100.200.triq, explains the contents of the file. Specifically, it says that the file contains input from 11 iterations between 100 and 200.

Let’s run the last two cases in the run matrix, too.

$ pycart -n 2
Case Config/Run Directory   Status  Iterations  Que CPU Time
---- ---------------------- ------- ----------- --- --------
0    poweroff/m1.25a0.0b0.0 DONE    200/200     .        0.0
1    poweroff/m1.25a2.0b0.0 ---     /           .
     Starting case 'poweroff/m1.25a2.0b0.0'
 > flowCart -his -clic -N 100 ...
 > flowCart -his -clic -restart -N 110 ...
 ...
 > flowCart -his -clic -restart -N 200 ...
     Writing triangulation: 'Components.11.100.200.triq'
2    poweroff/m1.25a0.0b2.0 ---     /           .
     Starting case 'poweroff/m1.25a0.0b2.0'
 > flowCart -his -clic -N 100 ...
 > flowCart -his -clic -restart -N 110 ...
 ...
 > flowCart -his -clic -restart -N 200 ...
     Writing triangulation: 'Components.11.100.200.triq'

Submitted or ran 2 job(s).

---=2, DONE=1,

4.1.6.2. Calculating Line Loads

The purpose of this example was to create line loads, so let’s investigate that part. To instruct pyCart which components on which to compute line loads, we go to the "DataBook" section of pyCart.json.

// Database info
"DataBook": {
    // List of data book components
    "Components": ["arrow_no_base", "ll_arrow"],
    // Location of data book
    "Folder": "data/",
    // Parameters for collecting data
    "nFirst": 0,
    "nStats": 100,
    "nMin": 100,
    // Basic component
    "bullet_no_base": {
        "Type": "FM"
    },
    // Line load
    "ll_arrow": {
        "Type": "LineLoad",
        "CompID": "arrow_no_base",
        "nCut": 100
    }
}

This specifies that the databook contains two “Components”. One of them is the the statistically averaged forces and moments on the arrow_no_base CompID, and the other is the sectional load on the same. Recall from Example 2 that the arrow_no_base component includes all the surfaces except the base.

The "ll_arrow" databook component is defined as a "LineLoad" component on the arrow_no_base CompID, and it is instructed to calculate the sectional loads on 100 slices of that component. By default, these slices will be at constant-x planes.

This "CompID" option allows users to calculate line loads on parts of the vehicle (for example a wing) and also have multiple line load databooks for the same vehicle.

Adding this little section to the "DataBook" is all that’s needed to set up a line load computation. To actually calculate the line loads, run the following commands.

Note: This command should take less than five seconds to run.

$ pycart --ll
Updating line load data book 'll_arrow' ...
poweroff/m1.25a0.0b0.0
  Adding new databook entry at iteration 200.
    triloadCmd < triload.ll_arrow.i > triload.ll_arrow.o
poweroff/m1.25a2.0b0.0
  Adding new databook entry at iteration 200.
    triloadCmd < triload.ll_arrow.i > triload.ll_arrow.o
poweroff/m1.25a0.0b2.0
  Adding new databook entry at iteration 200.
    triloadCmd < triload.ll_arrow.i > triload.ll_arrow.o

This command creates a collection of files. First, we will note the creation of a lineload folder in each case directory. In the poweroff/m1.25a0.0b0.0/lineload folder, there are several files used in the raw computation of line loads created by the Chimera Grid Tools utility triloadCmd.

The file triload.ll_arrow.i is the input to triloadCmd that is automatically created by pyCart. The main output file is LineLoad_ll_arrow.slds, which contains the non-dimensionalized forces on each of the 100 slices.

These raw files are then read by pyCart and processed into a databook in the data/ folder (locations specified by the DataBook>Folder option in pyCart.json). Below is a file tree of the 06_lineload_arrow/data folder.

data/
    ll_ll_arrow.csv
    lineload/
        LineLoad_ll_arrow.smy
        LineLoad_ll_arrow.smz
        poweroff/
            m1.25a0.0b0.0/
                LineLoad_ll_arrow.csv
            m1.25a2.0b0.0/
                LineLoad_ll_arrow.csv
            m1.25a0.0b2.0/
                LineLoad_ll_arrow.csv

The top-level ll_ll_arrow.csv file is a status file that stores which cases have computed line loads and what iteration at which they have been computed. It looks a lot like a force and moment databook file (e.g. aero_arrow_no_base.csv) except that there are no data columns (since those are stored in the line load folders.

In the data/lineload/ directory, there are two files with unusual file extensions. These are just text files that give the outline of the body intersected by the \(y{=}0\) plane (.smy) and \(z{=}0\) plane (.smz). They are used to make the line load plots more convenient, and which will make more sense in the next subsection.

Within the data/lineload/ folder, there is a whole file tree that mirrors that of the run cases. The actual sectional loads from poweroff/m1.25a.0.b0.0 are stored in data/lineload/poweroff/m1.25a0.0b0.0, etc. In this case, each line load case folder contains only one file, but if there were more line load components, there would be one for each line load. Each is a very simple file containing seven columns: x/Lref, and then one for each of the six coefficients (CA, CY, CN, CLL, CLM, CLN). The coefficient data is stored in a seemingly strange format of \(\mathrm{d}C_A/\mathrm{d}(x/L_\mathit{ref})\). Using this form keeps results nondimensional but also removes dependence on the number of cuts.

4.1.6.3. Creating Plots and Automated Reports

Line load plots are fairly easy to set up. First let’s just create the report and then describe the "Report" section of pyCart.json.

$ pycart --report
poweroff/m1.25a0.0b0.0
  CaseConds: New subfig at iteration 200.0
  FMTable: New subfig at iteration 200.0
  x = um.multiply(x, x, out=x)
  arrow_CA: New subfig at iteration 200.0
  arrow_CY: New subfig at iteration 200.0
  arrow_CN: New subfig at iteration 200.0
  arrow_CLL: New subfig at iteration 200.0
  arrow_CLN: New subfig at iteration 200.0
  arrow_CLM: New subfig at iteration 200.0
  L1: New subfig at iteration 200.0
  LL_CY: New subfig at iteration 200.0
  LL_CN: New subfig at iteration 200.0
poweroff/m1.25a2.0b0.0
  CaseConds: New subfig at iteration 200.0
  FMTable: New subfig at iteration 200.0
  arrow_CA: New subfig at iteration 200.0
  arrow_CY: New subfig at iteration 200.0
  arrow_CN: New subfig at iteration 200.0
  arrow_CLL: New subfig at iteration 200.0
  arrow_CLN: New subfig at iteration 200.0
  arrow_CLM: New subfig at iteration 200.0
  L1: New subfig at iteration 200.0
  LL_CY: New subfig at iteration 200.0
  LL_CN: New subfig at iteration 200.0
poweroff/m1.25a0.0b2.0
  CaseConds: New subfig at iteration 200.0
  FMTable: New subfig at iteration 200.0
  arrow_CA: New subfig at iteration 200.0
  arrow_CY: New subfig at iteration 200.0
  arrow_CN: New subfig at iteration 200.0
  arrow_CLL: New subfig at iteration 200.0
  arrow_CLN: New subfig at iteration 200.0
  arrow_CLM: New subfig at iteration 200.0
  L1: New subfig at iteration 200.0
  LL_CY: New subfig at iteration 200.0
  LL_CN: New subfig at iteration 200.0
Compiling...
Compiling...
Cleaning up...

This creates a multipage PDF (in this case one title page and three more pages with one page dedicated to each case) that contains selected analysis tables and plots. In this case we have set up the report to show one table identifying the case in more detail, one table of basic force coefficient results, and nine plots.

../../../_images/report-case-p3.png

Figure 4.7 Automatically generated report for poweroff/m1.25a2.0b0.0

The first six plots are of each force or moment coefficient on the arrow_no_base component. There is an obvious problem with the CLL and CLN plots, which has to do with some confusion due to the symmetry of the arrow shape. (This bug may go away in future versions of Cart3D). We will discuss how to make these two figures look a little better shortly, but let’s move on to the other three plots. The first is a plot of the global \(L_1\) norm of density residuals (which is the main residual reported by Cart3D).

The last two plots are line load plots. Let’s discuss the JSON syntax to set up each of these plots and also how these subfigures are assembled into a report. The basic skeleton of the "Report" section of pyCart.json is shown below.

"Report": {
    // List of reports
    "Reports": ["case"],
    // Define the report
    "case": {
        "Title": "Automated Cart3D Report with Line Load Plots",
        "Subtitle": "Example \\texttt{06\\_lineload\\_arrow}",
        "Restriction": "pyCart Example - Distribution Unlimited",
        "Figures": ["CaseTables", "CasePlots"]
    },
    // Define the figures
    "Figures": {
        "CaseTables": {
            "Alignment": "left",
            "Subfigures": ["CaseConds", "FMTable"]
        },
        "CasePlots": {
            "Header": "Iterative analysis and sectional loads",
            "Alignment": "center",
            "Subfigures": [
                "arrow_CA",  "arrow_CY",  "arrow_CN",
                "arrow_CLL", "arrow_CLN", "arrow_CLM",
                "L1",        "LL_CY",     "LL_CN"
            ]
        }
    },
    // Definitions for subfigures
    "Subfigures" {
        ...
    }
}

The overall structure is relatively simple: there is a list of reports (the same JSON file can have many different reports defined), an overall definition for the report including a list of figures, a section defining each figure, and a section defining the subfigures. A figure is a collection of subfigures plus an alignment option and optional header.

Creating this report creates a file called report-case.pdf` in the ``report/ folder. The individual plots created for the report are stored in folders such as report/poweroff/m1.25a2.0/a0.0/, with each subfigure having a file name corresponding to the title of the subfigure (e.g. arrow_CA.pdf).

4.1.6.3.1. Line Load Subfigures

The focus of this section is on the subfigures, and in particular the plots. To learn more about the two tables, the actual example pyCart.json file is relatively easy to understand. Defining syntax for the line load plots is shown below.

"Subfigures": {
    ...
    "LL_arrow": {
        "Type": "PlotLineLoad",
        "Component": "ll_arrow",
        "FigWidth": 5.5,
        "FigHeight": 6,
        "Width": 0.33,
        "SeamCurves": "smy",
        "SeamLocation": "bottom"
    },
    "LL_CY": {
        "Type": "LL_arrow",
        "Caption": "arrow\\_no\\_base/CY",
        "Coefficient": "CY"
    },
    "LL_CN": {
        "Type": "LL_arrow",
        "Caption": "arrow\\_no\\_base/CN",
        "Coefficient": "CN"
    }
}

We have two line load plots that share many common options defined in "LL_arrow". This demonstrates the concept of cascading options and can save time, effort, and number of lines in the JSON file. The LL_arrow>Type option is set to "PlotLineLoad", which is the basic pyCart line load subfigure type. The Component is set to the name of the line load component as listed in the "DataBook" section, and the Width setting determines what percentage of the available text width in the final PDF document is taken up by the figure.

The FigWidth and FigHeight obviously set an aspect ratio for the figure, but the absolute scale of FigWidth also determines the size at which the figure is rendered. A larger FigWidth will make the labels appear to be in a smaller font size since the size in the document is set by Width.

Finally, the SeamCurves option list which slice of the geometry (if any) to plot to help the reader anchor what part of the line load corresponds to what geometrical features. The SeamLocation plot sets where to put this slice; "bottom" is the usual choice.

Waring: The seam curve plots have automatically adjusted aspect ratio to avoid distorting the seam curve. As a result, geometry with inconvenient actual aspect ratios will lead to problematic seam curve plots.

../../../_images/LL_CN.png

Figure 4.8 Normal sectional loads at 2 degrees angle of attack

4.1.6.4. Residual History Subfigure

Cart3D residual plots almost always have the same JSON inputs. The version for this plot uses a different FigHeight in order to match the aspect ratio of the neighboring line load plots.

"Subfigures": {
    ...
    "L1": {
        "Type": "PlotL1",
        "FigWidth": 5.5,
        "FigHeight": 6,
        "Width": 0.33,
        "Caption": "$L_1$ Density Residual"
    },
    ...
}

4.1.6.5. Force & Moment Plots

The iterative history plots are relatively simple for this case since we are only plotting one component.

"Subfigures": {
    ...
    "arrow": {
        "Type": "PlotCoeff",
        "Component": "arrow_no_base",
        "FigWidth": 5.5,
        "FigHeight": 4.2,
        "Width": 0.33
    },
    "arrow_CA": {"Type": "arrow", "Coefficient": "CA"},
    "arrow_CY": {"Type": "arrow", "Coefficient": "CY"},
    "arrow_CN": {"Type": "arrow", "Coefficient": "CN"},
    "arrow_CLL": {"Type": "arrow", "Coefficient": "CLL"},
    "arrow_CLM": {"Type": "arrow", "Coefficient": "CLM"},
    "arrow_CLN": {"Type": "arrow", "Coefficient": "CLN"},
    ...
}

As we saw above, this simulation results in very poor results for CLL and CLN due to the symmetry of the configuration (among other things). We can at least make the figures look readable by using scientific notation for the mean value and removing the standard deviation.

"Subfigures": {
    ...
    "arrow_CLL": {
        "Type": "arrow",
        "Coefficient": "CLL",
        "MuFormat": "%.2e",
        "ShowSigma": false
    },
    "arrow_CLN": {
        "Type": "arrow",
        "Coefficient": "CLN",
        "MuFormat": "%.2e",
        "ShowSigma": false
    },
    ...
}

The updated CLN plot is shown below.

../../../_images/arrow_CLN.png

Figure 4.9 Problematic yawing moment coefficient with slightly improved formatting

There are also many different options for each of these plots, and it is also possible to plot line loads from other databases on top of those of the most recent case for comparison. See the JSON page for a thorough description of options.