├── .gitattributes ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── naca0012-lift-curve.png ├── old_setup.py ├── pyproject.toml ├── runs ├── cp_060_050.387 ├── cp_100_040.387 ├── cp_250_040.203 ├── cp_500_080.lnv ├── dae11.dat ├── dae21.dat ├── dae31.dat ├── dae51.dat ├── e387.dat ├── e387_09.100 ├── e387_11.100 ├── la203.bl ├── la203.dat ├── la203t.dat ├── lnv109a.dat ├── polref_100.387 └── tad.dat ├── setup.py └── src ├── __init__.py ├── example_data └── bl.txt ├── fortran ├── api.f90 ├── i_blpar.f90 ├── i_circle.f90 ├── i_pindex.f90 ├── i_xbl.f90 ├── i_xfoil.f90 ├── m_aread.f90 ├── m_iopol.f90 ├── m_naca.f90 ├── m_sort.f90 ├── m_spline.f90 ├── m_userio.f90 ├── m_xbl.f90 ├── m_xblsys.f90 ├── m_xfoil.f90 ├── m_xgdes.f90 ├── m_xgeom.f90 ├── m_xmdes.f90 ├── m_xoper.f90 ├── m_xpanel.f90 ├── m_xpol.f90 ├── m_xqdes.f90 ├── m_xsolve.f90 ├── m_xutils.f90 ├── p_xfoil.f90 ├── s_xbl.f90 ├── s_xfoil.f90 └── s_xoper.f90 └── xfoil ├── __init__.py ├── bdlayer.py ├── cpdist.py ├── model.py ├── model_parametrized.py ├── test.py └── xfoil.py /.gitattributes: -------------------------------------------------------------------------------- 1 | static/* linguist-vendored 2 | 3 | # Basic .gitattributes for a python repo. 4 | 5 | # Source files 6 | # ============ 7 | *.pxd text diff=python 8 | *.py text diff=python 9 | *.py3 text diff=python 10 | *.pyw text diff=python 11 | *.ipynb text 12 | *.pyx text diff=python 13 | 14 | # Binary files 15 | # ============ 16 | *.db binary 17 | *.p binary 18 | *.pkl binary 19 | *.pickle binary 20 | *.pyc binary 21 | *.pyd binary 22 | *.pyo binary 23 | 24 | # Note: .db, .p, and .pkl files are associated 25 | # with the python modules ``pickle``, ``dbm.*``, 26 | # ``shelve``, ``marshal``, ``anydbm``, & ``bsddb`` 27 | # (among others). -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | dist/ 3 | *.egg-info/ 4 | venv/ 5 | .idea/ 6 | cmake-build-debug/ 7 | pip-wheel-metadata/xfoil.dist-info/LICENSE 8 | pip-wheel-metadata/xfoil.dist-info/METADATA 9 | src/xfoil/__pycache__/test.cpython-36.pyc 10 | :00.bl 11 | Untitled.ipynb 12 | .ipynb_checkpoints/Untitled-checkpoint.ipynb 13 | .vscode/settings.json 14 | pip-wheel-metadata/xfoil.dist-info/top_level.txt 15 | src/__pycache__/__init__.cpython-36.pyc 16 | src/fortran/i_circle.mod 17 | src/fortran/i_pindex.mod 18 | src/xfoil/__pycache__/__init__.cpython-36.pyc 19 | src/xfoil/__pycache__/model.cpython-36.pyc 20 | src/xfoil/__pycache__/xfoil.cpython-36.pyc 21 | build_backup 22 | *.ipynb 23 | *.mod 24 | 25 | .vscode 26 | src/xfoil/__pycache__/* 27 | notebooks/* 28 | boundary_layer.txt 29 | cp.txt 30 | debug.py 31 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12) 2 | project(xfoil Fortran) 3 | 4 | enable_language(Fortran) 5 | set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} \ 6 | -O \ 7 | -fbounds-check \ 8 | -finit-real=inf \ 9 | -ffpe-trap=invalid,zero \ 10 | -fdefault-real-8") 11 | set(SRC_DIR "src/fortran") 12 | 13 | add_library(xfoil SHARED 14 | # Include modules 15 | ${SRC_DIR}/i_pindex.f90 16 | ${SRC_DIR}/i_xfoil.f90 17 | ${SRC_DIR}/i_blpar.f90 18 | ${SRC_DIR}/i_circle.f90 19 | ${SRC_DIR}/i_xbl.f90 20 | # Shared modules to avoid circular dependencies 21 | ${SRC_DIR}/s_xbl.f90 22 | ${SRC_DIR}/s_xoper.f90 23 | ${SRC_DIR}/s_xfoil.f90 24 | # Main modules 25 | ${SRC_DIR}/m_aread.f90 26 | ${SRC_DIR}/m_iopol.f90 27 | ${SRC_DIR}/m_naca.f90 28 | ${SRC_DIR}/m_sort.f90 29 | ${SRC_DIR}/m_spline.f90 30 | ${SRC_DIR}/m_userio.f90 31 | ${SRC_DIR}/m_xbl.f90 32 | ${SRC_DIR}/m_xblsys.f90 33 | ${SRC_DIR}/m_xfoil.f90 34 | ${SRC_DIR}/m_xgdes.f90 35 | ${SRC_DIR}/m_xgeom.f90 36 | ${SRC_DIR}/m_xmdes.f90 37 | ${SRC_DIR}/m_xoper.f90 38 | ${SRC_DIR}/m_xpanel.f90 39 | ${SRC_DIR}/m_xpol.f90 40 | ${SRC_DIR}/m_xqdes.f90 41 | ${SRC_DIR}/m_xsolve.f90 42 | ${SRC_DIR}/m_xutils.f90 43 | # API 44 | ${SRC_DIR}/api.f90) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > **IMPORTANT NOTE: major changes and upgrades are currently taking place. This readme file might not be up to date. Please contact me if you need any details on current usage. (July 2020)** 2 | 3 | General 4 | ------- 5 | This is a stripped down version of XFOIL, presented in the form of a Python module. What's unique about this package 6 | w.r.t. many others out there allowing an interface to XFOIL, is the fact that the Python code talks directly to a 7 | compiled Fortran library. This approach avoids having to read/write in-/output files to the disk and communicating with 8 | the XFOIl executable. Eliminating the need for constant disk I/O operations can significantly speed up parallel 9 | frameworks in particular, giving this approach a clear advantage. 10 | 11 | Building and Installing the Python Module 12 | ----------------------------------------- 13 | See https://github.com/KikeM/xfoil-python/issues/7#issuecomment-659533863 for installation instructions. 14 | 15 | Using the Module 16 | ---------------- 17 | All XFoil operations are performed using the `XFoil` class. So the first step when using this module is to create an 18 | instance of this class: 19 | 20 | ```pycon 21 | >>> from xfoil import XFoil 22 | >>> xf = XFoil() 23 | ``` 24 | 25 | If this does not produce any errors, the installation should be functioning properly. 26 | 27 | 28 | The symmetric NACA 0012 airfoil is included as a test case. It can be loaded into the XFoil library like this: 29 | 30 | ```pycon 31 | >>> from xfoil.test import naca0012 32 | >>> xf.airfoil = naca0012 33 | 34 | Number of input coordinate points: 160 35 | Counterclockwise ordering 36 | Max thickness = 0.120008 at x = 0.308 37 | Max camber = 0.000000 at x = 0.033 38 | 39 | LE x,y = -0.00000 0.00000 | Chord = 1.00000 40 | TE x,y = 1.00000 0.00000 | 41 | 42 | Current airfoil nodes set from buffer airfoil nodes ( 160 ) 43 | ``` 44 | 45 | Once the airfoil has been loaded successfully it can be analyzed. Let's analyze it for a range of angles of attack, at a 46 | Reynolds number of one million. Let's limit the maximum number of iterations to 40 (the default is 20) as well. 47 | For the range of angles of attack, we will go from -20 degrees to 20 degrees with steps of 0.5 degrees: 48 | 49 | ```pycon 50 | >>> xf.Re = 1e6 51 | >>> xf.max_iter = 40 52 | >>> a, cl, cd, cm = xf.aseq(-20, 20, 0.5) 53 | ``` 54 | 55 | The XFOIL library should produce a lot of output, which should be familiar to those who have used the original XFOIL 56 | application before. The final result are lists of angles of attack, `a`, and the corresponding lift coefficients, `cl`, 57 | drag coefficients, `cd`, and moment coefficients, `cm`. We can now, for example, plot the lift curve for this airfoil: 58 | 59 | ```pycon 60 | >>> import matplotlib.pyplot as plt 61 | >>> plt.plot(a, cl) 62 | >>> plt.show() 63 | ``` 64 | 65 | This should produce the following figure: 66 | 67 | ![NACA 0012 Lift Curve](https://github.com/daniel-de-vries/xfoil-python/raw/master/naca0012-lift-curve.png) 68 | 69 | Just like in the original XFOIL application, an airfoil can also analyzed for a single angle of attack, single lift 70 | coefficient, or a range of lift coefficients. The commands for these operations are 71 | 72 | ```pycon 73 | >>> cl, cd, cm = xf.a(10) 74 | >>> a, cd, cm = xf.cl(1) 75 | >>> a, cl, cd, cm = xf.cseq(-0.5, 0.5, 0.05) 76 | ``` 77 | 78 | to analyze for an angle of attack of 10 degrees, a lift coefficient of 1.0, and for a range of lift coefficients from 79 | -0.5 to 0.5 with steps of 0.05. 80 | 81 | For other features and specifics, see the documentation in the Python source files. 82 | 83 | -------------------------------------------------------------------------------- /naca0012-lift-curve.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emvalbuena/xfoil-python/7b09c55b149d121740724126741e7e3967667fff/naca0012-lift-curve.png -------------------------------------------------------------------------------- /old_setup.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright (c) 2019 D. de Vries 3 | # 4 | # This file is part of XFoil. 5 | # 6 | # XFoil is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # XFoil is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with XFoil. If not, see . 18 | import os 19 | import platform 20 | import subprocess 21 | import sys 22 | 23 | from setuptools import setup 24 | from setuptools.extension import Extension 25 | from setuptools.command.build_ext import build_ext 26 | 27 | version = '0.0.16' 28 | 29 | options = {k: 'OFF' for k in ['--opt', '--debug', '--cuda']} 30 | for flag in options.keys(): 31 | if flag in sys.argv: 32 | options[flag] = 'ON' 33 | sys.argv.remove(flag) 34 | 35 | # Command line flags forwarded to CMake 36 | cmake_cmd_args = [] 37 | for f in sys.argv: 38 | if f.startswith('-D'): 39 | cmake_cmd_args.append(f) 40 | sys.argv.remove(f) 41 | 42 | 43 | class CMakeExtension(Extension): 44 | 45 | def __init__(self, name, cmake_list_dir='.', **kwargs): 46 | super().__init__(name, sources=[], **kwargs) 47 | self.cmake_lists_dir = os.path.abspath(cmake_list_dir) 48 | 49 | 50 | class CMakeBuild(build_ext): 51 | 52 | def build_extensions(self): 53 | # Ensure that CMake is present and working 54 | try: 55 | out = subprocess.check_output(['cmake', '--version']) 56 | except OSError: 57 | raise RuntimeError('Cannot find CMake executable') 58 | 59 | for ext in self.extensions: 60 | extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name))) 61 | cfg = 'Debug' if options['--debug'] == 'ON' else 'Release' 62 | 63 | cmake_args = [ 64 | '-DCMAKE_BUILD_TYPE=%s' % cfg, 65 | # Ask CMake to place the resulting library in the directory 66 | # containing the extension 67 | '-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}'.format(cfg.upper(), extdir), 68 | # Other intermediate static libraries are placed in a 69 | # temporary build directory instead 70 | '-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_{}={}'.format(cfg.upper(), self.build_temp), 71 | # Hint CMake to use the same Python executable that 72 | # is launching the build, prevents possible mismatching if 73 | # multiple versions of Python are installed 74 | '-DPYTHON_EXECUTABLE={}'.format(sys.executable), 75 | # Add other project-specific CMake arguments if needed 76 | '-DCMAKE_Fortran_COMPILER=/usr/local/bin/gfortran', 77 | '-DCMAKE_MAKE_PROGRAM=make', 78 | ] 79 | 80 | # We can handle some platform-specific settings at our discretion 81 | if platform.system() == 'Windows': 82 | plat = ('x64' if platform.architecture()[0] == '64bit' else 'Win32') 83 | cmake_args += [ 84 | # These options are likely to be needed under Windows 85 | '-DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=TRUE', 86 | '-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_{}={}'.format(cfg.upper(), extdir), 87 | ] 88 | # Assuming that Visual Studio and MinGW are supported compilers 89 | if self.compiler.compiler_type == 'msvc': 90 | cmake_args += [ 91 | '-DCMAKE_GENERATOR_PLATFORM=%s' % plat, 92 | ] 93 | else: 94 | cmake_args += [ 95 | '-G', 'MinGW Makefiles', 96 | ] 97 | 98 | cmake_args += cmake_cmd_args 99 | 100 | print(cmake_args) 101 | 102 | if not os.path.exists(self.build_temp): 103 | os.makedirs(self.build_temp) 104 | 105 | # Config and build the extension 106 | subprocess.check_call(['cmake', ext.cmake_lists_dir] + cmake_args, 107 | cwd=self.build_temp) 108 | subprocess.check_call(['cmake', '--build', '.', '--config', cfg], 109 | cwd=self.build_temp) 110 | 111 | 112 | def readme(): 113 | with open('README.md') as f: 114 | return f.read() 115 | 116 | 117 | setup( 118 | name='xfoil', 119 | version=version, 120 | description='Stripped down version of XFOIL as compiled python module ', 121 | long_description=readme(), 122 | classifiers=[ 123 | 'Development Status :: 3 - Alpha', 124 | 'Intended Audience :: Science/Research', 125 | 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)', 126 | 'Natural Language :: English', 127 | 'Operating System :: MacOS :: MacOS X', 128 | 'Operating System :: POSIX :: Linux', 129 | 'Operating System :: Microsoft :: Windows', 130 | 'Programming Language :: Fortran', 131 | 'Programming Language :: Python :: 3 :: Only', 132 | 'Topic :: Scientific/Engineering', 133 | ], 134 | keywords='xfoil airfoil aerodynamic analysis', 135 | url='https://github.com/daniel-de-vries/xfoil-python', 136 | download_url='https://github.com/daniel-de-vries/xfoil-python/tarball/' + version, 137 | author='Daniël de Vries', 138 | author_email='contact@daniel-de-vries.com', 139 | license='GNU General Public License v3 or later (GPLv3+)', 140 | packages=['xfoil'], 141 | package_dir={'': 'src'}, 142 | ext_modules=[CMakeExtension('xfoil.xfoil')], 143 | cmdclass={'build_ext': CMakeBuild}, 144 | install_requires=['numpy'], 145 | zip_save=False 146 | ) 147 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["scikit-build", "cmake"] -------------------------------------------------------------------------------- /runs/cp_060_050.387: -------------------------------------------------------------------------------- 1 | 0.950 -0.0370 | CL=0.838 (a=5 deg nominal) Re=60000 2 | 0.900 -0.1214 3 | 0.850 -0.2418 4 | 0.800 -0.4137 5 | 0.750 -0.5977 6 | 0.700 -0.6307 7 | 0.650 -0.6126 8 | 0.600 -0.6075 9 | 0.550 -0.5985 10 | 0.500 -0.5990 11 | 0.450 -0.6124 12 | 0.400 -0.6330 13 | 0.350 -0.6652 14 | 0.300 -0.7310 15 | 0.250 -0.8065 16 | 0.200 -0.8648 17 | 0.150 -0.9291 18 | 0.100 -1.0042 19 | 0.075 -1.0262 20 | 0.060 -1.0360 21 | 0.050 -1.0463 22 | 0.040 -1.0469 23 | 0.030 -1.0311 24 | 0.025 -1.0353 25 | 0.020 -1.0571 26 | 0.015 -1.0064 27 | 0.010 -0.9906 28 | 0.005 -0.8359 29 | 0.0 0.4274 30 | 0.950 0.1178 31 | 0.900 0.1461 32 | 0.850 0.1603 33 | 0.800 0.1754 34 | 0.750 0.1786 35 | 0.700 0.1837 36 | 0.650 0.1912 37 | 0.600 0.1977 38 | 0.550 0.1983 39 | 0.500 0.2044 40 | 0.450 0.2144 41 | 0.400 0.2156 42 | 0.350 0.2243 43 | 0.300 0.2354 44 | 0.250 0.2380 45 | 0.200 0.2570 46 | 0.150 0.2817 47 | 0.100 0.3200 48 | 0.075 0.3595 49 | 0.060 0.3932 50 | 0.050 0.4291 51 | 0.040 0.4701 52 | 0.031 0.5370 53 | 0.025 0.5845 54 | 0.020 0.6551 55 | 0.015 0.7133 56 | 0.010 0.8403 57 | 0.005 0.9710 58 | -------------------------------------------------------------------------------- /runs/cp_100_040.387: -------------------------------------------------------------------------------- 1 | # Langley Cp data 2 | 0.950 0.0451 | CL=0.778 (a=4 deg nominal) Re=100000 3 | 0.900 -.0008 4 | 0.850 -.0410 5 | 0.800 -.1223 6 | 0.750 -.3670 7 | 0.700 -.6230 8 | 0.650 -.6383 9 | 0.600 -.6343 10 | 0.550 -.6327 11 | 0.500 -.6351 12 | 0.450 -.6557 13 | 0.400 -.6849 14 | 0.350 -.7470 15 | 0.300 -.8061 16 | 0.250 -.8481 17 | 0.200 -.8876 18 | 0.150 -.9254 19 | 0.100 -.9656 20 | 0.075 -.9831 21 | 0.060 -.9826 22 | 0.050 -.9700 23 | 0.040 -.9659 24 | 0.030 -.9529 25 | 0.025 -.9409 26 | 0.020 -.9137 27 | 0.015 -.8654 28 | 0.010 -.8129 29 | 0.005 -.6744 30 | 0.0 0.6121 31 | 0.950 0.1352 32 | 0.900 0.1558 33 | 0.850 0.1623 34 | 0.800 0.1692 35 | 0.750 0.1688 36 | 0.700 0.1743 37 | 0.650 0.1755 38 | 0.600 0.1795 39 | 0.550 0.1787 40 | 0.500 0.1851 41 | 0.450 0.1902 42 | 0.400 0.1894 43 | 0.350 0.1963 44 | 0.300 0.1978 45 | 0.250 0.1970 46 | 0.200 0.2121 47 | 0.150 0.2204 48 | 0.100 0.2585 49 | 0.075 0.2879 50 | 0.060 0.3143 51 | 0.050 0.3489 52 | 0.040 0.3891 53 | 0.031 0.4545 54 | 0.025 0.4966 55 | 0.020 0.5466 56 | 0.015 0.6190 57 | 0.010 0.7428 58 | 0.005 0.9269 59 | -------------------------------------------------------------------------------- /runs/cp_250_040.203: -------------------------------------------------------------------------------- 1 | 1.000 0.088 | CL=1.08 (a=4 deg nominal) Re=250000 2 | 0.950 -.051 3 | 0.900 -.102 4 | 0.850 -.196 5 | 0.800 -.293 6 | 0.750 -.386 7 | 0.700 -.458 8 | 0.675 -.481 9 | 0.650 -.719 10 | 0.625 -1.098 11 | 0.600 -1.098 12 | 0.575 -1.098 13 | 0.550 -1.098 14 | 0.525 -1.098 15 | 0.500 -1.123 16 | 0.475 -1.146 17 | 0.450 -1.195 18 | 0.425 -1.244 19 | 0.400 -1.291 20 | 0.375 -1.344 21 | 0.350 -1.344 22 | 0.325 -1.363 23 | 0.300 -1.388 24 | 0.250 -1.388 25 | 0.200 -1.363 26 | 0.150 -1.342 27 | 0.100 -1.246 28 | 0.075 -1.195 29 | 0.050 -1.144 30 | 0.025 -1.007 31 | 0.012 -.811 32 | 0.000 0.760 33 | 0.012 0.430 34 | 0.025 0.140 35 | 0.050 0.189 36 | 0.075 0.189 37 | 0.100 0.189 38 | 0.150 0.189 39 | 0.200 0.160 40 | 0.300 0.163 41 | 0.400 0.140 42 | 0.500 0.139 43 | 0.600 0.189 44 | 0.700 0.212 45 | 0.800 0.212 46 | 0.850 0.237 47 | 0.900 0.330 48 | 0.950 0.430 49 | -------------------------------------------------------------------------------- /runs/cp_500_080.lnv: -------------------------------------------------------------------------------- 1 | 1.000 0.055 | CL=1.234 (a=8 deg nominal) Re=500000 2 | 0.950 0.050 3 | 0.900 0.020 4 | 0.850 0.000 5 | 0.800 -.045 6 | 0.750 -.105 7 | 0.700 -.150 8 | 0.650 -.222 9 | 0.600 -.309 10 | 0.550 -.418 11 | 0.500 -.567 12 | 0.450 -.743 13 | 0.425 -.860 14 | 0.400 -1.216 15 | 0.375 -1.775 16 | 0.350 -1.784 17 | 0.325 -1.784 18 | 0.300 -1.870 19 | 0.275 -1.944 20 | 0.250 -2.022 21 | 0.225 -2.072 22 | 0.200 -2.111 23 | 0.150 -2.126 24 | 0.100 -2.063 25 | 0.075 -2.005 26 | 0.050 -1.946 27 | 0.025 -1.805 28 | 0.012 -1.171 29 | 0.000 0.202 30 | 0.012 0.750 31 | 0.025 0.486 32 | 0.050 0.414 33 | 0.075 0.400 34 | 0.100 0.408 35 | 0.150 0.400 36 | 0.200 0.395 37 | 0.300 0.336 38 | 0.400 0.371 39 | 0.500 0.357 40 | 0.600 0.332 41 | 0.700 0.250 42 | 0.800 0.211 43 | 0.900 0.152 44 | 0.950 0.077 45 | -------------------------------------------------------------------------------- /runs/dae11.dat: -------------------------------------------------------------------------------- 1 | DAE 11 2 | # Daedalus wing center panel airfoil. Design Re = 500K 3 | 1.000000 0.000000 4 | 0.986485 0.002537 5 | 0.970011 0.005613 6 | 0.947881 0.010041 7 | 0.918618 0.016374 8 | 0.887980 0.023556 9 | 0.857968 0.031118 10 | 0.827970 0.039139 11 | 0.797803 0.047590 12 | 0.767378 0.056399 13 | 0.736634 0.065482 14 | 0.705687 0.074715 15 | 0.675260 0.083695 16 | 0.645478 0.092177 17 | 0.616310 0.099961 18 | 0.587628 0.106875 19 | 0.559192 0.112804 20 | 0.530735 0.117738 21 | 0.502104 0.121740 22 | 0.473284 0.124848 23 | 0.444338 0.127068 24 | 0.415323 0.128391 25 | 0.386255 0.128806 26 | 0.357167 0.128336 27 | 0.328135 0.126996 28 | 0.299232 0.124754 29 | 0.270512 0.121609 30 | 0.242030 0.117536 31 | 0.213885 0.112508 32 | 0.186216 0.106500 33 | 0.159197 0.099489 34 | 0.133039 0.091476 35 | 0.108024 0.082466 36 | 0.084520 0.072514 37 | 0.062995 0.061754 38 | 0.044085 0.050490 39 | 0.028485 0.039251 40 | 0.016619 0.028679 41 | 0.008417 0.019287 42 | 0.003417 0.011421 43 | 0.000883 0.005097 44 | 0.000128 0.000182 45 | 0.000626 -0.003555 46 | 0.002138 -0.006473 47 | 0.004541 -0.008835 48 | 0.008212 -0.010744 49 | 0.014240 -0.012418 50 | 0.024697 -0.013921 51 | 0.041573 -0.014931 52 | 0.065014 -0.015107 53 | 0.092723 -0.014502 54 | 0.122696 -0.013331 55 | 0.153786 -0.011784 56 | 0.185487 -0.010003 57 | 0.217549 -0.008087 58 | 0.249834 -0.006102 59 | 0.282263 -0.004093 60 | 0.314698 -0.002099 61 | 0.347047 -0.000149 62 | 0.379318 0.001724 63 | 0.411508 0.003509 64 | 0.443624 0.005174 65 | 0.475671 0.006709 66 | 0.507637 0.008092 67 | 0.539527 0.009282 68 | 0.571366 0.010264 69 | 0.603162 0.011026 70 | 0.634928 0.011552 71 | 0.666677 0.011849 72 | 0.698414 0.011916 73 | 0.730135 0.011759 74 | 0.761819 0.011381 75 | 0.793447 0.010763 76 | 0.825020 0.009891 77 | 0.856580 0.008751 78 | 0.888343 0.007325 79 | 0.920025 0.005610 80 | 0.948000 0.003865 81 | 0.969655 0.002348 82 | 0.986285 0.001076 83 | 1.000000 0.000000 84 | -------------------------------------------------------------------------------- /runs/dae21.dat: -------------------------------------------------------------------------------- 1 | DAE 21 2 | # Daedalus outer panel break airfoil. Design Re = 375K 3 | 1.000000 0.000000 4 | 0.986712 0.002418 5 | 0.970362 0.005492 6 | 0.947691 0.010083 7 | 0.917703 0.016743 8 | 0.887293 0.024120 9 | 0.857161 0.031966 10 | 0.826867 0.040283 11 | 0.796262 0.048982 12 | 0.765287 0.057938 13 | 0.734180 0.066919 14 | 0.703358 0.075625 15 | 0.672878 0.083860 16 | 0.642725 0.091437 17 | 0.612839 0.098204 18 | 0.583189 0.104141 19 | 0.553743 0.109238 20 | 0.524452 0.113495 21 | 0.495245 0.116921 22 | 0.466044 0.119541 23 | 0.436797 0.121383 24 | 0.407512 0.122444 25 | 0.378226 0.122715 26 | 0.348985 0.122181 27 | 0.319838 0.120829 28 | 0.290842 0.118635 29 | 0.262053 0.115583 30 | 0.233558 0.111651 31 | 0.205468 0.106814 32 | 0.177922 0.101046 33 | 0.151092 0.094310 34 | 0.125176 0.086572 35 | 0.100450 0.077840 36 | 0.077317 0.068163 37 | 0.056331 0.057700 38 | 0.038181 0.046773 39 | 0.023556 0.035891 40 | 0.012848 0.025735 41 | 0.005879 0.016869 42 | 0.001956 0.009449 43 | 0.000266 0.003383 44 | 0.000061 -0.001451 45 | 0.000768 -0.005145 46 | 0.002174 -0.007971 47 | 0.004373 -0.010203 48 | 0.007802 -0.012025 49 | 0.013654 -0.013482 50 | 0.024269 -0.014572 51 | 0.041672 -0.014985 52 | 0.065976 -0.014369 53 | 0.094566 -0.012972 54 | 0.125275 -0.011034 55 | 0.156913 -0.008816 56 | 0.189022 -0.006461 57 | 0.221380 -0.004063 58 | 0.253714 -0.001687 59 | 0.285949 0.000632 60 | 0.318102 0.002874 61 | 0.350185 0.005015 62 | 0.382195 0.007039 63 | 0.414128 0.008920 64 | 0.445987 0.010630 65 | 0.477768 0.012157 66 | 0.509472 0.013465 67 | 0.541126 0.014532 68 | 0.572758 0.015351 69 | 0.604367 0.015925 70 | 0.635947 0.016240 71 | 0.667511 0.016282 72 | 0.699072 0.016053 73 | 0.730622 0.015565 74 | 0.762134 0.014807 75 | 0.793605 0.013763 76 | 0.825056 0.012422 77 | 0.856541 0.010783 78 | 0.888226 0.008848 79 | 0.920042 0.006634 80 | 0.948501 0.004447 81 | 0.970227 0.002643 82 | 0.986570 0.001203 83 | 1.000000 0.000000 84 | -------------------------------------------------------------------------------- /runs/dae31.dat: -------------------------------------------------------------------------------- 1 | DAE 31 2 | # Daedalus tip panel airfoil (4ft from tip). Design Re = 250K 3 | 1.000000 0.000000 4 | 0.983670 0.003678 5 | 0.964831 0.008217 6 | 0.942298 0.013939 7 | 0.915136 0.021198 8 | 0.884751 0.029762 9 | 0.854418 0.038671 10 | 0.823963 0.047867 11 | 0.793343 0.057188 12 | 0.763399 0.066115 13 | 0.734041 0.074433 14 | 0.705002 0.082031 15 | 0.676045 0.088917 16 | 0.647058 0.095104 17 | 0.617978 0.100577 18 | 0.588755 0.105349 19 | 0.559366 0.109434 20 | 0.529812 0.112852 21 | 0.500123 0.115621 22 | 0.470348 0.117747 23 | 0.440557 0.119235 24 | 0.410816 0.120061 25 | 0.381154 0.120198 26 | 0.351603 0.119637 27 | 0.322220 0.118356 28 | 0.293057 0.116321 29 | 0.264162 0.113501 30 | 0.235612 0.109876 31 | 0.207525 0.105414 32 | 0.180030 0.100065 33 | 0.153293 0.093810 34 | 0.127559 0.086629 35 | 0.103134 0.078508 36 | 0.080386 0.069477 37 | 0.059755 0.059645 38 | 0.041713 0.049168 39 | 0.026721 0.038403 40 | 0.015173 0.027944 41 | 0.007269 0.018571 42 | 0.002584 0.010709 43 | 0.000358 0.004518 44 | 0.000025 -0.000558 45 | 0.000189 -0.002800 46 | 0.001175 -0.006664 47 | 0.002966 -0.009596 48 | 0.005693 -0.011873 49 | 0.009988 -0.013595 50 | 0.017247 -0.014838 51 | 0.029729 -0.015535 52 | 0.049021 -0.015193 53 | 0.074285 -0.013756 54 | 0.102957 -0.011523 55 | 0.133315 -0.008820 56 | 0.164511 -0.005908 57 | 0.196175 -0.002926 58 | 0.228118 0.000031 59 | 0.260168 0.002902 60 | 0.292125 0.005647 61 | 0.323993 0.008244 62 | 0.355786 0.010669 63 | 0.387504 0.012911 64 | 0.419145 0.014938 65 | 0.450717 0.016729 66 | 0.482216 0.018267 67 | 0.513641 0.019520 68 | 0.545019 0.020458 69 | 0.576374 0.021089 70 | 0.607695 0.021417 71 | 0.638977 0.021429 72 | 0.670233 0.021125 73 | 0.701474 0.020513 74 | 0.732690 0.019612 75 | 0.763858 0.018421 76 | 0.794976 0.016921 77 | 0.826072 0.015114 78 | 0.857232 0.012998 79 | 0.888815 0.010562 80 | 0.919284 0.007958 81 | 0.945604 0.005528 82 | 0.967071 0.003429 83 | 0.984882 0.001590 84 | 1.000000 0.000000 85 | -------------------------------------------------------------------------------- /runs/dae51.dat: -------------------------------------------------------------------------------- 1 | DAE 51 2 | # Daedalus propeller airfoil 3 | 1.000000 -0.000051 4 | 0.989166 0.001996 5 | 0.975819 0.004501 6 | 0.957448 0.007991 7 | 0.931599 0.013004 8 | 0.901654 0.018957 9 | 0.870818 0.025167 10 | 0.839998 0.031363 11 | 0.809336 0.037430 12 | 0.778839 0.043301 13 | 0.748503 0.048933 14 | 0.718326 0.054243 15 | 0.688314 0.059175 16 | 0.658443 0.063716 17 | 0.628653 0.067839 18 | 0.598855 0.071530 19 | 0.569004 0.074792 20 | 0.539074 0.077652 21 | 0.509071 0.080095 22 | 0.479015 0.082100 23 | 0.448934 0.083641 24 | 0.418877 0.084690 25 | 0.388863 0.085217 26 | 0.358908 0.085197 27 | 0.329049 0.084600 28 | 0.299321 0.083399 29 | 0.269760 0.081570 30 | 0.240419 0.079081 31 | 0.211388 0.075895 32 | 0.182766 0.071967 33 | 0.154699 0.067243 34 | 0.127404 0.061670 35 | 0.101193 0.055204 36 | 0.076503 0.047832 37 | 0.054060 0.039675 38 | 0.034881 0.031085 39 | 0.020059 0.022737 40 | 0.010052 0.015405 41 | 0.004208 0.009557 42 | 0.001251 0.005050 43 | 0.000113 0.001479 44 | 0.000123 -0.001494 45 | 0.001002 -0.004085 46 | 0.002793 -0.006422 47 | 0.006019 -0.008524 48 | 0.011960 -0.010609 49 | 0.022698 -0.012727 50 | 0.040333 -0.014554 51 | 0.064233 -0.015717 52 | 0.091882 -0.016173 53 | 0.121305 -0.016067 54 | 0.151560 -0.015570 55 | 0.182231 -0.014790 56 | 0.213149 -0.013797 57 | 0.244240 -0.012649 58 | 0.275464 -0.011392 59 | 0.306798 -0.010061 60 | 0.338230 -0.008690 61 | 0.369725 -0.007318 62 | 0.401184 -0.005962 63 | 0.432597 -0.004640 64 | 0.463976 -0.003366 65 | 0.495325 -0.002147 66 | 0.526644 -0.000994 67 | 0.557930 0.000082 68 | 0.589182 0.001071 69 | 0.620390 0.001960 70 | 0.651547 0.002731 71 | 0.682648 0.003367 72 | 0.713694 0.003847 73 | 0.744690 0.004152 74 | 0.775644 0.004269 75 | 0.806546 0.004190 76 | 0.837373 0.003898 77 | 0.868134 0.003359 78 | 0.898985 0.002532 79 | 0.929868 0.001410 80 | 0.956572 0.000219 81 | 0.975393 -0.000742 82 | 0.988983 -0.001472 83 | 1.000000 -0.002051 84 | -------------------------------------------------------------------------------- /runs/e387.dat: -------------------------------------------------------------------------------- 1 | E387 2 | 1.00000 0.00000 3 | 0.99677 0.00043 4 | 0.98729 0.00180 5 | 0.97198 0.00423 6 | 0.95128 0.00763 7 | 0.92554 0.01184 8 | 0.89510 0.01679 9 | 0.86035 0.02242 10 | 0.82183 0.02866 11 | 0.78007 0.03540 12 | 0.73567 0.04249 13 | 0.68922 0.04975 14 | 0.64136 0.05696 15 | 0.59272 0.06390 16 | 0.54394 0.07020 17 | 0.49549 0.07546 18 | 0.44767 0.07936 19 | 0.40077 0.08173 20 | 0.35505 0.08247 21 | 0.31078 0.08156 22 | 0.26813 0.07908 23 | 0.22742 0.07529 24 | 0.18906 0.07037 25 | 0.15345 0.06448 26 | 0.12094 0.05775 27 | 0.09185 0.05033 28 | 0.06643 0.04238 29 | 0.04493 0.03408 30 | 0.02748 0.02562 31 | 0.01423 0.01726 32 | 0.00519 0.00931 33 | 0.00044 0.00234 34 | 0.00091 -0.00286 35 | 0.00717 -0.00682 36 | 0.01890 -0.01017 37 | 0.03596 -0.01265 38 | 0.05827 -0.01425 39 | 0.08569 -0.01500 40 | 0.11800 -0.01502 41 | 0.15490 -0.01441 42 | 0.19599 -0.01329 43 | 0.24083 -0.01177 44 | 0.28892 -0.00998 45 | 0.33968 -0.00804 46 | 0.39252 -0.00605 47 | 0.44679 -0.00410 48 | 0.50182 -0.00228 49 | 0.55694 -0.00065 50 | 0.61147 0.00074 51 | 0.66472 0.00186 52 | 0.71602 0.00268 53 | 0.76475 0.00320 54 | 0.81027 0.00342 55 | 0.85202 0.00337 56 | 0.88944 0.00307 57 | 0.92205 0.00258 58 | 0.94942 0.00196 59 | 0.97118 0.00132 60 | 0.98705 0.00071 61 | 0.99674 0.00021 62 | 1.00000 0.00000 63 | -------------------------------------------------------------------------------- /runs/e387_09.100: -------------------------------------------------------------------------------- 1 | 2 | XFOIL Version 6.90 3 | 4 | Calculated polar for: Eppler 387 1 elements 5 | 6 | 1 1 Reynolds number fixed Mach number fixed 7 | 8 | xtrf = 1.000 (top) 1.000 (bottom) element 1 9 | Mach = 0.000 Re = 0.100 e 6 Ncrit = 9.000 10 | 11 | alpha CL CD CDp CM Top Xtr Bot Xtr 12 | ------- -------- --------- --------- -------- ------- ------- 13 | -3.000 0.1048 0.01946 0.01072 -0.1011 0.9086 0.0922 14 | -2.900 0.1145 0.01905 0.01039 -0.1009 0.9029 0.0999 15 | -2.800 0.1271 0.01856 0.00992 -0.1010 0.8993 0.1103 16 | -2.700 0.1402 0.01812 0.00956 -0.1013 0.8964 0.1268 17 | -2.600 0.1505 0.01776 0.00923 -0.1010 0.8914 0.1446 18 | -2.500 0.1617 0.01730 0.00895 -0.1011 0.8875 0.1717 19 | -2.400 0.1736 0.01670 0.00860 -0.1011 0.8845 0.2145 20 | -2.300 0.1837 0.01611 0.00840 -0.1011 0.8804 0.2881 21 | -2.200 0.1924 0.01544 0.00832 -0.1008 0.8761 0.4082 22 | -2.100 0.2001 0.01482 0.00828 -0.0998 0.8729 0.5607 23 | -2.000 0.2043 0.01437 0.00830 -0.0974 0.8701 0.7026 24 | -1.900 0.2064 0.01411 0.00836 -0.0945 0.8652 0.8362 25 | -1.800 0.2267 0.01386 0.00804 -0.0956 0.8620 1.0000 26 | -1.700 0.2383 0.01389 0.00790 -0.0955 0.8590 1.0000 27 | -1.600 0.2490 0.01398 0.00786 -0.0955 0.8547 1.0000 28 | -1.500 0.2599 0.01406 0.00781 -0.0955 0.8505 1.0000 29 | -1.400 0.2710 0.01411 0.00773 -0.0953 0.8474 1.0000 30 | -1.200 0.2926 0.01429 0.00768 -0.0953 0.8397 1.0000 31 | -1.000 0.3145 0.01440 0.00757 -0.0949 0.8337 1.0000 32 | -0.800 0.3359 0.01461 0.00763 -0.0949 0.8258 1.0000 33 | -0.600 0.3576 0.01473 0.00755 -0.0945 0.8204 1.0000 34 | -0.400 0.3791 0.01498 0.00767 -0.0946 0.8125 1.0000 35 | -0.200 0.4008 0.01510 0.00763 -0.0942 0.8075 1.0000 36 | 0.000 0.4222 0.01538 0.00782 -0.0943 0.7998 1.0000 37 | 0.200 0.4439 0.01551 0.00781 -0.0939 0.7950 1.0000 38 | 0.400 0.4654 0.01581 0.00804 -0.0941 0.7874 1.0000 39 | 0.600 0.4871 0.01596 0.00806 -0.0937 0.7827 1.0000 40 | 0.800 0.5086 0.01628 0.00835 -0.0939 0.7755 1.0000 41 | 1.000 0.5304 0.01644 0.00841 -0.0935 0.7706 1.0000 42 | 1.200 0.5518 0.01678 0.00872 -0.0937 0.7638 1.0000 43 | 1.400 0.5736 0.01697 0.00884 -0.0934 0.7588 1.0000 44 | 1.600 0.5950 0.01730 0.00916 -0.0935 0.7525 1.0000 45 | 1.800 0.6167 0.01754 0.00936 -0.0933 0.7471 1.0000 46 | 2.000 0.6382 0.01784 0.00964 -0.0933 0.7416 1.0000 47 | 2.200 0.6596 0.01813 0.00992 -0.0932 0.7355 1.0000 48 | 2.400 0.6814 0.01834 0.01009 -0.0929 0.7311 1.0000 49 | 2.600 0.7025 0.01875 0.01057 -0.0931 0.7240 1.0000 50 | 2.800 0.7244 0.01891 0.01069 -0.0927 0.7198 1.0000 51 | 3.000 0.7451 0.01938 0.01122 -0.0929 0.7124 1.0000 52 | 3.200 0.7669 0.01953 0.01136 -0.0924 0.7077 1.0000 53 | 3.400 0.7875 0.01998 0.01191 -0.0925 0.7003 1.0000 54 | 3.600 0.8092 0.02011 0.01203 -0.0920 0.6953 1.0000 55 | 3.800 0.8295 0.02053 0.01253 -0.0920 0.6875 1.0000 56 | 4.000 0.8514 0.02053 0.01252 -0.0913 0.6820 1.0000 57 | 4.100 0.8607 0.02079 0.01286 -0.0912 0.6764 1.0000 58 | 4.200 0.8712 0.02078 0.01286 -0.0908 0.6724 1.0000 59 | 4.300 0.8823 0.02067 0.01275 -0.0903 0.6695 1.0000 60 | 4.400 0.8916 0.02091 0.01307 -0.0902 0.6636 1.0000 61 | 4.500 0.9021 0.02088 0.01305 -0.0898 0.6596 1.0000 62 | 4.600 0.9133 0.02079 0.01293 -0.0893 0.6568 1.0000 63 | 4.700 0.9226 0.02106 0.01330 -0.0893 0.6512 1.0000 64 | 4.800 0.9332 0.02110 0.01337 -0.0890 0.6475 1.0000 65 | 4.900 0.9444 0.02106 0.01333 -0.0886 0.6448 1.0000 66 | 5.000 0.9540 0.02130 0.01366 -0.0885 0.6400 1.0000 67 | 5.100 0.9643 0.02140 0.01381 -0.0883 0.6358 1.0000 68 | 5.200 0.9754 0.02136 0.01378 -0.0880 0.6328 1.0000 69 | 5.300 0.9854 0.02152 0.01400 -0.0878 0.6284 1.0000 70 | 5.400 0.9954 0.02162 0.01420 -0.0875 0.6234 1.0000 71 | 5.500 1.0066 0.02145 0.01402 -0.0870 0.6197 1.0000 72 | 5.600 1.0157 0.02157 0.01424 -0.0867 0.6130 1.0000 73 | 5.700 1.0266 0.02137 0.01403 -0.0861 0.6079 1.0000 74 | 5.800 1.0360 0.02136 0.01410 -0.0856 0.6009 1.0000 75 | 5.900 1.0468 0.02109 0.01382 -0.0849 0.5951 1.0000 76 | 6.000 1.0560 0.02107 0.01389 -0.0844 0.5873 1.0000 77 | 6.100 1.0671 0.02078 0.01357 -0.0838 0.5817 1.0000 78 | 6.200 1.0760 0.02080 0.01370 -0.0834 0.5735 1.0000 79 | 6.300 1.0870 0.02056 0.01344 -0.0828 0.5676 1.0000 80 | 6.400 1.0961 0.02053 0.01356 -0.0823 0.5593 1.0000 81 | 6.500 1.1060 0.02045 0.01353 -0.0818 0.5519 1.0000 82 | 6.600 1.1163 0.02029 0.01341 -0.0813 0.5450 1.0000 83 | 6.700 1.1255 0.02029 0.01352 -0.0808 0.5365 1.0000 84 | 6.800 1.1358 0.02015 0.01341 -0.0803 0.5292 1.0000 85 | 6.900 1.1453 0.02008 0.01342 -0.0798 0.5203 1.0000 86 | 7.000 1.1544 0.02003 0.01348 -0.0793 0.5104 1.0000 87 | 7.100 1.1637 0.01995 0.01348 -0.0787 0.4999 1.0000 88 | 7.200 1.1728 0.01985 0.01346 -0.0781 0.4882 1.0000 89 | 7.300 1.1816 0.01977 0.01346 -0.0775 0.4749 1.0000 90 | 7.400 1.1903 0.01971 0.01347 -0.0768 0.4599 1.0000 91 | 7.500 1.1984 0.01965 0.01346 -0.0761 0.4411 1.0000 92 | 7.600 1.2055 0.01965 0.01347 -0.0753 0.4143 1.0000 93 | 7.700 1.2113 0.01978 0.01352 -0.0743 0.3772 1.0000 94 | 7.800 1.2151 0.02018 0.01362 -0.0731 0.3296 1.0000 95 | 7.900 1.2166 0.02093 0.01397 -0.0719 0.2827 1.0000 96 | 8.000 1.2176 0.02184 0.01455 -0.0708 0.2438 1.0000 97 | 8.100 1.2191 0.02276 0.01522 -0.0698 0.2131 1.0000 98 | 8.200 1.2206 0.02367 0.01595 -0.0688 0.1885 1.0000 99 | 8.300 1.2220 0.02459 0.01671 -0.0678 0.1669 1.0000 100 | 8.400 1.2224 0.02557 0.01750 -0.0667 0.1477 1.0000 101 | 8.500 1.2228 0.02655 0.01835 -0.0655 0.1267 1.0000 102 | 8.600 1.2212 0.02767 0.01929 -0.0642 0.1086 1.0000 103 | -------------------------------------------------------------------------------- /runs/e387_11.100: -------------------------------------------------------------------------------- 1 | 2 | XFOIL Version 6.90 3 | 4 | Calculated polar for: Eppler 387 5 | 6 | 1 1 Reynolds number fixed Mach number fixed 7 | 8 | xtrf = 1.000 (top) 1.000 (bottom) 9 | Mach = 0.000 Re = 0.100 e 6 Ncrit = 11.000 10 | 11 | alpha CL CD CDp CM Top Xtr Bot Xtr 12 | ------- -------- --------- --------- -------- ------- ------- 13 | -3.000 0.0560 0.02350 0.01498 -0.0988 0.9417 0.0994 14 | -2.900 0.0725 0.02284 0.01431 -0.0997 0.9384 0.1034 15 | -2.800 0.0920 0.02213 0.01360 -0.1013 0.9361 0.1128 16 | -2.700 0.1121 0.02138 0.01290 -0.1029 0.9341 0.1252 17 | -2.600 0.1330 0.02070 0.01217 -0.1045 0.9324 0.1443 18 | -2.400 0.1588 0.01962 0.01143 -0.1054 0.9245 0.1926 19 | -2.100 0.1963 0.01636 0.01058 -0.1056 0.9170 0.6517 20 | -1.900 0.2190 0.01570 0.01026 -0.1033 0.9104 1.0000 21 | -1.800 0.2368 0.01571 0.01006 -0.1045 0.9079 1.0000 22 | -1.700 0.2458 0.01589 0.01010 -0.1043 0.9028 1.0000 23 | -1.600 0.2595 0.01597 0.01003 -0.1048 0.8992 1.0000 24 | -1.500 0.2750 0.01599 0.00990 -0.1055 0.8965 1.0000 25 | -1.400 0.2863 0.01613 0.00992 -0.1057 0.8925 1.0000 26 | -1.300 0.2970 0.01627 0.00996 -0.1057 0.8882 1.0000 27 | -1.200 0.3107 0.01633 0.00990 -0.1061 0.8852 1.0000 28 | -1.100 0.3251 0.01635 0.00982 -0.1065 0.8829 1.0000 29 | -1.000 0.3331 0.01660 0.01000 -0.1063 0.8778 1.0000 30 | -0.900 0.3449 0.01670 0.01001 -0.1064 0.8743 1.0000 31 | -0.800 0.3581 0.01675 0.00997 -0.1066 0.8717 1.0000 32 | -0.700 0.3688 0.01690 0.01005 -0.1066 0.8682 1.0000 33 | -0.600 0.3785 0.01710 0.01017 -0.1066 0.8639 1.0000 34 | -0.500 0.3905 0.01718 0.01018 -0.1066 0.8609 1.0000 35 | -0.400 0.4031 0.01722 0.01015 -0.1066 0.8586 1.0000 36 | -0.300 0.4123 0.01748 0.01035 -0.1066 0.8543 1.0000 37 | -0.200 0.4227 0.01764 0.01047 -0.1066 0.8507 1.0000 38 | -0.100 0.4345 0.01772 0.01048 -0.1065 0.8479 1.0000 39 | 0.000 0.4466 0.01777 0.01047 -0.1064 0.8458 1.0000 40 | 0.100 0.4554 0.01808 0.01075 -0.1065 0.8412 1.0000 41 | 0.200 0.4660 0.01824 0.01086 -0.1064 0.8378 1.0000 42 | 0.300 0.4775 0.01832 0.01089 -0.1063 0.8353 1.0000 43 | 0.400 0.4894 0.01837 0.01089 -0.1062 0.8333 1.0000 44 | 0.500 0.4982 0.01873 0.01123 -0.1063 0.8286 1.0000 45 | 0.600 0.5087 0.01890 0.01136 -0.1063 0.8254 1.0000 46 | 0.700 0.5201 0.01898 0.01140 -0.1061 0.8229 1.0000 47 | 0.800 0.5316 0.01903 0.01141 -0.1059 0.8209 1.0000 48 | 0.900 0.5406 0.01942 0.01179 -0.1061 0.8164 1.0000 49 | 1.000 0.5510 0.01961 0.01196 -0.1061 0.8132 1.0000 50 | 1.100 0.5622 0.01970 0.01202 -0.1059 0.8107 1.0000 51 | 1.200 0.5736 0.01976 0.01204 -0.1056 0.8087 1.0000 52 | 1.300 0.5828 0.02015 0.01243 -0.1059 0.8045 1.0000 53 | 1.400 0.5930 0.02037 0.01264 -0.1059 0.8011 1.0000 54 | 1.500 0.6041 0.02048 0.01273 -0.1057 0.7986 1.0000 55 | 1.600 0.6154 0.02054 0.01276 -0.1054 0.7966 1.0000 56 | 1.700 0.6248 0.02092 0.01314 -0.1056 0.7928 1.0000 57 | 1.800 0.6348 0.02119 0.01341 -0.1057 0.7893 1.0000 58 | 1.900 0.6457 0.02131 0.01354 -0.1055 0.7867 1.0000 59 | 2.000 0.6570 0.02137 0.01357 -0.1052 0.7846 1.0000 60 | 2.100 0.6667 0.02171 0.01391 -0.1053 0.7812 1.0000 61 | 2.200 0.6763 0.02204 0.01426 -0.1054 0.7774 1.0000 62 | 2.300 0.6871 0.02218 0.01439 -0.1052 0.7746 1.0000 63 | 2.400 0.6983 0.02223 0.01443 -0.1049 0.7725 1.0000 64 | 2.500 0.7083 0.02250 0.01471 -0.1049 0.7695 1.0000 65 | 2.600 0.7175 0.02292 0.01515 -0.1051 0.7653 1.0000 66 | 2.700 0.7282 0.02305 0.01529 -0.1049 0.7625 1.0000 67 | 2.800 0.7394 0.02309 0.01531 -0.1045 0.7603 1.0000 68 | 2.900 0.7494 0.02335 0.01562 -0.1044 0.7572 1.0000 69 | 3.000 0.7584 0.02378 0.01609 -0.1046 0.7528 1.0000 70 | 3.100 0.7691 0.02389 0.01620 -0.1043 0.7499 1.0000 71 | 3.200 0.7804 0.02389 0.01619 -0.1038 0.7476 1.0000 72 | 3.300 0.7896 0.02428 0.01661 -0.1039 0.7437 1.0000 73 | 3.400 0.7990 0.02461 0.01697 -0.1039 0.7396 1.0000 74 | 3.500 0.8099 0.02464 0.01701 -0.1034 0.7368 1.0000 75 | 3.600 0.8213 0.02456 0.01692 -0.1028 0.7346 1.0000 76 | 3.700 0.8292 0.02516 0.01758 -0.1031 0.7292 1.0000 77 | 3.800 0.8396 0.02523 0.01767 -0.1027 0.7255 1.0000 78 | 3.900 0.8510 0.02505 0.01752 -0.1019 0.7228 1.0000 79 | 4.000 0.8591 0.02546 0.01799 -0.1018 0.7172 1.0000 80 | 4.100 0.8695 0.02542 0.01796 -0.1012 0.7129 1.0000 81 | 4.200 0.8810 0.02512 0.01764 -0.1002 0.7100 1.0000 82 | 4.300 0.8887 0.02559 0.01818 -0.1002 0.7036 1.0000 83 | 4.400 0.8995 0.02546 0.01806 -0.0994 0.6998 1.0000 84 | 4.500 0.9112 0.02517 0.01775 -0.0985 0.6972 1.0000 85 | 4.600 0.9187 0.02575 0.01842 -0.0987 0.6906 1.0000 86 | 4.700 0.9296 0.02564 0.01834 -0.0980 0.6871 1.0000 87 | 4.800 0.9414 0.02542 0.01811 -0.0973 0.6848 1.0000 88 | 5.000 0.9598 0.02594 0.01875 -0.0969 0.6748 1.0000 89 | 5.100 0.9717 0.02568 0.01853 -0.0961 0.6724 1.0000 90 | 5.300 0.9903 0.02610 0.01908 -0.0955 0.6620 1.0000 91 | 5.400 0.9998 0.02619 0.01923 -0.0950 0.6569 1.0000 92 | 5.500 1.0096 0.02612 0.01921 -0.0943 0.6511 1.0000 93 | 5.600 1.0221 0.02551 0.01855 -0.0931 0.6476 1.0000 94 | 5.700 1.0295 0.02575 0.01891 -0.0927 0.6392 1.0000 95 | 5.800 1.0413 0.02518 0.01830 -0.0915 0.6343 1.0000 96 | 5.900 1.0499 0.02511 0.01832 -0.0908 0.6261 1.0000 97 | 6.000 1.0598 0.02484 0.01808 -0.0899 0.6194 1.0000 98 | 6.100 1.0705 0.02445 0.01769 -0.0890 0.6128 1.0000 99 | 6.200 1.0796 0.02434 0.01765 -0.0883 0.6050 1.0000 100 | 6.300 1.0913 0.02379 0.01712 -0.0873 0.5992 1.0000 101 | 6.400 1.0999 0.02374 0.01718 -0.0866 0.5905 1.0000 102 | 6.500 1.1110 0.02333 0.01676 -0.0858 0.5843 1.0000 103 | 6.600 1.1205 0.02315 0.01665 -0.0851 0.5761 1.0000 104 | 6.700 1.1298 0.02301 0.01659 -0.0844 0.5678 1.0000 105 | 6.800 1.1417 0.02253 0.01609 -0.0836 0.5615 1.0000 106 | 6.900 1.1502 0.02244 0.01612 -0.0829 0.5516 1.0000 107 | 7.000 1.1595 0.02224 0.01601 -0.0822 0.5420 1.0000 108 | 7.100 1.1693 0.02193 0.01575 -0.0814 0.5321 1.0000 109 | 7.200 1.1789 0.02159 0.01545 -0.0805 0.5213 1.0000 110 | 7.300 1.1880 0.02127 0.01521 -0.0796 0.5087 1.0000 111 | 7.400 1.1965 0.02097 0.01499 -0.0787 0.4940 1.0000 112 | 7.500 1.2050 0.02057 0.01461 -0.0777 0.4767 1.0000 113 | 7.600 1.2118 0.02025 0.01440 -0.0765 0.4529 1.0000 114 | 7.700 1.2175 0.02003 0.01418 -0.0752 0.4195 1.0000 115 | 7.800 1.2217 0.02007 0.01403 -0.0738 0.3744 1.0000 116 | 7.900 1.2234 0.02059 0.01418 -0.0724 0.3208 1.0000 117 | 8.000 1.2233 0.02152 0.01468 -0.0710 0.2748 1.0000 118 | 8.100 1.2227 0.02261 0.01542 -0.0696 0.2392 1.0000 119 | 8.200 1.2222 0.02371 0.01625 -0.0683 0.2104 1.0000 120 | 8.300 1.2217 0.02480 0.01712 -0.0670 0.1860 1.0000 121 | 8.400 1.2208 0.02592 0.01804 -0.0657 0.1637 1.0000 122 | 8.500 1.2186 0.02714 0.01906 -0.0641 0.1423 1.0000 123 | 9.000 1.2117 0.03330 0.02451 -0.0564 0.0811 1.0000 124 | -------------------------------------------------------------------------------- /runs/la203.bl: -------------------------------------------------------------------------------- 1 | # s x y Ue/Vinf Dstar Theta Cf H 2 | 0.00000 1.00000 0.00000********* 0.000000 0.000000 0.000000 1.000 3 | 0.00678 0.99394 0.00304 5.27909 0.000000 0.000000 0.000000 1.000 4 | 0.01507 0.98615 0.00588 0.66356 0.000000 0.000000 0.000000 1.000 5 | 0.02505 0.97667 0.00898 1.02369 0.000000 0.000000 0.000000 1.000 6 | 0.03671 0.96552 0.01241 0.98680 0.000000 0.000000 0.000000 1.000 7 | 0.05003 0.95274 0.01616 1.00600 0.000000 0.000000 0.000000 1.000 8 | 0.06496 0.93839 0.02026 1.01642 0.000000 0.000000 0.000000 1.000 9 | 0.08145 0.92250 0.02470 1.02850 0.000000 0.000000 0.000000 1.000 10 | 0.09946 0.90514 0.02949 1.04043 0.000000 0.000000 0.000000 1.000 11 | 0.11892 0.88637 0.03463 1.05326 0.000000 0.000000 0.000000 1.000 12 | 0.13978 0.86625 0.04011 1.06653 0.000000 0.000000 0.000000 1.000 13 | 0.16195 0.84486 0.04594 1.08119 0.000000 0.000000 0.000000 1.000 14 | 0.18537 0.82226 0.05209 1.09721 0.000000 0.000000 0.000000 1.000 15 | 0.20995 0.79854 0.05854 1.11490 0.000000 0.000000 0.000000 1.000 16 | 0.23560 0.77379 0.06529 1.13482 0.000000 0.000000 0.000000 1.000 17 | 0.26224 0.74809 0.07229 1.15776 0.000000 0.000000 0.000000 1.000 18 | 0.28977 0.72152 0.07949 1.18501 0.000000 0.000000 0.000000 1.000 19 | 0.31805 0.69419 0.08680 1.21576 0.000000 0.000000 0.000000 1.000 20 | 0.34698 0.66619 0.09406 1.25083 0.000000 0.000000 0.000000 1.000 21 | 0.37640 0.63762 0.10109 1.28741 0.000000 0.000000 0.000000 1.000 22 | 0.40618 0.60858 0.10764 1.32053 0.000000 0.000000 0.000000 1.000 23 | 0.43618 0.57917 0.11357 1.34930 0.000000 0.000000 0.000000 1.000 24 | 0.46631 0.54949 0.11877 1.37478 0.000000 0.000000 0.000000 1.000 25 | 0.49647 0.51965 0.12318 1.39617 0.000000 0.000000 0.000000 1.000 26 | 0.52658 0.48976 0.12674 1.41457 0.000000 0.000000 0.000000 1.000 27 | 0.55654 0.45992 0.12944 1.43028 0.000000 0.000000 0.000000 1.000 28 | 0.58628 0.43023 0.13122 1.44179 0.000000 0.000000 0.000000 1.000 29 | 0.61573 0.40080 0.13209 1.44937 0.000000 0.000000 0.000000 1.000 30 | 0.64479 0.37173 0.13207 1.45518 0.000000 0.000000 0.000000 1.000 31 | 0.67341 0.34313 0.13118 1.45792 0.000000 0.000000 0.000000 1.000 32 | 0.70150 0.31509 0.12943 1.45827 0.000000 0.000000 0.000000 1.000 33 | 0.72900 0.28772 0.12685 1.45747 0.000000 0.000000 0.000000 1.000 34 | 0.75583 0.26111 0.12342 1.44864 0.000000 0.000000 0.000000 1.000 35 | 0.78192 0.23535 0.11923 1.43613 0.000000 0.000000 0.000000 1.000 36 | 0.80720 0.21054 0.11439 1.42239 0.000000 0.000000 0.000000 1.000 37 | 0.83159 0.18676 0.10897 1.40732 0.000000 0.000000 0.000000 1.000 38 | 0.85502 0.16409 0.10305 1.39083 0.000000 0.000000 0.000000 1.000 39 | 0.87741 0.14263 0.09669 1.37245 0.000000 0.000000 0.000000 1.000 40 | 0.89869 0.12243 0.08996 1.35194 0.000000 0.000000 0.000000 1.000 41 | 0.91882 0.10358 0.08292 1.32911 0.000000 0.000000 0.000000 1.000 42 | 0.93772 0.08614 0.07564 1.30309 0.000000 0.000000 0.000000 1.000 43 | 0.95534 0.07016 0.06819 1.27319 0.000000 0.000000 0.000000 1.000 44 | 0.97165 0.05572 0.06064 1.23879 0.000000 0.000000 0.000000 1.000 45 | 0.98659 0.04285 0.05305 1.19811 0.000000 0.000000 0.000000 1.000 46 | 1.00014 0.03160 0.04549 1.14953 0.000000 0.000000 0.000000 1.000 47 | 1.01228 0.02201 0.03803 1.09034 0.000000 0.000000 0.000000 1.000 48 | 1.02307 0.01413 0.03068 1.01356 0.000000 0.000000 0.000000 1.000 49 | 1.03265 0.00796 0.02334 0.89499 0.000000 0.000000 0.000000 1.000 50 | 1.04136 0.00354 0.01584 0.70021 0.000000 0.000000 0.000000 1.000 51 | 1.04963 0.00089 0.00800 0.41358 0.000000 0.000000 0.000000 1.000 52 | 1.05768 0.00000 0.00000 0.07437 0.000000 0.000000 0.000000 1.000 53 | 1.06575 0.00089 -0.00802 -0.30981 0.000000 0.000000 0.000000 1.000 54 | 1.07335 0.00354 -0.01514 -0.67584 0.000000 0.000000 0.000000 1.000 55 | 1.08113 0.00796 -0.02154 -1.03868 0.000000 0.000000 0.000000 1.000 56 | 1.08905 0.01413 -0.02652 -1.30412 0.000000 0.000000 0.000000 1.000 57 | 1.09753 0.02201 -0.02964 -1.31181 0.000000 0.000000 0.000000 1.000 58 | 1.10726 0.03160 -0.03132 -1.21396 0.000000 0.000000 0.000000 1.000 59 | 1.11854 0.04285 -0.03221 -1.14228 0.000000 0.000000 0.000000 1.000 60 | 1.13142 0.05572 -0.03268 -1.09742 0.000000 0.000000 0.000000 1.000 61 | 1.14587 0.07016 -0.03287 -1.06685 0.000000 0.000000 0.000000 1.000 62 | 1.16184 0.08614 -0.03286 -1.04468 0.000000 0.000000 0.000000 1.000 63 | 1.17929 0.10358 -0.03269 -1.02851 0.000000 0.000000 0.000000 1.000 64 | 1.19814 0.12243 -0.03241 -1.01642 0.000000 0.000000 0.000000 1.000 65 | 1.21834 0.14263 -0.03202 -1.00732 0.000000 0.000000 0.000000 1.000 66 | 1.23981 0.16409 -0.03156 -1.00034 0.000000 0.000000 0.000000 1.000 67 | 1.26248 0.18676 -0.03102 -0.99532 0.000000 0.000000 0.000000 1.000 68 | 1.28627 0.21054 -0.03041 -0.99147 0.000000 0.000000 0.000000 1.000 69 | 1.31109 0.23535 -0.02972 -0.98880 0.000000 0.000000 0.000000 1.000 70 | 1.33686 0.26111 -0.02897 -0.98680 0.000000 0.000000 0.000000 1.000 71 | 1.36348 0.28772 -0.02812 -0.98556 0.000000 0.000000 0.000000 1.000 72 | 1.39087 0.31509 -0.02718 -0.98480 0.000000 0.000000 0.000000 1.000 73 | 1.41893 0.34313 -0.02612 -0.98446 0.000000 0.000000 0.000000 1.000 74 | 1.44756 0.37173 -0.02492 -0.98473 0.000000 0.000000 0.000000 1.000 75 | 1.47666 0.40080 -0.02351 -0.98475 0.000000 0.000000 0.000000 1.000 76 | 1.50614 0.43023 -0.02183 -0.98213 0.000000 0.000000 0.000000 1.000 77 | 1.53589 0.45992 -0.01983 -0.97642 0.000000 0.000000 0.000000 1.000 78 | 1.56583 0.48976 -0.01753 -0.96882 0.000000 0.000000 0.000000 1.000 79 | 1.59583 0.51965 -0.01495 -0.95900 0.000000 0.000000 0.000000 1.000 80 | 1.62580 0.54949 -0.01210 -0.94609 0.000000 0.000000 0.000000 1.000 81 | 1.65564 0.57917 -0.00905 -0.93071 0.000000 0.000000 0.000000 1.000 82 | 1.68522 0.60858 -0.00592 -0.91406 0.000000 0.000000 0.000000 1.000 83 | 1.71442 0.63762 -0.00282 -0.89802 0.000000 0.000000 0.000000 1.000 84 | 1.74315 0.66619 0.00014 -0.88328 0.000000 0.000000 0.000000 1.000 85 | 1.77129 0.69419 0.00292 -0.86902 0.000000 0.000000 0.000000 1.000 86 | 1.79873 0.72152 0.00545 -0.85540 0.000000 0.000000 0.000000 1.000 87 | 1.82539 0.74809 0.00769 -0.84247 0.000000 0.000000 0.000000 1.000 88 | 1.85116 0.77379 0.00959 -0.83037 0.000000 0.000000 0.000000 1.000 89 | 1.87597 0.79854 0.01115 -0.81896 0.000000 0.000000 0.000000 1.000 90 | 1.89971 0.82226 0.01231 -0.80866 0.000000 0.000000 0.000000 1.000 91 | 1.92232 0.84486 0.01309 -0.79895 0.000000 0.000000 0.000000 1.000 92 | 1.94372 0.86625 0.01346 -0.79065 0.000000 0.000000 0.000000 1.000 93 | 1.96384 0.88637 0.01345 -0.78324 0.000000 0.000000 0.000000 1.000 94 | 1.98261 0.90514 0.01306 -0.77687 0.000000 0.000000 0.000000 1.000 95 | 1.99999 0.92250 0.01230 -0.77234 0.000000 0.000000 0.000000 1.000 96 | 2.01591 0.93839 0.01122 -0.77013 0.000000 0.000000 0.000000 1.000 97 | 2.03033 0.95274 0.00984 -0.76862 0.000000 0.000000 0.000000 1.000 98 | 2.04321 0.96552 0.00821 -0.78701 0.000000 0.000000 0.000000 1.000 99 | 2.05451 0.97667 0.00639 -0.74096 0.000000 0.000000 0.000000 1.000 100 | 2.06419 0.98615 0.00443 -1.02456 0.000000 0.000000 0.000000 1.000 101 | 2.07224 0.99394 0.00238 -3.04501 0.000000 0.000000 0.000000 1.000 102 | 2.07876 1.00000 0.00000118.42509 0.000000 0.000000 0.000000 1.000 103 | -------------------------------------------------------------------------------- /runs/la203.dat: -------------------------------------------------------------------------------- 1 | LA203A 2 | 1.000000 0.000000 3 | 0.993938 0.003044 4 | 0.986151 0.005883 5 | 0.976665 0.008985 6 | 0.965516 0.012408 7 | 0.952740 0.016162 8 | 0.938385 0.020258 9 | 0.922500 0.024700 10 | 0.905141 0.029490 11 | 0.886369 0.034630 12 | 0.866250 0.040113 13 | 0.844856 0.045936 14 | 0.822261 0.052086 15 | 0.798545 0.058545 16 | 0.773791 0.065291 17 | 0.748087 0.072292 18 | 0.721524 0.079495 19 | 0.694194 0.086797 20 | 0.666193 0.094063 21 | 0.637621 0.101087 22 | 0.608579 0.107640 23 | 0.579167 0.113566 24 | 0.549490 0.118770 25 | 0.519653 0.123176 26 | 0.489759 0.126743 27 | 0.459916 0.129436 28 | 0.430226 0.131219 29 | 0.400796 0.132090 30 | 0.371729 0.132075 31 | 0.343127 0.131182 32 | 0.315090 0.129435 33 | 0.287716 0.126854 34 | 0.261106 0.123424 35 | 0.235350 0.119234 36 | 0.210538 0.114389 37 | 0.186758 0.108970 38 | 0.164095 0.103048 39 | 0.142628 0.096688 40 | 0.122432 0.089956 41 | 0.103579 0.082919 42 | 0.086135 0.075641 43 | 0.070162 0.068190 44 | 0.055715 0.060636 45 | 0.042846 0.053047 46 | 0.031599 0.045492 47 | 0.022015 0.038031 48 | 0.014127 0.030677 49 | 0.007963 0.023336 50 | 0.003544 0.015836 51 | 0.000887 0.008000 52 | 0.000000 0.000000 53 | 0.000887 -0.008018 54 | 0.003544 -0.015138 55 | 0.007963 -0.021544 56 | 0.014127 -0.026519 57 | 0.022015 -0.029639 58 | 0.031599 -0.031320 59 | 0.042846 -0.032209 60 | 0.055715 -0.032676 61 | 0.070162 -0.032868 62 | 0.086135 -0.032857 63 | 0.103579 -0.032693 64 | 0.122432 -0.032408 65 | 0.142628 -0.032024 66 | 0.164095 -0.031556 67 | 0.186758 -0.031016 68 | 0.210538 -0.030405 69 | 0.235350 -0.029724 70 | 0.261106 -0.028966 71 | 0.287716 -0.028124 72 | 0.315090 -0.027183 73 | 0.343127 -0.026124 74 | 0.371729 -0.024919 75 | 0.400796 -0.023512 76 | 0.430226 -0.021827 77 | 0.459916 -0.019830 78 | 0.489759 -0.017533 79 | 0.519653 -0.014948 80 | 0.549490 -0.012098 81 | 0.579167 -0.009052 82 | 0.608579 -0.005918 83 | 0.637621 -0.002821 84 | 0.666193 0.000143 85 | 0.694194 0.002917 86 | 0.721524 0.005447 87 | 0.748087 0.007686 88 | 0.773791 0.009595 89 | 0.798545 0.011145 90 | 0.822261 0.012312 91 | 0.844856 0.013088 92 | 0.866250 0.013463 93 | 0.886369 0.013448 94 | 0.905141 0.013056 95 | 0.922500 0.012302 96 | 0.938385 0.011218 97 | 0.952740 0.009838 98 | 0.965516 0.008212 99 | 0.976665 0.006393 100 | 0.986151 0.004425 101 | 0.993938 0.002384 102 | 1.000000 0.000000 103 | 104 | -------------------------------------------------------------------------------- /runs/la203t.dat: -------------------------------------------------------------------------------- 1 | LA230A blunt TE 2 | 1.000455 0.000895 3 | 0.993427 0.004332 4 | 0.981492 0.008450 5 | 0.967879 0.012697 6 | 0.952291 0.017269 7 | 0.934612 0.022276 8 | 0.914876 0.027744 9 | 0.893349 0.033633 10 | 0.870451 0.039856 11 | 0.846614 0.046320 12 | 0.822246 0.052928 13 | 0.797640 0.059604 14 | 0.773000 0.066294 15 | 0.748527 0.072935 16 | 0.724456 0.079441 17 | 0.700950 0.085719 18 | 0.678100 0.091696 19 | 0.655966 0.097294 20 | 0.634488 0.102460 21 | 0.613509 0.107185 22 | 0.592872 0.111482 23 | 0.572474 0.115369 24 | 0.552260 0.118854 25 | 0.532181 0.121940 26 | 0.512197 0.124633 27 | 0.492299 0.126938 28 | 0.472493 0.128851 29 | 0.452778 0.130366 30 | 0.433139 0.131481 31 | 0.413556 0.132197 32 | 0.394032 0.132519 33 | 0.374603 0.132449 34 | 0.355296 0.131983 35 | 0.336122 0.131120 36 | 0.317102 0.129862 37 | 0.298297 0.128215 38 | 0.279735 0.126157 39 | 0.261354 0.123677 40 | 0.243142 0.120790 41 | 0.225156 0.117523 42 | 0.207483 0.113902 43 | 0.190225 0.109959 44 | 0.173498 0.105734 45 | 0.157428 0.101275 46 | 0.142137 0.096640 47 | 0.127740 0.091896 48 | 0.114330 0.087111 49 | 0.101967 0.082352 50 | 0.090672 0.077676 51 | 0.080423 0.073127 52 | 0.071170 0.068734 53 | 0.062842 0.064514 54 | 0.055354 0.060471 55 | 0.048621 0.056601 56 | 0.042561 0.052894 57 | 0.037097 0.049337 58 | 0.032164 0.045916 59 | 0.027702 0.042615 60 | 0.023663 0.039417 61 | 0.020007 0.036305 62 | 0.016704 0.033262 63 | 0.013731 0.030267 64 | 0.011068 0.027303 65 | 0.008710 0.024356 66 | 0.006648 0.021414 67 | 0.004880 0.018473 68 | 0.003404 0.015529 69 | 0.002211 0.012581 70 | 0.001291 0.009644 71 | 0.000631 0.006741 72 | 0.000216 0.003893 73 | 0.000020 0.001100 74 | 0.000029 -0.001660 75 | 0.000247 -0.004414 76 | 0.000696 -0.007167 77 | 0.001403 -0.009910 78 | 0.002374 -0.012614 79 | 0.003602 -0.015256 80 | 0.005087 -0.017812 81 | 0.006845 -0.020249 82 | 0.008898 -0.022529 83 | 0.011262 -0.024606 84 | 0.013938 -0.026425 85 | 0.016933 -0.027936 86 | 0.020241 -0.029152 87 | 0.023844 -0.030106 88 | 0.027745 -0.030836 89 | 0.031980 -0.031393 90 | 0.036588 -0.031834 91 | 0.041629 -0.032180 92 | 0.047184 -0.032454 93 | 0.053351 -0.032666 94 | 0.060260 -0.032819 95 | 0.068071 -0.032916 96 | 0.076988 -0.032954 97 | 0.087263 -0.032928 98 | 0.099188 -0.032834 99 | 0.113069 -0.032661 100 | 0.129156 -0.032402 101 | 0.147544 -0.032052 102 | 0.168081 -0.031613 103 | 0.190368 -0.031094 104 | 0.213899 -0.030504 105 | 0.238204 -0.029853 106 | 0.262922 -0.029142 107 | 0.287810 -0.028374 108 | 0.312695 -0.027544 109 | 0.337469 -0.026643 110 | 0.362036 -0.025661 111 | 0.386318 -0.024578 112 | 0.410302 -0.023356 113 | 0.434088 -0.021960 114 | 0.457807 -0.020377 115 | 0.481536 -0.018608 116 | 0.505316 -0.016656 117 | 0.529216 -0.014513 118 | 0.553344 -0.012183 119 | 0.577787 -0.009687 120 | 0.602567 -0.007073 121 | 0.627482 -0.004428 122 | 0.652205 -0.001848 123 | 0.676637 0.000620 124 | 0.700697 0.002939 125 | 0.724337 0.005075 126 | 0.747521 0.006998 127 | 0.770218 0.008681 128 | 0.792379 0.010100 129 | 0.813952 0.011230 130 | 0.834872 0.012054 131 | 0.855042 0.012555 132 | 0.874384 0.012720 133 | 0.892795 0.012552 134 | 0.910177 0.012048 135 | 0.926478 0.011213 136 | 0.941673 0.010057 137 | 0.955776 0.008580 138 | 0.968861 0.006778 139 | 0.980995 0.004570 140 | 0.992375 0.001840 141 | 0.999545 -0.000895 142 | -------------------------------------------------------------------------------- /runs/lnv109a.dat: -------------------------------------------------------------------------------- 1 | LNV-109A 2 | 1.000000 0.000000 3 | 0.993938 0.000543 4 | 0.986151 0.001101 5 | 0.976665 0.001787 6 | 0.965515 0.002657 7 | 0.952740 0.003737 8 | 0.938385 0.005056 9 | 0.922500 0.006639 10 | 0.905141 0.008509 11 | 0.886369 0.010690 12 | 0.866250 0.013204 13 | 0.844856 0.016069 14 | 0.822261 0.019300 15 | 0.798545 0.022912 16 | 0.773791 0.026914 17 | 0.748087 0.031312 18 | 0.721524 0.036110 19 | 0.694194 0.041303 20 | 0.666193 0.046886 21 | 0.637621 0.052846 22 | 0.608579 0.059164 23 | 0.579167 0.065813 24 | 0.549490 0.072756 25 | 0.519653 0.079934 26 | 0.489759 0.087276 27 | 0.459916 0.094701 28 | 0.430226 0.102116 29 | 0.400796 0.109249 30 | 0.371729 0.115295 31 | 0.343127 0.119496 32 | 0.315090 0.121941 33 | 0.287718 0.122784 34 | 0.261106 0.122185 35 | 0.235350 0.120264 36 | 0.210538 0.117155 37 | 0.186758 0.113001 38 | 0.164095 0.107922 39 | 0.142628 0.102024 40 | 0.122432 0.095430 41 | 0.103579 0.088284 42 | 0.086135 0.080712 43 | 0.070162 0.072825 44 | 0.055715 0.064730 45 | 0.042846 0.056528 46 | 0.031599 0.048318 47 | 0.022015 0.040194 48 | 0.014127 0.032222 49 | 0.007963 0.024369 50 | 0.003544 0.016413 51 | 0.000887 0.008081 52 | 0.000000 0.000000 53 | 0.000887 -.008081 54 | 0.003544 -.015530 55 | 0.007963 -.022138 56 | 0.014127 -.027272 57 | 0.022015 -.030455 58 | 0.031599 -.031544 59 | 0.042846 -.031202 60 | 0.055715 -.030105 61 | 0.070162 -.028554 62 | 0.086135 -.026666 63 | 0.103579 -.024529 64 | 0.122432 -.022211 65 | 0.142628 -.019767 66 | 0.164095 -.017246 67 | 0.186758 -.014689 68 | 0.210538 -.012132 69 | 0.235350 -.009608 70 | 0.261106 -.007151 71 | 0.287718 -.004782 72 | 0.315090 -.002532 73 | 0.343127 -.000425 74 | 0.371729 0.001516 75 | 0.400796 0.003265 76 | 0.430226 0.004793 77 | 0.459916 0.006064 78 | 0.489759 0.006997 79 | 0.519653 0.007552 80 | 0.549490 0.007802 81 | 0.579167 0.007826 82 | 0.608579 0.007672 83 | 0.637621 0.007376 84 | 0.666193 0.006968 85 | 0.694194 0.006477 86 | 0.721524 0.005927 87 | 0.748087 0.005340 88 | 0.773791 0.004735 89 | 0.798545 0.004130 90 | 0.822261 0.003538 91 | 0.844856 0.002973 92 | 0.866250 0.002443 93 | 0.886369 0.001955 94 | 0.905141 0.001515 95 | 0.922500 0.001126 96 | 0.938385 0.000789 97 | 0.952740 0.000505 98 | 0.965515 0.000273 99 | 0.976665 0.000093 100 | 0.986151 -.000038 101 | 0.993938 -.000097 102 | 1.000000 0.000000 103 | -------------------------------------------------------------------------------- /runs/polref_100.387: -------------------------------------------------------------------------------- 1 | # Langley LTPT 2 | 0.0201 0.098 | Eppler 387 polar Re=100000 Langley LTPT 3 | 0.0201 0.101 4 | 0.0168 0.199 5 | 0.0164 0.289 6 | 0.0155 0.289 7 | 0.0173 0.392 8 | 0.0189 0.491 9 | 0.0218 0.589 10 | 0.0216 0.589 11 | 0.0238 0.686 12 | 0.0241 0.786 13 | 0.0241 0.880 14 | 0.0234 0.880 15 | 0.0237 0.880 16 | 0.0230 0.978 17 | 0.0232 0.978 18 | 0.0225 1.029 19 | 0.0219 1.029 20 | 0.0214 1.077 21 | 0.0212 1.077 22 | 0.0212 1.179 23 | 0.0207 1.179 24 | 0.0246 1.190 25 | 0.0285 1.199 26 | 0.0505 1.205 27 | 999. 999. 28 | -2.97 0.098 29 | -2.97 0.101 30 | -2.01 0.199 31 | -1.00 0.289 32 | -1.00 0.289 33 | 0.00 0.392 34 | 1.00 0.491 35 | 2.00 0.589 36 | 2.00 0.589 37 | 3.00 0.686 38 | 4.02 0.786 39 | 5.00 0.880 40 | 5.00 0.880 41 | 5.00 0.880 42 | 6.01 0.978 43 | 6.01 0.978 44 | 6.52 1.029 45 | 6.52 1.029 46 | 7.01 1.077 47 | 7.01 1.077 48 | 8.02 1.179 49 | 8.02 1.179 50 | 8.52 1.190 51 | 9.02 1.199 52 | 11.02 1.205 53 | 12.04 1.194 54 | 999. 999. 55 | -2.97 -0.1002 56 | -2.97 -0.1005 57 | -2.01 -0.0994 58 | -1.00 -0.0955 59 | -1.00 -0.0955 60 | 0.00 -0.0971 61 | 1.00 -0.0972 62 | 2.00 -0.0983 63 | 2.00 -0.0983 64 | 3.00 -0.0983 65 | 4.02 -0.0943 66 | 5.00 -0.0879 67 | 5.00 -0.0879 68 | 5.00 -0.0879 69 | 6.01 -0.0835 70 | 6.01 -0.0835 71 | 6.52 -0.0814 72 | 6.52 -0.0814 73 | 7.01 -0.0786 74 | 7.01 -0.0786 75 | 8.02 -0.0752 76 | 8.02 -0.0752 77 | 8.52 -0.0717 78 | 9.02 -0.0674 79 | 11.02 -0.0549 80 | 12.04 -0.0509 81 | 999. 999. 82 | 999. 999. 83 | -------------------------------------------------------------------------------- /runs/tad.dat: -------------------------------------------------------------------------------- 1 | me993ym 2 | 1.000000 -1.663260 3 | 0.9963190 -1.657740 4 | 0.9923760 -1.652410 5 | 0.9881520 -1.647300 6 | 0.9836010 -1.642480 7 | 0.9788250 -1.637880 8 | 0.9739550 -1.633390 9 | 0.9689880 -1.628990 10 | 0.9639510 -1.624680 11 | 0.9588620 -1.620430 12 | 0.9537280 -1.616240 13 | 0.9485550 -1.612090 14 | 0.9433500 -1.607980 15 | 0.9381160 -1.603910 16 | 0.9328550 -1.599880 17 | 0.9275730 -1.595870 18 | 0.9222710 -1.591890 19 | 0.9169450 -1.587940 20 | 0.9116010 -1.584020 21 | 0.9062440 -1.580110 22 | 0.9008700 -1.576230 23 | 0.8954800 -1.572370 24 | 0.8900780 -1.568530 25 | 0.8846650 -1.564700 26 | 0.8792370 -1.560890 27 | 0.8737950 -1.557100 28 | 0.8628800 -1.549570 29 | 0.8574070 -1.545830 30 | 0.8519240 -1.542100 31 | 0.8464320 -1.538390 32 | 0.8409280 -1.534690 33 | 0.8354140 -1.531010 34 | 0.8298910 -1.527350 35 | 0.8243610 -1.523690 36 | 0.8188240 -1.520040 37 | 0.8132780 -1.516410 38 | 0.8077220 -1.512790 39 | 0.8021580 -1.509180 40 | 0.7965880 -1.505590 41 | 0.7910120 -1.502000 42 | 0.7854280 -1.498430 43 | 0.7798360 -1.494860 44 | 0.7742380 -1.491310 45 | 0.7686350 -1.487770 46 | 0.7630270 -1.484230 47 | 0.7574120 -1.480710 48 | 0.7517890 -1.477190 49 | 0.7461580 -1.473690 50 | 0.7405200 -1.470210 51 | 0.7348750 -1.466730 52 | 0.7292220 -1.463260 53 | 0.7235610 -1.459810 54 | 0.7178890 -1.456380 55 | 0.7122060 -1.452970 56 | 0.7065110 -1.449570 57 | 0.7008030 -1.446200 58 | 0.6950810 -1.442850 59 | 0.6893410 -1.439530 60 | 0.6835860 -1.436240 61 | 0.6778160 -1.432970 62 | 0.6720270 -1.429740 63 | 0.6662170 -1.426550 64 | 0.6603850 -1.423390 65 | 0.6545330 -1.420280 66 | 0.6486610 -1.417200 67 | 0.6427690 -1.414160 68 | 0.6368650 -1.411140 69 | 0.6309560 -1.408140 70 | 0.6250400 -1.405140 71 | 0.6191170 -1.402160 72 | 0.6131850 -1.399200 73 | 0.6072410 -1.396270 74 | 0.6012850 -1.393350 75 | 0.5953140 -1.390470 76 | 0.5893260 -1.387630 77 | 0.5833180 -1.384820 78 | 0.5772900 -1.382060 79 | 0.5712390 -1.379350 80 | 0.5651720 -1.376680 81 | 0.5591060 -1.374000 82 | 0.5530440 -1.371320 83 | 0.5469830 -1.368630 84 | 0.5409210 -1.365940 85 | 0.5348560 -1.363270 86 | 0.5287810 -1.360610 87 | 0.5226900 -1.357990 88 | 0.5165750 -1.355430 89 | 0.5104230 -1.352960 90 | 0.5042240 -1.350610 91 | 0.4979660 -1.348420 92 | 0.4916450 -1.346420 93 | 0.4852640 -1.344620 94 | 0.4788290 -1.343020 95 | 0.4723530 -1.341600 96 | 0.4658470 -1.340330 97 | 0.4593150 -1.339190 98 | 0.4527520 -1.338250 99 | 0.4461500 -1.337640 100 | 0.4395190 -1.337560 101 | 0.4329310 -1.338300 102 | 0.4266160 -1.340270 103 | 0.4211230 -1.343940 104 | 0.4171770 -1.349230 105 | 0.4148200 -1.355420 106 | 0.4141470 -1.361990 107 | 0.4159600 -1.368320 108 | 0.4201320 -1.373430 109 | 0.4256470 -1.377080 110 | 0.4317250 -1.379730 111 | 0.4380560 -1.381700 112 | 0.4445110 -1.383210 113 | 0.4510340 -1.384390 114 | 0.4575970 -1.385340 115 | 0.4641820 -1.386100 116 | 0.4707820 -1.386730 117 | 0.4840060 -1.387710 118 | 0.4906250 -1.388100 119 | 0.4972460 -1.388450 120 | 0.5038680 -1.388770 121 | 0.5104900 -1.389080 122 | 0.5171130 -1.389390 123 | 0.5237350 -1.389720 124 | 0.5303560 -1.390060 125 | 0.5369750 -1.390450 126 | 0.5435910 -1.390880 127 | 0.5502020 -1.391380 128 | 0.5568070 -1.391950 129 | 0.5634040 -1.392620 130 | 0.5699870 -1.393400 131 | 0.5765520 -1.394330 132 | 0.5830910 -1.395420 133 | 0.5895930 -1.396720 134 | 0.5960380 -1.398280 135 | 0.6023990 -1.400140 136 | 0.6086350 -1.402400 137 | 0.6146660 -1.405150 138 | 0.6205920 -1.408120 139 | 0.6265110 -1.411110 140 | 0.6324210 -1.414120 141 | 0.6383260 -1.417130 142 | 0.6442210 -1.420170 143 | 0.6501000 -1.423230 144 | 0.6559590 -1.426330 145 | 0.6676120 -1.432660 146 | 0.6734070 -1.435880 147 | 0.6791830 -1.439140 148 | 0.6849410 -1.442420 149 | 0.6906820 -1.445740 150 | 0.6964080 -1.449080 151 | 0.7021190 -1.452450 152 | 0.7078170 -1.455840 153 | 0.7135020 -1.459250 154 | 0.7191760 -1.462680 155 | 0.7248400 -1.466130 156 | 0.7304950 -1.469590 157 | 0.7361420 -1.473060 158 | 0.7417800 -1.476550 159 | 0.7474110 -1.480050 160 | 0.7530360 -1.483560 161 | 0.7586530 -1.487080 162 | 0.7642640 -1.490610 163 | 0.7698680 -1.494160 164 | 0.7754670 -1.497710 165 | 0.7810590 -1.501270 166 | 0.7866440 -1.504840 167 | 0.7922230 -1.508420 168 | 0.7977950 -1.512020 169 | 0.8033590 -1.515620 170 | 0.8089150 -1.519240 171 | 0.8144640 -1.522870 172 | 0.8200050 -1.526510 173 | 0.8255370 -1.530160 174 | 0.8310600 -1.533830 175 | 0.8365740 -1.537510 176 | 0.8420800 -1.541210 177 | 0.8475750 -1.544920 178 | 0.8530600 -1.548640 179 | 0.8585350 -1.552380 180 | 0.8640000 -1.556130 181 | 0.8694530 -1.559900 182 | 0.8748950 -1.563690 183 | 0.8803250 -1.567500 184 | 0.8857420 -1.571320 185 | 0.8911460 -1.575160 186 | 0.8965360 -1.579020 187 | 0.9019110 -1.582900 188 | 0.9072710 -1.586800 189 | 0.9126150 -1.590730 190 | 0.9179410 -1.594680 191 | 0.9232480 -1.598650 192 | 0.9285340 -1.602650 193 | 0.9337970 -1.606680 194 | 0.9390350 -1.610750 195 | 0.9442430 -1.614850 196 | 0.9494180 -1.619000 197 | 0.9545560 -1.623190 198 | 0.9596490 -1.627430 199 | 0.9646920 -1.631740 200 | 0.9696590 -1.636130 201 | 0.9745360 -1.640620 202 | 0.9793090 -1.645220 203 | 0.9838610 -1.650040 204 | 0.9880470 -1.655180 205 | 0.9919670 -1.660530 206 | 0.9955810 -1.666090 207 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup, find_packages 2 | 3 | version = '0.0.16' 4 | 5 | def readme(): 6 | with open('README.md') as f: 7 | return f.read() 8 | 9 | setup( 10 | name='xfoil', 11 | version=version, 12 | description='Stripped down version of XFOIL as compiled python module ', 13 | #long_description=readme(), 14 | classifiers=[ 15 | 'Development Status :: 3 - Alpha', 16 | 'Intended Audience :: Science/Research', 17 | 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)', 18 | 'Natural Language :: English', 19 | 'Operating System :: MacOS :: MacOS X', 20 | 'Operating System :: POSIX :: Linux', 21 | 'Operating System :: Microsoft :: Windows', 22 | 'Programming Language :: Fortran', 23 | 'Programming Language :: Python :: 3 :: Only', 24 | 'Topic :: Scientific/Engineering', 25 | ], 26 | keywords='xfoil airfoil aerodynamic analysis', 27 | #url='https://github.com/daniel-de-vries/xfoil-python', 28 | #download_url='https://github.com/daniel-de-vries/xfoil-python/tarball/' + version, 29 | author='Daniël de Vries', 30 | author_email='contact@daniel-de-vries.com', 31 | license='GNU General Public License v3 or later (GPLv3+)', 32 | packages=['xfoil'], 33 | package_dir={'': 'src'}, 34 | #ext_modules=[CMakeExtension('xfoil.xfoil')], 35 | #cmdclass={'build_ext': CMakeBuild}, 36 | install_requires=['numpy'], 37 | #zip_save=False 38 | ) 39 | -------------------------------------------------------------------------------- /src/__init__.py: -------------------------------------------------------------------------------- 1 | from . import xfoil -------------------------------------------------------------------------------- /src/fortran/api.f90: -------------------------------------------------------------------------------- 1 | !*********************************************************************** 2 | ! Copyright (c) 2019 D. de Vries 3 | ! 4 | ! This file is part of XFoil. 5 | ! 6 | ! XFoil is free software: you can redistribute it and/or modify 7 | ! it under the terms of the GNU General Public License as published by 8 | ! the Free Software Foundation, either version 3 of the License, or 9 | ! (at your option) any later version. 10 | ! 11 | ! XFoil is distributed in the hope that it will be useful, 12 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | ! GNU General Public License for more details. 15 | ! 16 | ! You should have received a copy of the GNU General Public License 17 | ! along with XFoil. If not, see . 18 | !*********************************************************************** 19 | 20 | module api 21 | use, intrinsic :: iso_c_binding, only: c_float, c_int, c_bool, c_null_ptr, c_char, c_null_char 22 | implicit none 23 | contains 24 | subroutine set_print(setting) bind(c, name='set_print') 25 | use i_xfoil, only: show_output 26 | logical(c_bool), intent(in) :: setting 27 | show_output = setting 28 | end subroutine set_print 29 | 30 | function get_print() bind(c, name='get_print') 31 | use i_xfoil, only: show_output 32 | logical(c_bool) :: get_print 33 | get_print = show_output 34 | end function get_print 35 | 36 | subroutine set_airfoil(x_in, y_in, n_in) bind(c, name='set_airfoil') 37 | use m_xgeom, only: geopar, norm 38 | use m_spline, only: seval, segspl, scalc 39 | use m_xgdes, only: abcopy 40 | use m_xgeom, only: cang 41 | use i_xfoil 42 | 43 | integer(c_int), intent(in) :: n_in 44 | real(c_float), intent(in) :: x_in(n_in), y_in(n_in) 45 | 46 | ! Local variables 47 | ! 48 | real :: area, xble, xbte, xinl, xout, xtmp, yble, ybot, ybte, ytmp, ytop, amax, angtol 49 | integer :: i, ip, kdot, lu, imax, Itype 50 | 51 | data angtol/40.0/ 52 | 53 | do i=1, n_in 54 | XB(i) = x_in(i) 55 | YB(i) = y_in(i) 56 | end do 57 | NB = n_in 58 | 59 | !---- calculate airfoil area assuming counterclockwise ordering 60 | area = 0.0 61 | do i = 1, NB 62 | ip = i + 1 63 | if (i==NB) ip = 1 64 | area = area + 0.5 * (YB(i) + YB(ip)) * (XB(i) - XB(ip)) 65 | enddo 66 | ! 67 | if (area>=0.0) then 68 | LCLock = .false. 69 | if (show_output) write (*, 99001) NB 70 | !............................................................... 71 | 99001 format (/' Number of input coordinate points:', i4/' Counterclockwise ordering') 72 | else 73 | !----- if area is negative (clockwise order), reverse coordinate order 74 | LCLock = .true. 75 | if (show_output) write (*, 99002) NB 76 | 99002 format (/' Number of input coordinate points:', i4/' Clockwise ordering') 77 | do i = 1, NB / 2 78 | xtmp = XB(NB - i + 1) 79 | ytmp = YB(NB - i + 1) 80 | XB(NB - i + 1) = XB(i) 81 | YB(NB - i + 1) = YB(i) 82 | XB(i) = xtmp 83 | YB(i) = ytmp 84 | enddo 85 | endif 86 | ! 87 | if (LNOrm) then 88 | call norm(XB, XBP, YB, YBP, SB, NB) 89 | if (show_output) write (*, 99003) 90 | 99003 format (/' Airfoil has been normalized') 91 | endif 92 | ! 93 | call scalc(XB, YB, SB, NB) 94 | call segspl(XB, XBP, SB, NB) 95 | call segspl(YB, YBP, SB, NB) 96 | ! 97 | call geopar(XB, XBP, YB, YBP, SB, NB, W1, SBLe, CHOrdb, AREab, & 98 | RADble, ANGbte, EI11ba, EI22ba, APX1ba, APX2ba, EI11bt, EI22bt, APX1bt, & 99 | & APX2bt, THIckb, CAMbrb) 100 | ! 101 | xble = seval(SBLe, XB, XBP, SB, NB) 102 | yble = seval(SBLe, YB, YBP, SB, NB) 103 | xbte = 0.5 * (XB(1) + XB(NB)) 104 | ybte = 0.5 * (YB(1) + YB(NB)) 105 | ! 106 | if (show_output) write (*, 99004) xble, yble, CHOrdb, xbte, ybte 107 | 99004 format (/' LE x,y =', 2F10.5, ' | Chord =', f10.5/' TE x,y =', 2F10.5, ' |') 108 | ! 109 | !---- set reasonable MSES domain parameters for non-MSES coordinate file 110 | if (Itype<=2 .and. ISPars==' ') then 111 | xble = seval(SBLe, XB, XBP, SB, NB) 112 | yble = seval(SBLe, YB, YBP, SB, NB) 113 | xinl = xble - 2.0 * CHOrdb 114 | xout = xble + 3.0 * CHOrdb 115 | ybot = yble - 2.5 * CHOrdb 116 | ytop = yble + 3.5 * CHOrdb 117 | xinl = aint(20.0 * abs(xinl / CHOrdb) + 0.5) / 20.0 * sign(CHOrdb, xinl) 118 | xout = aint(20.0 * abs(xout / CHOrdb) + 0.5) / 20.0 * sign(CHOrdb, xout) 119 | ybot = aint(20.0 * abs(ybot / CHOrdb) + 0.5) / 20.0 * sign(CHOrdb, ybot) 120 | ytop = aint(20.0 * abs(ytop / CHOrdb) + 0.5) / 20.0 * sign(CHOrdb, ytop) 121 | write (ISPars, 99005) xinl, xout, ybot, ytop 122 | 99005 format (1x, 4F8.2) 123 | endif 124 | ! 125 | !---- wipe out old flap hinge location 126 | XBF = 0.0 127 | YBF = 0.0 128 | LBFlap = .false. 129 | ! 130 | !---- wipe out off-design alphas, CLs 131 | !c NALOFF = 0 132 | !c NCLOFF = 0 133 | ! 134 | 135 | call abcopy(.true.) 136 | ! 137 | call cang(X, Y, N, 0, imax, amax) 138 | if (abs(amax)>angtol .and. show_output) write (*, 99007) amax, imax 139 | 99007 format (/& 140 | ' WARNING: Poor input coordinate distribution'/& 141 | ' Excessive panel angle', f7.1, ' at i =', i4/& 142 | ' Repaneling with PANE and/or PPAR suggested'/& 143 | ' (doing GDES,CADD before repaneling _may_'/& 144 | ' improve excessively coarse LE spacing') 145 | end subroutine set_airfoil 146 | 147 | function get_n_coords() bind(c, name='get_n_coords') 148 | use i_xfoil, only: NB 149 | integer(c_int) :: get_n_coords 150 | get_n_coords = NB 151 | end function get_n_coords 152 | 153 | subroutine get_airfoil(x, y, n) bind(c, name='get_airfoil') 154 | use i_xfoil, only: XB, YB 155 | integer(c_int), intent(in) :: n 156 | real(c_float), intent(inout) :: x(n), y(n) 157 | integer :: i 158 | do i=1, n 159 | x(i) = XB(i) 160 | y(i) = YB(i) 161 | end do 162 | end subroutine get_airfoil 163 | 164 | subroutine set_naca(spec) bind(c, name='set_naca') 165 | use m_xfoil, only: naca 166 | integer(c_int), intent(in) :: spec 167 | if (spec <= 0) then 168 | write(0, *) 'Invalid NACA specifier. Specify a NACA 4 or 5 series airfoil code.' 169 | else 170 | call naca(spec) 171 | end if 172 | end subroutine set_naca 173 | 174 | subroutine set_reynolds(Re) bind(c, name='set_reynolds') 175 | use i_xfoil 176 | real(c_float), intent(in) :: Re 177 | 178 | if (Re == 0.) then 179 | LVIsc = .false. 180 | else 181 | LVIsc = .true. 182 | end if 183 | 184 | REInf1 = Re 185 | 186 | LBLini = .false. 187 | LIPan = .false. 188 | 189 | LVConv = .false. 190 | end subroutine set_reynolds 191 | 192 | function get_reynolds() bind(c, name='get_reynolds') 193 | use i_xfoil, only: REInf1 194 | real(c_float) :: get_reynolds 195 | get_reynolds = REInf1 196 | end function get_reynolds 197 | 198 | subroutine set_mach(M) bind(c, name='set_mach') 199 | use s_xfoil, only: comset, cpcalc, clcalc, cdcalc 200 | use i_xfoil 201 | 202 | real(c_float), intent(in) :: M 203 | 204 | if (M /= MINf) then 205 | MINf = M 206 | 207 | call comset 208 | if (MINf>0.0 .and. show_output) write (*, 99003) CPStar, QSTar / QINf 209 | 99003 format (/' Sonic Cp =', f10.2, ' Sonic Q/Qinf =', f10.3/) 210 | 211 | call cpcalc(N, QINv, QINf, MINf, CPI) 212 | if (LVIsc) call cpcalc(N + NW, QVIs, QINf, MINf, CPV) 213 | call clcalc(N, X, Y, GAM, GAM_a, ALFa, MINf, QINf, XCMref, YCMref, CL, CM, CDP, CL_alf, CL_msq) 214 | call cdcalc 215 | end if 216 | 217 | LVConv = .false. 218 | end subroutine set_mach 219 | 220 | function get_mach() bind(c, name='get_mach') 221 | use i_xfoil, only: MINf 222 | real(c_float) :: get_mach 223 | get_mach = MINf 224 | end function get_mach 225 | 226 | subroutine set_xtr(xtr_top, xtr_bot) bind(c, name='set_xtr') 227 | use i_xfoil, only: XSTrip, LVConv 228 | real(c_float), intent(in) :: xtr_top, xtr_bot 229 | XSTrip(1) = xtr_top 230 | XSTrip(2) = xtr_bot 231 | LVConv = .false. 232 | end subroutine set_xtr 233 | 234 | subroutine get_xtr(xtr_top, xtr_bot) bind(c, name='get_xtr') 235 | use i_xfoil, only: XSTrip 236 | real(c_float) :: xtr_top, xtr_bot 237 | xtr_top = XSTrip(1) 238 | xtr_bot = XSTrip(2) 239 | end subroutine get_xtr 240 | 241 | subroutine set_n_crit(n_crit) bind(c, name='set_n_crit') 242 | use i_xfoil, only: ACRit, LVConv 243 | real(c_float), intent(in) :: n_crit 244 | ACRit(1) = n_crit 245 | ACRit(2) = n_crit 246 | LVConv = .false. 247 | end subroutine set_n_crit 248 | 249 | function get_n_crit() bind(c, name='get_n_crit') 250 | use i_xfoil, only: ACRit 251 | real(c_float) :: get_n_crit 252 | get_n_crit = ACRit(1) 253 | end function get_n_crit 254 | 255 | subroutine set_max_iter(max_iter) bind(c, name='set_max_iter') 256 | use i_xfoil, only: ITMax 257 | integer(c_int), intent(in) :: max_iter 258 | ITMax = max_iter 259 | end subroutine set_max_iter 260 | 261 | function get_max_iter() bind(c, name='get_max_iter') 262 | use i_xfoil, only: ITMax 263 | integer(c_int) :: get_max_iter 264 | get_max_iter = ITMax 265 | end function get_max_iter 266 | 267 | subroutine reset_bls() bind(c, name='reset_bls') 268 | use i_xfoil, only: LBLini, LIPan, show_output 269 | LBLini = .not.LBLini 270 | if (LBLini) then 271 | if (show_output) write (*, *) 'BLs are assumed to be initialized' 272 | else 273 | if (show_output) write (*, *) 'BLs will be initialized on next point' 274 | LIPan = .false. 275 | endif 276 | end subroutine reset_bls 277 | 278 | subroutine repanel(n_panel, cv_par, cte_ratio, ctr_ratio, & 279 | xs_ref1, xs_ref2, xp_ref1, xp_ref2) bind(c, name='repanel') 280 | use m_xfoil, only: pangen 281 | use m_xgeom, only: cang 282 | use i_xfoil 283 | 284 | integer :: imax 285 | real :: amax 286 | integer(c_int), intent(in) :: n_panel 287 | real(c_float), intent(in) :: cv_par, cte_ratio, ctr_ratio, xs_ref1, xs_ref2, xp_ref1, xp_ref2 288 | 289 | NPAn = min(n_panel, IQX - 6) 290 | CVPar = cv_par 291 | CTErat = cte_ratio 292 | CTRrat = ctr_ratio 293 | XSRef1 = xs_ref1 294 | XSRef2 = xs_ref2 295 | XPRef1 = xp_ref1 296 | XPRef2 = xp_ref2 297 | 298 | call pangen(.true.) 299 | if (N>0) call cang(X, Y, N, 1, imax, amax) 300 | end subroutine repanel 301 | 302 | subroutine filter(factor) bind(c, name='filter') 303 | use m_xmdes, only: cnfilt, piqsum, qspcir, qspint 304 | use i_xfoil 305 | 306 | real(c_float), intent(in) :: factor 307 | 308 | real :: cfilt, clq 309 | integer :: kqsp 310 | 311 | !----- apply modified Hanning filter to Cn coefficients 312 | cfilt = factor 313 | call cnfilt(cfilt) 314 | call piqsum 315 | call qspcir 316 | 317 | do kqsp = 1, NQSp 318 | call qspint(ALQsp(kqsp), QSPec(1, kqsp), QINf, MINf, clq, CMQsp(kqsp)) 319 | if (IACqsp==1) CLQsp(kqsp) = clq 320 | enddo 321 | LQSppl = .false. 322 | end subroutine filter 323 | 324 | subroutine alfa_(a_input, cl_out, cd_out, cd_f_out, cd_p_out, cm_out, cp_out, conv) bind(c, name='alfa') 325 | use m_xoper, only: specal, viscal, fcpmin 326 | use i_xfoil 327 | 328 | real(c_float), intent(in) :: a_input 329 | real(c_float), intent(out) :: cl_out, cd_out, cd_f_out, cd_p_out, cm_out, cp_out 330 | logical(c_bool), intent(out) :: conv 331 | ADEg = a_input 332 | 333 | ALFa = a_input * DTOr 334 | QINf = 1.0 335 | LALfa = .true. 336 | call specal 337 | if (abs(ALFa - AWAke)>1.0E-5) LWAke = .false. 338 | if (abs(ALFa - AVIsc)>1.0E-5) LVConv = .false. 339 | if (abs(MINf - MVIsc)>1.0E-5) LVConv = .false. 340 | ! 341 | if (LVIsc) then 342 | conv = viscal(ITMax) 343 | conv = LVConv .and. conv 344 | else 345 | conv = .true. 346 | end if 347 | 348 | cl_out = CL 349 | cd_out = CD 350 | cd_f_out = CDF 351 | cd_p_out = CDP 352 | cm_out = CM 353 | 354 | call fcpmin 355 | cp_out = CPMn 356 | end subroutine alfa_ 357 | 358 | subroutine cl_(cl_input, a_out, cd_out, cd_f_out, cd_p_out, cm_out, cp_out, conv) bind(c, name='cl') 359 | use m_xoper, only: speccl, viscal, fcpmin 360 | use i_xfoil 361 | 362 | real(c_float), intent(in) :: cl_input 363 | real(c_float), intent(out) :: a_out, cd_out, cd_f_out, cd_p_out, cm_out, cp_out 364 | logical(c_bool), intent(out) :: conv 365 | 366 | CLSpec = cl_input 367 | ALFa = 0.0 368 | QINf = 1.0 369 | LALfa = .false. 370 | call speccl 371 | ADEg = ALFa / DTOr 372 | if (abs(ALFa - AWAke)>1.0E-5) LWAke = .false. 373 | if (abs(ALFa - AVIsc)>1.0E-5) LVConv = .false. 374 | if (abs(MINf - MVIsc)>1.0E-5) LVConv = .false. 375 | 376 | if (LVIsc) then 377 | conv = viscal(ITMax) 378 | conv = LVConv .and. conv 379 | else 380 | conv = .true. 381 | end if 382 | 383 | a_out = ALFa / DTOr 384 | cd_out = CD 385 | cd_f_out = CDF 386 | cd_p_out = CDP 387 | cm_out = CM 388 | 389 | call fcpmin 390 | cp_out = CPMn 391 | end subroutine cl_ 392 | 393 | subroutine aseq(a_start, a_end, n_step, & 394 | a_arr, cl_arr, cd_arr, cm_arr, cp_arr, conv_arr) bind(c, name='aseq') 395 | use m_xoper, only: specal, viscal, fcpmin 396 | use i_xfoil 397 | real(c_float), intent(in) :: a_start, a_end 398 | integer(c_int), intent(in) :: n_step 399 | real(c_float), dimension(n_step), intent(inout) :: a_arr, cl_arr, cd_arr, cm_arr, cp_arr 400 | logical(c_bool), dimension(n_step), intent(inout) :: conv_arr 401 | integer :: i, j, iseqex, itmaxs 402 | real :: a0, da, nan 403 | 404 | nan = 0 405 | nan = 0/nan 406 | 407 | a0 = a_start * DTOr 408 | da = (a_end - a_start) / float(n_step) * DTOr 409 | 410 | LALfa = .true. 411 | 412 | !----- initialize unconverged-point counter 413 | iseqex = 0 414 | 415 | do i=1, n_step 416 | ALFa = a0 + da * float(i - 1) 417 | if (abs(ALFa - AWAke)>1.0E-5) LWAke = .false. 418 | if (abs(ALFa - AVIsc)>1.0E-5) LVConv = .false. 419 | if (abs(MINf - MVIsc)>1.0E-5) LVConv = .false. 420 | call specal 421 | itmaxs = ITMax + 5 422 | if (LVIsc) then 423 | conv_arr(i) = viscal(itmaxs) 424 | end if 425 | ADEg = ALFa / DTOr 426 | 427 | a_arr(i) = ADEg 428 | cl_arr(i) = CL 429 | cd_arr(i) = CD 430 | cm_arr(i) = CM 431 | 432 | call fcpmin 433 | cp_arr(i) = CPMn 434 | 435 | if ((LVConv .and. conv_arr(i)) .or. .not.LVIsc) then 436 | conv_arr(i) = .true. 437 | elseif (LVIsc .and. .not. (LVConv .and. conv_arr(i))) then 438 | conv_arr(i) = .false. 439 | endif 440 | end do 441 | end subroutine aseq 442 | 443 | subroutine cseq(cl_start, cl_end, n_step, & 444 | a_arr, cl_arr, cd_arr, cm_arr, cp_arr, conv_arr) bind(c, name='cseq') 445 | use m_xoper, only: specal, viscal, speccl, fcpmin 446 | use i_xfoil 447 | real(c_float), intent(in) :: cl_start, cl_end 448 | integer(c_int), intent(in) :: n_step 449 | real(c_float), dimension(n_step), intent(inout) :: a_arr, cl_arr, cd_arr, cm_arr, cp_arr 450 | logical(c_bool), dimension(n_step), intent(inout) :: conv_arr 451 | integer :: i, j, iseqex, itmaxs 452 | real :: cl0, dcl 453 | 454 | cl0 = cl_start 455 | dcl = (cl_end - cl_start) / float(n_step) 456 | LALfa = .false. 457 | 458 | !----- initialize unconverged-point counter 459 | iseqex = 0 460 | 461 | do i=1, n_step 462 | CLSpec = cl0 + dcl * float(i - 1) 463 | call speccl 464 | if (abs(ALFa - AWAke)>1.0E-5) LWAke = .false. 465 | if (abs(ALFa - AVIsc)>1.0E-5) LVConv = .false. 466 | if (abs(MINf - MVIsc)>1.0E-5) LVConv = .false. 467 | 468 | itmaxs = ITMax + 5 469 | if (LVIsc) then 470 | conv_arr(i) = viscal(itmaxs) 471 | end if 472 | ADEg = ALFa / DTOr 473 | 474 | a_arr(i) = ADEg 475 | cl_arr(i) = CL 476 | cd_arr(i) = CD 477 | cm_arr(i) = CM 478 | 479 | call fcpmin 480 | cp_arr(i) = CPMn 481 | 482 | if ((LVConv .and. conv_arr(i)) .or. .not.LVIsc) then 483 | conv_arr(i) = .true. 484 | elseif (LVIsc .and. .not. (LVConv .and. conv_arr(i))) then 485 | conv_arr(i) = .false. 486 | endif 487 | end do 488 | end subroutine cseq 489 | 490 | subroutine bldump_(c_filename, length) bind(c, name='boundary_layer_dump') 491 | use m_xoper, only: bldump 492 | use i_xfoil 493 | use iso_c_binding 494 | implicit none 495 | 496 | ! Input parameters 497 | integer(c_int), intent(in) :: length 498 | CHARACTER(kind=C_CHAR), intent(in) :: c_filename 499 | 500 | ! Fortran-like string 501 | character(len = length) :: f_filename 502 | 503 | ! Convert C char pointer array to Fortran string 504 | f_filename = char_array_to_string(c_filename, length) 505 | 506 | ! Output Fortran filename 507 | write(*,*) f_filename 508 | 509 | ! Dump boundary layer properties 510 | call bldump(f_filename) 511 | 512 | end subroutine bldump_ 513 | 514 | subroutine cpdump_(c_filename, length) bind(c, name='cp_dump') 515 | use m_xoper, only: cpdump 516 | use i_xfoil 517 | use iso_c_binding 518 | implicit none 519 | 520 | ! Input parameters 521 | integer(c_int), intent(in) :: length 522 | CHARACTER(kind=C_CHAR), intent(in) :: c_filename 523 | 524 | ! Fortran-like string 525 | character(len = length) :: f_filename 526 | 527 | ! Convert C char pointer array to Fortran string 528 | f_filename = char_array_to_string(c_filename, length) 529 | 530 | ! Output Fortran filename 531 | write(*,*) f_filename 532 | 533 | ! Dump boundary layer properties 534 | call cpdump(f_filename) 535 | 536 | end subroutine cpdump_ 537 | 538 | 539 | ! Utility functions 540 | ! fortran character(len=*) are not compatible with c 541 | ! To be compatible with c, strings sould be copied to a c_char array 542 | function char_array_to_string(char_array, length) 543 | integer(c_int) :: length 544 | character(c_char) :: char_array(length) 545 | character(len=length) :: char_array_to_string 546 | integer :: i 547 | do i = 1, length 548 | char_array_to_string(i:i) = char_array(i) 549 | enddo 550 | end function char_array_to_string 551 | 552 | ! C ends strings with a \0 character. Add this so it is received correctly in c compatible languages 553 | function string_to_char_array(s, length) 554 | integer(c_int) :: length 555 | character :: s(*) 556 | character(c_char) :: string_to_char_array(length) 557 | integer :: i 558 | 559 | do i = 1, length 560 | string_to_char_array(i:i) = s(i) 561 | enddo 562 | 563 | string_to_char_array(i+1:i+1) = c_null_char 564 | 565 | end function string_to_char_array 566 | 567 | end module api 568 | -------------------------------------------------------------------------------- /src/fortran/i_blpar.f90: -------------------------------------------------------------------------------- 1 | !*********************************************************************** 2 | ! Copyright (c) 2019 D. de Vries 3 | ! Original Copyright (c) 2000 Mark Drela 4 | ! 5 | ! This file is part of XFoil. 6 | ! 7 | ! XFoil is free software: you can redistribute it and/or modify 8 | ! it under the terms of the GNU General Public License as published by 9 | ! the Free Software Foundation, either version 3 of the License, or 10 | ! (at your option) any later version. 11 | ! 12 | ! XFoil is distributed in the hope that it will be useful, 13 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | ! GNU General Public License for more details. 16 | ! 17 | ! You should have received a copy of the GNU General Public License 18 | ! along with XFoil. If not, see . 19 | !*********************************************************************** 20 | 21 | !*==I_BLPAR.f90 processed by SPAG 7.21DC at 11:25 on 11 Jan 2019 22 | module i_blpar 23 | implicit none 24 | ! 25 | !*** Start of declarations rewritten by SPAG 26 | ! 27 | ! Local variables 28 | ! 29 | real :: cffac, ctcon, ctrcex, ctrcon, dlcon, duxcon, gacon, gbcon, gccon, sccon 30 | ! 31 | !*** End of declarations rewritten by SPAG 32 | ! 33 | ! 34 | ! COMMON /BLPAR/ 35 | ! 36 | end module i_blpar 37 | -------------------------------------------------------------------------------- /src/fortran/i_circle.f90: -------------------------------------------------------------------------------- 1 | !*********************************************************************** 2 | ! Copyright (c) 2019 D. de Vries 3 | ! Original Copyright (c) 2000 Mark Drela 4 | ! 5 | ! This file is part of XFoil. 6 | ! 7 | ! XFoil is free software: you can redistribute it and/or modify 8 | ! it under the terms of the GNU General Public License as published by 9 | ! the Free Software Foundation, either version 3 of the License, or 10 | ! (at your option) any later version. 11 | ! 12 | ! XFoil is distributed in the hope that it will be useful, 13 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | ! GNU General Public License for more details. 16 | ! 17 | ! You should have received a copy of the GNU General Public License 18 | ! along with XFoil. If not, see . 19 | !*********************************************************************** 20 | 21 | !*==I_CIRCLE.f90 processed by SPAG 7.21DC at 11:25 on 11 Jan 2019 22 | module i_circle 23 | implicit none 24 | ! 25 | !*** Start of declarations rewritten by SPAG 26 | ! 27 | ! PARAMETER definitions 28 | ! 29 | integer, parameter :: ICX = 257, IMX = (ICX - 1) / 4 30 | ! 31 | ! Local variables 32 | ! 33 | real :: ag0, agte, dwc, pi, qim0, qimold 34 | complex :: chordz, dzte, zleold 35 | complex, dimension(0:IMX) :: cn 36 | complex, dimension(ICX, 0:IMX) :: eiw 37 | integer :: mc, mct, nc 38 | complex, dimension(ICX) :: piq, zc, zcoldw 39 | real, dimension(ICX) :: sc, scold, wc, xcold, ycold 40 | complex, dimension(ICX, IMX / 4) :: zc_cn 41 | ! 42 | !*** End of declarations rewritten by SPAG 43 | ! 44 | ! 45 | ! PARAMETER definitions 46 | ! 47 | ! 48 | ! COMMON /CPC01/ 49 | ! 50 | ! 51 | ! COMMON /CPI01/ 52 | ! 53 | ! 54 | ! COMMON /CPR01/ 55 | ! 56 | end module i_circle 57 | -------------------------------------------------------------------------------- /src/fortran/i_pindex.f90: -------------------------------------------------------------------------------- 1 | !*********************************************************************** 2 | ! Copyright (c) 2019 D. de Vries 3 | ! Original Copyright (c) 2000 Mark Drela 4 | ! 5 | ! This file is part of XFoil. 6 | ! 7 | ! XFoil is free software: you can redistribute it and/or modify 8 | ! it under the terms of the GNU General Public License as published by 9 | ! the Free Software Foundation, either version 3 of the License, or 10 | ! (at your option) any later version. 11 | ! 12 | ! XFoil is distributed in the hope that it will be useful, 13 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | ! GNU General Public License for more details. 16 | ! 17 | ! You should have received a copy of the GNU General Public License 18 | ! along with XFoil. If not, see . 19 | !*********************************************************************** 20 | 21 | !*==I_PINDEX.f90 processed by SPAG 7.21DC at 11:25 on 11 Jan 2019 22 | ! AREAD 23 | module i_pindex 24 | implicit none 25 | ! 26 | !*** Start of declarations rewritten by SPAG 27 | ! 28 | ! PARAMETER definitions 29 | ! 30 | integer, parameter :: IAL = 1, ICL = 2, ICD = 3, ICM = 4, ICW = 5, ICV = 6, ICP = 7, IMA = 8, IRE = 9, & 31 | & ICH = 10, IMC = 11, ICDH = 12, ICMDOT = 13, IPTOT = 13, JNC = 1, JTP = 2, JTN = 3, & 32 | & JTI = 4, JPTOT = 4 33 | ! 34 | ! Local variables 35 | ! 36 | character(6), dimension(IPTOT), save :: cpolform 37 | character(10), dimension(IPTOT), save :: cpolname 38 | character(6), dimension(JPTOT), save :: cpolsform 39 | character(5), dimension(JPTOT), save :: cpolsname 40 | ! 41 | !*** End of declarations rewritten by SPAG 42 | ! 43 | ! 44 | !*** Start of declarations rewritten by SPAG 45 | ! 46 | ! PARAMETER definitions 47 | ! 48 | ! 49 | ! Local variables 50 | ! 51 | ! 52 | !*** End of declarations rewritten by SPAG 53 | ! 54 | ! 55 | !---- Pointers for referencing polar force coefficients 56 | ! First 4 pointers must be main polar plot variables. 57 | ! 58 | ! ! alpha 59 | ! ! CL 60 | ! ! CD 61 | ! ! Cm 62 | ! ! CDwave 63 | ! ! CDvisc 64 | ! ! CDpres 65 | ! ! Mach 66 | ! ! Re 67 | ! ! Hinge moment 68 | ! ! Minimum Cp on surface 69 | ! ! CDh (engine thrust coeff.) 70 | ! 71 | ! 72 | !--------------------- 73 | ! Pointers for referencing polar airfoil-side quantities 74 | ! 75 | ! Cm_dot 76 | ! ! Ncrit 77 | ! ! trip 78 | ! ! transition 79 | 80 | ! 81 | data cpolname/'alpha ', 'CL ', 'CD ', 'CM ', 'CDw ', 'CDv ', 'CDp ', & 82 | &'Mach ', 'Re ', 'Chinge ', 'Cpmin ', 'CDh ', 'Cmdot '/ 83 | ! transition index 84 | ! ! alpha 85 | ! ! CL 86 | ! ! CD 87 | ! ! CM 88 | ! ! CDw 89 | ! ! CDv 90 | ! ! CDp 91 | ! ! Mach 92 | ! ! Re 93 | ! ! Chinge 94 | ! ! Cpmin 95 | ! ! CDh 96 | data cpolform/'F7.3 ', 'F9.4 ', 'F10.5 ', 'F9.4 ', 'F10.5 ', 'F10.5 ', 'F10.5 ', 'F8.4 ', 'E11.3 ', & 97 | &'F10.5 ', 'F9.4 ', 'F11.5 ', 'F9.5 '/ 98 | ! Cmdot 99 | 100 | data cpolsname/'Ncrit', 'Xtrip', 'Xtr ', 'Itr '/ 101 | ! ! Ncrit 102 | ! ! Xtrip 103 | ! ! Xtr 104 | data cpolsform/'F7.3 ', 'F9.4 ', 'F9.4 ', 'F9.4 '/ 105 | ! Itr 106 | end module i_pindex 107 | -------------------------------------------------------------------------------- /src/fortran/i_xbl.f90: -------------------------------------------------------------------------------- 1 | !*********************************************************************** 2 | ! Copyright (c) 2019 D. de Vries 3 | ! Original Copyright (c) 2000 Mark Drela 4 | ! 5 | ! This file is part of XFoil. 6 | ! 7 | ! XFoil is free software: you can redistribute it and/or modify 8 | ! it under the terms of the GNU General Public License as published by 9 | ! the Free Software Foundation, either version 3 of the License, or 10 | ! (at your option) any later version. 11 | ! 12 | ! XFoil is distributed in the hope that it will be useful, 13 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | ! GNU General Public License for more details. 16 | ! 17 | ! You should have received a copy of the GNU General Public License 18 | ! along with XFoil. If not, see . 19 | !*********************************************************************** 20 | 21 | !*==I_XBL.f90 processed by SPAG 7.21DC at 11:25 on 11 Jan 2019 22 | module i_xbl 23 | use i_blpar 24 | implicit none 25 | ! 26 | !*** Start of declarations rewritten by SPAG 27 | ! 28 | ! PARAMETER definitions 29 | ! 30 | integer, parameter :: NCOM = 73 31 | ! 32 | ! Local variables 33 | ! 34 | real :: amcrit, bule, cfm, cfm_d1, cfm_d2, cfm_ms, cfm_re, cfm_t1, cfm_t2, cfm_u1, cfm_u2, dwte, gambl, & 35 | & gm1bl, hstinv, hstinv_ms, hvrat, qinfbl, reybl, reybl_ms, reybl_re, rstbl, rstbl_ms, tkbl, & 36 | & tkbl_ms, xiforc, xt, xt_a1, xt_d1, xt_d2, xt_ms, xt_re, xt_t1, xt_t2, xt_u1, xt_u2, xt_x1, & 37 | & xt_x2, xt_xf 38 | real, pointer :: ampl1, ampl2, cf1, cf1_d1, cf1_ms, cf1_re, cf1_t1, cf1_u1, cf2, cf2_d2, cf2_ms, cf2_re, & 39 | & cf2_t2, cf2_u2, cq1, cq1_d1, cq1_ms, cq1_re, cq1_t1, cq1_u1, cq2, cq2_d2, cq2_ms, & 40 | & cq2_re, cq2_t2, cq2_u2, d1, d2, de1, de1_d1, de1_ms, de1_t1, de1_u1, de2, de2_d2, & 41 | & de2_ms, de2_t2, de2_u2, di1, di1_d1, di1_ms, di1_re, di1_s1, di1_t1, di1_u1, di2, & 42 | & di2_d2, di2_ms, di2_re, di2_s2, di2_t2, di2_u2, dw1, dw2, h1, h1_d1, h1_t1, h2, h2_d2, & 43 | & h2_t2, hc1, hc1_d1, hc1_ms, hc1_t1, hc1_u1, hc2, hc2_d2, hc2_ms, hc2_t2, hc2_u2, hk1, & 44 | & hk1_d1, hk1_ms, hk1_t1, hk1_u1, hk2, hk2_d2, hk2_ms, hk2_t2, hk2_u2 45 | real, dimension(NCOM) :: c1sav, c2sav 46 | real, target, dimension(NCOM) :: com1, com2 47 | real, pointer :: hs1, hs1_d1, hs1_ms, hs1_re, hs1_t1, hs1_u1, hs2, hs2_d2, hs2_ms, hs2_re, hs2_t2, & 48 | & hs2_u2, m1, m1_ms, m1_u1, m2, m2_ms, m2_u2, r1, r1_ms, r1_u1, r2, r2_ms, r2_u2, rt1, & 49 | & rt1_ms, rt1_re, rt1_t1, rt1_u1, rt2, rt2_ms, rt2_re, rt2_t2, rt2_u2, s1, s2, t1, t2, & 50 | & u1, u1_ms, u1_uei, u2, u2_ms, u2_uei, us1, us1_d1, us1_ms, us1_re, us1_t1, us1_u1, us2, & 51 | & us2_d2, us2_ms, us2_re, us2_t2, us2_u2, v1, v1_ms, v1_re, v1_u1, v2, v2_ms, v2_re, & 52 | & v2_u2, x1, x2 53 | integer :: idampv 54 | logical :: simi, tran, trforc, trfree, turb, wake 55 | real, dimension(4, 5) :: vs1, vs2 56 | real, dimension(4) :: vsm, vsr, vsrez, vsx 57 | ! 58 | !*** End of declarations rewritten by SPAG 59 | ! 60 | ! 61 | ! PARAMETER definitions 62 | ! 63 | ! 64 | ! COMMON /V_COM/ 65 | ! 66 | ! 67 | ! COMMON /V_INT/ 68 | ! 69 | ! 70 | ! COMMON /V_SAV/ 71 | ! 72 | ! 73 | ! COMMON /V_SYS/ 74 | ! 75 | ! 76 | ! COMMON /V_VAR/ 77 | ! 78 | ! 79 | ! COMMON /V_VAR1/ 80 | ! 81 | ! 82 | ! COMMON /V_VAR2/ 83 | ! 84 | ! 85 | ! COMMON /V_VARA/ 86 | ! 87 | end module i_xbl 88 | -------------------------------------------------------------------------------- /src/fortran/m_aread.f90: -------------------------------------------------------------------------------- 1 | !*********************************************************************** 2 | ! Copyright (c) 2019 D. de Vries 3 | ! Original Copyright (c) 2000 Mark Drela 4 | ! 5 | ! This file is part of XFoil. 6 | ! 7 | ! XFoil is free software: you can redistribute it and/or modify 8 | ! it under the terms of the GNU General Public License as published by 9 | ! the Free Software Foundation, either version 3 of the License, or 10 | ! (at your option) any later version. 11 | ! 12 | ! XFoil is distributed in the hope that it will be useful, 13 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | ! GNU General Public License for more details. 16 | ! 17 | ! You should have received a copy of the GNU General Public License 18 | ! along with XFoil. If not, see . 19 | !*********************************************************************** 20 | 21 | !*==AREAD.f90 processed by SPAG 7.21DC at 11:25 on 11 Jan 2019 22 | module m_aread 23 | contains 24 | subroutine aread(Lu, Fname, Nmax, X, Y, N, Name, Ispars, Itype, Info) 25 | use i_xfoil, only: show_output 26 | use m_userio, only: getflt, aski 27 | implicit none 28 | ! 29 | !*** Start of declarations rewritten by SPAG 30 | ! 31 | ! Dummy arguments 32 | ! 33 | character(*) :: Fname, Ispars, Name 34 | integer :: Info, Itype, Lu, N, Nmax 35 | real, dimension(Nmax) :: X, Y 36 | intent (in) Fname, Info, Lu, Nmax 37 | intent (out) Ispars, Itype, N 38 | intent (inout) Name, X, Y 39 | ! 40 | ! Local variables 41 | ! 42 | real, dimension(10) :: a 43 | logical :: error, lopen 44 | integer :: i, iel, na, nel, nfn 45 | character(80) :: line, line1, line2 46 | ! 47 | !*** End of declarations rewritten by SPAG 48 | ! 49 | ! 50 | !*** Start of declarations rewritten by SPAG 51 | ! 52 | ! Dummy arguments 53 | ! 54 | ! 55 | ! Local variables 56 | ! 57 | ! 58 | !*** End of declarations rewritten by SPAG 59 | ! 60 | !-------------------------------------------------------- 61 | ! Reads in several types of airfoil coordinate file. 62 | ! 63 | ! Input: 64 | ! LU logical unit to use for reading 65 | ! FNAME name of coordinate file to be read, 66 | ! if FNAME(1:1).eq.' ', unit LU is assumed 67 | ! to be already open 68 | ! INFO 0 keep quiet 69 | ! 1 print info on airfoil 70 | ! Output: 71 | ! X,Y coordinates 72 | ! N number of X,Y coordinates 73 | ! NAME character name string (if ITYPE > 1) 74 | ! ISPARS ISES/MSES domain-size string (if ITYPE > 2) 75 | ! ITYPE returns type of file: 76 | ! 0 None. Read error occurred. 77 | ! 1 Generic. 78 | ! 2 Labeled generic. 79 | ! 3 MSES single element. 80 | ! 4 MSES multi-element. 81 | !-------------------------------------------------------- 82 | ! 83 | iel = 0 84 | nel = 0 85 | ! 86 | !---- assume read error will occur 87 | Itype = 0 88 | ! 89 | lopen = Fname(1:1)/=' ' 90 | if (lopen) open (Lu, file = Fname, status = 'OLD', err = 200) 91 | do 92 | ! 93 | read (Lu, 99004, end = 300, err = 200) line1 94 | if (index('#!', line1(1:1))==0) then 95 | do 96 | ! 97 | read (Lu, 99004, end = 300) line2 98 | if (index('#!', line2(1:1))==0) then 99 | ! 100 | i = 1 101 | ! 102 | !---- try to read two numbers from first line 103 | na = 2 104 | call getflt(line1, a, na, error) 105 | if (error .or. na<2) then 106 | !------ must be a name string 107 | Name = line1 108 | else 109 | !------ no name, just two valid numbers... must be plain airfoil file 110 | Name = ' ' 111 | if (Info>0) then 112 | if (show_output) then 113 | write (*, *) 114 | write (*, *) 'Plain airfoil file' 115 | endif 116 | endif 117 | Itype = 1 118 | rewind (Lu) 119 | goto 5 120 | endif 121 | ! 122 | !---- if we got here, there's a name line, 123 | !- so now try to read four MSES domain numbers from second line 124 | na = 4 125 | call getflt(line2, a, na, error) 126 | !------ less than two valid numbers... not a valid format 127 | if (error .or. na<2) goto 300 128 | ! 129 | if (na<4) then 130 | !------ less than four numbers... usual .dat labeled file 131 | Name = line1 132 | if (Info>0) then 133 | if (show_output) then 134 | write (*, *) 135 | write (*, *) 'Labeled airfoil file. Name: ', Name 136 | endif 137 | endif 138 | Itype = 2 139 | rewind (Lu) 140 | read (Lu, 99004, end = 300) line1 141 | ! 142 | else 143 | !------ four or more numbers... MSES or MISES file 144 | if (Info>0) then 145 | if (show_output) then 146 | write (*, *) 147 | write (*, *) 'MSES airfoil file. Name: ', Name 148 | endif 149 | endif 150 | Itype = 3 151 | Ispars = line2 152 | endif 153 | 5 do 154 | ! 155 | !---- read each element until 999.0 or end of file is encountered 156 | nel = nel + 1 157 | do i = 1, Nmax 158 | do 159 | read (Lu, 99004, end = 100) line 160 | ! 161 | !------ skip comment line 162 | if (index('#!', line(1:1))==0) then 163 | ! 164 | na = 2 165 | call getflt(line, a, na, error) 166 | if (error) goto 300 167 | ! 168 | !------ skip line without at least two numbers 169 | if (na>=2) then 170 | ! 171 | X(i) = a(1) 172 | Y(i) = a(2) 173 | ! 174 | if (X(i)==999.0 .and. Y(i)==999.0) then 175 | !-------- if this is the element we want, just exit 176 | if (iel==nel) goto 100 177 | ! 178 | if (iel==0) then 179 | call aski('Enter element number^', iel) 180 | Itype = 4 181 | endif 182 | ! 183 | !-------- if this is the specified element, exit. 184 | if (iel==nel) goto 100 185 | goto 10 186 | endif 187 | exit 188 | endif 189 | endif 190 | enddo 191 | enddo 192 | if (show_output) write (*, 99001) Nmax 193 | 99001 format (/' Buffer array size exceeded'/' Maximum number of points: ', i4) 194 | if (show_output) write (*, 99005) 195 | if (lopen) close (Lu) 196 | Itype = 0 197 | return 198 | 10 enddo 199 | endif 200 | enddo 201 | endif 202 | enddo 203 | ! 204 | 100 N = i - 1 205 | if (lopen) close (Lu) 206 | return 207 | ! 208 | 200 nfn = index(Fname, ' ') + 1 209 | if (show_output) write (*, 99002) Fname(1:nfn) 210 | 99002 format (/' File OPEN error. Nonexistent file: ', a) 211 | if (show_output) write (*, 99005) 212 | Itype = 0 213 | return 214 | ! 215 | 300 if (lopen) close (Lu) 216 | if (show_output) write (*, 99003) 217 | 99003 format (/' File READ error. Unrecognizable file format') 218 | if (show_output) write (*, 99005) 219 | Itype = 0 220 | return 221 | !............................................................... 222 | 99004 format (a) 223 | 99005 format (' *** LOAD NOT COMPLETED ***') 224 | end subroutine aread 225 | 226 | end module m_aread -------------------------------------------------------------------------------- /src/fortran/m_naca.f90: -------------------------------------------------------------------------------- 1 | !*********************************************************************** 2 | ! Copyright (c) 2019 D. de Vries 3 | ! Original Copyright (c) 2000 Mark Drela 4 | ! 5 | ! This file is part of XFoil. 6 | ! 7 | ! XFoil is free software: you can redistribute it and/or modify 8 | ! it under the terms of the GNU General Public License as published by 9 | ! the Free Software Foundation, either version 3 of the License, or 10 | ! (at your option) any later version. 11 | ! 12 | ! XFoil is distributed in the hope that it will be useful, 13 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | ! GNU General Public License for more details. 16 | ! 17 | ! You should have received a copy of the GNU General Public License 18 | ! along with XFoil. If not, see . 19 | !*********************************************************************** 20 | 21 | !*==NACA4.f90 processed by SPAG 7.21DC at 11:25 on 11 Jan 2019 22 | ! POLREF 23 | module m_naca 24 | contains 25 | subroutine naca4(Ides, Xx, Yt, Yc, Nside, Xb, Yb, Nb, Name) 26 | implicit none 27 | ! 28 | !*** Start of declarations rewritten by SPAG 29 | ! 30 | ! Dummy arguments 31 | ! 32 | integer :: Ides, Nb, Nside 33 | character(*) :: Name 34 | real, dimension(2 * Nside) :: Xb, Yb 35 | real, dimension(Nside) :: Xx, Yc, Yt 36 | intent (in) Ides, Nside 37 | intent (out) Name, Nb, Xb, Yb 38 | intent (inout) Xx, Yc, Yt 39 | ! 40 | ! Local variables 41 | ! 42 | real, save :: an 43 | real :: anp, frac, m, p, t 44 | character(10), save :: digits 45 | integer :: i, ib, n1, n2, n3, n4 46 | ! 47 | !*** End of declarations rewritten by SPAG 48 | ! 49 | ! 50 | !*** Start of declarations rewritten by SPAG 51 | ! 52 | ! Dummy arguments 53 | ! 54 | ! 55 | ! Local variables 56 | ! 57 | ! 58 | !*** End of declarations rewritten by SPAG 59 | ! 60 | ! 61 | data digits/'0123456789'/ 62 | ! 63 | !---- TE point bunching parameter 64 | data an/1.5/ 65 | ! 66 | n4 = Ides / 1000 67 | n3 = (Ides - n4 * 1000) / 100 68 | n2 = (Ides - n4 * 1000 - n3 * 100) / 10 69 | n1 = (Ides - n4 * 1000 - n3 * 100 - n2 * 10) 70 | ! 71 | m = float(n4) / 100.0 72 | p = float(n3) / 10.0 73 | t = float(n2 * 10 + n1) / 100.0 74 | ! 75 | anp = an + 1.0 76 | do i = 1, Nside 77 | frac = float(i - 1) / float(Nside - 1) 78 | if (i==Nside) then 79 | Xx(i) = 1.0 80 | else 81 | Xx(i) = 1.0 - anp * frac * (1.0 - frac)**an - (1.0 - frac)**anp 82 | endif 83 | Yt(i) = (0.29690 * sqrt(Xx(i)) - 0.12600 * Xx(i) & 84 | - 0.35160 * Xx(i)**2 + 0.28430 * Xx(i)**3 - 0.10150 * Xx(i)**4) * t / 0.20 85 | if (Xx(i). 19 | !*********************************************************************** 20 | 21 | !*==HSORT.f90 processed by SPAG 7.21DC at 11:25 on 11 Jan 2019 22 | module m_sort 23 | contains 24 | subroutine hsort(N, A, Indx) 25 | implicit none 26 | ! 27 | !*** Start of declarations rewritten by SPAG 28 | ! 29 | ! Dummy arguments 30 | ! 31 | integer :: N 32 | real, dimension(*) :: A 33 | integer, dimension(*) :: Indx 34 | intent (in) A, N 35 | intent (inout) Indx 36 | ! 37 | ! Local variables 38 | ! 39 | integer :: i, indxt, ir, j, l 40 | real :: q 41 | ! 42 | !*** End of declarations rewritten by SPAG 43 | ! 44 | ! 45 | !*** Start of declarations rewritten by SPAG 46 | ! 47 | ! Dummy arguments 48 | ! 49 | ! 50 | ! Local variables 51 | ! 52 | ! 53 | !*** End of declarations rewritten by SPAG 54 | ! 55 | !-------------------------------------- 56 | ! Heapsort algorithm. 57 | ! Returns INDX(.) such that 58 | ! 59 | ! A(INDX(i)) < A(INDX(i+1)) 60 | ! 61 | ! Stolen from Numerical Recipes. 62 | !-------------------------------------- 63 | ! 64 | do i = 1, N 65 | Indx(i) = i 66 | enddo 67 | ! 68 | if (N<=1) return 69 | ! 70 | l = N / 2 + 1 71 | ir = N 72 | do 73 | ! 74 | if (l>1) then 75 | l = l - 1 76 | indxt = Indx(l) 77 | q = A(indxt) 78 | else 79 | indxt = Indx(ir) 80 | q = A(indxt) 81 | Indx(ir) = Indx(1) 82 | ! 83 | ir = ir - 1 84 | if (ir==1) then 85 | Indx(1) = indxt 86 | return 87 | endif 88 | endif 89 | ! 90 | i = l 91 | j = l + l 92 | do 93 | ! 94 | if (j<=ir) then 95 | if (jTol) then 202 | k = k + 1 203 | Indx(k) = i 204 | endif 205 | enddo 206 | ! 207 | Nnew = k 208 | ! 209 | end subroutine remd 210 | !*==SORTDUP.f90 processed by SPAG 7.21DC at 11:25 on 11 Jan 2019 211 | ! REMD 212 | 213 | 214 | subroutine sortdup(Kk, S, W) 215 | use i_xfoil, only: show_output 216 | implicit none 217 | ! 218 | !*** Start of declarations rewritten by SPAG 219 | ! 220 | ! Dummy arguments 221 | ! 222 | integer :: Kk 223 | real, dimension(Kk) :: S, W 224 | intent (in) Kk 225 | intent (inout) S, W 226 | ! 227 | ! Local variables 228 | ! 229 | logical :: done 230 | integer :: ipass, n, np 231 | real :: temp 232 | ! 233 | !*** End of declarations rewritten by SPAG 234 | ! 235 | ! 236 | !*** Start of declarations rewritten by SPAG 237 | ! 238 | ! Dummy arguments 239 | ! 240 | ! 241 | ! Local variables 242 | ! 243 | ! 244 | !*** End of declarations rewritten by SPAG 245 | ! 246 | !--- Sort arrays in S with no removal of duplicates 247 | ! 248 | !---- sort arrays 249 | do ipass = 1, 1234 250 | done = .true. 251 | do n = 1, Kk - 1 252 | np = n + 1 253 | if (S(np)=Kk) return 404 | if (S(k)==S(k + 1)) then 405 | !------- eliminate pair 406 | Kk = Kk - 2 407 | do kt = k, Kk 408 | S(kt) = S(kt + 2) 409 | W(kt) = W(kt + 2) 410 | enddo 411 | endif 412 | enddo 413 | ! 414 | end subroutine sort 415 | !*==SORTOL.f90 processed by SPAG 7.21DC at 11:25 on 11 Jan 2019 416 | 417 | 418 | subroutine sortol(Tol, Kk, S, W) 419 | use i_xfoil, only: show_output 420 | implicit none 421 | ! 422 | !*** Start of declarations rewritten by SPAG 423 | ! 424 | ! Dummy arguments 425 | ! 426 | integer :: Kk 427 | real :: Tol 428 | real, dimension(Kk) :: S, W 429 | intent (in) Tol 430 | intent (inout) Kk, S, W 431 | ! 432 | ! Local variables 433 | ! 434 | logical :: done 435 | real :: dsq, temp 436 | integer :: ipass, k, kks, kt, n, np 437 | ! 438 | !*** End of declarations rewritten by SPAG 439 | ! 440 | ! 441 | !*** Start of declarations rewritten by SPAG 442 | ! 443 | ! Dummy arguments 444 | ! 445 | ! 446 | ! Local variables 447 | ! 448 | ! 449 | !*** End of declarations rewritten by SPAG 450 | ! 451 | ! 452 | !---- sort arrays 453 | do ipass = 1, 1234 454 | done = .true. 455 | do n = 1, Kk - 1 456 | np = n + 1 457 | if (S(np). 19 | !*********************************************************************** 20 | 21 | !*==ABCOPY.f90 processed by SPAG 7.21DC at 11:25 on 11 Jan 2019 22 | ! INTX 23 | ! 24 | module m_xgdes 25 | contains 26 | subroutine abcopy(Lconf) 27 | use s_xfoil, only: tecalc 28 | use m_xpanel, only: apcalc, ncalc 29 | use m_xgeom, only: lefind 30 | use m_spline, only: seval, segspl, scalc 31 | use i_xfoil 32 | implicit none 33 | ! 34 | !*** Start of declarations rewritten by SPAG 35 | ! 36 | ! Dummy arguments 37 | ! 38 | logical :: Lconf 39 | intent (in) Lconf 40 | ! 41 | ! Local variables 42 | ! 43 | integer :: i, j 44 | ! 45 | !*** End of declarations rewritten by SPAG 46 | ! 47 | ! 48 | !*** Start of declarations rewritten by SPAG 49 | ! 50 | ! Dummy arguments 51 | ! 52 | ! 53 | ! Local variables 54 | ! 55 | ! 56 | !*** End of declarations rewritten by SPAG 57 | ! 58 | ! 59 | if (NB<=1) then 60 | if (show_output) write (*, *) 'ABCOPY: Buffer airfoil not available.' 61 | return 62 | elseif (NB>IQX - 5) then 63 | if (show_output) then 64 | write (*, *) 'Maximum number of panel nodes : ', IQX - 5 65 | write (*, *) 'Number of buffer airfoil points: ', NB 66 | write (*, *) 'Current airfoil cannot be set.' 67 | write (*, *) 'Try executing PANE at Top Level instead.' 68 | endif 69 | return 70 | endif 71 | if (N/=NB) LBLini = .false. 72 | ! 73 | N = NB 74 | do i = 1, N 75 | X(i) = XB(i) 76 | Y(i) = YB(i) 77 | enddo 78 | LGSame = .true. 79 | ! 80 | if (LBFlap) then 81 | XOF = XBF 82 | YOF = YBF 83 | LFLap = .true. 84 | endif 85 | ! 86 | !---- strip out doubled points 87 | i = 1 88 | do 89 | i = i + 1 90 | if (X(i - 1)==X(i) .and. Y(i - 1)==Y(i)) then 91 | do j = i, N - 1 92 | X(j) = X(j + 1) 93 | Y(j) = Y(j + 1) 94 | enddo 95 | N = N - 1 96 | endif 97 | if (i>=N) then 98 | ! 99 | call scalc(X, Y, S, N) 100 | call segspl(X, XP, S, N) 101 | call segspl(Y, YP, S, N) 102 | 103 | call ncalc(X, Y, S, N, NX, NY) 104 | 105 | call lefind(SLE, X, XP, Y, YP, S, N) 106 | XLE = seval(SLE, X, XP, S, N) 107 | YLE = seval(SLE, Y, YP, S, N) 108 | XTE = 0.5 * (X(1) + X(N)) 109 | YTE = 0.5 * (Y(1) + Y(N)) 110 | CHOrd = sqrt((XTE - XLE)**2 + (YTE - YLE)**2) 111 | 112 | call tecalc 113 | call apcalc 114 | ! 115 | LGAmu = .false. 116 | LQInu = .false. 117 | LWAke = .false. 118 | LQAij = .false. 119 | LADij = .false. 120 | LWDij = .false. 121 | LIPan = .false. 122 | LVConv = .false. 123 | LSCini = .false. 124 | !CC LBLINI = .FALSE. 125 | ! 126 | if (Lconf .and. show_output) write (*, 99001) N 127 | 99001 format (/' Current airfoil nodes set from buffer airfoil nodes (', i4, ' )') 128 | exit 129 | endif 130 | enddo 131 | ! 132 | end subroutine abcopy 133 | !*==GETXYF.f90 processed by SPAG 7.21DC at 11:25 on 11 Jan 2019 134 | ! ABCOPY 135 | 136 | 137 | subroutine getxyf(X, Xp, Y, Yp, S, N, Tops, Bots, Xf, Yf) 138 | use i_xfoil, only: show_output 139 | use m_userio, only: askr 140 | use m_spline, only: seval, sinvrt 141 | implicit none 142 | ! 143 | !*** Start of declarations rewritten by SPAG 144 | ! 145 | ! Dummy arguments 146 | ! 147 | real :: Bots, Tops, Xf, Yf 148 | integer :: N 149 | real, dimension(N) :: S, X, Xp, Y, Yp 150 | intent (in) Y, Yp 151 | intent (inout) Bots, Tops, Yf 152 | ! 153 | ! Local variables 154 | ! 155 | real :: boty, topy, yrel 156 | ! 157 | !*** End of declarations rewritten by SPAG 158 | ! 159 | ! 160 | !*** Start of declarations rewritten by SPAG 161 | ! 162 | ! Dummy arguments 163 | ! 164 | ! 165 | ! Local variables 166 | ! 167 | ! 168 | !*** End of declarations rewritten by SPAG 169 | ! 170 | ! 171 | if (Xf==-999.0) call askr('Enter flap hinge x location^', Xf) 172 | ! 173 | !---- find top and bottom y at hinge x location 174 | Tops = S(1) + (X(1) - Xf) 175 | Bots = S(N) - (X(N) - Xf) 176 | call sinvrt(Tops, Xf, X, Xp, S, N) 177 | call sinvrt(Bots, Xf, X, Xp, S, N) 178 | topy = seval(Tops, Y, Yp, S, N) 179 | boty = seval(Bots, Y, Yp, S, N) 180 | ! 181 | if (show_output) write (*, 99001) topy, boty 182 | 99001 format (/' Top surface: y =', f8.4, ' y/t = 1.0'/' Bottom surface: y =', f8.4, ' y/t = 0.0') 183 | ! 184 | if (Yf==-999.0) call askr('Enter flap hinge y location (or 999 to specify y/t)^', Yf) 185 | ! 186 | if (Yf==999.0) then 187 | call askr('Enter flap hinge relative y/t location^', yrel) 188 | Yf = topy * yrel + boty * (1.0 - yrel) 189 | endif 190 | ! 191 | end subroutine getxyf 192 | 193 | end module m_xgdes -------------------------------------------------------------------------------- /src/fortran/m_xutils.f90: -------------------------------------------------------------------------------- 1 | !*********************************************************************** 2 | ! Copyright (c) 2019 D. de Vries 3 | ! Original Copyright (c) 2000 Mark Drela 4 | ! 5 | ! This file is part of XFoil. 6 | ! 7 | ! XFoil is free software: you can redistribute it and/or modify 8 | ! it under the terms of the GNU General Public License as published by 9 | ! the Free Software Foundation, either version 3 of the License, or 10 | ! (at your option) any later version. 11 | ! 12 | ! XFoil is distributed in the hope that it will be useful, 13 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | ! GNU General Public License for more details. 16 | ! 17 | ! You should have received a copy of the GNU General Public License 18 | ! along with XFoil. If not, see . 19 | !*********************************************************************** 20 | 21 | !*==M_XUTILS.f90 processed by SPAG 7.21DC at 11:25 on 11 Jan 2019 22 | module m_xutils 23 | implicit none 24 | ! 25 | !*** Start of declarations rewritten by SPAG 26 | ! 27 | !*** End of declarations rewritten by SPAG 28 | ! 29 | ! 30 | !*** Start of declarations rewritten by SPAG 31 | ! 32 | !*** End of declarations rewritten by SPAG 33 | ! 34 | contains 35 | subroutine setexp(S, Ds1, Smax, Nn) 36 | use i_xfoil, only: show_output 37 | implicit none 38 | ! 39 | !*** Start of declarations rewritten by SPAG 40 | ! 41 | ! Dummy arguments 42 | ! 43 | real :: Ds1, Smax 44 | integer :: Nn 45 | real, dimension(Nn) :: S 46 | intent (in) Ds1, Nn, Smax 47 | intent (inout) S 48 | ! 49 | ! Local variables 50 | ! 51 | real :: aaa, bbb, ccc, disc, dratio, dresdr, ds, ratio, res, rnex, rni, sigma, sigman 52 | integer :: iter, n, nex 53 | ! 54 | !*** End of declarations rewritten by SPAG 55 | ! 56 | ! 57 | !*** Start of declarations rewritten by SPAG 58 | ! 59 | ! Dummy arguments 60 | ! 61 | ! 62 | ! Local variables 63 | ! 64 | ! 65 | !*** End of declarations rewritten by SPAG 66 | ! 67 | !........................................................ 68 | ! Sets geometrically stretched array S: 69 | ! 70 | ! S(i+1) - S(i) = r * [S(i) - S(i-1)] 71 | ! 72 | ! S (output) array to be set 73 | ! DS1 (input) first S increment: S(2) - S(1) 74 | ! SMAX (input) final S value: S(NN) 75 | ! NN (input) number of points 76 | !........................................................ 77 | ! 78 | sigma = Smax / Ds1 79 | nex = Nn - 1 80 | rnex = float(nex) 81 | rni = 1.0 / rnex 82 | ! 83 | !---- solve quadratic for initial geometric ratio guess 84 | aaa = rnex * (rnex - 1.0) * (rnex - 2.0) / 6.0 85 | bbb = rnex * (rnex - 1.0) / 2.0 86 | ccc = rnex - sigma 87 | ! 88 | disc = bbb**2 - 4.0 * aaa * ccc 89 | disc = max(0.0, disc) 90 | ! 91 | if (nex<=1) then 92 | stop 'SETEXP: Cannot fill array. N too small.' 93 | elseif (nex==2) then 94 | ratio = -ccc / bbb + 1.0 95 | else 96 | ratio = (-bbb + sqrt(disc)) / (2.0 * aaa) + 1.0 97 | endif 98 | ! 99 | if (ratio/=1.0) then 100 | ! 101 | !---- Newton iteration for actual geometric ratio 102 | do iter = 1, 100 103 | sigman = (ratio**nex - 1.0) / (ratio - 1.0) 104 | res = sigman**rni - sigma**rni 105 | dresdr = rni * sigman**rni * (rnex * ratio**(nex - 1) - sigman) / (ratio**nex - 1.0) 106 | ! 107 | dratio = -res / dresdr 108 | ratio = ratio + dratio 109 | ! 110 | if (abs(dratio)<1.0E-5) goto 100 111 | ! 112 | enddo 113 | if (show_output) write (*, *) 'SETEXP: Convergence failed. Continuing anyway ...' 114 | endif 115 | ! 116 | !---- set up stretched array using converged geometric ratio 117 | 100 S(1) = 0.0 118 | ds = Ds1 119 | do n = 2, Nn 120 | S(n) = S(n - 1) + ds 121 | ds = ds * ratio 122 | enddo 123 | ! 124 | end subroutine setexp 125 | 126 | 127 | function atanc(Y, X, Thold) 128 | implicit none 129 | ! 130 | !*** Start of declarations rewritten by SPAG 131 | ! 132 | ! Dummy arguments 133 | ! 134 | real :: Thold, X, Y 135 | real :: atanc 136 | intent (in) Thold, X, Y 137 | ! 138 | ! Local variables 139 | ! 140 | real :: dtcorr, dthet, thnew 141 | real, save :: pi, tpi 142 | ! 143 | !*** End of declarations rewritten by SPAG 144 | ! 145 | ! 146 | !*** Start of declarations rewritten by SPAG 147 | ! 148 | ! Dummy arguments 149 | ! 150 | ! 151 | ! Local variables 152 | ! 153 | ! 154 | !*** End of declarations rewritten by SPAG 155 | ! 156 | !--------------------------------------------------------------- 157 | ! ATAN2 function with branch cut checking. 158 | ! 159 | ! Increments position angle of point X,Y from some previous 160 | ! value THOLD due to a change in position, ensuring that the 161 | ! position change does not cross the ATAN2 branch cut 162 | ! (which is in the -x direction). For example: 163 | ! 164 | ! ATANC( -1.0 , -1.0 , 0.75*pi ) returns 1.25*pi , whereas 165 | ! ATAN2( -1.0 , -1.0 ) returns -.75*pi . 166 | ! 167 | ! Typically, ATANC is used to fill an array of angles: 168 | ! 169 | ! THETA(1) = ATAN2( Y(1) , X(1) ) 170 | ! DO i=2, N 171 | ! THETA(i) = ATANC( Y(i) , X(i) , THETA(i-1) ) 172 | ! END DO 173 | ! 174 | ! This will prevent the angle array THETA(i) from jumping by 175 | ! +/- 2 pi when the path X(i),Y(i) crosses the negative x axis. 176 | ! 177 | ! Input: 178 | ! X,Y point position coordinates 179 | ! THOLD position angle of nearby point 180 | ! 181 | ! Output: 182 | ! ATANC position angle of X,Y 183 | !--------------------------------------------------------------- 184 | data pi/3.1415926535897932384/ 185 | data tpi/6.2831853071795864769/ 186 | ! 187 | !---- set new position angle, ignoring branch cut in ATAN2 function for now 188 | thnew = atan2(Y, X) 189 | dthet = thnew - Thold 190 | ! 191 | !---- angle change cannot exceed +/- pi, so get rid of any multiples of 2 pi 192 | dtcorr = dthet - tpi * int((dthet + sign(pi, dthet)) / tpi) 193 | ! 194 | !---- set correct new angle 195 | atanc = Thold + dtcorr 196 | ! 197 | end function atanc 198 | ! ATANC 199 | end module m_xutils 200 | -------------------------------------------------------------------------------- /src/fortran/p_xfoil.f90: -------------------------------------------------------------------------------- 1 | !*********************************************************************** 2 | ! Copyright (c) 2019 D. de Vries 3 | ! 4 | ! This file is part of XFoil. 5 | ! 6 | ! XFoil is free software: you can redistribute it and/or modify 7 | ! it under the terms of the GNU General Public License as published by 8 | ! the Free Software Foundation, either version 3 of the License, or 9 | ! (at your option) any later version. 10 | ! 11 | ! XFoil is distributed in the hope that it will be useful, 12 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | ! GNU General Public License for more details. 15 | ! 16 | ! You should have received a copy of the GNU General Public License 17 | ! along with XFoil. If not, see . 18 | !*********************************************************************** 19 | ! 20 | program p_xfoil 21 | use m_xfoil, only: xfoil 22 | call xfoil 23 | end program p_xfoil 24 | -------------------------------------------------------------------------------- /src/fortran/s_xbl.f90: -------------------------------------------------------------------------------- 1 | !*********************************************************************** 2 | ! Copyright (c) 2019 D. de Vries 3 | ! Original Copyright (c) 2000 Mark Drela 4 | ! 5 | ! This file is part of XFoil. 6 | ! 7 | ! XFoil is free software: you can redistribute it and/or modify 8 | ! it under the terms of the GNU General Public License as published by 9 | ! the Free Software Foundation, either version 3 of the License, or 10 | ! (at your option) any later version. 11 | ! 12 | ! XFoil is distributed in the hope that it will be useful, 13 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | ! GNU General Public License for more details. 16 | ! 17 | ! You should have received a copy of the GNU General Public License 18 | ! along with XFoil. If not, see . 19 | !*********************************************************************** 20 | 21 | module s_xbl 22 | contains 23 | ! iblsys was originally in xbl between setbl and mrchue. 24 | ! It was moved here to avoid a circular use dependency. 25 | subroutine iblsys 26 | use i_xfoil 27 | use i_xbl 28 | implicit none 29 | ! 30 | !*** Start of declarations rewritten by SPAG 31 | ! 32 | ! Local variables 33 | ! 34 | integer :: ibl, is, iv 35 | ! 36 | !*** End of declarations rewritten by SPAG 37 | ! 38 | ! 39 | !*** Start of declarations rewritten by SPAG 40 | ! 41 | ! Local variables 42 | ! 43 | ! 44 | !*** End of declarations rewritten by SPAG 45 | ! 46 | !--------------------------------------------- 47 | ! Sets the BL Newton system line number 48 | ! corresponding to each BL station. 49 | !--------------------------------------------- 50 | iv = 0 51 | do is = 1, 2 52 | do ibl = 2, NBL(is) 53 | iv = iv + 1 54 | ISYs(ibl, is) = iv 55 | enddo 56 | enddo 57 | ! 58 | NSYs = iv 59 | if (NSYs>2 * IVX) stop '*** IBLSYS: BL system array overflow. ***' 60 | ! 61 | end subroutine iblsys 62 | !*==MRCHUE.f90 processed by SPAG 7.21DC at 11:25 on 11 Jan 2019 63 | end module s_xbl -------------------------------------------------------------------------------- /src/fortran/s_xfoil.f90: -------------------------------------------------------------------------------- 1 | !*********************************************************************** 2 | ! Copyright (c) 2019 D. de Vries 3 | ! Original Copyright (c) 2000 Mark Drela 4 | ! 5 | ! This file is part of XFoil. 6 | ! 7 | ! XFoil is free software: you can redistribute it and/or modify 8 | ! it under the terms of the GNU General Public License as published by 9 | ! the Free Software Foundation, either version 3 of the License, or 10 | ! (at your option) any later version. 11 | ! 12 | ! XFoil is distributed in the hope that it will be useful, 13 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | ! GNU General Public License for more details. 16 | ! 17 | ! You should have received a copy of the GNU General Public License 18 | ! along with XFoil. If not, see . 19 | !*********************************************************************** 20 | 21 | module s_xfoil 22 | contains 23 | subroutine mrcl(Cls, M_cls, R_cls) 24 | use i_xfoil 25 | implicit none 26 | ! 27 | !*** Start of declarations rewritten by SPAG 28 | ! 29 | ! Dummy arguments 30 | ! 31 | real :: Cls, M_cls, R_cls 32 | intent (in) Cls 33 | intent (out) M_cls, R_cls 34 | ! 35 | ! Local variables 36 | ! 37 | real :: cla, rrat 38 | ! 39 | !*** End of declarations rewritten by SPAG 40 | ! 41 | ! 42 | !*** Start of declarations rewritten by SPAG 43 | ! 44 | ! Dummy arguments 45 | ! 46 | ! 47 | ! Local variables 48 | ! 49 | ! 50 | !*** End of declarations rewritten by SPAG 51 | ! 52 | !------------------------------------------- 53 | ! Sets actual Mach, Reynolds numbers 54 | ! from unit-CL values and specified CLS 55 | ! depending on MATYP,RETYP flags. 56 | !------------------------------------------- 57 | ! 58 | cla = max(Cls, 0.000001) 59 | ! 60 | if (RETyp<1 .or. RETyp>3) then 61 | if (show_output) then 62 | write (*, *) 'MRCL: Illegal Re(CL) dependence trigger.' 63 | write (*, *) ' Setting fixed Re.' 64 | endif 65 | RETyp = 1 66 | endif 67 | if (MATyp<1 .or. MATyp>3) then 68 | if (show_output) then 69 | write (*, *) 'MRCL: Illegal Mach(CL) dependence trigger.' 70 | write (*, *) ' Setting fixed Mach.' 71 | endif 72 | MATyp = 1 73 | endif 74 | ! 75 | ! 76 | if (MATyp==1) then 77 | ! 78 | MINf = MINf1 79 | M_cls = 0. 80 | ! 81 | elseif (MATyp==2) then 82 | ! 83 | MINf = MINf1 / sqrt(cla) 84 | M_cls = -0.5 * MINf / cla 85 | ! 86 | elseif (MATyp==3) then 87 | ! 88 | MINf = MINf1 89 | M_cls = 0. 90 | ! 91 | endif 92 | ! 93 | ! 94 | if (RETyp==1) then 95 | ! 96 | REInf = REInf1 97 | R_cls = 0. 98 | ! 99 | elseif (RETyp==2) then 100 | ! 101 | REInf = REInf1 / sqrt(cla) 102 | R_cls = -0.5 * REInf / cla 103 | ! 104 | elseif (RETyp==3) then 105 | ! 106 | REInf = REInf1 / cla 107 | R_cls = -REInf / cla 108 | ! 109 | endif 110 | ! 111 | ! 112 | if (MINf>=0.99) then 113 | if (show_output) then 114 | write (*, *) 115 | write (*, *) 'MRCL: CL too low for chosen Mach(CL) dependence' 116 | write (*, *) ' Aritificially limiting Mach to 0.99' 117 | endif 118 | MINf = 0.99 119 | M_cls = 0. 120 | endif 121 | ! 122 | rrat = 1.0 123 | if (REInf1>0.0) rrat = REInf / REInf1 124 | ! 125 | if (rrat>100.0) then 126 | if (show_output) then 127 | write (*, *) 128 | write (*, *) 'MRCL: CL too low for chosen Re(CL) dependence' 129 | write (*, *) ' Aritificially limiting Re to ', REInf1 * 100.0 130 | endif 131 | REInf = REInf1 * 100.0 132 | R_cls = 0. 133 | endif 134 | ! 135 | end subroutine mrcl 136 | !*==GETDEF.f90 processed by SPAG 7.21DC at 11:25 on 11 Jan 2019 137 | ! MRCL 138 | 139 | 140 | subroutine comset 141 | use i_xfoil 142 | implicit none 143 | ! 144 | !*** Start of declarations rewritten by SPAG 145 | ! 146 | ! Local variables 147 | ! 148 | real :: beta, beta_msq 149 | ! 150 | !*** End of declarations rewritten by SPAG 151 | ! 152 | ! 153 | !*** Start of declarations rewritten by SPAG 154 | ! 155 | ! Local variables 156 | ! 157 | ! 158 | !*** End of declarations rewritten by SPAG 159 | ! 160 | ! 161 | !---- set Karman-Tsien parameter TKLAM 162 | beta = sqrt(1.0 - MINf**2) 163 | beta_msq = -0.5 / beta 164 | ! 165 | TKLam = MINf**2 / (1.0 + beta)**2 166 | TKL_msq = 1.0 / (1.0 + beta)**2 - 2.0 * TKLam / (1.0 + beta) * beta_msq 167 | ! 168 | !---- set sonic Pressure coefficient and speed 169 | if (MINf==0.0) then 170 | CPStar = -999.0 171 | QSTar = 999.0 172 | else 173 | CPStar = 2.0 / (GAMma * MINf**2) & 174 | * (((1.0 + 0.5 * GAMm1 * MINf**2) / (1.0 + 0.5 * GAMm1))**(GAMma / GAMm1) - 1.0) 175 | QSTar = QINf / MINf * sqrt((1.0 + 0.5 * GAMm1 * MINf**2) / (1.0 + 0.5 * GAMm1)) 176 | endif 177 | ! 178 | end subroutine comset 179 | !*==CPCALC.f90 processed by SPAG 7.21DC at 11:25 on 11 Jan 2019 180 | ! COMSET 181 | 182 | subroutine cpcalc(N, Q, Qinf, Minf, Cp) 183 | use i_xfoil, only: show_output 184 | implicit none 185 | ! 186 | !*** Start of declarations rewritten by SPAG 187 | ! 188 | ! Dummy arguments 189 | ! 190 | real :: Minf, Qinf 191 | integer :: N 192 | real, dimension(N) :: Cp, Q 193 | intent (in) Minf, N, Q, Qinf 194 | intent (out) Cp 195 | ! 196 | ! Local variables 197 | ! 198 | real :: beta, bfac, cpinc, den 199 | logical :: denneg 200 | integer :: i 201 | ! 202 | !*** End of declarations rewritten by SPAG 203 | ! 204 | ! 205 | !*** Start of declarations rewritten by SPAG 206 | ! 207 | ! Dummy arguments 208 | ! 209 | ! 210 | ! Local variables 211 | ! 212 | ! 213 | !*** End of declarations rewritten by SPAG 214 | ! 215 | !--------------------------------------------- 216 | ! Sets compressible Cp from speed. 217 | !--------------------------------------------- 218 | ! 219 | ! 220 | beta = sqrt(1.0 - Minf**2) 221 | bfac = 0.5 * Minf**2 / (1.0 + beta) 222 | ! 223 | denneg = .false. 224 | ! 225 | do i = 1, N 226 | cpinc = 1.0 - (Q(i) / Qinf)**2 227 | den = beta + bfac * cpinc 228 | Cp(i) = cpinc / den 229 | if (den<=0.0) denneg = .true. 230 | enddo 231 | ! 232 | if (denneg) then 233 | if (show_output) then 234 | write (*, *) 235 | write (*, *) 'CPCALC: Local speed too large. ', 'Compressibility corrections invalid.' 236 | endif 237 | endif 238 | ! 239 | end subroutine cpcalc 240 | !*==CLCALC.f90 processed by SPAG 7.21DC at 11:25 on 11 Jan 2019 241 | ! CPCALC 242 | 243 | 244 | subroutine clcalc(N, X, Y, Gam, Gam_a, Alfa, Minf, Qinf, Xref, Yref, Cl, Cm, Cdp, Cl_alf, Cl_msq) 245 | implicit none 246 | ! 247 | !*** Start of declarations rewritten by SPAG 248 | ! 249 | ! Dummy arguments 250 | ! 251 | real :: Alfa, Cdp, Cl, Cl_alf, Cl_msq, Cm, Minf, Qinf, Xref, Yref 252 | integer :: N 253 | real, dimension(N) :: Gam, Gam_a, X, Y 254 | intent (in) Alfa, Gam, Gam_a, Minf, N, Qinf, X, Xref, Y, Yref 255 | intent (inout) Cdp, Cl, Cl_alf, Cl_msq, Cm 256 | ! 257 | ! Local variables 258 | ! 259 | real :: ag, ag_alf, ag_msq, ax, ay, beta, beta_msq, bfac, bfac_msq, ca, cginc, cpc_cpi, cpg1, cpg1_alf, & 260 | & cpg1_msq, cpg2, cpg2_alf, cpg2_msq, cpi_gam, dg, dx, dx_alf, dy, sa 261 | integer :: i, ip 262 | ! 263 | !*** End of declarations rewritten by SPAG 264 | ! 265 | ! 266 | !*** Start of declarations rewritten by SPAG 267 | ! 268 | ! Dummy arguments 269 | ! 270 | ! 271 | ! Local variables 272 | ! 273 | ! 274 | !*** End of declarations rewritten by SPAG 275 | ! 276 | !----------------------------------------------------------- 277 | ! Integrates surface pressures to get CL and CM. 278 | ! Integrates skin friction to get CDF. 279 | ! Calculates dCL/dAlpha for prescribed-CL routines. 280 | !----------------------------------------------------------- 281 | ! 282 | !cC---- moment-reference coordinates 283 | !c XREF = 0.25 284 | !c YREF = 0. 285 | ! 286 | sa = sin(Alfa) 287 | ca = cos(Alfa) 288 | ! 289 | beta = sqrt(1.0 - Minf**2) 290 | beta_msq = -0.5 / beta 291 | ! 292 | bfac = 0.5 * Minf**2 / (1.0 + beta) 293 | bfac_msq = 0.5 / (1.0 + beta) - bfac / (1.0 + beta) * beta_msq 294 | ! 295 | Cl = 0.0 296 | Cm = 0.0 297 | 298 | Cdp = 0.0 299 | ! 300 | Cl_alf = 0. 301 | Cl_msq = 0. 302 | ! 303 | i = 1 304 | cginc = 1.0 - (Gam(i) / Qinf)**2 305 | cpg1 = cginc / (beta + bfac * cginc) 306 | cpg1_msq = -cpg1 / (beta + bfac * cginc) * (beta_msq + bfac_msq * cginc) 307 | ! 308 | cpi_gam = -2.0 * Gam(i) / Qinf**2 309 | cpc_cpi = (1.0 - bfac * cpg1) / (beta + bfac * cginc) 310 | cpg1_alf = cpc_cpi * cpi_gam * Gam_a(i) 311 | ! 312 | do i = 1, N 313 | ip = i + 1 314 | if (i==N) ip = 1 315 | ! 316 | cginc = 1.0 - (Gam(ip) / Qinf)**2 317 | cpg2 = cginc / (beta + bfac * cginc) 318 | cpg2_msq = -cpg2 / (beta + bfac * cginc) * (beta_msq + bfac_msq * cginc) 319 | ! 320 | cpi_gam = -2.0 * Gam(ip) / Qinf**2 321 | cpc_cpi = (1.0 - bfac * cpg2) / (beta + bfac * cginc) 322 | cpg2_alf = cpc_cpi * cpi_gam * Gam_a(ip) 323 | ! 324 | dx = (X(ip) - X(i)) * ca + (Y(ip) - Y(i)) * sa 325 | dy = (Y(ip) - Y(i)) * ca - (X(ip) - X(i)) * sa 326 | dg = cpg2 - cpg1 327 | ! 328 | ax = (0.5 * (X(ip) + X(i)) - Xref) * ca + (0.5 * (Y(ip) + Y(i)) - Yref) * sa 329 | ay = (0.5 * (Y(ip) + Y(i)) - Yref) * ca - (0.5 * (X(ip) + X(i)) - Xref) * sa 330 | ag = 0.5 * (cpg2 + cpg1) 331 | ! 332 | dx_alf = -(X(ip) - X(i)) * sa + (Y(ip) - Y(i)) * ca 333 | ag_alf = 0.5 * (cpg2_alf + cpg1_alf) 334 | ag_msq = 0.5 * (cpg2_msq + cpg1_msq) 335 | ! 336 | Cl = Cl + dx * ag 337 | Cdp = Cdp - dy * ag 338 | Cm = Cm - dx * (ag * ax + dg * dx / 12.0) - dy * (ag * ay + dg * dy / 12.0) 339 | ! 340 | Cl_alf = Cl_alf + dx * ag_alf + ag * dx_alf 341 | Cl_msq = Cl_msq + dx * ag_msq 342 | ! 343 | cpg1 = cpg2 344 | cpg1_alf = cpg2_alf 345 | cpg1_msq = cpg2_msq 346 | enddo 347 | ! 348 | end subroutine clcalc 349 | !*==CDCALC.f90 processed by SPAG 7.21DC at 11:25 on 11 Jan 2019 350 | ! CLCALC 351 | 352 | 353 | subroutine cdcalc 354 | use i_xfoil 355 | implicit none 356 | ! 357 | !*** Start of declarations rewritten by SPAG 358 | ! 359 | ! Local variables 360 | ! 361 | real :: ca, dx, sa, shwake, thwake, uewake, urat 362 | integer :: i, ibl, im, is 363 | ! 364 | !*** End of declarations rewritten by SPAG 365 | ! 366 | ! 367 | !*** Start of declarations rewritten by SPAG 368 | ! 369 | ! Local variables 370 | ! 371 | ! 372 | !*** End of declarations rewritten by SPAG 373 | ! 374 | ! 375 | sa = sin(ALFa) 376 | ca = cos(ALFa) 377 | ! 378 | if (LVIsc .and. LBLini) then 379 | ! 380 | !----- set variables at the end of the wake 381 | thwake = THEt(NBL(2), 2) 382 | urat = UEDg(NBL(2), 2) / QINf 383 | uewake = UEDg(NBL(2), 2) * (1.0 - TKLam) / (1.0 - TKLam * urat**2) 384 | shwake = DSTr(NBL(2), 2) / THEt(NBL(2), 2) 385 | ! 386 | !----- extrapolate wake to downstream infinity using Squire-Young relation 387 | ! (reduces errors of the wake not being long enough) 388 | CD = 2.0 * thwake * (uewake / QINf)**(0.5 * (5.0 + shwake)) 389 | ! 390 | else 391 | ! 392 | CD = 0.0 393 | ! 394 | endif 395 | ! 396 | !---- calculate friction drag coefficient 397 | CDF = 0.0 398 | do is = 1, 2 399 | do ibl = 3, IBLte(is) 400 | i = IPAn(ibl, is) 401 | im = IPAn(ibl - 1, is) 402 | dx = (X(i) - X(im)) * ca + (Y(i) - Y(im)) * sa 403 | CDF = CDF + 0.5 * (TAU(ibl, is) + TAU(ibl - 1, is)) * dx * 2.0 / QINf**2 404 | enddo 405 | enddo 406 | ! 407 | end subroutine cdcalc 408 | !*==LOAD.f90 processed by SPAG 7.21DC at 11:25 on 11 Jan 2019 409 | ! CDCALC 410 | 411 | 412 | subroutine tecalc 413 | use i_xfoil 414 | implicit none 415 | ! 416 | !*** Start of declarations rewritten by SPAG 417 | ! 418 | ! Local variables 419 | ! 420 | real :: dxs, dxte, dys, dyte, scs, sds 421 | ! 422 | !*** End of declarations rewritten by SPAG 423 | ! 424 | ! 425 | !*** Start of declarations rewritten by SPAG 426 | ! 427 | ! Local variables 428 | ! 429 | ! 430 | !*** End of declarations rewritten by SPAG 431 | ! 432 | !------------------------------------------- 433 | ! Calculates total and projected TE gap 434 | ! areas and TE panel strengths. 435 | !------------------------------------------- 436 | ! 437 | !---- set TE base vector and TE bisector components 438 | dxte = X(1) - X(N) 439 | dyte = Y(1) - Y(N) 440 | dxs = 0.5 * (-XP(1) + XP(N)) 441 | dys = 0.5 * (-YP(1) + YP(N)) 442 | ! 443 | !---- normal and streamwise projected TE gap areas 444 | ANTe = dxs * dyte - dys * dxte 445 | ASTe = dxs * dxte + dys * dyte 446 | ! 447 | !---- total TE gap area 448 | DSTe = sqrt(dxte**2 + dyte**2) 449 | ! 450 | SHArp = DSTe<0.0001 * CHOrd 451 | ! 452 | if (SHArp) then 453 | scs = 1.0 454 | sds = 0.0 455 | else 456 | scs = ANTe / DSTe 457 | sds = ASTe / DSTe 458 | endif 459 | ! 460 | !---- TE panel source and vorticity strengths 461 | SIGte = 0.5 * (GAM(1) - GAM(N)) * scs 462 | GAMte = -.5 * (GAM(1) - GAM(N)) * sds 463 | ! 464 | SIGte_a = 0.5 * (GAM_a(1) - GAM_a(N)) * scs 465 | GAMte_a = -.5 * (GAM_a(1) - GAM_a(N)) * sds 466 | ! 467 | end subroutine tecalc 468 | !*==INTE.f90 processed by SPAG 7.21DC at 11:25 on 11 Jan 2019 469 | ! TECALC 470 | 471 | end module s_xfoil -------------------------------------------------------------------------------- /src/fortran/s_xoper.f90: -------------------------------------------------------------------------------- 1 | !*********************************************************************** 2 | ! Copyright (c) 2019 D. de Vries 3 | ! Original Copyright (c) 2000 Mark Drela 4 | ! 5 | ! This file is part of XFoil. 6 | ! 7 | ! XFoil is free software: you can redistribute it and/or modify 8 | ! it under the terms of the GNU General Public License as published by 9 | ! the Free Software Foundation, either version 3 of the License, or 10 | ! (at your option) any later version. 11 | ! 12 | ! XFoil is distributed in the hope that it will be useful, 13 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | ! GNU General Public License for more details. 16 | ! 17 | ! You should have received a copy of the GNU General Public License 18 | ! along with XFoil. If not, see . 19 | !*********************************************************************** 20 | 21 | module s_xoper 22 | contains 23 | ! mhinge was originally in xoper between cpdump and vpar 24 | ! It was moved here to avoid a circular dependency. 25 | subroutine mhinge 26 | use m_xgdes, only : getxyf 27 | use m_spline, only : seval, sinvrt 28 | use i_xfoil 29 | implicit none 30 | ! 31 | !*** Start of declarations rewritten by SPAG 32 | ! 33 | ! Local variables 34 | ! 35 | real :: botp, bots, botx, boty, dx, dy, frac, pmid, topp, tops, topx, topy, xmid, ymid 36 | integer :: i 37 | ! 38 | !*** End of declarations rewritten by SPAG 39 | ! 40 | ! 41 | !*** Start of declarations rewritten by SPAG 42 | ! 43 | ! Local variables 44 | ! 45 | ! 46 | !*** End of declarations rewritten by SPAG 47 | ! 48 | !---------------------------------------------------- 49 | ! Calculates the hinge moment of the flap about 50 | ! (XOF,YOF) by integrating surface pressures. 51 | !---------------------------------------------------- 52 | ! 53 | if (.not.LFLap) then 54 | ! 55 | call getxyf(X, XP, Y, YP, S, N, tops, bots, XOF, YOF) 56 | LFLap = .true. 57 | ! 58 | else 59 | ! 60 | !------ find top and bottom y at hinge x location 61 | tops = XOF 62 | bots = S(N) - XOF 63 | call sinvrt(tops, XOF, X, XP, S, N) 64 | call sinvrt(bots, XOF, X, XP, S, N) 65 | ! 66 | endif 67 | ! 68 | topx = seval(tops, X, XP, S, N) 69 | topy = seval(tops, Y, YP, S, N) 70 | botx = seval(bots, X, XP, S, N) 71 | boty = seval(bots, Y, YP, S, N) 72 | ! 73 | ! 74 | HMOm = 0. 75 | HFX = 0. 76 | HFY = 0. 77 | ! 78 | !---- integrate pressures on top and bottom sides of flap 79 | do i = 2, N 80 | if (S(i - 1)bots) then 81 | ! 82 | dx = X(i) - X(i - 1) 83 | dy = Y(i) - Y(i - 1) 84 | xmid = 0.5 * (X(i) + X(i - 1)) - XOF 85 | ymid = 0.5 * (Y(i) + Y(i - 1)) - YOF 86 | if (LVIsc) then 87 | pmid = 0.5 * (CPV(i) + CPV(i - 1)) 88 | else 89 | pmid = 0.5 * (CPI(i) + CPI(i - 1)) 90 | endif 91 | HMOm = HMOm + pmid * (xmid * dx + ymid * dy) 92 | HFX = HFX - pmid * dy 93 | HFY = HFY + pmid * dx 94 | endif 95 | enddo 96 | ! 97 | !---- find S(I)..S(I-1) interval containing s=TOPS 98 | do i = 2, N 99 | if (S(i)>tops) exit 100 | enddo 101 | ! 102 | !---- add on top surface chunk TOPS..S(I-1), missed in the DO 20 loop. 103 | dx = topx - X(i - 1) 104 | dy = topy - Y(i - 1) 105 | xmid = 0.5 * (topx + X(i - 1)) - XOF 106 | ymid = 0.5 * (topy + Y(i - 1)) - YOF 107 | if (S(i)/=S(i - 1)) then 108 | frac = (tops - S(i - 1)) / (S(i) - S(i - 1)) 109 | else 110 | frac = 0. 111 | endif 112 | if (LVIsc) then 113 | topp = CPV(i) * frac + CPV(i - 1) * (1.0 - frac) 114 | pmid = 0.5 * (topp + CPV(i - 1)) 115 | else 116 | topp = CPI(i) * frac + CPI(i - 1) * (1.0 - frac) 117 | pmid = 0.5 * (topp + CPI(i - 1)) 118 | endif 119 | HMOm = HMOm + pmid * (xmid * dx + ymid * dy) 120 | HFX = HFX - pmid * dy 121 | HFY = HFY + pmid * dx 122 | ! 123 | !---- add on inside flap surface contribution from hinge to top surface 124 | dx = XOF - topx 125 | dy = YOF - topy 126 | xmid = 0.5 * (topx + XOF) - XOF 127 | ymid = 0.5 * (topy + YOF) - YOF 128 | HMOm = HMOm + pmid * (xmid * dx + ymid * dy) 129 | HFX = HFX - pmid * dy 130 | HFY = HFY + pmid * dx 131 | ! 132 | !---- find S(I)..S(I-1) interval containing s=BOTS 133 | do i = N, 2, -1 134 | if (S(i - 1). 18 | from .xfoil import XFoil 19 | from .model import Airfoil 20 | from .model_parametrized import Parsec 21 | from .bdlayer import BoundaryLayer 22 | from .cpdist import CpAnalysis -------------------------------------------------------------------------------- /src/xfoil/bdlayer.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | 4 | from dotmap import DotMap 5 | 6 | class BoundaryLayer(): 7 | """Read and process the boundary layer file created by Xfoil. 8 | 9 | The boundary layer properties are created as a DotMap with 10 | the following levels: 11 | - upper 12 | - lower 13 | - wake 14 | 15 | Note 16 | ---- 17 | It assumes the file already exists when it is instantiated. 18 | """ 19 | 20 | def __init__(self, filename): 21 | 22 | self.filename = filename 23 | 24 | # Read the file 25 | self._read_file() 26 | 27 | # Postprocess 28 | self._find_airfoil() 29 | self._trim_coord() 30 | self._trim_boundary_layer() 31 | 32 | def _read_file(self): 33 | """Read the boundary layer file and 34 | extract the data in the right format. 35 | """ 36 | # Read the boundary data file 37 | df_bl = pd.read_csv(self.filename, delim_whitespace=True) 38 | 39 | # Get all the variables 40 | self.variables = df_bl.columns 41 | 42 | # Remove the columns that do not contain data 43 | df_bl.dropna(axis=1, how='all', inplace=True) 44 | 45 | # Rename the columns appropriately 46 | df_bl.columns = self.variables[1:len(df_bl.columns)+1] 47 | 48 | # Extract all the variables 49 | self.s_raw = df_bl['s'].values 50 | self.x_raw = df_bl['x'].values 51 | self.y_raw = df_bl['y'].values 52 | 53 | self.ue_vinfty_raw = df_bl['Ue/Vinf'].values 54 | self.d_star_raw = df_bl['Dstar'].values 55 | self.theta_raw = df_bl['Theta'].values 56 | 57 | self.cf_raw = df_bl['Cf'].values 58 | 59 | self.H_raw = df_bl['H'].values 60 | self.H_star_raw = df_bl['H*'].values 61 | 62 | self.P_raw = df_bl['P'].values 63 | self.m_raw = df_bl['m'].values 64 | 65 | # Memory clean-up 66 | self.df_bl = df_bl 67 | 68 | def _find_airfoil(self): 69 | """Find the array index at the end of the profile. 70 | 71 | Notes 72 | ----- 73 | Creates attribute last_index. 74 | """ 75 | coord_LE = np.min(self.x_raw) 76 | 77 | self.idx_LE = np.where(self.x_raw == coord_LE)[0][0] 78 | _, self.idx_TE = np.where(self.x_raw == 1.0)[0] 79 | 80 | def _get_trimmed_values(self, property): 81 | """Trim the boundary layer property according to the three sections present: 82 | - Upper surface 83 | - Lower surface 84 | - Wake 85 | 86 | Parameters 87 | ---------- 88 | property: numpy array 89 | 90 | Returns 91 | ------- 92 | DotMap 93 | - Keys: 94 | - "upper" 95 | - "lower" 96 | - "wake" 97 | - Values: numpy arrays 98 | 99 | Notes 100 | ----- 101 | The length of upper and lower is not necessarily the same due to curvature. 102 | """ 103 | data = DotMap() 104 | data.upper = property[0 :self.idx_LE+1] 105 | data.lower = property[self.idx_LE :self.idx_TE+1] 106 | data.wake = property[self.idx_TE+1: ] 107 | 108 | return data 109 | 110 | def _trim_boundary_layer(self): 111 | """ 112 | Cut the boundary layer properties between airfoil upper, lower sections and wake. 113 | """ 114 | self.cf = self._get_trimmed_values(self.cf_raw) 115 | self.H = self._get_trimmed_values(self.H_raw) 116 | self.H_star = self._get_trimmed_values(self.H_star_raw) 117 | self.theta = self._get_trimmed_values(self.theta_raw) 118 | self.d_star = self._get_trimmed_values(self.d_star_raw) 119 | 120 | def _trim_coord(self): 121 | """Cut the coordinates (x,y,s) between airfoil upper, lower sections and wake. 122 | """ 123 | self.x = self._get_trimmed_values(self.x_raw) 124 | self.y = self._get_trimmed_values(self.y_raw) 125 | self.s = self._get_trimmed_values(self.s_raw) 126 | 127 | def detect_bubbles(self): 128 | """ 129 | Detect any recirculation bubble via the Cf coefficient. 130 | 131 | Returns 132 | ------- 133 | dict: 134 | - Keys: 135 | - "upper" 136 | - exists 137 | - indices 138 | - length 139 | - "lower" 140 | - ... 141 | """ 142 | 143 | bubble = DotMap() 144 | 145 | # Upper bubble 146 | bubble.upper.exists, bubble.upper.indices = self._detect_bubble(self.cf['upper']) 147 | 148 | # Lower bubble 149 | bubble.lower.exists, bubble.lower.indices = self._detect_bubble(self.cf['lower']) 150 | 151 | # Compute lengths (if any) 152 | if bubble.upper.exists is True: 153 | bubble.upper.length = self.s.upper[bubble.upper.indices[-1]] - self.s.upper[bubble.upper.indices[0]] 154 | else: 155 | bubble.upper.length = 0.0 156 | 157 | if bubble.lower.exists is True: 158 | bubble.lower.length = self.s.lower[bubble.lower.indices[-1]] - self.s.lower[bubble.lower.indices[0]] 159 | else: 160 | bubble.lower.length = 0.0 161 | 162 | return bubble 163 | 164 | def _detect_bubble(self, cf): 165 | """ 166 | Detect bubble in cf section. 167 | 168 | Parameters 169 | ---------- 170 | cf: np.array 171 | 172 | Returns 173 | ------- 174 | tuple: bool, list 175 | bool: True when there is a bubble 176 | list: [start index, last index] of the bubble 177 | """ 178 | 179 | # Look for the the indices with negative cf 180 | idx = np.where(cf<0)[0] 181 | 182 | # Assume no bubble 183 | flag_bubble = False 184 | 185 | # If there are no indices, there is no bubble 186 | if len(idx) == 0: 187 | return flag_bubble, [] 188 | else: 189 | flag_bubble = True 190 | return flag_bubble, [idx[0], idx[-1]] 191 | 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /src/xfoil/cpdist.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | 4 | from dotmap import DotMap 5 | 6 | class CpAnalysis(): 7 | """Read and process the boundary layer file created by Xfoil. 8 | 9 | Note 10 | ---- 11 | It assumes the file already exists when it is instantiated. 12 | """ 13 | 14 | def __init__(self, filename): 15 | 16 | self.filename = filename 17 | 18 | # Read the file 19 | self._read_file() 20 | 21 | self._find_airfoil() 22 | self._trim_variables() 23 | 24 | def _read_file(self): 25 | """Read the boundary layer file and 26 | extract the data in the right format. 27 | """ 28 | # Read the boundary data file 29 | df_cp = pd.read_csv(self.filename, delim_whitespace=True) 30 | 31 | # Get all the variables 32 | self.variables = df_cp.columns 33 | 34 | # Remove the columns that do not contain data 35 | df_cp.dropna(axis=1, how='all', inplace=True) 36 | 37 | # Rename the columns appropriately 38 | df_cp.columns = self.variables[1:len(df_cp.columns)+1] 39 | 40 | # Extract all the variables 41 | self.df_cp = df_cp 42 | 43 | # Memory clean-up 44 | del df_cp 45 | 46 | def _find_airfoil(self): 47 | """Find the array index at the end of the profile. 48 | 49 | Notes 50 | ----- 51 | Creates attribute last_index. 52 | """ 53 | coord_LE = np.min(self.df_cp['x'].values) 54 | 55 | self.idx_LE = np.where(self.df_cp['x'].values == coord_LE)[0][0] 56 | _, self.idx_TE = np.where(self.df_cp['x'].values == 1.0)[0] 57 | 58 | def _trim_variables(self): 59 | 60 | self.cp = DotMap() 61 | self.x = DotMap() 62 | 63 | self.cp.upper = self.df_cp['Cp'].values[0 :self.idx_LE+1] 64 | self.cp.lower = self.df_cp['Cp'].values[self.idx_LE: ] 65 | 66 | self.x.upper = self.df_cp['x'].values[0 :self.idx_LE+1] 67 | self.x.lower = self.df_cp['x'].values[self.idx_LE: ] 68 | -------------------------------------------------------------------------------- /src/xfoil/model.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright (c) 2019 D. de Vries 3 | # 4 | # This file is part of XFoil. 5 | # 6 | # XFoil is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # XFoil is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with XFoil. If not, see . 18 | import numpy as np 19 | 20 | class Airfoil(): 21 | """Airfoil 22 | 23 | Attributes 24 | ---------- 25 | n_coords 26 | x 27 | y 28 | """ 29 | 30 | def __init__(self, x, y): 31 | self.coords = np.ndarray((0, 2)) 32 | self.x = x 33 | self.y = y 34 | 35 | @property 36 | def n_coords(self): 37 | """int: Number of coordinates which define the airfoil surface.""" 38 | return self.coords.shape[0] 39 | 40 | @property 41 | def x(self): 42 | """np.ndarray: List of x-coordinates of the airfoil surface.""" 43 | return self.coords[:, 0] 44 | 45 | @x.setter 46 | def x(self, value): 47 | v = value.flatten() 48 | self.coords.resize((v.size, 2)) 49 | self.coords[:, 0] = v[:] 50 | 51 | @property 52 | def y(self): 53 | """np.ndarray: List of y-coordinates of the airfoil surface.""" 54 | return self.coords[:, 1] 55 | 56 | @y.setter 57 | def y(self, value): 58 | v = value.flatten() 59 | self.coords.resize((v.size, 2)) 60 | self.coords[:, 1] = v[:] 61 | -------------------------------------------------------------------------------- /src/xfoil/model_parametrized.py: -------------------------------------------------------------------------------- 1 | """ 2 | +------------------+------------------------------------------------+ 3 | | PARSEC parameter | Definition | 4 | +------------------+------------------------------------------------+ 5 | | p1 | Leading edge radius | 6 | +------------------+------------------------------------------------+ 7 | | p2 | Upper crest position in horizontal coordinates | 8 | +------------------+------------------------------------------------+ 9 | | p3 | Upper crest position in vertical coordinates | 10 | +------------------+------------------------------------------------+ 11 | | p4 | Upper crest curvature | 12 | +------------------+------------------------------------------------+ 13 | | p5 | Lower crest position in horizontal coordinates | 14 | +------------------+------------------------------------------------+ 15 | | p6 | Lower crest position in vertical coordinates | 16 | +------------------+------------------------------------------------+ 17 | | p7 | Lower crest curvature | 18 | +------------------+------------------------------------------------+ 19 | | p8 | Trailing edge offset in vertical sense | 20 | +------------------+------------------------------------------------+ 21 | | p9 | Trailing edge thickness | 22 | +------------------+------------------------------------------------+ 23 | | p10 | Trailing edge direction | 24 | +------------------+------------------------------------------------+ 25 | | p11 | Trailing edge wedge angle | 26 | +------------------+------------------------------------------------+ 27 | (Generated with http://www.tablesgenerator.com/) 28 | 29 | Source 30 | ------ 31 | Sobieczky H. (1999) Parametric Airfoils and Wings. 32 | In: Fujii K., Dulikravich G.S. (eds) Recent Development of Aerodynamic Design Methodologies. 33 | Notes on Numerical Fluid Mechanics (NNFM), vol 65. Vieweg+Teubner Verlag 34 | """ 35 | 36 | 37 | from copy import deepcopy 38 | 39 | from scipy.optimize import minimize 40 | 41 | import numpy as np 42 | from numpy.linalg import solve 43 | 44 | from xfoil import Airfoil 45 | from dotmap import DotMap 46 | 47 | class ParametrizedAirfoil(): 48 | 49 | def __init__(self, *args, **kwargs): 50 | pass 51 | 52 | def fit(airfoil:Airfoil): 53 | 54 | # Code to find the best fitting coefficients. 55 | 56 | 57 | return design_vector 58 | 59 | class Parsec(ParametrizedAirfoil): 60 | """ 61 | Parsec airfoil parametrization. 62 | 63 | Parameters 64 | ---------- 65 | design_vector: dict 66 | """ 67 | 68 | def __init__(self, design_vector: dict = None, N = 160): 69 | super().__init__() 70 | 71 | # Save design vector 72 | if design_vector is None: 73 | self.dv = self._basic_design_vector() 74 | else: 75 | self.dv = design_vector 76 | 77 | self.N = N 78 | 79 | # Create specific PARSEC coefficient vectors 80 | self._q1 = [n + 1/2 for n in range(0,6)] 81 | self._q2 = [n**2 - 1/4 for n in range(0,6)] 82 | 83 | # Display attributes 84 | self._rhs_upper = None 85 | self._rhs_lower = None 86 | self._matrix_lower = None 87 | self._matrix_upper = None 88 | self._coeff_lower = None 89 | self._coeff_upper = None 90 | 91 | self.x = None 92 | self.y_upper = None 93 | self.y_lower = None 94 | 95 | def _basic_design_vector(self): 96 | """ 97 | Load a basic design vector. 98 | 99 | Parameters 100 | ---------- 101 | None 102 | 103 | Returns 104 | ------- 105 | dict 106 | """ 107 | coeff = [ 108 | 0.05, # p1 | Leading edge radius 109 | 110 | 0.3, # p2 | Upper crest position in horizontal coordinates 111 | 0.1, # p3 | Upper crest position in vertical coordinates 112 | 1.0, # p4 | Upper crest curvature 113 | 114 | 0.3, # p5 | Lower crest position in horizontal coordinates 115 | -0.1, # p6 | Lower crest position in vertical coordinates 116 | 0.1, # p7 | Lower crest curvature 117 | 118 | 0.1, # p8 | Trailing edge offset in vertical sense 119 | 0.1, # p9 | Trailing edge thickness 120 | 1.0, # p10 | Trailing edge direction 121 | 20.0 # p11 | Trailing edge wedge angle 122 | ] 123 | 124 | return {'p{}'.format(q):value for q, value in zip(range(1,12), coeff)} 125 | 126 | def create_airfoil(self, p:dict = None, x: np.array = None): 127 | """ 128 | Create airfoil coordinates compatible with xfoil. 129 | 130 | Parameters 131 | ---------- 132 | p: dict 133 | Default: None 134 | New design vector 135 | 136 | Returns 137 | ------- 138 | Airfoil 139 | """ 140 | if p is not None: 141 | self.dv = deepcopy(p) 142 | else: 143 | pass 144 | 145 | if x is not None: 146 | self.N = len(x) 147 | 148 | # Prepare linear system 149 | self._create_matrices() 150 | self._create_rhs() 151 | 152 | # Solve linear system 153 | self._compute_coefficients() 154 | 155 | # Compute airfoil 156 | self._compute_coordinates(x) 157 | 158 | # Prepare output 159 | x = np.concatenate([np.flip(self.x), self.x[1:]]) 160 | y = np.concatenate([np.flip(self.y_upper), self.y_lower[1:]]) 161 | 162 | return Airfoil(x = x, y = y) 163 | 164 | def _create_rhs(self): 165 | """ 166 | Assemble the RHS vectors for the upper and lower surface. 167 | """ 168 | self._rhs_upper = self._fill_in_rhs(sign = '+') 169 | self._rhs_lower = self._fill_in_rhs(sign = '-') 170 | 171 | def _compute_coefficients(self): 172 | """ 173 | Solve linear system to obtain PARSEC coefficients. 174 | """ 175 | 176 | self._coeff_upper = solve(self._matrix_upper, self._rhs_upper) 177 | self._coeff_lower = solve(self._matrix_lower, self._rhs_lower) 178 | 179 | def _compute_coordinates(self, x: np.array = None): 180 | """ 181 | Compute the airfoil coordinates for the current 182 | design vector. 183 | 184 | Parameters 185 | ---------- 186 | x: np.array 187 | 188 | Returns 189 | ------- 190 | """ 191 | 192 | if x is None: 193 | x = self._cosine_distribution() 194 | 195 | # Make sure we are mapping the [0,1] domain 196 | x = np.sort(x) 197 | 198 | x_q = np.array([x**q for q in self._q1]) 199 | 200 | self.y_upper = np.dot(np.transpose(self._coeff_upper), x_q)[0] 201 | self.y_lower = np.dot(np.transpose(self._coeff_lower), x_q)[0] 202 | 203 | self.x = x 204 | 205 | def _cosine_distribution(self, N:int = None): 206 | """ 207 | Compute a cosine distribution in [0,1]. 208 | 209 | Returns 210 | ------- 211 | x: np.array 212 | """ 213 | 214 | from math import cos, pi 215 | 216 | if N is None: 217 | N = self.N 218 | 219 | x = np.linspace(start = 0, stop = 1, num = N) 220 | x = list(map(cos, x * pi)) 221 | 222 | # Sort from negative to positive 223 | x = np.sort(np.array(x)) 224 | 225 | # Center and scale 226 | x += 1.0 227 | x /= 2.0 228 | 229 | return x 230 | 231 | def _fill_in_rhs(self, sign = '+'): 232 | """ 233 | Fill-in vector according to airfoil surface. 234 | 235 | Parameters 236 | --------- 237 | sign: str 238 | '+': Upper surface 239 | '-': Lower surface 240 | 241 | Returns 242 | ------- 243 | vec: np.array 244 | """ 245 | 246 | from math import tan, sqrt, pi 247 | 248 | deg_to_rad = pi / 180.0 249 | vec = np.ndarray(shape=(6,1)) 250 | 251 | if sign == '+': 252 | vec[0] = self.dv['p8'] + self.dv['p9'] / 2.0 253 | vec[1] = self.dv['p3'] 254 | vec[2] = tan(deg_to_rad * (self.dv['p10'] - self.dv['p11'] / 2.0)) 255 | vec[3] = 0.0 256 | vec[4] = self.dv['p4'] 257 | vec[5] = sqrt(2.0 * self.dv['p1']) 258 | elif sign == '-': 259 | vec[0] = self.dv['p8'] - self.dv['p9'] / 2.0 260 | vec[1] = self.dv['p6'] 261 | vec[2] = tan(deg_to_rad * (self.dv['p10'] + self.dv['p11'] / 2.0)) 262 | vec[3] = 0.0 263 | vec[4] = self.dv['p7'] 264 | vec[5] = -sqrt(2.0 * self.dv['p1']) 265 | else: 266 | raise ValueError('Which section do you want to create?') 267 | 268 | return vec 269 | 270 | def _create_matrices(self): 271 | 272 | self._matrix_upper = self._fill_in_matrix(p = self.dv['p2']) 273 | self._matrix_lower = self._fill_in_matrix(p = self.dv['p5']) 274 | 275 | def _fill_in_matrix(self, p:float): 276 | """ 277 | Fill-in matrix according to parameter p2/p5. 278 | 279 | Parameters 280 | ---------- 281 | p: float 282 | Crest position in horizontal coordinates 283 | - Upper: p2 284 | - Lower: p5 285 | 286 | Returns 287 | ------- 288 | matrix: np.ndarray(shape=(6,6)) 289 | 290 | Notes 291 | ----- 292 | Row definitions: 293 | 0: TE height 294 | 1: Max. location 295 | 2: TE direction 296 | 3: Max. condition 297 | 4: Curvature 298 | 5: LE radius 299 | 300 | """ 301 | 302 | matrix = np.ndarray(shape=(6,6)) 303 | 304 | matrix[0] = np.ones(6, dtype=float) 305 | matrix[1] = np.array([p**q for q in self._q1], dtype=float) 306 | matrix[2] = np.array([q for q in self._q1], dtype=float) 307 | matrix[3] = np.array([q * p**(q-1.0) for q in self._q1], dtype=float) 308 | matrix[4] = np.array([q2 * p**(q1-2.0) for q1, q2 in zip(self._q1, self._q2)], dtype=float) 309 | matrix[5] = np.zeros(6, dtype = float) 310 | matrix[5,0] = 1.0 311 | 312 | return matrix 313 | -------------------------------------------------------------------------------- /src/xfoil/test.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright (c) 2019 D. de Vries 3 | # 4 | # This file is part of XFoil. 5 | # 6 | # XFoil is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # XFoil is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with XFoil. If not, see . 18 | import numpy as np 19 | import unittest 20 | 21 | from xfoil import XFoil 22 | from xfoil.model import Airfoil 23 | 24 | # from .xfoil import XFoil 25 | # from .model import Airfoil 26 | 27 | naca0012 = Airfoil( 28 | x=np.array([+1.0000e+00, +9.9168e-01, +9.8037e-01, +9.6727e-01, +9.5272e-01, +9.3720e-01, +9.2112e-01, +9.0474e-01, 29 | +8.8821e-01, +8.7160e-01, +8.5494e-01, +8.3827e-01, +8.2158e-01, +8.0488e-01, +7.8817e-01, +7.7146e-01, 30 | +7.5475e-01, +7.3803e-01, +7.2132e-01, +7.0460e-01, +6.8789e-01, +6.7118e-01, +6.5447e-01, +6.3777e-01, 31 | +6.2108e-01, +6.0440e-01, +5.8772e-01, +5.7106e-01, +5.5441e-01, +5.3778e-01, +5.2116e-01, +5.0456e-01, 32 | +4.8798e-01, +4.7143e-01, +4.5489e-01, +4.3839e-01, +4.2191e-01, +4.0546e-01, +3.8905e-01, +3.7268e-01, 33 | +3.5635e-01, +3.4007e-01, +3.2383e-01, +3.0766e-01, +2.9154e-01, +2.7550e-01, +2.5953e-01, +2.4366e-01, 34 | +2.2788e-01, +2.1222e-01, +1.9670e-01, +1.8135e-01, +1.6619e-01, +1.5127e-01, +1.3666e-01, +1.2246e-01, 35 | +1.0877e-01, +9.5752e-02, +8.3582e-02, +7.2423e-02, +6.2395e-02, +5.3537e-02, +4.5806e-02, +3.9101e-02, 36 | +3.3294e-02, +2.8256e-02, +2.3867e-02, +2.0028e-02, +1.6658e-02, +1.3692e-02, +1.1080e-02, +8.7858e-03, 37 | +6.7811e-03, +5.0484e-03, +3.5772e-03, +2.3627e-03, +1.4037e-03, +6.9909e-04, +2.4355e-04, +2.6000e-05, 38 | +2.6000e-05, +2.4355e-04, +6.9909e-04, +1.4037e-03, +2.3627e-03, +3.5772e-03, +5.0484e-03, +6.7811e-03, 39 | +8.7858e-03, +1.1080e-02, +1.3692e-02, +1.6658e-02, +2.0028e-02, +2.3867e-02, +2.8256e-02, +3.3294e-02, 40 | +3.9101e-02, +4.5806e-02, +5.3537e-02, +6.2395e-02, +7.2423e-02, +8.3582e-02, +9.5752e-02, +1.0877e-01, 41 | +1.2246e-01, +1.3666e-01, +1.5127e-01, +1.6619e-01, +1.8135e-01, +1.9670e-01, +2.1222e-01, +2.2788e-01, 42 | +2.4366e-01, +2.5953e-01, +2.7550e-01, +2.9154e-01, +3.0766e-01, +3.2383e-01, +3.4007e-01, +3.5635e-01, 43 | +3.7268e-01, +3.8905e-01, +4.0546e-01, +4.2191e-01, +4.3839e-01, +4.5489e-01, +4.7143e-01, +4.8798e-01, 44 | +5.0456e-01, +5.2116e-01, +5.3778e-01, +5.5441e-01, +5.7106e-01, +5.8772e-01, +6.0440e-01, +6.2108e-01, 45 | +6.3777e-01, +6.5447e-01, +6.7118e-01, +6.8789e-01, +7.0460e-01, +7.2132e-01, +7.3803e-01, +7.5475e-01, 46 | +7.7146e-01, +7.8817e-01, +8.0488e-01, +8.2158e-01, +8.3827e-01, +8.5494e-01, +8.7160e-01, +8.8821e-01, 47 | +9.0474e-01, +9.2112e-01, +9.3720e-01, +9.5272e-01, +9.6727e-01, +9.8037e-01, +9.9168e-01, +1.0000e+00] 48 | ), 49 | y=np.array([+1.2600e-03, +2.4215e-03, +3.9814e-03, +5.7619e-03, +7.7062e-03, +9.7433e-03, +1.1815e-02, +1.3886e-02, 50 | +1.5936e-02, +1.7956e-02, +1.9943e-02, +2.1894e-02, +2.3810e-02, +2.5689e-02, +2.7532e-02, +2.9338e-02, 51 | +3.1107e-02, +3.2839e-02, +3.4534e-02, +3.6190e-02, +3.7807e-02, +3.9384e-02, +4.0921e-02, +4.2415e-02, 52 | +4.3865e-02, +4.5271e-02, +4.6630e-02, +4.7940e-02, +4.9199e-02, +5.0406e-02, +5.1557e-02, +5.2650e-02, 53 | +5.3683e-02, +5.4652e-02, +5.5554e-02, +5.6385e-02, +5.7143e-02, +5.7822e-02, +5.8419e-02, +5.8930e-02, 54 | +5.9349e-02, +5.9671e-02, +5.9891e-02, +6.0004e-02, +6.0002e-02, +5.9879e-02, +5.9628e-02, +5.9241e-02, 55 | +5.8710e-02, +5.8027e-02, +5.7181e-02, +5.6164e-02, +5.4967e-02, +5.3580e-02, +5.1997e-02, +5.0216e-02, 56 | +4.8243e-02, +4.6095e-02, +4.3805e-02, +4.1422e-02, +3.9000e-02, +3.6592e-02, +3.4237e-02, +3.1957e-02, 57 | +2.9760e-02, +2.7644e-02, +2.5598e-02, +2.3613e-02, +2.1675e-02, +1.9770e-02, +1.7888e-02, +1.6017e-02, 58 | +1.4147e-02, +1.2270e-02, +1.0381e-02, +8.4792e-03, +6.5676e-03, +4.6570e-03, +2.7615e-03, +9.0564e-04, 59 | -9.0564e-04, -2.7615e-03, -4.6570e-03, -6.5676e-03, -8.4792e-03, -1.0381e-02, -1.2270e-02, -1.4147e-02, 60 | -1.6017e-02, -1.7888e-02, -1.9770e-02, -2.1675e-02, -2.3613e-02, -2.5598e-02, -2.7644e-02, -2.9760e-02, 61 | -3.1957e-02, -3.4237e-02, -3.6592e-02, -3.9000e-02, -4.1422e-02, -4.3805e-02, -4.6095e-02, -4.8243e-02, 62 | -5.0216e-02, -5.1997e-02, -5.3580e-02, -5.4967e-02, -5.6164e-02, -5.7181e-02, -5.8027e-02, -5.8710e-02, 63 | -5.9241e-02, -5.9628e-02, -5.9879e-02, -6.0002e-02, -6.0004e-02, -5.9891e-02, -5.9671e-02, -5.9349e-02, 64 | -5.8930e-02, -5.8419e-02, -5.7822e-02, -5.7143e-02, -5.6385e-02, -5.5554e-02, -5.4652e-02, -5.3683e-02, 65 | -5.2650e-02, -5.1557e-02, -5.0406e-02, -4.9199e-02, -4.7940e-02, -4.6630e-02, -4.5271e-02, -4.3865e-02, 66 | -4.2415e-02, -4.0921e-02, -3.9384e-02, -3.7807e-02, -3.6190e-02, -3.4534e-02, -3.2839e-02, -3.1107e-02, 67 | -2.9338e-02, -2.7532e-02, -2.5689e-02, -2.3810e-02, -2.1894e-02, -1.9943e-02, -1.7956e-02, -1.5936e-02, 68 | -1.3886e-02, -1.1815e-02, -9.7433e-03, -7.7062e-03, -5.7619e-03, -3.9814e-03, -2.4215e-03, -1.2600e-03] 69 | ) 70 | ) 71 | 72 | 73 | class TestXFoil(unittest.TestCase): 74 | """Test whether the XFOIL module functions properly.""" 75 | 76 | def assertNumpyArraysAlmostEqual(self, first, second, decimal, msg=''): 77 | for i in range(first.size): 78 | self.assertAlmostEqual(first[i], second[i], decimal, msg) 79 | 80 | def test_a(self): 81 | """Analyse the NACA 0012 at Re = 1e6, M = 0, α = 10 degrees and verify the results.""" 82 | xf = XFoil() 83 | xf.airfoil = naca0012 84 | xf.conditions = (50000, 0) 85 | xf.max_iter = 1000 86 | cl, cd, cm, cp = xf.a(5) 87 | 88 | print(cl, cd, cm, cp) 89 | 90 | self.assertAlmostEqual(cl, 1.0809, 4) 91 | self.assertAlmostEqual(cd, 0.0150, 4) 92 | self.assertAlmostEqual(cm, 0.0053, 4) 93 | 94 | def test_cl(self): 95 | """Analyse the NACA 0012 at Re = 1e6, M = 0, C_l = 1 and verify the results.""" 96 | xf = XFoil() 97 | xf.airfoil = naca0012 98 | xf.conditions = (1e6, 0) 99 | a, cd, cm, cp= xf.cl(1) 100 | 101 | self.assertAlmostEqual(a, 9.0617, 4) 102 | self.assertAlmostEqual(cd, 0.0135, 4) 103 | self.assertAlmostEqual(cm, 0.0013, 4) 104 | 105 | def test_aseq(self): 106 | """Analyse the NACA 0012 at Re = 1e6, M = 0, α = -20, -19.5, ..., 19.5 and verify the results.""" 107 | xf = XFoil() 108 | xf.airfoil = naca0012 109 | xf.conditions = (1e6, 0) 110 | xf.max_iter = 40 111 | a, cl, cd, cm, co = xf.aseq(-20, 20, 0.5) 112 | 113 | self.assertNumpyArraysAlmostEqual(a, np.arange(-20, 20, 0.5), 4) 114 | self.assertNumpyArraysAlmostEqual(cl, np.array([ 115 | -1.1177, -1.1521, -1.1878, -1.2263, -1.2654, -1.3014, -1.3296, -1.3656, -1.3861, -1.3883, 116 | -1.3793, -1.3661, -1.3492, -1.3264, -1.3155, -1.2830, -1.2451, -1.2065, -1.1664, -1.1223, 117 | -1.0809, -1.0363, -0.9948, -0.9512, -0.9100, -0.8685, -0.8266, -0.7637, -0.6948, -0.6255, 118 | -0.5580, -0.4878, -0.4278, -0.3723, -0.3199, -0.2672, -0.2142, -0.1609, -0.1073, -0.0537, 119 | -0.0000, +0.0537, +0.1073, +0.1609, +0.2142, +0.2672, +0.3199, +0.3723, +0.4278, +0.4878, 120 | +0.5580, +0.6255, +0.6949, +0.7638, +0.8264, +0.8684, +0.9099, +0.9511, +0.9948, +1.0363, 121 | +1.0809, +1.1224, +1.1665, +1.2067, +1.2454, +1.2834, +1.3161, +1.3273, +1.3502, +1.3673, 122 | +1.3808, +1.3900, +1.3877, +1.3670, +1.3323, +1.3041, +1.2680, +1.2288, +1.1901, +1.1541]), 4) 123 | self.assertNumpyArraysAlmostEqual(cd, np.array([ 124 | +0.1474, +0.1320, +0.1171, +0.1023, +0.0879, +0.0746, +0.0630, +0.0509, +0.0417, +0.0358, 125 | +0.0317, +0.0286, +0.0261, +0.0243, +0.0219, +0.0205, +0.0194, +0.0181, +0.0169, +0.0161, 126 | +0.0150, +0.0143, +0.0134, +0.0128, +0.0121, +0.0115, +0.0109, +0.0104, +0.0097, +0.0091, 127 | +0.0085, +0.0078, +0.0073, +0.0068, +0.0064, +0.0061, +0.0058, +0.0056, +0.0055, +0.0054, 128 | +0.0054, +0.0054, +0.0055, +0.0056, +0.0058, +0.0061, +0.0064, +0.0068, +0.0073, +0.0078, 129 | +0.0085, +0.0091, +0.0097, +0.0104, +0.0109, +0.0115, +0.0121, +0.0128, +0.0134, +0.0143, 130 | +0.0150, +0.0161, +0.0169, +0.0181, +0.0194, +0.0205, +0.0220, +0.0243, +0.0261, +0.0286, 131 | +0.0317, +0.0357, +0.0417, +0.0509, +0.0628, +0.0745, +0.0879, +0.1023, +0.1171, +0.1321]), 4) 132 | self.assertNumpyArraysAlmostEqual(cm, np.array([ 133 | +0.0238, +0.0148, +0.0066, -0.0012, -0.0085, -0.0153, -0.0210, -0.0268, -0.0304, -0.0317, 134 | -0.0312, -0.0295, -0.0269, -0.0237, -0.0184, -0.0156, -0.0134, -0.0112, -0.0091, -0.0074, 135 | -0.0053, -0.0034, -0.0010, +0.0013, +0.0040, +0.0067, +0.0093, +0.0074, +0.0043, +0.0011, 136 | -0.0017, -0.0051, -0.0060, -0.0058, -0.0049, -0.0039, -0.0030, -0.0022, -0.0014, -0.0007, 137 | +0.0000, +0.0007, +0.0014, +0.0022, +0.0030, +0.0039, +0.0049, +0.0058, +0.0060, +0.0051, 138 | +0.0017, -0.0011, -0.0043, -0.0074, -0.0092, -0.0066, -0.0039, -0.0013, +0.0010, +0.0034, 139 | +0.0053, +0.0074, +0.0091, +0.0111, +0.0133, +0.0155, +0.0182, +0.0236, +0.0267, +0.0294, 140 | +0.0310, +0.0315, +0.0302, +0.0264, +0.0208, +0.0149, +0.0082, +0.0008, -0.0070, -0.0152]), 4) 141 | 142 | def test_cseq(self): 143 | """Analyse the NACA 0012 at Re = 1e6, M = 0, C_l = -0.5, -0.45, ..., 0.45 and verify the results.""" 144 | xf = XFoil() 145 | xf.airfoil = naca0012 146 | xf.conditions = (1e6, 0.) 147 | xf.max_iter = 40 148 | a, cl, cd, cm = xf.cseq(-0.5, 0.5, 0.05) 149 | 150 | self.assertNumpyArraysAlmostEqual(cl, np.arange(-0.5, 0.5, 0.05), 4) 151 | self.assertNumpyArraysAlmostEqual(a, np.array([ 152 | -4.5879, -4.1765, -3.7446, -3.2848, -2.8112, -2.3371, -1.8666, -1.3981, -0.9324, -0.4659, 153 | -0.0000, +0.4659, +0.9323, +1.3981, +1.8665, +2.3370, +2.8111, +3.2847, +3.7445, +4.1764]), +4) 154 | self.assertNumpyArraysAlmostEqual(cd, np.array([ 155 | +0.0079, +0.0075, +0.0070, +0.0066, +0.0063, +0.0060, +0.0058, +0.0056, +0.0055, +0.0054, 156 | +0.0054, +0.0054, +0.0055, +0.0056, +0.0058, +0.0060, +0.0063, +0.0066, +0.0070, +0.0075]), 4) 157 | self.assertNumpyArraysAlmostEqual(cm, np.array([ 158 | -0.0045, -0.0055, -0.0058, -0.0054, -0.0045, -0.0036, -0.0028, -0.0020, -0.0013, -0.0007, 159 | -0.0000, +0.0007, +0.0013, +0.0020, +0.0028, +0.0036, 0.0045, +0.0054, +0.0058, +0.0055]), 4) 160 | 161 | 162 | if __name__ == '__main__': 163 | unittest.main() 164 | -------------------------------------------------------------------------------- /src/xfoil/xfoil.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright (c) 2019 D. de Vries 3 | # 4 | # This file is part of XFoil. 5 | # 6 | # XFoil is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # XFoil is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with XFoil. If not, see . 18 | 19 | #import sys 20 | #sys.path.insert(0, '/Users/Kike/Library/Mobile Documents/com~apple~CloudDocs/Documents/Inbox/TU_Delft/MsC/Q1/Aircraft_Aerodynamics/Code/xfoil-python/') 21 | 22 | 23 | import numpy as np 24 | import ctypes 25 | import os 26 | import glob 27 | 28 | from deprecated import deprecated 29 | 30 | from ctypes import c_bool, c_int, c_float, byref, POINTER, cdll, c_char_p, c_char 31 | from shutil import copy2 32 | from tempfile import NamedTemporaryFile 33 | 34 | 35 | from xfoil.model import Airfoil 36 | 37 | here = os.path.abspath(os.path.dirname(__file__)) 38 | #lib_path = glob.glob(os.path.join(here, 'libxfoil.*'))[0] 39 | #lib_ext = lib_path[lib_path.rfind('.'):] 40 | 41 | lib_path = '/Users/Kike/Library/Mobile Documents/com~apple~CloudDocs/Documents/Inbox/TU_Delft/MsC/Q1/Aircraft_Aerodynamics/Code/xfoil-python/build/lib.macosx-10.7-x86_64-3.6/xfoil/libxfoil.dylib' 42 | lib_ext = 'dylib' 43 | 44 | fptr = POINTER(c_float) 45 | bptr = POINTER(c_bool) 46 | 47 | class XFoil(object): 48 | """Interface to the XFoil Fortran routines. 49 | 50 | Attributes 51 | ---------- 52 | airfoil 53 | Re 54 | M 55 | xtr 56 | n_crit 57 | max_iter 58 | """ 59 | 60 | def __init__(self): 61 | super().__init__() 62 | tmp = NamedTemporaryFile(mode='wb', delete=False, suffix=lib_ext) 63 | tmp.close() 64 | self._lib_path = tmp.name 65 | copy2(lib_path, self._lib_path) 66 | self._lib = cdll.LoadLibrary(self._lib_path) 67 | self._lib.init() 68 | self._airfoil = None 69 | 70 | self._lib.get_print.restype = c_bool 71 | self._lib.get_reynolds.restype = c_float 72 | self._lib.get_mach.restype = c_float 73 | self._lib.get_n_crit.restype = c_float 74 | 75 | self.file_boundary_layer = str() 76 | 77 | def __del__(self): 78 | handle = self._lib._handle 79 | del self._lib 80 | try: 81 | ctypes.windll.kernel32.FreeLibrary(handle) 82 | except AttributeError: 83 | pass 84 | finally: 85 | os.remove(self._lib_path) 86 | 87 | @property 88 | def print(self): 89 | """bool: True if console output should be shown.""" 90 | return self._lib.get_print() 91 | 92 | @print.setter 93 | def print(self, value): 94 | self._lib.set_print(byref(c_bool(value))) 95 | 96 | @property 97 | def airfoil(self): 98 | """Airfoil: Instance of the Airfoil class.""" 99 | n = self._lib.get_n_coords() 100 | x = np.asfortranarray(np.zeros(n), dtype=c_float) 101 | y = np.asfortranarray(np.zeros(n), dtype=c_float) 102 | self._lib.get_airfoil(x.ctypes.data_as(fptr), y.ctypes.data_as(fptr), byref(c_int(n))) 103 | return Airfoil(x.astype(float), y.astype(float)) 104 | 105 | @airfoil.setter 106 | def airfoil(self, airfoil): 107 | self._airfoil = airfoil 108 | self._lib.set_airfoil( 109 | np.asfortranarray(airfoil.x.flatten(), dtype=c_float).ctypes.data_as(fptr), 110 | np.asfortranarray(airfoil.y.flatten(), dtype=c_float).ctypes.data_as(fptr), 111 | byref(c_int(airfoil.n_coords)) 112 | ) 113 | 114 | @property 115 | def Re(self): 116 | """float: Reynolds number.""" 117 | return float(self._lib.get_reynolds()) 118 | 119 | @Re.setter 120 | def Re(self, value): 121 | self._lib.set_reynolds(byref(c_float(value))) 122 | 123 | @property 124 | def M(self): 125 | """float: Mach number.""" 126 | return float(self._lib.get_mach()) 127 | 128 | @M.setter 129 | def M(self, value): 130 | self._lib.set_mach(byref(c_float(value))) 131 | 132 | @property 133 | def xtr(self): 134 | """tuple(float, float): Top and bottom flow trip x/c locations.""" 135 | xtr_top = c_float() 136 | xtr_bot = c_float() 137 | self._lib.get_xtr(byref(xtr_top), byref(xtr_bot)) 138 | return float(xtr_top), float(xtr_bot) 139 | 140 | @xtr.setter 141 | def xtr(self, value): 142 | self._lib.set_xtr(byref(c_float(value[0])), byref(c_float(value[1]))) 143 | 144 | @property 145 | def n_crit(self): 146 | """float: Critical amplification ratio.""" 147 | return float(self._lib.get_n_crit()) 148 | 149 | @n_crit.setter 150 | def n_crit(self, value): 151 | self._lib.set_n_crit(byref(c_float(value))) 152 | 153 | @property 154 | def max_iter(self): 155 | """int: Maximum number of iterations.""" 156 | return int(self._lib.get_max_iter()) 157 | 158 | @max_iter.setter 159 | def max_iter(self, max_iter): 160 | self._lib.set_max_iter(byref(c_int(max_iter))) 161 | 162 | def naca(self, specifier): 163 | """Set a NACA 4 or 5 series airfoil. 164 | 165 | Parameters 166 | ---------- 167 | specifier : string 168 | A NACA 4 or 5 series identifier, such as '2412'. 169 | """ 170 | self._lib.set_naca(byref(c_int(int(specifier)))) 171 | 172 | def reset_bls(self): 173 | """Reset the boundary layers to be reinitialized on the next analysis.""" 174 | self._lib.reset_bls() 175 | 176 | def repanel(self, n_nodes=160, cv_par=1, cte_ratio=0.15, ctr_ratio=0.2, xt_ref=(1, 1), xb_ref=(1, 1)): 177 | """Re-panel airfoil. 178 | 179 | Parameters 180 | ---------- 181 | n_nodes : int 182 | Number of panel nodes 183 | cv_par : float 184 | Panel bunching parameter 185 | cte_ratio : float 186 | TE/LE panel density ratio 187 | ctr_ratio : float 188 | Refined-area/LE panel density ratio 189 | xt_ref : tuple of two floats 190 | Top side refined area x/c limits 191 | xb_ref : tuple of two floats 192 | Bottom side refined area x/c limits 193 | """ 194 | self._lib.repanel(byref(c_int(n_nodes)), byref(c_float(cv_par)), 195 | byref(c_float(cte_ratio)), byref(c_float(ctr_ratio)), 196 | byref(c_float(xt_ref[0])), byref(c_float(xt_ref[1])), 197 | byref(c_float(xb_ref[0])), byref(c_float(xb_ref[1]))) 198 | 199 | def filter(self, factor=0.2): 200 | """Filter surface speed distribution using modified Hanning filter. 201 | 202 | Parameters 203 | ---------- 204 | factor : float 205 | Filter parameter. If set to 1, the standard, full Hanning filter is applied. Default is 0.2. 206 | """ 207 | self._lib.filter(byref(c_float(factor))) 208 | 209 | def a(self, a): 210 | """Analyze airfoil at a fixed angle of attack. 211 | 212 | Parameters 213 | ---------- 214 | a : float 215 | Angle of attack in degrees 216 | 217 | Returns 218 | ------- 219 | cl, cd, cd_f, cd_p, cm, cp : float 220 | Corresponding values of the lift, drag, pressure drag, moment, and minimum pressure coefficients. 221 | 222 | # TODO: reorganize a and cl to always give the same output structure. 223 | """ 224 | cl = c_float() 225 | cd = c_float() 226 | cd_f = c_float() 227 | cd_p = c_float() 228 | cm = c_float() 229 | cp = c_float() 230 | conv = c_bool() 231 | 232 | self._lib.alfa(byref(c_float(a)), byref(cl), byref(cd), byref(cd_f), byref(cd_p), byref(cm), byref(cp), byref(conv)) 233 | 234 | return (cl.value, cd.value, cd_f.value, cd_p.value, cm.value, cp.value) if conv else (np.nan, np.nan, np.nan, np.nan, np.nan, np.nan) 235 | 236 | def cl(self, cl): 237 | """ 238 | Analyze airfoil at a fixed lift coefficient. 239 | 240 | Parameters 241 | ---------- 242 | cl : float 243 | Lift coefficient 244 | 245 | Returns 246 | ------- 247 | a, cd, cd_f, cd_p, cm, cp : float 248 | Corresponding values of the angle of attack, drag, moment, and minimum pressure coefficients. 249 | """ 250 | a = c_float() 251 | cd = c_float() 252 | cd_f = c_float() 253 | cd_p = c_float() 254 | cm = c_float() 255 | cp = c_float() 256 | conv = c_bool() 257 | 258 | self._lib.cl(byref(c_float(cl)), byref(a), byref(cd), byref(cd_f), byref(cd_p), byref(cm), byref(cp), byref(conv)) 259 | 260 | return (a.value, cd.value, cd_f.value, cd_p.value, cm.value, cp.value) if conv else (np.nan, np.nan, np.nan, np.nan, np.nan, np.nan) 261 | 262 | @deprecated(reason='The changes in the Fortran API have not been included here. Unexpected behaviour if called.') 263 | def aseq(self, a_start, a_end, a_step): 264 | """Analyze airfoil at a sequence of angles of attack. 265 | 266 | The analysis is done for the angles of attack given by range(a_start, a_end, a_step). 267 | 268 | Parameters 269 | ---------- 270 | a_start, a_end, a_step : float 271 | Start, end, and increment angles for the range. 272 | 273 | Returns 274 | ------- 275 | a, cl, cd, cm, co : np.ndarray 276 | Lists of angles of attack and their corresponding lift, drag, moment, and minimum pressure coefficients. 277 | """ 278 | n = abs(int((a_end - a_start) / a_step)) 279 | 280 | a = np.zeros(n, dtype=c_float) 281 | cl = np.zeros(n, dtype=c_float) 282 | cd = np.zeros(n, dtype=c_float) 283 | cm = np.zeros(n, dtype=c_float) 284 | cp = np.zeros(n, dtype=c_float) 285 | conv = np.zeros(n, dtype=c_bool) 286 | 287 | self._lib.aseq(byref(c_float(a_start)), byref(c_float(a_end)), byref(c_int(n)), 288 | a.ctypes.data_as(fptr), cl.ctypes.data_as(fptr), 289 | cd.ctypes.data_as(fptr), cm.ctypes.data_as(fptr), 290 | cp.ctypes.data_as(fptr), conv.ctypes.data_as(bptr)) 291 | 292 | isnan = np.logical_not(conv) 293 | a[isnan] = np.nan 294 | cl[isnan] = np.nan 295 | cd[isnan] = np.nan 296 | cm[isnan] = np.nan 297 | cp[isnan] = np.nan 298 | 299 | return a.astype(float), cl.astype(float), cd.astype(float), cm.astype(float), cp.astype(float) 300 | 301 | @deprecated(reason='The changes in the Fortran API have not been included here. Unexpected behaviour if called.') 302 | def cseq(self, cl_start, cl_end, cl_step): 303 | """Analyze airfoil at a sequence of lift coefficients. 304 | 305 | The analysis is done for the lift coefficients given by range(cl_start, cl_end, cl_step). 306 | 307 | Parameters 308 | ---------- 309 | cl_start, cl_end, cl_step : float 310 | Start, end, and increment lift coefficients for the range. 311 | 312 | Returns 313 | ------- 314 | a, cl, cd, cm, co : np.ndarray 315 | Lists of angles of attack and their corresponding lift, drag, moment, and minimum pressure coefficients. 316 | """ 317 | n = abs(int((cl_end - cl_start) / cl_step)) 318 | 319 | a = np.zeros(n, dtype=c_float) 320 | cl = np.zeros(n, dtype=c_float) 321 | cd = np.zeros(n, dtype=c_float) 322 | cm = np.zeros(n, dtype=c_float) 323 | cp = np.zeros(n, dtype=c_float) 324 | conv = np.zeros(n, dtype=c_bool) 325 | 326 | self._lib.cseq(byref(c_float(cl_start)), byref(c_float(cl_end)), byref(c_int(n)), 327 | a.ctypes.data_as(fptr), cl.ctypes.data_as(fptr), 328 | cd.ctypes.data_as(fptr), cm.ctypes.data_as(fptr), 329 | cp.ctypes.data_as(fptr), conv.ctypes.data_as(bptr)) 330 | 331 | isnan = np.logical_not(conv) 332 | a[isnan] = np.nan 333 | cl[isnan] = np.nan 334 | cd[isnan] = np.nan 335 | cm[isnan] = np.nan 336 | cp[isnan] = np.nan 337 | return a.astype(float), cl.astype(float), cd.astype(float), cm.astype(float), cp.astype(float) 338 | 339 | def dump_boundary_layer(self, py_name='boundary_layer.txt'): 340 | """Dump boundary layer data to file. 341 | 342 | Parameters 343 | ---------- 344 | fname: str 345 | 346 | Returns 347 | ------- 348 | None 349 | """ 350 | # Get file name in C format 351 | c_name, string_length = self._py2c_string(py_name) 352 | 353 | # Save it for later postprocessing 354 | self.file_boundary_layer = py_name 355 | 356 | # Compute the boundary layer properties and dump them 357 | self._lib.boundary_layer_dump(c_name, byref(string_length)) 358 | 359 | def dump_cp(self, fname='cp.txt'): 360 | """Dump Cp coefficient to file. 361 | 362 | Parameters 363 | ---------- 364 | fname: str 365 | 366 | Returns 367 | ------- 368 | None 369 | 370 | """ 371 | # Get file name length 372 | c_name, string_length = self._py2c_string(fname) 373 | 374 | self._lib.cp_dump(c_name, byref(string_length)) 375 | 376 | def _py2c_string(self, fname): 377 | """Convert a Python string to a C char array. 378 | 379 | Parameters 380 | ---------- 381 | fname: str 382 | 383 | Returns 384 | ------- 385 | c_fname: ctypes.c_char_p 386 | fname as C char pointer 387 | 388 | string_length: ctypes.c_int 389 | string length as C int 390 | 391 | """ 392 | # Get file name length 393 | string_length = c_int(len(fname)) 394 | 395 | # Create a C char array from the string 396 | c_fname = c_char_p(fname.encode('utf-8')) 397 | 398 | # Return 399 | return c_fname, string_length 400 | --------------------------------------------------------------------------------