Skip to content

Commit 0ccf684

Browse files
committed
Update documentation
1 parent 34dc1ca commit 0ccf684

37 files changed

+1566
-13242
lines changed

.buildinfo

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# Sphinx build info version 1
22
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
3-
config: aea0f0a733cb8e7ad2e3e83173dce995
3+
config: 8937e576f6feb1b1c733aaae2220b675
44
tags: 645f666f9bcd5a90fca523b33c5a78b7

_sources/airfoil/ffd.rst.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ First step involves creating options dictionary which is used for initializating
1313
and ``nffd`` are the two mandatory options, rest all are optional, please refer :ref:`options<options>`
1414
section for more details. Following snippet of the code shows an example::
1515

16+
from blackbox import AirfoilCST
17+
from baseclasses import AeroProblem
18+
import numpy as np
19+
1620
solverOptions = {
1721
# Common Parameters
1822
"monitorvariables": ["cl", "cd", "cmz", "yplus"],

_sources/index.rst.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ wing data generation. Blackbox can also run on High-Performance Computing resour
1919

2020
install
2121
airfoil/intro
22+
wing/intro
2223
hpc

_sources/install.rst.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
.. _install:
2+
13
Installation
24
============
35

@@ -17,7 +19,8 @@ Due to this dependency, Blackbox is limited to these systems only. The dependenc
1719
`baseclasses <https://github.com/mdolab/baseclasses>`_ 1.7.0 or higher
1820
`pyGeo <https://github.com/mdolab/pygeo>`_ 1.12.2 or higher
1921
`pyHyp <https://github.com/mdolab/pyhyp>`_ 2.6.0 or higher
20-
`cgnsutilities <https://github.com/mdolab/cgnsutilities>`_
22+
`idwarp <https://github.com/mdolab/idwarp>`_ 2.6.1 or higher
23+
`cgnsutilities <https://github.com/mdolab/cgnsutilities>`_ 2.7.1 or higher
2124
`ADflow <https://github.com/mdolab/adflow>`_ 2.7.4 or higher
2225
=========================================================== ================
2326

_sources/wing/adflow.rst.txt

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
*******************************
2+
Sample generation using ADflow
3+
*******************************
4+
5+
This section explains how to use ``WingFFD`` module for generating samples using ADflow. There are typically three
6+
main steps involved in the process: setting up options and initializing the module, adding design variables
7+
and generating samples. The ``WingFFD`` module is demonstrated using a CRM wing example. This script is
8+
available in ``examples`` directory of the repository on github.
9+
10+
Setting up options
11+
------------------
12+
13+
First step involves creating options dictionary which is used for initializating the module. There are five
14+
mandatory options: ``solverOptions``, ``ffdFile``, ``gridFile``, ``liftIndex`` and ``aeroProblem``, rest all are optional,
15+
please refer :ref:`options<options>` section for more details. Following snippet of the code shows an example::
16+
17+
from blackbox import WingFFD
18+
from baseclasses import AeroProblem
19+
import numpy as np
20+
21+
solverOptions = {
22+
# Common Parameters
23+
"monitorvariables": ["cl", "cd", "cmy", "yplus"],
24+
"writeTecplotSurfaceSolution": True,
25+
"writeSurfaceSolution": False,
26+
"writeVolumeSolution": False,
27+
# Physics Parameters
28+
"equationType": "RANS",
29+
"smoother": "DADI",
30+
"MGCycle": "sg",
31+
"nsubiterturb": 10,
32+
"nCycles": 7000,
33+
# ANK Solver Parameters
34+
"useANKSolver": True,
35+
"ANKSubspaceSize": 400,
36+
"ANKASMOverlap": 3,
37+
"ANKPCILUFill": 4,
38+
"ANKJacobianLag": 5,
39+
"ANKOuterPreconIts": 3,
40+
"ANKInnerPreconIts": 3,
41+
# NK Solver Parameters
42+
"useNKSolver": True,
43+
"NKSwitchTol": 1e-6,
44+
"NKSubspaceSize": 400,
45+
"NKASMOverlap": 3,
46+
"NKPCILUFill": 4,
47+
"NKJacobianLag": 5,
48+
"NKOuterPreconIts": 3,
49+
"NKInnerPreconIts": 3,
50+
# Termination Criteria
51+
"L2Convergence": 1e-14
52+
}
53+
54+
# Creating aeroproblem for adflow
55+
# Chord ref is 1.0 since all the dimensions are scaled according to it
56+
ap = AeroProblem(
57+
name="crm", alpha=2.0, mach=0.85, reynolds=5e6, reynoldsLength=1.0, T=298.15,
58+
areaRef=3.407014, chordRef=1.0, evalFuncs=["cl", "cd", "cmy"], xRef=1.2077, yRef=0.0, zRef=0.007669
59+
)
60+
61+
# Options for blackbox
62+
options = {
63+
"solver": "adflow",
64+
"solverOptions": solverOptions,
65+
"gridFile": "crm_volMesh.cgns",
66+
"ffdFile": "crm_ffd.xyz",
67+
"liftIndex": 3, # Very important
68+
"aeroProblem": ap,
69+
"noOfProcessors": 8,
70+
"sliceLocation": [0.883, 1.003, 2.093, 2.612, 3.112, 3.548],
71+
"writeDeformedFFD": True
72+
}
73+
74+
# Initialize the class
75+
wing = WingFFD(options=options)
76+
77+
Firstly, required packages and modules are imported. Then, ``solverOptions`` dictionary is created, refer
78+
`ADflow <https://mdolab-adflow.readthedocs-hosted.com/en/latest/options.html>`_. Then, `AeroProblem <https://mdolab-baseclasses.readthedocs-hosted.com/en/latest/pyAero_problem.html>`_
79+
object is created which contains details about the flow conditions and the desired output variables are
80+
defined using ``evalFuncs`` argument. Then, ``options`` dictionary is created, refer :ref:`options<options>`
81+
section for more details.
82+
83+
Adding design variables
84+
-----------------------
85+
86+
Next step is to add design variables based on which samples will be generated. The ``addDV`` method needs three arguments:
87+
88+
- ``name (str)``: name of the design variable to add. The available design variables are:
89+
90+
- ``shape``: FFD control points which parameterize the airfoil shape
91+
- ``twist``: Twist of the airfoil sections along the wing span, number of sections will be one less than the sections defined in the FFD file since root is fixed
92+
- ``alpha``: Angle of attack for the analysis
93+
- ``mach``: Mach number for the analysis
94+
- ``altitude``: Altitude for the analysis
95+
96+
- ``lowerBound (numpy array or float)``: lower bound for the variable
97+
- ``upperBound (numpy array or float)``: upper bound for the variable
98+
99+
.. note::
100+
When ``shape`` variable is to be added, the lower and upper bound should be a 1D numpy array of the same size
101+
as the number of FFD points. The number of FFD points can be accessed via ``nffd`` attribute of the class.
102+
103+
When ``twist`` variable is to be added, the lower and upper bound should be a 1D numpy array of the same size
104+
as the number of section defined in the FFD file minus one. The twist is defined in degrees. The number of twist
105+
sections can be accessed via ``nTwist`` attribute of the class.
106+
107+
For other cases, lower and upper bound should be float.
108+
109+
Following code snippet adds ``alpha``, ``shape``, and ``twist`` as design variables::
110+
111+
# Add alpha as a design variable
112+
wing.addDV("alpha", lowerBound=1.5, upperBound=3.5)
113+
114+
# Add the wing shape as a design variable
115+
lowerBound = np.array([-0.01]*wing.nffd)
116+
upperBound = np.array([0.01]*wing.nffd)
117+
wing.addDV("shape", lowerBound=lowerBound, upperBound=upperBound)
118+
119+
# Add the wing twist as a design variable
120+
lowerBound = np.array([-2.0]*wing.nTwist)
121+
upperBound = np.array([2.0]*wing.nTwist)
122+
wing.addDV("twist", lowerBound=lowerBound, upperBound=upperBound)
123+
124+
Here, the upper and lower bound for ``shape`` variable is set to 0.01 and -0.01, respectively.
125+
126+
Generating samples and accessing data
127+
---------------------------------------
128+
129+
After adding design variables, generating samples is very easy. You just need to use ``generateSamples``
130+
method from the initialized object. This method has two arguments:
131+
132+
- ``numSamples (int)``: number of samples to generate
133+
- ``doe (numpy array)``: 2D numpy array in which each row represents a specific sample
134+
135+
.. note::
136+
You can either provide ``numSamples`` or ``doe`` i.e. both of them are mutually exclusive.
137+
If both are provided, then an error will be raised.
138+
139+
Typically, ``numSamples (int)`` should be used for generating samples. This option will internally generate doe based on the
140+
options provided while initializating the module. In some cases, you might want to generate samples based on your own doe. In that
141+
case, you use ``doe (numpy array)`` argument. Following snippet of the code will generate 5 samples using internally generated doe::
142+
143+
wing.generateSamples(numSamples=5)
144+
145+
You can see the following output upon successful completion of sample generation process:
146+
147+
- A folder with the name specificed in the ``directory`` option (or the default name - *output*) is created. This folder contains all the generated
148+
files/folders.
149+
150+
- Within the main output folder, there will be subfolders equal to the number of samples you requested. Each of the folder corresponds to the specific
151+
analysis performed. It will contain log.txt which contains the output from mesh generation and solver. There will be other files depending on the
152+
options provided to solver and blackbox.
153+
154+
- ``data.mat`` file which contains:
155+
156+
- **Input variable**: a 2D numpy array ``x`` in which each row represents a specific sample based on which analysis is performed. The number
157+
of rows will be usually equal to the number of samples argument in the ``generateSamples`` method. But, many times few of the analysis
158+
fail. It depends a lot on the solver options, so set those options after some tuning.
159+
160+
.. note::
161+
The order of values in each row is based on how you add design variables. In this tutorial, first ``alpha`` is added as
162+
design variable and then shape coefficients are added. Thus, first value in each row will be alpha, next ``nffd``
163+
values will be FFD coefficients, and then ``nTwist`` values will be twist values.
164+
165+
- **Outputs**: There are two kinds of outputs - mandatory and user specificed. The ``evalFuncs`` argument in the aero problem
166+
decides the user desired outputs. Along with these outputs, `volume` of the wing is the mandatory output. Following snippet
167+
shows how to access the data.mat file. In this tutorial, ``evalFuncs`` argument contains ``cl``, ``cd``, ``cmy``. So, data.mat
168+
will contain these variables, along with ``volume``::
169+
170+
from scipy.io import loadmat
171+
data = loadmat("data.mat") # mention the location of mat file
172+
173+
x = data["x"]
174+
cl = data["cl"]
175+
cd = data["cd"]
176+
cmy = data["cmy"]
177+
volume = data["volume"]
178+
179+
- ``description.txt``: contains various informations about the sample generation such as design variables, bounds, number of failed analysis, etc.

_sources/wing/dafoam.rst.txt

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
*******************************
2+
Sample generation using DAFoam
3+
*******************************
4+
5+
This section explains how to use ``WingFFD`` module for generating samples using DAFoam. There are typically three
6+
main steps involved in the process: setting up options and initializing the module, adding design variables
7+
and generating samples. The ``WingFFD`` module is demonstrated using a CRM wing example. This script is
8+
available in ``examples`` directory of the repository on github.
9+
10+
Setting up options
11+
------------------
12+
13+
First step involves creating options dictionary which is used for initializating the module. There are five
14+
mandatory options: ``solverOptions``, ``ffdFile``, ``gridFile``, ``liftIndex`` and ``aeroProblem``, rest all are optional,
15+
please refer :ref:`options<options>` section for more details. Following snippet of the code shows an example::
16+
17+
from blackbox import WingFFD
18+
from baseclasses import AeroProblem
19+
import numpy as np
20+
21+
solverOptions = {
22+
"designSurfaces": ["wing"],
23+
"solverName": "DARhoSimpleCFoam",
24+
"primalMinResTol": 1e-6,
25+
"primalMinResTolDiff": 1e2,
26+
"checkMeshThreshold": {
27+
"maxAspectRatio": 1000.0,
28+
"maxNonOrth": 70.0,
29+
"maxSkewness": 4.0,
30+
"maxIncorrectlyOrientedFaces": 0,
31+
}
32+
33+
# Creating aeroproblem for adflow
34+
# Chord ref is 1.0 since all the dimensions are scaled according to it
35+
ap = AeroProblem(
36+
name="crm", alpha=2.0, mach=0.85, reynolds=5e6, reynoldsLength=1.0, T=298.15,
37+
areaRef=3.407014, chordRef=1.0, evalFuncs=["cl", "cd", "cmy"], xRef=1.2077, yRef=0.0, zRef=0.007669
38+
)
39+
40+
# Options for blackbox
41+
options = {
42+
"solver": "dafoam",
43+
"solverOptions": solverOptions,
44+
"openfoamDir": ".",
45+
"gridFile": "crm_volMesh.cgns",
46+
"ffdFile": "crm_ffd.xyz",
47+
"liftIndex": 3, # Very important
48+
"aeroProblem": ap,
49+
"noOfProcessors": 8,
50+
"writeDeformedFFD": True,
51+
"getSurfaceForces": True
52+
}
53+
54+
# Initialize the class
55+
wing = WingFFD(options=options)
56+
57+
Firstly, required packages and modules are imported. Then, ``solverOptions`` dictionary is created, refer DAFoam documentation
58+
for more details. Then, `AeroProblem <https://mdolab-baseclasses.readthedocs-hosted.com/en/latest/pyAero_problem.html>`_
59+
object is created which contains details about the flow conditions and the desired output variables are
60+
defined using ``evalFuncs`` argument. Then, ``options`` dictionary is created, refer :ref:`options<options>`
61+
section for more details.
62+
63+
.. note::
64+
In solver options dictionary for DAFoam, no need to mention arguments such as ``primalBC``, ``function``,
65+
``normalizeStates``, ``inputInfo``. These options are internally set before each analysis.
66+
67+
Adding design variables
68+
-----------------------
69+
70+
Next step is to add design variables based on which samples will be generated. The ``addDV`` method needs three arguments:
71+
72+
- ``name (str)``: name of the design variable to add. The available design variables are:
73+
74+
- ``shape``: FFD control points which parameterize the airfoil shape
75+
- ``twist``: Twist of the airfoil sections along the wing span, number of sections will be one less than the sections defined in the FFD file since root is fixed
76+
- ``alpha``: Angle of attack for the analysis
77+
- ``mach``: Mach number for the analysis
78+
- ``altitude``: Altitude for the analysis
79+
80+
- ``lowerBound (numpy array or float)``: lower bound for the variable
81+
- ``upperBound (numpy array or float)``: upper bound for the variable
82+
83+
.. note::
84+
When ``shape`` variable is to be added, the lower and upper bound should be a 1D numpy array of the same size
85+
as the number of FFD points. The number of FFD points can be accessed via ``nffd`` attribute of the class.
86+
87+
When ``twist`` variable is to be added, the lower and upper bound should be a 1D numpy array of the same size
88+
as the number of section defined in the FFD file minus one. The twist is defined in degrees. The number of twist
89+
sections can be accessed via ``nTwist`` attribute of the class.
90+
91+
For other cases, lower and upper bound should be float.
92+
93+
Following code snippet adds ``alpha`` and ``mach`` as design variables::
94+
95+
# Add alpha as a design variable
96+
wing.addDV("alpha", lowerBound=1.5, upperBound=3.5)
97+
98+
# Add mach as a design variable
99+
wing.addDV("mach", lowerBound=0.7, upperBound=0.8)
100+
101+
Generating samples and accessing data
102+
---------------------------------------
103+
104+
After adding design variables, generating samples is very easy. You just need to use ``generateSamples``
105+
method from the initialized object. This method has two arguments:
106+
107+
- ``numSamples (int)``: number of samples to generate
108+
- ``doe (numpy array)``: 2D numpy array in which each row represents a specific sample
109+
110+
.. note::
111+
You can either provide ``numSamples`` or ``doe`` i.e. both of them are mutually exclusive.
112+
If both are provided, then an error will be raised.
113+
114+
Typically, ``numSamples (int)`` should be used for generating samples. This option will internally generate doe based on the
115+
options provided while initializating the module. In some cases, you might want to generate samples based on your own doe. In that
116+
case, you use ``doe (numpy array)`` argument. Following snippet of the code will generate 5 samples using internally generated doe::
117+
118+
wing.generateSamples(numSamples=5)
119+
120+
You can see the following output upon successful completion of sample generation process:
121+
122+
- A folder with the name specificed in the ``directory`` option (or the default name - *output*) is created. This folder contains all the generated
123+
files/folders.
124+
125+
- Within the main output folder, there will be subfolders equal to the number of samples you requested. Each of the folder corresponds to the specific
126+
analysis performed. It will contain log.txt which contains the output from mesh generation and solver. There will be other files depending on the
127+
options provided to solver and blackbox.
128+
129+
- ``data.mat`` file which contains:
130+
131+
- **Input variable**: a 2D numpy array ``x`` in which each row represents a specific sample based on which analysis is performed. The number
132+
of rows will be usually equal to the number of samples argument in the ``generateSamples`` method. But, many times few of the analysis
133+
fail. It depends a lot on the solver options, so set those options after some tuning.
134+
135+
.. note::
136+
The order of values in each row is based on how you add design variables. In this tutorial, first ``alpha`` is added as
137+
design variable and then shape coefficients are added. Thus, first value in each row will be alpha, next ``nffd``
138+
values will be FFD coefficients, and then ``nTwist`` values will be twist values.
139+
140+
- **Outputs**: There are two kinds of outputs - mandatory and user specificed. The ``evalFuncs`` argument in the aero problem
141+
decides the user desired outputs. Along with these outputs, `volume` of the wing is the mandatory output. Following snippet
142+
shows how to access the data.mat file. In this tutorial, ``evalFuncs`` argument contains ``cl``, ``cd``, ``cmy``. So, data.mat
143+
will contain these variables, along with ``volume``::
144+
145+
from scipy.io import loadmat
146+
data = loadmat("data.mat") # mention the location of mat file
147+
148+
x = data["x"]
149+
cl = data["cl"]
150+
cd = data["cd"]
151+
cmy = data["cmy"]
152+
volume = data["volume"]
153+
154+
- ``description.txt``: contains various informations about the sample generation such as design variables, bounds, number of failed analysis, etc.
155+
156+
Extracting surface force data
157+
-------------------------------
158+
159+
To get forces at each surface mesh coordinate, set the option ``getSurfaceForces`` to True, refer :ref:`options<options>`
160+
section for more details. This creates a ``surfaceForces.mat`` file in each corresponding analysis folder. This mat file contains two
161+
variables: ``forces`` and ``surfaceCoords``. The ``forces`` is a 2d numpy of size Ncoords x 3, where Ncoords is the number of surface
162+
mesh points and 3 corresponds to x, y, and z component of the force vector. The ``surfaceCoords`` is also a 2d numpy array of size
163+
Ncoords x 3, containing surface mesh coordinates. These forces and surface coordinates can be extracted as shown in previous section
164+
using ``loadmat`` function from scipy.

0 commit comments

Comments
 (0)