├── AUTHORS ├── clean_build.sh ├── INSTALL ├── setup.py.in ├── README.md ├── examples ├── c_example.c ├── clarky.dat ├── python_example2.py ├── fortran_example.f90 ├── mh32_smoothed.dat ├── python_example3_parallel.py └── python_example1.py ├── CMakeLists.txt ├── src ├── naca.f ├── xfoil_data_mod.f90 ├── my_equivalence.f90 ├── xfoil_math.f ├── libxfoil.h ├── memory.c └── libxfoil.f90 ├── python ├── libxfoil.i └── libxfoil_wrap.py └── LICENSE /AUTHORS: -------------------------------------------------------------------------------- 1 | Copyright (C) 2018 2 | 3 | Xfoil was written by Mark Drela and Harold Youngren. libxfoil was written by 4 | Daniel Prosser . 5 | -------------------------------------------------------------------------------- /clean_build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm -rf build install 4 | rm examples/{c_example,fortran_example} 5 | rm setup.py python/{libxfoil.py,libxfoil_wrap.c} 6 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | libxfoil uses CMake to configure and build. distutils is used to build and 2 | install the Python bindings. A basic build can use the following steps: 3 | 4 | # Build and install library with C and Fortran bindings 5 | mkdir build 6 | cd build 7 | cmake -DCMAKE_BUILD_TYPE="Release" .. 8 | make 9 | make install 10 | cd .. 11 | 12 | # Build and install python bindings 13 | python setup.py build_ext 14 | python setup.py install 15 | 16 | To see available build options, use ccmake. Sample build scripts are also 17 | included. 18 | -------------------------------------------------------------------------------- /setup.py.in: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from distutils.core import setup, Extension 4 | 5 | setup(name = 'libxfoil', 6 | version = '${LIBXFOIL_VERSION}', 7 | py_modules = ['libxfoil_wrap', 'libxfoil'], 8 | ext_modules = [Extension('_libxfoil', 9 | sources=['python/libxfoil.i'], 10 | libraries=['xfoil'], 11 | library_dirs=['${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}'], 12 | include_dirs=['${CMAKE_SOURCE_DIR}/src'])], 13 | package_dir = {'': 'python'} 14 | ) 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | libxfoil 2 | ================================================================================ 3 | 4 | libxfoil is a library to analyze the aerodynamics of 2-dimensional airfoil 5 | sections programmatically using the Xfoil aerodynamics engine. The main focus 6 | is on supporting the functionality of Xfoil's OPER direct analysis mode, but 7 | some geometry functions including spline interpolation, flap deflections, 8 | trailing edge gap modifications, and NACA 4- and 5-digit airfoil generation 9 | are also included. In addition to integrated forces and moments, pressure 10 | distributions and boundary layer variables (including skin friction coefficient, 11 | displacement thickness, log of amplification ratio, etc.) can also be accessed. 12 | 13 | The API employs a pseudo object-oriented approach; global variables in the 14 | original Xfoil code have been moved to a struct, allowing multiple instances of 15 | the Xfoil engine, representing different airfoils, to be saved in memory 16 | simultaneously and executed in parallel. Memory for each instance is managed 17 | dynamically through the xfoil_init and xfoil_cleanup methods. libxfoil provides 18 | C, Fortran, and Python bindings as well as example programs in each language. 19 | -------------------------------------------------------------------------------- /examples/c_example.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "libxfoil.h" 5 | 6 | int main() 7 | { 8 | xfoil_options_type opts; 9 | xfoil_geom_options_type geom_opts; 10 | int nhalf = 100; 11 | int npoint = nhalf*2-1; 12 | double x[npoint], z[npoint]; 13 | int noppoint = 5; 14 | double oppoints[5] = {-0.3, 0.0, 0.3, 0.6, 0.9}; 15 | int opmodes[5] = {1, 1, 1, 1, 1}; 16 | double re[5] = {1.E+05, 1.E+05, 1.E+05, 1.E+05, 1.E+05}; 17 | double mach[5] = {0.0, 0.0, 0.0, 0.0, 0.0}; 18 | bool use_flap = false; 19 | bool reinitialize = false; 20 | bool fix_unconverged = false; 21 | bool converged; 22 | double lift[noppoint], drag[noppoint], moment[noppoint], viscrms[noppoint]; 23 | double alpha[noppoint], xtrt[noppoint], xtrb[noppoint]; 24 | int i, stat; 25 | xfoil_data_group xdg; 26 | 27 | opts.ncrit = 9.; 28 | opts.xtript = 1.; 29 | opts.xtripb = 1.; 30 | opts.viscous_mode = true; 31 | opts.silent_mode = true; 32 | opts.maxit = 100; 33 | opts.vaccel = 0.01; 34 | 35 | geom_opts.npan = 200; 36 | geom_opts.cvpar = 1.0; 37 | geom_opts.cterat = 0.15; 38 | geom_opts.ctrrat = 0.2; 39 | geom_opts.xsref1 = 1.; 40 | geom_opts.xsref2 = 1.; 41 | geom_opts.xpref1 = 1.; 42 | geom_opts.xpref2 = 1.; 43 | 44 | // Generate an airfoil 45 | naca_5_digit("25012", &nhalf, x, z, &npoint, &stat); 46 | if (stat != 0) { return stat; } 47 | 48 | // Set up inputs 49 | xfoil_init(&xdg); 50 | xfoil_defaults(&xdg, &opts); 51 | xfoil_set_paneling(&xdg, &geom_opts); 52 | xfoil_set_buffer_airfoil(&xdg, x, z, &npoint); 53 | xfoil_smooth_paneling(&xdg, &stat); 54 | if (stat != 0) { return stat; } 55 | 56 | // Run it at all operating points 57 | printf("Running Xfoil ...\n"); 58 | for ( i = 0; i < noppoint; i++ ) 59 | { 60 | xfoil_set_reynolds_number(&xdg, &re[i]); 61 | xfoil_set_mach_number(&xdg, &mach[i]); 62 | xfoil_speccl(&xdg, &oppoints[i], &alpha[i], &lift[i], &drag[i], &moment[i], 63 | &converged, &stat); 64 | if (stat != 0) { return stat; } 65 | if (! converged) 66 | printf("Point %d did not converge.\n", i); 67 | else 68 | { 69 | printf("Point %d converged.\n", i+1); 70 | printf("Point %d: AoA = %.4f, Cl = %.4f, Cd = %.4f, Cm = %.4f\n", i+1, 71 | alpha[i], lift[i], drag[i], moment[i]); 72 | } 73 | } 74 | xfoil_cleanup(&xdg); 75 | 76 | // Now, do the same thing but with the run_xfoil method 77 | printf("\nRunning Xfoil using the run_xfoil method ...\n"); 78 | run_xfoil(&npoint, x, z, &geom_opts, &noppoint, oppoints, opmodes, re, mach, 79 | &use_flap, NULL, NULL, NULL, NULL, &opts, &reinitialize, 80 | &fix_unconverged, lift, drag, moment, viscrms, alpha, xtrt, xtrb, 81 | &stat); 82 | if (stat != 0) { return stat; } 83 | 84 | for ( i = 0; i < noppoint; i++ ) 85 | { 86 | printf("Point %d: AoA = %.4f, Cl = %.4f, Cd = %.4f, Cm = %.4f\n", i+1, 87 | alpha[i], lift[i], drag[i], moment[i]); 88 | } 89 | 90 | return 0; 91 | } 92 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Set up project 2 | cmake_minimum_required(VERSION 2.8.8) 3 | project(libxfoil C) 4 | enable_language(Fortran) 5 | set(LIBXFOIL_VERSION 1.0) 6 | 7 | # Determine compiler 8 | get_filename_component(Fortran_COMPILER_NAME ${CMAKE_Fortran_COMPILER} NAME) 9 | message("Fortran compiler: " ${CMAKE_Fortran_COMPILER}) 10 | 11 | # Default compiler flags 12 | if (Fortran_COMPILER_NAME MATCHES "gfortran") 13 | set (Fortran_REAL_FLAGS "-fdefault-real-8 -std=legacy") 14 | set (Fortran_DBLE_FLAGS "-std=legacy") 15 | elseif (Fortran_COMPILER_NAME MATCHES "ifort") 16 | set (Fortran_REAL_FLAGS "-r8") 17 | set (Fortran_DBLE_FLAGS "") 18 | else (Fortran_COMPILER_NAME MATCHES "gfortran") 19 | message(FATAL_ERROR "Fortran compiler not supported.") 20 | endif (Fortran_COMPILER_NAME MATCHES "gfortran") 21 | 22 | set(CMAKE_C_FLAGS_DEBUG "-g -Wall -fPIC") 23 | set(CMAKE_C_FLAGS_RELEASE "-fPIC -O2") 24 | 25 | # Build shared or static library 26 | set (LIBRARY_TYPE "shared" 27 | CACHE STRING "Whether to build a shared or static library" 28 | ) 29 | 30 | # Option to build examples 31 | set (BUILD_EXAMPLES TRUE 32 | CACHE BOOL "Whether to build and install example programs." 33 | ) 34 | 35 | # Set source files (exclude examples here) 36 | file(GLOB SOURCESC "src/*.c") 37 | file(GLOB SOURCESDBLE "src/*.f90") 38 | file(GLOB SOURCESREAL "src/*.f") 39 | 40 | # Source file flags 41 | set_source_files_properties(${SOURCESREAL} PROPERTIES COMPILE_FLAGS ${Fortran_REAL_FLAGS}) 42 | set_source_files_properties(${SOURCESDBLE} PROPERTIES COMPILE_FLAGS ${Fortran_DBLE_FLAGS}) 43 | 44 | # include directory (needed by examples) 45 | include_directories(${CMAKE_SOURCE_DIR}/src) 46 | 47 | # Build libraries 48 | if (LIBRARY_TYPE MATCHES "static") 49 | add_library(xfoil STATIC ${SOURCESC} ${SOURCESDBLE} ${SOURCESREAL}) 50 | else (LIBRARY_TYPE MATCHES "static") 51 | add_library(xfoil SHARED ${SOURCESC} ${SOURCESDBLE} ${SOURCESREAL}) 52 | endif (LIBRARY_TYPE MATCHES "static") 53 | 54 | # Build examples 55 | if (BUILD_EXAMPLES) 56 | add_executable(fortran_example "examples/fortran_example.f90") 57 | target_link_libraries(fortran_example xfoil) 58 | set_target_properties(fortran_example PROPERTIES 59 | INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}) 60 | 61 | add_executable(c_example "examples/c_example.c") 62 | target_link_libraries(c_example xfoil) 63 | set_target_properties(c_example PROPERTIES 64 | INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}) 65 | endif (BUILD_EXAMPLES) 66 | 67 | # Set up distutils script for Python 68 | configure_file(setup.py.in ${CMAKE_SOURCE_DIR}/setup.py) 69 | 70 | # Installation 71 | install(TARGETS xfoil DESTINATION lib${LIB_SUFFIX}) 72 | install(FILES "src/libxfoil.h" DESTINATION include) 73 | install(FILES ${CMAKE_BINARY_DIR}/libxfoil.mod DESTINATION include) 74 | if (BUILD_EXAMPLES) 75 | install(TARGETS fortran_example DESTINATION ${CMAKE_SOURCE_DIR}/examples) 76 | install(TARGETS c_example DESTINATION ${CMAKE_SOURCE_DIR}/examples) 77 | endif (BUILD_EXAMPLES) 78 | -------------------------------------------------------------------------------- /examples/clarky.dat: -------------------------------------------------------------------------------- 1 | 1.000000 0.000000 2 | 0.990000 0.002376 3 | 0.980000 0.004743 4 | 0.970000 0.007109 5 | 0.960000 0.009445 6 | 0.940000 0.014058 7 | 0.920000 0.018570 8 | 0.900000 0.022963 9 | 0.880000 0.027265 10 | 0.860000 0.031458 11 | 0.840000 0.035550 12 | 0.820000 0.039533 13 | 0.800000 0.043405 14 | 0.780000 0.047167 15 | 0.760000 0.050810 16 | 0.740000 0.054332 17 | 0.720000 0.057734 18 | 0.700000 0.061017 19 | 0.680000 0.064179 20 | 0.660000 0.067211 21 | 0.640000 0.070103 22 | 0.620000 0.072845 23 | 0.600000 0.075407 24 | 0.580000 0.077810 25 | 0.560000 0.080022 26 | 0.540000 0.082054 27 | 0.520000 0.083906 28 | 0.500000 0.085588 29 | 0.480000 0.087080 30 | 0.460000 0.088372 31 | 0.440000 0.089464 32 | 0.420000 0.090325 33 | 0.400000 0.090937 34 | 0.380000 0.091299 35 | 0.360000 0.091421 36 | 0.340000 0.091313 37 | 0.320000 0.091005 38 | 0.300000 0.090506 39 | 0.280000 0.089838 40 | 0.260000 0.088930 41 | 0.240000 0.087692 42 | 0.220000 0.086013 43 | 0.200000 0.083805 44 | 0.180000 0.080966 45 | 0.160000 0.077478 46 | 0.140000 0.073360 47 | 0.120000 0.068551 48 | 0.100000 0.062943 49 | 0.080000 0.056384 50 | 0.060000 0.048726 51 | 0.050000 0.044251 52 | 0.040000 0.039107 53 | 0.030000 0.033003 54 | 0.020000 0.025359 55 | 0.012000 0.017853 56 | 0.008000 0.013725 57 | 0.004000 0.008918 58 | 0.002000 0.005799 59 | 0.001000 0.003729 60 | 0.000500 0.002340 61 | 0.000000 0.000000 62 | 0.000500 -0.004670 63 | 0.001000 -0.005939 64 | 0.002000 -0.007809 65 | 0.004000 -0.010508 66 | 0.008000 -0.014285 67 | 0.012000 -0.016963 68 | 0.020000 -0.020259 69 | 0.030000 -0.022593 70 | 0.040000 -0.024497 71 | 0.050000 -0.026021 72 | 0.060000 -0.027096 73 | 0.080000 -0.028414 74 | 0.100000 -0.029323 75 | 0.120000 -0.029891 76 | 0.140000 -0.030160 77 | 0.160000 -0.030158 78 | 0.180000 -0.029947 79 | 0.200000 -0.029555 80 | 0.220000 -0.029013 81 | 0.240000 -0.028382 82 | 0.260000 -0.027670 83 | 0.280000 -0.026908 84 | 0.300000 -0.026137 85 | 0.320000 -0.025375 86 | 0.340000 -0.024623 87 | 0.360000 -0.023881 88 | 0.380000 -0.023139 89 | 0.400000 -0.022397 90 | 0.420000 -0.021656 91 | 0.440000 -0.020914 92 | 0.460000 -0.020172 93 | 0.480000 -0.019420 94 | 0.500000 -0.018668 95 | 0.520000 -0.017926 96 | 0.540000 -0.017174 97 | 0.560000 -0.016432 98 | 0.580000 -0.015680 99 | 0.600000 -0.014937 100 | 0.620000 -0.014195 101 | 0.640000 -0.013443 102 | 0.660000 -0.012701 103 | 0.680000 -0.011949 104 | 0.700000 -0.011207 105 | 0.720000 -0.010454 106 | 0.740000 -0.009712 107 | 0.760000 -0.008960 108 | 0.780000 -0.008217 109 | 0.800000 -0.007465 110 | 0.820000 -0.006723 111 | 0.840000 -0.005980 112 | 0.860000 -0.005228 113 | 0.880000 -0.004485 114 | 0.900000 -0.003733 115 | 0.920000 -0.002990 116 | 0.940000 -0.002238 117 | 0.960000 -0.001495 118 | 0.970000 -0.001119 119 | 0.980000 -0.000743 120 | 0.990000 -0.000376 121 | 1.000000 0.000000 122 | -------------------------------------------------------------------------------- /src/naca.f: -------------------------------------------------------------------------------- 1 | C This file is part of libxfoil 2 | 3 | C libxfoil is free software: you can redistribute it and/or modify 4 | C it under the terms of the GNU General Public License as published by 5 | C the Free Software Foundation, either version 3 of the License, or 6 | C (at your option) any later version. 7 | 8 | C libxfoil is distributed in the hope that it will be useful, 9 | C but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | C MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | C GNU General Public License for more details. 12 | 13 | C You should have received a copy of the GNU General Public License 14 | C along with libxfoil. If not, see . 15 | 16 | C Copyright (C) 2019 Daniel Prosser (this modified version of 17 | C XFoil code) 18 | C Original copyright (C) 2000 Mark Drela (original XFoil code) 19 | 20 | C===================================================================70 21 | 22 | SUBROUTINE NACA4(CAMB,XCAMB,THICK,XX,YT,YC,NSIDE,XB,YB,NB) 23 | REAL*8 CAMB, XCAMB, THICK 24 | REAL*8 XX(NSIDE), YT(NSIDE), YC(NSIDE) 25 | REAL*8 XB(2*NSIDE), YB(2*NSIDE) 26 | REAL*8 M 27 | C 28 | C---- TE point bunching parameter 29 | DATA AN / 1.5 / 30 | C 31 | M = CAMB / 100.0 32 | P = XCAMB 33 | T = THICK / 100.0 34 | C 35 | ANP = AN + 1.0 36 | DO 10 I=1, NSIDE 37 | FRAC = FLOAT(I-1)/FLOAT(NSIDE-1) 38 | IF(I.EQ.NSIDE) THEN 39 | XX(I) = 1.0 40 | ELSE 41 | XX(I) = 1.0 - ANP*FRAC*(1.0-FRAC)**AN - (1.0-FRAC)**ANP 42 | ENDIF 43 | YT(I) = ( 0.29690*SQRT(XX(I)) 44 | & - 0.12600*XX(I) 45 | & - 0.35160*XX(I)**2 46 | & + 0.28430*XX(I)**3 47 | & - 0.10150*XX(I)**4) * T / 0.20 48 | IF(XX(I).LT.P) THEN 49 | YC(I) = M/P**2 * (2.0*P*XX(I) - XX(I)**2) 50 | ELSE 51 | YC(I) = M/(1.0-P)**2 * ((1.0-2.0*P) + 2.0*P*XX(I)-XX(I)**2) 52 | ENDIF 53 | 10 CONTINUE 54 | C 55 | IB = 0 56 | DO 20 I=NSIDE, 1, -1 57 | IB = IB + 1 58 | XB(IB) = XX(I) 59 | YB(IB) = YC(I) + YT(I) 60 | 20 CONTINUE 61 | DO 30 I=2, NSIDE 62 | IB = IB + 1 63 | XB(IB) = XX(I) 64 | YB(IB) = YC(I) - YT(I) 65 | 30 CONTINUE 66 | NB = IB 67 | C 68 | RETURN 69 | END 70 | 71 | 72 | SUBROUTINE NACA5(IDES,XX,YT,YC,NSIDE,XB,YB,NB) 73 | REAL*8 XX(NSIDE), YT(NSIDE), YC(NSIDE) 74 | REAL*8 XB(2*NSIDE), YB(2*NSIDE) 75 | REAL*8 M 76 | C 77 | C---- TE point bunching parameter 78 | DATA AN / 1.5 / 79 | C 80 | N5 = IDES / 10000 81 | N4 = (IDES - N5*10000 ) / 1000 82 | N3 = (IDES - N5*10000 - N4*1000 ) / 100 83 | N2 = (IDES - N5*10000 - N4*1000 - N3*100 ) / 10 84 | N1 = (IDES - N5*10000 - N4*1000 - N3*100 - N2*10) 85 | C 86 | N543 = 100*N5 + 10*N4 + N3 87 | C 88 | IF (N543 .EQ. 210) THEN 89 | cc P = 0.05 90 | M = 0.0580 91 | C = 361.4 92 | ELSE IF (N543 .EQ. 220) THEN 93 | cc P = 0.10 94 | M = 0.1260 95 | C = 51.64 96 | ELSE IF (N543 .EQ. 230) THEN 97 | cc P = 0.15 98 | M = 0.2025 99 | C = 15.957 100 | ELSE IF (N543 .EQ. 240) THEN 101 | cc P = 0.20 102 | M = 0.2900 103 | C = 6.643 104 | ELSE IF (N543 .EQ. 250) THEN 105 | cc P = 0.25 106 | M = 0.3910 107 | C = 3.230 108 | ELSE 109 | WRITE(*,*) 'Illegal 5-digit designation' 110 | WRITE(*,*) 'First three digits must be 210, 220, ... 250' 111 | IDES = 0 112 | RETURN 113 | ENDIF 114 | C 115 | C 116 | T = FLOAT(N2*10 + N1) / 100.0 117 | C 118 | ANP = AN + 1.0 119 | DO 10 I=1, NSIDE 120 | FRAC = FLOAT(I-1)/FLOAT(NSIDE-1) 121 | IF(I.EQ.NSIDE) THEN 122 | XX(I) = 1.0 123 | ELSE 124 | XX(I) = 1.0 - ANP*FRAC*(1.0-FRAC)**AN - (1.0-FRAC)**ANP 125 | ENDIF 126 | C 127 | YT(I) = ( 0.29690*SQRT(XX(I)) 128 | & - 0.12600*XX(I) 129 | & - 0.35160*XX(I)**2 130 | & + 0.28430*XX(I)**3 131 | & - 0.10150*XX(I)**4) * T / 0.20 132 | IF(XX(I).LT.M) THEN 133 | YC(I) = (C/6.0) * (XX(I)**3 - 3.0*M*XX(I)**2 134 | & + M*M*(3.0-M)*XX(I)) 135 | ELSE 136 | YC(I) = (C/6.0) * M**3 * (1.0 - XX(I)) 137 | ENDIF 138 | 10 CONTINUE 139 | C 140 | IB = 0 141 | DO 20 I=NSIDE, 1, -1 142 | IB = IB + 1 143 | XB(IB) = XX(I) 144 | YB(IB) = YC(I) + YT(I) 145 | 20 CONTINUE 146 | DO 30 I=2, NSIDE 147 | IB = IB + 1 148 | XB(IB) = XX(I) 149 | YB(IB) = YC(I) - YT(I) 150 | 30 CONTINUE 151 | NB = IB 152 | C 153 | RETURN 154 | END 155 | -------------------------------------------------------------------------------- /examples/python_example2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | import libxfoil_wrap as xiw 5 | from libxfoil import xfoil_options_type, xfoil_geom_options_type, \ 6 | xfoil_data_group 7 | from matplotlib import pyplot as plt 8 | from math import sqrt 9 | 10 | def read_airfoil(fname): 11 | 12 | try: 13 | f = open(fname) 14 | except IOError: 15 | print("Unable to open {}.".format(fname)) 16 | sys.exit(1) 17 | 18 | x = [] 19 | z = [] 20 | for line in f: 21 | if line.startswith("MH"): 22 | continue 23 | 24 | x.append(float(line.split()[0])) 25 | z.append(float(line.split()[1])) 26 | 27 | f.close() 28 | 29 | return x, z, len(x) 30 | 31 | def centered_difference(yp1, y0, ym1, xp1, xm1): 32 | 33 | a = (yp1-y0 - (ym1-y0)*xp1/xm1) / (xp1*xp1 - xp1*xm1); 34 | b = (ym1-y0 - a*xm1*xm1) / xm1; 35 | 36 | return b 37 | 38 | def surface_derivative(var, x, z): 39 | 40 | n = len(x) 41 | s = [0.]*n 42 | for i in range(1,n): 43 | dx = x[i] - x[i-1] 44 | dz = z[i] - z[i-1] 45 | ds = sqrt(dx**2. + dz**2.) 46 | s[i] = s[i-1] + ds 47 | 48 | dvar = [0.]*n 49 | ds = s[1] - s[0] 50 | dvar[0] = (var[1] - var[0])/ds 51 | for i in range(1,n-1): 52 | splus = s[i+1] - s[i] 53 | sminus = s[i-1] - s[i] 54 | dvar[i] = centered_difference(var[i+1], var[i], var[i-1], splus, sminus) 55 | ds = s[n-1] - s[n-2] 56 | dvar[n-1] = (var[n-1]-var[n-2])/ds 57 | 58 | return dvar 59 | 60 | def plot_geometry(x, z, xwake, zwake, title=None): 61 | 62 | fig, ax = plt.subplots() 63 | ax.set_xlabel("x") 64 | ax.set_ylabel("z") 65 | if title is not None: 66 | ax.set_title(title) 67 | ax.plot(x, z) 68 | ax.plot(xwake, zwake, marker='.') 69 | ax.set_aspect('equal', 'datalim') 70 | ax.grid() 71 | 72 | plt.show() 73 | 74 | def plot_with_wake(x, xwake, var, varwake, varname, flip=False): 75 | 76 | fig, ax = plt.subplots() 77 | ax.set_xlabel("x") 78 | ax.set_ylabel(varname) 79 | ax.plot(x, var) 80 | ax.plot(xwake, varwake) 81 | if flip: 82 | ymin = ax.get_ylim()[0] 83 | ymax = ax.get_ylim()[1] 84 | ax.set_ylim(ymax, ymin) 85 | ax.grid() 86 | ax.legend(['Surface', 'Wake']) 87 | 88 | plt.show() 89 | 90 | if __name__ == "__main__": 91 | 92 | x, z, npoint = read_airfoil("mh32_smoothed.dat") 93 | 94 | opts = xfoil_options_type() 95 | opts.ncrit = 9. 96 | opts.xtript = 1. 97 | opts.xtripb = 1. 98 | opts.viscous_mode = True 99 | opts.silent_mode = True 100 | opts.maxit = 100 101 | opts.vaccel = 0.01 102 | 103 | geom_opts = xfoil_geom_options_type() 104 | geom_opts.npan = 160 105 | geom_opts.cvpar = 1. 106 | geom_opts.cterat = 0.15 107 | geom_opts.ctrrat = 0.2 108 | geom_opts.xsref1 = 1. 109 | geom_opts.xsref2 = 1. 110 | geom_opts.xpref1 = 1. 111 | geom_opts.xpref2 = 1. 112 | 113 | # Xfoil data 114 | xdg = xfoil_data_group() 115 | 116 | xiw.xfoil_init(xdg) 117 | xiw.xfoil_defaults(xdg, opts) 118 | xiw.xfoil_set_buffer_airfoil(xdg, x, z, npoint) 119 | xiw.xfoil_set_paneling(xdg, geom_opts) 120 | if (xiw.xfoil_smooth_paneling(xdg) != 0): 121 | print("Err 1") 122 | sys.exit(1) 123 | xnew, znew, stat = xiw.xfoil_get_current_airfoil(xdg, geom_opts.npan) 124 | if (stat != 0): 125 | print("Err 2") 126 | sys.exit(1) 127 | 128 | xiw.xfoil_set_reynolds_number(xdg, 127000.) 129 | xiw.xfoil_set_mach_number(xdg, 0.0) 130 | alpha, cl, cd, cm, converged, stat = xiw.xfoil_speccl(xdg, 0.72) 131 | if (stat != 0): 132 | print("Err 3") 133 | sys.exit(1) 134 | 135 | cp = xiw.xfoil_get_cp(xdg, geom_opts.npan) 136 | uedge = xiw.xfoil_get_uedge(xdg, geom_opts.npan) 137 | dstar = xiw.xfoil_get_deltastar(xdg, geom_opts.npan) 138 | mass = [] 139 | for i in range(geom_opts.npan): 140 | mass.append(uedge[i]*dstar[i]) 141 | 142 | nwake = xiw.xfoil_get_wakepoints(xdg) 143 | xw, zw = xiw.xfoil_get_wake_geometry(xdg, nwake) 144 | cpw = xiw.xfoil_get_wake_cp(xdg, nwake) 145 | uedgew = xiw.xfoil_get_wake_uedge(xdg, nwake) 146 | dstarw = xiw.xfoil_get_wake_deltastar(xdg, nwake) 147 | 148 | massw = [] 149 | for i in range(nwake): 150 | massw.append(uedgew[i]*dstarw[i]) 151 | 152 | xiw.xfoil_cleanup(xdg) 153 | 154 | # Mass defect derivative 155 | 156 | dmass = surface_derivative(mass, x, z) 157 | for i in range(81): 158 | dmass[i] *= -1.; # Sign is flipped on top surface 159 | dmassw = surface_derivative(massw, xw, zw) 160 | 161 | plot_geometry(xnew, znew, xw, zw, "Airfoil + wake") 162 | plot_with_wake(xnew, xw, cp, cpw, "Pressure coefficient", flip=True) 163 | plot_with_wake(xnew, xw, uedge, uedgew, "Edge velocity") 164 | plot_with_wake(xnew, xw, dstar, dstarw, "Displacement thickness") 165 | plot_with_wake(xnew, xw, mass, massw, "Mass defect") 166 | plot_with_wake(xnew, xw, dmass, dmassw, "Mass defect derivative") 167 | -------------------------------------------------------------------------------- /examples/fortran_example.f90: -------------------------------------------------------------------------------- 1 | program main 2 | 3 | use iso_c_binding 4 | use libxfoil 5 | 6 | implicit none 7 | 8 | type(xfoil_options_type) :: opts 9 | type(xfoil_geom_options_type) :: geom_opts 10 | integer :: npoint 11 | integer, parameter :: noppoint = 8 12 | double precision, dimension(:), allocatable :: x, z, s, xs, zs 13 | double precision :: xle, zle, sle 14 | double precision, dimension(noppoint) :: & 15 | oppoints = (/-6.d0, -3.d0, 0.d0, 3.d0, 6.d0, 9.d0, 12.d0, 15.d0/) 16 | integer, dimension(noppoint) :: opmodes = (/0, 0, 0, 0, 0, 0, 0, 0/) 17 | double precision, dimension(noppoint) :: re = 3.D+05 18 | double precision, dimension(noppoint) :: mach = 0.3d0 19 | double precision, dimension(noppoint) :: flapang = 0.d0 20 | double precision, dimension(noppoint) :: lift, drag, moment, viscrms, alpha, & 21 | xtrt, xtrb 22 | integer i 23 | logical(c_bool) :: use_flap = .false. 24 | logical(c_bool) :: fix_unconverged = .false. 25 | logical(c_bool) :: reinitialize = .false. 26 | integer(c_int) :: stat 27 | logical(c_bool) converged 28 | type(xfoil_data_group) :: xdg 29 | 30 | opts%ncrit = 9.d0 31 | opts%xtript = 1.d0 32 | opts%xtripb = 1.d0 33 | opts%viscous_mode = .true. 34 | opts%silent_mode = .true. 35 | opts%maxit = 100 36 | opts%vaccel = 0.01d0 37 | 38 | geom_opts%npan = 200 39 | geom_opts%cvpar = 1.d0 40 | geom_opts%cterat = 0.15d0 41 | geom_opts%ctrrat = 0.2d0 42 | geom_opts%xsref1 = 1.d0 43 | geom_opts%xsref2 = 1.d0 44 | geom_opts%xpref1 = 1.d0 45 | geom_opts%xpref2 = 1.d0 46 | 47 | ! Read airfoil from file 48 | call read_airfoil_points("clarky.dat", npoint) 49 | allocate(x(npoint)) 50 | allocate(z(npoint)) 51 | allocate(s(npoint)) 52 | allocate(xs(npoint)) 53 | allocate(zs(npoint)) 54 | call read_airfoil("clarky.dat", npoint, x, z) 55 | 56 | ! Get leading edge location 57 | call xfoil_spline_coordinates(x, z, npoint, s, xs, zs) 58 | call xfoil_lefind(x, z, s, xs, zs, npoint, sle, xle, zle) 59 | write(*,'(A14,F8.5,A2,F8.5)') "Leading edge: ", xle, ", ", zle 60 | 61 | ! Set up inputs 62 | call xfoil_init(xdg) 63 | call xfoil_defaults(xdg, opts) 64 | call xfoil_set_paneling(xdg, geom_opts) 65 | call xfoil_set_buffer_airfoil(xdg, x, z, npoint) 66 | call xfoil_smooth_paneling(xdg, stat) 67 | if (stat /= 0) then 68 | write(*,*) "Error smoothing paneling." 69 | stop 70 | end if 71 | 72 | ! Run at all operating points 73 | write(*,*) "Running Xfoil ..." 74 | do i = 1, noppoint 75 | call xfoil_set_reynolds_number(xdg, re(i)) 76 | call xfoil_set_mach_number(xdg, mach(i)) 77 | call xfoil_specal(xdg, oppoints(i), alpha(i), lift(i), drag(i), moment(i), & 78 | converged, stat) 79 | if (stat /= 0) then 80 | write(*,*) "Error running Xfoil." 81 | stop 82 | end if 83 | if (.not. converged) then 84 | write(*,"(A7,I1,A18)") " Point ", i, " did not converge." 85 | else 86 | write(*,"(A7,I1,A11)") " Point ", i, " converged." 87 | write(*,'(A7,I1,A8,F7.4,A7,F7.4,A7,F7.4,A7,F7.4)') & 88 | " Point ", i, ": AoA = ", alpha(i), ", Cl = ", lift(i), ", Cd = ", & 89 | drag(i), ", Cm = ", moment(i) 90 | end if 91 | end do 92 | call xfoil_cleanup(xdg) 93 | 94 | ! Now, do the same thing but with the run_xfoil method 95 | write(*,*) 96 | write(*,*) "Running Xfoil using the run_xfoil method ..." 97 | call run_xfoil(npoint, x, z, geom_opts, noppoint, oppoints, opmodes, re, & 98 | mach, use_flap, 0.d0, 0.d0, 0, flapang, opts, reinitialize, & 99 | fix_unconverged, lift, drag, moment, viscrms, alpha, xtrt, & 100 | xtrb, stat) 101 | if (stat /= 0) then 102 | write(*,*) "Error running Xfoil." 103 | stop 104 | end if 105 | 106 | do i = 1, noppoint 107 | write(*,'(A6,I1,A8,F7.4,A7,F7.4,A7,F7.4,A7,F7.4)') & 108 | "Point ", i, ": AoA = ", alpha(i), ", Cl = ", lift(i), ", Cd = ", & 109 | drag(i), ", Cm = ", moment(i) 110 | end do 111 | 112 | deallocate(x) 113 | deallocate(z) 114 | deallocate(s) 115 | deallocate(xs) 116 | deallocate(zs) 117 | 118 | end program main 119 | 120 | subroutine read_airfoil_points(filename, npoint) 121 | 122 | character(*), intent(in) :: filename 123 | integer, intent(out) :: npoint 124 | 125 | integer :: iunit, stat 126 | 127 | iunit = 12 128 | open(iunit, file=trim(filename), status="old", iostat=stat) 129 | if (stat /= 0) then 130 | write(*,*) "Error opening file "//trim(filename)//"." 131 | stop 132 | end if 133 | 134 | npoint = 0 135 | do while(.true.) 136 | read(iunit,*,end=500) 137 | npoint = npoint + 1 138 | end do 139 | 140 | 500 close(iunit) 141 | 142 | end subroutine read_airfoil_points 143 | 144 | subroutine read_airfoil(filename, npoint, x, z) 145 | 146 | character(*), intent(in) :: filename 147 | integer, intent(in) :: npoint 148 | double precision, dimension(npoint), intent(out) :: x, z 149 | 150 | integer :: i, iunit, stat 151 | 152 | iunit = 12 153 | open(iunit, file=trim(filename), status="old", iostat=stat) 154 | if (stat /= 0) then 155 | write(*,*) "Error opening file "//trim(filename)//"." 156 | stop 157 | end if 158 | 159 | do i = 1, npoint 160 | read(iunit,*) x(i), z(i) 161 | end do 162 | 163 | close(iunit) 164 | 165 | end subroutine read_airfoil 166 | -------------------------------------------------------------------------------- /examples/mh32_smoothed.dat: -------------------------------------------------------------------------------- 1 | MH 32 8.7% 2 | 1.000000 -0.2129452E-13 3 | 0.9921647 0.8721214E-03 4 | 0.9804825 0.2361752E-02 5 | 0.9672509 0.4222947E-02 6 | 0.9534896 0.6268677E-02 7 | 0.9395538 0.8411639E-02 8 | 0.9255355 0.1061317E-01 9 | 0.9114643 0.1284931E-01 10 | 0.8973586 0.1510264E-01 11 | 0.8832476 0.1735733E-01 12 | 0.8691546 0.1960036E-01 13 | 0.8550812 0.2182357E-01 14 | 0.8410248 0.2402051E-01 15 | 0.8269829 0.2618541E-01 16 | 0.8129546 0.2831263E-01 17 | 0.7989389 0.3039640E-01 18 | 0.7849338 0.3243125E-01 19 | 0.7709357 0.3441265E-01 20 | 0.7569403 0.3633740E-01 21 | 0.7429439 0.3820345E-01 22 | 0.7289435 0.4000964E-01 23 | 0.7149371 0.4175552E-01 24 | 0.7009230 0.4344113E-01 25 | 0.6869006 0.4506686E-01 26 | 0.6728694 0.4663329E-01 27 | 0.6588291 0.4814112E-01 28 | 0.6447795 0.4959129E-01 29 | 0.6307198 0.5098498E-01 30 | 0.6166499 0.5232366E-01 31 | 0.6025702 0.5360881E-01 32 | 0.5884822 0.5484169E-01 33 | 0.5743880 0.5602298E-01 34 | 0.5602900 0.5715274E-01 35 | 0.5461912 0.5823018E-01 36 | 0.5320947 0.5925365E-01 37 | 0.5180033 0.6022055E-01 38 | 0.5039184 0.6112769E-01 39 | 0.4898399 0.6197182E-01 40 | 0.4757665 0.6275008E-01 41 | 0.4616967 0.6346013E-01 42 | 0.4476292 0.6410019E-01 43 | 0.4335633 0.6466881E-01 44 | 0.4194986 0.6516481E-01 45 | 0.4054364 0.6558702E-01 46 | 0.3913792 0.6593375E-01 47 | 0.3773309 0.6620232E-01 48 | 0.3632953 0.6638899E-01 49 | 0.3492745 0.6648918E-01 50 | 0.3352697 0.6649808E-01 51 | 0.3212809 0.6641092E-01 52 | 0.3073075 0.6622326E-01 53 | 0.2933485 0.6593112E-01 54 | 0.2794033 0.6553123E-01 55 | 0.2654736 0.6502066E-01 56 | 0.2515652 0.6439596E-01 57 | 0.2376863 0.6365193E-01 58 | 0.2238457 0.6278113E-01 59 | 0.2100505 0.6177435E-01 60 | 0.1963066 0.6062128E-01 61 | 0.1826204 0.5931098E-01 62 | 0.1689994 0.5783176E-01 63 | 0.1554533 0.5617111E-01 64 | 0.1419951 0.5431543E-01 65 | 0.1286420 0.5224963E-01 66 | 0.1154176 0.4995672E-01 67 | 0.1023535 0.4741722E-01 68 | 0.8949161E-01 0.4460852E-01 69 | 0.7688533E-01 0.4150489E-01 70 | 0.6460784E-01 0.3808049E-01 71 | 0.5277209E-01 0.3431558E-01 72 | 0.4156216E-01 0.3021162E-01 73 | 0.3129358E-01 0.2583601E-01 74 | 0.2244952E-01 0.2139527E-01 75 | 0.1547940E-01 0.1724413E-01 76 | 0.1041752E-01 0.1367633E-01 77 | 0.6867056E-02 0.1070762E-01 78 | 0.4368837E-02 0.8205275E-02 79 | 0.2591429E-02 0.6044834E-02 80 | 0.1332719E-02 0.4133899E-02 81 | 0.4957402E-03 0.2398981E-02 82 | 0.6252949E-04 0.7938129E-03 83 | 0.4937912E-04 -0.7206555E-03 84 | 0.5320733E-03 -0.2245262E-02 85 | 0.1576319E-02 -0.3702848E-02 86 | 0.3155404E-02 -0.5063053E-02 87 | 0.5291043E-02 -0.6396062E-02 88 | 0.8134170E-02 -0.7791651E-02 89 | 0.1200666E-01 -0.9323129E-02 90 | 0.1744944E-01 -0.1105094E-01 91 | 0.2510523E-01 -0.1297976E-01 92 | 0.3514522E-01 -0.1495624E-01 93 | 0.4690625E-01 -0.1675503E-01 94 | 0.5958896E-01 -0.1827225E-01 95 | 0.7274282E-01 -0.1951081E-01 96 | 0.8617340E-01 -0.2050728E-01 97 | 0.9978826E-01 -0.2130034E-01 98 | 0.1135337 -0.2192238E-01 99 | 0.1273749 -0.2239894E-01 100 | 0.1412896 -0.2275047E-01 101 | 0.1552625 -0.2299389E-01 102 | 0.1692826 -0.2314332E-01 103 | 0.1833416 -0.2321077E-01 104 | 0.1974324 -0.2320629E-01 105 | 0.2115499 -0.2313847E-01 106 | 0.2256895 -0.2301458E-01 107 | 0.2398477 -0.2284080E-01 108 | 0.2540217 -0.2262245E-01 109 | 0.2682095 -0.2236417E-01 110 | 0.2824091 -0.2207005E-01 111 | 0.2966192 -0.2174372E-01 112 | 0.3108383 -0.2138836E-01 113 | 0.3250652 -0.2100677E-01 114 | 0.3392989 -0.2060139E-01 115 | 0.3535387 -0.2017438E-01 116 | 0.3677840 -0.1972771E-01 117 | 0.3820343 -0.1926320E-01 118 | 0.3962892 -0.1878249E-01 119 | 0.4105482 -0.1828711E-01 120 | 0.4248110 -0.1777844E-01 121 | 0.4390773 -0.1725773E-01 122 | 0.4533469 -0.1672615E-01 123 | 0.4676198 -0.1618483E-01 124 | 0.4818959 -0.1563489E-01 125 | 0.4961752 -0.1507743E-01 126 | 0.5104576 -0.1451353E-01 127 | 0.5247429 -0.1394418E-01 128 | 0.5390310 -0.1337035E-01 129 | 0.5533219 -0.1279293E-01 130 | 0.5676157 -0.1221282E-01 131 | 0.5819123 -0.1163101E-01 132 | 0.5962104 -0.1104858E-01 133 | 0.6105071 -0.1046672E-01 134 | 0.6248009 -0.9886559E-02 135 | 0.6390918 -0.9309065E-02 136 | 0.6533799 -0.8735159E-02 137 | 0.6676652 -0.8165744E-02 138 | 0.6819475 -0.7601781E-02 139 | 0.6962265 -0.7044323E-02 140 | 0.7105022 -0.6494504E-02 141 | 0.7247743 -0.5953499E-02 142 | 0.7390429 -0.5422503E-02 143 | 0.7533077 -0.4902754E-02 144 | 0.7675681 -0.4395629E-02 145 | 0.7818233 -0.3902778E-02 146 | 0.7960723 -0.3426171E-02 147 | 0.8103148 -0.2968002E-02 148 | 0.8245509 -0.2530493E-02 149 | 0.8387806 -0.2115783E-02 150 | 0.8530035 -0.1726034E-02 151 | 0.8672184 -0.1363692E-02 152 | 0.8814242 -0.1031654E-02 153 | 0.8956199 -0.7331438E-03 154 | 0.9098047 -0.4714736E-03 155 | 0.9239756 -0.2503082E-03 156 | 0.9381264 -0.7481002E-04 157 | 0.9522484 0.4839983E-04 158 | 0.9662950 0.1157019E-03 159 | 0.9799485 0.1306899E-03 160 | 0.9920323 0.8608885E-04 161 | 1.000000 0.2129452E-13 162 | -------------------------------------------------------------------------------- /examples/python_example3_parallel.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | from matplotlib import pyplot as plt 5 | from matplotlib.lines import Line2D 6 | import numpy as np 7 | import time 8 | import multiprocessing as mp 9 | 10 | import libxfoil_wrap as xiw 11 | from libxfoil import xfoil_options_type, xfoil_geom_options_type, \ 12 | xfoil_data_group 13 | 14 | # Global Xfoil settings 15 | opts = xfoil_options_type() 16 | opts.ncrit = 7.5 17 | opts.xtript = 1. 18 | opts.xtripb = 1. 19 | opts.viscous_mode = True 20 | opts.silent_mode = True 21 | opts.maxit = 300 22 | opts.vaccel = 0.01 23 | 24 | geom_opts = xfoil_geom_options_type() 25 | geom_opts.npan = 200 26 | geom_opts.cvpar = 1. 27 | geom_opts.cterat = 0.15 28 | geom_opts.ctrrat = 0.2 29 | geom_opts.xsref1 = 1. 30 | geom_opts.xsref2 = 1. 31 | geom_opts.xpref1 = 1. 32 | geom_opts.xpref2 = 1. 33 | 34 | def analyze_all_re(camber, xcamber, thick, re, mach): 35 | 36 | xdg = xfoil_data_group() 37 | 38 | # Set up airfoil 39 | npointside = 100 40 | x, z, npoint = xiw.naca_4_digit(camber, xcamber, thick, npointside) 41 | xiw.xfoil_init(xdg) 42 | xiw.xfoil_defaults(xdg, opts) 43 | xiw.xfoil_set_paneling(xdg, geom_opts) 44 | xiw.xfoil_set_buffer_airfoil(xdg, x, z, npoint) 45 | if xiw.xfoil_smooth_paneling(xdg) != 0: 46 | print("Error smoothing paneling: xfoil_set_buffer_airfoil must be " + 47 | "called first.") 48 | sys.exit(1) 49 | 50 | xiw.xfoil_set_mach_number(xdg, mach) 51 | noper = 61 52 | alpha = np.linspace(-10., 10., noper) 53 | results = [] 54 | for reynolds_number in re: 55 | xiw.xfoil_set_reynolds_number(xdg, reynolds_number) 56 | xiw.xfoil_reinitialize_bl(xdg) 57 | res = {'re': reynolds_number, 'mach': mach, 58 | 'alpha': np.linspace(-10., 10., noper), 'cl': np.zeros((noper)), 59 | 'cd': np.zeros((noper)), 'cm': np.zeros((noper))} 60 | for i in range(noper): 61 | alpha_out, res['cl'][i], res['cd'][i], res['cm'][i], converged, \ 62 | stat = xiw.xfoil_specal(xdg, res['alpha'][i]) 63 | if stat == 0: 64 | if not converged: 65 | print("Warning: convergence failed for alpha {:.1f}." \ 66 | .format(res['alpha'][i])) 67 | else: 68 | print("Error: xfoil_smooth_paneling must be called first.") 69 | sys.exit(1) 70 | results.append(res) 71 | 72 | return results 73 | 74 | def analyze_one_re(camber, xcamber, thick, re, mach): 75 | 76 | xdg = xfoil_data_group() 77 | 78 | # Set up airfoil 79 | npointside = 100 80 | x, z, npoint = xiw.naca_4_digit(camber, xcamber, thick, npointside) 81 | xiw.xfoil_init(xdg) 82 | xiw.xfoil_defaults(xdg, opts) 83 | xiw.xfoil_set_paneling(xdg, geom_opts) 84 | xiw.xfoil_set_buffer_airfoil(xdg, x, z, npoint) 85 | if xiw.xfoil_smooth_paneling(xdg) != 0: 86 | print("Error smoothing paneling: xfoil_set_buffer_airfoil must be " + 87 | "called first.") 88 | sys.exit(1) 89 | 90 | # Set operating point 91 | xiw.xfoil_set_reynolds_number(xdg, re) 92 | xiw.xfoil_set_mach_number(xdg, mach) 93 | noper = 61 94 | alpha = np.linspace(-10., 10., noper) 95 | res = {'re': re, 'mach': mach, 'alpha': np.linspace(-10., 10., noper), 96 | 'cl': np.zeros((noper)), 'cd': np.zeros((noper)), 97 | 'cm': np.zeros((noper))} 98 | for i in range(noper): 99 | alpha_out, res['cl'][i], res['cd'][i], res['cm'][i], converged, stat = \ 100 | xiw.xfoil_specal(xdg, res['alpha'][i]) 101 | if stat == 0: 102 | if not converged: 103 | print("Warning: convergence failed for alpha {:.1f}." \ 104 | .format(res['alpha'][i])) 105 | else: 106 | print("Error: xfoil_smooth_paneling must be called first.") 107 | sys.exit(1) 108 | 109 | return res 110 | 111 | def plot(results): 112 | fig, axarr = plt.subplots(2,2) 113 | 114 | axarr[0,0].set_xlabel("Angle of attack") 115 | axarr[0,0].set_ylabel("Lift coefficient") 116 | lines = [] 117 | labels = [] 118 | for result in results: 119 | line, = axarr[0,0].plot(result['alpha'], result['cl']) 120 | lines.append(line) 121 | labels.append("Re = {:.1e}".format(result['re'])) 122 | 123 | axarr[0,1].set_xlabel("Drag coefficient") 124 | axarr[0,1].set_ylabel("Lift coefficient") 125 | for result in results: 126 | axarr[0,1].plot(result['cd'], result['cl']) 127 | 128 | axarr[1,0].set_xlabel("Angle of attack") 129 | axarr[1,0].set_ylabel("Pitching moment coefficient") 130 | for result in results: 131 | axarr[1,0].plot(result['alpha'], result['cm']) 132 | 133 | # Use the last frame for a legend 134 | axarr[1,1].legend(handles=lines, labels=labels, loc='center', ncol=3) 135 | 136 | plt.show() 137 | 138 | # Analyze an airfoil over a range of Reynolds numbers and angles of attack 139 | if __name__ == "__main__": 140 | 141 | nre = 33 142 | re = np.linspace(2e+5, 6e+5, nre) 143 | mach = 0.05 144 | camber = 0.0 145 | xcamber = 0.0 146 | thick = 10. 147 | 148 | # Execute in serial 149 | start = time.time() 150 | results = analyze_all_re(camber, xcamber, thick, re, mach) 151 | end = time.time() 152 | print("Serial execution time: {:.4f} sec".format(end-start)) 153 | 154 | # Execute in parallel 155 | # Note: currently, xdg cannot be passed as an argument to a worker process, 156 | # which means each process must set up a new xdg when run in parallel. 157 | # This incurs some overhead compared to the serial case, but testing 158 | # indicates this overhead is not very significant, and the parallel 159 | # version still performs considerably better than the serial version for 160 | # this test (greater than 2x speed-up on a quad-core Intel i5 laptop). 161 | pool = mp.Pool(mp.cpu_count()) 162 | resultslist = [] 163 | start = time.time() 164 | for i in range(nre): 165 | resultslist.append(pool.apply_async(analyze_one_re, 166 | args=(camber, xcamber, thick, re[i], mach))) 167 | results = [] 168 | for result in resultslist: 169 | results.append(result.get()) 170 | end = time.time() 171 | print("Parallel execution time: {:.4f} sec".format(end-start)) 172 | 173 | plot(results) 174 | -------------------------------------------------------------------------------- /examples/python_example1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | import libxfoil_wrap as xiw 5 | from libxfoil import xfoil_options_type, xfoil_geom_options_type, \ 6 | xfoil_data_group 7 | from matplotlib import pyplot as plt 8 | 9 | def plot_spline(x, z, xspline, zspline, name): 10 | 11 | fig, ax = plt.subplots() 12 | ax.set_xlabel('x') 13 | ax.set_ylabel('z') 14 | ax.set_title(name) 15 | ax.plot(x, z) 16 | ax.plot(xspline, zspline, 'o') 17 | ax.grid() 18 | ax.set_aspect('equal', 'datalim') 19 | ax.legend(['Airfoil', 'Some spline interp points']) 20 | 21 | plt.show() 22 | 23 | def plot_oldnew(x, z, xnew, znew): 24 | 25 | fig, ax = plt.subplots() 26 | ax.set_xlabel('x') 27 | ax.set_ylabel('z') 28 | ax.plot(x, z) 29 | ax.plot(xnew, znew) 30 | ax.grid() 31 | ax.set_aspect('equal', 'datalim') 32 | ax.legend(['Original', 'Modified']) 33 | 34 | plt.show() 35 | 36 | def plot_surface_var(x_noflap, var_noflap, x_withflap, var_withflap, varname, 37 | reverse_y=False): 38 | 39 | fig, ax = plt.subplots() 40 | ax.set_xlabel('x/c') 41 | ax.set_ylabel(varname) 42 | ax.plot(x_noflap, var_noflap) 43 | ax.plot(x_withflap, var_withflap) 44 | if reverse_y: 45 | ylim = ax.get_ylim() 46 | ax.set_ylim(ylim[1], ylim[0]) 47 | ax.grid() 48 | ax.legend(['No flap', 'With flap']) 49 | 50 | plt.show() 51 | 52 | if __name__ == "__main__": 53 | 54 | # Generate an airfoil 55 | digits = '2312' 56 | npointside = 100 57 | camber = 2.0 58 | xcamber = 0.30 59 | thick = 12. 60 | x, z, npoint = xiw.naca_4_digit(camber, xcamber, thick, npointside) 61 | 62 | # Test spline fitting and eval 63 | s, xs, zs = xiw.xfoil_spline_coordinates(x, z, npoint) 64 | smax = s[len(s)-1] 65 | x0, z0 = xiw.xfoil_eval_spline(x, z, s, xs, zs, npoint, 0.0) 66 | x14, z14 = xiw.xfoil_eval_spline(x, z, s, xs, zs, npoint, 0.25*smax) 67 | sle, xle, zle = xiw.xfoil_lefind(x, z, s, xs, zs, npoint) 68 | x34, z34 = xiw.xfoil_eval_spline(x, z, s, xs, zs, npoint, 0.75*smax) 69 | x1, z1 = xiw.xfoil_eval_spline(x, z, s, xs, zs, npoint, smax) 70 | 71 | plot_spline(x, z, [x0, x14, xle, x34, x1], [z0, z14, zle, z34, z1], 72 | 'NACA ' + digits) 73 | 74 | # Xfoil settings 75 | opts = xfoil_options_type() 76 | opts.ncrit = 9. 77 | opts.xtript = 1. 78 | opts.xtripb = 1. 79 | opts.viscous_mode = True 80 | opts.silent_mode = True 81 | opts.maxit = 200 82 | opts.vaccel = 0.01 83 | 84 | geom_opts = xfoil_geom_options_type() 85 | geom_opts.npan = 160 86 | geom_opts.cvpar = 1. 87 | geom_opts.cterat = 0.15 88 | geom_opts.ctrrat = 0.2 89 | geom_opts.xsref1 = 1. 90 | geom_opts.xsref2 = 1. 91 | geom_opts.xpref1 = 1. 92 | geom_opts.xpref2 = 1. 93 | 94 | # Xfoil data 95 | xdg = xfoil_data_group() 96 | 97 | # Modify the trailing edge gap 98 | xiw.xfoil_init(xdg) 99 | xiw.xfoil_defaults(xdg, opts) 100 | xiw.xfoil_set_buffer_airfoil(xdg, x, z, npoint) 101 | xiw.xfoil_set_paneling(xdg, geom_opts) 102 | if (xiw.xfoil_smooth_paneling(xdg) != 0): 103 | print("Error smoothing paneling: xfoil_set_buffer_airfoil must be called " + 104 | "first.") 105 | sys.exit(1) 106 | npointnew, stat = xiw.xfoil_modify_tegap(xdg, 0., 0.9) 107 | if (stat != 0): 108 | print("Error modifying TE gap: xfoil_set_buffer_airfoil must be called " + 109 | "first.") 110 | sys.exit(1) 111 | x_noflap, z_noflap, stat = xiw.xfoil_get_current_airfoil(xdg, npointnew) 112 | if (stat != 0): 113 | print("Error getting airfoil: xfoil_smooth_paneling must be called first.") 114 | sys.exit(1) 115 | plot_oldnew(x, z, x_noflap, z_noflap) 116 | 117 | # Set operating point 118 | re = 1.E+05 119 | mach = 0.1 120 | xiw.xfoil_set_reynolds_number(xdg, re) 121 | xiw.xfoil_set_mach_number(xdg, mach) 122 | 123 | # Run xfoil for current airfoil 124 | print("Running Xfoil without flap...") 125 | cl_spec = 1.0 126 | alpha, cl, cd, cm, converged, stat = xiw.xfoil_speccl(xdg, cl_spec) 127 | if (stat == 0): 128 | if not converged: 129 | print("Warning: Xfoil calculations did not converge.") 130 | print("Alpha: {:.4f}, Cl: {:.4f}, Cd: {:.4f}, Cm: {:.4f}"\ 131 | .format(alpha, cl, cd, cm)) 132 | elif stat == 1: 133 | print("Error running xfoil: xfoil_smooth_paneling must be called first.") 134 | sys.exit(1) 135 | 136 | # Get surface cp, cf, transition location, ampl. ratio 137 | cp_noflap = xiw.xfoil_get_cp(xdg, npointnew) 138 | cf_noflap = xiw.xfoil_get_cf(xdg, npointnew) 139 | xtranst_noflap, _, xtransb_noflap, _ = xiw.xfoil_get_transloc(xdg) 140 | ampl_noflap = xiw.xfoil_get_ampl(xdg, npointnew) 141 | 142 | # Apply a flap deflection 143 | x_flap = 0.7 144 | y_flap = 0.0 145 | y_flap_spec = 0 146 | if (xiw.xfoil_smooth_paneling(xdg) != 0): 147 | print("Error smoothing paneling: xfoil_set_buffer_airfoil must be called " + 148 | "first.") 149 | sys.exit(1) 150 | npointnew, stat = xiw.xfoil_apply_flap_deflection(xdg, x_flap, y_flap, 151 | y_flap_spec, 10.) 152 | if (stat != 0): 153 | print("Error applying flap deflection: " + 154 | "xfoil_set_buffer_airfoil must be called first.") 155 | sys.exit(1) 156 | x_withflap, z_withflap, stat = xiw.xfoil_get_current_airfoil(xdg, npointnew) 157 | if (stat != 0): 158 | print("Error getting airfoil: xfoil_smooth_paneling must be called first.") 159 | sys.exit(1) 160 | plot_oldnew(x, z, x_withflap, z_withflap) 161 | 162 | # Run xfoil again with flap 163 | print("Running Xfoil with flap...") 164 | xiw.xfoil_reinitialize_bl(xdg) 165 | alpha, cl, cd, cm, converged, stat = xiw.xfoil_speccl(xdg, cl_spec) 166 | if (stat == 0): 167 | if not converged: 168 | print("Warning: Xfoil calculations did not converge.") 169 | print("Alpha: {:.4f}, Cl: {:.4f}, Cd: {:.4f}, Cm: {:.4f}"\ 170 | .format(alpha, cl, cd, cm)) 171 | elif stat == 1: 172 | print("Error running xfoil: xfoil_smooth_paneling must be called first.") 173 | sys.exit(1) 174 | 175 | # Get surface cp, cf, transition location, ampl. ratio 176 | cp_withflap = xiw.xfoil_get_cp(xdg, npointnew) 177 | cf_withflap = xiw.xfoil_get_cf(xdg, npointnew) 178 | xtranst_withflap, _, xtransb_withflap, _ = xiw.xfoil_get_transloc(xdg) 179 | ampl_withflap = xiw.xfoil_get_ampl(xdg, npointnew) 180 | xiw.xfoil_cleanup(xdg) 181 | 182 | print("Transition locations:") 183 | print("No flap: xtranstop = {:.4f}, xtransbot = {:.4f}"\ 184 | .format(xtranst_noflap, xtransb_noflap)) 185 | print("With flap: xtranstop = {:.4f}, xtransbot = {:.4f}"\ 186 | .format(xtranst_withflap, xtransb_withflap)) 187 | 188 | # Plot cp, cf, and amplification ratio 189 | plot_surface_var(x_noflap, cp_noflap, x_withflap, cp_withflap, 190 | "Pressure coefficient", reverse_y=True) 191 | plot_surface_var(x_noflap, cf_noflap, x_withflap, cf_withflap, 192 | "Skin friction coefficient") 193 | plot_surface_var(x_noflap, ampl_noflap, x_withflap, ampl_withflap, 194 | "Amplitude ratio") 195 | -------------------------------------------------------------------------------- /src/xfoil_data_mod.f90: -------------------------------------------------------------------------------- 1 | ! This file is part of libxfoil. 2 | 3 | ! libxfoil is free software: you can redistribute it and/or modify 4 | ! it under the terms of the GNU General Public License as published by 5 | ! the Free Software Foundation, either version 3 of the License, or 6 | ! (at your option) any later version. 7 | 8 | ! libxfoil is distributed in the hope that it will be useful, 9 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | ! GNU General Public License for more details. 12 | 13 | ! You should have received a copy of the GNU General Public License 14 | ! along with libxfoil. If not, see . 15 | 16 | ! Copyright (C) 2018 Daniel Prosser 17 | 18 | module xfoil_data_mod 19 | 20 | ! Derived type including all of the originally-global Xfoil variables 21 | ! This is huge because Xfoil uses a lot of global variables! 22 | 23 | use iso_c_binding 24 | 25 | implicit none 26 | 27 | !------ Primary dimensioning limit parameters 28 | ! IQX number of surface panel nodes + 6 29 | ! IWX number of wake panel nodes 30 | ! IPX number of Qspec(s) distributions 31 | ! ISX number of airfoil sides 32 | ! 33 | !------ Derived dimensioning limit parameters 34 | ! IBX number of buffer airfoil nodes 35 | ! IMX number of complex mapping coefficients Cn 36 | ! IZX number of panel nodes (airfoil + wake) 37 | ! IVX number of nodes along BL on one side of airfoil and wake 38 | ! NAX number of points in stored polar 39 | ! NPX number of polars and reference polars 40 | ! NFX number of points in one reference polar 41 | ! NTX number of points in thickness/camber arrays 42 | 43 | INTEGER(c_int), PARAMETER :: IQX=360 44 | INTEGER(c_int), PARAMETER :: ISX=2 45 | INTEGER(c_int), PARAMETER :: IBX=4*IQX 46 | INTEGER(c_int), PARAMETER :: IWX=IQX/8+2 47 | INTEGER(c_int), PARAMETER :: IZX=IQX+IWX 48 | INTEGER(c_int), PARAMETER :: IVX=IQX/2 + IWX + 50 49 | INTEGER(c_int), PARAMETER :: NCOM = 73 50 | 51 | ! The following are originally from XFOIL.INC or added for libxfoil 52 | 53 | type, bind(c) :: xfoil_data_type 54 | 55 | REAL(c_double) :: PI, HOPI, QOPI, DTOR 56 | LOGICAL(c_bool) :: SILENT_MODE, VISCOUS_MODE 57 | INTEGER(c_int) :: MAXIT 58 | TYPE(c_ptr) :: GAM, GAMU, QINVU, GAM_A 59 | TYPE(c_ptr) :: QINV, QINV_A 60 | LOGICAL(c_bool) :: LGAMU, LQAIJ, SHARP, LVISC, LWAKE, LVCONV, LWDIJ, LIPAN 61 | LOGICAL(c_bool) :: LBLINI, LADIJ, LALFA 62 | INTEGER(c_int) :: RETYP, MATYP, ITMAX 63 | TYPE(c_ptr) :: AIJ, BIJ, DIJ, CIJ 64 | TYPE(c_ptr) :: DZDG, DZDN, DQDG, DZDM, DQDM 65 | TYPE(c_ptr) :: X, Y, NX, NY, S, APANEL 66 | TYPE(c_ptr) :: SIG, XP, YP 67 | INTEGER(c_int) :: N, NB, NPAN, NW, IST, NSYS 68 | REAL(c_double) :: PSIO, QINF, ALFA, Z_QINF, Z_ALFA, Z_QDOF0, Z_QDOF1 69 | REAL(c_double) :: Z_QDOF2, Z_QDOF3, ANTE, ASTE, DSTE, ADEG, AMAX 70 | TYPE(c_ptr) :: QF0, QF1, QF2, QF3 71 | TYPE(c_ptr) :: AIJPIV, IBLTE, NBL 72 | TYPE(c_ptr) :: IPAN, ISYS 73 | REAL(c_double) :: SIGTE, GAMTE, SIGTE_A, GAMTE_A, MINF, MINF1, REINF, REINF1 74 | REAL(c_double) :: TKLAM, TKL_MSQ, CPSTAR, QSTAR, GAMMA, GAMM1 75 | REAL(c_double) :: XCMREF, YCMREF, CL, CM, CD, CDP, CDF, CL_ALF, CL_MSQ, SBLE 76 | TYPE(c_ptr) :: XB, YB, SB, XBP, YBP, SNEW 77 | TYPE(c_ptr) :: W1, W2, W3 78 | TYPE(c_ptr) :: W4, W5, W6 79 | REAL(c_double) :: XLE, YLE, XTE, YTE, CHORD, SLE 80 | REAL(c_double) :: CVPAR, CTERAT, CTRRAT, XSREF1, XSREF2, XPREF1, XPREF2 81 | REAL(c_double) :: MINF_CL, COSA, SINA, ACRIT, RLX, VACCEL 82 | TYPE(c_ptr) :: CPI, CPV, QVIS 83 | TYPE(c_ptr) :: VTI, XSSI 84 | REAL(c_double) :: AWAKE, AVISC, MVISC, CLSPEC, QTAN1, QTAN2, SST, SST_GO 85 | REAL(c_double) :: SST_GP 86 | TYPE(c_ptr) :: WGAP, XSTRIP, XSSITR 87 | TYPE(c_ptr) :: UINV, UINV_A, UEDG 88 | TYPE(c_ptr) :: THET, DSTR, CTAU 89 | TYPE(c_ptr) :: MASS, TAU, DIS, CTQ 90 | TYPE(c_ptr) :: DELT, TSTR, USLP 91 | INTEGER(c_int) :: IDAMP 92 | TYPE(c_ptr) :: ITRAN 93 | INTEGER(c_int) :: IMXBL, ISMXBL 94 | TYPE(c_ptr) :: TFORCE 95 | TYPE(c_ptr) :: VM, VA, VB, VDEL 96 | TYPE(c_ptr) :: VZ, XOCTR, YOCTR 97 | REAL(c_double) :: RMSBL, RMXBL, WAKLEN 98 | TYPE(c_ptr) :: UNEW, U_AC 99 | TYPE(c_ptr) :: QNEW, Q_AC 100 | CHARACTER(c_char), dimension(1) :: VMXBL 101 | REAL(c_double) :: THICKB, XTHICKB, THICKM, XTHICKM, CAMBR, XCAMBR 102 | LOGICAL(c_bool) :: XFOIL_FAIL 103 | 104 | end type xfoil_data_type 105 | 106 | ! The following are originally from BLPAR.INC 107 | ! 108 | !- SCCON = shear coefficient lag constant 109 | !- GACON = G-beta locus constants... 110 | !- GBCON = G = GACON * sqrt(1.0 + GBCON*beta) 111 | !- GCCON = + GCCON / [H*Rtheta*sqrt(Cf/2)] <-- wall term 112 | !- DLCON = wall/wake dissipation length ratio Lo/L 113 | !- CTCON = Ctau weighting coefficient (implied by G-beta constants) 114 | ! 115 | type, bind(c) :: blpar_data_type 116 | 117 | REAL(c_double) :: SCCON, GACON, GBCON, GCCON, DLCON, CTRCON, CTRCEX, DUXCON 118 | REAL(c_double) :: CTCON, CFFAC 119 | 120 | end type blpar_data_type 121 | 122 | ! The following are originally from XBL.INC 123 | 124 | type, bind(c) :: xbl_data_type 125 | 126 | INTEGER(c_int) :: IDAMPV 127 | LOGICAL(c_bool) :: SIMI, TRAN, TURB, WAKE 128 | LOGICAL(c_bool) :: TRFORC, TRFREE 129 | REAL(c_double) :: X1, U1, T1, D1, S1, AMPL1, U1_UEI, U1_MS, DW1 130 | REAL(c_double) :: H1, H1_T1, H1_D1 131 | REAL(c_double) :: M1, M1_U1, M1_MS 132 | REAL(c_double) :: R1, R1_U1, R1_MS 133 | REAL(c_double) :: V1, V1_U1, V1_MS, V1_RE 134 | REAL(c_double) :: HK1, HK1_U1, HK1_T1, HK1_D1, HK1_MS 135 | REAL(c_double) :: HS1, HS1_U1, HS1_T1, HS1_D1, HS1_MS, HS1_RE 136 | REAL(c_double) :: HC1, HC1_U1, HC1_T1, HC1_D1, HC1_MS 137 | REAL(c_double) :: RT1, RT1_U1, RT1_T1, RT1_MS, RT1_RE 138 | REAL(c_double) :: CF1, CF1_U1, CF1_T1, CF1_D1, CF1_MS, CF1_RE 139 | REAL(c_double) :: DI1, DI1_U1, DI1_T1, DI1_D1, DI1_S1, DI1_MS, DI1_RE 140 | REAL(c_double) :: US1, US1_U1, US1_T1, US1_D1, US1_MS, US1_RE 141 | REAL(c_double) :: CQ1, CQ1_U1, CQ1_T1, CQ1_D1, CQ1_MS, CQ1_RE 142 | REAL(c_double) :: DE1, DE1_U1, DE1_T1, DE1_D1, DE1_MS 143 | REAL(c_double) :: X2, U2, T2, D2, S2, AMPL2, U2_UEI, U2_MS, DW2 144 | REAL(c_double) :: H2, H2_T2, H2_D2 145 | REAL(c_double) :: M2, M2_U2, M2_MS 146 | REAL(c_double) :: R2, R2_U2, R2_MS 147 | REAL(c_double) :: V2, V2_U2, V2_MS, V2_RE 148 | REAL(c_double) :: HK2, HK2_U2, HK2_T2, HK2_D2, HK2_MS 149 | REAL(c_double) :: HS2, HS2_U2, HS2_T2, HS2_D2, HS2_MS, HS2_RE 150 | REAL(c_double) :: HC2, HC2_U2, HC2_T2, HC2_D2, HC2_MS 151 | REAL(c_double) :: RT2, RT2_U2, RT2_T2, RT2_MS, RT2_RE 152 | REAL(c_double) :: CF2, CF2_U2, CF2_T2, CF2_D2, CF2_MS, CF2_RE 153 | REAL(c_double) :: DI2, DI2_U2, DI2_T2, DI2_D2, DI2_S2, DI2_MS, DI2_RE 154 | REAL(c_double) :: US2, US2_U2, US2_T2, US2_D2, US2_MS, US2_RE 155 | REAL(c_double) :: CQ2, CQ2_U2, CQ2_T2, CQ2_D2, CQ2_MS, CQ2_RE 156 | REAL(c_double) :: DE2, DE2_U2, DE2_T2, DE2_D2, DE2_MS 157 | REAL(c_double) :: CFM, CFM_MS, CFM_RE 158 | REAL(c_double) :: CFM_U1, CFM_T1, CFM_D1, CFM_U2, CFM_T2, CFM_D2 159 | REAL(c_double) :: XT, XT_A1, XT_MS, XT_RE, XT_XF 160 | REAL(c_double) :: XT_X1, XT_T1, XT_D1, XT_U1, XT_X2, XT_T2, XT_D2, XT_U2 161 | TYPE(c_ptr) :: C1SAV, C2SAV 162 | REAL(c_double) :: DWTE, QINFBL, TKBL, TKBL_MS, RSTBL, RSTBL_MS, HSTINV 163 | REAL(c_double) :: HSTINV_MS, REYBL, REYBL_MS, REYBL_RE, GAMBL, GM1BL 164 | REAL(c_double) :: HVRA, BULE, XIFORC, AMCRIT 165 | TYPE(c_ptr) :: VS1, VS2 166 | TYPE(c_ptr) :: VSREZ, VSR, VSM, VSX 167 | 168 | end type xbl_data_type 169 | 170 | ! "Master" xfoil data grouping. Users only need to maintain an instance of this 171 | ! data type, not any of the subtypes individually. 172 | 173 | type, bind(c) :: xfoil_data_group 174 | 175 | type(xfoil_data_type) :: xfd 176 | type(blpar_data_type) :: bld 177 | type(xbl_data_type) :: xbd 178 | 179 | end type xfoil_data_group 180 | 181 | end module xfoil_data_mod 182 | -------------------------------------------------------------------------------- /src/my_equivalence.f90: -------------------------------------------------------------------------------- 1 | ! This file is part of libxfoil. 2 | 3 | ! libxfoil is free software: you can redistribute it and/or modify 4 | ! it under the terms of the GNU General Public License as published by 5 | ! the Free Software Foundation, either version 3 of the License, or 6 | ! (at your option) any later version. 7 | 8 | ! libxfoil is distributed in the hope that it will be useful, 9 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | ! GNU General Public License for more details. 12 | 13 | ! You should have received a copy of the GNU General Public License 14 | ! along with libxfoil. If not, see . 15 | 16 | ! Copyright (C) 2018 Daniel Prosser 17 | 18 | module my_equivalence 19 | 20 | ! Provides routines to copy array values so that equivalence statements can 21 | ! be removed. This is needed for parallelization. 22 | 23 | implicit none 24 | 25 | integer, parameter :: toA = 1 26 | integer, parameter :: toB = 2 27 | 28 | contains 29 | 30 | !=============================================================================80 31 | ! 32 | ! Manual equivalence between A (3-D) and B (2-D) 33 | ! Copies B(bcopyidx(1),bcopyidx(2)) to the appropriate location in A, if 34 | ! direction == toA (1). Alternatively, copies from the appropriate location 35 | ! in A to B(bcopyidx(1),bcopyidx(2)), if direction == toB (2). 36 | ! 37 | ! Used to replace an equivalence statement like the following: 38 | ! EQUIVALENCE(A(aequividx(1),aequividx(2),aequividx(3)), 39 | ! B(bequividx(1),bequividx(2))) 40 | ! 41 | !=============================================================================80 42 | subroutine my_equiv_3_2(A, B, aequividx, bequividx, bcopyidx, direction) 43 | 44 | double precision, dimension(:,:,:), intent(inout) :: A 45 | double precision, dimension(:,:), intent(inout) :: B 46 | integer, dimension(3), intent(in) :: aequividx 47 | integer, dimension(2), intent(in) :: bequividx, bcopyidx 48 | integer, intent(in) :: direction 49 | 50 | integer na1, na2, na3, nb1, nb2 51 | integer an, bn 52 | integer aequiv, bequiv 53 | integer, dimension(3) :: aidx 54 | 55 | na1 = size(A,1) 56 | na2 = size(A,2) 57 | na3 = size(A,3) 58 | nb1 = size(B,1) 59 | nb2 = size(B,2) 60 | 61 | ! Find virtual 1-D equivalence points 62 | 63 | aequiv = equiv_pt_3d(na1, na2, aequividx) 64 | bequiv = equiv_pt_2d(nb1, bequividx) 65 | 66 | ! 1-D transformation of point to copy from B 67 | 68 | bn = equiv_pt_2d(nb1, bcopyidx) 69 | 70 | ! 1-D point in A to copy to 71 | 72 | an = bn - bequiv + aequiv 73 | 74 | ! Translation to 3-D index in A 75 | 76 | aidx = inv_equiv_pt_3d(an, na1, na2) 77 | 78 | ! Copy data 79 | 80 | if (direction == toA) then 81 | A(aidx(1),aidx(2),aidx(3)) = B(bcopyidx(1),bcopyidx(2)) 82 | else 83 | B(bcopyidx(1),bcopyidx(2)) = A(aidx(1),aidx(2),aidx(3)) 84 | end if 85 | 86 | end subroutine my_equiv_3_2 87 | 88 | !=============================================================================80 89 | ! 90 | ! Manual equivalence of B (2-D) and A (3-D) 91 | ! Copies A(acopyidx(1),acopyidx(2),acopyidx(3)) to the appropriate location in 92 | ! B, if direction == toB (2). Alternatively, copies to 93 | ! A(acopyidx(1),acopyidx(2),acopyidx(3)) from the appropriate location in B, 94 | ! if direction == toA (1). 95 | ! 96 | ! Used to replace an equivalence statement like the following: 97 | ! EQUIVALENCE(A(aequividx(1),aequividx(2),aequividx(3)), 98 | ! B(bequividx(1),bequividx(2))) 99 | ! 100 | !=============================================================================80 101 | subroutine my_equiv_2_3(A, B, aequividx, bequividx, acopyidx, direction) 102 | 103 | double precision, dimension(:,:,:), intent(inout) :: A 104 | double precision, dimension(:,:), intent(inout) :: B 105 | integer, dimension(3), intent(in) :: aequividx, acopyidx 106 | integer, dimension(2), intent(in) :: bequividx 107 | integer, intent(in) :: direction 108 | 109 | integer na1, na2, na3, nb1, nb2 110 | integer an, bn 111 | integer aequiv, bequiv 112 | integer, dimension(2) :: bidx 113 | 114 | na1 = size(A,1) 115 | na2 = size(A,2) 116 | na3 = size(A,3) 117 | nb1 = size(B,1) 118 | nb2 = size(B,2) 119 | 120 | ! Find virtual 1-D equivalence points 121 | 122 | aequiv = equiv_pt_3d(na1, na2, aequividx) 123 | bequiv = equiv_pt_2d(nb1, bequividx) 124 | 125 | ! 1-D transformation of point to copy from a 126 | 127 | an = equiv_pt_3d(na1, na2, acopyidx) 128 | 129 | ! 1-D point in B to copy to 130 | 131 | bn = an - aequiv + bequiv 132 | 133 | ! Translation to 2-D index in B 134 | 135 | bidx = inv_equiv_pt_2d(bn, nb1) 136 | 137 | ! Copy data 138 | 139 | if (direction == toB) then 140 | B(bidx(1),bidx(2)) = A(acopyidx(1),acopyidx(2),acopyidx(3)) 141 | else 142 | A(acopyidx(1),acopyidx(2),acopyidx(3)) = B(bidx(1),bidx(2)) 143 | end if 144 | 145 | end subroutine my_equiv_2_3 146 | 147 | !=============================================================================80 148 | ! 149 | ! Manual equivalence between A (3-D) and B (1-D) 150 | ! Copies B(bcopyidx) to the appropriate location in A, if 151 | ! direction == toA (1). Alternatively, copies from the appropriate location 152 | ! in A to B(bcopyidx), if direction == toB (2). 153 | ! 154 | ! Used to replace an equivalence statement like the following: 155 | ! EQUIVALENCE(A(aequividx(1),aequividx(2),aequividx(3)), 156 | ! B(bequividx) 157 | ! 158 | !=============================================================================80 159 | subroutine my_equiv_3_1(A, B, aequividx, bequividx, bcopyidx, direction) 160 | 161 | double precision, dimension(:,:,:), intent(inout) :: A 162 | double precision, dimension(:), intent(inout) :: B 163 | integer, dimension(3), intent(in) :: aequividx 164 | integer, intent(in) :: bequividx, bcopyidx, direction 165 | 166 | integer na1, na2, na3, nb1 167 | integer an, bn 168 | integer aequiv, bequiv 169 | integer, dimension(3) :: aidx 170 | 171 | na1 = size(A,1) 172 | na2 = size(A,2) 173 | na3 = size(A,3) 174 | nb1 = size(B,1) 175 | 176 | ! Find virtual 1-D equivalence points 177 | 178 | aequiv = equiv_pt_3d(na1, na2, aequividx) 179 | bequiv = bequividx 180 | 181 | ! 1-D transformation of point to copy from B 182 | 183 | bn = bcopyidx 184 | 185 | ! 1-D point in A to copy to 186 | 187 | an = bn - bequiv + aequiv 188 | 189 | ! Translation to 3-D index in A 190 | 191 | aidx = inv_equiv_pt_3d(an, na1, na2) 192 | 193 | ! Copy data 194 | 195 | if (direction == toA) then 196 | A(aidx(1),aidx(2),aidx(3)) = B(bcopyidx) 197 | else 198 | B(bcopyidx) = A(aidx(1),aidx(2),aidx(3)) 199 | end if 200 | 201 | end subroutine my_equiv_3_1 202 | 203 | !=============================================================================80 204 | ! 205 | ! Determines 1-D point in memory for a 3D array with dimensions n1, n2, n3 206 | ! for the index (aidx(1), aidx(2), aidx(3)) 207 | ! 208 | !=============================================================================80 209 | function equiv_pt_3d(n1, n2, aidx) result(equiv_pt) 210 | 211 | integer, intent(in) :: n1, n2 212 | integer, dimension(3), intent(in) :: aidx 213 | integer :: equiv_pt 214 | 215 | equiv_pt = (aidx(3)-1)*n1*n2 + (aidx(2)-1)*n1 + aidx(1) 216 | 217 | end function equiv_pt_3d 218 | 219 | !=============================================================================80 220 | ! 221 | ! Determines 3-D indices corresponding to 1-D point in memory (for 3-D array) 222 | ! 223 | !=============================================================================80 224 | function inv_equiv_pt_3d(pt, n1, n2) result(inv_equiv_pt) 225 | 226 | integer, intent(in) :: pt, n1, n2 227 | integer, dimension(3) :: inv_equiv_pt 228 | 229 | inv_equiv_pt(3) = ceiling(dble(pt)/dble(n1*n2)) 230 | inv_equiv_pt(2) = ceiling(dble(pt - (inv_equiv_pt(3)-1)*n1*n2)/dble(n1)) 231 | inv_equiv_pt(1) = pt - (inv_equiv_pt(2)-1)*n1 - (inv_equiv_pt(3)-1)*n1*n2 232 | 233 | end function inv_equiv_pt_3d 234 | 235 | !=============================================================================80 236 | ! 237 | ! Determines 1-D point in memory for a 2D array with dimensions n1, n2 for the 238 | ! index (aidx(1), aidx(2)) 239 | ! 240 | !=============================================================================80 241 | function equiv_pt_2d(n1, aidx) result(equiv_pt) 242 | 243 | integer, intent(in) :: n1 244 | integer, dimension(2), intent(in) :: aidx 245 | integer :: equiv_pt 246 | 247 | equiv_pt = (aidx(2)-1)*n1 + aidx(1) 248 | 249 | end function equiv_pt_2d 250 | 251 | !=============================================================================80 252 | ! 253 | ! Determines 2-D indices corresponding to 1-D point in memory (for 2-D array) 254 | ! 255 | !=============================================================================80 256 | function inv_equiv_pt_2d(pt, n1) result(inv_equiv_pt) 257 | 258 | integer, intent(in) :: pt, n1 259 | integer, dimension(2) :: inv_equiv_pt 260 | 261 | inv_equiv_pt(2) = ceiling(dble(pt)/dble(n1)) 262 | inv_equiv_pt(1) = pt - (inv_equiv_pt(2)-1)*n1 263 | 264 | end function inv_equiv_pt_2d 265 | 266 | end module my_equivalence 267 | -------------------------------------------------------------------------------- /src/xfoil_math.f: -------------------------------------------------------------------------------- 1 | C This file is part of libxfoil 2 | 3 | C libxfoil is free software: you can redistribute it and/or modify 4 | C it under the terms of the GNU General Public License as published by 5 | C the Free Software Foundation, either version 3 of the License, or 6 | C (at your option) any later version. 7 | 8 | C libxfoil is distributed in the hope that it will be useful, 9 | C but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | C MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | C GNU General Public License for more details. 12 | 13 | C You should have received a copy of the GNU General Public License 14 | C along with libxfoil. If not, see . 15 | 16 | C Copyright (C) 2018 Daniel Prosser (this modified version of 17 | C XFoil code) 18 | C Original copyright (C) 2000 Mark Drela (original XFoil code) 19 | 20 | C===================================================================70 21 | C ******************************************************* 22 | C * * 23 | C * Factors a full NxN matrix into an LU form. * 24 | C * Subr. BAKSUB can back-substitute it with some RHS.* 25 | C * Assumes matrix is non-singular... * 26 | C * ...if it isn't, a divide by zero will result. * 27 | C * * 28 | C * A is the matrix... * 29 | C * ...replaced with its LU factors. * 30 | C * * 31 | C * Mark Drela 1988 * 32 | C ******************************************************* 33 | C===================================================================70 34 | SUBROUTINE LUDCMP(NSIZ,N,A,INDX) 35 | C 36 | DIMENSION A(NSIZ,NSIZ), INDX(NSIZ) 37 | C 38 | PARAMETER (NVX=500) 39 | DIMENSION VV(NVX) 40 | C 41 | IF(N.GT.NVX) STOP 'LUDCMP: Array overflow. Increase NVX.' 42 | C 43 | DO 12 I=1, N 44 | AAMAX = 0. 45 | DO 11 J=1, N 46 | AAMAX = MAX( ABS(A(I,J)) , AAMAX ) 47 | 11 CONTINUE 48 | VV(I) = 1.0/AAMAX 49 | 12 CONTINUE 50 | C 51 | DO 19 J=1, N 52 | DO 14 I=1, J-1 53 | SUM = A(I,J) 54 | DO 13 K=1, I-1 55 | SUM = SUM - A(I,K)*A(K,J) 56 | 13 CONTINUE 57 | A(I,J) = SUM 58 | 14 CONTINUE 59 | C 60 | AAMAX = 0. 61 | DO 16 I=J, N 62 | SUM = A(I,J) 63 | DO 15 K=1, J-1 64 | SUM = SUM - A(I,K)*A(K,J) 65 | 15 CONTINUE 66 | A(I,J) = SUM 67 | C 68 | DUM = VV(I)*ABS(SUM) 69 | IF(DUM.GE.AAMAX) THEN 70 | IMAX = I 71 | AAMAX = DUM 72 | ENDIF 73 | 16 CONTINUE 74 | C 75 | IF(J.NE.IMAX) THEN 76 | DO 17 K=1, N 77 | DUM = A(IMAX,K) 78 | A(IMAX,K) = A(J,K) 79 | A(J,K) = DUM 80 | 17 CONTINUE 81 | VV(IMAX) = VV(J) 82 | ENDIF 83 | C 84 | INDX(J) = IMAX 85 | IF(J.NE.N) THEN 86 | DUM = 1.0/A(J,J) 87 | DO 18 I=J+1, N 88 | A(I,J) = A(I,J)*DUM 89 | 18 CONTINUE 90 | ENDIF 91 | C 92 | 19 CONTINUE 93 | C 94 | RETURN 95 | END ! LUDCMP 96 | 97 | 98 | C===================================================================70 99 | C===================================================================70 100 | SUBROUTINE BAKSUB(NSIZ,N,A,INDX,B) 101 | DIMENSION A(NSIZ,NSIZ), B(NSIZ), INDX(NSIZ) 102 | C 103 | II = 0 104 | DO 12 I=1, N 105 | LL = INDX(I) 106 | SUM = B(LL) 107 | B(LL) = B(I) 108 | IF(II.NE.0) THEN 109 | DO 11 J=II, I-1 110 | SUM = SUM - A(I,J)*B(J) 111 | 11 CONTINUE 112 | ELSE IF(SUM.NE.0.0) THEN 113 | II = I 114 | ENDIF 115 | B(I) = SUM 116 | 12 CONTINUE 117 | C 118 | DO 14 I=N, 1, -1 119 | SUM = B(I) 120 | IF(I.LT.N) THEN 121 | DO 13 J=I+1, N 122 | SUM = SUM - A(I,J)*B(J) 123 | 13 CONTINUE 124 | ENDIF 125 | B(I) = SUM/A(I,I) 126 | 14 CONTINUE 127 | C 128 | RETURN 129 | END ! BAKSUB 130 | 131 | C===================================================================70 132 | C 133 | C Solves KK long, tri-diagonal system | 134 | C | 135 | C A C D | 136 | C B A C D | 137 | C B A . . | 138 | C . . C . | 139 | C B A D | 140 | C | 141 | C The righthand side D is replaced by | 142 | C the solution. A, C are destroyed. | 143 | C 144 | C===================================================================70 145 | SUBROUTINE TRISOL(A,B,C,D,KK) 146 | DIMENSION A(KK),B(KK),C(KK),D(KK) 147 | C 148 | DO 1 K=2, KK 149 | KM = K-1 150 | C(KM) = C(KM) / A(KM) 151 | D(KM) = D(KM) / A(KM) 152 | A(K) = A(K) - B(K)*C(KM) 153 | D(K) = D(K) - B(K)*D(KM) 154 | 1 CONTINUE 155 | C 156 | D(KK) = D(KK)/A(KK) 157 | C 158 | DO 2 K=KK-1, 1, -1 159 | D(K) = D(K) - C(K)*D(K+1) 160 | 2 CONTINUE 161 | C 162 | RETURN 163 | END ! TRISOL 164 | 165 | C===================================================================70 166 | C--------------------------------------------------------------- 167 | C ATAN2 function with branch cut checking. 168 | C 169 | C Increments position angle of point X,Y from some previous 170 | C value THOLD due to a change in position, ensuring that the 171 | C position change does not cross the ATAN2 branch cut 172 | C (which is in the -x direction). For example: 173 | C 174 | C ATANC( -1.0 , -1.0 , 0.75*pi ) returns 1.25*pi , whereas 175 | C ATAN2( -1.0 , -1.0 ) returns -.75*pi . 176 | C 177 | C Typically, ATANC is used to fill an array of angles: 178 | C 179 | C THETA(1) = ATAN2( Y(1) , X(1) ) 180 | C DO i=2, N 181 | C THETA(i) = ATANC( Y(i) , X(i) , THETA(i-1) ) 182 | C END DO 183 | C 184 | C This will prevent the angle array THETA(i) from jumping by 185 | C +/- 2 pi when the path X(i),Y(i) crosses the negative x axis. 186 | C 187 | C Input: 188 | C X,Y point position coordinates 189 | C THOLD position angle of nearby point 190 | C 191 | C Output: 192 | C ATANC position angle of X,Y 193 | C--------------------------------------------------------------- 194 | C===================================================================70 195 | FUNCTION ATANC(Y,X,THOLD) 196 | IMPLICIT REAL (A-H,M,O-Z) 197 | DATA PI /3.1415926535897932384/ 198 | DATA TPI /6.2831853071795864769/ 199 | C 200 | C---- set new position angle, ignoring branch cut in ATAN2 function for now 201 | THNEW = ATAN2( Y , X ) 202 | DTHET = THNEW - THOLD 203 | C 204 | C---- angle change cannot exceed +/- pi, so get rid of any multiples of 2 pi 205 | DTCORR = DTHET - TPI*INT( (DTHET + SIGN(PI,DTHET))/TPI ) 206 | C 207 | C---- set correct new angle 208 | ATANC = THOLD + DTCORR 209 | C 210 | RETURN 211 | END ! ATANC 212 | 213 | C===================================================================70 214 | C ******************************************************* 215 | C * * 216 | C * Solves general NxN system in NN unknowns * 217 | C * with arbitrary number (NRHS) of righthand sides. * 218 | C * Assumes system is invertible... * 219 | C * ...if it isn't, a divide by zero will result. * 220 | C * * 221 | C * Z is the coefficient matrix... * 222 | C * ...destroyed during solution process. * 223 | C * R is the righthand side(s)... * 224 | C * ...replaced by the solution vector(s). * 225 | C * * 226 | C * Mark Drela 1984 * 227 | C ******************************************************* 228 | C===================================================================70 229 | SUBROUTINE GAUSS(NSIZ,NN,Z,R,NRHS) 230 | C 231 | DIMENSION Z(NSIZ,NSIZ), R(NSIZ,NRHS) 232 | C 233 | DO 1 NP=1, NN-1 234 | NP1 = NP+1 235 | C 236 | C------ find max pivot index NX 237 | NX = NP 238 | DO 11 N=NP1, NN 239 | IF(ABS(Z(N,NP))-ABS(Z(NX,NP))) 11,11,111 240 | 111 NX = N 241 | 11 CONTINUE 242 | C 243 | PIVOT = 1.0/Z(NX,NP) 244 | C 245 | C------ switch pivots 246 | Z(NX,NP) = Z(NP,NP) 247 | C 248 | C------ switch rows & normalize pivot row 249 | DO 12 L=NP1, NN 250 | TEMP = Z(NX,L)*PIVOT 251 | Z(NX,L) = Z(NP,L) 252 | Z(NP,L) = TEMP 253 | 12 CONTINUE 254 | C 255 | DO 13 L=1, NRHS 256 | TEMP = R(NX,L)*PIVOT 257 | R(NX,L) = R(NP,L) 258 | R(NP,L) = TEMP 259 | 13 CONTINUE 260 | C 261 | C------ forward eliminate everything 262 | DO 15 K=NP1, NN 263 | ZTMP = Z(K,NP) 264 | C 265 | C IF(ZTMP.EQ.0.0) GO TO 15 266 | C 267 | DO 151 L=NP1, NN 268 | Z(K,L) = Z(K,L) - ZTMP*Z(NP,L) 269 | 151 CONTINUE 270 | DO 152 L=1, NRHS 271 | R(K,L) = R(K,L) - ZTMP*R(NP,L) 272 | 152 CONTINUE 273 | 15 CONTINUE 274 | C 275 | 1 CONTINUE 276 | C 277 | C---- solve for last row 278 | DO 2 L=1, NRHS 279 | R(NN,L) = R(NN,L)/Z(NN,NN) 280 | 2 CONTINUE 281 | C 282 | C---- back substitute everything 283 | DO 3 NP=NN-1, 1, -1 284 | NP1 = NP+1 285 | DO 31 L=1, NRHS 286 | DO 310 K=NP1, NN 287 | R(NP,L) = R(NP,L) - Z(NP,K)*R(K,L) 288 | 310 CONTINUE 289 | 31 CONTINUE 290 | 3 CONTINUE 291 | C 292 | RETURN 293 | END ! GAUSS 294 | -------------------------------------------------------------------------------- /python/libxfoil.i: -------------------------------------------------------------------------------- 1 | /* This file is part of libxfoil. 2 | 3 | libxfoil is free software: you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation, either version 3 of the License, or 6 | (at your option) any later version. 7 | 8 | libxfoil is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with libxfoil. If not, see . 15 | 16 | Copyright (C) 2019 Daniel Prosser */ 17 | 18 | %module libxfoil 19 | %include "cstring.i" 20 | %include "cpointer.i" 21 | %include "carrays.i" 22 | %{ 23 | #include "libxfoil.h" 24 | %} 25 | 26 | /* Type handling */ 27 | %cstring_bounded_mutable(char *des, 1024); 28 | %pointer_functions(int, intp); 29 | %pointer_functions(double, doublep); 30 | %pointer_functions(bool, boolp); 31 | %array_functions(double, doublea); 32 | %array_functions(int, inta); 33 | 34 | /* Xfoil dimensioning constants */ 35 | #define IQX 360 36 | #define ISX 2 37 | #define IBX 1440 38 | #define IWX 47 39 | #define IZX 407 40 | #define IVX 277 41 | #define NCOM 73 42 | 43 | /* Structs */ 44 | typedef struct 45 | { 46 | double ncrit; 47 | double xtript, xtripb; 48 | bool viscous_mode; 49 | bool silent_mode; 50 | int maxit; 51 | double vaccel; 52 | } xfoil_options_type; 53 | 54 | typedef struct 55 | { 56 | int npan; 57 | double cvpar, cterat, ctrrat, xsref1, xsref2, xpref1, xpref2; 58 | } xfoil_geom_options_type; 59 | 60 | /* Data structs. Users only need to maintain an instance of the xfoil_data_group 61 | type, though the subtypes also need to be defined here. */ 62 | typedef struct 63 | { 64 | double PI, HOPI, QOPI, DTOR; 65 | bool SILENT_MODE, VISCOUS_MODE; 66 | int MAXIT; 67 | double GAM[IQX], GAMU[IQX*2], QINVU[IZX*2], GAM_A[IQX]; 68 | double QINV[IZX], QINV_A[IZX]; 69 | bool LGAMU, LQAIJ, SHARP, LVISC, LWAKE, LVCONV, LWDIJ, LIPAN; 70 | bool LBLINI, LADIJ, LALFA; 71 | int RETYP, MATYP, ITMAX; 72 | double AIJ[IQX*IQX], BIJ[IQX*IZX], DIJ[IZX*IZX], CIJ[IWX*IQX]; 73 | double DZDG[IQX], DZDN[IQX], DQDG[IQX], DZDM[IZX], DQDM[IZX]; 74 | double X[IZX], Y[IZX], NX[IZX], NY[IZX], S[IZX], APANEL[IZX]; 75 | double SIG[IZX], XP[IZX], YP[IZX]; 76 | int N, NB, NPAN, NW, IST, NSYS; 77 | double PSIO, QINF, ALFA, Z_QINF, Z_ALFA, Z_QDOF0, Z_QDOF1; 78 | double Z_QDOF2, Z_QDOF3, ANTE, ASTE, DSTE, ADEG, AMAX; 79 | double QF0[IQX], QF1[IQX], QF2[IQX], QF3[IQX]; 80 | int AIJPIV[IQX], IBLTE[ISX], NBL[ISX]; 81 | int IPAN[IVX*ISX], ISYS[IVX*ISX]; 82 | double SIGTE, GAMTE, SIGTE_A, GAMTE_A, MINF, MINF1, REINF, REINF1; 83 | double TKLAM, TKL_MSQ, CPSTAR, QSTAR, GAMMA, GAMM1; 84 | double XCMREF, YCMREF, CL, CM, CD, CDP, CDF, CL_ALF, CL_MSQ, SBLE; 85 | double XB[IBX], YB[IBX], SB[IBX], XBP[IBX], YBP[IBX], SNEW[5*IBX]; 86 | double W1[6*IQX], W2[6*IQX], W3[6*IQX]; 87 | double W4[6*IQX], W5[6*IQX], W6[6*IQX]; 88 | double XLE, YLE, XTE, YTE, CHORD, SLE; 89 | double CVPAR, CTERAT, CTRRAT, XSREF1, XSREF2, XPREF1, XPREF2; 90 | double MINF_CL, COSA, SINA, ACRIT, RLX, VACCEL; 91 | double CPI[IZX], CPV[IZX], QVIS[IZX]; 92 | double VTI[IVX*ISX], XSSI[IVX*ISX]; 93 | double AWAKE, AVISC, MVISC, CLSPEC, QTAN1, QTAN2, SST, SST_GO; 94 | double SST_GP; 95 | double WGAP[IWX], XSTRIP[ISX], XSSITR[ISX]; 96 | double UINV[IVX*ISX], UINV_A[IVX*ISX], UEDG[IVX*ISX]; 97 | double THET[IVX*ISX], DSTR[IVX*ISX], CTAU[IVX*ISX]; 98 | double MASS[IVX*ISX], TAU[IVX*ISX], DIS[IVX*ISX], CTQ[IVX*ISX]; 99 | double DELT[IVX*ISX], TSTR[IVX*ISX], USLP[IVX*ISX]; 100 | int IDAMP; 101 | int ITRAN[ISX], IMXBL, ISMXBL; 102 | bool TFORCE[ISX]; 103 | double VM[3*IZX*IZX], VA[3*2*IZX], VB[3*2*IZX], VDEL[3*2*IZX]; 104 | double VZ[3*2], XOCTR[ISX], YOCTR[ISX]; 105 | double RMSBL, RMXBL, WAKLEN; 106 | double UNEW[IVX*2], U_AC[IVX*2]; 107 | double QNEW[IQX], Q_AC[IQX]; 108 | char VMXBL; 109 | double THICKB, XTHICKB, THICKM, XTHICKM, CAMBR, XCAMBR; 110 | bool XFOIL_FAIL; 111 | } xfoil_data_type; 112 | 113 | typedef struct 114 | { 115 | double SCCON, GACON, GBCON, GCCON, DLCON, CTRCON, CTRCEX, DUXCON; 116 | double CTCON, CFFAC; 117 | } blpar_data_type; 118 | 119 | typedef struct 120 | { 121 | int IDAMPV; 122 | bool SIMI, TRAN, TURB, WAKE; 123 | bool TRFORC, TRFREE; 124 | double X1, U1, T1, D1, S1, AMPL1, U1_UEI, U1_MS, DW1; 125 | double H1, H1_T1, H1_D1; 126 | double M1, M1_U1, M1_MS; 127 | double R1, R1_U1, R1_MS; 128 | double V1, V1_U1, V1_MS, V1_RE; 129 | double HK1, HK1_U1, HK1_T1, HK1_D1, HK1_MS; 130 | double HS1, HS1_U1, HS1_T1, HS1_D1, HS1_MS, HS1_RE; 131 | double HC1, HC1_U1, HC1_T1, HC1_D1, HC1_MS; 132 | double RT1, RT1_U1, RT1_T1, RT1_MS, RT1_RE; 133 | double CF1, CF1_U1, CF1_T1, CF1_D1, CF1_MS, CF1_RE; 134 | double DI1, DI1_U1, DI1_T1, DI1_D1, DI1_S1, DI1_MS, DI1_RE; 135 | double US1, US1_U1, US1_T1, US1_D1, US1_MS, US1_RE; 136 | double CQ1, CQ1_U1, CQ1_T1, CQ1_D1, CQ1_MS, CQ1_RE ; 137 | double DE1, DE1_U1, DE1_T1, DE1_D1, DE1_MS; 138 | double X2, U2, T2, D2, S2, AMPL2, U2_UEI, U2_MS, DW2; 139 | double H2, H2_T2, H2_D2; 140 | double M2, M2_U2, M2_MS; 141 | double R2, R2_U2, R2_MS; 142 | double V2, V2_U2, V2_MS, V2_RE; 143 | double HK2, HK2_U2, HK2_T2, HK2_D2, HK2_MS; 144 | double HS2, HS2_U2, HS2_T2, HS2_D2, HS2_MS, HS2_RE; 145 | double HC2, HC2_U2, HC2_T2, HC2_D2, HC2_MS; 146 | double RT2, RT2_U2, RT2_T2, RT2_MS, RT2_RE; 147 | double CF2, CF2_U2, CF2_T2, CF2_D2, CF2_MS, CF2_RE; 148 | double DI2, DI2_U2, DI2_T2, DI2_D2, DI2_S2, DI2_MS, DI2_RE; 149 | double US2, US2_U2, US2_T2, US2_D2, US2_MS, US2_RE; 150 | double CQ2, CQ2_U2, CQ2_T2, CQ2_D2, CQ2_MS, CQ2_RE; 151 | double DE2, DE2_U2, DE2_T2, DE2_D2, DE2_MS; 152 | double CFM, CFM_MS, CFM_RE; 153 | double CFM_U1, CFM_T1, CFM_D1, CFM_U2, CFM_T2, CFM_D2; 154 | double XT, XT_A1, XT_MS, XT_RE, XT_XF; 155 | double XT_X1, XT_T1, XT_D1, XT_U1, XT_X2, XT_T2, XT_D2, XT_U2; 156 | double C1SAV[NCOM], C2SAV[NCOM]; 157 | double DWTE, QINFBL, TKBL, TKBL_MS, RSTBL, RSTBL_MS, HSTINV; 158 | double HSTINV_MS, REYBL, REYBL_MS, REYBL_RE, GAMBL, GM1BL; 159 | double HVRA, BULE, XIFORC, AMCRIT; 160 | double VS1[4*5], VS2[4*5]; 161 | double VSREZ[4], VSR[4], VSM[4], VSX[4]; 162 | } xbl_data_type; 163 | 164 | typedef struct 165 | { 166 | xfoil_data_type xfd; 167 | blpar_data_type bld; 168 | xbl_data_type xbd; 169 | } xfoil_data_group; 170 | 171 | /* Memory management */ 172 | extern void xfoil_init(xfoil_data_group *xdg); 173 | extern void xfoil_cleanup(xfoil_data_group *xdg); 174 | extern void xfoil_copy(xfoil_data_group *xdg_from, 175 | xfoil_data_group *xdg_to); 176 | 177 | /* Xfoil routines modifying xfoil_data_group */ 178 | extern void xfoil_defaults(xfoil_data_group *xdg, 179 | xfoil_options_type *xfoil_options); 180 | extern void xfoil_set_paneling(xfoil_data_group *xdg, 181 | xfoil_geom_options_type *geom_opts); 182 | extern void xfoil_set_buffer_airfoil(xfoil_data_group *xdg, double *xin, 183 | double *zin, int *npointin); 184 | extern void xfoil_get_buffer_airfoil(xfoil_data_group *xdg, double *xout, 185 | double *zout, int *npoint, int *stat); 186 | extern void xfoil_get_current_airfoil(xfoil_data_group *xdg, double *xout, 187 | double *zout, int *npoint, int *stat); 188 | extern void xfoil_smooth_paneling(xfoil_data_group *xdg, int *stat); 189 | extern void xfoil_apply_flap_deflection(xfoil_data_group *xdg, 190 | double *xflap, double *zflap, 191 | int *z_flap_spec, double *degrees, 192 | int *npointout, int *stat); 193 | extern void xfoil_modify_tegap(xfoil_data_group *xdg, double *gap, 194 | double *blendloc, int *npointout, int *stat); 195 | extern void xfoil_geometry_info(xfoil_data_group *xdg, double *maxt, 196 | double *xmaxt, double *maxc, double *xmaxc, 197 | int *stat); 198 | extern void xfoil_set_reynolds_number(xfoil_data_group *xdg, double *re); 199 | extern void xfoil_set_mach_number(xfoil_data_group *xdg, double *mach); 200 | extern void xfoil_reinitialize_bl(xfoil_data_group *xdg); 201 | extern void xfoil_specal(xfoil_data_group *xdg, double *alpha_spec, 202 | double *alpha, double *lift, double *drag, 203 | double *moment, bool *converged, int *stat); 204 | extern void xfoil_speccl(xfoil_data_group *xdg, double *cl_spec, 205 | double *alpha, double *lift, double *drag, 206 | double *moment, bool *converged, int *stat); 207 | extern void xfoil_get_transloc(xfoil_data_group *xdg, double *xtranst, 208 | double *ztranst, double *xtransb, 209 | double *ztransb); 210 | extern void xfoil_get_cp(xfoil_data_group *xdg, int *npoint, double *cp); 211 | extern void xfoil_get_cf(xfoil_data_group *xdg, int *npoint, double *cf); 212 | extern void xfoil_get_uedge(xfoil_data_group *xdg, int *npoint, double *uedge); 213 | extern void xfoil_get_deltastar(xfoil_data_group *xdg, int *npoint, 214 | double *deltastar); 215 | extern void xfoil_get_diss(xfoil_data_group *xdg, int *npoint, double *diss); 216 | extern void xfoil_get_hk(xfoil_data_group *xdg, int *npoint, double *hk); 217 | extern void xfoil_get_retheta(xfoil_data_group *xdg, int *npoint, 218 | double *retheta); 219 | extern void xfoil_get_ampl(xfoil_data_group *xdg, int *npoint, 220 | double *ampl); 221 | 222 | /* Wake data (also modifies xfoil_data_group) */ 223 | extern void xfoil_get_wakepoints(xfoil_data_group *xdg, int *nwake); 224 | extern void xfoil_get_wake_geometry(xfoil_data_group *xdg, int *nwake, 225 | double *xw, double *zw); 226 | extern void xfoil_get_wake_cp(xfoil_data_group *xdg, int *nwake, double *cp); 227 | extern void xfoil_get_wake_uedge(xfoil_data_group *xdg, int *nwake, 228 | double *uedge); 229 | extern void xfoil_get_wake_deltastar(xfoil_data_group *xdg, int *nwake, 230 | double *deltastar); 231 | 232 | /* The following methods utilize xfoil functionality, performing some 233 | calculations and returning a result, without needing to maintain an 234 | xfoil_data_group instance. */ 235 | extern void run_xfoil(int *npointin, double *xin, double *zin, 236 | xfoil_geom_options_type *geom_opts, int *noppoint, 237 | double *operating_points, int *op_modes, 238 | double *reynolds_numbers, double *mach_numbers, 239 | bool *use_flap, double *x_flap, double *z_flap, 240 | int *z_flap_spec, double *flap_degrees, 241 | xfoil_options_type *xfoil_opts, bool *reinitialize, 242 | bool *fix_unconverged, double *lift, double *drag, 243 | double *moment, double *viscrms, double *alpha, 244 | double *xtrt, double *xtrb, int *stat); 245 | extern void naca_4_digit(double *camber, double *xcamber, double *thick, 246 | int *npointside, double *xout, double *zout, 247 | int *nout); 248 | extern void naca_5_digit(char *des, int *npointside, double *xout, 249 | double *zout, int *nout, int *stat); 250 | extern void xfoil_spline_coordinates(double *x, double *z, int *npt, double *s, 251 | double *xs, double *zs); 252 | extern void xfoil_eval_spline(double *x, double *z, double *s, double *xs, 253 | double *zs, int *npt, double *sc, double *xc, 254 | double *zc); 255 | extern void xfoil_lefind(double *x, double *z, double *s, double *xs, 256 | double *zs, int *npt, double *sle, double *xle, 257 | double *zle); 258 | -------------------------------------------------------------------------------- /src/libxfoil.h: -------------------------------------------------------------------------------- 1 | /* This file is part of libxfoil. 2 | 3 | libxfoil is free software: you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation, either version 3 of the License, or 6 | (at your option) any later version. 7 | 8 | libxfoil is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with libxfoil. If not, see . 15 | 16 | Copyright (C) 2019 Daniel Prosser 17 | 18 | See libxfoil.f90 for descriptions of inputs and outputs. */ 19 | 20 | #pragma once 21 | 22 | /* Xfoil dimensioning constants */ 23 | 24 | #define IQX 360 25 | #define ISX 2 26 | #define IBX 1440 27 | #define IWX 47 28 | #define IZX 407 29 | #define IVX 277 30 | #define NCOM 73 31 | 32 | #include 33 | 34 | /* Xfoil settings structs */ 35 | 36 | typedef struct 37 | { 38 | double ncrit; 39 | double xtript, xtripb; 40 | bool viscous_mode; 41 | bool silent_mode; 42 | int maxit; 43 | double vaccel; 44 | } xfoil_options_type; 45 | 46 | typedef struct 47 | { 48 | int npan; 49 | double cvpar, cterat, ctrrat, xsref1, xsref2, xpref1, xpref2; 50 | } xfoil_geom_options_type; 51 | 52 | /* Data structs. Users only need to maintain an instance of the xfoil_data_group 53 | type, though the subtypes also need to be defined here. */ 54 | 55 | typedef struct 56 | { 57 | double PI, HOPI, QOPI, DTOR; 58 | bool SILENT_MODE, VISCOUS_MODE; 59 | int MAXIT; 60 | double *GAM, *GAMU, *QINVU, *GAM_A; 61 | double *QINV, *QINV_A; 62 | bool LGAMU, LQAIJ, SHARP, LVISC, LWAKE, LVCONV, LWDIJ, LIPAN; 63 | bool LBLINI, LADIJ, LALFA; 64 | int RETYP, MATYP, ITMAX; 65 | double *AIJ, *BIJ, *DIJ, *CIJ; 66 | double *DZDG, *DZDN, *DQDG, *DZDM, *DQDM; 67 | double *X, *Y, *NX, *NY, *S, *APANEL; 68 | double *SIG, *XP, *YP; 69 | int N, NB, NPAN, NW, IST, NSYS; 70 | double PSIO, QINF, ALFA, Z_QINF, Z_ALFA, Z_QDOF0, Z_QDOF1; 71 | double Z_QDOF2, Z_QDOF3, ANTE, ASTE, DSTE, ADEG, AMAX; 72 | double *QF0, *QF1, *QF2, *QF3; 73 | int *AIJPIV, *IBLTE, *NBL; 74 | int *IPAN, *ISYS; 75 | double SIGTE, GAMTE, SIGTE_A, GAMTE_A, MINF, MINF1, REINF, REINF1; 76 | double TKLAM, TKL_MSQ, CPSTAR, QSTAR, GAMMA, GAMM1; 77 | double XCMREF, YCMREF, CL, CM, CD, CDP, CDF, CL_ALF, CL_MSQ, SBLE; 78 | double *XB, *YB, *SB, *XBP, *YBP, *SNEW; 79 | double *W1, *W2, *W3; 80 | double *W4, *W5, *W6; 81 | double XLE, YLE, XTE, YTE, CHORD, SLE; 82 | double CVPAR, CTERAT, CTRRAT, XSREF1, XSREF2, XPREF1, XPREF2; 83 | double MINF_CL, COSA, SINA, ACRIT, RLX, VACCEL; 84 | double *CPI, *CPV, *QVIS; 85 | double *VTI, *XSSI; 86 | double AWAKE, AVISC, MVISC, CLSPEC, QTAN1, QTAN2, SST, SST_GO; 87 | double SST_GP; 88 | double *WGAP, *XSTRIP, *XSSITR; 89 | double *UINV, *UINV_A, *UEDG; 90 | double *THET, *DSTR, *CTAU; 91 | double *MASS, *TAU, *DIS, *CTQ; 92 | double *DELT, *TSTR, *USLP; 93 | int IDAMP; 94 | int *ITRAN; 95 | int IMXBL, ISMXBL; 96 | bool *TFORCE; 97 | double *VM, *VA, *VB, *VDEL; 98 | double *VZ, *XOCTR, *YOCTR; 99 | double RMSBL, RMXBL, WAKLEN; 100 | double *UNEW, *U_AC; 101 | double *QNEW, *Q_AC; 102 | char VMXBL; 103 | double THICKB, XTHICKB, THICKM, XTHICKM, CAMBR, XCAMBR; 104 | bool XFOIL_FAIL; 105 | } xfoil_data_type; 106 | 107 | typedef struct 108 | { 109 | double SCCON, GACON, GBCON, GCCON, DLCON, CTRCON, CTRCEX, DUXCON; 110 | double CTCON, CFFAC; 111 | } blpar_data_type; 112 | 113 | typedef struct 114 | { 115 | int IDAMPV; 116 | bool SIMI, TRAN, TURB, WAKE; 117 | bool TRFORC, TRFREE; 118 | double X1, U1, T1, D1, S1, AMPL1, U1_UEI, U1_MS, DW1; 119 | double H1, H1_T1, H1_D1; 120 | double M1, M1_U1, M1_MS; 121 | double R1, R1_U1, R1_MS; 122 | double V1, V1_U1, V1_MS, V1_RE; 123 | double HK1, HK1_U1, HK1_T1, HK1_D1, HK1_MS; 124 | double HS1, HS1_U1, HS1_T1, HS1_D1, HS1_MS, HS1_RE; 125 | double HC1, HC1_U1, HC1_T1, HC1_D1, HC1_MS; 126 | double RT1, RT1_U1, RT1_T1, RT1_MS, RT1_RE; 127 | double CF1, CF1_U1, CF1_T1, CF1_D1, CF1_MS, CF1_RE; 128 | double DI1, DI1_U1, DI1_T1, DI1_D1, DI1_S1, DI1_MS, DI1_RE; 129 | double US1, US1_U1, US1_T1, US1_D1, US1_MS, US1_RE; 130 | double CQ1, CQ1_U1, CQ1_T1, CQ1_D1, CQ1_MS, CQ1_RE; 131 | double DE1, DE1_U1, DE1_T1, DE1_D1, DE1_MS; 132 | double X2, U2, T2, D2, S2, AMPL2, U2_UEI, U2_MS, DW2; 133 | double H2, H2_T2, H2_D2; 134 | double M2, M2_U2, M2_MS; 135 | double R2, R2_U2, R2_MS; 136 | double V2, V2_U2, V2_MS, V2_RE; 137 | double HK2, HK2_U2, HK2_T2, HK2_D2, HK2_MS; 138 | double HS2, HS2_U2, HS2_T2, HS2_D2, HS2_MS, HS2_RE; 139 | double HC2, HC2_U2, HC2_T2, HC2_D2, HC2_MS; 140 | double RT2, RT2_U2, RT2_T2, RT2_MS, RT2_RE; 141 | double CF2, CF2_U2, CF2_T2, CF2_D2, CF2_MS, CF2_RE; 142 | double DI2, DI2_U2, DI2_T2, DI2_D2, DI2_S2, DI2_MS, DI2_RE; 143 | double US2, US2_U2, US2_T2, US2_D2, US2_MS, US2_RE; 144 | double CQ2, CQ2_U2, CQ2_T2, CQ2_D2, CQ2_MS, CQ2_RE; 145 | double DE2, DE2_U2, DE2_T2, DE2_D2, DE2_MS; 146 | double CFM, CFM_MS, CFM_RE; 147 | double CFM_U1, CFM_T1, CFM_D1, CFM_U2, CFM_T2, CFM_D2; 148 | double XT, XT_A1, XT_MS, XT_RE, XT_XF; 149 | double XT_X1, XT_T1, XT_D1, XT_U1, XT_X2, XT_T2, XT_D2, XT_U2; 150 | double *C1SAV, *C2SAV; 151 | double DWTE, QINFBL, TKBL, TKBL_MS, RSTBL, RSTBL_MS, HSTINV; 152 | double HSTINV_MS, REYBL, REYBL_MS, REYBL_RE, GAMBL, GM1BL; 153 | double HVRA, BULE, XIFORC, AMCRIT; 154 | double *VS1, *VS2; 155 | double *VSREZ, *VSR, *VSM, *VSX; 156 | } xbl_data_type; 157 | 158 | typedef struct 159 | { 160 | xfoil_data_type xfd; 161 | blpar_data_type bld; 162 | xbl_data_type xbd; 163 | } xfoil_data_group; 164 | 165 | /* Memory management */ 166 | 167 | extern void xfoil_init(xfoil_data_group *xdg); 168 | extern void xfoil_cleanup(xfoil_data_group *xdg); 169 | extern void xfoil_copy(const xfoil_data_group *xdg_from, 170 | xfoil_data_group *xdg_to); 171 | 172 | /* Xfoil routines modifying xfoil_data_group */ 173 | 174 | extern void xfoil_defaults(xfoil_data_group *xdg, 175 | const xfoil_options_type *xfoil_options); 176 | extern void xfoil_set_paneling(xfoil_data_group *xdg, 177 | const xfoil_geom_options_type *geom_opts); 178 | extern void xfoil_set_buffer_airfoil(xfoil_data_group *xdg, const double xin[], 179 | const double zin[], const int *npointin); 180 | extern void xfoil_get_buffer_airfoil(const xfoil_data_group *xdg, double xout[], 181 | double zout[], const int *npoint, 182 | int *stat); 183 | extern void xfoil_get_current_airfoil(const xfoil_data_group *xdg, 184 | double xout[], double zout[], 185 | const int *npoint, int *stat); 186 | extern void xfoil_smooth_paneling(xfoil_data_group *xdg, int *stat); 187 | extern void xfoil_apply_flap_deflection(xfoil_data_group *xdg, 188 | const double *xflap, 189 | const double *zflap, 190 | const int *z_flap_spec, 191 | const double *degrees, int *npointout, 192 | int *stat); 193 | extern void xfoil_modify_tegap(xfoil_data_group *xdg, const double *gap, 194 | const double *blendloc, int *npointout, 195 | int *stat); 196 | extern void xfoil_geometry_info(const xfoil_data_group *xdg, double *maxt, 197 | double *xmaxt, double *maxc, double *xmaxc, 198 | int *stat); 199 | extern void xfoil_set_reynolds_number(xfoil_data_group *xdg, const double *re); 200 | extern void xfoil_set_mach_number(xfoil_data_group *xdg, const double *mach); 201 | extern void xfoil_reinitialize_bl(xfoil_data_group *xdg); 202 | extern void xfoil_specal(xfoil_data_group *xdg, const double *alpha_spec, 203 | double *alpha, double *lift, double *drag, 204 | double *moment, bool *converged, int *stat); 205 | extern void xfoil_speccl(xfoil_data_group *xdg, const double *cl_spec, 206 | double *alpha, double *lift, double *drag, 207 | double *moment, bool *converged, int *stat); 208 | extern void xfoil_get_transloc(const xfoil_data_group *xdg, double *xtranst, 209 | double *ztranst, double *xtransb, 210 | double *ztransb); 211 | extern void xfoil_get_cp(const xfoil_data_group *xdg, const int *npoint, 212 | double cp[]); 213 | extern void xfoil_get_cf(const xfoil_data_group *xdg, const int *npoint, 214 | double cf[]); 215 | extern void xfoil_get_uedge(const xfoil_data_group *xdg, const int *npoint, 216 | double uedge[]); 217 | extern void xfoil_get_deltastar(const xfoil_data_group *xdg, const int *npoint, 218 | double deltastar[]); 219 | extern void xfoil_get_diss(const xfoil_data_group *xdg, const int *npoint, 220 | double diss[]); 221 | extern void xfoil_get_hk(const xfoil_data_group *xdg, const int *npoint, 222 | double hk[]); 223 | extern void xfoil_get_retheta(const xfoil_data_group *xdg, const int *npoint, 224 | double retheta[]); 225 | extern void xfoil_get_ampl(const xfoil_data_group *xdg, const int *npoint, 226 | double ampl[]); 227 | 228 | /* Wake data (also uses xfoil_data_group) */ 229 | extern void xfoil_get_wakepoints(const xfoil_data_group *xdg, int *nwake); 230 | extern void xfoil_get_wake_geometry(const xfoil_data_group *xdg, 231 | const int *nwake, double xw[], 232 | double zw[]); 233 | extern void xfoil_get_wake_cp(const xfoil_data_group *xdg, const int *nwake, 234 | double cp[]); 235 | extern void xfoil_get_wake_uedge(const xfoil_data_group *xdg, const int *nwake, 236 | double uedge[]); 237 | extern void xfoil_get_wake_deltastar(const xfoil_data_group *xdg, 238 | const int *nwake, double deltastar[]); 239 | 240 | /* The following methods utilize xfoil functionality, performing some 241 | calculations and returning a result, without needing to maintain an 242 | xfoil_data_group instance. */ 243 | extern void run_xfoil(const int *npointin, const double xin[], 244 | const double zin[], 245 | const xfoil_geom_options_type *geom_opts, 246 | const int *noppoint, const double operating_points[], 247 | const int op_modes[], const double reynolds_numbers[], 248 | const double mach_numbers[], const bool *use_flap, 249 | const double *x_flap, const double *z_flap, 250 | const int *z_flap_spec, const double flap_degrees[], 251 | const xfoil_options_type *xfoil_opts, 252 | const bool *reinitialize, const bool *fix_unconverged, 253 | double lift[], double drag[], double moment[], 254 | double viscrms[], double alpha[], double xtrt[], 255 | double xtrb[], int *stat); 256 | extern void naca_4_digit(const double *camber, const double *xcamber, 257 | const double *thick, const int *npointside, 258 | double xout[], double zout[], int *nout); 259 | extern void naca_5_digit(const char des[5], const int *npointside, 260 | double xout[], double zout[], int *nout, int *stat); 261 | extern void xfoil_spline_coordinates(const double x[], const double z[], 262 | const int *npt, double s[], double xs[], 263 | double zs[]); 264 | extern void xfoil_eval_spline(const double x[], const double z[], 265 | const double s[], const double xs[], 266 | const double zs[], const int *npt, 267 | const double *sc, double *xc, double *zc); 268 | extern void xfoil_lefind(const double x[], const double z[], const double s[], 269 | const double xs[], const double zs[], const int *npt, 270 | double *sle, double *xle, double *zle); 271 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Library General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License 307 | along with this program; if not, write to the Free Software 308 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 309 | 310 | 311 | Also add information on how to contact you by electronic and paper mail. 312 | 313 | If the program is interactive, make it output a short notice like this 314 | when it starts in an interactive mode: 315 | 316 | Gnomovision version 69, Copyright (C) year name of author 317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 318 | This is free software, and you are welcome to redistribute it 319 | under certain conditions; type `show c' for details. 320 | 321 | The hypothetical commands `show w' and `show c' should show the appropriate 322 | parts of the General Public License. Of course, the commands you use may 323 | be called something other than `show w' and `show c'; they could even be 324 | mouse-clicks or menu items--whatever suits your program. 325 | 326 | You should also get your employer (if you work as a programmer) or your 327 | school, if any, to sign a "copyright disclaimer" for the program, if 328 | necessary. Here is a sample; alter the names: 329 | 330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 331 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 332 | 333 | , 1 April 1989 334 | Ty Coon, President of Vice 335 | 336 | This General Public License does not permit incorporating your program into 337 | proprietary programs. If your program is a subroutine library, you may 338 | consider it more useful to permit linking proprietary applications with the 339 | library. If this is what you want to do, use the GNU Library General 340 | Public License instead of this License. 341 | -------------------------------------------------------------------------------- /python/libxfoil_wrap.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # This file is part of libxfoil. 4 | # 5 | # libxfoil is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # libxfoil is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with libxfoil. If not, see . 17 | # 18 | # Copyright (C) 2019 Daniel Prosser 19 | # 20 | # See libxfoil.f90 for descriptions of inputs and outputs. 21 | # 22 | #=============================================================================== 23 | # 24 | # Abstracts swig datatypes so the functions can be called with native types. 25 | # 26 | 27 | import libxfoil as xi 28 | 29 | def xfoil_init(xdg): 30 | 31 | xi.xfoil_init(xdg) 32 | 33 | def xfoil_cleanup(xdg): 34 | 35 | xi.xfoil_cleanup(xdg) 36 | 37 | def xfoil_copy(xdg_from, xdg_to): 38 | 39 | xi.xfoil_copy(xdg_from, xdg_to) 40 | 41 | def xfoil_defaults(xdg, xfoil_options): 42 | 43 | xi.xfoil_defaults(xdg, xfoil_options) 44 | 45 | def xfoil_set_paneling(xdg, geom_opts): 46 | 47 | xi.xfoil_set_paneling(xdg, geom_opts) 48 | 49 | def xfoil_set_buffer_airfoil(xdg, xin, zin, npointin): 50 | 51 | xin_a = xi.new_doublea(npointin) 52 | zin_a = xi.new_doublea(npointin) 53 | npointin_p = xi.copy_intp(npointin) 54 | for i in range(npointin): 55 | xi.doublea_setitem(xin_a, i, xin[i]) 56 | xi.doublea_setitem(zin_a, i, zin[i]) 57 | 58 | xi.xfoil_set_buffer_airfoil(xdg, xin_a, zin_a, npointin_p) 59 | 60 | xi.delete_doublea(xin_a) 61 | xi.delete_doublea(zin_a) 62 | xi.delete_intp(npointin_p) 63 | 64 | def xfoil_get_buffer_airfoil(xdg, npoint): 65 | 66 | xout_a = xi.new_doublea(npoint) 67 | zout_a = xi.new_doublea(npoint) 68 | npoint_p = xi.copy_intp(npoint) 69 | stat_p = xi.new_intp() 70 | 71 | xi.xfoil_get_buffer_airfoil(xdg, xout_a, zout_a, npoint_p, stat_p) 72 | 73 | xout = npoint*[0] 74 | zout = npoint*[0] 75 | for i in range(npoint): 76 | xout[i] = xi.doublea_getitem(xout_a, i) 77 | zout[i] = xi.doublea_getitem(zout_a, i) 78 | stat = xi.intp_value(stat_p) 79 | 80 | xi.delete_doublea(xout_a) 81 | xi.delete_doublea(zout_a) 82 | xi.delete_intp(npoint_p) 83 | xi.delete_intp(stat_p) 84 | 85 | return xout, zout, stat 86 | 87 | def xfoil_get_current_airfoil(xdg, npoint): 88 | 89 | xout_a = xi.new_doublea(npoint) 90 | zout_a = xi.new_doublea(npoint) 91 | npoint_p = xi.copy_intp(npoint) 92 | stat_p = xi.new_intp() 93 | 94 | xi.xfoil_get_current_airfoil(xdg, xout_a, zout_a, npoint_p, stat_p) 95 | 96 | xout = npoint*[0] 97 | zout = npoint*[0] 98 | for i in range(npoint): 99 | xout[i] = xi.doublea_getitem(xout_a, i) 100 | zout[i] = xi.doublea_getitem(zout_a, i) 101 | stat = xi.intp_value(stat_p) 102 | 103 | xi.delete_doublea(xout_a) 104 | xi.delete_doublea(zout_a) 105 | xi.delete_intp(npoint_p) 106 | xi.delete_intp(stat_p) 107 | 108 | return xout, zout, stat 109 | 110 | def xfoil_smooth_paneling(xdg): 111 | 112 | stat_p = xi.new_intp() 113 | 114 | xi.xfoil_smooth_paneling(xdg, stat_p) 115 | stat = xi.intp_value(stat_p) 116 | 117 | xi.delete_intp(stat_p) 118 | 119 | return stat 120 | 121 | def xfoil_apply_flap_deflection(xdg, xflap, zflap, z_flap_spec, degrees): 122 | 123 | xflap_p = xi.copy_doublep(xflap) 124 | zflap_p = xi.copy_doublep(zflap) 125 | z_flap_spec_p = xi.copy_intp(z_flap_spec) 126 | degrees_p = xi.copy_doublep(degrees) 127 | npointout_p = xi.new_intp() 128 | stat_p = xi.new_intp() 129 | 130 | xi.xfoil_apply_flap_deflection(xdg, xflap_p, zflap_p, z_flap_spec_p, 131 | degrees_p, npointout_p, stat_p) 132 | 133 | npointout = xi.intp_value(npointout_p) 134 | stat = xi.intp_value(stat_p) 135 | 136 | xi.delete_doublep(xflap_p) 137 | xi.delete_doublep(zflap_p) 138 | xi.delete_intp(z_flap_spec_p) 139 | xi.delete_intp(npointout_p) 140 | xi.delete_intp(stat_p) 141 | 142 | return npointout, stat 143 | 144 | def xfoil_modify_tegap(xdg, gap, blendloc): 145 | 146 | stat_p = xi.new_intp() 147 | gap_p = xi.copy_doublep(gap) 148 | blendloc_p = xi.copy_doublep(blendloc) 149 | npointout_p = xi.new_intp() 150 | 151 | xi.xfoil_modify_tegap(xdg, gap_p, blendloc_p, npointout_p, stat_p) 152 | 153 | npointout = xi.intp_value(npointout_p) 154 | stat = xi.intp_value(stat_p) 155 | 156 | xi.delete_doublep(gap_p) 157 | xi.delete_doublep(blendloc_p) 158 | xi.delete_intp(npointout_p) 159 | xi.delete_intp(stat_p) 160 | 161 | return npointout, stat 162 | 163 | def xfoil_geometry_info(xdg): 164 | 165 | maxt_p = xi.new_doublep() 166 | xmaxt_p = xi.new_doublep() 167 | maxc_p = xi.new_doublep() 168 | xmaxc_p = xi.new_doublep() 169 | stat_p = xi.new_intp() 170 | 171 | xi.xfoil_geometry_info(xdg, maxt_p, xmaxt_p, maxc_p, xmaxc_p, stat_p) 172 | 173 | maxt = xi.doublep_value(maxt_p) 174 | xmaxt = xi.doublep_value(xmaxt_p) 175 | maxc = xi.doublep_value(maxc_p) 176 | xmaxc = xi.doublep_value(xmaxc_p) 177 | stat = xi.intp_value(stat_p) 178 | 179 | xi.delete_doublep(maxt_p) 180 | xi.delete_doublep(xmaxt_p) 181 | xi.delete_doublep(maxc_p) 182 | xi.delete_doublep(xmaxc_p) 183 | xi.delete_intp(stat_p) 184 | 185 | return maxt, xmaxt, maxc, xmaxc, stat 186 | 187 | def xfoil_set_reynolds_number(xdg, re): 188 | 189 | re_p = xi.copy_doublep(re) 190 | 191 | xi.xfoil_set_reynolds_number(xdg, re_p) 192 | 193 | xi.delete_doublep(re_p) 194 | 195 | def xfoil_set_mach_number(xdg, mach): 196 | 197 | mach_p = xi.copy_doublep(mach) 198 | 199 | xi.xfoil_set_mach_number(xdg, mach_p) 200 | 201 | xi.delete_doublep(mach_p) 202 | 203 | def xfoil_reinitialize_bl(xdg): 204 | 205 | xi.xfoil_reinitialize_bl(xdg) 206 | 207 | def xfoil_specal(xdg, alpha_spec): 208 | 209 | alpha_spec_p = xi.copy_doublep(alpha_spec) 210 | alpha_p = xi.new_doublep() 211 | lift_p = xi.new_doublep() 212 | drag_p = xi.new_doublep() 213 | moment_p = xi.new_doublep() 214 | converged_p = xi.new_boolp() 215 | stat_p = xi.new_intp() 216 | 217 | xi.xfoil_specal(xdg, alpha_spec_p, alpha_p, lift_p, drag_p, moment_p, 218 | converged_p, stat_p) 219 | 220 | alpha = xi.doublep_value(alpha_p) 221 | lift = xi.doublep_value(lift_p) 222 | drag = xi.doublep_value(drag_p) 223 | moment = xi.doublep_value(moment_p) 224 | converged = xi.boolp_value(converged_p) 225 | stat = xi.intp_value(stat_p) 226 | 227 | xi.delete_doublep(alpha_spec_p) 228 | xi.delete_doublep(alpha_p) 229 | xi.delete_doublep(lift_p) 230 | xi.delete_doublep(drag_p) 231 | xi.delete_doublep(moment_p) 232 | xi.delete_boolp(converged_p) 233 | xi.delete_intp(stat_p) 234 | 235 | return alpha, lift, drag, moment, converged, stat 236 | 237 | def xfoil_speccl(xdg, cl_spec): 238 | 239 | cl_spec_p = xi.copy_doublep(cl_spec) 240 | alpha_p = xi.new_doublep() 241 | lift_p = xi.new_doublep() 242 | drag_p = xi.new_doublep() 243 | moment_p = xi.new_doublep() 244 | converged_p = xi.new_boolp() 245 | stat_p = xi.new_intp() 246 | 247 | xi.xfoil_speccl(xdg, cl_spec_p, alpha_p, lift_p, drag_p, moment_p, 248 | converged_p, stat_p) 249 | 250 | alpha = xi.doublep_value(alpha_p) 251 | lift = xi.doublep_value(lift_p) 252 | drag = xi.doublep_value(drag_p) 253 | moment = xi.doublep_value(moment_p) 254 | converged = xi.boolp_value(converged_p) 255 | stat = xi.intp_value(stat_p) 256 | 257 | xi.delete_doublep(cl_spec_p) 258 | xi.delete_doublep(alpha_p) 259 | xi.delete_doublep(lift_p) 260 | xi.delete_doublep(drag_p) 261 | xi.delete_doublep(moment_p) 262 | xi.delete_boolp(converged_p) 263 | xi.delete_intp(stat_p) 264 | 265 | return alpha, lift, drag, moment, converged, stat 266 | 267 | def xfoil_get_transloc(xdg): 268 | 269 | xtranst_p = xi.new_doublep() 270 | ztranst_p = xi.new_doublep() 271 | xtransb_p = xi.new_doublep() 272 | ztransb_p = xi.new_doublep() 273 | 274 | xi.xfoil_get_transloc(xdg, xtranst_p, ztranst_p, xtransb_p, ztransb_p) 275 | 276 | xtranst = xi.doublep_value(xtranst_p) 277 | ztranst = xi.doublep_value(ztranst_p) 278 | xtransb = xi.doublep_value(xtransb_p) 279 | ztransb = xi.doublep_value(ztransb_p) 280 | 281 | xi.delete_doublep(xtranst_p) 282 | xi.delete_doublep(ztranst_p) 283 | xi.delete_doublep(xtransb_p) 284 | xi.delete_doublep(ztransb_p) 285 | 286 | return xtranst, ztranst, xtransb, ztransb 287 | 288 | def xfoil_get_cp(xdg, npoint): 289 | 290 | npoint_p = xi.copy_intp(npoint) 291 | cp_a = xi.new_doublea(npoint) 292 | 293 | xi.xfoil_get_cp(xdg, npoint_p, cp_a) 294 | 295 | cp = npoint*[0] 296 | for i in range(npoint): 297 | cp[i] = xi.doublea_getitem(cp_a, i) 298 | 299 | xi.delete_intp(npoint_p) 300 | xi.delete_doublea(cp_a) 301 | 302 | return cp 303 | 304 | def xfoil_get_cf(xdg, npoint): 305 | 306 | npoint_p = xi.copy_intp(npoint) 307 | cf_a = xi.new_doublea(npoint) 308 | 309 | xi.xfoil_get_cf(xdg, npoint_p, cf_a) 310 | 311 | cf = npoint*[0] 312 | for i in range(npoint): 313 | cf[i] = xi.doublea_getitem(cf_a, i) 314 | 315 | xi.delete_intp(npoint_p) 316 | xi.delete_doublea(cf_a) 317 | 318 | return cf 319 | 320 | def xfoil_get_uedge(xdg, npoint): 321 | 322 | npoint_p = xi.copy_intp(npoint) 323 | uedge_a = xi.new_doublea(npoint) 324 | 325 | xi.xfoil_get_uedge(xdg, npoint_p, uedge_a) 326 | 327 | uedge = npoint*[0] 328 | for i in range(npoint): 329 | uedge[i] = xi.doublea_getitem(uedge_a, i) 330 | 331 | xi.delete_intp(npoint_p) 332 | xi.delete_doublea(uedge_a) 333 | 334 | return uedge 335 | 336 | def xfoil_get_deltastar(xdg, npoint): 337 | 338 | npoint_p = xi.copy_intp(npoint) 339 | deltastar_a = xi.new_doublea(npoint) 340 | 341 | xi.xfoil_get_deltastar(xdg, npoint_p, deltastar_a) 342 | 343 | deltastar = npoint*[0] 344 | for i in range(npoint): 345 | deltastar[i] = xi.doublea_getitem(deltastar_a, i) 346 | 347 | xi.delete_intp(npoint_p) 348 | xi.delete_doublea(deltastar_a) 349 | 350 | return deltastar 351 | 352 | def xfoil_get_diss(xdg, npoint): 353 | 354 | npoint_p = xi.copy_intp(npoint) 355 | diss_a = xi.new_doublea(npoint) 356 | 357 | xi.xfoil_get_diss(xdg, npoint_p, diss_a) 358 | 359 | diss = npoint*[0] 360 | for i in range(npoint): 361 | diss[i] = xi.doublea_getitem(diss_a, i) 362 | 363 | xi.delete_intp(npoint_p) 364 | xi.delete_doublea(diss_a) 365 | 366 | return diss 367 | 368 | def xfoil_get_hk(xdg, npoint): 369 | 370 | npoint_p = xi.copy_intp(npoint) 371 | hk_a = xi.new_doublea(npoint) 372 | 373 | xi.xfoil_get_hk(xdg, npoint_p, hk_a) 374 | 375 | hk = npoint*[0] 376 | for i in range(npoint): 377 | hk[i] = xi.doublea_getitem(hk_a, i) 378 | 379 | xi.delete_intp(npoint_p) 380 | xi.delete_doublea(hk_a) 381 | 382 | return hk 383 | 384 | def xfoil_get_retheta(xdg, npoint): 385 | 386 | npoint_p = xi.copy_intp(npoint) 387 | retheta_a = xi.new_doublea(npoint) 388 | 389 | xi.xfoil_get_retheta(xdg, npoint_p, retheta_a) 390 | 391 | retheta = npoint*[0] 392 | for i in range(npoint): 393 | retheta[i] = xi.doublea_getitem(retheta_a, i) 394 | 395 | xi.delete_intp(npoint_p) 396 | xi.delete_doublea(retheta_a) 397 | 398 | return retheta 399 | 400 | def xfoil_get_ampl(xdg, npoint): 401 | 402 | npoint_p = xi.copy_intp(npoint) 403 | ampl_a = xi.new_doublea(npoint) 404 | 405 | xi.xfoil_get_ampl(xdg, npoint_p, ampl_a) 406 | 407 | ampl = npoint*[0] 408 | for i in range(npoint): 409 | ampl[i] = xi.doublea_getitem(ampl_a, i) 410 | 411 | xi.delete_intp(npoint_p) 412 | xi.delete_doublea(ampl_a) 413 | 414 | return ampl 415 | 416 | def xfoil_get_wakepoints(xdg): 417 | 418 | nwake_p = xi.new_intp() 419 | 420 | xi.xfoil_get_wakepoints(xdg, nwake_p) 421 | 422 | nwake = xi.intp_value(nwake_p) 423 | xi.delete_intp(nwake_p) 424 | 425 | return nwake 426 | 427 | def xfoil_get_wake_geometry(xdg, nwake): 428 | 429 | nwake_p = xi.copy_intp(nwake) 430 | xw_a = xi.new_doublea(nwake) 431 | zw_a = xi.new_doublea(nwake) 432 | 433 | xi.xfoil_get_wake_geometry(xdg, nwake_p, xw_a, zw_a) 434 | 435 | xw = nwake*[0] 436 | zw = nwake*[0] 437 | for i in range(nwake): 438 | xw[i] = xi.doublea_getitem(xw_a, i) 439 | zw[i] = xi.doublea_getitem(zw_a, i) 440 | 441 | xi.delete_intp(nwake_p) 442 | xi.delete_doublea(xw_a) 443 | xi.delete_doublea(zw_a) 444 | 445 | return xw, zw 446 | 447 | def xfoil_get_wake_cp(xdg, nwake): 448 | 449 | nwake_p = xi.copy_intp(nwake) 450 | cp_a = xi.new_doublea(nwake) 451 | 452 | xi.xfoil_get_wake_cp(xdg, nwake_p, cp_a) 453 | 454 | cp = nwake*[0] 455 | for i in range(nwake): 456 | cp[i] = xi.doublea_getitem(cp_a, i) 457 | 458 | xi.delete_intp(nwake_p) 459 | xi.delete_doublea(cp_a) 460 | 461 | return cp 462 | 463 | def xfoil_get_wake_uedge(xdg, nwake): 464 | 465 | nwake_p = xi.copy_intp(nwake) 466 | uedge_a = xi.new_doublea(nwake) 467 | 468 | xi.xfoil_get_wake_uedge(xdg, nwake_p, uedge_a) 469 | 470 | uedge = nwake*[0] 471 | for i in range(nwake): 472 | uedge[i] = xi.doublea_getitem(uedge_a, i) 473 | 474 | xi.delete_intp(nwake_p) 475 | xi.delete_doublea(uedge_a) 476 | 477 | return uedge 478 | 479 | def xfoil_get_wake_deltastar(xdg, nwake): 480 | 481 | nwake_p = xi.copy_intp(nwake) 482 | deltastar_a = xi.new_doublea(nwake) 483 | 484 | xi.xfoil_get_wake_deltastar(xdg, nwake_p, deltastar_a) 485 | 486 | deltastar = nwake*[0] 487 | for i in range(nwake): 488 | deltastar[i] = xi.doublea_getitem(deltastar_a, i) 489 | 490 | xi.delete_intp(nwake_p) 491 | xi.delete_doublea(deltastar_a) 492 | 493 | return deltastar 494 | 495 | def run_xfoil(npointin, xin, zin, geom_opts, noppoint, operating_points, 496 | op_modes, reynolds_numbers, mach_numbers, use_flap, x_flap, 497 | z_flap, z_flap_spec, flap_degrees, xfoil_opts, reinitialize, 498 | fix_unconverged): 499 | 500 | npointin_p = xi.copy_intp(npointin) 501 | xin_a = xi.new_doublea(npointin) 502 | zin_a = xi.new_doublea(npointin) 503 | noppoint_p = xi.copy_intp(noppoint) 504 | operating_points_a = xi.new_doublea(noppoint) 505 | op_modes_a = xi.new_inta(noppoint) 506 | reynolds_numbers_a = xi.new_doublea(noppoint) 507 | mach_numbers_a = xi.new_doublea(noppoint) 508 | use_flap_p = xi.copy_boolp(use_flap) 509 | if use_flap: 510 | x_flap_p = xi.copy_doublep(x_flap) 511 | z_flap_p = xi.copy_doublep(z_flap) 512 | z_flap_spec_p = xi.copy_intp(z_flap_spec) 513 | else: 514 | x_flap_p = xi.new_doublep() 515 | z_flap_p = xi.new_doublep() 516 | z_flap_spec_p = xi.new_intp() 517 | flap_degrees_a = xi.new_doublea(noppoint) 518 | reinitialize_p = xi.copy_boolp(reinitialize) 519 | fix_unconverged_p = xi.copy_boolp(fix_unconverged) 520 | lift_a = xi.new_doublea(noppoint) 521 | drag_a = xi.new_doublea(noppoint) 522 | moment_a = xi.new_doublea(noppoint) 523 | viscrms_a = xi.new_doublea(noppoint) 524 | alpha_a = xi.new_doublea(noppoint) 525 | xtrt_a = xi.new_doublea(noppoint) 526 | xtrb_a = xi.new_doublea(noppoint) 527 | stat_p = xi.new_intp() 528 | 529 | for i in range(npointin): 530 | xi.doublea_setitem(xin_a, i, xin[i]) 531 | xi.doublea_setitem(zin_a, i, zin[i]) 532 | for i in range(noppoint): 533 | xi.doublea_setitem(operating_points_a, i, operating_points[i]) 534 | xi.inta_setitem(op_modes_a, i, op_modes[i]) 535 | xi.doublea_setitem(reynolds_numbers_a, i, reynolds_numbers[i]) 536 | xi.doublea_setitem(mach_numbers_a, i, mach_numbers[i]) 537 | if use_flap: 538 | xi.doublea_setitem(flap_degrees_a, i, flap_degrees[i]) 539 | 540 | xi.run_xfoil(npointin_p, xin_a, zin_a, geom_opts, noppoint_p, 541 | operating_points_a, op_modes_a, reynolds_numbers_a, 542 | mach_numbers_a, use_flap_p, x_flap_p, z_flap_p, z_flap_spec_p, 543 | flap_degrees_a, xfoil_opts, reinitialize_p, fix_unconverged_p, 544 | lift_a, drag_a, moment_a, viscrms_a, alpha_a, xtrt_a, xtrb_a, 545 | stat_p) 546 | 547 | stat = xi.intp_value(stat_p) 548 | lift = noppoint*[0] 549 | drag = noppoint*[0] 550 | moment = noppoint*[0] 551 | viscrms = noppoint*[0] 552 | alpha = noppoint*[0] 553 | xtrt = noppoint*[0] 554 | xtrb = noppoint*[0] 555 | for i in range(noppoint): 556 | lift[i] = xi.doublea_getitem(lift_a, i) 557 | drag[i] = xi.doublea_getitem(drag_a, i) 558 | moment[i] = xi.doublea_getitem(moment_a, i) 559 | viscrms[i] = xi.doublea_getitem(viscrms_a, i) 560 | alpha[i] = xi.doublea_getitem(alpha_a, i) 561 | xtrt[i] = xi.doublea_getitem(xtrt_a, i) 562 | xtrb[i] = xi.doublea_getitem(xtrb_a, i) 563 | 564 | xi.delete_intp(npointin_p) 565 | xi.delete_doublea(xin_a) 566 | xi.delete_doublea(zin_a) 567 | xi.delete_intp(noppoint_p) 568 | xi.delete_doublea(operating_points_a) 569 | xi.delete_inta(op_modes_a) 570 | xi.delete_doublea(reynolds_numbers_a) 571 | xi.delete_doublea(mach_numbers_a) 572 | xi.delete_boolp(use_flap_p) 573 | xi.delete_doublep(x_flap_p) 574 | xi.delete_doublep(z_flap_p) 575 | xi.delete_intp(z_flap_spec_p) 576 | xi.delete_doublea(flap_degrees_a) 577 | xi.delete_doublea(lift_a) 578 | xi.delete_doublea(drag_a) 579 | xi.delete_doublea(moment_a) 580 | xi.delete_doublea(viscrms_a) 581 | xi.delete_doublea(alpha_a) 582 | xi.delete_doublea(xtrt_a) 583 | xi.delete_doublea(xtrb_a) 584 | xi.delete_intp(stat_p) 585 | 586 | return lift, drag, moment, viscrms, alpha, xtrt, xtrb, stat 587 | 588 | def naca_4_digit(camber, xcamber, thick, npointside): 589 | 590 | camber_p = xi.copy_doublep(camber) 591 | xcamber_p = xi.copy_doublep(xcamber) 592 | thick_p = xi.copy_doublep(thick) 593 | npointside_p = xi.copy_intp(npointside) 594 | xout_a = xi.new_doublea(2*npointside) 595 | zout_a = xi.new_doublea(2*npointside) 596 | nout_p = xi.new_intp() 597 | 598 | xi.naca_4_digit(camber_p, xcamber_p, thick_p, npointside_p, xout_a, zout_a, 599 | nout_p) 600 | 601 | nout = xi.intp_value(nout_p) 602 | xout = nout*[0] 603 | zout = nout*[0] 604 | for i in range(nout): 605 | xout[i] = xi.doublea_getitem(xout_a, i) 606 | zout[i] = xi.doublea_getitem(zout_a, i) 607 | 608 | xi.delete_doublep(camber_p) 609 | xi.delete_doublep(xcamber_p) 610 | xi.delete_doublep(thick_p) 611 | xi.delete_intp(npointside_p) 612 | xi.delete_doublea(xout_a) 613 | xi.delete_doublea(zout_a) 614 | xi.delete_intp(nout_p) 615 | 616 | return xout, zout, nout 617 | 618 | def naca_5_digit(des, npointside): 619 | 620 | npointside_p = xi.copy_intp(npointside) 621 | xout_a = xi.new_doublea(2*npointside) 622 | zout_a = xi.new_doublea(2*npointside) 623 | nout_p = xi.new_intp() 624 | stat_p = xi.new_intp() 625 | 626 | xi.naca_5_digit(des, npointside_p, xout_a, zout_a, nout_p, stat_p) 627 | 628 | nout = xi.intp_value(nout_p) 629 | stat = xi.intp_value(stat_p) 630 | if stat != 0: 631 | nout = 1 632 | xout = nout*[0] 633 | zout = nout*[0] 634 | for i in range(nout): 635 | xout[i] = xi.doublea_getitem(xout_a, i) 636 | zout[i] = xi.doublea_getitem(zout_a, i) 637 | 638 | xi.delete_intp(npointside_p) 639 | xi.delete_doublea(xout_a) 640 | xi.delete_doublea(zout_a) 641 | xi.delete_intp(nout_p) 642 | xi.delete_intp(stat_p) 643 | 644 | return xout, zout, nout, stat 645 | 646 | def xfoil_spline_coordinates(x, z, npt): 647 | 648 | x_a = xi.new_doublea(npt) 649 | z_a = xi.new_doublea(npt) 650 | npt_p = xi.copy_intp(npt) 651 | s_a = xi.new_doublea(npt) 652 | xs_a = xi.new_doublea(npt) 653 | zs_a = xi.new_doublea(npt) 654 | for i in range(npt): 655 | xi.doublea_setitem(x_a, i, x[i]) 656 | xi.doublea_setitem(z_a, i, z[i]) 657 | 658 | xi.xfoil_spline_coordinates(x_a, z_a, npt_p, s_a, xs_a, zs_a) 659 | 660 | s = npt*[0] 661 | xs = npt*[0] 662 | zs = npt*[0] 663 | for i in range(npt): 664 | s[i] = xi.doublea_getitem(s_a, i) 665 | xs[i] = xi.doublea_getitem(xs_a, i) 666 | zs[i] = xi.doublea_getitem(zs_a, i) 667 | 668 | xi.delete_doublea(x_a) 669 | xi.delete_doublea(z_a) 670 | xi.delete_intp(npt_p) 671 | xi.delete_doublea(s_a) 672 | xi.delete_doublea(xs_a) 673 | xi.delete_doublea(zs_a) 674 | 675 | return s, xs, zs 676 | 677 | def xfoil_eval_spline(x, z, s, xs, zs, npt, sc): 678 | 679 | x_a = xi.new_doublea(npt) 680 | z_a = xi.new_doublea(npt) 681 | s_a = xi.new_doublea(npt) 682 | xs_a = xi.new_doublea(npt) 683 | zs_a = xi.new_doublea(npt) 684 | npt_p = xi.copy_intp(npt) 685 | sc_p = xi.copy_doublep(sc) 686 | xc_p = xi.new_doublep() 687 | zc_p = xi.new_doublep() 688 | for i in range(npt): 689 | xi.doublea_setitem(x_a, i, x[i]) 690 | xi.doublea_setitem(z_a, i, z[i]) 691 | xi.doublea_setitem(s_a, i, s[i]) 692 | xi.doublea_setitem(xs_a, i, xs[i]) 693 | xi.doublea_setitem(zs_a, i, zs[i]) 694 | 695 | xi.xfoil_eval_spline(x_a, z_a, s_a, xs_a, zs_a, npt_p, sc_p, xc_p, zc_p) 696 | 697 | xc = xi.doublep_value(xc_p) 698 | zc = xi.doublep_value(zc_p) 699 | 700 | xi.delete_doublea(x_a) 701 | xi.delete_doublea(z_a) 702 | xi.delete_doublea(s_a) 703 | xi.delete_doublea(xs_a) 704 | xi.delete_doublea(zs_a) 705 | xi.delete_doublep(sc_p) 706 | xi.delete_doublep(xc_p) 707 | xi.delete_doublep(zc_p) 708 | 709 | return xc, zc 710 | 711 | def xfoil_lefind(x, z, s, xs, zs, npt): 712 | 713 | x_a = xi.new_doublea(npt) 714 | z_a = xi.new_doublea(npt) 715 | s_a = xi.new_doublea(npt) 716 | xs_a = xi.new_doublea(npt) 717 | zs_a = xi.new_doublea(npt) 718 | npt_p = xi.copy_intp(npt) 719 | sle_p = xi.new_doublep() 720 | xle_p = xi.new_doublep() 721 | zle_p = xi.new_doublep() 722 | for i in range(npt): 723 | xi.doublea_setitem(x_a, i, x[i]) 724 | xi.doublea_setitem(z_a, i, z[i]) 725 | xi.doublea_setitem(s_a, i, s[i]) 726 | xi.doublea_setitem(xs_a, i, xs[i]) 727 | xi.doublea_setitem(zs_a, i, zs[i]) 728 | 729 | xi.xfoil_lefind(x_a, z_a, s_a, xs_a, zs_a, npt_p, sle_p, xle_p, zle_p) 730 | 731 | sle = xi.doublep_value(sle_p) 732 | xle = xi.doublep_value(xle_p) 733 | zle = xi.doublep_value(zle_p) 734 | 735 | xi.delete_doublea(x_a) 736 | xi.delete_doublea(z_a) 737 | xi.delete_doublea(s_a) 738 | xi.delete_doublea(xs_a) 739 | xi.delete_doublea(zs_a) 740 | xi.delete_doublep(sle_p) 741 | xi.delete_doublep(xle_p) 742 | xi.delete_doublep(zle_p) 743 | 744 | return sle, xle, zle 745 | -------------------------------------------------------------------------------- /src/memory.c: -------------------------------------------------------------------------------- 1 | /* This file is part of libxfoil. 2 | 3 | libxfoil is free software: you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation, either version 3 of the License, or 6 | (at your option) any later version. 7 | 8 | libxfoil is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with libxfoil. If not, see . 15 | 16 | Copyright (C) 2019 Daniel Prosser 17 | 18 | See libxfoil.f90 for descriptions of inputs and outputs. */ 19 | 20 | #include 21 | #include 22 | #include "libxfoil.h" 23 | 24 | /******************************************************************************/ 25 | // 26 | // Allocates memory for structs in xfoil_data_group. This is the C backend 27 | // for the xfoil_init library method. 28 | // 29 | /******************************************************************************/ 30 | void allocate_xdg(xfoil_data_group *xdg) 31 | { 32 | xdg->xfd.GAM = malloc(IQX*sizeof(double)); 33 | xdg->xfd.GAMU = malloc(IQX*2*sizeof(double)); 34 | xdg->xfd.QINVU = malloc(IZX*2*sizeof(double)); 35 | xdg->xfd.GAM_A = malloc(IQX*sizeof(double)); 36 | xdg->xfd.QINV = malloc(IZX*sizeof(double)); 37 | xdg->xfd.QINV_A = malloc(IZX*sizeof(double)); 38 | xdg->xfd.AIJ = malloc(IQX*IQX*sizeof(double)); 39 | xdg->xfd.BIJ = malloc(IQX*IZX*sizeof(double)); 40 | xdg->xfd.DIJ = malloc(IZX*IZX*sizeof(double)); 41 | xdg->xfd.CIJ = malloc(IWX*IQX*sizeof(double)); 42 | xdg->xfd.DZDG = malloc(IQX*sizeof(double)); 43 | xdg->xfd.DZDN = malloc(IQX*sizeof(double)); 44 | xdg->xfd.DQDG = malloc(IQX*sizeof(double)); 45 | xdg->xfd.DZDM = malloc(IZX*sizeof(double)); 46 | xdg->xfd.DQDM = malloc(IZX*sizeof(double)); 47 | xdg->xfd.X = malloc(IZX*sizeof(double)); 48 | xdg->xfd.Y = malloc(IZX*sizeof(double)); 49 | xdg->xfd.NX = malloc(IZX*sizeof(double)); 50 | xdg->xfd.NY = malloc(IZX*sizeof(double)); 51 | xdg->xfd.S = malloc(IZX*sizeof(double)); 52 | xdg->xfd.APANEL = malloc(IZX*sizeof(double)); 53 | xdg->xfd.SIG = malloc(IZX*sizeof(double)); 54 | xdg->xfd.XP = malloc(IZX*sizeof(double)); 55 | xdg->xfd.YP = malloc(IZX*sizeof(double)); 56 | xdg->xfd.QF0 = malloc(IQX*sizeof(double)); 57 | xdg->xfd.QF1 = malloc(IQX*sizeof(double)); 58 | xdg->xfd.QF2 = malloc(IQX*sizeof(double)); 59 | xdg->xfd.QF3 = malloc(IQX*sizeof(double)); 60 | xdg->xfd.AIJPIV = malloc(IQX*sizeof(int)); 61 | xdg->xfd.IBLTE = malloc(ISX*sizeof(int)); 62 | xdg->xfd.NBL = malloc(ISX*sizeof(int)); 63 | xdg->xfd.IPAN = malloc(IVX*ISX*sizeof(int)); 64 | xdg->xfd.ISYS = malloc(IVX*ISX*sizeof(int)); 65 | xdg->xfd.XB = malloc(IBX*sizeof(double)); 66 | xdg->xfd.YB = malloc(IBX*sizeof(double)); 67 | xdg->xfd.SB = malloc(IBX*sizeof(double)); 68 | xdg->xfd.XBP = malloc(IBX*sizeof(double)); 69 | xdg->xfd.YBP = malloc(IBX*sizeof(double)); 70 | xdg->xfd.SNEW = malloc(5*IBX*sizeof(double)); 71 | xdg->xfd.W1 = malloc(6*IQX*sizeof(double)); 72 | xdg->xfd.W2 = malloc(6*IQX*sizeof(double)); 73 | xdg->xfd.W3 = malloc(6*IQX*sizeof(double)); 74 | xdg->xfd.W4 = malloc(6*IQX*sizeof(double)); 75 | xdg->xfd.W5 = malloc(6*IQX*sizeof(double)); 76 | xdg->xfd.W6 = malloc(6*IQX*sizeof(double)); 77 | xdg->xfd.CPI = malloc(IZX*sizeof(double)); 78 | xdg->xfd.CPV = malloc(IZX*sizeof(double)); 79 | xdg->xfd.QVIS = malloc(IZX*sizeof(double)); 80 | xdg->xfd.VTI = malloc(IVX*ISX*sizeof(double)); 81 | xdg->xfd.XSSI = malloc(IVX*ISX*sizeof(double)); 82 | xdg->xfd.WGAP = malloc(IWX*sizeof(double)); 83 | xdg->xfd.XSTRIP = malloc(ISX*sizeof(double)); 84 | xdg->xfd.XSSITR = malloc(ISX*sizeof(double)); 85 | xdg->xfd.UINV = malloc(IVX*ISX*sizeof(double)); 86 | xdg->xfd.UINV_A = malloc(IVX*ISX*sizeof(double)); 87 | xdg->xfd.UEDG = malloc(IVX*ISX*sizeof(double)); 88 | xdg->xfd.THET = malloc(IVX*ISX*sizeof(double)); 89 | xdg->xfd.DSTR = malloc(IVX*ISX*sizeof(double)); 90 | xdg->xfd.CTAU = malloc(IVX*ISX*sizeof(double)); 91 | xdg->xfd.MASS = malloc(IVX*ISX*sizeof(double)); 92 | xdg->xfd.TAU = malloc(IVX*ISX*sizeof(double)); 93 | xdg->xfd.DIS = malloc(IVX*ISX*sizeof(double)); 94 | xdg->xfd.CTQ = malloc(IVX*ISX*sizeof(double)); 95 | xdg->xfd.DELT = malloc(IVX*ISX*sizeof(double)); 96 | xdg->xfd.TSTR = malloc(IVX*ISX*sizeof(double)); 97 | xdg->xfd.USLP = malloc(IVX*ISX*sizeof(double)); 98 | xdg->xfd.ITRAN = malloc(ISX*sizeof(int)); 99 | xdg->xfd.TFORCE = malloc(ISX*sizeof(bool)); 100 | xdg->xfd.VM = malloc(3*IZX*IZX*sizeof(double)); 101 | xdg->xfd.VA = malloc(3*2*IZX*sizeof(double)); 102 | xdg->xfd.VB = malloc(3*2*IZX*sizeof(double)); 103 | xdg->xfd.VDEL = malloc(3*2*IZX*sizeof(double)); 104 | xdg->xfd.VZ = malloc(3*2*sizeof(double)); 105 | xdg->xfd.XOCTR = malloc(ISX*sizeof(double)); 106 | xdg->xfd.YOCTR = malloc(ISX*sizeof(double)); 107 | xdg->xfd.UNEW = malloc(IVX*2*sizeof(double)); 108 | xdg->xfd.U_AC = malloc(IVX*2*sizeof(double)); 109 | xdg->xfd.QNEW = malloc(IQX*sizeof(double)); 110 | xdg->xfd.Q_AC = malloc(IQX*sizeof(double)); 111 | xdg->xbd.C1SAV = malloc(NCOM*sizeof(double)); 112 | xdg->xbd.C2SAV = malloc(NCOM*sizeof(double)); 113 | xdg->xbd.VS1 = malloc(4*5*sizeof(double)); 114 | xdg->xbd.VS2 = malloc(4*5*sizeof(double)); 115 | xdg->xbd.VSREZ = malloc(4*sizeof(double)); 116 | xdg->xbd.VSR = malloc(4*sizeof(double)); 117 | xdg->xbd.VSM = malloc(4*sizeof(double)); 118 | xdg->xbd.VSX = malloc(4*sizeof(double)); 119 | } 120 | 121 | /******************************************************************************/ 122 | // 123 | // Frees memory for structs in xfoil_data_group. This is the C backend for the 124 | // for the xfoil_cleanup library method. 125 | // 126 | /******************************************************************************/ 127 | void free_xdg(xfoil_data_group *xdg) 128 | { 129 | free(xdg->xfd.GAM); 130 | free(xdg->xfd.GAMU); 131 | free(xdg->xfd.QINVU); 132 | free(xdg->xfd.GAM_A); 133 | free(xdg->xfd.QINV); 134 | free(xdg->xfd.QINV_A); 135 | free(xdg->xfd.AIJ); 136 | free(xdg->xfd.BIJ); 137 | free(xdg->xfd.DIJ); 138 | free(xdg->xfd.CIJ); 139 | free(xdg->xfd.DZDG); 140 | free(xdg->xfd.DZDN); 141 | free(xdg->xfd.DQDG); 142 | free(xdg->xfd.DZDM); 143 | free(xdg->xfd.DQDM); 144 | free(xdg->xfd.X); 145 | free(xdg->xfd.Y); 146 | free(xdg->xfd.NX); 147 | free(xdg->xfd.NY); 148 | free(xdg->xfd.S); 149 | free(xdg->xfd.APANEL); 150 | free(xdg->xfd.SIG); 151 | free(xdg->xfd.XP); 152 | free(xdg->xfd.YP); 153 | free(xdg->xfd.QF0); 154 | free(xdg->xfd.QF1); 155 | free(xdg->xfd.QF2); 156 | free(xdg->xfd.QF3); 157 | free(xdg->xfd.AIJPIV); 158 | free(xdg->xfd.IBLTE); 159 | free(xdg->xfd.NBL); 160 | free(xdg->xfd.IPAN); 161 | free(xdg->xfd.ISYS); 162 | free(xdg->xfd.XB); 163 | free(xdg->xfd.YB); 164 | free(xdg->xfd.SB); 165 | free(xdg->xfd.XBP); 166 | free(xdg->xfd.YBP); 167 | free(xdg->xfd.SNEW); 168 | free(xdg->xfd.W1); 169 | free(xdg->xfd.W2); 170 | free(xdg->xfd.W3); 171 | free(xdg->xfd.W4); 172 | free(xdg->xfd.W5); 173 | free(xdg->xfd.W6); 174 | free(xdg->xfd.CPI); 175 | free(xdg->xfd.CPV); 176 | free(xdg->xfd.QVIS); 177 | free(xdg->xfd.VTI); 178 | free(xdg->xfd.XSSI); 179 | free(xdg->xfd.WGAP); 180 | free(xdg->xfd.XSTRIP); 181 | free(xdg->xfd.XSSITR); 182 | free(xdg->xfd.UINV); 183 | free(xdg->xfd.UINV_A); 184 | free(xdg->xfd.UEDG); 185 | free(xdg->xfd.THET); 186 | free(xdg->xfd.DSTR); 187 | free(xdg->xfd.CTAU); 188 | free(xdg->xfd.MASS); 189 | free(xdg->xfd.TAU); 190 | free(xdg->xfd.DIS); 191 | free(xdg->xfd.CTQ); 192 | free(xdg->xfd.DELT); 193 | free(xdg->xfd.TSTR); 194 | free(xdg->xfd.USLP); 195 | free(xdg->xfd.ITRAN); 196 | free(xdg->xfd.TFORCE); 197 | free(xdg->xfd.VM); 198 | free(xdg->xfd.VA); 199 | free(xdg->xfd.VB); 200 | free(xdg->xfd.VDEL); 201 | free(xdg->xfd.VZ); 202 | free(xdg->xfd.XOCTR); 203 | free(xdg->xfd.YOCTR); 204 | free(xdg->xfd.UNEW); 205 | free(xdg->xfd.U_AC); 206 | free(xdg->xfd.QNEW); 207 | free(xdg->xfd.Q_AC); 208 | free(xdg->xbd.C1SAV); 209 | free(xdg->xbd.C2SAV); 210 | free(xdg->xbd.VS1); 211 | free(xdg->xbd.VS2); 212 | free(xdg->xbd.VSREZ); 213 | free(xdg->xbd.VSR); 214 | free(xdg->xbd.VSM); 215 | free(xdg->xbd.VSX); 216 | } 217 | 218 | /******************************************************************************/ 219 | // 220 | // Copies everything in xdg_from to xdg_to. xfoil_init must have been already 221 | // called for both. 222 | // 223 | /******************************************************************************/ 224 | void copy_xdg(xfoil_data_group *xdg_from, xfoil_data_group *xdg_to) 225 | { 226 | int i; 227 | 228 | xdg_to->xfd.PI = xdg_from->xfd.PI; 229 | xdg_to->xfd.HOPI = xdg_from->xfd.HOPI; 230 | xdg_to->xfd.QOPI = xdg_from->xfd.QOPI; 231 | xdg_to->xfd.DTOR = xdg_from->xfd.DTOR; 232 | xdg_to->xfd.SILENT_MODE = xdg_from->xfd.SILENT_MODE; 233 | xdg_to->xfd.VISCOUS_MODE = xdg_from->xfd.VISCOUS_MODE; 234 | xdg_to->xfd.MAXIT = xdg_from->xfd.MAXIT; 235 | xdg_to->xfd.LGAMU = xdg_from->xfd.LGAMU; 236 | xdg_to->xfd.LQAIJ = xdg_from->xfd.LQAIJ; 237 | xdg_to->xfd.SHARP = xdg_from->xfd.SHARP; 238 | xdg_to->xfd.LVISC = xdg_from->xfd.LVISC; 239 | xdg_to->xfd.LWAKE = xdg_from->xfd.LWAKE; 240 | xdg_to->xfd.LVCONV = xdg_from->xfd.LVCONV; 241 | xdg_to->xfd.LWDIJ = xdg_from->xfd.LWDIJ; 242 | xdg_to->xfd.LIPAN = xdg_from->xfd.LIPAN; 243 | xdg_to->xfd.LBLINI = xdg_from->xfd.LBLINI; 244 | xdg_to->xfd.LADIJ = xdg_from->xfd.LADIJ; 245 | xdg_to->xfd.LALFA = xdg_from->xfd.LALFA; 246 | xdg_to->xfd.RETYP = xdg_from->xfd.RETYP; 247 | xdg_to->xfd.MATYP = xdg_from->xfd.MATYP; 248 | xdg_to->xfd.ITMAX = xdg_from->xfd.ITMAX; 249 | xdg_to->xfd.N = xdg_from->xfd.N; 250 | xdg_to->xfd.NB = xdg_from->xfd.NB; 251 | xdg_to->xfd.NPAN = xdg_from->xfd.NPAN; 252 | xdg_to->xfd.NW = xdg_from->xfd.NW; 253 | xdg_to->xfd.IST = xdg_from->xfd.IST; 254 | xdg_to->xfd.NSYS = xdg_from->xfd.NSYS; 255 | xdg_to->xfd.PSIO = xdg_from->xfd.PSIO; 256 | xdg_to->xfd.QINF = xdg_from->xfd.QINF; 257 | xdg_to->xfd.ALFA = xdg_from->xfd.ALFA; 258 | xdg_to->xfd.Z_QINF = xdg_from->xfd.Z_QINF; 259 | xdg_to->xfd.Z_ALFA = xdg_from->xfd.Z_ALFA; 260 | xdg_to->xfd.Z_QDOF0 = xdg_from->xfd.Z_QDOF0; 261 | xdg_to->xfd.Z_QDOF1 = xdg_from->xfd.Z_QDOF1; 262 | xdg_to->xfd.Z_QDOF2 = xdg_from->xfd.Z_QDOF2; 263 | xdg_to->xfd.Z_QDOF3 = xdg_from->xfd.Z_QDOF3; 264 | xdg_to->xfd.ANTE = xdg_from->xfd.ANTE; 265 | xdg_to->xfd.ASTE = xdg_from->xfd.ASTE; 266 | xdg_to->xfd.DSTE = xdg_from->xfd.DSTE; 267 | xdg_to->xfd.ADEG = xdg_from->xfd.ADEG; 268 | xdg_to->xfd.AMAX = xdg_from->xfd.AMAX; 269 | xdg_to->xfd.SIGTE = xdg_from->xfd.SIGTE; 270 | xdg_to->xfd.GAMTE = xdg_from->xfd.GAMTE; 271 | xdg_to->xfd.SIGTE_A = xdg_from->xfd.SIGTE_A; 272 | xdg_to->xfd.GAMTE_A = xdg_from->xfd.GAMTE_A; 273 | xdg_to->xfd.MINF = xdg_from->xfd.MINF; 274 | xdg_to->xfd.MINF1 = xdg_from->xfd.MINF1; 275 | xdg_to->xfd.REINF = xdg_from->xfd.REINF; 276 | xdg_to->xfd.REINF1 = xdg_from->xfd.REINF1; 277 | xdg_to->xfd.TKLAM = xdg_from->xfd.TKLAM; 278 | xdg_to->xfd.TKL_MSQ = xdg_from->xfd.TKL_MSQ; 279 | xdg_to->xfd.CPSTAR = xdg_from->xfd.CPSTAR; 280 | xdg_to->xfd.QSTAR = xdg_from->xfd.QSTAR; 281 | xdg_to->xfd.GAMMA = xdg_from->xfd.GAMMA; 282 | xdg_to->xfd.GAMM1 = xdg_from->xfd.GAMM1; 283 | xdg_to->xfd.XCMREF = xdg_from->xfd.XCMREF; 284 | xdg_to->xfd.YCMREF = xdg_from->xfd.YCMREF; 285 | xdg_to->xfd.CL = xdg_from->xfd.CL; 286 | xdg_to->xfd.CM = xdg_from->xfd.CM; 287 | xdg_to->xfd.CD = xdg_from->xfd.CD; 288 | xdg_to->xfd.CDP = xdg_from->xfd.CDP; 289 | xdg_to->xfd.CDF = xdg_from->xfd.CDF; 290 | xdg_to->xfd.CL_ALF = xdg_from->xfd.CL_ALF; 291 | xdg_to->xfd.CL_MSQ = xdg_from->xfd.CL_MSQ; 292 | xdg_to->xfd.SBLE = xdg_from->xfd.SBLE; 293 | xdg_to->xfd.XLE = xdg_from->xfd.XLE; 294 | xdg_to->xfd.YLE = xdg_from->xfd.YLE; 295 | xdg_to->xfd.XTE = xdg_from->xfd.XTE; 296 | xdg_to->xfd.YTE = xdg_from->xfd.YTE; 297 | xdg_to->xfd.CHORD = xdg_from->xfd.CHORD; 298 | xdg_to->xfd.SLE = xdg_from->xfd.SLE; 299 | xdg_to->xfd.CVPAR = xdg_from->xfd.CVPAR; 300 | xdg_to->xfd.CTERAT = xdg_from->xfd.CTERAT; 301 | xdg_to->xfd.CTRRAT = xdg_from->xfd.CTRRAT; 302 | xdg_to->xfd.XSREF1 = xdg_from->xfd.XSREF1; 303 | xdg_to->xfd.XSREF2 = xdg_from->xfd.XSREF2; 304 | xdg_to->xfd.XPREF1 = xdg_from->xfd.XPREF1; 305 | xdg_to->xfd.XPREF2 = xdg_from->xfd.XPREF2; 306 | xdg_to->xfd.MINF_CL = xdg_from->xfd.MINF_CL; 307 | xdg_to->xfd.COSA = xdg_from->xfd.COSA; 308 | xdg_to->xfd.SINA = xdg_from->xfd.SINA; 309 | xdg_to->xfd.ACRIT = xdg_from->xfd.ACRIT; 310 | xdg_to->xfd.RLX = xdg_from->xfd.RLX; 311 | xdg_to->xfd.VACCEL = xdg_from->xfd.VACCEL; 312 | xdg_to->xfd.AWAKE = xdg_from->xfd.AWAKE; 313 | xdg_to->xfd.AVISC = xdg_from->xfd.AVISC; 314 | xdg_to->xfd.MVISC = xdg_from->xfd.MVISC; 315 | xdg_to->xfd.CLSPEC = xdg_from->xfd.CLSPEC; 316 | xdg_to->xfd.QTAN1 = xdg_from->xfd.QTAN1; 317 | xdg_to->xfd.QTAN2 = xdg_from->xfd.QTAN2; 318 | xdg_to->xfd.SST = xdg_from->xfd.SST; 319 | xdg_to->xfd.SST_GO = xdg_from->xfd.SST_GO; 320 | xdg_to->xfd.SST_GP = xdg_from->xfd.SST_GP; 321 | xdg_to->xfd.IDAMP = xdg_from->xfd.IDAMP; 322 | xdg_to->xfd.IMXBL = xdg_from->xfd.IMXBL; 323 | xdg_to->xfd.ISMXBL = xdg_from->xfd.ISMXBL; 324 | xdg_to->xfd.RMSBL = xdg_from->xfd.RMSBL; 325 | xdg_to->xfd.RMXBL = xdg_from->xfd.RMXBL; 326 | xdg_to->xfd.WAKLEN = xdg_from->xfd.WAKLEN; 327 | xdg_to->xfd.VMXBL = xdg_from->xfd.VMXBL; 328 | xdg_to->xfd.THICKB = xdg_from->xfd.THICKB; 329 | xdg_to->xfd.XTHICKB = xdg_from->xfd.XTHICKB; 330 | xdg_to->xfd.THICKM = xdg_from->xfd.THICKM; 331 | xdg_to->xfd.XTHICKM = xdg_from->xfd.XTHICKM; 332 | xdg_to->xfd.CAMBR = xdg_from->xfd.CAMBR; 333 | xdg_to->xfd.XCAMBR = xdg_from->xfd.XCAMBR; 334 | xdg_to->xfd.XFOIL_FAIL = xdg_from->xfd.XFOIL_FAIL; 335 | xdg_to->xbd.IDAMPV = xdg_from->xbd.IDAMPV; 336 | xdg_to->xbd.SIMI = xdg_from->xbd.SIMI; 337 | xdg_to->xbd.TRAN = xdg_from->xbd.TRAN; 338 | xdg_to->xbd.TURB = xdg_from->xbd.TURB; 339 | xdg_to->xbd.WAKE = xdg_from->xbd.WAKE; 340 | xdg_to->xbd.TRFORC = xdg_from->xbd.TRFORC; 341 | xdg_to->xbd.TRFREE = xdg_from->xbd.TRFREE; 342 | xdg_to->xbd.X1 = xdg_from->xbd.X1; 343 | xdg_to->xbd.U1 = xdg_from->xbd.U1; 344 | xdg_to->xbd.T1 = xdg_from->xbd.T1; 345 | xdg_to->xbd.D1 = xdg_from->xbd.D1; 346 | xdg_to->xbd.S1 = xdg_from->xbd.S1; 347 | xdg_to->xbd.AMPL1 = xdg_from->xbd.AMPL1; 348 | xdg_to->xbd.U1_UEI = xdg_from->xbd.U1_UEI; 349 | xdg_to->xbd.U1_MS = xdg_from->xbd.U1_MS; 350 | xdg_to->xbd.DW1 = xdg_from->xbd.DW1; 351 | xdg_to->xbd.H1 = xdg_from->xbd.H1; 352 | xdg_to->xbd.H1_T1 = xdg_from->xbd.H1_T1; 353 | xdg_to->xbd.H1_D1 = xdg_from->xbd.H1_D1; 354 | xdg_to->xbd.M1 = xdg_from->xbd.M1; 355 | xdg_to->xbd.M1_U1 = xdg_from->xbd.M1_U1; 356 | xdg_to->xbd.M1_MS = xdg_from->xbd.M1_MS; 357 | xdg_to->xbd.R1 = xdg_from->xbd.R1; 358 | xdg_to->xbd.R1_U1 = xdg_from->xbd.R1_U1; 359 | xdg_to->xbd.R1_MS = xdg_from->xbd.R1_MS; 360 | xdg_to->xbd.V1 = xdg_from->xbd.V1; 361 | xdg_to->xbd.V1_U1 = xdg_from->xbd.V1_U1; 362 | xdg_to->xbd.V1_MS = xdg_from->xbd.V1_MS; 363 | xdg_to->xbd.V1_RE = xdg_from->xbd.V1_RE; 364 | xdg_to->xbd.HK1 = xdg_from->xbd.HK1; 365 | xdg_to->xbd.HK1_U1 = xdg_from->xbd.HK1_U1; 366 | xdg_to->xbd.HK1_T1 = xdg_from->xbd.HK1_T1; 367 | xdg_to->xbd.HK1_D1 = xdg_from->xbd.HK1_D1; 368 | xdg_to->xbd.HK1_MS = xdg_from->xbd.HK1_MS; 369 | xdg_to->xbd.HS1 = xdg_from->xbd.HS1; 370 | xdg_to->xbd.HS1_U1 = xdg_from->xbd.HS1_U1; 371 | xdg_to->xbd.HS1_T1 = xdg_from->xbd.HS1_T1; 372 | xdg_to->xbd.HS1_D1 = xdg_from->xbd.HS1_D1; 373 | xdg_to->xbd.HS1_MS = xdg_from->xbd.HS1_MS; 374 | xdg_to->xbd.HS1_RE = xdg_from->xbd.HS1_RE; 375 | xdg_to->xbd.HC1 = xdg_from->xbd.HC1; 376 | xdg_to->xbd.HC1_U1 = xdg_from->xbd.HC1_U1; 377 | xdg_to->xbd.HC1_T1 = xdg_from->xbd.HC1_T1; 378 | xdg_to->xbd.HC1_D1 = xdg_from->xbd.HC1_D1; 379 | xdg_to->xbd.HC1_MS = xdg_from->xbd.HC1_MS; 380 | xdg_to->xbd.RT1 = xdg_from->xbd.RT1; 381 | xdg_to->xbd.RT1_U1 = xdg_from->xbd.RT1_U1; 382 | xdg_to->xbd.RT1_T1 = xdg_from->xbd.RT1_T1; 383 | xdg_to->xbd.RT1_MS = xdg_from->xbd.RT1_MS; 384 | xdg_to->xbd.RT1_RE = xdg_from->xbd.RT1_RE; 385 | xdg_to->xbd.CF1 = xdg_from->xbd.CF1; 386 | xdg_to->xbd.CF1_U1 = xdg_from->xbd.CF1_U1; 387 | xdg_to->xbd.CF1_T1 = xdg_from->xbd.CF1_T1; 388 | xdg_to->xbd.CF1_D1 = xdg_from->xbd.CF1_D1; 389 | xdg_to->xbd.CF1_MS = xdg_from->xbd.CF1_MS; 390 | xdg_to->xbd.CF1_RE = xdg_from->xbd.CF1_RE; 391 | xdg_to->xbd.DI1 = xdg_from->xbd.DI1; 392 | xdg_to->xbd.DI1_U1 = xdg_from->xbd.DI1_U1; 393 | xdg_to->xbd.DI1_T1 = xdg_from->xbd.DI1_T1; 394 | xdg_to->xbd.DI1_D1 = xdg_from->xbd.DI1_D1; 395 | xdg_to->xbd.DI1_S1 = xdg_from->xbd.DI1_S1; 396 | xdg_to->xbd.DI1_MS = xdg_from->xbd.DI1_MS; 397 | xdg_to->xbd.DI1_RE = xdg_from->xbd.DI1_RE; 398 | xdg_to->xbd.US1 = xdg_from->xbd.US1; 399 | xdg_to->xbd.US1_U1 = xdg_from->xbd.US1_U1; 400 | xdg_to->xbd.US1_T1 = xdg_from->xbd.US1_T1; 401 | xdg_to->xbd.US1_D1 = xdg_from->xbd.US1_D1; 402 | xdg_to->xbd.US1_MS = xdg_from->xbd.US1_MS; 403 | xdg_to->xbd.US1_RE = xdg_from->xbd.US1_RE; 404 | xdg_to->xbd.CQ1 = xdg_from->xbd.CQ1; 405 | xdg_to->xbd.CQ1_U1 = xdg_from->xbd.CQ1_U1; 406 | xdg_to->xbd.CQ1_T1 = xdg_from->xbd.CQ1_T1; 407 | xdg_to->xbd.CQ1_D1 = xdg_from->xbd.CQ1_D1; 408 | xdg_to->xbd.CQ1_MS = xdg_from->xbd.CQ1_MS; 409 | xdg_to->xbd.CQ1_RE = xdg_from->xbd.CQ1_RE; 410 | xdg_to->xbd.DE1 = xdg_from->xbd.DE1; 411 | xdg_to->xbd.DE1_U1 = xdg_from->xbd.DE1_U1; 412 | xdg_to->xbd.DE1_T1 = xdg_from->xbd.DE1_T1; 413 | xdg_to->xbd.DE1_D1 = xdg_from->xbd.DE1_D1; 414 | xdg_to->xbd.DE1_MS = xdg_from->xbd.DE1_MS; 415 | xdg_to->xbd.X2 = xdg_from->xbd.X2; 416 | xdg_to->xbd.U2 = xdg_from->xbd.U2; 417 | xdg_to->xbd.T2 = xdg_from->xbd.T2; 418 | xdg_to->xbd.D2 = xdg_from->xbd.D2; 419 | xdg_to->xbd.S2 = xdg_from->xbd.S2; 420 | xdg_to->xbd.AMPL2 = xdg_from->xbd.AMPL2; 421 | xdg_to->xbd.U2_UEI = xdg_from->xbd.U2_UEI; 422 | xdg_to->xbd.U2_MS = xdg_from->xbd.U2_MS; 423 | xdg_to->xbd.DW2 = xdg_from->xbd.DW2; 424 | xdg_to->xbd.H2 = xdg_from->xbd.H2; 425 | xdg_to->xbd.H2_T2 = xdg_from->xbd.H2_T2; 426 | xdg_to->xbd.H2_D2 = xdg_from->xbd.H2_D2; 427 | xdg_to->xbd.M2 = xdg_from->xbd.M2; 428 | xdg_to->xbd.M2_U2 = xdg_from->xbd.M2_U2; 429 | xdg_to->xbd.M2_MS = xdg_from->xbd.M2_MS; 430 | xdg_to->xbd.R2 = xdg_from->xbd.R2; 431 | xdg_to->xbd.R2_U2 = xdg_from->xbd.R2_U2; 432 | xdg_to->xbd.R2_MS = xdg_from->xbd.R2_MS; 433 | xdg_to->xbd.V2 = xdg_from->xbd.V2; 434 | xdg_to->xbd.V2_U2 = xdg_from->xbd.V2_U2; 435 | xdg_to->xbd.V2_MS = xdg_from->xbd.V2_MS; 436 | xdg_to->xbd.V2_RE = xdg_from->xbd.V2_RE; 437 | xdg_to->xbd.HK2 = xdg_from->xbd.HK2; 438 | xdg_to->xbd.HK2_U2 = xdg_from->xbd.HK2_U2; 439 | xdg_to->xbd.HK2_T2 = xdg_from->xbd.HK2_T2; 440 | xdg_to->xbd.HK2_D2 = xdg_from->xbd.HK2_D2; 441 | xdg_to->xbd.HK2_MS = xdg_from->xbd.HK2_MS; 442 | xdg_to->xbd.HS2 = xdg_from->xbd.HS2; 443 | xdg_to->xbd.HS2_U2 = xdg_from->xbd.HS2_U2; 444 | xdg_to->xbd.HS2_T2 = xdg_from->xbd.HS2_T2; 445 | xdg_to->xbd.HS2_D2 = xdg_from->xbd.HS2_D2; 446 | xdg_to->xbd.HS2_MS = xdg_from->xbd.HS2_MS; 447 | xdg_to->xbd.HS2_RE = xdg_from->xbd.HS2_RE; 448 | xdg_to->xbd.HC2 = xdg_from->xbd.HC2; 449 | xdg_to->xbd.HC2_U2 = xdg_from->xbd.HC2_U2; 450 | xdg_to->xbd.HC2_T2 = xdg_from->xbd.HC2_T2; 451 | xdg_to->xbd.HC2_D2 = xdg_from->xbd.HC2_D2; 452 | xdg_to->xbd.HC2_MS = xdg_from->xbd.HC2_MS; 453 | xdg_to->xbd.RT2 = xdg_from->xbd.RT2; 454 | xdg_to->xbd.RT2_U2 = xdg_from->xbd.RT2_U2; 455 | xdg_to->xbd.RT2_T2 = xdg_from->xbd.RT2_T2; 456 | xdg_to->xbd.RT2_MS = xdg_from->xbd.RT2_MS; 457 | xdg_to->xbd.RT2_RE = xdg_from->xbd.RT2_RE; 458 | xdg_to->xbd.CF2 = xdg_from->xbd.CF2; 459 | xdg_to->xbd.CF2_U2 = xdg_from->xbd.CF2_U2; 460 | xdg_to->xbd.CF2_T2 = xdg_from->xbd.CF2_T2; 461 | xdg_to->xbd.CF2_D2 = xdg_from->xbd.CF2_D2; 462 | xdg_to->xbd.CF2_MS = xdg_from->xbd.CF2_MS; 463 | xdg_to->xbd.CF2_RE = xdg_from->xbd.CF2_RE; 464 | xdg_to->xbd.DI2 = xdg_from->xbd.DI2; 465 | xdg_to->xbd.DI2_U2 = xdg_from->xbd.DI2_U2; 466 | xdg_to->xbd.DI2_T2 = xdg_from->xbd.DI2_T2; 467 | xdg_to->xbd.DI2_D2 = xdg_from->xbd.DI2_D2; 468 | xdg_to->xbd.DI2_S2 = xdg_from->xbd.DI2_S2; 469 | xdg_to->xbd.DI2_MS = xdg_from->xbd.DI2_MS; 470 | xdg_to->xbd.DI2_RE = xdg_from->xbd.DI2_RE; 471 | xdg_to->xbd.US2 = xdg_from->xbd.US2; 472 | xdg_to->xbd.US2_U2 = xdg_from->xbd.US2_U2; 473 | xdg_to->xbd.US2_T2 = xdg_from->xbd.US2_T2; 474 | xdg_to->xbd.US2_D2 = xdg_from->xbd.US2_D2; 475 | xdg_to->xbd.US2_MS = xdg_from->xbd.US2_MS; 476 | xdg_to->xbd.US2_RE = xdg_from->xbd.US2_RE; 477 | xdg_to->xbd.CQ2 = xdg_from->xbd.CQ2; 478 | xdg_to->xbd.CQ2_U2 = xdg_from->xbd.CQ2_U2; 479 | xdg_to->xbd.CQ2_T2 = xdg_from->xbd.CQ2_T2; 480 | xdg_to->xbd.CQ2_D2 = xdg_from->xbd.CQ2_D2; 481 | xdg_to->xbd.CQ2_MS = xdg_from->xbd.CQ2_MS; 482 | xdg_to->xbd.CQ2_RE = xdg_from->xbd.CQ2_RE; 483 | xdg_to->xbd.DE2 = xdg_from->xbd.DE2; 484 | xdg_to->xbd.DE2_U2 = xdg_from->xbd.DE2_U2; 485 | xdg_to->xbd.DE2_T2 = xdg_from->xbd.DE2_T2; 486 | xdg_to->xbd.DE2_D2 = xdg_from->xbd.DE2_D2; 487 | xdg_to->xbd.DE2_MS = xdg_from->xbd.DE2_MS; 488 | xdg_to->xbd.CFM = xdg_from->xbd.CFM; 489 | xdg_to->xbd.CFM_MS = xdg_from->xbd.CFM_MS; 490 | xdg_to->xbd.CFM_RE = xdg_from->xbd.CFM_RE; 491 | xdg_to->xbd.CFM_U1 = xdg_from->xbd.CFM_U1; 492 | xdg_to->xbd.CFM_T1 = xdg_from->xbd.CFM_T1; 493 | xdg_to->xbd.CFM_D1 = xdg_from->xbd.CFM_D1; 494 | xdg_to->xbd.CFM_U2 = xdg_from->xbd.CFM_U2; 495 | xdg_to->xbd.CFM_T2 = xdg_from->xbd.CFM_T2; 496 | xdg_to->xbd.CFM_D2 = xdg_from->xbd.CFM_D2; 497 | xdg_to->xbd.XT = xdg_from->xbd.XT; 498 | xdg_to->xbd.XT_A1 = xdg_from->xbd.XT_A1; 499 | xdg_to->xbd.XT_MS = xdg_from->xbd.XT_MS; 500 | xdg_to->xbd.XT_RE = xdg_from->xbd.XT_RE; 501 | xdg_to->xbd.XT_XF = xdg_from->xbd.XT_XF; 502 | xdg_to->xbd.XT_X1 = xdg_from->xbd.XT_X1; 503 | xdg_to->xbd.XT_T1 = xdg_from->xbd.XT_T1; 504 | xdg_to->xbd.XT_D1 = xdg_from->xbd.XT_D1; 505 | xdg_to->xbd.XT_U1 = xdg_from->xbd.XT_U1; 506 | xdg_to->xbd.XT_X2 = xdg_from->xbd.XT_X2; 507 | xdg_to->xbd.XT_T2 = xdg_from->xbd.XT_T2; 508 | xdg_to->xbd.XT_D2 = xdg_from->xbd.XT_D2; 509 | xdg_to->xbd.XT_U2 = xdg_from->xbd.XT_U2; 510 | xdg_to->xbd.DWTE = xdg_from->xbd.DWTE; 511 | xdg_to->xbd.QINFBL = xdg_from->xbd.QINFBL; 512 | xdg_to->xbd.TKBL = xdg_from->xbd.TKBL; 513 | xdg_to->xbd.TKBL_MS = xdg_from->xbd.TKBL_MS; 514 | xdg_to->xbd.RSTBL = xdg_from->xbd.RSTBL; 515 | xdg_to->xbd.RSTBL_MS = xdg_from->xbd.RSTBL_MS; 516 | xdg_to->xbd.HSTINV = xdg_from->xbd.HSTINV; 517 | xdg_to->xbd.HSTINV_MS = xdg_from->xbd.HSTINV_MS; 518 | xdg_to->xbd.REYBL = xdg_from->xbd.REYBL; 519 | xdg_to->xbd.REYBL_MS = xdg_from->xbd.REYBL_MS; 520 | xdg_to->xbd.REYBL_RE = xdg_from->xbd.REYBL_RE; 521 | xdg_to->xbd.GAMBL = xdg_from->xbd.GAMBL; 522 | xdg_to->xbd.GM1BL = xdg_from->xbd.GM1BL; 523 | xdg_to->xbd.HVRA = xdg_from->xbd.HVRA; 524 | xdg_to->xbd.BULE = xdg_from->xbd.BULE; 525 | xdg_to->xbd.XIFORC = xdg_from->xbd.XIFORC; 526 | xdg_to->xbd.AMCRIT = xdg_from->xbd.AMCRIT; 527 | xdg_to->bld.SCCON = xdg_from->bld.SCCON; 528 | xdg_to->bld.GACON = xdg_from->bld.GACON; 529 | xdg_to->bld.GBCON = xdg_from->bld.GBCON; 530 | xdg_to->bld.GCCON = xdg_from->bld.GCCON; 531 | xdg_to->bld.DLCON = xdg_from->bld.DLCON; 532 | xdg_to->bld.CTRCON = xdg_from->bld.CTRCON; 533 | xdg_to->bld.CTRCEX = xdg_from->bld.CTRCEX; 534 | xdg_to->bld.DUXCON = xdg_from->bld.DUXCON; 535 | xdg_to->bld.CTCON = xdg_from->bld.CTCON; 536 | xdg_to->bld.CFFAC = xdg_from->bld.CFFAC; 537 | for ( i = 0; i < IQX; i++ ) 538 | { 539 | xdg_to->xfd.GAM[i] = xdg_from->xfd.GAM[i]; 540 | } 541 | for ( i = 0; i < IQX*2; i++ ) 542 | { 543 | xdg_to->xfd.GAMU[i] = xdg_from->xfd.GAMU[i]; 544 | } 545 | for ( i = 0; i < IZX*2; i++ ) 546 | { 547 | xdg_to->xfd.QINVU[i] = xdg_from->xfd.QINVU[i]; 548 | } 549 | for ( i = 0; i < IQX; i++ ) 550 | { 551 | xdg_to->xfd.GAM_A[i] = xdg_from->xfd.GAM_A[i]; 552 | } 553 | for ( i = 0; i < IZX; i++ ) 554 | { 555 | xdg_to->xfd.QINV[i] = xdg_from->xfd.QINV[i]; 556 | } 557 | for ( i = 0; i < IZX; i++ ) 558 | { 559 | xdg_to->xfd.QINV_A[i] = xdg_from->xfd.QINV_A[i]; 560 | } 561 | for ( i = 0; i < IQX*IQX; i++ ) 562 | { 563 | xdg_to->xfd.AIJ[i] = xdg_from->xfd.AIJ[i]; 564 | } 565 | for ( i = 0; i < IQX*IZX; i++ ) 566 | { 567 | xdg_to->xfd.BIJ[i] = xdg_from->xfd.BIJ[i]; 568 | } 569 | for ( i = 0; i < IZX*IZX; i++ ) 570 | { 571 | xdg_to->xfd.DIJ[i] = xdg_from->xfd.DIJ[i]; 572 | } 573 | for ( i = 0; i < IWX*IQX; i++ ) 574 | { 575 | xdg_to->xfd.CIJ[i] = xdg_from->xfd.CIJ[i]; 576 | } 577 | for ( i = 0; i < IQX; i++ ) 578 | { 579 | xdg_to->xfd.DZDG[i] = xdg_from->xfd.DZDG[i]; 580 | } 581 | for ( i = 0; i < IQX; i++ ) 582 | { 583 | xdg_to->xfd.DZDN[i] = xdg_from->xfd.DZDN[i]; 584 | } 585 | for ( i = 0; i < IQX; i++ ) 586 | { 587 | xdg_to->xfd.DQDG[i] = xdg_from->xfd.DQDG[i]; 588 | } 589 | for ( i = 0; i < IZX; i++ ) 590 | { 591 | xdg_to->xfd.DZDM[i] = xdg_from->xfd.DZDM[i]; 592 | } 593 | for ( i = 0; i < IZX; i++ ) 594 | { 595 | xdg_to->xfd.DQDM[i] = xdg_from->xfd.DQDM[i]; 596 | } 597 | for ( i = 0; i < IZX; i++ ) 598 | { 599 | xdg_to->xfd.X[i] = xdg_from->xfd.X[i]; 600 | } 601 | for ( i = 0; i < IZX; i++ ) 602 | { 603 | xdg_to->xfd.Y[i] = xdg_from->xfd.Y[i]; 604 | } 605 | for ( i = 0; i < IZX; i++ ) 606 | { 607 | xdg_to->xfd.NX[i] = xdg_from->xfd.NX[i]; 608 | } 609 | for ( i = 0; i < IZX; i++ ) 610 | { 611 | xdg_to->xfd.NY[i] = xdg_from->xfd.NY[i]; 612 | } 613 | for ( i = 0; i < IZX; i++ ) 614 | { 615 | xdg_to->xfd.S[i] = xdg_from->xfd.S[i]; 616 | } 617 | for ( i = 0; i < IZX; i++ ) 618 | { 619 | xdg_to->xfd.APANEL[i] = xdg_from->xfd.APANEL[i]; 620 | } 621 | for ( i = 0; i < IZX; i++ ) 622 | { 623 | xdg_to->xfd.SIG[i] = xdg_from->xfd.SIG[i]; 624 | } 625 | for ( i = 0; i < IZX; i++ ) 626 | { 627 | xdg_to->xfd.XP[i] = xdg_from->xfd.XP[i]; 628 | } 629 | for ( i = 0; i < IZX; i++ ) 630 | { 631 | xdg_to->xfd.YP[i] = xdg_from->xfd.YP[i]; 632 | } 633 | for ( i = 0; i < IQX; i++ ) 634 | { 635 | xdg_to->xfd.QF0[i] = xdg_from->xfd.QF0[i]; 636 | } 637 | for ( i = 0; i < IQX; i++ ) 638 | { 639 | xdg_to->xfd.QF1[i] = xdg_from->xfd.QF1[i]; 640 | } 641 | for ( i = 0; i < IQX; i++ ) 642 | { 643 | xdg_to->xfd.QF2[i] = xdg_from->xfd.QF2[i]; 644 | } 645 | for ( i = 0; i < IQX; i++ ) 646 | { 647 | xdg_to->xfd.QF3[i] = xdg_from->xfd.QF3[i]; 648 | } 649 | for ( i = 0; i < IQX; i++ ) 650 | { 651 | xdg_to->xfd.AIJPIV[i] = xdg_from->xfd.AIJPIV[i]; 652 | } 653 | for ( i = 0; i < ISX; i++ ) 654 | { 655 | xdg_to->xfd.IBLTE[i] = xdg_from->xfd.IBLTE[i]; 656 | } 657 | for ( i = 0; i < ISX; i++ ) 658 | { 659 | xdg_to->xfd.NBL[i] = xdg_from->xfd.NBL[i]; 660 | } 661 | for ( i = 0; i < IVX*ISX; i++ ) 662 | { 663 | xdg_to->xfd.IPAN[i] = xdg_from->xfd.IPAN[i]; 664 | } 665 | for ( i = 0; i < IVX*ISX; i++ ) 666 | { 667 | xdg_to->xfd.ISYS[i] = xdg_from->xfd.ISYS[i]; 668 | } 669 | for ( i = 0; i < IBX; i++ ) 670 | { 671 | xdg_to->xfd.XB[i] = xdg_from->xfd.XB[i]; 672 | } 673 | for ( i = 0; i < IBX; i++ ) 674 | { 675 | xdg_to->xfd.YB[i] = xdg_from->xfd.YB[i]; 676 | } 677 | for ( i = 0; i < IBX; i++ ) 678 | { 679 | xdg_to->xfd.SB[i] = xdg_from->xfd.SB[i]; 680 | } 681 | for ( i = 0; i < IBX; i++ ) 682 | { 683 | xdg_to->xfd.XBP[i] = xdg_from->xfd.XBP[i]; 684 | } 685 | for ( i = 0; i < IBX; i++ ) 686 | { 687 | xdg_to->xfd.YBP[i] = xdg_from->xfd.YBP[i]; 688 | } 689 | for ( i = 0; i < 5*IBX; i++ ) 690 | { 691 | xdg_to->xfd.SNEW[i] = xdg_from->xfd.SNEW[i]; 692 | } 693 | for ( i = 0; i < 6*IQX; i++ ) 694 | { 695 | xdg_to->xfd.W1[i] = xdg_from->xfd.W1[i]; 696 | } 697 | for ( i = 0; i < 6*IQX; i++ ) 698 | { 699 | xdg_to->xfd.W2[i] = xdg_from->xfd.W2[i]; 700 | } 701 | for ( i = 0; i < 6*IQX; i++ ) 702 | { 703 | xdg_to->xfd.W3[i] = xdg_from->xfd.W3[i]; 704 | } 705 | for ( i = 0; i < 6*IQX; i++ ) 706 | { 707 | xdg_to->xfd.W4[i] = xdg_from->xfd.W4[i]; 708 | } 709 | for ( i = 0; i < 6*IQX; i++ ) 710 | { 711 | xdg_to->xfd.W5[i] = xdg_from->xfd.W5[i]; 712 | } 713 | for ( i = 0; i < 6*IQX; i++ ) 714 | { 715 | xdg_to->xfd.W6[i] = xdg_from->xfd.W6[i]; 716 | } 717 | for ( i = 0; i < IZX; i++ ) 718 | { 719 | xdg_to->xfd.CPI[i] = xdg_from->xfd.CPI[i]; 720 | } 721 | for ( i = 0; i < IZX; i++ ) 722 | { 723 | xdg_to->xfd.CPV[i] = xdg_from->xfd.CPV[i]; 724 | } 725 | for ( i = 0; i < IZX; i++ ) 726 | { 727 | xdg_to->xfd.QVIS[i] = xdg_from->xfd.QVIS[i]; 728 | } 729 | for ( i = 0; i < IVX*ISX; i++ ) 730 | { 731 | xdg_to->xfd.VTI[i] = xdg_from->xfd.VTI[i]; 732 | } 733 | for ( i = 0; i < IVX*ISX; i++ ) 734 | { 735 | xdg_to->xfd.XSSI[i] = xdg_from->xfd.XSSI[i]; 736 | } 737 | for ( i = 0; i < IWX; i++ ) 738 | { 739 | xdg_to->xfd.WGAP[i] = xdg_from->xfd.WGAP[i]; 740 | } 741 | for ( i = 0; i < ISX; i++ ) 742 | { 743 | xdg_to->xfd.XSTRIP[i] = xdg_from->xfd.XSTRIP[i]; 744 | } 745 | for ( i = 0; i < ISX; i++ ) 746 | { 747 | xdg_to->xfd.XSSITR[i] = xdg_from->xfd.XSSITR[i]; 748 | } 749 | for ( i = 0; i < IVX*ISX; i++ ) 750 | { 751 | xdg_to->xfd.UINV[i] = xdg_from->xfd.UINV[i]; 752 | } 753 | for ( i = 0; i < IVX*ISX; i++ ) 754 | { 755 | xdg_to->xfd.UINV_A[i] = xdg_from->xfd.UINV_A[i]; 756 | } 757 | for ( i = 0; i < IVX*ISX; i++ ) 758 | { 759 | xdg_to->xfd.UEDG[i] = xdg_from->xfd.UEDG[i]; 760 | } 761 | for ( i = 0; i < IVX*ISX; i++ ) 762 | { 763 | xdg_to->xfd.THET[i] = xdg_from->xfd.THET[i]; 764 | } 765 | for ( i = 0; i < IVX*ISX; i++ ) 766 | { 767 | xdg_to->xfd.DSTR[i] = xdg_from->xfd.DSTR[i]; 768 | } 769 | for ( i = 0; i < IVX*ISX; i++ ) 770 | { 771 | xdg_to->xfd.CTAU[i] = xdg_from->xfd.CTAU[i]; 772 | } 773 | for ( i = 0; i < IVX*ISX; i++ ) 774 | { 775 | xdg_to->xfd.MASS[i] = xdg_from->xfd.MASS[i]; 776 | } 777 | for ( i = 0; i < IVX*ISX; i++ ) 778 | { 779 | xdg_to->xfd.TAU[i] = xdg_from->xfd.TAU[i]; 780 | } 781 | for ( i = 0; i < IVX*ISX; i++ ) 782 | { 783 | xdg_to->xfd.DIS[i] = xdg_from->xfd.DIS[i]; 784 | } 785 | for ( i = 0; i < IVX*ISX; i++ ) 786 | { 787 | xdg_to->xfd.CTQ[i] = xdg_from->xfd.CTQ[i]; 788 | } 789 | for ( i = 0; i < IVX*ISX; i++ ) 790 | { 791 | xdg_to->xfd.DELT[i] = xdg_from->xfd.DELT[i]; 792 | } 793 | for ( i = 0; i < IVX*ISX; i++ ) 794 | { 795 | xdg_to->xfd.TSTR[i] = xdg_from->xfd.TSTR[i]; 796 | } 797 | for ( i = 0; i < IVX*ISX; i++ ) 798 | { 799 | xdg_to->xfd.USLP[i] = xdg_from->xfd.USLP[i]; 800 | } 801 | for ( i = 0; i < ISX; i++ ) 802 | { 803 | xdg_to->xfd.ITRAN[i] = xdg_from->xfd.ITRAN[i]; 804 | } 805 | for ( i = 0; i < ISX; i++ ) 806 | { 807 | xdg_to->xfd.TFORCE[i] = xdg_from->xfd.TFORCE[i]; 808 | } 809 | for ( i = 0; i < 3*IZX*IZX; i++ ) 810 | { 811 | xdg_to->xfd.VM[i] = xdg_from->xfd.VM[i]; 812 | } 813 | for ( i = 0; i < 3*2*IZX; i++ ) 814 | { 815 | xdg_to->xfd.VA[i] = xdg_from->xfd.VA[i]; 816 | } 817 | for ( i = 0; i < 3*2*IZX; i++ ) 818 | { 819 | xdg_to->xfd.VB[i] = xdg_from->xfd.VB[i]; 820 | } 821 | for ( i = 0; i < 3*2*IZX; i++ ) 822 | { 823 | xdg_to->xfd.VDEL[i] = xdg_from->xfd.VDEL[i]; 824 | } 825 | for ( i = 0; i < 3*2; i++ ) 826 | { 827 | xdg_to->xfd.VZ[i] = xdg_from->xfd.VZ[i]; 828 | } 829 | for ( i = 0; i < ISX; i++ ) 830 | { 831 | xdg_to->xfd.XOCTR[i] = xdg_from->xfd.XOCTR[i]; 832 | } 833 | for ( i = 0; i < ISX; i++ ) 834 | { 835 | xdg_to->xfd.YOCTR[i] = xdg_from->xfd.YOCTR[i]; 836 | } 837 | for ( i = 0; i < IVX*2; i++ ) 838 | { 839 | xdg_to->xfd.UNEW[i] = xdg_from->xfd.UNEW[i]; 840 | } 841 | for ( i = 0; i < IVX*2; i++ ) 842 | { 843 | xdg_to->xfd.U_AC[i] = xdg_from->xfd.U_AC[i]; 844 | } 845 | for ( i = 0; i < IQX; i++ ) 846 | { 847 | xdg_to->xfd.QNEW[i] = xdg_from->xfd.QNEW[i]; 848 | } 849 | for ( i = 0; i < IQX; i++ ) 850 | { 851 | xdg_to->xfd.Q_AC[i] = xdg_from->xfd.Q_AC[i]; 852 | } 853 | for ( i = 0; i < NCOM; i++ ) 854 | { 855 | xdg_to->xbd.C1SAV[i] = xdg_from->xbd.C1SAV[i]; 856 | } 857 | for ( i = 0; i < NCOM; i++ ) 858 | { 859 | xdg_to->xbd.C2SAV[i] = xdg_from->xbd.C2SAV[i]; 860 | } 861 | for ( i = 0; i < 4*5; i++ ) 862 | { 863 | xdg_to->xbd.VS1[i] = xdg_from->xbd.VS1[i]; 864 | } 865 | for ( i = 0; i < 4*5; i++ ) 866 | { 867 | xdg_to->xbd.VS2[i] = xdg_from->xbd.VS2[i]; 868 | } 869 | for ( i = 0; i < 4; i++ ) 870 | { 871 | xdg_to->xbd.VSREZ[i] = xdg_from->xbd.VSREZ[i]; 872 | } 873 | for ( i = 0; i < 4; i++ ) 874 | { 875 | xdg_to->xbd.VSR[i] = xdg_from->xbd.VSR[i]; 876 | } 877 | for ( i = 0; i < 4; i++ ) 878 | { 879 | xdg_to->xbd.VSM[i] = xdg_from->xbd.VSM[i]; 880 | } 881 | for ( i = 0; i < 4; i++ ) 882 | { 883 | xdg_to->xbd.VSX[i] = xdg_from->xbd.VSX[i]; 884 | } 885 | } 886 | -------------------------------------------------------------------------------- /src/libxfoil.f90: -------------------------------------------------------------------------------- 1 | ! This file is part of libxfoil. 2 | 3 | ! libxfoil is free software: you can redistribute it and/or modify 4 | ! it under the terms of the GNU General Public License as published by 5 | ! the Free Software Foundation, either version 3 of the License, or 6 | ! (at your option) any later version. 7 | 8 | ! libxfoil is distributed in the hope that it will be useful, 9 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | ! GNU General Public License for more details. 12 | 13 | ! You should have received a copy of the GNU General Public License 14 | ! along with libxfoil. If not, see . 15 | 16 | ! Copyright (C) 2019 Daniel Prosser 17 | 18 | module libxfoil 19 | 20 | ! Contains subroutines to use XFoil to analyze an airfoil 21 | 22 | use iso_c_binding 23 | use xfoil_data_mod 24 | 25 | implicit none 26 | 27 | type, bind(c) :: xfoil_options_type 28 | 29 | real(c_double) :: ncrit !Critical ampl. ratio 30 | real(c_double) :: xtript, xtripb !Trip locations 31 | logical(c_bool) :: viscous_mode 32 | logical(c_bool) :: silent_mode !Toggle xfoil screen write 33 | integer(c_int) :: maxit !Iterations for BL calcs 34 | real(c_double) :: vaccel !Xfoil BL convergence accelerator 35 | ! point (recommended for optimization) 36 | 37 | end type xfoil_options_type 38 | 39 | type, bind(c) :: xfoil_geom_options_type 40 | 41 | integer(c_int) :: npan 42 | real(c_double) :: cvpar, cterat, ctrrat, xsref1, xsref2, xpref1, xpref2 43 | 44 | end type xfoil_geom_options_type 45 | 46 | contains 47 | 48 | !=============================================================================80 49 | ! 50 | ! Allocates memory for structs in xfoil_data_group using C backend 51 | ! 52 | !=============================================================================80 53 | subroutine xfoil_init(xdg) bind(c, name="xfoil_init") 54 | 55 | type(xfoil_data_group), intent(inout) :: xdg 56 | 57 | interface 58 | subroutine allocate_xdg(xdg) bind(c) 59 | use xfoil_data_mod, only : xfoil_data_group 60 | type(xfoil_data_group), intent(inout) :: xdg 61 | end subroutine allocate_xdg 62 | end interface 63 | 64 | call allocate_xdg(xdg) 65 | 66 | end subroutine xfoil_init 67 | 68 | !=============================================================================80 69 | ! 70 | ! Frees memory for structs in xfoil_data_group using C backend 71 | ! 72 | !=============================================================================80 73 | subroutine xfoil_cleanup(xdg) bind(c, name="xfoil_cleanup") 74 | 75 | type(xfoil_data_group), intent(inout) :: xdg 76 | 77 | interface 78 | subroutine free_xdg(xdg) bind(c) 79 | use xfoil_data_mod, only : xfoil_data_group 80 | type(xfoil_data_group), intent(inout) :: xdg 81 | end subroutine free_xdg 82 | end interface 83 | 84 | call free_xdg(xdg) 85 | 86 | end subroutine xfoil_cleanup 87 | 88 | !=============================================================================80 89 | ! 90 | ! Copies xfoil_data_groups using C backend. xfoil_init must have already been 91 | ! called for both. 92 | ! 93 | !=============================================================================80 94 | subroutine xfoil_copy(xdg_from, xdg_to) bind(c, name="xfoil_copy") 95 | 96 | type(xfoil_data_group), intent(in) :: xdg_from 97 | type(xfoil_data_group), intent(inout) :: xdg_to 98 | 99 | interface 100 | subroutine copy_xdg(xdg_from, xdg_to) bind(c) 101 | use xfoil_data_mod, only : xfoil_data_group 102 | type(xfoil_data_group), intent(in) :: xdg_from 103 | type(xfoil_data_group), intent(inout) :: xdg_to 104 | end subroutine copy_xdg 105 | end interface 106 | 107 | call copy_xdg(xdg_from, xdg_to) 108 | 109 | end subroutine xfoil_copy 110 | 111 | !=============================================================================80 112 | ! 113 | ! Initializes xfoil variables from settings 114 | ! 115 | !=============================================================================80 116 | subroutine xfoil_defaults(xdg, xfoil_options) bind(c, name="xfoil_defaults") 117 | 118 | use iso_c_binding 119 | type(xfoil_data_group), intent(inout) :: xdg 120 | type(xfoil_options_type), intent(in) :: xfoil_options 121 | 122 | real(c_double), pointer :: SIG(:) 123 | real(c_double), pointer :: QF0(:) 124 | real(c_double), pointer :: QF1(:) 125 | real(c_double), pointer :: QF2(:) 126 | real(c_double), pointer :: QF3(:) 127 | real(c_double), pointer :: XSTRIP(:) 128 | real(c_double), pointer :: GAMU(:,:) 129 | real(c_double), pointer :: GAM(:) 130 | real(c_double), pointer :: APANEL(:) 131 | 132 | call c_f_pointer(xdg%xfd%SIG, SIG, [IZX]) 133 | call c_f_pointer(xdg%xfd%QF0, QF0, [IQX]) 134 | call c_f_pointer(xdg%xfd%QF1, QF1, [IQX]) 135 | call c_f_pointer(xdg%xfd%QF2, QF2, [IQX]) 136 | call c_f_pointer(xdg%xfd%QF3, QF3, [IQX]) 137 | call c_f_pointer(xdg%xfd%XSTRIP, XSTRIP, [ISX]) 138 | call c_f_pointer(xdg%xfd%GAMU, GAMU, [IQX,2]) 139 | call c_f_pointer(xdg%xfd%GAM, GAM, [IQX]) 140 | call c_f_pointer(xdg%xfd%APANEL, APANEL, [IZX]) 141 | 142 | xdg%xfd%SILENT_MODE = xfoil_options%silent_mode 143 | xdg%xfd%VISCOUS_MODE = xfoil_options%viscous_mode 144 | xdg%xfd%MAXIT = xfoil_options%maxit 145 | xdg%xfd%N = 0 146 | xdg%xfd%PI = 4.d0*atan(1.d0) 147 | xdg%xfd%HOPI = 0.5d0/xdg%xfd%PI 148 | xdg%xfd%QOPI = 0.25d0/xdg%xfd%PI 149 | xdg%xfd%DTOR = xdg%xfd%PI/180.d0 150 | xdg%xfd%QINF = 1.d0 151 | SIG(:) = 0.d0 152 | QF0(:) = 0.d0 153 | QF1(:) = 0.d0 154 | QF2(:) = 0.d0 155 | QF3(:) = 0.d0 156 | xdg%xfd%NW = 0 157 | xdg%xfd%RETYP = 1 158 | xdg%xfd%MATYP = 1 159 | xdg%xfd%GAMMA = 1.4d0 160 | xdg%xfd%GAMM1 = xdg%xfd%GAMMA - 1.d0 161 | xdg%xfd%XCMREF = 0.25d0 162 | xdg%xfd%YCMREF = 0.d0 163 | xdg%xfd%LVISC = xfoil_options%viscous_mode 164 | xdg%xfd%AWAKE = 0.d0 165 | xdg%xfd%AVISC = 0.d0 166 | xdg%xfd%ITMAX = xfoil_options%maxit 167 | xdg%xfd%LWDIJ = .false. 168 | xdg%xfd%LIPAN = .false. 169 | xdg%xfd%LBLINI = .false. 170 | xdg%xfd%ACRIT = xfoil_options%ncrit 171 | xdg%xfd%IDAMP = 0 172 | XSTRIP(1) = xfoil_options%xtript 173 | XSTRIP(2) = xfoil_options%xtripb 174 | xdg%xfd%VACCEL = xfoil_options%vaccel 175 | xdg%xfd%WAKLEN = 1.d0 176 | xdg%xfd%PSIO = 0.d0 177 | GAMU(:,:) = 0.d0 178 | GAM(:) = 0.d0 179 | xdg%xfd%SIGTE = 0.d0 180 | xdg%xfd%GAMTE = 0.d0 181 | xdg%xfd%SIGTE_A = 0.d0 182 | xdg%xfd%GAMTE_A = 0.d0 183 | APANEL(:) = 0.d0 184 | 185 | ! Set boundary layer calibration parameters 186 | 187 | call BLPINI(xdg%bld) 188 | 189 | end subroutine xfoil_defaults 190 | 191 | !=============================================================================80 192 | ! 193 | ! Sets xfoil paneling options 194 | ! 195 | !=============================================================================80 196 | subroutine xfoil_set_paneling(xdg, geom_options) & 197 | bind(c, name="xfoil_set_paneling") 198 | 199 | type(xfoil_data_group), intent(inout) :: xdg 200 | type(xfoil_geom_options_type), intent(in) :: geom_options 201 | 202 | xdg%xfd%NPAN = geom_options%npan 203 | xdg%xfd%CVPAR = geom_options%cvpar 204 | xdg%xfd%CTERAT = geom_options%cterat 205 | xdg%xfd%CTRRAT = geom_options%ctrrat 206 | xdg%xfd%XSREF1 = geom_options%xsref1 207 | xdg%xfd%XSREF2 = geom_options%xsref2 208 | xdg%xfd%XPREF1 = geom_options%xpref1 209 | xdg%xfd%XPREF2 = geom_options%xpref2 210 | 211 | end subroutine xfoil_set_paneling 212 | 213 | !=============================================================================80 214 | ! 215 | ! Sets buffer airfoil for xfoil 216 | ! 217 | !=============================================================================80 218 | subroutine xfoil_set_buffer_airfoil(xdg, xin, zin, npointin) & 219 | bind(c, name="xfoil_set_buffer_airfoil") 220 | 221 | use iso_c_binding 222 | type(xfoil_data_group), intent(inout) :: xdg 223 | real(c_double), dimension(npointin), intent(in) :: xin, zin 224 | integer(c_int), intent(in) :: npointin 225 | 226 | real(c_double), pointer :: XB(:) 227 | real(c_double), pointer :: YB(:) 228 | 229 | call c_f_pointer(xdg%xfd%XB, XB, [IBX]) 230 | call c_f_pointer(xdg%xfd%YB, YB, [IBX]) 231 | 232 | xdg%xfd%NB = npointin 233 | XB(1:xdg%xfd%NB) = xin 234 | YB(1:xdg%xfd%NB) = zin 235 | 236 | end subroutine xfoil_set_buffer_airfoil 237 | 238 | !=============================================================================80 239 | ! 240 | ! Returns buffer airfoil coordinates from Xfoil 241 | ! stat: 0 for success, 1 if buffer airfoil is not available (call 242 | ! xfoil_set_buffer_airfoil first) 243 | ! 244 | !=============================================================================80 245 | subroutine xfoil_get_buffer_airfoil(xdg, xout, zout, npoint, stat) & 246 | bind(c, name="xfoil_get_buffer_airfoil") 247 | 248 | use iso_c_binding 249 | type(xfoil_data_group), intent(in) :: xdg 250 | integer(c_int), intent(in) :: npoint 251 | real(c_double), dimension(npoint), intent(out) :: xout, zout 252 | integer(c_int), intent(out) :: stat 253 | 254 | real(c_double), pointer :: XB(:) 255 | real(c_double), pointer :: YB(:) 256 | 257 | call c_f_pointer(xdg%xfd%XB, XB, [IBX]) 258 | call c_f_pointer(xdg%xfd%YB, YB, [IBX]) 259 | 260 | ! Check that buffer airfoil is available 261 | 262 | stat = 0 263 | if (xdg%xfd%NB == 0) then 264 | stat = 1 265 | return 266 | end if 267 | 268 | xout(1:npoint) = XB(1:npoint) 269 | zout(1:npoint) = YB(1:npoint) 270 | 271 | end subroutine xfoil_get_buffer_airfoil 272 | 273 | !=============================================================================80 274 | ! 275 | ! Returns current (not buffer) airfoil coordinates from Xfoil 276 | ! stat: 0 for success, 1 if current airfoil is not available (call 277 | ! xfoil_smooth_paneling first) 278 | ! 279 | !=============================================================================80 280 | subroutine xfoil_get_current_airfoil(xdg, xout, zout, npoint, stat) & 281 | bind(c, name="xfoil_get_current_airfoil") 282 | 283 | use iso_c_binding 284 | type(xfoil_data_group), intent(in) :: xdg 285 | integer(c_int), intent(in) :: npoint 286 | real(c_double), dimension(npoint), intent(out) :: xout, zout 287 | integer(c_int), intent(out) :: stat 288 | 289 | real(c_double), pointer :: X(:) 290 | real(c_double), pointer :: Y(:) 291 | 292 | call c_f_pointer(xdg%xfd%X, X, [IZX]) 293 | call c_f_pointer(xdg%xfd%Y, Y, [IZX]) 294 | 295 | ! Check that airfoil is available 296 | 297 | stat = 0 298 | if (xdg%xfd%N == 0) then 299 | stat = 1 300 | return 301 | end if 302 | 303 | xout(1:npoint) = X(1:npoint) 304 | zout(1:npoint) = Y(1:npoint) 305 | 306 | end subroutine xfoil_get_current_airfoil 307 | 308 | !=============================================================================80 309 | ! 310 | ! Smooths buffer airfoil using Xfoil's PANGEN subroutine 311 | ! stat: 0 for success, 1 for failure (xfoil_set_buffer_airfoil not called yet) 312 | ! 313 | !=============================================================================80 314 | subroutine xfoil_smooth_paneling(xdg, stat) & 315 | bind(c, name="xfoil_smooth_paneling") 316 | 317 | type(xfoil_data_group), intent(inout) :: xdg 318 | integer(c_int), intent(out) :: stat 319 | 320 | ! Check that buffer airfoil is set 321 | 322 | stat = 0 323 | if (xdg%xfd%NB == 0) then 324 | stat = 1 325 | return 326 | end if 327 | 328 | ! Smooth paneling with PANGEN 329 | 330 | call PANGEN(xdg%xfd, .NOT. xdg%xfd%SILENT_MODE) 331 | 332 | end subroutine xfoil_smooth_paneling 333 | 334 | !=============================================================================80 335 | ! 336 | ! Subroutine to apply a flap deflection to the buffer airfoil and set it as the 337 | ! current airfoil. It is recommended to call this after xfoil_smooth_paneling. 338 | ! z_flap_spec = 0: specified as y/c 339 | ! = 1: specified as y/local thickness 340 | ! stat: 0 for success, 1 for failure (xfoil_set_buffer_airfoil not called yet) 341 | ! 342 | !=============================================================================80 343 | subroutine xfoil_apply_flap_deflection(xdg, xflap, zflap, z_flap_spec, degrees,& 344 | npointout, stat) & 345 | bind(c, name="xfoil_apply_flap_deflection") 346 | 347 | type(xfoil_data_group), intent(inout) :: xdg 348 | real(c_double), intent(in) :: xflap, zflap, degrees 349 | integer(c_int), intent(in) :: z_flap_spec 350 | integer(c_int), intent(out) :: npointout, stat 351 | 352 | ! Check that buffer airfoil is set 353 | 354 | stat = 0 355 | if (xdg%xfd%NB == 0) then 356 | stat = 1 357 | return 358 | end if 359 | 360 | ! Apply flap deflection 361 | 362 | call FLAP(xdg%xfd, xflap, zflap, z_flap_spec, degrees) 363 | 364 | ! Get new buffer airfoil points (may have changed) 365 | 366 | npointout = xdg%xfd%NB 367 | 368 | end subroutine xfoil_apply_flap_deflection 369 | 370 | !=============================================================================80 371 | ! 372 | ! Subroutine to modify the trailing edge gap of the buffer airfoil and set it as 373 | ! the current airfoil. 374 | ! gap: the new TE gap 375 | ! blendloc: x/c location where the shape is first modified to accomodate the gap 376 | ! 0 < blendloc < 1 377 | ! stat: 0 for success, 1 for failure (xfoil_set_buffer_airfoil not called yet) 378 | ! 379 | !=============================================================================80 380 | subroutine xfoil_modify_tegap(xdg, gap, blendloc, npointout, stat) & 381 | bind(c, name="xfoil_modify_tegap") 382 | 383 | type(xfoil_data_group), intent(inout) :: xdg 384 | real(c_double), intent(in) :: gap, blendloc 385 | integer(c_int), intent(out) :: npointout, stat 386 | 387 | ! Check that buffer airfoil is set 388 | 389 | stat = 0 390 | if (xdg%xfd%NB == 0) then 391 | stat = 1 392 | return 393 | end if 394 | 395 | ! Modify trailing edge gap 396 | 397 | call TGAP(xdg%xfd, gap, blendloc) 398 | 399 | ! Get new buffer airfoil points (may have changed) 400 | 401 | npointout = xdg%xfd%NB 402 | 403 | end subroutine xfoil_modify_tegap 404 | 405 | !=============================================================================80 406 | ! 407 | ! Gets thickness and camber information for the current (not buffer) airfoil 408 | ! stat: 0 for success, 1 if current airfoil is not available (call 409 | ! xfoil_smooth_paneling first) 410 | ! 411 | !=============================================================================80 412 | subroutine xfoil_geometry_info(xdg, maxt, xmaxt, maxc, xmaxc, stat) & 413 | bind(c, name="xfoil_geometry_info") 414 | 415 | type(xfoil_data_group), intent(in) :: xdg 416 | real(c_double), intent(out) :: maxt, xmaxt, maxc, xmaxc 417 | integer(c_int), intent(out) :: stat 418 | 419 | ! Check that airfoil is available 420 | 421 | stat = 0 422 | if (xdg%xfd%N == 0) then 423 | stat = 1 424 | return 425 | end if 426 | 427 | maxt = xdg%xfd%THICKB 428 | xmaxt = xdg%xfd%XTHICKB 429 | maxc = xdg%xfd%CAMBR 430 | xmaxc = xdg%xfd%XCAMBR 431 | 432 | end subroutine xfoil_geometry_info 433 | 434 | !=============================================================================80 435 | ! 436 | ! Sets Reynolds number for viscous calculations 437 | ! 438 | !=============================================================================80 439 | subroutine xfoil_set_reynolds_number(xdg, re) & 440 | bind(c, name="xfoil_set_reynolds_number") 441 | 442 | type(xfoil_data_group), intent(inout) :: xdg 443 | real(c_double), intent(in) :: re 444 | 445 | xdg%xfd%REINF1 = re 446 | 447 | end subroutine xfoil_set_reynolds_number 448 | 449 | !=============================================================================80 450 | ! 451 | ! Sets Mach number 452 | ! 453 | !=============================================================================80 454 | subroutine xfoil_set_mach_number(xdg, mach) & 455 | bind(c, name="xfoil_set_mach_number") 456 | 457 | type(xfoil_data_group), intent(inout) :: xdg 458 | real(c_double), intent(in) :: mach 459 | 460 | call MINFSET(xdg%xfd, mach) 461 | 462 | end subroutine xfoil_set_mach_number 463 | 464 | !=============================================================================80 465 | ! 466 | ! Resets BL initialization flags in xfoil, so BL will be reinitialized at next 467 | ! point 468 | ! 469 | !=============================================================================80 470 | subroutine xfoil_reinitialize_bl(xdg) bind(c, name="xfoil_reinitialize_bl") 471 | 472 | type(xfoil_data_group), intent(inout) :: xdg 473 | 474 | xdg%xfd%LIPAN = .false. 475 | xdg%xfd%LBLINI = .false. 476 | 477 | end subroutine xfoil_reinitialize_bl 478 | 479 | !=============================================================================80 480 | ! 481 | ! Runs Xfoil at a specified angle of attack 482 | ! Assumes airfoil geometry, reynolds number, and mach number have already been 483 | ! set in Xfoil. 484 | ! stat: 0 for success, 1 if current airfoil is not available (call 485 | ! xfoil_smooth_paneling first) 486 | ! 487 | !=============================================================================80 488 | subroutine xfoil_specal(xdg, alpha_spec, alpha, lift, drag, moment, converged, & 489 | stat) bind(c, name="xfoil_specal") 490 | 491 | type(xfoil_data_group), intent(inout) :: xdg 492 | real(c_double), intent(in) :: alpha_spec 493 | real(c_double), intent(out) :: alpha, lift, drag, moment 494 | logical(c_bool), intent(out) :: converged 495 | integer(c_int), intent(out) :: stat 496 | 497 | ! Check that airfoil is available 498 | 499 | stat = 0 500 | if (xdg%xfd%N == 0) then 501 | stat = 1 502 | return 503 | end if 504 | 505 | ! Inviscid calculations for specified angle of attack 506 | 507 | converged = .true. 508 | xdg%xfd%LALFA = .true. 509 | xdg%xfd%ALFA = alpha_spec*xdg%xfd%DTOR 510 | call SPECAL(xdg%xfd) 511 | if (abs(xdg%xfd%ALFA-xdg%xfd%AWAKE) .GT. 1.0D-5) xdg%xfd%LWAKE = .false. 512 | if (abs(xdg%xfd%ALFA-xdg%xfd%AVISC) .GT. 1.0D-5) xdg%xfd%LVCONV = .false. 513 | if (abs(xdg%xfd%MINF-xdg%xfd%MVISC) .GT. 1.0D-5) xdg%xfd%LVCONV = .false. 514 | 515 | ! Viscous calculations (if requested) 516 | 517 | if (xdg%xfd%VISCOUS_MODE) then 518 | call VISCAL(xdg%xfd, xdg%bld, xdg%xbd, xdg%xfd%MAXIT) 519 | converged = xdg%xfd%LVCONV 520 | end if 521 | 522 | ! Outputs 523 | 524 | alpha = xdg%xfd%ALFA/xdg%xfd%DTOR 525 | lift = xdg%xfd%CL 526 | moment = xdg%xfd%CM 527 | if (xdg%xfd%VISCOUS_MODE) then 528 | drag = xdg%xfd%CD 529 | else 530 | drag = xdg%xfd%CDP 531 | end if 532 | 533 | end subroutine xfoil_specal 534 | 535 | !=============================================================================80 536 | ! 537 | ! Runs Xfoil at a specified lift coefficient 538 | ! Assumes airfoil geometry, reynolds number, and mach number have already been 539 | ! set in Xfoil. 540 | ! stat: 0 for success, 1 if current airfoil is not available (call 541 | ! xfoil_smooth_paneling first) 542 | ! 543 | !=============================================================================80 544 | subroutine xfoil_speccl(xdg, cl_spec, alpha, lift, drag, moment, converged, & 545 | stat) bind(c, name="xfoil_speccl") 546 | 547 | type(xfoil_data_group), intent(inout) :: xdg 548 | real(c_double), intent(in) :: cl_spec 549 | real(c_double), intent(out) :: alpha, lift, drag, moment 550 | logical(c_bool), intent(out) :: converged 551 | integer(c_int), intent(out) :: stat 552 | 553 | ! Check that airfoil is available 554 | 555 | stat = 0 556 | if (xdg%xfd%N == 0) then 557 | stat = 1 558 | return 559 | end if 560 | 561 | ! Inviscid calculations for specified lift coefficient 562 | 563 | converged = .true. 564 | xdg%xfd%LALFA = .false. 565 | xdg%xfd%ALFA = 0.d0 566 | xdg%xfd%CLSPEC = cl_spec 567 | call SPECCL(xdg%xfd) 568 | if (abs(xdg%xfd%ALFA-xdg%xfd%AWAKE) .GT. 1.0D-5) xdg%xfd%LWAKE = .false. 569 | if (abs(xdg%xfd%ALFA-xdg%xfd%AVISC) .GT. 1.0D-5) xdg%xfd%LVCONV = .false. 570 | if (abs(xdg%xfd%MINF-xdg%xfd%MVISC) .GT. 1.0D-5) xdg%xfd%LVCONV = .false. 571 | 572 | ! Viscous calculations (if requested) 573 | 574 | if (xdg%xfd%VISCOUS_MODE) then 575 | call VISCAL(xdg%xfd, xdg%bld, xdg%xbd, xdg%xfd%MAXIT) 576 | converged = xdg%xfd%LVCONV 577 | end if 578 | 579 | ! Outputs 580 | 581 | alpha = xdg%xfd%ALFA/xdg%xfd%DTOR 582 | lift = xdg%xfd%CL 583 | moment = xdg%xfd%CM 584 | if (xdg%xfd%VISCOUS_MODE) then 585 | drag = xdg%xfd%CD 586 | else 587 | drag = xdg%xfd%CDP 588 | end if 589 | 590 | end subroutine xfoil_speccl 591 | 592 | !=============================================================================80 593 | ! 594 | ! Returns transition locations on top and bottom in x and z 595 | ! 596 | !=============================================================================80 597 | subroutine xfoil_get_transloc(xdg, xtranst, ztranst, xtransb, ztransb) & 598 | bind(c, name="xfoil_get_transloc") 599 | 600 | use iso_c_binding 601 | type(xfoil_data_group), intent(in) :: xdg 602 | real(c_double), intent(out) :: xtranst, ztranst, xtransb, ztransb 603 | 604 | real(c_double), pointer :: XOCTR(:) 605 | real(c_double), pointer :: YOCTR(:) 606 | 607 | call c_f_pointer(xdg%xfd%XOCTR, XOCTR, [ISX]) 608 | call c_f_pointer(xdg%xfd%YOCTR, YOCTR, [ISX]) 609 | 610 | xtranst = XOCTR(1) 611 | ztranst = YOCTR(1) 612 | xtransb = XOCTR(2) 613 | ztransb = YOCTR(2) 614 | 615 | end subroutine xfoil_get_transloc 616 | 617 | !=============================================================================80 618 | ! 619 | ! Returns cp on surface 620 | ! 621 | !=============================================================================80 622 | subroutine xfoil_get_cp(xdg, npoint, cp) bind(c, name="xfoil_get_cp") 623 | 624 | use iso_c_binding 625 | type(xfoil_data_group), intent(in) :: xdg 626 | integer(c_int), intent(in) :: npoint 627 | real(c_double), dimension(npoint), intent(out) :: cp 628 | 629 | real(c_double), pointer :: CPV(:) 630 | real(c_double), pointer :: CPI(:) 631 | 632 | call c_f_pointer(xdg%xfd%CPV, CPV, [IZX]) 633 | call c_f_pointer(xdg%xfd%CPI, CPI, [IZX]) 634 | 635 | if (xdg%xfd%VISCOUS_MODE) then 636 | cp(1:npoint) = CPV(1:npoint) 637 | else 638 | cp(1:npoint) = CPI(1:npoint) 639 | end if 640 | 641 | end subroutine xfoil_get_cp 642 | 643 | !=============================================================================80 644 | ! 645 | ! Returns skin friction coefficient on surface 646 | ! 647 | !=============================================================================80 648 | subroutine xfoil_get_cf(xdg, npoint, cf) bind(c, name="xfoil_get_cf") 649 | 650 | use iso_c_binding 651 | type(xfoil_data_group), intent(in) :: xdg 652 | integer(c_int), intent(in) :: npoint 653 | real(c_double), dimension(npoint), intent(out) :: cf 654 | 655 | integer(c_int) :: is, ibl, i 656 | real(c_double) :: que 657 | 658 | integer(c_int), pointer :: NBL(:) 659 | integer(c_int), pointer :: IPAN(:,:) 660 | real(c_double), pointer :: TAU(:,:) 661 | 662 | call c_f_pointer(xdg%xfd%NBL, NBL, [ISX]) 663 | call c_f_pointer(xdg%xfd%IPAN, IPAN, [IVX,ISX]) 664 | call c_f_pointer(xdg%xfd%TAU, TAU, [IVX,ISX]) 665 | 666 | que = 0.5d0*xdg%xfd%QINF**2.d0 667 | 668 | ! Populate skin friction array, going over upper surface and then lower surface 669 | 670 | do is = 1, 2 671 | do ibl = 2, NBL(is) 672 | i = IPAN(ibl,is) 673 | 674 | ! Xfoil BL arrays include wake; only accept surface points here 675 | 676 | if (i <= npoint) cf(i) = TAU(ibl,is) / que 677 | 678 | end do 679 | end do 680 | 681 | end subroutine xfoil_get_cf 682 | 683 | !=============================================================================80 684 | ! 685 | ! Returns BL edge velocity on surface 686 | ! 687 | !=============================================================================80 688 | subroutine xfoil_get_uedge(xdg, npoint, uedge) bind(c, name="xfoil_get_uedge") 689 | 690 | use iso_c_binding 691 | type(xfoil_data_group), intent(in) :: xdg 692 | integer(c_int), intent(in) :: npoint 693 | real(c_double), dimension(npoint), intent(out) :: uedge 694 | 695 | integer(c_int) :: is, ibl, i 696 | real(c_double) :: uei 697 | 698 | integer(c_int), pointer :: NBL(:) 699 | integer(c_int), pointer :: IPAN(:,:) 700 | real(c_double), pointer :: UEDG(:,:) 701 | 702 | call c_f_pointer(xdg%xfd%NBL, NBL, [ISX]) 703 | call c_f_pointer(xdg%xfd%IPAN, IPAN, [IVX,ISX]) 704 | call c_f_pointer(xdg%xfd%UEDG, UEDG, [IVX,ISX]) 705 | 706 | ! Populate uedge array, going over upper surface and then lower surface 707 | 708 | do is = 1, 2 709 | do ibl = 2, NBL(is) 710 | i = IPAN(ibl,is) 711 | 712 | ! Xfoil BL arrays include wake; only accept surface points here 713 | 714 | if (i <= npoint) then 715 | uei = UEDG(ibl,is) 716 | uedge(i) = uei * (1.d0-xdg%xfd%TKLAM) / & 717 | (1.d0 - xdg%xfd%TKLAM*(uei/xdg%xfd%QINF)**2.d0) 718 | end if 719 | 720 | end do 721 | end do 722 | 723 | end subroutine xfoil_get_uedge 724 | 725 | !=============================================================================80 726 | ! 727 | ! Returns BL displacement thickness on surface 728 | ! 729 | !=============================================================================80 730 | subroutine xfoil_get_deltastar(xdg, npoint, deltastar) & 731 | bind(c, name="xfoil_get_deltastar") 732 | 733 | use iso_c_binding 734 | type(xfoil_data_group), intent(in) :: xdg 735 | integer(c_int), intent(in) :: npoint 736 | real(c_double), dimension(npoint), intent(out) :: deltastar 737 | 738 | integer(c_int) :: is, ibl, i 739 | 740 | integer(c_int), pointer :: NBL(:) 741 | integer(c_int), pointer :: IPAN(:,:) 742 | real(c_double), pointer :: DSTR(:,:) 743 | 744 | call c_f_pointer(xdg%xfd%NBL, NBL, [ISX]) 745 | call c_f_pointer(xdg%xfd%IPAN, IPAN, [IVX,ISX]) 746 | call c_f_pointer(xdg%xfd%DSTR, DSTR, [IVX,ISX]) 747 | 748 | ! Populate deltastar array, going over upper surface and then lower surface 749 | 750 | do is = 1, 2 751 | do ibl = 2, NBL(is) 752 | i = IPAN(ibl,is) 753 | 754 | ! Xfoil BL arrays include wake; only accept surface points here 755 | 756 | if (i <= npoint) then 757 | deltastar(i) = DSTR(ibl,is) 758 | end if 759 | 760 | end do 761 | end do 762 | 763 | end subroutine xfoil_get_deltastar 764 | 765 | !=============================================================================80 766 | ! 767 | ! Returns BL dissipation coefficient on surface 768 | ! 769 | !=============================================================================80 770 | subroutine xfoil_get_diss(xdg, npoint, diss) bind(c, name="xfoil_get_diss") 771 | 772 | use iso_c_binding 773 | type(xfoil_data_group), intent(in) :: xdg 774 | integer(c_int), intent(in) :: npoint 775 | real(c_double), dimension(npoint), intent(out) :: diss 776 | 777 | integer(c_int) :: is, ibl, i 778 | 779 | integer(c_int), pointer :: NBL(:) 780 | integer(c_int), pointer :: IPAN(:,:) 781 | real(c_double), pointer :: DIS(:,:) 782 | 783 | call c_f_pointer(xdg%xfd%NBL, NBL, [ISX]) 784 | call c_f_pointer(xdg%xfd%IPAN, IPAN, [IVX,ISX]) 785 | call c_f_pointer(xdg%xfd%DIS, DIS, [IVX,ISX]) 786 | 787 | ! Populate diss array, going over upper surface and then lower surface 788 | 789 | do is = 1, 2 790 | do ibl = 2, NBL(is) 791 | i = IPAN(ibl,is) 792 | 793 | ! Xfoil BL arrays include wake; only accept surface points here 794 | 795 | if (i <= npoint) then 796 | diss(i) = DIS(ibl,is) / xdg%xfd%QINF**3.d0 797 | end if 798 | 799 | end do 800 | end do 801 | 802 | end subroutine xfoil_get_diss 803 | 804 | !=============================================================================80 805 | ! 806 | ! Returns BL kinematic shape parameter on surface 807 | ! 808 | !=============================================================================80 809 | subroutine xfoil_get_hk(xdg, npoint, hk) bind(c, name="xfoil_get_hk") 810 | 811 | use iso_c_binding 812 | type(xfoil_data_group), intent(in) :: xdg 813 | integer(c_int), intent(in) :: npoint 814 | real(c_double), dimension(npoint), intent(out) :: hk 815 | 816 | integer(c_int) :: is, ibl, i 817 | real(c_double) :: thi, dsi, uei, uc, amsq, dummy 818 | 819 | integer(c_int), pointer :: NBL(:) 820 | integer(c_int), pointer :: IPAN(:,:) 821 | real(c_double), pointer :: THET(:,:) 822 | real(c_double), pointer :: DSTR(:,:) 823 | real(c_double), pointer :: UEDG(:,:) 824 | 825 | call c_f_pointer(xdg%xfd%NBL, NBL, [ISX]) 826 | call c_f_pointer(xdg%xfd%IPAN, IPAN, [IVX,ISX]) 827 | call c_f_pointer(xdg%xfd%THET, THET, [IVX,ISX]) 828 | call c_f_pointer(xdg%xfd%DSTR, DSTR, [IVX,ISX]) 829 | call c_f_pointer(xdg%xfd%UEDG, UEDG, [IVX,ISX]) 830 | 831 | ! Populate hk array, going over upper surface and then lower surface 832 | 833 | do is = 1, 2 834 | do ibl = 2, NBL(is) 835 | i = IPAN(ibl,is) 836 | 837 | ! Xfoil BL arrays include wake; only accept surface points here 838 | 839 | if (i <= npoint) then 840 | thi = THET(ibl,is) 841 | dsi = DSTR(ibl,is) 842 | uei = UEDG(ibl,is) 843 | uc = uei * (1.d0-xdg%xfd%TKLAM) / & 844 | (1.d0 - xdg%xfd%TKLAM*(uei/xdg%xfd%QINF)**2.d0) 845 | amsq = uc*uc*xdg%xbd%HSTINV / & 846 | (xdg%xfd%GAMM1*(1.d0 - 0.5d0*uc*uc*xdg%xbd%HSTINV)) 847 | call HKIN(dsi/thi, amsq, hk(i), dummy, dummy) 848 | end if 849 | 850 | end do 851 | end do 852 | 853 | end subroutine xfoil_get_hk 854 | 855 | !=============================================================================80 856 | ! 857 | ! Returns BL momentum thickness Reynolds number on surface 858 | ! 859 | !=============================================================================80 860 | subroutine xfoil_get_retheta(xdg, npoint, retheta) & 861 | bind(c, name="xfoil_get_retheta") 862 | 863 | use iso_c_binding 864 | type(xfoil_data_group), intent(in) :: xdg 865 | integer(c_int), intent(in) :: npoint 866 | real(c_double), dimension(npoint), intent(out) :: retheta 867 | 868 | integer(c_int) :: is, ibl, i 869 | real(c_double) :: uei, ue, herat, rhoe, amue 870 | 871 | ! Sutherland's constant/To (assumes stagnation conditions are at STP) 872 | 873 | real(c_double), parameter :: hvrat = 0.35d0 874 | 875 | integer(c_int), pointer :: NBL(:) 876 | integer(c_int), pointer :: IPAN(:,:) 877 | real(c_double), pointer :: UEDG(:,:) 878 | real(c_double), pointer :: THET(:,:) 879 | 880 | call c_f_pointer(xdg%xfd%NBL, NBL, [ISX]) 881 | call c_f_pointer(xdg%xfd%IPAN, IPAN, [IVX,ISX]) 882 | call c_f_pointer(xdg%xfd%UEDG, UEDG, [IVX,ISX]) 883 | call c_f_pointer(xdg%xfd%THET, THET, [IVX,ISX]) 884 | 885 | ! Populate ampl array, going over upper surface and then lower surface 886 | 887 | do is = 1, 2 888 | do ibl = 2, NBL(is) 889 | i = IPAN(ibl,is) 890 | 891 | ! Xfoil BL arrays include wake; only accept surface points here 892 | 893 | if (i <= npoint) then 894 | uei = UEDG(ibl,is) 895 | ue = uei * (1.d0-xdg%xfd%TKLAM) / & 896 | (1.d0 - xdg%xfd%TKLAM*(uei/xdg%xfd%QINF)**2.d0) 897 | herat = (1.d0 - 0.5d0*xdg%xbd%HSTINV*uei**2.d0) & 898 | / (1.d0 - 0.5d0*xdg%xbd%HSTINV*xdg%xfd%QINF**2.d0) 899 | rhoe = herat**(1.d0/xdg%xfd%GAMM1) 900 | amue = sqrt(herat**3.d0) * (1.d0+hvrat)/(herat+hvrat) 901 | retheta(i) = xdg%xfd%REINF * rhoe*ue*THET(ibl,is)/amue 902 | end if 903 | 904 | end do 905 | end do 906 | 907 | end subroutine xfoil_get_retheta 908 | 909 | !=============================================================================80 910 | ! 911 | ! Returns amplification ratio N 912 | ! 913 | !=============================================================================80 914 | subroutine xfoil_get_ampl(xdg, npoint, ampl) bind(c, name="xfoil_get_ampl") 915 | 916 | use iso_c_binding 917 | type(xfoil_data_group), intent(in) :: xdg 918 | integer(c_int), intent(in) :: npoint 919 | real(c_double), dimension(npoint), intent(out) :: ampl 920 | 921 | integer(c_int) :: is, ibl, i 922 | 923 | integer(c_int), pointer :: NBL(:) 924 | integer(c_int), pointer :: IPAN(:,:) 925 | real(c_double), pointer :: X(:) 926 | real(c_double), pointer :: XOCTR(:) 927 | real(c_double), pointer :: CTAU(:,:) 928 | 929 | call c_f_pointer(xdg%xfd%NBL, NBL, [ISX]) 930 | call c_f_pointer(xdg%xfd%IPAN, IPAN, [IVX,ISX]) 931 | call c_f_pointer(xdg%xfd%X, X, [IZX]) 932 | call c_f_pointer(xdg%xfd%XOCTR, XOCTR, [ISX]) 933 | call c_f_pointer(xdg%xfd%CTAU, CTAU, [IVX,ISX]) 934 | 935 | ! Populate ampl array, going over upper surface and then lower surface 936 | 937 | do is = 1, 2 938 | do ibl = 2, NBL(is) 939 | i = IPAN(ibl,is) 940 | 941 | ! Xfoil BL arrays include wake; only accept surface points here 942 | 943 | if (i <= npoint) then 944 | ! In laminar regions, CTAU is log of amplification ratio. In turbulent 945 | ! regions, we'll just set it to ACRIT 946 | if (X(i) <= XOCTR(is)) then 947 | ampl(i) = CTAU(ibl,is) 948 | else 949 | ampl(i) = xdg%xfd%ACRIT 950 | end if 951 | end if 952 | 953 | end do 954 | end do 955 | 956 | end subroutine xfoil_get_ampl 957 | 958 | !=============================================================================80 959 | ! 960 | ! Returns number of wake points 961 | ! 962 | !=============================================================================80 963 | subroutine xfoil_get_wakepoints(xdg, nwake) bind(c, name="xfoil_get_wakepoints") 964 | 965 | use iso_c_binding 966 | type(xfoil_data_group), intent(in) :: xdg 967 | integer(c_int), intent(out) :: nwake 968 | 969 | nwake = xdg%xfd%NW 970 | 971 | end subroutine xfoil_get_wakepoints 972 | 973 | !=============================================================================80 974 | ! 975 | ! Returns wake X and Z coordinates 976 | ! 977 | !=============================================================================80 978 | subroutine xfoil_get_wake_geometry(xdg, nwake, xw, zw) & 979 | bind(c, name="xfoil_get_wake_geometry") 980 | 981 | use iso_c_binding 982 | type(xfoil_data_group), intent(in) :: xdg 983 | integer(c_int), intent(in) :: nwake 984 | real(c_double), dimension(nwake), intent(out) :: xw, zw 985 | 986 | integer(c_int) :: i 987 | 988 | real(c_double), pointer :: X(:) 989 | real(c_double), pointer :: Y(:) 990 | 991 | call c_f_pointer(xdg%xfd%X, X, [IZX]) 992 | call c_f_pointer(xdg%xfd%Y, Y, [IZX]) 993 | 994 | do i = xdg%xfd%N+1, xdg%xfd%N+xdg%xfd%NW 995 | xw(i-xdg%xfd%N) = X(i) 996 | zw(i-xdg%xfd%N) = Y(i) 997 | end do 998 | 999 | end subroutine xfoil_get_wake_geometry 1000 | 1001 | !=============================================================================80 1002 | ! 1003 | ! Returns cp in wake 1004 | ! 1005 | !=============================================================================80 1006 | subroutine xfoil_get_wake_cp(xdg, nwake, cp) bind(c, name="xfoil_get_wake_cp") 1007 | 1008 | use iso_c_binding 1009 | type(xfoil_data_group), intent(in) :: xdg 1010 | integer(c_int), intent(in) :: nwake 1011 | real(c_double), dimension(nwake), intent(out) :: cp 1012 | 1013 | real(c_double), pointer :: CPV(:) 1014 | real(c_double), pointer :: CPI(:) 1015 | 1016 | call c_f_pointer(xdg%xfd%CPV, CPV, [IZX]) 1017 | call c_f_pointer(xdg%xfd%CPI, CPI, [IZX]) 1018 | 1019 | if (xdg%xfd%VISCOUS_MODE) then 1020 | cp(1:nwake) = CPV(xdg%xfd%N+1:xdg%xfd%NW) 1021 | else 1022 | cp(1:nwake) = CPI(xdg%xfd%N+1:xdg%xfd%NW) 1023 | end if 1024 | 1025 | end subroutine xfoil_get_wake_cp 1026 | 1027 | !=============================================================================80 1028 | ! 1029 | ! Returns BL edge velocity in wake 1030 | ! 1031 | !=============================================================================80 1032 | subroutine xfoil_get_wake_uedge(xdg, nwake, uedge) & 1033 | bind(c, name="xfoil_get_wake_uedge") 1034 | 1035 | use iso_c_binding 1036 | type(xfoil_data_group), intent(in) :: xdg 1037 | integer(c_int), intent(in) :: nwake 1038 | real(c_double), dimension(nwake), intent(out) :: uedge 1039 | 1040 | integer(c_int) :: i, nside 1041 | real(c_double) :: uei 1042 | 1043 | integer(c_int), pointer :: IBLTE(:) 1044 | integer(c_int), pointer :: NBL(:) 1045 | real(c_double), pointer :: UEDG(:,:) 1046 | 1047 | call c_f_pointer(xdg%xfd%IBLTE, IBLTE, [ISX]) 1048 | call c_f_pointer(xdg%xfd%NBL, NBL, [ISX]) 1049 | call c_f_pointer(xdg%xfd%UEDG, UEDG, [IVX,ISX]) 1050 | 1051 | ! Populate uedge array, taking points only from upper surface wake (lower 1052 | ! surface wake is the same) 1053 | 1054 | nside = NBL(2) + IBLTE(1) - IBLTE(2) 1055 | do i = IBLTE(1)+1, nside 1056 | uei = UEDG(i,1) 1057 | uedge(i-IBLTE(1)) = uei * (1.d0 - xdg%xfd%TKLAM) / & 1058 | (1.d0 - xdg%xfd%TKLAM*(uei/xdg%xfd%QINF)**2.d0) 1059 | end do 1060 | 1061 | end subroutine xfoil_get_wake_uedge 1062 | 1063 | !=============================================================================80 1064 | ! 1065 | ! Returns BL displacement thickness in wake 1066 | ! 1067 | !=============================================================================80 1068 | subroutine xfoil_get_wake_deltastar(xdg, nwake, deltastar) & 1069 | bind(c, name="xfoil_get_wake_deltastar") 1070 | 1071 | use iso_c_binding 1072 | type(xfoil_data_group), intent(in) :: xdg 1073 | integer(c_int), intent(in) :: nwake 1074 | real(c_double), dimension(nwake), intent(out) :: deltastar 1075 | 1076 | integer(c_int) :: i, nside 1077 | 1078 | integer(c_int), pointer :: IBLTE(:) 1079 | integer(c_int), pointer :: NBL(:) 1080 | real(c_double), pointer :: DSTR(:,:) 1081 | 1082 | call c_f_pointer(xdg%xfd%IBLTE, IBLTE, [ISX]) 1083 | call c_f_pointer(xdg%xfd%NBL, NBL, [ISX]) 1084 | call c_f_pointer(xdg%xfd%DSTR, DSTR, [IVX,ISX]) 1085 | 1086 | ! Populate uedge array, taking points only from upper surface wake (lower 1087 | ! surface wake is the same) 1088 | 1089 | nside = NBL(2) + IBLTE(1) - IBLTE(2) 1090 | do i = IBLTE(1)+1, nside 1091 | deltastar(i-IBLTE(1)) = DSTR(i,1) 1092 | end do 1093 | 1094 | end subroutine xfoil_get_wake_deltastar 1095 | 1096 | !=============================================================================80 1097 | ! 1098 | ! Subroutine to analyze an airfoil in a loop over a number of operating points. 1099 | ! 1100 | ! Inputs: 1101 | ! npointin: number of points in airfoil coordinates 1102 | ! xin, zin: airfoil coordinates 1103 | ! geom_opts: Xfoil paneling settings 1104 | ! noppoints: number of operating points to analyze 1105 | ! operating_points: specified AoA or Cl for each point 1106 | ! op_modes: indicates whether each operating_point specifies an AoA or Cl. 1107 | ! 0 => AoA, 1 => Cl 1108 | ! reynolds_numbers, mach_numbers: Re and Mach for each operating point 1109 | ! use_flap: T or F; whether flap deflections will be applied 1110 | ! x_flap, z_flap: x and z flap hinge coordinates 1111 | ! z_flap_spec: 0 => z_flap = z/c, 1 => z_flap = z/local_thickness 1112 | ! flap_degrees: flap deflection at each operating point (+ve down) 1113 | ! xfoil_opts: Xfoil run settings 1114 | ! reinitialize: T or F; whether to always reinitialize the BL at each point 1115 | ! fix_unconverged: T or F; if true, for any points that fail to converge, 1116 | ! will try to initialize the BL at a point closer to Cl = 0, and then 1117 | ! run again at the original operating point 1118 | ! 1119 | ! Outputs: 1120 | ! alpha, Cl, Cd, Cm, and x/c transition locations at each operating point 1121 | ! viscrms: rms for viscous calculations (check for convergence) 1122 | ! 1123 | !=============================================================================80 1124 | subroutine run_xfoil(npointin, xin, zin, geom_opts, noppoint, operating_points,& 1125 | op_modes, reynolds_numbers, mach_numbers, use_flap, & 1126 | x_flap, z_flap, z_flap_spec, flap_degrees, xfoil_opts, & 1127 | reinitialize, fix_unconverged, lift, drag, moment, & 1128 | viscrms, alpha, xtrt, xtrb, stat) bind(c, name="run_xfoil") 1129 | 1130 | integer(c_int), intent(in) :: npointin, noppoint 1131 | real(c_double), dimension(npointin), intent(in) :: xin, zin 1132 | type(xfoil_geom_options_type), intent(in) :: geom_opts 1133 | real(c_double), dimension(noppoint), intent(in) :: operating_points, & 1134 | reynolds_numbers, mach_numbers, flap_degrees 1135 | real(c_double), intent(in) :: x_flap, z_flap 1136 | integer(c_int), intent(in) :: z_flap_spec 1137 | type(xfoil_options_type), intent(in) :: xfoil_opts 1138 | logical(c_bool), intent(in) :: use_flap, reinitialize, fix_unconverged 1139 | integer(c_int), dimension(noppoint), intent(in) :: op_modes 1140 | real(c_double), dimension(noppoint), intent(out) :: lift, drag, moment, & 1141 | viscrms 1142 | real(c_double), dimension(noppoint), intent(out) :: alpha, xtrt, xtrb 1143 | integer(c_int), intent(out) :: stat 1144 | 1145 | type(xfoil_data_group) :: xdg 1146 | integer(c_int) :: i, dummy 1147 | logical(c_bool), dimension(noppoint) :: point_converged, point_fixed 1148 | real(c_double) :: newpoint, ztrt, ztrb 1149 | character(30) :: text 1150 | character(150) :: message 1151 | 1152 | if (.not. xfoil_opts%silent_mode) then 1153 | write(*,*) 1154 | write(*,*) 'Analyzing aerodynamics using the XFOIL engine ...' 1155 | end if 1156 | 1157 | point_converged(:) = .true. 1158 | point_fixed(:) = .false. 1159 | 1160 | ! Set xfoil defaults and paneling settings 1161 | 1162 | call xfoil_init(xdg) 1163 | call xfoil_defaults(xdg, xfoil_opts) 1164 | call xfoil_set_paneling(xdg, geom_opts) 1165 | 1166 | ! Set airfoil and smooth paneling 1167 | 1168 | if (.not. use_flap) then 1169 | call xfoil_set_buffer_airfoil(xdg, xin, zin, npointin) 1170 | call xfoil_smooth_paneling(xdg, stat) 1171 | if (stat /= 0) return 1172 | end if 1173 | 1174 | ! Run xfoil for requested operating points 1175 | 1176 | lift(:) = 0.d0 1177 | drag(:) = 0.d0 1178 | moment(:) = 0.d0 1179 | viscrms(:) = 0.d0 1180 | 1181 | ! Run xfoil for requested operating points 1182 | 1183 | run_oppoints: do i = 1, noppoint 1184 | 1185 | ! Reset airfoil, smooth paneling, and apply flap deflection 1186 | 1187 | if (use_flap) then 1188 | call xfoil_set_buffer_airfoil(xdg, xin, zin, npointin) 1189 | call xfoil_smooth_paneling(xdg, stat) 1190 | call xfoil_apply_flap_deflection(xdg, x_flap, z_flap, z_flap_spec, & 1191 | flap_degrees(i), dummy, stat) 1192 | end if 1193 | 1194 | call xfoil_set_reynolds_number(xdg, reynolds_numbers(i)) 1195 | call xfoil_set_mach_number(xdg, mach_numbers(i)) 1196 | 1197 | if (reinitialize) call xfoil_reinitialize_bl(xdg) 1198 | 1199 | if (op_modes(i) == 0) then 1200 | 1201 | call xfoil_specal(xdg, operating_points(i), alpha(i), lift(i), drag(i), & 1202 | moment(i), point_converged(i), stat) 1203 | 1204 | elseif (op_modes(i) == 1) then 1205 | 1206 | call xfoil_speccl(xdg, operating_points(i), alpha(i), lift(i), drag(i), & 1207 | moment(i), point_converged(i), stat) 1208 | 1209 | else 1210 | 1211 | write(*,*) 1212 | write(*,*) "Error in run_xfoil: op_mode must be 0 or 1." 1213 | write(*,*) 1214 | stop 1215 | 1216 | end if 1217 | 1218 | ! Additional outputs 1219 | 1220 | call xfoil_get_transloc(xdg, xtrt(i), ztrt, xtrb(i), ztrb) 1221 | 1222 | ! Handling of unconverged points 1223 | 1224 | if (xfoil_opts%viscous_mode .and. .not. point_converged(i)) then 1225 | 1226 | if (fix_unconverged) then 1227 | 1228 | ! Try to initialize BL at new point (in the direction away from stall) 1229 | 1230 | newpoint = operating_points(i) - 0.5d0*abs(operating_points(i))*sign( & 1231 | 1.d0, operating_points(i)) 1232 | if (newpoint == 0.d0) newpoint = 0.1d0 1233 | 1234 | call xfoil_reinitialize_bl(xdg) 1235 | if (op_modes(i) == 0) then 1236 | call xfoil_specal(xdg, newpoint, alpha(i), lift(i), drag(i), & 1237 | moment(i), point_converged(i), stat) 1238 | else 1239 | call xfoil_speccl(xdg, newpoint, alpha(i), lift(i), drag(i), & 1240 | moment(i), point_converged(i), stat) 1241 | end if 1242 | 1243 | ! Now try to run again at the old operating point 1244 | 1245 | if (op_modes(i) == 0) then 1246 | call xfoil_specal(xdg, operating_points(i), alpha(i), lift(i), & 1247 | drag(i), moment(i), point_converged(i), stat) 1248 | else 1249 | call xfoil_speccl(xdg, operating_points(i), alpha(i), lift(i), & 1250 | drag(i), moment(i), point_converged(i), stat) 1251 | end if 1252 | 1253 | if (point_converged(i)) point_fixed(i) = .true. 1254 | 1255 | call xfoil_get_transloc(xdg, xtrt(i), ztrt, xtrb(i), ztrb) 1256 | 1257 | end if 1258 | end if 1259 | 1260 | ! Convergence check 1261 | 1262 | viscrms(i) = xdg%xfd%RMSBL 1263 | 1264 | end do run_oppoints 1265 | 1266 | ! Final check for NaNs 1267 | 1268 | do i = 1, noppoint 1269 | if (isnan(lift(i))) then 1270 | lift(i) = -1.D+08 1271 | viscrms(i) = 1.D+08 1272 | end if 1273 | if (isnan(drag(i))) then 1274 | drag(i) = 1.D+08 1275 | viscrms(i) = 1.D+08 1276 | end if 1277 | if (isnan(moment(i))) then 1278 | moment(i) = -1.D+08 1279 | viscrms(i) = 1.D+08 1280 | end if 1281 | if (isnan(viscrms(i))) then 1282 | viscrms(i) = 1.D+08 1283 | end if 1284 | end do 1285 | 1286 | ! Print warnings about unconverged points 1287 | 1288 | if (.not. xfoil_opts%silent_mode) then 1289 | 1290 | write(*,*) 1291 | 1292 | do i = 1, noppoint 1293 | 1294 | write(text,*) i 1295 | text = adjustl(text) 1296 | 1297 | if (point_converged(i)) then 1298 | message = 'Operating point '//trim(text)//' converged.' 1299 | elseif (.not. point_converged(i) .and. point_fixed(i)) then 1300 | message = 'Operating point '//trim(text)//' initially did not '// & 1301 | 'converge but was fixed.' 1302 | elseif (.not. point_converged(i) .and. .not. point_fixed(i)) then 1303 | message = 'Operating point '//trim(text)//' initially did not '// & 1304 | 'converge and was not fixed.' 1305 | end if 1306 | 1307 | write(*,*) trim(message) 1308 | 1309 | end do 1310 | end if 1311 | 1312 | call xfoil_cleanup(xdg) 1313 | 1314 | end subroutine run_xfoil 1315 | 1316 | !=============================================================================80 1317 | ! 1318 | ! Subroutine to generate a 4-digit NACA airfoil 1319 | ! Inputs: 1320 | ! camber: max MCL camber, as a percent 1321 | ! xcamber: location of max MCL camber point, as x/c 1322 | ! thick: max thickness, as a percent 1323 | ! npointside: number of points on each side (top and bottom) 1324 | ! Outputs: 1325 | ! xout: x coordinates 1326 | ! zout: z coordinates 1327 | ! nout: total number of points (2*npointside) 1328 | ! 1329 | !=============================================================================80 1330 | subroutine naca_4_digit(camber, xcamber, thick, npointside, xout, zout, nout) & 1331 | bind(c, name="naca_4_digit") 1332 | 1333 | real(c_double), intent(in) :: camber, xcamber, thick 1334 | integer(c_int), intent(in) :: npointside 1335 | real(c_double), dimension(2*npointside), intent(out) :: xout, zout 1336 | integer(c_int), intent(out) :: nout 1337 | 1338 | real(c_double), dimension(npointside) :: xx, yt, yc 1339 | 1340 | call NACA4(camber, xcamber, thick, xx, yt, yc, npointside, xout, zout, nout) 1341 | 1342 | end subroutine naca_4_digit 1343 | 1344 | !=============================================================================80 1345 | ! 1346 | ! Subroutine to generate a 5-digit NACA airfoil 1347 | ! Inputs: 1348 | ! des: 5-digit designation 1349 | ! npointside: number of points per side 1350 | ! Outputs: 1351 | ! xout: x coordinates 1352 | ! zout: z coordinates 1353 | ! nout: total number of points (2*npointside) 1354 | ! stat: 0 for success, 1 for failure 1355 | ! 1356 | !=============================================================================80 1357 | subroutine naca_5_digit(des, npointside, xout, zout, nout, stat) & 1358 | bind(c, name="naca_5_digit") 1359 | 1360 | character(c_char), dimension(5), intent(in) :: des 1361 | integer(c_int), intent(in) :: npointside 1362 | real(c_double), dimension(2*npointside), intent(out) :: xout, zout 1363 | integer(c_int), intent(out) :: nout, stat 1364 | 1365 | integer(c_int) :: ides, i 1366 | real(c_double), dimension(npointside) :: xx, yt, yc 1367 | character(5, kind=c_char) :: desfor 1368 | 1369 | do i = 1, 5 1370 | desfor(i:i) = des(i) 1371 | end do 1372 | read(desfor,'(I5)') ides 1373 | 1374 | call NACA5(ides, xx, yt, yc, npointside, xout, zout, nout) 1375 | if (ides == 0) then 1376 | stat = 1 1377 | else 1378 | stat = 0 1379 | end if 1380 | 1381 | end subroutine naca_5_digit 1382 | 1383 | !=============================================================================80 1384 | ! 1385 | ! Fits a spline to airfoil coordinates 1386 | ! 1387 | !=============================================================================80 1388 | subroutine xfoil_spline_coordinates(x, z, npt, s, xs, zs) & 1389 | bind(c, name="xfoil_spline_coordinates") 1390 | 1391 | real(c_double), dimension(npt), intent(in) :: x, z 1392 | integer(c_int), intent(in) :: npt 1393 | real(c_double), dimension(npt), intent(out) :: s, xs, zs 1394 | 1395 | call SCALC(x, z, s, npt) 1396 | call SEGSPL(x, xs, s, npt) 1397 | call SEGSPL(z, zs, s, npt) 1398 | 1399 | end subroutine xfoil_spline_coordinates 1400 | 1401 | !=============================================================================80 1402 | ! 1403 | ! Computes x and z at a given spline coordinate 1404 | ! 1405 | ! Inputs 1406 | ! x, z: buffer airfoil coordinates 1407 | ! s: arc length array (from xfoil_spline_coordinates) 1408 | ! xs, zs: splined airfoil coordinates (from xfoil_spline_coordinates) 1409 | ! npt: number of points in buffer coordinates 1410 | ! sc: arc length value to calculate xc and zc 1411 | ! 1412 | ! Outputs 1413 | ! xc, zc: coordinates at sc 1414 | ! 1415 | !=============================================================================80 1416 | subroutine xfoil_eval_spline(x, z, s, xs, zs, npt, sc, xc, zc) & 1417 | bind(c, name="xfoil_eval_spline") 1418 | 1419 | real(c_double), dimension(npt), intent(in) :: x, z, s, xs, zs 1420 | integer(c_int), intent(in) :: npt 1421 | real(c_double), intent(in) :: sc 1422 | real(c_double), intent(out) :: xc, zc 1423 | 1424 | interface 1425 | double precision function SEVAL(SS, X, XS, S, N) 1426 | integer, intent(in) :: N 1427 | double precision, intent(in) :: SS 1428 | double precision, dimension(N), intent(in) :: X, XS, S 1429 | end function SEVAL 1430 | end interface 1431 | 1432 | xc = SEVAL(sc, x, xs, s, npt) 1433 | zc = SEVAL(sc, z, zs, s, npt) 1434 | 1435 | end subroutine xfoil_eval_spline 1436 | 1437 | !=============================================================================80 1438 | ! 1439 | ! Computes leading edge arc length, x, and z 1440 | ! 1441 | ! Inputs 1442 | ! x, z: buffer airfoil coordinates 1443 | ! s: arc length array (from xfoil_spline_coordinates) 1444 | ! xs, zs: splined airfoil coordinates (from xfoil_spline_coordinates) 1445 | ! npt: number of points in buffer coordinates 1446 | ! 1447 | ! Outputs 1448 | ! sle: leading edge arc length 1449 | ! xle, zle: leading edge coordinates 1450 | ! 1451 | !=============================================================================80 1452 | subroutine xfoil_lefind(x, z, s, xs, zs, npt, sle, xle, zle) & 1453 | bind(c, name="xfoil_lefind") 1454 | 1455 | real(c_double), dimension(npt), intent(in) :: x, z, s, xs, zs 1456 | integer(c_int), intent(in) :: npt 1457 | real(c_double), intent(out) :: sle, xle, zle 1458 | 1459 | call LEFIND(sle, x, xs, z, zs, s, npt, .true.) 1460 | call xfoil_eval_spline(x, z, s, xs, zs, npt, sle, xle, zle) 1461 | 1462 | end subroutine xfoil_lefind 1463 | 1464 | end module libxfoil 1465 | --------------------------------------------------------------------------------