PR

Pythonを使ってXFOILで2次元翼型を解析する

Visual Studio CodeでPythonを使ってXfoilで2次元翼型を解析する方法について説明する

スポンサーリンク

Xfoilとは

みんな大好きXFLR5に搭載されている2次元翼型の解析プログラム

本来はfortranで書かれたプログラムだが,有志によってPythonでも利用ができるようになっている

↓XFLR5についてはこちら

Xfoilのインストール手順

OS

Windows10
バージョン 20H2 (OS ビルド 19042.1415)

参考
Windows10のバージョンを確認・表記する - Qiita

Visual Studio Code

バージョン1.63.2

参考
VS Codeのバージョン確認方法 - Qiita

Visual Studio Codeのインストールのときに参考にしたサイト
【ゼロから!】Visual Studio Codeのインストールと使い方

Xfoilのインストールは公式ドキュメントを参考に以下の手順で行う

  1. ディレクトリを準備する
  2. Python 3.6 をインストールする
  3. Xfoilのリポジトリをダウンロードする
  4. setup.py を書き換える
  5. cygwinccompiler.py を書き換える
  6. CMakeLists.txt をダウンロードする
  7. pipでxfoilをインポートする
  8. xfoil.py を書き換える(オプション)

↓公式ドキュメント
github.com/daniel-de-vries/xfoil-python
xfoil · PyPI

また,今回使うxfoilのモジュールはC言語とfortranを動かして計算を行うので,事前にMinGW(gccとgfortran)とCMakeをインストールしておく必要がある

Furthermore, working compilers for C and Fortran have to be installed and on the PATH. On Windows, the build and installation have ONLY been tested with MinGW, using gcc and gfortran.

MinGWのインストールはこちら

CMakeのインストールはこちら

それでは1つずつ説明していく

ディレクトリを準備する

今回はターミナルとしてVisual Studio Codeを使う

↓Visudal Studio Codeのインストールについてはこちら

デスクトップにxfoilという名前のフォルダを作成し,Visual Studio Codeでフォルダを開く

フォルダを開いた状態で「Ctrl+@」を押せばターミナルが開く

今後のコマンドはここに入力していく

ちなみに gcc と gfortran がきちんとインストールできているかは次のようにして確認できる

C:\Users\XXX\Desktop\xfoil>gcc --version
gcc (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
C:\Users\XXX\Desktop\xfoil>gfortran --version
GNU Fortran (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0      
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Pythonをインストールする

公式ドキュメントではPythonのバージョンとして3.6が指定されている

Pythonの3系なら動くらしい

If you are on a Windows machine (64bit) with Python 3.6, installing XFoil is a simple matter of running:
pip install xfoil
If you are using a different type of machine, or a different version of Python, you will have to make sure some software is installed on your system in order for the package to be successfully built. First of all, the module targets Python 3, and does NOT support Python 2. So make sure a Python 3 environment is installed and available.

今回は公式サイトからPython 3.6.8のWindows x86-64 executable installerをインストールした

公式サイト
https://www.python.org/downloads/

参考
【2021年度版】Pythonインストール Windows10(64bit)編 - Qiita

ダウンロード先のパスは後で使うのでどこかにメモしておくといい

C:\Users\XXX\AppData\Local\Programs\Python\Python36

インストールが終わったらターミナルで次のコマンドを実行し,3.6 がちゃんとインストールされていることを確認する(3.8-32はもとから入っていたバージョン)

C:\Users\XXX\Desktop\xfoil>py --list
Installed Pythons found by py Launcher for Windows
 -3.8-32 *
 -3.6-64

ちなみにWindowsでは仮想環境を構築しなくてもpyコマンドを使うことで複数のバージョンのPythonを使い分けることができる

参考
Windows で複数バージョンの Python を使う - Qiita
Pythonの複数バージョンの扱い方(Windowsの場合) - ガンマソフト株式会社

試しに py -3.6 -m pip list でインポートしたモジュールの一覧を見てみる

C:\Users\XXX\Desktop\xfoil>py -3.6 -m pip list        
Package    Version
---------- -------
pip        18.1   
setuptools 40.6.2 
You are using pip version 18.1, however version 21.3.1 is available.
You should consider upgrading via the 'python -m pip install --upgrade pip' command.

もちろん3.6.8はインストールしたばかりなので何のモジュールも入っていない

pipでxfoilをインポートする(1回目)

公式ドキュメントに従ってとりあえず py -3.6 -m pip install xfoil のコマンドを実行する

C:\Users\XXX\Desktop\xfoil>py -3.6 -m pip install xfoil
Collecting xfoil
  Using cached https://files.pythonhosted.org/packages/04/60/2dd764444b07772e3be5f9b109c5e554da09262ff73795c5b55e5cae62f9/xfoil-1.1.1.tar.gz
Collecting numpy (from xfoil)
  Using cached https://files.pythonhosted.org/packages/ea/bc/da526221bc111857c7ef39c3af670bbcf5e69c247b0d22e51986f6d0c5c2/numpy-1.19.5-cp36-cp36m-win_amd64.whl
Installing collected packages: numpy, xfoil
  Running setup.py install for xfoil ... error
    Complete output from command C:\Users\XXX\AppData\Local\Programs\Python\Python36\python.exe -u -c "import setuptools, tokenize;__file__='C:\\Users\\XXX\\AppData\\Local\\Temp\\pip-install-8wnrcm39\\xfoil\\setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record C:\Users\XXX\AppData\Local\Temp\pip-record-bbh_3yu3\install-record.txt --single-version-externally-managed --compile:
    C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\dist.py:261: UserWarning: Unknown distribution option: 'zip_save'
      warnings.warn(msg)
    running install
    running build
    running build_py
    creating build
    creating build\lib.win-amd64-3.6
    creating build\lib.win-amd64-3.6\xfoil
    copying xfoil\model.py -> build\lib.win-amd64-3.6\xfoil
    copying xfoil\test.py -> build\lib.win-amd64-3.6\xfoil
    copying xfoil\xfoil.py -> build\lib.win-amd64-3.6\xfoil
    copying xfoil\__init__.py -> build\lib.win-amd64-3.6\xfoil
    running build_ext
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "C:\Users\XXX\AppData\Local\Temp\pip-install-8wnrcm39\xfoil\setup.py", line 149, in <module>
        zip_save=False
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\site-packages\setuptools\__init__.py", line 143, in setup
        return distutils.core.setup(**attrs)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\core.py", line 148, in setup
        dist.run_commands()
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\dist.py", line 955, in run_commands
        self.run_command(cmd)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\dist.py", line 974, in run_command
        cmd_obj.run()
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\site-packages\setuptools\command\install.py", line 61, in run
        return orig.install.run(self)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\command\install.py", line 545, in run
        self.run_command('build')
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\cmd.py", line 313, in run_command
        self.distribution.run_command(command)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\dist.py", line 974, in run_command
        cmd_obj.run()
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\command\build.py", line 135, in run
        self.run_command(cmd_name)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\cmd.py", line 313, in run_command
        self.distribution.run_command(command)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\dist.py", line 974, in run_command
        cmd_obj.run()
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\site-packages\setuptools\command\build_ext.py", line 78, in run
        _build_ext.run(self)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\command\build_ext.py", line 308, in run       
        force=self.force)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\ccompiler.py", line 1031, in new_compiler     
        return klass(None, dry_run, force)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\cygwinccompiler.py", line 282, in __init__    
        CygwinCCompiler.__init__ (self, verbose, dry_run, force)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\cygwinccompiler.py", line 157, in __init__    
        self.dll_libraries = get_msvcr()
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\cygwinccompiler.py", line 86, in get_msvcr    
        raise ValueError("Unknown MS Compiler version %s " % msc_ver)
    ValueError: Unknown MS Compiler version 1916

    ----------------------------------------
Command "C:\Users\XXX\AppData\Local\Programs\Python\Python36\python.exe -u -c "import setuptools, tokenize;__file__='C:\\Users\\XXX\\AppData\\Local\\Temp\\pip-install-8wnrcm39\\xfoil\\setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record C:\Users\XXX\AppData\Local\Temp\pip-record-bbh_3yu3\install-record.txt --single-version-externally-managed --compile" failed with error code 1 in C:\Users\XXX\AppData\Local\Temp\pip-install-8wnrcm39\xfoil\
You are using pip version 18.1, however version 21.3.1 is available.
You should consider upgrading via the 'python -m pip install --upgrade pip' command.

大量のエラーが出てきてインストールできない

xfoil のリポジトリをダウンロードする

公式ドキュメントに従って次の作業を行う

  • リポジトリをダウンロードする
  • distutils.cfg を作成する

Then, installing XFoil should be as simple as running
pip install .
from the root of the downloaded repository.

On Windows, you may have to force the system to use MinGW. To do so, create a file named distutils.cfg in PYTHONPATH\Lib\distutils with the following contents:
[build]
compiler=mingw32

README.md
リポジトリのダウンロード

PyPlのDownload filesから xfoil-1.1.1.tar.gz をダウンロードする
https://pypi.org/project/xfoil/#files

ダウンロードした xfoil-1.1.1.tar.gz を用意したディレクトリ(Desktop/xfoil)の中に解凍する

distutils.cfg の作成

Visual Studio Code を起動し,Pythonをダウンロードしたフォルダ(C:\Users\XXX\AppData\Local\Programs\Python\Python36)を開く

Lib の中に distutils.cfg を作成する

[build]
compiler=mingw32

これでインストールできるはずである

pipでxfoilをインポートする(2回目)

公式ドキュメントに従って py -3.6 -m pip install . のコマンドを実行する

C:\Users\XXX\Desktop\xfoil>py -3.6 -m pip install .
Processing c:\users\XXX\desktop\xfoil
Requirement already satisfied: numpy in c:\users\XXX\appdata\local\programs\python\python36\lib\site-packages (from xfoil==1.1.1) (1.19.5)
Installing collected packages: xfoil
  Found existing installation: xfoil 1.1.1
    Can't uninstall 'xfoil'. No files were found to uninstall.
  Running setup.py install for xfoil ... error
    Complete output from command C:\Users\XXX\AppData\Local\Programs\Python\Python36\python.exe -u -c "import setuptools, tokenize;__file__='C:\\Users\\XXX\\AppData\\Local\\Temp\\pip-req-build-ot2p31be\\setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record C:\Users\XXX\AppData\Local\Temp\pip-record-qsmao969\install-record.txt --single-version-externally-managed --compile:    
    C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\dist.py:261: UserWarning: Unknown distribution option: 'zip_save'
      warnings.warn(msg)
    running install
    running build
    running build_py
    creating build
    creating build\lib.win-amd64-3.6
    creating build\lib.win-amd64-3.6\xfoil
    copying xfoil\model.py -> build\lib.win-amd64-3.6\xfoil
    copying xfoil\test.py -> build\lib.win-amd64-3.6\xfoil
    copying xfoil\xfoil.py -> build\lib.win-amd64-3.6\xfoil
    copying xfoil\__init__.py -> build\lib.win-amd64-3.6\xfoil
    running build_ext
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "C:\Users\XXX\AppData\Local\Temp\pip-req-build-ot2p31be\setup.py", line 149, in <module>
        zip_save=False
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\site-packages\setuptools\__init__.py", line 143, in setup
        return distutils.core.setup(**attrs)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\core.py", line 148, in setup
        dist.run_commands()
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\dist.py", line 955, in run_commands
        self.run_command(cmd)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\dist.py", line 974, in run_command
        cmd_obj.run()
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\site-packages\setuptools\command\install.py", line 61, in run
        return orig.install.run(self)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\command\install.py", line 545, in run
        self.run_command('build')
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\cmd.py", line 313, in run_command
        self.distribution.run_command(command)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\dist.py", line 974, in run_command
        cmd_obj.run()
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\command\build.py", line 135, in run
        self.run_command(cmd_name)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\cmd.py", line 313, in run_command
        self.distribution.run_command(command)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\dist.py", line 974, in run_command
        cmd_obj.run()
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\site-packages\setuptools\command\build_ext.py", line 78, in run
        _build_ext.run(self)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\command\build_ext.py", line 308, in run
        force=self.force)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\ccompiler.py", line 1031, in new_compiler
        return klass(None, dry_run, force)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\cygwinccompiler.py", line 285, in __init__
        CygwinCCompiler.__init__ (self, verbose, dry_run, force)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\cygwinccompiler.py", line 160, in __init__
        self.dll_libraries = get_msvcr()
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\cygwinccompiler.py", line 89, in get_msvcr
        raise ValueError("Unknown MS Compiler version %s " % msc_ver)
    ValueError: Unknown MS Compiler version 1916

    ----------------------------------------
  Can't roll back xfoil; was not uninstalled
Command "C:\Users\XXX\AppData\Local\Programs\Python\Python36\python.exe -u -c "import setuptools, tokenize;__file__='C:\\Users\\XXX\\AppData\\Local\\Temp\\pip-req-build-ot2p31be\\setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record C:\Users\XXX\AppData\Local\Temp\pip-record-qsmao969\install-record.txt --single-version-externally-managed --compile" failed with error code 1 in C:\Users\XXX\AppData\Local\Temp\pip-req-build-ot2p31be\
You are using pip version 18.1, however version 21.3.1 is available.
You should consider upgrading via the 'python -m pip install --upgrade pip' command.

あいかわらず大量のエラーが出てくる

原因は以下の2つ

  1. 変数 zip_safe が zip_save になってしまっている
  2. cygwinccompiler.py でコンパイラが定義されていない

それぞれについて対処していく

setup.py を書き換える

1つ目のエラーは,本来 zip_safe で与えられる変数が開発側のミス?で zip_save となってしまっていることが原因らしい

参考
zip_save() misspelling? · Issue #17

該当するエラー文はこれ

C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\dist.py:261: UserWarning: Unknown distribution option: 'zip_save'

zip_save の誤字は setup.py に記述されている

File "C:\Users\XXX\AppData\Local\Temp\pip-install-ztilo6_t\xfoil\setup.py", line 149, in <module>
    zip_save=False

というわけで先ほどダウンロードした Desktop/xfoil/setup.py の149行目の zip_save を zip_safe に書き換えて保存する

setup(
    name='xfoil',
    version=__version__,
    description='Stripped down version of XFOIL as compiled python module ',
    long_description=readme(),
    long_description_content_type='text/markdown',
    classifiers=[
        'Development Status :: 3 - Alpha',
        'Intended Audience :: Science/Research',
        'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)',
        'Natural Language :: English',
        'Operating System :: MacOS :: MacOS X',
        'Operating System :: POSIX :: Linux',
        'Operating System :: Microsoft :: Windows',
        'Programming Language :: Fortran',
        'Programming Language :: Python :: 3 :: Only',
        'Topic :: Scientific/Engineering',
    ],
    keywords='xfoil airfoil aerodynamic analysis',
    url='https://github.com/daniel-de-vries/xfoil-python',
    download_url='https://github.com/daniel-de-vries/xfoil-python/tarball/' + __version__,
    author='Daniël de Vries',
    author_email='contact@daniel-de-vries.com',
    license='GNU General Public License v3 or later (GPLv3+)',
    packages=['xfoil'],
    # package_dir={'': 'src'},
    ext_modules=[CMakeExtension('xfoil.xfoil')],
    cmdclass={'build_ext': CMakeBuild},
    install_requires=['numpy'],
    zip_safe=False # MODIFIED
)

cygwinccompiler.py を書き換える

2つ目のエラーは,cygwinccompiler.py でMS Compilerが定義されていないことが原因らしい

参考
Cythonのインストール - TB-code

該当するエラー文はこれ

File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\cygwinccompiler.py", line 86, in get_msvcr    
        raise ValueError("Unknown MS Compiler version %s " % msc_ver)
ValueError: Unknown MS Compiler version 1916

エラー文に書かれているディレクトリにある cygwinccompiler.py というファイルに MS Compiler version 1916 を次のように追加する

def get_msvcr():
    """Include the appropriate MSVC runtime library if Python was built
    with MSVC 7.0 or later.
    """
    msc_pos = sys.version.find('MSC v.')
    if msc_pos != -1:
        msc_ver = sys.version[msc_pos+6:msc_pos+10]
        if msc_ver == '1300':
            # MSVC 7.0
            return ['msvcr70']
        elif msc_ver == '1310':
            # MSVC 7.1
            return ['msvcr71']
        elif msc_ver == '1400':
            # VS2005 / MSVC 8.0
            return ['msvcr80']
        elif msc_ver == '1500':
            # VS2008 / MSVC 9.0
            return ['msvcr90']
        elif msc_ver == '1600':
            # VS2010 / MSVC 10.0
            return ['msvcr100']
        elif msc_ver == '1916': # MODIFIED
            # VS2015 / Visual C++ 14.0
            return ['vcruntime140']
        else:
            raise ValueError("Unknown MS Compiler version %s " % msc_ver)

これでインストールできるはずである

pipでxfoilをインポートする(3回目)

再び py -3.6 -m pip install . のコマンドを実行する

C:\Users\XXX\Desktop\xfoil>py -3.6 -m pip install . 
Processing c:\users\XXX\desktop\xfoil
Collecting numpy (from xfoil==1.1.1)
  Using cached https://files.pythonhosted.org/packages/ea/bc/da526221bc111857c7ef39c3af670bbcf5e69c247b0d22e51986f6d0c5c2/numpy-1.19.5-cp36-cp36m-win_amd64.whl
Installing collected packages: numpy, xfoil
  Found existing installation: xfoil 1.1.1
    Can't uninstall 'xfoil'. No files were found to uninstall.
  Running setup.py install for xfoil ... error
    Complete output from command C:\Users\XXX\AppData\Local\Programs\Python\Python36\python.exe -u -c "import setuptools, tokenize;__file__='C:\\Users\\XXX\\AppData\\Local\\Temp\\pip-req-build-f50kvmpq\\setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record C:\Users\XXX\AppData\Local\Temp\pip-record-56yc4aev\install-record.txt --single-version-externally-managed --compile:
    running install
    running build
    running build_py
    creating build
    creating build\lib.win-amd64-3.6
    creating build\lib.win-amd64-3.6\xfoil
    copying xfoil\model.py -> build\lib.win-amd64-3.6\xfoil
    copying xfoil\test.py -> build\lib.win-amd64-3.6\xfoil
    copying xfoil\xfoil.py -> build\lib.win-amd64-3.6\xfoil
    copying xfoil\__init__.py -> build\lib.win-amd64-3.6\xfoil
    running build_ext
    ['-DCMAKE_BUILD_TYPE=Release', '-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE=C:\\Users\\XXX\\AppData\\Local\\Temp\\pip-req-build-f50kvmpq\\build\\lib.win-amd64-3.6\\xfoil', '-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE=build\\temp.win-amd64-3.6\\Release', '-DPYTHON_EXECUTABLE=C:\\Users\\XXX\\AppData\\Local\\Programs\\Python\\Python36\\python.exe', '-DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=TRUE', '-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE=C:\\Users\\XXX\\AppData\\Local\\Temp\\pip-req-build-f50kvmpq\\build\\lib.win-amd64-3.6\\xfoil', '-G', 'MinGW Makefiles']
    CMake Error: The source directory "C:/Users/XXX/AppData/Local/Temp/pip-req-build-f50kvmpq" does not appear to contain CMakeLists.txt.
    Specify --help for usage, or press the help button on the CMake GUI.
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "C:\Users\XXX\AppData\Local\Temp\pip-req-build-f50kvmpq\setup.py", line 149, in <module>
        zip_safe=False
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\site-packages\setuptools\__init__.py", line 143, in setup
        return distutils.core.setup(**attrs)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\core.py", line 148, in setup
        dist.run_commands()
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\dist.py", line 955, in run_commands
        self.run_command(cmd)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\dist.py", line 974, in run_command
        cmd_obj.run()
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\site-packages\setuptools\command\install.py", line 61, in run
        return orig.install.run(self)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\command\install.py", line 545, in run
        self.run_command('build')
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\cmd.py", line 313, in run_command
        self.distribution.run_command(command)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\dist.py", line 974, in run_command
        cmd_obj.run()
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\command\build.py", line 135, in run
        self.run_command(cmd_name)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\cmd.py", line 313, in run_command
        self.distribution.run_command(command)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\dist.py", line 974, in run_command
        cmd_obj.run()
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\site-packages\setuptools\command\build_ext.py", line 78, in run
        _build_ext.run(self)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\distutils\command\build_ext.py", line 339, in run
        self.build_extensions()
      File "C:\Users\XXX\AppData\Local\Temp\pip-req-build-f50kvmpq\setup.py", line 110, in build_extensions
        cwd=self.build_temp)
      File "C:\Users\XXX\AppData\Local\Programs\Python\Python36\lib\subprocess.py", line 311, in check_call
        raise CalledProcessError(retcode, cmd)
    subprocess.CalledProcessError: Command '['cmake', 'C:\\Users\\XXX\\AppData\\Local\\Temp\\pip-req-build-f50kvmpq', '-DCMAKE_BUILD_TYPE=Release', '-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE=C:\\Users\\XXX\\AppData\\Local\\Temp\\pip-req-build-f50kvmpq\\build\\lib.win-amd64-3.6\\xfoil', '-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE=build\\temp.win-amd64-3.6\\Release', '-DPYTHON_EXECUTABLE=C:\\Users\\XXX\\AppData\\Local\\Programs\\Python\\Python36\\python.exe', '-DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=TRUE', '-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE=C:\\Users\\XXX\\AppData\\Local\\Temp\\pip-req-build-f50kvmpq\\build\\lib.win-amd64-3.6\\xfoil', 
'-G', 'MinGW Makefiles']' returned non-zero exit status 1.

    ----------------------------------------
  Can't roll back xfoil; was not uninstalled
Command "C:\Users\XXX\AppData\Local\Programs\Python\Python36\python.exe -u -c "import setuptools, tokenize;__file__='C:\\Users\\XXX\\AppData\\Local\\Temp\\pip-req-build-f50kvmpq\\setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record C:\Users\XXX\AppData\Local\Temp\pip-record-56yc4aev\install-record.txt --single-version-externally-managed --compile" failed with error code 1 in C:\Users\XXX\AppData\Local\Temp\pip-req-build-f50kvmpq\
You are using pip version 18.1, however version 21.3.1 is available.
You should consider upgrading via the 'python -m pip install --upgrade pip' command.

まだエラーが出てくる

CMakeLists.txt がないことが原因らしい

CMake Error: The source directory "C:/Users/XXX/AppData/Local/Temp/pip-req-build-f50kvmpq" does not appear to contain CMakeLists.txt.

CMakeLists.txt をダウンロードする

GitHub の CMakeLists.txt と src をダウンロードする

公式のGitHubページの Code>Download Zip からリポジトリのダウンロードを行う

GitHub - daniel-de-vries/xfoil-python: Stripped down version of XFOIL as compiled python module
Stripped down version of XFOIL as compiled python module - daniel-de-vries/xfoil-python

ダウンロードした xfoil-python-master.zip の中の CMakeLists.txt と src を Desktop/xfoil に解凍する

これでインストールできるはずである

pipでxfoilをインポートする(4回目)

満を持して py -3.6 -m pip install . のコマンドを実行する

C:\Users\XXX\Desktop\xfoil>py -3.6 -m pip install . 
Processing c:\users\XXX\desktop\xfoil
Requirement already satisfied: numpy in c:\users\XXX\appdata\local\programs\python\python36\lib\site-packages (from xfoil==1.1.1) (1.19.5)
Installing collected packages: xfoil
  Found existing installation: xfoil 1.1.1
    Can't uninstall 'xfoil'. No files were found to uninstall.
  Running setup.py install for xfoil ... done
Successfully installed xfoil-1.1.1
You are using pip version 18.1, however version 21.3.1 is available.
You should consider upgrading via the 'python -m pip install --upgrade pip' command.

感動の瞬間である

py -3.6 -m pip list で確認しても xfoil と numpy がインストールできていることがわかる

C:\Users\XXX\Desktop\xfoil>py -3.6 -m pip list  
Package    Version
---------- -------
numpy      1.19.5
pip        18.1
setuptools 40.6.2
xfoil      1.1.1
You are using pip version 18.1, however version 21.3.1 is available.
You should consider upgrading via the 'python -m pip install --upgrade pip' command.

xfoil.py を書き換える(オプション)

今回インストールした xfoil は,反復計算が収束しなかった場合に Nan を返す使用になっている

変数 conv が計算の収束を判断するbool値で,if conv をもとに np.nan を返すかどうか判断している

※コメントアウトは省略

def a(self, a):
   cl = c_float()
   cd = c_float()
   cm = c_float()
   cp = c_float()
   conv = c_bool()

   self._lib.alfa(byref(c_float(a)), byref(cl), byref(cd), byref(cm), byref(cp), byref(conv))

   return (cl.value, cd.value, cm.value, cp.value) if conv else (np.nan, np.nan, np.nan, np.nan)

def cl(self, cl):
   a = c_float()
   cd = c_float()
   cm = c_float()
   cp = c_float()
   conv = c_bool()

   self._lib.cl(byref(c_float(cl)), byref(a), byref(cd), byref(cm), byref(cp), byref(conv))

   return (a.value, cd.value, cm.value, cp.value) if conv else (np.nan, np.nan, np.nan, np.nan)

def aseq(self, a_start, a_end, a_step):
   n = abs(int((a_end - a_start) / a_step))

   a = np.zeros(n, dtype=c_float)
   cl = np.zeros(n, dtype=c_float)
   cd = np.zeros(n, dtype=c_float)
   cm = np.zeros(n, dtype=c_float)
   cp = np.zeros(n, dtype=c_float)
   conv = np.zeros(n, dtype=c_bool)

   self._lib.aseq(byref(c_float(a_start)), byref(c_float(a_end)), byref(c_int(n)),
                  a.ctypes.data_as(fptr), cl.ctypes.data_as(fptr),
                  cd.ctypes.data_as(fptr), cm.ctypes.data_as(fptr),
                  cp.ctypes.data_as(fptr), conv.ctypes.data_as(bptr))

   isnan = np.logical_not(conv)
   a[isnan] = np.nan
   cl[isnan] = np.nan
   cd[isnan] = np.nan
   cm[isnan] = np.nan
   cp[isnan] = np.nan
   return a.astype(float), cl.astype(float), cd.astype(float), cm.astype(float), cp.astype(float)

def cseq(self, cl_start, cl_end, cl_step):
   n = abs(int((cl_end - cl_start) / cl_step))

   a = np.zeros(n, dtype=c_float)
   cl = np.zeros(n, dtype=c_float)
   cd = np.zeros(n, dtype=c_float)
   cm = np.zeros(n, dtype=c_float)
   cp = np.zeros(n, dtype=c_float)
   conv = np.zeros(n, dtype=c_bool)

   self._lib.cseq(byref(c_float(cl_start)), byref(c_float(cl_end)), byref(c_int(n)),
                  a.ctypes.data_as(fptr), cl.ctypes.data_as(fptr),
                  cd.ctypes.data_as(fptr), cm.ctypes.data_as(fptr),
                  cp.ctypes.data_as(fptr), conv.ctypes.data_as(bptr))

   isnan = np.logical_not(conv)
   a[isnan] = np.nan
   cl[isnan] = np.nan
   cd[isnan] = np.nan
   cm[isnan] = np.nan
   cp[isnan] = np.nan
   return a.astype(float), cl.astype(float), cd.astype(float), cm.astype(float), cp.astype(float)

収束していない値をはなから使えないようにしてくれる心遣いではあるが,とにかく何かしらの値を返してほしい場合は面倒なことになってしまう

反復計算が収束していなくても値が返ってくるようにするために,ダウンロードしたレポジトリにある xfoil.py を次のように書き換える

※コメントアウトは省略

def a(self, a):
    cl = c_float()
    cd = c_float()
    cm = c_float()
    cp = c_float()
    conv = c_bool()

    self._lib.alfa(byref(c_float(a)), byref(cl), byref(cd), byref(cm), byref(cp), byref(conv))

    return (cl.value, cd.value, cm.value, cp.value) # if conv else (np.nan, np.nan, np.nan, np.nan)

def cl(self, cl):
    a = c_float()
    cd = c_float()
    cm = c_float()
    cp = c_float()
    conv = c_bool()

    self._lib.cl(byref(c_float(cl)), byref(a), byref(cd), byref(cm), byref(cp), byref(conv))

    return (a.value, cd.value, cm.value, cp.value) # if conv else (np.nan, np.nan, np.nan, np.nan)

def aseq(self, a_start, a_end, a_step):
    n = abs(int((a_end - a_start) / a_step))

    a = np.zeros(n, dtype=c_float)
    cl = np.zeros(n, dtype=c_float)
    cd = np.zeros(n, dtype=c_float)
    cm = np.zeros(n, dtype=c_float)
    cp = np.zeros(n, dtype=c_float)
    conv = np.zeros(n, dtype=c_bool)

    self._lib.aseq(byref(c_float(a_start)), byref(c_float(a_end)), byref(c_int(n)),
                    a.ctypes.data_as(fptr), cl.ctypes.data_as(fptr),
                    cd.ctypes.data_as(fptr), cm.ctypes.data_as(fptr),
                    cp.ctypes.data_as(fptr), conv.ctypes.data_as(bptr))

    isnan = np.logical_not(conv)
    #a[isnan] = np.nan
    #cl[isnan] = np.nan
    #cd[isnan] = np.nan
    #cm[isnan] = np.nan
    #cp[isnan] = np.nan
    return a.astype(float), cl.astype(float), cd.astype(float), cm.astype(float), cp.astype(float)

def cseq(self, cl_start, cl_end, cl_step):
    n = abs(int((cl_end - cl_start) / cl_step))

    a = np.zeros(n, dtype=c_float)
    cl = np.zeros(n, dtype=c_float)
    cd = np.zeros(n, dtype=c_float)
    cm = np.zeros(n, dtype=c_float)
    cp = np.zeros(n, dtype=c_float)
    conv = np.zeros(n, dtype=c_bool)

    self._lib.cseq(byref(c_float(cl_start)), byref(c_float(cl_end)), byref(c_int(n)),
                    a.ctypes.data_as(fptr), cl.ctypes.data_as(fptr),
                    cd.ctypes.data_as(fptr), cm.ctypes.data_as(fptr),
                    cp.ctypes.data_as(fptr), conv.ctypes.data_as(bptr))

    isnan = np.logical_not(conv)
    #a[isnan] = np.nan
    #cl[isnan] = np.nan
    #cd[isnan] = np.nan
    #cm[isnan] = np.nan
    #cp[isnan] = np.nan
    return a.astype(float), cl.astype(float), cd.astype(float), cm.astype(float), cp.astype(float)

書き換えたら保存してもう一度 pip でインストールを行う

C:\Users\XXX\Desktop\xfoil>py -3.6 -m pip install .
Processing c:\users\XXX\desktop\xfoil
  Preparing metadata (setup.py) ... done
Requirement already satisfied: numpy in c:\users\XXX\appdata\local\programs\python\python36\lib\site-packages (from xfoil==1.1.1) (1.19.5)
Using legacy 'setup.py install' for xfoil, since package 'wheel' is not installed.
Installing collected packages: xfoil
  Attempting uninstall: xfoil
    Found existing installation: xfoil 1.1.1
    Uninstalling xfoil-1.1.1:
      Successfully uninstalled xfoil-1.1.1
    Running setup.py install for xfoil ... done
Successfully installed xfoil-1.1.1

テストプログラムの実行

テストプログラムを実行するために matplotlib もインストールしておく

C:\Users\XXX\Desktop\xfoil>py -3.6 -m pip install matplotlib

解析する翼型はみんな大好きDAE31とNACA4412

datファイルのデータはこれ

DAE31
 1.0000000     0.0000000
 0.9910549     0.0019676
 0.9751725     0.0056508
 0.9562892     0.0102773
 0.9348845     0.0157716
 0.9118290     0.0219602
 0.8877617     0.0287011
 0.8629994     0.0358851
 0.8377395     0.0434059
 0.8121316     0.0511492
 0.7867002     0.0588254
 0.7619602     0.0661241
 0.7378954     0.0729224
 0.7142982     0.0791842
 0.6909062     0.0849452
 0.6675955     0.0902334
 0.6443157     0.0950530
 0.6210077     0.0994086
 0.5976155     0.1033104
 0.5741033     0.1067704
 0.5504558     0.1097981
 0.5266740     0.1124031
 0.5027839     0.1145914
 0.4788216     0.1163647
 0.4548339     0.1177244
 0.4308940     0.1186644
 0.4070451     0.1191690
 0.3832867     0.1192302
 0.3596416     0.1188447
 0.3361549     0.1180073
 0.3128750     0.1167072
 0.2898298     0.1149313
 0.2670436     0.1126721
 0.2445728     0.1099286
 0.2225073     0.1067006
 0.2009441     0.1029850
 0.1799680     0.0987808
 0.1596995     0.0941120
 0.1403288     0.0890216
 0.1220556     0.0835674
 0.1050817     0.0778315
 0.0895859     0.0719246
 0.0757089     0.0659851
 0.0635164     0.0601440
 0.0529609     0.0544931
 0.0439060     0.0490943
 0.0361794     0.0439863
 0.0296006     0.0391763
 0.0239969     0.0346545
 0.0192170     0.0304007
 0.0151340     0.0263895
 0.0116467     0.0225925
 0.0086870     0.0189712
 0.0062058     0.0154863
 0.0041396     0.0121274
 0.0024387     0.0088917
 0.0011249     0.0057470
 0.0005111     0.0036795
 0.0002956     0.0026546
 0.0001444     0.0016368
 0.0000000     0.0000000
 0.0000732    -0.0033344
 0.0003224    -0.0052847
 0.0005253    -0.0062484
 0.0007913    -0.0071995
 0.0011270    -0.0081316
 0.0015386    -0.0090365
 0.0020315    -0.0099069
 0.0026069    -0.0107343
 0.0032641    -0.0115095
 0.0040024    -0.0122247
 0.0048172    -0.0128750
 0.0057020    -0.0134557
 0.0066512    -0.0139647
 0.0076586    -0.0144080
 0.0087170    -0.0147934
 0.0098213    -0.0151289
 0.0121629    -0.0156765
 0.0160127    -0.0162722
 0.0203174    -0.0166809
 0.0251704    -0.0169573
 0.0307077    -0.0170976
 0.0371267    -0.0170789
 0.0447105    -0.0168835
 0.0538609    -0.0164863
 0.0651185    -0.0158460
 0.0791218    -0.0148852
 0.0964621    -0.0135084
 0.1173137    -0.0116815
 0.1411530    -0.0094668
 0.1669774    -0.0070044
 0.1937839    -0.0044371
 0.2208949    -0.0018732
 0.2480412     0.0006298
 0.2751500     0.0030496
 0.3021781     0.0053706
 0.3291109     0.0075769
 0.3559543     0.0096567
 0.3827039     0.0116006
 0.4093341     0.0133929
 0.4358625     0.0150181
 0.4622963     0.0164689
 0.4886091     0.0177316
 0.5148084     0.0187870
 0.5409500     0.0196233
 0.5670984     0.0202439
 0.5932355     0.0206558
 0.6193428     0.0208512
 0.6454416     0.0208262
 0.6715560     0.0205806
 0.6977112     0.0201197
 0.7238936     0.0194539
 0.7500470     0.0185860
 0.7761535     0.0175065
 0.8022314     0.0162106
 0.8282915     0.0146975
 0.8543374     0.0129730
 0.8802830     0.0110562
 0.9059293     0.0089751
 0.9307780     0.0068061
 0.9538566     0.0046630
 0.9740739     0.0026703
 0.9908034     0.0009545
 1.0000000     0.0000000
NACA4412
 1.0000000     0.0013136
 0.9939273     0.0029719
 0.9833112     0.0058293
 0.9709450     0.0091023
 0.9571338     0.0126881
 0.9423309     0.0164505
 0.9269393     0.0202749
 0.9112263     0.0240880
 0.8953420     0.0278499
 0.8793632     0.0315409
 0.8633282     0.0351517
 0.8472560     0.0386778
 0.8311561     0.0421170
 0.8150338     0.0454683
 0.7988922     0.0487309
 0.7827335     0.0519042
 0.7665595     0.0549876
 0.7503718     0.0579806
 0.7341717     0.0608824
 0.7179607     0.0636923
 0.7017402     0.0664093
 0.6855117     0.0690325
 0.6692766     0.0715607
 0.6530365     0.0739926
 0.6367928     0.0763270
 0.6205471     0.0785623
 0.6043011     0.0806969
 0.5880564     0.0827292
 0.5718147     0.0846572
 0.5555780     0.0864788
 0.5393482     0.0881921
 0.5231275     0.0897945
 0.5069182     0.0912838
 0.4907233     0.0926571
 0.4745468     0.0939118
 0.4583946     0.0950446
 0.4422758     0.0960523
 0.4262098     0.0969310
 0.4102226     0.0976771
 0.3943970     0.0982802
 0.3787710     0.0986930
 0.3632373     0.0989005
 0.3477749     0.0989039
 0.3323710     0.0987000
 0.3170230     0.0982856
 0.3017333     0.0976571
 0.2865063     0.0968109
 0.2713487     0.0957430
 0.2562684     0.0944495
 0.2412746     0.0929264
 0.2263781     0.0911697
 0.2115920     0.0891755
 0.1969314     0.0869400
 0.1824151     0.0844599
 0.1680668     0.0817327
 0.1539168     0.0787573
 0.1400052     0.0755352
 0.1263858     0.0720724
 0.1131318     0.0683825
 0.1003415     0.0644905
 0.0881413     0.0604380
 0.0766810     0.0562868
 0.0661153     0.0521168
 0.0565712     0.0480165
 0.0481145     0.0440659
 0.0407355     0.0403219
 0.0343604     0.0368119
 0.0288778     0.0335380
 0.0241649     0.0304851
 0.0201059     0.0276294
 0.0166001     0.0249444
 0.0135646     0.0224043
 0.0109328     0.0199852
 0.0086525     0.0176661
 0.0066841     0.0154288
 0.0049983     0.0132582
 0.0040202     0.0118416
 0.0035734     0.0111413
 0.0031540     0.0104460
 0.0027617     0.0097554
 0.0023966     0.0090699
 0.0020581     0.0083892
 0.0017459     0.0077129
 0.0014600     0.0070410
 0.0011999     0.0063730
 0.0009655     0.0057087
 0.0007569     0.0050484
 0.0005740     0.0043921
 0.0004167     0.0037412
 0.0002853     0.0030976
 0.0001796     0.0024626
 0.0000989     0.0018360
 0.0000425     0.0012178
 0.0000095     0.0006069
 0.0000000     0.0000000
 0.0000140    -0.0006062
 0.0000519    -0.0012151
 0.0001154    -0.0018282
 0.0002060    -0.0024460
 0.0003255    -0.0030688
 0.0004747    -0.0036950
 0.0006543    -0.0043216
 0.0008650    -0.0049466
 0.0011073    -0.0055688
 0.0013814    -0.0061866
 0.0016875    -0.0067993
 0.0020260    -0.0074063
 0.0023965    -0.0080067
 0.0027991    -0.0085999
 0.0032337    -0.0091856
 0.0036998    -0.0097628
 0.0041970    -0.0103312
 0.0047253    -0.0108907
 0.0052842    -0.0114408
 0.0058736    -0.0119818
 0.0064937    -0.0125137
 0.0071442    -0.0130366
 0.0078253    -0.0135508
 0.0085375    -0.0140565
 0.0092809    -0.0145539
 0.0100561    -0.0150432
 0.0108639    -0.0155250
 0.0117048    -0.0159992
 0.0125798    -0.0164663
 0.0144369    -0.0173806
 0.0175104    -0.0187064
 0.0209725    -0.0199834
 0.0248868    -0.0212172
 0.0293357    -0.0224108
 0.0344235    -0.0235640
 0.0402806    -0.0246724
 0.0470649    -0.0257260
 0.0549436    -0.0267059
 0.0640642    -0.0275835
 0.0745185    -0.0283238
 0.0863003    -0.0288915
 0.0992890    -0.0292609
 0.1132825    -0.0294225
 0.1280578    -0.0293839
 0.1434186    -0.0291639
 0.1592140    -0.0287872
 0.1753366    -0.0282792
 0.1917117    -0.0276641
 0.2082873    -0.0269638
 0.2250258    -0.0261983
 0.2418975    -0.0253851
 0.2588747    -0.0245404
 0.2759252    -0.0236791
 0.2929960    -0.0228160
 0.3100367    -0.0219643
 0.3270315    -0.0211343
 0.3439784    -0.0203342
 0.3608826    -0.0195714
 0.3777601    -0.0188511
 0.3946253    -0.0181811
 0.4115641    -0.0175410
 0.4285819    -0.0168825
 0.4456487    -0.0162064
 0.4627544    -0.0155175
 0.4798894    -0.0148203
 0.4970437    -0.0141191
 0.5141991    -0.0134183
 0.5313422    -0.0127217
 0.5484689    -0.0120324
 0.5655781    -0.0113532
 0.5826705    -0.0106865
 0.5997473    -0.0100345
 0.6168100    -0.0093992
 0.6338601    -0.0087823
 0.6508991    -0.0081853
 0.6679286    -0.0076094
 0.6849499    -0.0070560
 0.7019645    -0.0065259
 0.7189736    -0.0060199
 0.7359787    -0.0055387
 0.7529808    -0.0050828
 0.7699811    -0.0046525
 0.7869807    -0.0042480
 0.8039804    -0.0038693
 0.8209805    -0.0035163
 0.8379804    -0.0031887
 0.8549773    -0.0028863
 0.8719640    -0.0026085
 0.8889233    -0.0023548
 0.9058166    -0.0021249
 0.9225614    -0.0019184
 0.9389893    -0.0017355
 0.9547906    -0.0015769
 0.9694916    -0.0014436
 0.9825665    -0.0013359
 0.9936870    -0.0012516
 1.0000000    -0.0012064

前縁の座標が(0,0),後縁のx座標が1であることを確認する(ここがずれていると計算が安定しない)

test_01.py

迎角の範囲を指定して計算するテストプログラムはこんな感じ

#!python3.6
import numpy as np
import matplotlib.pyplot as plt
from xfoil import XFoil
from xfoil.model import Airfoil

# Create an instance of the XFoil class
xf = XFoil()

# Read an airfoil in the same format as XFLR5 (.dat)
with open("./DAE31.dat", "r") as f:
    airfoil = f.readlines()
# Split strings by tab
airfoil = [line.split() for line in airfoil]
# Convert strings in list to numpy array 
airfoil = np.array(airfoil[1:],dtype='float64')

# Airfoil: Instance of the Airfoil class
xf.airfoil = Airfoil(airfoil[:,0],airfoil[:,1])

# Difine analysis
xf.Re = 1e6         # float: Reynolds number
xf.M = 0            # float: Mach number.
xf.n_crit = 9       # float: Critical amplification ratio
xf.xtr = (1, 1)     # tuple(float, float): Top and bottom flow trip x/c locations
xf.max_iter = 100   # int: Maximum number of iterations
xf.reset_bls        # Reset the boundary layers to be reinitialized on the next analysis
xf.repanel          # Re-panel airfoil

# Analyze airfoil at a sequence of angles of attack
a, cl, cd, cm, cp = xf.aseq(-20, 21, 1)
LbyD = cl/cd

print(a,cl)

plot(a, cl, cd, cm, cp, LbyD)

グラフを書くための関数はこれ

def plot(a, cl, cd, cm, cp, LbyD):
    # Plot graph
    fig = plt.figure(figsize=(16, 9))
    ax11 = fig.add_subplot(221)
    ax12 = fig.add_subplot(222)
    ax21 = fig.add_subplot(223)
    ax22 = fig.add_subplot(224)

    ax11.plot([-200,0,0,0,0,200], [0,0,200,-200,0,0], 'k-', linewidth=0.5)
    ax12.plot([-200,0,0,0,0,200], [0,0,200,-200,0,0], 'k-', linewidth=0.5)
    ax21.plot([-200,0,0,0,0,200], [0,0,200,-200,0,0], 'k-', linewidth=0.5)
    ax22.plot([-200,0,0,0,0,200], [0,0,200,-200,0,0], 'k-', linewidth=0.5)

    ax11.set_xlabel('alpha')
    ax11.set_ylabel('Cl')
    ax11.plot(a, cl, 'r.-')
    ax12.set_xlabel('Cl')
    ax12.set_ylabel('Cd')
    ax12.plot(cl, cd, 'r.-')
    ax21.set_xlabel('Cl')
    ax21.set_ylabel('Cm')
    ax21.plot(cl, cm, 'r.-')
    ax22.set_xlabel('Cl')
    ax22.set_ylabel('L/D')
    ax22.plot(cl, LbyD, 'r.-')

    ax11.grid(True)
    ax11.set_xlim([-20,20])
    ax11.set_xticks([i*10 for i in range(-2,3,1)])
    ax11.set_ylim([-0.5,2.0])
    ax11.set_yticks([i*0.1 for i in range(-5,25,5)])
    ax12.grid(True)
    ax12.set_xlim([-0.5,2.0])
    ax12.set_xticks([i*0.1 for i in range(-5,25,5)])
    ax12.set_ylim([0,0.2])
    ax12.set_yticks([i*0.01 for i in range(0,25,5)])
    ax21.grid(True)
    ax21.set_xlim([-0.5,2.0])
    ax21.set_xticks([i*0.1 for i in range(-5,25,5)])
    ax21.set_ylim([-0.16,0])
    ax21.set_yticks([i*0.01 for i in range(-16,0,2)])
    ax22.grid(True)
    ax22.set_xlim([-0.5,2.0])
    ax22.set_xticks([i*0.1 for i in range(-5,25,5)])
    ax22.set_ylim([-50,200])
    ax22.set_yticks([i*10 for i in range(-5,25,5)])

    # Show graph
    plt.show()

参考
Pythonの複数バージョンの扱い方(Windowsの場合) - ガンマソフト株式会社
Pythonでファイルの読み込み、書き込み(作成・追記) _ note.nkmk.me
Python, splitでカンマ区切り文字列を分割、空白を削除しリスト化 _ note.nkmk.me
Pythonのrange関数の使い方 _ note.nkmk.me

まずはDAE31から実行してみる

C:\Users\XXX\Desktop\xfoil\test>py test_01.py 

 Number of input coordinate points: 124
 Counterclockwise ordering
 Max thickness =     0.110598  at x =   0.290
 Max camber    =     0.067515  at x =   0.455

  LE  x,y  =  -0.00003  -0.00112  |   Chord =   1.00003
  TE  x,y  =   1.00000   0.00000  |

 Current airfoil nodes set from buffer airfoil nodes ( 124 )
 Calculating unit vorticity distributions ...
 Calculating wake trajectory ...
 Calculating source influence matrix ...

 Solving BL system ...

 Initializing BL ...
    side            1  ...
 MRCHUE: Inverse mode at  32     Hk =   4.873
 MRCHUE: Inverse mode at  33     Hk =   6.535

    (中略)

 Side 2 forced transition at x/c =  1.0000   41

   2   rms: 0.9086E-01   max: 0.4994E+00   T at    2  1
       a = 20.000      CL =  1.7431
      Cm = -0.0828     CD =  0.10866   =>   CDf =  0.00496    CDp =  0.10370

 Side 1  free  transition at x/c =  0.0123   35
 Side 2 forced transition at x/c =  1.0000   41

   3   rms: 0.3153E-01   max: 0.1986E+00   D at   61  1
       a = 20.000      CL =  1.7240
      Cm = -0.0841     CD =  0.11121   =>   CDf =  0.00484    CDp =  0.10637

 Side 1  free  transition at x/c =  0.0126   35
 Side 2 forced transition at x/c =  1.0000   41

   4   rms: 0.5837E-02   max: 0.6224E-01   D at   60  1
       a = 20.000      CL =  1.7212
      Cm = -0.0843     CD =  0.11120   =>   CDf =  0.00477    CDp =  0.10643

 Side 1  free  transition at x/c =  0.0127   35
 Side 2 forced transition at x/c =  1.0000   41

   5   rms: 0.7752E-03   max: -.6740E-02   D at   60  1
       a = 20.000      CL =  1.7215
      Cm = -0.0842     CD =  0.11097   =>   CDf =  0.00475    CDp =  0.10622

 Side 1  free  transition at x/c =  0.0126   35
 Side 2 forced transition at x/c =  1.0000   41

   6   rms: 0.6234E-04   max: 0.3615E-03   C at   41  2
       a = 20.000      CL =  1.7215
      Cm = -0.0842     CD =  0.11098   =>   CDf =  0.00475    CDp =  0.10622
      9.000   15.7656   0.110976   0.013829   0.001426  -0.012403    0.0126     #

こんな図が出力される

本家と比べてみる

非常にそれっぽい

次はNACA4412

負の迎角が大きいところでは怪しいがそれ以外はいい感じに計算できている

test_02.py

次は圧力分布を計算してみる

テストプログラムはこれ

#!python3.6
import numpy as np
import matplotlib.pyplot as plt
from xfoil import XFoil
from xfoil.model import Airfoil

# Create an instance of the XFoil class
xf = XFoil()

# Read an airfoil in the same format as XFLR5 (.dat)
with open("./DAE31.dat", "r") as f:
    airfoil = f.readlines()
# Split strings by tab
airfoil = [line.split() for line in airfoil]
# Convert strings in list to numpy array 
airfoil = np.array(airfoil[1:],dtype='float64')

# Airfoil: Instance of the Airfoil class
xf.airfoil = Airfoil(airfoil[:,0],airfoil[:,1])

# Difine analysis
xf.Re = 1e6         # float: Reynolds number
xf.M = 0            # float: Mach number.
xf.n_crit = 9       # float: Critical amplification ratio
xf.xtr = (1, 1)     # tuple(float, float): Top and bottom flow trip x/c locations
xf.max_iter = 100   # int: Maximum number of iterations
xf.reset_bls        # Reset the boundary layers to be reinitialized on the next analysis
xf.repanel          # Re-panel airfoil

# Analyze airfoil at a fixed lift coefficient
a, cd, cm, cp = xf.cl(1.0)
x, cp = xf.get_cp_distribution()

plot(x,cp)
def plot(x, cp):
    # Plot graph
    fig = plt.figure(figsize=(16, 9))
    ax = fig.add_subplot(111)

    ax.plot([-200,0,0,0,0,200], [0,0,200,-200,0,0], 'k-', linewidth=0.5)

    linetype = 'r.-'
    ax.set_xlabel('x')
    ax.set_ylabel('Cp')
    ax.plot(x, cp, linetype)

    ax.grid(True)
    ax.set_xlim([0.03,1.03])
    ax.set_xticks([i*0.1 for i in range(0,11,1)])
    ax.set_ylim([-1.26,1.07])
    ax.invert_yaxis()
    ax.set_yticks([i*0.1 for i in range(-12,10,2)])

    # Show graph
    plt.show()

実行する

C:\Users\XXX\Desktop\xfoil\test>py test_02.py

 Number of input coordinate points: 124
 Counterclockwise ordering
 Max thickness =     0.110598  at x =   0.290
 Max camber    =     0.067515  at x =   0.455

  LE  x,y  =  -0.00003  -0.00112  |   Chord =   1.00003     
  TE  x,y  =   1.00000   0.00000  |

 Current airfoil nodes set from buffer airfoil nodes ( 124 )
 Calculating unit vorticity distributions ...
 Calculating wake trajectory ...
 Calculating source influence matrix ...

 Solving BL system ...

 Initializing BL ...
    side            1  ...
 MRCHUE: Inverse mode at  44     Hk =   5.001
 MRCHUE: Inverse mode at  45     Hk =   6.456
 MRCHUE: Inverse mode at  46     Hk =   2.500
    side            2  ...
 MRCHUE: Inverse mode at  63     Hk =   2.716

 Side 1  free  transition at x/c =  0.5999   46
 Side 2 forced transition at x/c =  1.0000   63

   1   rms: 0.1135E+00   max: -.5909E+00   C at   63  2   RLX: 0.846
       a =  2.263      CL =  0.9994
      Cm = -0.1580     CD =  0.00546   =>   CDf =  0.00398    CDp =  0.00148

 Side 1  free  transition at x/c =  0.6592   49
 Side 2 forced transition at x/c =  1.0000   62

   2   rms: 0.5143E-01   max: 0.7163E+00   C at   49  1
       a =  2.372      CL =  1.0000
      Cm = -0.1558     CD =  0.00571   =>   CDf =  0.00359    CDp =  0.00212

 Side 1  free  transition at x/c =  0.6277   48
 Side 2 forced transition at x/c =  1.0000   62

   3   rms: 0.6191E-02   max: -.6767E-01   D at   50  1
       a =  2.372      CL =  1.0000
      Cm = -0.1559     CD =  0.00584   =>   CDf =  0.00378    CDp =  0.00206

 Side 1  free  transition at x/c =  0.6275   48
 Side 2 forced transition at x/c =  1.0000   62

   4   rms: 0.1876E-03   max: 0.1840E-02   C at   48  1
       a =  2.372      CL =  1.0000
      Cm = -0.1559     CD =  0.00584   =>   CDf =  0.00378    CDp =  0.00206

 Side 1  free  transition at x/c =  0.6274   48
 Side 2 forced transition at x/c =  1.0000   62

   5   rms: 0.5736E-06   max: -.3553E-05   D at   48  1
       a =  2.372      CL =  1.0000
      Cm = -0.1559     CD =  0.00584   =>   CDf =  0.00378    CDp =  0.00206
      9.000    3.6745   0.005839   0.000000   0.000000   0.000000    0.6274     #

DAE31の結果

NACA4412

それっぽい

まとめ

Visual Studio CodeでPythonを使ってXfoilで2次元翼型を解析する方法について説明した

久しぶりにPythonで環境構築をやることになったが,相変わらずの重労働だった(3日くらいかかった)

これを使えばいろいろと面白いことができるんじゃないかと思う

↓関連記事

補足

最新版のPythonのバージョン(3.10)でやりたい場合は,MS Compilerのバージョンを1929にする

XFLR5
質問・感想・意見などあれば気軽にTwitterのDMかコメントお願いします!
スポンサーリンク

コメント