- Speed and stability improvements
- Added setup parameter stepsize_limit
- Increased internal tolerance of boundary layer solve to 1e-6
- Fixed wrong assertions in airfoil check from 1.2.2

- Check airfoil geometry on init

- Added incompressible_bl parameter
- Added inviscid CL
- Added set_forced_transition function
- Added tolerance as parameter

- Adapted pressure calculation for pitching airfoils [6]
- Added equal_wakes parameter

Viiflow comes as a 64bit Cython wheel for Windows and Linux. Cython wheels are installation packages of compiled modules usable from Python. To use it, you therefore need Python (3.7+).

Now, if you are note comfortable already with Python you may want to start here. While no serious programming is necessary to use viiflow, it will be very beneficial if you know how statements and loops work to define your airfoil analysis.

If you have little experience with installing and running Python on Windows: I found it easiest to rely on scoop and use:

```
scoop install python
```

For the examples you will also need jupyter, so use `pip install jupyter`

after installing python. After that, use `jupyter notebook`

from the powershell, go to the examples folder and open the ipynb files.

If you have little experience with Python on Linux: By default, a lot of Linux distributions see Python 2.7 as the default version, though this is changing. Check whether you have Python3.7 installed by using `python3`

in a shell. You may need to use `python3 -m pip install jupyter`

, `python3 -m jupyter notebook`

for all commands.

To install the wheels, use

```
pip install viiflow-[...].whl
pip install viiflowtools-[...].whl
```

from a shell.

While viiflow is compiled cython code, it calls numpys linear algebra solve routine at every iteration. For this to be efficient, you may need an efficient numpy installation. Here you can find wheel distributions of numpy for windows built with Intel MKL.

The viiflow library has four methods:

- setup: This function builds a setup structure that is used in the latter methods
- init: This function uses the parameters to set up the data structures, calculate the panel operators, initialize the boundary layers and so on.
- iter: This function uses the output of init to iterate the parameters until convergence.
- set_forced_transition: Set current boundary layer to assume a forced transition

The setup routine can be called with a list of parameters and returns a parameter structure. The call

```
import viiflow as vf
s = vf.setup(Re=1e6,alpha=10)
s.Ma = 0.1
```

defines the setup structure `s`

with the parameters Reynolds number 1e6 and angle of attack 10°. After creation, the Mach number was changed from its default value (0) to 0.1. The following parameters can be used. The parameters not available in *Basic* are only available in the *Pro* version of viiflow.

Type | Name | Explanation | Default | Basic |
---|---|---|---|---|

double | Re | Reynolds Number | 1E6 | ✓ |

double | Ma | Mach Number (<1) | 0 | ✓ |

double | ncrit | Critical amplification factor | 9 | ✓ |

int | itermax | Maximum number of Newton iterations | 100 | ✓ |

bool | iterate_wakes | Recalculate wake shape during iterations | 0 | ✓ |

int | substeps | No of steps between two panel nodes (*1) | 1 | ✓ |

bool | silent | Do not print info during iterations | 0 | ✓ |

bool | gradients | Calculate gradients | 0 | × |

double | alpha | Angle of attack | 0 | ✓ |

double | pitch_rate | Pitching rate about (0,0) (*2) | 0 | ✓ |

double | LocusA | G-beta constant A (*3) | 6.75 | ✓ |

double | LocusB | G-beta constant B (*3) | 0.83 | ✓ |

double | ViscPwrExp | Viscosity-temperature model exponent | 0.7 | ✓ |

double | equal_wakes | if>0, length of all wakes w.r.t. chord | -1 | ✓ |

int | incompressible_bl | if>0, calculate boundary layer with Ma=0 | 0 | ✓ |

double | stepsize_limit | Additional limit on Newton step, between 0 and 1 | 1 | ✓ |

During one iteration viiflow marches from the stagnation point along the pressure and suction side of the airfoil to solve the boundary layer equations. The boundary layer equations are essentially a set of ordinary differential equations (ODEs).

By default, the discretization of the ODE on the surface of the airfoil is the same as the panel nodes, i.e. a step along the surface is a single step from panel node to panel node.

By setting substeps to n, the path between to panel nodes is divided into n segments for the ODE solver. This does increase the numerical effort during the march, but not the effort for the much larger problem of the global Newton step.

Pitching airfoils experience different flow conditions than non-pitching airfoils. A pitch rate is given as the physical pitch rate in rad per sec divided by the speed of the free flow. For example, setting pitch_rate to 40*pi/180/20 would be a pitch rate of 40°/s at a current speed of 20m/s. The pitching motion is assumed to be about (0,0), so arrange your geometry accordingly.

Usually the airfoils analyzed will have a chord length of 1m and the results are scaled to the application. To model a pitching airfoil (40°/s) for a model plane at 20 m/s that has a chord length of 7cm where viiflow is calculating the airfoil characteristics at a length of 1m, one would set the pitch rate to 40*pi/180/20*0.07.

The quantity describes as well the chord to radius ratio for rotating airfoils, so set pitch_rate to c/R if given.

The parameter A and B modify the equations used in the turbulent boundary layer. They are part of an empirical correlation called the G-beta locus [1,4] and influence turbulent separation.

Examplary values from [2] are : XFOIL default [1] (A=6.7, B=.75), Boeing (A=6.935, B=.70, reference not found by the author), Green et al.[5] (A=6.43, B=.80), RFOIL [2] and viiflow defaults (A=6.75, B=.83).

The init routine can be called to initialize the variables that are used during the iterations. These are

- the panel structure
`p`

, which contains the airfoil geometries, wake geometries, viscid and inviscid solutions and the lift and moment coefficient. E.g.`p.CL`

returns the calculated lift coefficient and`p.foils[0].X`

returns the airfoil geometry as a 2xN ndarray. - the boundary layer structure
`bl`

, which is a list of structures for every airfoil. Every structure, among other things, contains the substructures`bl_fl`

, the airfoil surface boundary layer, and`bl_wk`

, the wake boundary layer. - The array
`x0`

, which is the variable used in the Newton iteration in`iter`

.

```
import viiflowtools.vf_tools as vft
# Read Airfoil coordinates into numpy 2x220 array using a function from viiflowtools
RAE = vft.repanel_spline(vft.read_selig("RAE2822.dat"),220)
# Init takes a list of airfoil geometries, here this list is a single airfoil.
# A single 2xN array is fine as well.
[p,bl,x] = vf.init([RAE],s) # [p,bl,x] = vf.init(RAE,s) works, too
print(p.gamma_inviscid)
print(bl.bl_fl.nodes.theta)
```

The above code read an airfoil into a numpy array, and lets the init function initialize `p`

, `bl`

and `x`

. the ' `print`

statement display first the vector of the inviscid solution (the edge velocity) and secondly the initial momentum thickness.

This routine is called to drive the problem towards a solution using `s.itermax`

Newton iterations.
A very simple call would be

```
for AOA in range(0,10):
s.alpha = AOA
[x,flag] = vf.iter(x,bl,p,s)
if flag: # if flag = 1: converged
print('AOA %u CL %f CD %f'%(AOA,p.CL,bl[0].CD))
```

Above, the call to iter lets it run until convergence or the defined maxiumum number of iterations, overwriting `p`

,`bl`

and `x`

in the process. If the iterations were successful, the Lift and drag coefficients are printed.

A more advanced call is

```
res = None
grad = None
s.itermax = 0 #No internal iteration
for iter in range(100):
[x,flag,res,grad] = vf.iter(x,bl,p,s,res,grad)
x -= 0.01*np.linalg.solve(grad,res)
if np.sqrt(np.dot(res.T,res))<1e-5
print('Now close enough for me!)
break
```

This allows for a fine-grained control of the iterations. Here, the iterations are stopped when the residual falls below `1e-5`

.
For the usage of gradient information I suggest looking into the Fluid-Structure Interaction example.

grad contains

- res_vd: gradient of residual w.r.t. virtual displacement
- gam_vd: gradient of surface speed w.r.t. virtual displacement
- cl_vd: gradient of lift coefficient w.r.t. virtual displacement
- delta_vd: gradient of boundary layer displacement thickness w.r.t. virtual displacement
- cd_vd: gradient of drag coefficient w.r.t. virtual displacement
- gam_x = gradient of surface speed w.r.t. x
- cl_x = gradient of lift coefficient w.r.t. x
- cd_x = gradient of drag coefficient w.r.t. x.

This routine is called to set a boundary layer to force transition at a given foil-coordinate x location

```
[p,bl,x] = vf.init([RAE],s)
trans_upper = 0.025 # Transition location on suction side
trans_lower = 0.4 # Transition location on pressure side
for AOA in range(0,10):
s.alpha = AOA
if AOA>5: # Only use forced transition if AOA>5 for some reason
vf.set_forced_transition(bl,p,[trans_upper],[trans_lower])
[x,flag] = vf.iter(x,bl,p,s)
if flag: # if flag = 1: converged
print('AOA %u CL %f CD %f'%(AOA,p.CL,bl[0].CD))
```

The lists at the third and fourth argument can have as many entries as there are airfoils, or can be empty. If the given transition location is empty or some coordinate not within the airfoil coordinate range, no forced transition occurs. If only forced transition is allowed, set in addition s.ncrit = np.inf.

There exists a *Basic* version and a *Pro* version of viiflow. The *Basic* version does not offer

- Multiple airfoil geometries.
- Gradient calculations.

[1] Drela, Mark, and Michael B. Giles. *Viscous-inviscid analysis of transonic and low Reynolds number airfoils.* AIAA journal 25.10 (1987): 1347-1355.

[2] Van Rooij, R. P. J. O. M. *Modification of the boundary layer calculation in RFOIL for improved airfoil stall prediction.* Report IW-96087R TU-Delft, the Netherlands (1996).

[3] Drela, Mark. *Integral boundary layer formulation for blunt trailing edges. 7th Applied Aerodynamics Conference. 1989.*

[4] Francis H. Clauser. *Turbulent boundary layers in adverse pressure gradients.* Journal of the Aeronautical Sciences 21.2 (1954): 91-108.

[5] Green, J. E., D. J. Weeks, and J. W. F. Brooman. *Prediction of turbulent boundary layers and wakes in compressible flow by a lag-entrainment method.* ARC R&M 3791 (1973).

[6] van der Horst, Sander, et al. *Flow Curvature Effects for VAWT: a Review of Virtual Airfoil Transformations and Implementation in XFOIL.* 34th Wind Energy Symposium. 2016.